Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
timeout.py185 linesDownload Raw Back to eventlet
1# Copyright (c) 2009-2010 Denis Bilenko, denis.bilenko at gmail com2# Copyright (c) 2010 Eventlet Contributors (see AUTHORS)3# and licensed under the MIT license:4#5# Permission is hereby granted, free of charge, to any person obtaining a copy6# of this software and associated documentation files (the "Software"), to deal7# in the Software without restriction, including without limitation the rights8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell9# copies of the Software, and to permit persons to whom the Software is10# furnished to do so, subject to the following conditions:11#12# The above copyright notice and this permission notice shall be included in13# all copies or substantial portions of the Software.14#15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN21# THE SOFTWARE.22 23import functools24import inspect25 26import eventlet27from eventlet.support import greenlets as greenlet28from eventlet.hubs import get_hub29 30__all__ = ['Timeout', 'with_timeout', 'wrap_is_timeout', 'is_timeout']31 32_MISSING = object()33 34# deriving from BaseException so that "except Exception as e" doesn't catch35# Timeout exceptions.36 37 38class Timeout(BaseException):39    """Raises *exception* in the current greenthread after *timeout* seconds.40 41    When *exception* is omitted or ``None``, the :class:`Timeout` instance42    itself is raised. If *seconds* is None, the timer is not scheduled, and is43    only useful if you're planning to raise it directly.44 45    Timeout objects are context managers, and so can be used in with statements.46    When used in a with statement, if *exception* is ``False``, the timeout is47    still raised, but the context manager suppresses it, so the code outside the48    with-block won't see it.49    """50 51    def __init__(self, seconds=None, exception=None):52        self.seconds = seconds53        self.exception = exception54        self.timer = None55        self.start()56 57    def start(self):58        """Schedule the timeout.  This is called on construction, so59        it should not be called explicitly, unless the timer has been60        canceled."""61        assert not self.pending, \62            '%r is already started; to restart it, cancel it first' % self63        if self.seconds is None:  # "fake" timeout (never expires)64            self.timer = None65        elif self.exception is None or isinstance(self.exception, bool):  # timeout that raises self66            self.timer = get_hub().schedule_call_global(67                self.seconds, greenlet.getcurrent().throw, self)68        else:  # regular timeout with user-provided exception69            self.timer = get_hub().schedule_call_global(70                self.seconds, greenlet.getcurrent().throw, self.exception)71        return self72 73    @property74    def pending(self):75        """True if the timeout is scheduled to be raised."""76        if self.timer is not None:77            return self.timer.pending78        else:79            return False80 81    def cancel(self):82        """If the timeout is pending, cancel it.  If not using83        Timeouts in ``with`` statements, always call cancel() in a84        ``finally`` after the block of code that is getting timed out.85        If not canceled, the timeout will be raised later on, in some86        unexpected section of the application."""87        if self.timer is not None:88            self.timer.cancel()89            self.timer = None90 91    def __repr__(self):92        classname = self.__class__.__name__93        if self.pending:94            pending = ' pending'95        else:96            pending = ''97        if self.exception is None:98            exception = ''99        else:100            exception = ' exception=%r' % self.exception101        return '<%s at %s seconds=%s%s%s>' % (102            classname, hex(id(self)), self.seconds, exception, pending)103 104    def __str__(self):105        """106        >>> raise Timeout  # doctest: +IGNORE_EXCEPTION_DETAIL107        Traceback (most recent call last):108            ...109        Timeout110        """111        if self.seconds is None:112            return ''113        if self.seconds == 1:114            suffix = ''115        else:116            suffix = 's'117        if self.exception is None or self.exception is True:118            return '%s second%s' % (self.seconds, suffix)119        elif self.exception is False:120            return '%s second%s (silent)' % (self.seconds, suffix)121        else:122            return '%s second%s (%s)' % (self.seconds, suffix, self.exception)123 124    def __enter__(self):125        if self.timer is None:126            self.start()127        return self128 129    def __exit__(self, typ, value, tb):130        self.cancel()131        if value is self and self.exception is False:132            return True133 134    @property135    def is_timeout(self):136        return True137 138 139def with_timeout(seconds, function, *args, **kwds):140    """Wrap a call to some (yielding) function with a timeout; if the called141    function fails to return before the timeout, cancel it and return a flag142    value.143    """144    timeout_value = kwds.pop("timeout_value", _MISSING)145    timeout = Timeout(seconds)146    try:147        try:148            return function(*args, **kwds)149        except Timeout as ex:150            if ex is timeout and timeout_value is not _MISSING:151                return timeout_value152            raise153    finally:154        timeout.cancel()155 156 157def wrap_is_timeout(base):158    '''Adds `.is_timeout=True` attribute to objects returned by `base()`.159 160    When `base` is class, attribute is added as read-only property. Returns `base`.161    Otherwise, it returns a function that sets attribute on result of `base()` call.162 163    Wrappers make best effort to be transparent.164    '''165    if inspect.isclass(base):166        base.is_timeout = property(lambda _: True)167        return base168 169    @functools.wraps(base)170    def fun(*args, **kwargs):171        ex = base(*args, **kwargs)172        ex.is_timeout = True173        return ex174    return fun175 176 177if isinstance(__builtins__, dict):  # seen when running tests on py310, but HOW??178    _timeout_err = __builtins__.get('TimeoutError', Timeout)179else:180    _timeout_err = getattr(__builtins__, 'TimeoutError', Timeout)181 182 183def is_timeout(obj):184    return bool(getattr(obj, 'is_timeout', False)) or isinstance(obj, _timeout_err)185 
codekingpro/portable-devtools · Team Ai