updating stupid venv thing

This commit is contained in:
2021-12-22 12:54:23 -05:00
parent 8360b4a4dc
commit 022505d957
637 changed files with 212972 additions and 0 deletions

View File

@@ -0,0 +1,523 @@
# -*- coding: utf-8 -*-
# Copyright 2016-2018 Julien Danjou
# Copyright 2017 Elisey Zanko
# Copyright 2016 Étienne Bersac
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
try:
from inspect import iscoroutinefunction
except ImportError:
iscoroutinefunction = None
try:
import tornado
except ImportError:
tornado = None
import sys
import threading
import typing as t
import warnings
from abc import ABCMeta, abstractmethod
from concurrent import futures
from pip._vendor import six
from pip._vendor.tenacity import _utils
# Import all built-in retry strategies for easier usage.
from .retry import retry_base # noqa
from .retry import retry_all # noqa
from .retry import retry_always # noqa
from .retry import retry_any # noqa
from .retry import retry_if_exception # noqa
from .retry import retry_if_exception_type # noqa
from .retry import retry_if_not_result # noqa
from .retry import retry_if_result # noqa
from .retry import retry_never # noqa
from .retry import retry_unless_exception_type # noqa
from .retry import retry_if_exception_message # noqa
from .retry import retry_if_not_exception_message # noqa
# Import all nap strategies for easier usage.
from .nap import sleep # noqa
from .nap import sleep_using_event # noqa
# Import all built-in stop strategies for easier usage.
from .stop import stop_after_attempt # noqa
from .stop import stop_after_delay # noqa
from .stop import stop_all # noqa
from .stop import stop_any # noqa
from .stop import stop_never # noqa
from .stop import stop_when_event_set # noqa
# Import all built-in wait strategies for easier usage.
from .wait import wait_chain # noqa
from .wait import wait_combine # noqa
from .wait import wait_exponential # noqa
from .wait import wait_fixed # noqa
from .wait import wait_incrementing # noqa
from .wait import wait_none # noqa
from .wait import wait_random # noqa
from .wait import wait_random_exponential # noqa
from .wait import wait_random_exponential as wait_full_jitter # noqa
# Import all built-in before strategies for easier usage.
from .before import before_log # noqa
from .before import before_nothing # noqa
# Import all built-in after strategies for easier usage.
from .after import after_log # noqa
from .after import after_nothing # noqa
# Import all built-in after strategies for easier usage.
from .before_sleep import before_sleep_log # noqa
from .before_sleep import before_sleep_nothing # noqa
WrappedFn = t.TypeVar("WrappedFn", bound=t.Callable)
@t.overload
def retry(fn):
# type: (WrappedFn) -> WrappedFn
"""Type signature for @retry as a raw decorator."""
pass
@t.overload
def retry(*dargs, **dkw): # noqa
# type: (...) -> t.Callable[[WrappedFn], WrappedFn]
"""Type signature for the @retry() decorator constructor."""
pass
def retry(*dargs, **dkw): # noqa
"""Wrap a function with a new `Retrying` object.
:param dargs: positional arguments passed to Retrying object
:param dkw: keyword arguments passed to the Retrying object
"""
# support both @retry and @retry() as valid syntax
if len(dargs) == 1 and callable(dargs[0]):
return retry()(dargs[0])
else:
def wrap(f):
if isinstance(f, retry_base):
warnings.warn(
(
"Got retry_base instance ({cls}) as callable argument, "
+ "this will probably hang indefinitely (did you mean "
+ "retry={cls}(...)?)"
).format(cls=f.__class__.__name__)
)
if iscoroutinefunction is not None and iscoroutinefunction(f):
r = AsyncRetrying(*dargs, **dkw)
elif (
tornado
and hasattr(tornado.gen, "is_coroutine_function")
and tornado.gen.is_coroutine_function(f)
):
r = TornadoRetrying(*dargs, **dkw)
else:
r = Retrying(*dargs, **dkw)
return r.wraps(f)
return wrap
class TryAgain(Exception):
"""Always retry the executed function when raised."""
NO_RESULT = object()
class DoAttempt(object):
pass
class DoSleep(float):
pass
class BaseAction(object):
"""Base class for representing actions to take by retry object.
Concrete implementations must define:
- __init__: to initialize all necessary fields
- REPR_ATTRS: class variable specifying attributes to include in repr(self)
- NAME: for identification in retry object methods and callbacks
"""
REPR_FIELDS = ()
NAME = None
def __repr__(self):
state_str = ", ".join(
"%s=%r" % (field, getattr(self, field)) for field in self.REPR_FIELDS
)
return "%s(%s)" % (type(self).__name__, state_str)
def __str__(self):
return repr(self)
class RetryAction(BaseAction):
REPR_FIELDS = ("sleep",)
NAME = "retry"
def __init__(self, sleep):
self.sleep = float(sleep)
_unset = object()
def _first_set(first, second):
return second if first is _unset else first
class RetryError(Exception):
"""Encapsulates the last attempt instance right before giving up."""
def __init__(self, last_attempt):
self.last_attempt = last_attempt
super(RetryError, self).__init__(last_attempt)
def reraise(self):
if self.last_attempt.failed:
raise self.last_attempt.result()
raise self
def __str__(self):
return "{0}[{1}]".format(self.__class__.__name__, self.last_attempt)
class AttemptManager(object):
"""Manage attempt context."""
def __init__(self, retry_state):
self.retry_state = retry_state
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
if isinstance(exc_value, BaseException):
self.retry_state.set_exception((exc_type, exc_value, traceback))
return True # Swallow exception.
else:
# We don't have the result, actually.
self.retry_state.set_result(None)
class BaseRetrying(object):
__metaclass__ = ABCMeta
def __init__(
self,
sleep=sleep,
stop=stop_never,
wait=wait_none(),
retry=retry_if_exception_type(),
before=before_nothing,
after=after_nothing,
before_sleep=None,
reraise=False,
retry_error_cls=RetryError,
retry_error_callback=None,
):
self.sleep = sleep
self.stop = stop
self.wait = wait
self.retry = retry
self.before = before
self.after = after
self.before_sleep = before_sleep
self.reraise = reraise
self._local = threading.local()
self.retry_error_cls = retry_error_cls
self.retry_error_callback = retry_error_callback
# This attribute was moved to RetryCallState and is deprecated on
# Retrying objects but kept for backward compatibility.
self.fn = None
def copy(
self,
sleep=_unset,
stop=_unset,
wait=_unset,
retry=_unset,
before=_unset,
after=_unset,
before_sleep=_unset,
reraise=_unset,
retry_error_cls=_unset,
retry_error_callback=_unset,
):
"""Copy this object with some parameters changed if needed."""
return self.__class__(
sleep=_first_set(sleep, self.sleep),
stop=_first_set(stop, self.stop),
wait=_first_set(wait, self.wait),
retry=_first_set(retry, self.retry),
before=_first_set(before, self.before),
after=_first_set(after, self.after),
before_sleep=_first_set(before_sleep, self.before_sleep),
reraise=_first_set(reraise, self.reraise),
retry_error_cls=_first_set(retry_error_cls, self.retry_error_cls),
retry_error_callback=_first_set(
retry_error_callback, self.retry_error_callback
),
)
def __repr__(self):
attrs = dict(
_utils.visible_attrs(self, attrs={"me": id(self)}),
__class__=self.__class__.__name__,
)
return (
"<%(__class__)s object at 0x%(me)x (stop=%(stop)s, "
"wait=%(wait)s, sleep=%(sleep)s, retry=%(retry)s, "
"before=%(before)s, after=%(after)s)>"
) % (attrs)
@property
def statistics(self):
"""Return a dictionary of runtime statistics.
This dictionary will be empty when the controller has never been
ran. When it is running or has ran previously it should have (but
may not) have useful and/or informational keys and values when
running is underway and/or completed.
.. warning:: The keys in this dictionary **should** be some what
stable (not changing), but there existence **may**
change between major releases as new statistics are
gathered or removed so before accessing keys ensure that
they actually exist and handle when they do not.
.. note:: The values in this dictionary are local to the thread
running call (so if multiple threads share the same retrying
object - either directly or indirectly) they will each have
there own view of statistics they have collected (in the
future we may provide a way to aggregate the various
statistics from each thread).
"""
try:
return self._local.statistics
except AttributeError:
self._local.statistics = {}
return self._local.statistics
def wraps(self, f):
"""Wrap a function for retrying.
:param f: A function to wraps for retrying.
"""
@_utils.wraps(f)
def wrapped_f(*args, **kw):
return self(f, *args, **kw)
def retry_with(*args, **kwargs):
return self.copy(*args, **kwargs).wraps(f)
wrapped_f.retry = self
wrapped_f.retry_with = retry_with
return wrapped_f
def begin(self, fn):
self.statistics.clear()
self.statistics["start_time"] = _utils.now()
self.statistics["attempt_number"] = 1
self.statistics["idle_for"] = 0
self.fn = fn
def iter(self, retry_state): # noqa
fut = retry_state.outcome
if fut is None:
if self.before is not None:
self.before(retry_state)
return DoAttempt()
is_explicit_retry = retry_state.outcome.failed and isinstance(
retry_state.outcome.exception(), TryAgain
)
if not (is_explicit_retry or self.retry(retry_state=retry_state)):
return fut.result()
if self.after is not None:
self.after(retry_state=retry_state)
self.statistics["delay_since_first_attempt"] = retry_state.seconds_since_start
if self.stop(retry_state=retry_state):
if self.retry_error_callback:
return self.retry_error_callback(retry_state=retry_state)
retry_exc = self.retry_error_cls(fut)
if self.reraise:
raise retry_exc.reraise()
six.raise_from(retry_exc, fut.exception())
if self.wait:
sleep = self.wait(retry_state=retry_state)
else:
sleep = 0.0
retry_state.next_action = RetryAction(sleep)
retry_state.idle_for += sleep
self.statistics["idle_for"] += sleep
self.statistics["attempt_number"] += 1
if self.before_sleep is not None:
self.before_sleep(retry_state=retry_state)
return DoSleep(sleep)
def __iter__(self):
self.begin(None)
retry_state = RetryCallState(self, fn=None, args=(), kwargs={})
while True:
do = self.iter(retry_state=retry_state)
if isinstance(do, DoAttempt):
yield AttemptManager(retry_state=retry_state)
elif isinstance(do, DoSleep):
retry_state.prepare_for_next_attempt()
self.sleep(do)
else:
break
@abstractmethod
def __call__(self, *args, **kwargs):
pass
def call(self, *args, **kwargs):
"""Use ``__call__`` instead because this method is deprecated."""
warnings.warn(
"'call()' method is deprecated. " + "Use '__call__()' instead",
DeprecationWarning,
)
return self.__call__(*args, **kwargs)
class Retrying(BaseRetrying):
"""Retrying controller."""
def __call__(self, fn, *args, **kwargs):
self.begin(fn)
retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
while True:
do = self.iter(retry_state=retry_state)
if isinstance(do, DoAttempt):
try:
result = fn(*args, **kwargs)
except BaseException: # noqa: B902
retry_state.set_exception(sys.exc_info())
else:
retry_state.set_result(result)
elif isinstance(do, DoSleep):
retry_state.prepare_for_next_attempt()
self.sleep(do)
else:
return do
class Future(futures.Future):
"""Encapsulates a (future or past) attempted call to a target function."""
def __init__(self, attempt_number):
super(Future, self).__init__()
self.attempt_number = attempt_number
@property
def failed(self):
"""Return whether a exception is being held in this future."""
return self.exception() is not None
@classmethod
def construct(cls, attempt_number, value, has_exception):
"""Construct a new Future object."""
fut = cls(attempt_number)
if has_exception:
fut.set_exception(value)
else:
fut.set_result(value)
return fut
class RetryCallState(object):
"""State related to a single call wrapped with Retrying."""
def __init__(self, retry_object, fn, args, kwargs):
#: Retry call start timestamp
self.start_time = _utils.now()
#: Retry manager object
self.retry_object = retry_object
#: Function wrapped by this retry call
self.fn = fn
#: Arguments of the function wrapped by this retry call
self.args = args
#: Keyword arguments of the function wrapped by this retry call
self.kwargs = kwargs
#: The number of the current attempt
self.attempt_number = 1
#: Last outcome (result or exception) produced by the function
self.outcome = None
#: Timestamp of the last outcome
self.outcome_timestamp = None
#: Time spent sleeping in retries
self.idle_for = 0
#: Next action as decided by the retry manager
self.next_action = None
@property
def seconds_since_start(self):
if self.outcome_timestamp is None:
return None
return self.outcome_timestamp - self.start_time
def prepare_for_next_attempt(self):
self.outcome = None
self.outcome_timestamp = None
self.attempt_number += 1
self.next_action = None
def set_result(self, val):
ts = _utils.now()
fut = Future(self.attempt_number)
fut.set_result(val)
self.outcome, self.outcome_timestamp = fut, ts
def set_exception(self, exc_info):
ts = _utils.now()
fut = Future(self.attempt_number)
_utils.capture(fut, exc_info)
self.outcome, self.outcome_timestamp = fut, ts
if iscoroutinefunction:
from pip._vendor.tenacity._asyncio import AsyncRetrying
if tornado:
from pip._vendor.tenacity.tornadoweb import TornadoRetrying

View File

@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Étienne Bersac
# Copyright 2016 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from asyncio import sleep
from pip._vendor.tenacity import AttemptManager
from pip._vendor.tenacity import BaseRetrying
from pip._vendor.tenacity import DoAttempt
from pip._vendor.tenacity import DoSleep
from pip._vendor.tenacity import RetryCallState
class AsyncRetrying(BaseRetrying):
def __init__(self, sleep=sleep, **kwargs):
super(AsyncRetrying, self).__init__(**kwargs)
self.sleep = sleep
async def __call__(self, fn, *args, **kwargs):
self.begin(fn)
retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
while True:
do = self.iter(retry_state=retry_state)
if isinstance(do, DoAttempt):
try:
result = await fn(*args, **kwargs)
except BaseException: # noqa: B902
retry_state.set_exception(sys.exc_info())
else:
retry_state.set_result(result)
elif isinstance(do, DoSleep):
retry_state.prepare_for_next_attempt()
await self.sleep(do)
else:
return do
def __aiter__(self):
self.begin(None)
self._retry_state = RetryCallState(self, fn=None, args=(), kwargs={})
return self
async def __anext__(self):
while True:
do = self.iter(retry_state=self._retry_state)
if do is None:
raise StopAsyncIteration
elif isinstance(do, DoAttempt):
return AttemptManager(retry_state=self._retry_state)
elif isinstance(do, DoSleep):
self._retry_state.prepare_for_next_attempt()
await self.sleep(do)
else:
return do
def wraps(self, fn):
fn = super().wraps(fn)
# Ensure wrapper is recognized as a coroutine function.
async def async_wrapped(*args, **kwargs):
return await fn(*args, **kwargs)
# Preserve attributes
async_wrapped.retry = fn.retry
async_wrapped.retry_with = fn.retry_with
return async_wrapped

View File

@@ -0,0 +1,159 @@
# Copyright 2016 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import inspect
import sys
import time
from functools import update_wrapper
from pip._vendor import six
# sys.maxint / 2, since Python 3.2 doesn't have a sys.maxint...
try:
MAX_WAIT = sys.maxint / 2
except AttributeError:
MAX_WAIT = 1073741823
if six.PY2:
from functools import WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES
def wraps(fn):
"""Do the same as six.wraps but only copy attributes that exist.
For example, object instances don't have __name__ attribute, so
six.wraps fails. This is fixed in Python 3
(https://bugs.python.org/issue3445), but didn't get backported to six.
Also, see https://github.com/benjaminp/six/issues/250.
"""
def filter_hasattr(obj, attrs):
return tuple(a for a in attrs if hasattr(obj, a))
return six.wraps(
fn,
assigned=filter_hasattr(fn, WRAPPER_ASSIGNMENTS),
updated=filter_hasattr(fn, WRAPPER_UPDATES),
)
def capture(fut, tb):
# TODO(harlowja): delete this in future, since its
# has to repeatedly calculate this crap.
fut.set_exception_info(tb[1], tb[2])
def getargspec(func):
# This was deprecated in Python 3.
return inspect.getargspec(func)
else:
from functools import wraps # noqa
def capture(fut, tb):
fut.set_exception(tb[1])
def getargspec(func):
return inspect.getfullargspec(func)
def visible_attrs(obj, attrs=None):
if attrs is None:
attrs = {}
for attr_name, attr in inspect.getmembers(obj):
if attr_name.startswith("_"):
continue
attrs[attr_name] = attr
return attrs
def find_ordinal(pos_num):
# See: https://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers
if pos_num == 0:
return "th"
elif pos_num == 1:
return "st"
elif pos_num == 2:
return "nd"
elif pos_num == 3:
return "rd"
elif pos_num >= 4 and pos_num <= 20:
return "th"
else:
return find_ordinal(pos_num % 10)
def to_ordinal(pos_num):
return "%i%s" % (pos_num, find_ordinal(pos_num))
def get_callback_name(cb):
"""Get a callback fully-qualified name.
If no name can be produced ``repr(cb)`` is called and returned.
"""
segments = []
try:
segments.append(cb.__qualname__)
except AttributeError:
try:
segments.append(cb.__name__)
if inspect.ismethod(cb):
try:
# This attribute doesn't exist on py3.x or newer, so
# we optionally ignore it... (on those versions of
# python `__qualname__` should have been found anyway).
segments.insert(0, cb.im_class.__name__)
except AttributeError:
pass
except AttributeError:
pass
if not segments:
return repr(cb)
else:
try:
# When running under sphinx it appears this can be none?
if cb.__module__:
segments.insert(0, cb.__module__)
except AttributeError:
pass
return ".".join(segments)
try:
now = time.monotonic # noqa
except AttributeError:
from monotonic import monotonic as now # noqa
class cached_property(object):
"""A property that is computed once per instance.
Upon being computed it replaces itself with an ordinary attribute. Deleting
the attribute resets the property.
Source: https://github.com/bottlepy/bottle/blob/1de24157e74a6971d136550afe1b63eec5b0df2b/bottle.py#L234-L246
""" # noqa: E501
def __init__(self, func):
update_wrapper(self, func)
self.func = func
def __get__(self, obj, cls):
if obj is None:
return self
value = obj.__dict__[self.func.__name__] = self.func(obj)
return value

View File

@@ -0,0 +1,40 @@
# Copyright 2016 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pip._vendor.tenacity import _utils
def after_nothing(retry_state):
"""After call strategy that does nothing."""
def after_log(logger, log_level, sec_format="%0.3f"):
"""After call strategy that logs to some logger the finished attempt."""
log_tpl = (
"Finished call to '%s' after " + str(sec_format) + "(s), "
"this was the %s time calling it."
)
def log_it(retry_state):
logger.log(
log_level,
log_tpl,
_utils.get_callback_name(retry_state.fn),
retry_state.seconds_since_start,
_utils.to_ordinal(retry_state.attempt_number),
)
return log_it

View File

@@ -0,0 +1,35 @@
# Copyright 2016 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pip._vendor.tenacity import _utils
def before_nothing(retry_state):
"""Before call strategy that does nothing."""
def before_log(logger, log_level):
"""Before call strategy that logs to some logger the attempt."""
def log_it(retry_state):
logger.log(
log_level,
"Starting call to '%s', this is the %s time calling it.",
_utils.get_callback_name(retry_state.fn),
_utils.to_ordinal(retry_state.attempt_number),
)
return log_it

View File

@@ -0,0 +1,51 @@
# Copyright 2016 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pip._vendor.tenacity import _utils
from pip._vendor.tenacity.compat import get_exc_info_from_future
def before_sleep_nothing(retry_state):
"""Before call strategy that does nothing."""
def before_sleep_log(logger, log_level, exc_info=False):
"""Before call strategy that logs to some logger the attempt."""
def log_it(retry_state):
if retry_state.outcome.failed:
ex = retry_state.outcome.exception()
verb, value = "raised", "%s: %s" % (type(ex).__name__, ex)
if exc_info:
local_exc_info = get_exc_info_from_future(retry_state.outcome)
else:
local_exc_info = False
else:
verb, value = "returned", retry_state.outcome.result()
local_exc_info = False # exc_info does not apply when no exception
logger.log(
log_level,
"Retrying %s in %s seconds as it %s %s.",
_utils.get_callback_name(retry_state.fn),
getattr(retry_state.next_action, "sleep"),
verb,
value,
exc_info=local_exc_info,
)
return log_it

View File

@@ -0,0 +1,23 @@
"""Utilities for providing backward compatibility."""
from pip._vendor import six
def get_exc_info_from_future(future):
"""
Get an exc_info value from a Future.
Given a a Future instance, retrieve an exc_info value suitable for passing
in as the exc_info parameter to logging.Logger.log() and related methods.
On Python 2, this will be a (type, value, traceback) triple.
On Python 3, this will be an exception instance (with embedded traceback).
If there was no exception, None is returned on both versions of Python.
"""
if six.PY3:
return future.exception()
else:
ex, tb = future.exception_info()
if ex is None:
return None
return type(ex), ex, tb

View File

@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Étienne Bersac
# Copyright 2016 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import time
def sleep(seconds):
"""
Sleep strategy that delays execution for a given number of seconds.
This is the default strategy, and may be mocked out for unit testing.
"""
time.sleep(seconds)
class sleep_using_event(object):
"""Sleep strategy that waits on an event to be set."""
def __init__(self, event):
self.event = event
def __call__(self, timeout):
# NOTE(harlowja): this may *not* actually wait for timeout
# seconds if the event is set (ie this may eject out early).
self.event.wait(timeout=timeout)

View File

@@ -0,0 +1,192 @@
# -*- encoding: utf-8 -*-
#
# Copyright 20162021 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import abc
import re
from pip._vendor import six
@six.add_metaclass(abc.ABCMeta)
class retry_base(object):
"""Abstract base class for retry strategies."""
@abc.abstractmethod
def __call__(self, retry_state):
pass
def __and__(self, other):
return retry_all(self, other)
def __or__(self, other):
return retry_any(self, other)
class _retry_never(retry_base):
"""Retry strategy that never rejects any result."""
def __call__(self, retry_state):
return False
retry_never = _retry_never()
class _retry_always(retry_base):
"""Retry strategy that always rejects any result."""
def __call__(self, retry_state):
return True
retry_always = _retry_always()
class retry_if_exception(retry_base):
"""Retry strategy that retries if an exception verifies a predicate."""
def __init__(self, predicate):
self.predicate = predicate
def __call__(self, retry_state):
if retry_state.outcome.failed:
return self.predicate(retry_state.outcome.exception())
else:
return False
class retry_if_exception_type(retry_if_exception):
"""Retries if an exception has been raised of one or more types."""
def __init__(self, exception_types=Exception):
self.exception_types = exception_types
super(retry_if_exception_type, self).__init__(
lambda e: isinstance(e, exception_types)
)
class retry_unless_exception_type(retry_if_exception):
"""Retries until an exception is raised of one or more types."""
def __init__(self, exception_types=Exception):
self.exception_types = exception_types
super(retry_unless_exception_type, self).__init__(
lambda e: not isinstance(e, exception_types)
)
def __call__(self, retry_state):
# always retry if no exception was raised
if not retry_state.outcome.failed:
return True
return self.predicate(retry_state.outcome.exception())
class retry_if_result(retry_base):
"""Retries if the result verifies a predicate."""
def __init__(self, predicate):
self.predicate = predicate
def __call__(self, retry_state):
if not retry_state.outcome.failed:
return self.predicate(retry_state.outcome.result())
else:
return False
class retry_if_not_result(retry_base):
"""Retries if the result refutes a predicate."""
def __init__(self, predicate):
self.predicate = predicate
def __call__(self, retry_state):
if not retry_state.outcome.failed:
return not self.predicate(retry_state.outcome.result())
else:
return False
class retry_if_exception_message(retry_if_exception):
"""Retries if an exception message equals or matches."""
def __init__(self, message=None, match=None):
if message and match:
raise TypeError(
"{}() takes either 'message' or 'match', not both".format(
self.__class__.__name__
)
)
# set predicate
if message:
def message_fnc(exception):
return message == str(exception)
predicate = message_fnc
elif match:
prog = re.compile(match)
def match_fnc(exception):
return prog.match(str(exception))
predicate = match_fnc
else:
raise TypeError(
"{}() missing 1 required argument 'message' or 'match'".format(
self.__class__.__name__
)
)
super(retry_if_exception_message, self).__init__(predicate)
class retry_if_not_exception_message(retry_if_exception_message):
"""Retries until an exception message equals or matches."""
def __init__(self, *args, **kwargs):
super(retry_if_not_exception_message, self).__init__(*args, **kwargs)
# invert predicate
if_predicate = self.predicate
self.predicate = lambda *args_, **kwargs_: not if_predicate(*args_, **kwargs_)
def __call__(self, retry_state):
if not retry_state.outcome.failed:
return True
return self.predicate(retry_state.outcome.exception())
class retry_any(retry_base):
"""Retries if any of the retries condition is valid."""
def __init__(self, *retries):
self.retries = retries
def __call__(self, retry_state):
return any(r(retry_state) for r in self.retries)
class retry_all(retry_base):
"""Retries if all the retries condition are valid."""
def __init__(self, *retries):
self.retries = retries
def __call__(self, retry_state):
return all(r(retry_state) for r in self.retries)

View File

@@ -0,0 +1,95 @@
# -*- encoding: utf-8 -*-
#
# Copyright 20162021 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import abc
from pip._vendor import six
@six.add_metaclass(abc.ABCMeta)
class stop_base(object):
"""Abstract base class for stop strategies."""
@abc.abstractmethod
def __call__(self, retry_state):
pass
def __and__(self, other):
return stop_all(self, other)
def __or__(self, other):
return stop_any(self, other)
class stop_any(stop_base):
"""Stop if any of the stop condition is valid."""
def __init__(self, *stops):
self.stops = stops
def __call__(self, retry_state):
return any(x(retry_state) for x in self.stops)
class stop_all(stop_base):
"""Stop if all the stop conditions are valid."""
def __init__(self, *stops):
self.stops = stops
def __call__(self, retry_state):
return all(x(retry_state) for x in self.stops)
class _stop_never(stop_base):
"""Never stop."""
def __call__(self, retry_state):
return False
stop_never = _stop_never()
class stop_when_event_set(stop_base):
"""Stop when the given event is set."""
def __init__(self, event):
self.event = event
def __call__(self, retry_state):
return self.event.is_set()
class stop_after_attempt(stop_base):
"""Stop when the previous attempt >= max_attempt."""
def __init__(self, max_attempt_number):
self.max_attempt_number = max_attempt_number
def __call__(self, retry_state):
return retry_state.attempt_number >= self.max_attempt_number
class stop_after_delay(stop_base):
"""Stop when the time from the first attempt >= limit."""
def __init__(self, max_delay):
self.max_delay = max_delay
def __call__(self, retry_state):
return retry_state.seconds_since_start >= self.max_delay

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Elisey Zanko
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from pip._vendor.tenacity import BaseRetrying
from pip._vendor.tenacity import DoAttempt
from pip._vendor.tenacity import DoSleep
from pip._vendor.tenacity import RetryCallState
from tornado import gen
class TornadoRetrying(BaseRetrying):
def __init__(self, sleep=gen.sleep, **kwargs):
super(TornadoRetrying, self).__init__(**kwargs)
self.sleep = sleep
@gen.coroutine
def __call__(self, fn, *args, **kwargs):
self.begin(fn)
retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
while True:
do = self.iter(retry_state=retry_state)
if isinstance(do, DoAttempt):
try:
result = yield fn(*args, **kwargs)
except BaseException: # noqa: B902
retry_state.set_exception(sys.exc_info())
else:
retry_state.set_result(result)
elif isinstance(do, DoSleep):
retry_state.prepare_for_next_attempt()
yield self.sleep(do)
else:
raise gen.Return(do)

View File

@@ -0,0 +1,183 @@
# -*- encoding: utf-8 -*-
#
# Copyright 20162021 Julien Danjou
# Copyright 2016 Joshua Harlow
# Copyright 2013-2014 Ray Holder
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import abc
import random
from pip._vendor import six
from pip._vendor.tenacity import _utils
@six.add_metaclass(abc.ABCMeta)
class wait_base(object):
"""Abstract base class for wait strategies."""
@abc.abstractmethod
def __call__(self, retry_state):
pass
def __add__(self, other):
return wait_combine(self, other)
def __radd__(self, other):
# make it possible to use multiple waits with the built-in sum function
if other == 0:
return self
return self.__add__(other)
class wait_fixed(wait_base):
"""Wait strategy that waits a fixed amount of time between each retry."""
def __init__(self, wait):
self.wait_fixed = wait
def __call__(self, retry_state):
return self.wait_fixed
class wait_none(wait_fixed):
"""Wait strategy that doesn't wait at all before retrying."""
def __init__(self):
super(wait_none, self).__init__(0)
class wait_random(wait_base):
"""Wait strategy that waits a random amount of time between min/max."""
def __init__(self, min=0, max=1): # noqa
self.wait_random_min = min
self.wait_random_max = max
def __call__(self, retry_state):
return self.wait_random_min + (
random.random() * (self.wait_random_max - self.wait_random_min)
)
class wait_combine(wait_base):
"""Combine several waiting strategies."""
def __init__(self, *strategies):
self.wait_funcs = strategies
def __call__(self, retry_state):
return sum(x(retry_state=retry_state) for x in self.wait_funcs)
class wait_chain(wait_base):
"""Chain two or more waiting strategies.
If all strategies are exhausted, the very last strategy is used
thereafter.
For example::
@retry(wait=wait_chain(*[wait_fixed(1) for i in range(3)] +
[wait_fixed(2) for j in range(5)] +
[wait_fixed(5) for k in range(4)))
def wait_chained():
print("Wait 1s for 3 attempts, 2s for 5 attempts and 5s
thereafter.")
"""
def __init__(self, *strategies):
self.strategies = strategies
def __call__(self, retry_state):
wait_func_no = min(max(retry_state.attempt_number, 1), len(self.strategies))
wait_func = self.strategies[wait_func_no - 1]
return wait_func(retry_state=retry_state)
class wait_incrementing(wait_base):
"""Wait an incremental amount of time after each attempt.
Starting at a starting value and incrementing by a value for each attempt
(and restricting the upper limit to some maximum value).
"""
def __init__(self, start=0, increment=100, max=_utils.MAX_WAIT): # noqa
self.start = start
self.increment = increment
self.max = max
def __call__(self, retry_state):
result = self.start + (self.increment * (retry_state.attempt_number - 1))
return max(0, min(result, self.max))
class wait_exponential(wait_base):
"""Wait strategy that applies exponential backoff.
It allows for a customized multiplier and an ability to restrict the
upper and lower limits to some maximum and minimum value.
The intervals are fixed (i.e. there is no jitter), so this strategy is
suitable for balancing retries against latency when a required resource is
unavailable for an unknown duration, but *not* suitable for resolving
contention between multiple processes for a shared resource. Use
wait_random_exponential for the latter case.
"""
def __init__(self, multiplier=1, max=_utils.MAX_WAIT, exp_base=2, min=0): # noqa
self.multiplier = multiplier
self.min = min
self.max = max
self.exp_base = exp_base
def __call__(self, retry_state):
try:
exp = self.exp_base ** (retry_state.attempt_number - 1)
result = self.multiplier * exp
except OverflowError:
return self.max
return max(max(0, self.min), min(result, self.max))
class wait_random_exponential(wait_exponential):
"""Random wait with exponentially widening window.
An exponential backoff strategy used to mediate contention between multiple
uncoordinated processes for a shared resource in distributed systems. This
is the sense in which "exponential backoff" is meant in e.g. Ethernet
networking, and corresponds to the "Full Jitter" algorithm described in
this blog post:
https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
Each retry occurs at a random time in a geometrically expanding interval.
It allows for a custom multiplier and an ability to restrict the upper
limit of the random interval to some maximum value.
Example::
wait_random_exponential(multiplier=0.5, # initial window 0.5s
max=60) # max 60s timeout
When waiting for an unavailable resource to become available again, as
opposed to trying to resolve contention for a shared resource, the
wait_exponential strategy (which uses a fixed interval) may be preferable.
"""
def __call__(self, retry_state):
high = super(wait_random_exponential, self).__call__(retry_state=retry_state)
return random.uniform(0, high)