Windows: Use 32-bit distribution of python

This commit is contained in:
James Taylor
2018-09-14 19:32:27 -07:00
parent 6ca20ff701
commit 4212164e91
166 changed files with 175548 additions and 44620 deletions

View File

@@ -13,12 +13,18 @@ module add timeouts to arbitrary code.
If a blocking function is called or an intense calculation is ongoing during
which no switches occur, :class:`Timeout` is powerless.
"""
from __future__ import absolute_import, print_function, division
from gevent._compat import string_types
from gevent.hub import getcurrent, _NONE, get_hub
from gevent._util import _NONE
__all__ = ['Timeout',
'with_timeout']
from greenlet import getcurrent
from gevent._hub_local import get_hub_noargs as get_hub
__all__ = [
'Timeout',
'with_timeout',
]
class _FakeTimer(object):
@@ -26,8 +32,22 @@ class _FakeTimer(object):
# without allocating any native resources. This is useful for timeouts
# that will never expire.
# Also partially mimics the API of Timeout itself for use in _start_new_or_dummy
pending = False
active = False
# This object is used as a singleton, so it should be
# immutable.
__slots__ = ()
@property
def pending(self):
return False
active = pending
@property
def seconds(self):
return None
timer = exception = seconds
def start(self, *args, **kwargs):
# pylint:disable=unused-argument
@@ -36,7 +56,14 @@ class _FakeTimer(object):
def stop(self):
return
def cancel(self):
cancel = stop
stop = close = cancel
def __enter__(self):
return self
def __exit__(self, _t, _v, _tb):
return
_FakeTimer = _FakeTimer()
@@ -44,23 +71,30 @@ _FakeTimer = _FakeTimer()
class Timeout(BaseException):
"""
Raise *exception* in the current greenlet after given time period::
Timeout(seconds=None, exception=None, ref=True, priority=-1)
Raise *exception* in the current greenlet after *seconds*
have elapsed::
timeout = Timeout(seconds, exception)
timeout.start()
try:
... # exception will be raised here, after *seconds* passed since start() call
finally:
timeout.cancel()
timeout.close()
.. note:: If the code that the timeout was protecting finishes
executing before the timeout elapses, be sure to ``cancel`` the
timeout so it is not unexpectedly raised in the future. Even if
it is raised, it is a best practice to cancel it. This
``try/finally`` construct or a ``with`` statement is a
recommended pattern.
.. note::
When *exception* is omitted or ``None``, the :class:`Timeout` instance itself is raised:
If the code that the timeout was protecting finishes
executing before the timeout elapses, be sure to ``close`` the
timeout so it is not unexpectedly raised in the future. Even if it
is raised, it is a best practice to close it. This ``try/finally``
construct or a ``with`` statement is a recommended pattern. (If
the timeout object will be started again, use ``cancel`` instead
of ``close``; this is rare.)
When *exception* is omitted or ``None``, the ``Timeout`` instance
itself is raised::
>>> import gevent
>>> gevent.Timeout(0.1).start()
@@ -69,14 +103,41 @@ class Timeout(BaseException):
...
Timeout: 0.1 seconds
To simplify starting and canceling timeouts, the ``with`` statement can be used::
If the *seconds* argument is not given or is ``None`` (e.g.,
``Timeout()``), then the timeout will never expire and never raise
*exception*. This is convenient for creating functions which take
an optional timeout parameter of their own. (Note that this is **not**
the same thing as a *seconds* value of ``0``.)
::
def function(args, timeout=None):
"A function with an optional timeout."
timer = Timeout(timeout)
with timer:
...
.. caution::
A *seconds* value less than ``0.0`` (e.g., ``-1``) is poorly defined. In the future,
support for negative values is likely to do the same thing as a value
of ``None`` or ``0``
A *seconds* value of ``0`` requests that the event loop spin and poll for I/O;
it will immediately expire as soon as control returns to the event loop.
.. rubric:: Use As A Context Manager
To simplify starting and canceling timeouts, the ``with``
statement can be used::
with gevent.Timeout(seconds, exception) as timeout:
pass # ... code block ...
This is equivalent to the try/finally block above with one additional feature:
if *exception* is the literal ``False``, the timeout is still raised, but the context manager
suppresses it, so the code outside the with-block won't see it.
This is equivalent to the try/finally block above with one
additional feature: if *exception* is the literal ``False``, the
timeout is still raised, but the context manager suppresses it, so
the code outside the with-block won't see it.
This is handy for adding a timeout to the functions that don't
support a *timeout* parameter themselves::
@@ -89,9 +150,14 @@ class Timeout(BaseException):
else:
... # a line was read within 5 seconds
.. caution:: If ``readline()`` above catches and doesn't re-raise :class:`BaseException`
(for example, with a bare ``except:``), then your timeout will fail to function and control
won't be returned to you when you expect.
.. caution::
If ``readline()`` above catches and doesn't re-raise
:exc:`BaseException` (for example, with a bare ``except:``), then
your timeout will fail to function and control won't be returned
to you when you expect.
.. rubric:: Catching Timeouts
When catching timeouts, keep in mind that the one you catch may
not be the one you have set (a calling function may have set its
@@ -105,54 +171,73 @@ class Timeout(BaseException):
except Timeout as t:
if t is not timeout:
raise # not my timeout
finally:
timeout.close()
If the *seconds* argument is not given or is ``None`` (e.g.,
``Timeout()``), then the timeout will never expire and never raise
*exception*. This is convenient for creating functions which take
an optional timeout parameter of their own. (Note that this is not the same thing
as a *seconds* value of 0.)
.. caution::
A *seconds* value less than 0.0 (e.g., -1) is poorly defined. In the future,
support for negative values is likely to do the same thing as a value
if ``None``.
.. versionchanged:: 1.1b2
If *seconds* is not given or is ``None``, no longer allocate a libev
timer that will never be started.
If *seconds* is not given or is ``None``, no longer allocate a
native timer object that will never be started.
.. versionchanged:: 1.1
Add warning about negative *seconds* values.
Add warning about negative *seconds* values.
.. versionchanged:: 1.3a1
Timeout objects now have a :meth:`close`
method that must be called when the timeout will no longer be
used to properly clean up native resources.
The ``with`` statement does this automatically.
"""
def __init__(self, seconds=None, exception=None, ref=True, priority=-1, _use_timer=True):
# We inherit a __dict__ from BaseException, so __slots__ actually
# makes us larger.
def __init__(self, seconds=None, exception=None, ref=True, priority=-1,
_one_shot=False):
BaseException.__init__(self)
self.seconds = seconds
self.exception = exception
if seconds is None or not _use_timer:
self._one_shot = _one_shot
if seconds is None:
# Avoid going through the timer codepath if no timeout is
# desired; this avoids some CFFI interactions on PyPy that can lead to a
# RuntimeError if this implementation is used during an `import` statement. See
# https://bitbucket.org/pypy/pypy/issues/2089/crash-in-pypy-260-linux64-with-gevent-11b1
# and https://github.com/gevent/gevent/issues/618.
# Plus, in general, it should be more efficient
self.timer = _FakeTimer
else:
# XXX: A timer <= 0 could cause libuv to block the loop; we catch
# that case in libuv/loop.py
self.timer = get_hub().loop.timer(seconds or 0.0, ref=ref, priority=priority)
def start(self):
"""Schedule the timeout."""
assert not self.pending, '%r is already started; to restart it, cancel it first' % self
if self.seconds is None: # "fake" timeout (never expires)
if self.pending:
raise AssertionError('%r is already started; to restart it, cancel it first' % self)
if self.seconds is None:
# "fake" timeout (never expires)
return
if self.exception is None or self.exception is False or isinstance(self.exception, string_types):
# timeout that raises self
self.timer.start(getcurrent().throw, self)
else: # regular timeout with user-provided exception
self.timer.start(getcurrent().throw, self.exception)
throws = self
else:
# regular timeout with user-provided exception
throws = self.exception
# Make sure the timer updates the current time so that we don't
# expire prematurely.
self.timer.start(getcurrent().throw, throws, update=True)
@classmethod
def start_new(cls, timeout=None, exception=None, ref=True):
def start_new(cls, timeout=None, exception=None, ref=True, _one_shot=False):
"""Create a started :class:`Timeout`.
This is a shortcut, the exact action depends on *timeout*'s type:
@@ -168,12 +253,12 @@ class Timeout(BaseException):
if not timeout.pending:
timeout.start()
return timeout
timeout = cls(timeout, exception, ref=ref)
timeout = cls(timeout, exception, ref=ref, _one_shot=_one_shot)
timeout.start()
return timeout
@staticmethod
def _start_new_or_dummy(timeout, exception=None):
def _start_new_or_dummy(timeout, exception=None, ref=True):
# Internal use only in 1.1
# Return an object with a 'cancel' method; if timeout is None,
# this will be a shared instance object that does nothing. Otherwise,
@@ -187,16 +272,33 @@ class Timeout(BaseException):
# under PyPy in synthetic benchmarks it makes no difference.
if timeout is None:
return _FakeTimer
return Timeout.start_new(timeout, exception)
return Timeout.start_new(timeout, exception, ref, _one_shot=True)
@property
def pending(self):
"""Return True if the timeout is scheduled to be raised."""
"""True if the timeout is scheduled to be raised."""
return self.timer.pending or self.timer.active
def cancel(self):
"""If the timeout is pending, cancel it. Otherwise, do nothing."""
"""
If the timeout is pending, cancel it. Otherwise, do nothing.
The timeout object can be :meth:`started <start>` again. If
you will not start the timeout again, you should use
:meth:`close` instead.
"""
self.timer.stop()
if self._one_shot:
self.close()
def close(self):
"""
Close the timeout and free resources. The timer cannot be started again
after this method has been used.
"""
self.timer.stop()
self.timer.close()
self.timer = _FakeTimer
def __repr__(self):
classname = type(self).__name__
@@ -229,14 +331,24 @@ class Timeout(BaseException):
return '%s second%s: %s' % (self.seconds, suffix, self.exception)
def __enter__(self):
"""
Start and return the timer. If the timer is already started, just return it.
"""
if not self.pending:
self.start()
return self
def __exit__(self, typ, value, tb):
self.cancel()
"""
Stop the timer.
.. versionchanged:: 1.3a1
The underlying native timer is also stopped. This object cannot be
used again.
"""
self.close()
if value is self and self.exception is False:
return True
return True # Suppress the exception
def with_timeout(seconds, function, *args, **kwds):
@@ -249,7 +361,7 @@ def with_timeout(seconds, function, *args, **kwds):
Keyword argument *timeout_value* is not passed to *function*.
"""
timeout_value = kwds.pop("timeout_value", _NONE)
timeout = Timeout.start_new(seconds)
timeout = Timeout.start_new(seconds, _one_shot=True)
try:
try:
return function(*args, **kwds)