~matsubara/ubuntu/trusty/python-urllib3/bug-1412545

« back to all changes in this revision

Viewing changes to .pc/01_do-not-use-embedded-python-six.patch/urllib3/connectionpool.py

  • Committer: Package Import Robot
  • Author(s): Barry Warsaw
  • Date: 2012-11-01 15:31:36 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20121101153136-w2fm02askveqxxkx
Tags: 1.5-0ubuntu1
* New upstream release.  Remaining changes:
  - 01_do-not-use-embedded-python-six.patch: refreshed
  - 02_require-cert-verification.patch: refreshed
  - 03-fix-appenginge.patch: removed

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
import logging
8
8
import socket
9
9
 
10
 
from socket import error as SocketError, timeout as SocketTimeout
 
10
from socket import timeout as SocketTimeout
11
11
 
12
 
try:   # Python 3
 
12
try: # Python 3
13
13
    from http.client import HTTPConnection, HTTPException
14
14
    from http.client import HTTP_PORT, HTTPS_PORT
15
15
except ImportError:
16
16
    from httplib import HTTPConnection, HTTPException
17
17
    from httplib import HTTP_PORT, HTTPS_PORT
18
18
 
19
 
try:   # Python 3
 
19
try: # Python 3
20
20
    from queue import LifoQueue, Empty, Full
21
21
except ImportError:
22
22
    from Queue import LifoQueue, Empty, Full
23
23
 
24
24
 
25
 
try:   # Compiled with SSL?
 
25
try: # Compiled with SSL?
26
26
    HTTPSConnection = object
27
27
    BaseSSLError = None
28
28
    ssl = None
29
29
 
30
 
    try:   # Python 3
 
30
    try: # Python 3
31
31
        from http.client import HTTPSConnection
32
32
    except ImportError:
33
33
        from httplib import HTTPSConnection
35
35
    import ssl
36
36
    BaseSSLError = ssl.SSLError
37
37
 
38
 
except (ImportError, AttributeError):
 
38
except (ImportError, AttributeError): # Platform-specific: No SSL.
39
39
    pass
40
40
 
41
41
 
43
43
from .response import HTTPResponse
44
44
from .util import get_host, is_connection_dropped
45
45
from .exceptions import (
 
46
    ClosedPoolError,
46
47
    EmptyPoolError,
47
48
    HostChangedError,
48
49
    MaxRetryError,
206
207
        try:
207
208
            conn = self.pool.get(block=self.block, timeout=timeout)
208
209
 
209
 
            # If this is a persistent connection, check if it got disconnected
210
 
            if conn and is_connection_dropped(conn):
211
 
                log.info("Resetting dropped connection: %s" % self.host)
212
 
                conn.close()
 
210
        except AttributeError: # self.pool is None
 
211
            raise ClosedPoolError(self, "Pool is closed.")
213
212
 
214
213
        except Empty:
215
214
            if self.block:
218
217
                                     "connections are allowed.")
219
218
            pass  # Oh well, we'll create a new connection then
220
219
 
 
220
        # If this is a persistent connection, check if it got disconnected
 
221
        if conn and is_connection_dropped(conn):
 
222
            log.info("Resetting dropped connection: %s" % self.host)
 
223
            conn.close()
 
224
 
221
225
        return conn or self._new_conn()
222
226
 
223
227
    def _put_conn(self, conn):
228
232
            Connection object for the current host and port as returned by
229
233
            :meth:`._new_conn` or :meth:`._get_conn`.
230
234
 
231
 
        If the pool is already full, the connection is discarded because we
232
 
        exceeded maxsize. If connections are discarded frequently, then maxsize
233
 
        should be increased.
 
235
        If the pool is already full, the connection is closed and discarded
 
236
        because we exceeded maxsize. If connections are discarded frequently,
 
237
        then maxsize should be increased.
 
238
 
 
239
        If the pool is closed, then the connection will be closed and discarded.
234
240
        """
235
241
        try:
236
242
            self.pool.put(conn, block=False)
 
243
            return # Everything is dandy, done.
 
244
        except AttributeError:
 
245
            # self.pool is None.
 
246
            pass
237
247
        except Full:
238
248
            # This should never happen if self.block == True
239
249
            log.warning("HttpConnectionPool is full, discarding connection: %s"
240
250
                        % self.host)
241
251
 
 
252
        # Connection never got put back into the pool, close it.
 
253
        conn.close()
 
254
 
242
255
    def _make_request(self, conn, method, url, timeout=_Default,
243
256
                      **httplib_request_kw):
244
257
        """
258
271
        if sock:
259
272
            sock.settimeout(timeout)
260
273
 
261
 
        httplib_response = conn.getresponse()
262
 
 
263
 
        log.debug("\"%s %s %s\" %s %s" %
264
 
                  (method, url,
265
 
                   conn._http_vsn_str, # pylint: disable-msg=W0212
266
 
                   httplib_response.status, httplib_response.length))
267
 
 
 
274
        try: # Python 2.7+, use buffering of HTTP responses
 
275
            httplib_response = conn.getresponse(buffering=True)
 
276
        except TypeError: # Python 2.6 and older
 
277
            httplib_response = conn.getresponse()
 
278
 
 
279
        # AppEngine doesn't have a version attr.
 
280
        http_version = getattr(conn, '_http_vsn_str', 'HTTP/?')
 
281
        log.debug("\"%s %s %s\" %s %s" % (method, url, http_version,
 
282
                                          httplib_response.status,
 
283
                                          httplib_response.length))
268
284
        return httplib_response
269
285
 
 
286
    def close(self):
 
287
        """
 
288
        Close all pooled connections and disable the pool.
 
289
        """
 
290
        # Disable access to the pool
 
291
        old_pool, self.pool = self.pool, None
 
292
 
 
293
        try:
 
294
            while True:
 
295
                conn = old_pool.get(block=False)
 
296
                if conn:
 
297
                    conn.close()
 
298
 
 
299
        except Empty:
 
300
            pass # Done.
270
301
 
271
302
    def is_same_host(self, url):
272
303
        """
273
304
        Check if the given ``url`` is a member of the same host as this
274
305
        connection pool.
275
306
        """
 
307
        if url.startswith('/'):
 
308
            return True
 
309
 
276
310
        # TODO: Add optional support for socket.gethostbyname checking.
277
311
        scheme, host, port = get_host(url)
278
312
 
280
314
            # Use explicit default port for comparison when none is given.
281
315
            port = port_by_scheme.get(scheme)
282
316
 
283
 
        return (url.startswith('/') or
284
 
                (scheme, host, port) == (self.scheme, self.host, self.port))
 
317
        return (scheme, host, port) == (self.scheme, self.host, self.port)
285
318
 
286
319
    def urlopen(self, method, url, body=None, headers=None, retries=3,
287
320
                redirect=True, assert_same_host=True, timeout=_Default,
320
353
            Number of retries to allow before raising a MaxRetryError exception.
321
354
 
322
355
        :param redirect:
323
 
            Automatically handle redirects (status codes 301, 302, 303, 307),
324
 
            each redirect counts as a retry.
 
356
            If True, automatically handle redirects (status codes 301, 302,
 
357
            303, 307). Each redirect counts as a retry.
325
358
 
326
359
        :param assert_same_host:
327
360
            If ``True``, will make sure that the host of the pool requests is
374
407
 
375
408
        try:
376
409
            # Request a connection from the queue
377
 
            # (Could raise SocketError: Bad file descriptor)
378
410
            conn = self._get_conn(timeout=pool_timeout)
379
411
 
380
412
            # Make the request on the httplib connection object
417
449
            # Name mismatch
418
450
            raise SSLError(e)
419
451
 
420
 
        except (HTTPException, SocketError) as e:
 
452
        except HTTPException as e:
421
453
            # Connection broken, discard. It will be replaced next _get_conn().
422
454
            conn = None
423
455
            # This is necessary so we can access e below
424
456
            err = e
425
457
 
426
458
        finally:
427
 
            if conn and release_conn:
428
 
                # Put the connection back to be reused
 
459
            if release_conn:
 
460
                # Put the connection back to be reused. If the connection is
 
461
                # expired then it will be None, which will get replaced with a
 
462
                # fresh connection during _get_conn.
429
463
                self._put_conn(conn)
430
464
 
431
465
        if not conn:
 
466
            # Try again
432
467
            log.warn("Retrying (%d attempts remain) after connection "
433
468
                     "broken by '%r': %s" % (retries, err, url))
434
469
            return self.urlopen(method, url, body, headers, retries - 1,
435
 
                                redirect, assert_same_host)  # Try again
 
470
                                redirect, assert_same_host,
 
471
                                timeout=timeout, pool_timeout=pool_timeout,
 
472
                                release_conn=release_conn, **response_kw)
436
473
 
437
474
        # Handle redirect?
438
475
        redirect_location = redirect and response.get_redirect_location()
439
476
        if redirect_location:
 
477
            if response.status == 303:
 
478
                method = 'GET'
440
479
            log.info("Redirecting %s -> %s" % (url, redirect_location))
441
480
            return self.urlopen(method, redirect_location, body, headers,
442
 
                                retries - 1, redirect, assert_same_host)
 
481
                                retries - 1, redirect, assert_same_host,
 
482
                                timeout=timeout, pool_timeout=pool_timeout,
 
483
                                release_conn=release_conn, **response_kw)
443
484
 
444
485
        return response
445
486