~inkscape.dev/inkscape-devlibs/trunk

« back to all changes in this revision

Viewing changes to python/Lib/site-packages/pip/_vendor/requests/packages/urllib3/util/retry.py

  • Committer: Eduard Braun
  • Date: 2016-12-22 23:29:22 UTC
  • Revision ID: eduard.braun2@gmx.de-20161222232922-45qxef2vw6v0ekr2
Sync python with devlibs64

r35:
Python: include pyserial (3.2.1) and pip (9.0.1) packages

r36:
Python: Fix scripts (executables in in Scripts directory)
They include an absolute path to the python executable (which is system dependent). Replace this with a simple call to "python.exe" (which means python has to be on the search path).

See also http://www.clemens-sielaff.com/create-a-portable-python-with-pip-on-windows/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import absolute_import
 
2
import time
 
3
import logging
 
4
 
 
5
from ..exceptions import (
 
6
    ConnectTimeoutError,
 
7
    MaxRetryError,
 
8
    ProtocolError,
 
9
    ReadTimeoutError,
 
10
    ResponseError,
 
11
)
 
12
from ..packages import six
 
13
 
 
14
 
 
15
log = logging.getLogger(__name__)
 
16
 
 
17
 
 
18
class Retry(object):
 
19
    """ Retry configuration.
 
20
 
 
21
    Each retry attempt will create a new Retry object with updated values, so
 
22
    they can be safely reused.
 
23
 
 
24
    Retries can be defined as a default for a pool::
 
25
 
 
26
        retries = Retry(connect=5, read=2, redirect=5)
 
27
        http = PoolManager(retries=retries)
 
28
        response = http.request('GET', 'http://example.com/')
 
29
 
 
30
    Or per-request (which overrides the default for the pool)::
 
31
 
 
32
        response = http.request('GET', 'http://example.com/', retries=Retry(10))
 
33
 
 
34
    Retries can be disabled by passing ``False``::
 
35
 
 
36
        response = http.request('GET', 'http://example.com/', retries=False)
 
37
 
 
38
    Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless
 
39
    retries are disabled, in which case the causing exception will be raised.
 
40
 
 
41
    :param int total:
 
42
        Total number of retries to allow. Takes precedence over other counts.
 
43
 
 
44
        Set to ``None`` to remove this constraint and fall back on other
 
45
        counts. It's a good idea to set this to some sensibly-high value to
 
46
        account for unexpected edge cases and avoid infinite retry loops.
 
47
 
 
48
        Set to ``0`` to fail on the first retry.
 
49
 
 
50
        Set to ``False`` to disable and imply ``raise_on_redirect=False``.
 
51
 
 
52
    :param int connect:
 
53
        How many connection-related errors to retry on.
 
54
 
 
55
        These are errors raised before the request is sent to the remote server,
 
56
        which we assume has not triggered the server to process the request.
 
57
 
 
58
        Set to ``0`` to fail on the first retry of this type.
 
59
 
 
60
    :param int read:
 
61
        How many times to retry on read errors.
 
62
 
 
63
        These errors are raised after the request was sent to the server, so the
 
64
        request may have side-effects.
 
65
 
 
66
        Set to ``0`` to fail on the first retry of this type.
 
67
 
 
68
    :param int redirect:
 
69
        How many redirects to perform. Limit this to avoid infinite redirect
 
70
        loops.
 
71
 
 
72
        A redirect is a HTTP response with a status code 301, 302, 303, 307 or
 
73
        308.
 
74
 
 
75
        Set to ``0`` to fail on the first retry of this type.
 
76
 
 
77
        Set to ``False`` to disable and imply ``raise_on_redirect=False``.
 
78
 
 
79
    :param iterable method_whitelist:
 
80
        Set of uppercased HTTP method verbs that we should retry on.
 
81
 
 
82
        By default, we only retry on methods which are considered to be
 
83
        idempotent (multiple requests with the same parameters end with the
 
84
        same state). See :attr:`Retry.DEFAULT_METHOD_WHITELIST`.
 
85
 
 
86
        Set to a ``False`` value to retry on any verb.
 
87
 
 
88
    :param iterable status_forcelist:
 
89
        A set of integer HTTP status codes that we should force a retry on.
 
90
        A retry is initiated if the request method is in ``method_whitelist``
 
91
        and the response status code is in ``status_forcelist``.
 
92
 
 
93
        By default, this is disabled with ``None``.
 
94
 
 
95
    :param float backoff_factor:
 
96
        A backoff factor to apply between attempts after the second try
 
97
        (most errors are resolved immediately by a second try without a
 
98
        delay). urllib3 will sleep for::
 
99
 
 
100
            {backoff factor} * (2 ^ ({number of total retries} - 1))
 
101
 
 
102
        seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep
 
103
        for [0.0s, 0.2s, 0.4s, ...] between retries. It will never be longer
 
104
        than :attr:`Retry.BACKOFF_MAX`.
 
105
 
 
106
        By default, backoff is disabled (set to 0).
 
107
 
 
108
    :param bool raise_on_redirect: Whether, if the number of redirects is
 
109
        exhausted, to raise a MaxRetryError, or to return a response with a
 
110
        response code in the 3xx range.
 
111
 
 
112
    :param bool raise_on_status: Similar meaning to ``raise_on_redirect``:
 
113
        whether we should raise an exception, or return a response,
 
114
        if status falls in ``status_forcelist`` range and retries have
 
115
        been exhausted.
 
116
    """
 
117
 
 
118
    DEFAULT_METHOD_WHITELIST = frozenset([
 
119
        'HEAD', 'GET', 'PUT', 'DELETE', 'OPTIONS', 'TRACE'])
 
120
 
 
121
    #: Maximum backoff time.
 
122
    BACKOFF_MAX = 120
 
123
 
 
124
    def __init__(self, total=10, connect=None, read=None, redirect=None,
 
125
                 method_whitelist=DEFAULT_METHOD_WHITELIST, status_forcelist=None,
 
126
                 backoff_factor=0, raise_on_redirect=True, raise_on_status=True,
 
127
                 _observed_errors=0):
 
128
 
 
129
        self.total = total
 
130
        self.connect = connect
 
131
        self.read = read
 
132
 
 
133
        if redirect is False or total is False:
 
134
            redirect = 0
 
135
            raise_on_redirect = False
 
136
 
 
137
        self.redirect = redirect
 
138
        self.status_forcelist = status_forcelist or set()
 
139
        self.method_whitelist = method_whitelist
 
140
        self.backoff_factor = backoff_factor
 
141
        self.raise_on_redirect = raise_on_redirect
 
142
        self.raise_on_status = raise_on_status
 
143
        self._observed_errors = _observed_errors  # TODO: use .history instead?
 
144
 
 
145
    def new(self, **kw):
 
146
        params = dict(
 
147
            total=self.total,
 
148
            connect=self.connect, read=self.read, redirect=self.redirect,
 
149
            method_whitelist=self.method_whitelist,
 
150
            status_forcelist=self.status_forcelist,
 
151
            backoff_factor=self.backoff_factor,
 
152
            raise_on_redirect=self.raise_on_redirect,
 
153
            raise_on_status=self.raise_on_status,
 
154
            _observed_errors=self._observed_errors,
 
155
        )
 
156
        params.update(kw)
 
157
        return type(self)(**params)
 
158
 
 
159
    @classmethod
 
160
    def from_int(cls, retries, redirect=True, default=None):
 
161
        """ Backwards-compatibility for the old retries format."""
 
162
        if retries is None:
 
163
            retries = default if default is not None else cls.DEFAULT
 
164
 
 
165
        if isinstance(retries, Retry):
 
166
            return retries
 
167
 
 
168
        redirect = bool(redirect) and None
 
169
        new_retries = cls(retries, redirect=redirect)
 
170
        log.debug("Converted retries value: %r -> %r", retries, new_retries)
 
171
        return new_retries
 
172
 
 
173
    def get_backoff_time(self):
 
174
        """ Formula for computing the current backoff
 
175
 
 
176
        :rtype: float
 
177
        """
 
178
        if self._observed_errors <= 1:
 
179
            return 0
 
180
 
 
181
        backoff_value = self.backoff_factor * (2 ** (self._observed_errors - 1))
 
182
        return min(self.BACKOFF_MAX, backoff_value)
 
183
 
 
184
    def sleep(self):
 
185
        """ Sleep between retry attempts using an exponential backoff.
 
186
 
 
187
        By default, the backoff factor is 0 and this method will return
 
188
        immediately.
 
189
        """
 
190
        backoff = self.get_backoff_time()
 
191
        if backoff <= 0:
 
192
            return
 
193
        time.sleep(backoff)
 
194
 
 
195
    def _is_connection_error(self, err):
 
196
        """ Errors when we're fairly sure that the server did not receive the
 
197
        request, so it should be safe to retry.
 
198
        """
 
199
        return isinstance(err, ConnectTimeoutError)
 
200
 
 
201
    def _is_read_error(self, err):
 
202
        """ Errors that occur after the request has been started, so we should
 
203
        assume that the server began processing it.
 
204
        """
 
205
        return isinstance(err, (ReadTimeoutError, ProtocolError))
 
206
 
 
207
    def is_forced_retry(self, method, status_code):
 
208
        """ Is this method/status code retryable? (Based on method/codes whitelists)
 
209
        """
 
210
        if self.method_whitelist and method.upper() not in self.method_whitelist:
 
211
            return False
 
212
 
 
213
        return self.status_forcelist and status_code in self.status_forcelist
 
214
 
 
215
    def is_exhausted(self):
 
216
        """ Are we out of retries? """
 
217
        retry_counts = (self.total, self.connect, self.read, self.redirect)
 
218
        retry_counts = list(filter(None, retry_counts))
 
219
        if not retry_counts:
 
220
            return False
 
221
 
 
222
        return min(retry_counts) < 0
 
223
 
 
224
    def increment(self, method=None, url=None, response=None, error=None,
 
225
                  _pool=None, _stacktrace=None):
 
226
        """ Return a new Retry object with incremented retry counters.
 
227
 
 
228
        :param response: A response object, or None, if the server did not
 
229
            return a response.
 
230
        :type response: :class:`~urllib3.response.HTTPResponse`
 
231
        :param Exception error: An error encountered during the request, or
 
232
            None if the response was received successfully.
 
233
 
 
234
        :return: A new ``Retry`` object.
 
235
        """
 
236
        if self.total is False and error:
 
237
            # Disabled, indicate to re-raise the error.
 
238
            raise six.reraise(type(error), error, _stacktrace)
 
239
 
 
240
        total = self.total
 
241
        if total is not None:
 
242
            total -= 1
 
243
 
 
244
        _observed_errors = self._observed_errors
 
245
        connect = self.connect
 
246
        read = self.read
 
247
        redirect = self.redirect
 
248
        cause = 'unknown'
 
249
 
 
250
        if error and self._is_connection_error(error):
 
251
            # Connect retry?
 
252
            if connect is False:
 
253
                raise six.reraise(type(error), error, _stacktrace)
 
254
            elif connect is not None:
 
255
                connect -= 1
 
256
            _observed_errors += 1
 
257
 
 
258
        elif error and self._is_read_error(error):
 
259
            # Read retry?
 
260
            if read is False:
 
261
                raise six.reraise(type(error), error, _stacktrace)
 
262
            elif read is not None:
 
263
                read -= 1
 
264
            _observed_errors += 1
 
265
 
 
266
        elif response and response.get_redirect_location():
 
267
            # Redirect retry?
 
268
            if redirect is not None:
 
269
                redirect -= 1
 
270
            cause = 'too many redirects'
 
271
 
 
272
        else:
 
273
            # Incrementing because of a server error like a 500 in
 
274
            # status_forcelist and a the given method is in the whitelist
 
275
            _observed_errors += 1
 
276
            cause = ResponseError.GENERIC_ERROR
 
277
            if response and response.status:
 
278
                cause = ResponseError.SPECIFIC_ERROR.format(
 
279
                    status_code=response.status)
 
280
 
 
281
        new_retry = self.new(
 
282
            total=total,
 
283
            connect=connect, read=read, redirect=redirect,
 
284
            _observed_errors=_observed_errors)
 
285
 
 
286
        if new_retry.is_exhausted():
 
287
            raise MaxRetryError(_pool, url, error or ResponseError(cause))
 
288
 
 
289
        log.debug("Incremented Retry for (url='%s'): %r", url, new_retry)
 
290
 
 
291
        return new_retry
 
292
 
 
293
    def __repr__(self):
 
294
        return ('{cls.__name__}(total={self.total}, connect={self.connect}, '
 
295
                'read={self.read}, redirect={self.redirect})').format(
 
296
                    cls=type(self), self=self)
 
297
 
 
298
 
 
299
# For backwards compatibility (equivalent to pre-v1.9):
 
300
Retry.DEFAULT = Retry(3)