~ubuntu-branches/debian/jessie/python-pip/jessie

« back to all changes in this revision

Viewing changes to pip/_vendor/requests/packages/urllib3/util.py

  • Committer: Package Import Robot
  • Author(s): Barry Warsaw
  • Date: 2014-03-31 14:44:40 UTC
  • mfrom: (1.2.6)
  • Revision ID: package-import@ubuntu.com-20140331144440-961i5y31zsxb7ev1
Tags: 1.5.4-1
* Team upload.
* New upstream release.
* d/patches:
  - system-ca-certificates.patch: Removed.  This is obsoleted by the
    vendorizing (and on Debian, de-vendorizing) of the requests library.
  - no-python-specific-scripts.patch: Removed.  Upstream renamed pip-X.Y
    to pipX.Y but adopts our pipX name as well.  I don't think it hurts
    to also have pipX.Y.
  - de-vendorize.patch: Added, in order to use Debian packages instead
    of vendorized packages.
* d/control:
  - Bump Standards-Version to 3.9.5 with no other changes needed.
  - Update Depends for the vendorized packages.
* d/python{,3}-pip.pyremove: Remove pip/_vendor directory from binary
  packages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# urllib3/util.py
 
2
# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
 
3
#
 
4
# This module is part of urllib3 and is released under
 
5
# the MIT License: http://www.opensource.org/licenses/mit-license.php
 
6
 
 
7
 
 
8
from base64 import b64encode
 
9
from binascii import hexlify, unhexlify
 
10
from collections import namedtuple
 
11
from hashlib import md5, sha1
 
12
from socket import error as SocketError, _GLOBAL_DEFAULT_TIMEOUT
 
13
import time
 
14
 
 
15
try:
 
16
    from select import poll, POLLIN
 
17
except ImportError:  # `poll` doesn't exist on OSX and other platforms
 
18
    poll = False
 
19
    try:
 
20
        from select import select
 
21
    except ImportError:  # `select` doesn't exist on AppEngine.
 
22
        select = False
 
23
 
 
24
try:  # Test for SSL features
 
25
    SSLContext = None
 
26
    HAS_SNI = False
 
27
 
 
28
    import ssl
 
29
    from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23
 
30
    from ssl import SSLContext  # Modern SSL?
 
31
    from ssl import HAS_SNI  # Has SNI?
 
32
except ImportError:
 
33
    pass
 
34
 
 
35
from .packages import six
 
36
from .exceptions import LocationParseError, SSLError, TimeoutStateError
 
37
 
 
38
 
 
39
_Default = object()
 
40
# The default timeout to use for socket connections. This is the attribute used
 
41
# by httplib to define the default timeout
 
42
 
 
43
 
 
44
def current_time():
 
45
    """
 
46
    Retrieve the current time, this function is mocked out in unit testing.
 
47
    """
 
48
    return time.time()
 
49
 
 
50
 
 
51
class Timeout(object):
 
52
    """
 
53
    Utility object for storing timeout values.
 
54
 
 
55
    Example usage:
 
56
 
 
57
    .. code-block:: python
 
58
 
 
59
        timeout = urllib3.util.Timeout(connect=2.0, read=7.0)
 
60
        pool = HTTPConnectionPool('www.google.com', 80, timeout=timeout)
 
61
        pool.request(...) # Etc, etc
 
62
 
 
63
    :param connect:
 
64
        The maximum amount of time to wait for a connection attempt to a server
 
65
        to succeed. Omitting the parameter will default the connect timeout to
 
66
        the system default, probably `the global default timeout in socket.py
 
67
        <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_.
 
68
        None will set an infinite timeout for connection attempts.
 
69
 
 
70
    :type connect: integer, float, or None
 
71
 
 
72
    :param read:
 
73
        The maximum amount of time to wait between consecutive
 
74
        read operations for a response from the server. Omitting
 
75
        the parameter will default the read timeout to the system
 
76
        default, probably `the global default timeout in socket.py
 
77
        <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_.
 
78
        None will set an infinite timeout.
 
79
 
 
80
    :type read: integer, float, or None
 
81
 
 
82
    :param total:
 
83
        This combines the connect and read timeouts into one; the read timeout
 
84
        will be set to the time leftover from the connect attempt. In the
 
85
        event that both a connect timeout and a total are specified, or a read
 
86
        timeout and a total are specified, the shorter timeout will be applied.
 
87
 
 
88
        Defaults to None.
 
89
 
 
90
    :type total: integer, float, or None
 
91
 
 
92
    .. note::
 
93
 
 
94
        Many factors can affect the total amount of time for urllib3 to return
 
95
        an HTTP response. Specifically, Python's DNS resolver does not obey the
 
96
        timeout specified on the socket. Other factors that can affect total
 
97
        request time include high CPU load, high swap, the program running at a
 
98
        low priority level, or other behaviors. The observed running time for
 
99
        urllib3 to return a response may be greater than the value passed to
 
100
        `total`.
 
101
 
 
102
        In addition, the read and total timeouts only measure the time between
 
103
        read operations on the socket connecting the client and the server,
 
104
        not the total amount of time for the request to return a complete
 
105
        response. For most requests, the timeout is raised because the server
 
106
        has not sent the first byte in the specified time. This is not always
 
107
        the case; if a server streams one byte every fifteen seconds, a timeout
 
108
        of 20 seconds will not ever trigger, even though the request will
 
109
        take several minutes to complete.
 
110
 
 
111
        If your goal is to cut off any request after a set amount of wall clock
 
112
        time, consider having a second "watcher" thread to cut off a slow
 
113
        request.
 
114
    """
 
115
 
 
116
    #: A sentinel object representing the default timeout value
 
117
    DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT
 
118
 
 
119
    def __init__(self, total=None, connect=_Default, read=_Default):
 
120
        self._connect = self._validate_timeout(connect, 'connect')
 
121
        self._read = self._validate_timeout(read, 'read')
 
122
        self.total = self._validate_timeout(total, 'total')
 
123
        self._start_connect = None
 
124
 
 
125
    def __str__(self):
 
126
        return '%s(connect=%r, read=%r, total=%r)' % (
 
127
            type(self).__name__, self._connect, self._read, self.total)
 
128
 
 
129
 
 
130
    @classmethod
 
131
    def _validate_timeout(cls, value, name):
 
132
        """ Check that a timeout attribute is valid
 
133
 
 
134
        :param value: The timeout value to validate
 
135
        :param name: The name of the timeout attribute to validate. This is used
 
136
            for clear error messages
 
137
        :return: the value
 
138
        :raises ValueError: if the type is not an integer or a float, or if it
 
139
            is a numeric value less than zero
 
140
        """
 
141
        if value is _Default:
 
142
            return cls.DEFAULT_TIMEOUT
 
143
 
 
144
        if value is None or value is cls.DEFAULT_TIMEOUT:
 
145
            return value
 
146
 
 
147
        try:
 
148
            float(value)
 
149
        except (TypeError, ValueError):
 
150
            raise ValueError("Timeout value %s was %s, but it must be an "
 
151
                             "int or float." % (name, value))
 
152
 
 
153
        try:
 
154
            if value < 0:
 
155
                raise ValueError("Attempted to set %s timeout to %s, but the "
 
156
                                 "timeout cannot be set to a value less "
 
157
                                 "than 0." % (name, value))
 
158
        except TypeError: # Python 3
 
159
            raise ValueError("Timeout value %s was %s, but it must be an "
 
160
                             "int or float." % (name, value))
 
161
 
 
162
        return value
 
163
 
 
164
    @classmethod
 
165
    def from_float(cls, timeout):
 
166
        """ Create a new Timeout from a legacy timeout value.
 
167
 
 
168
        The timeout value used by httplib.py sets the same timeout on the
 
169
        connect(), and recv() socket requests. This creates a :class:`Timeout`
 
170
        object that sets the individual timeouts to the ``timeout`` value passed
 
171
        to this function.
 
172
 
 
173
        :param timeout: The legacy timeout value
 
174
        :type timeout: integer, float, sentinel default object, or None
 
175
        :return: a Timeout object
 
176
        :rtype: :class:`Timeout`
 
177
        """
 
178
        return Timeout(read=timeout, connect=timeout)
 
179
 
 
180
    def clone(self):
 
181
        """ Create a copy of the timeout object
 
182
 
 
183
        Timeout properties are stored per-pool but each request needs a fresh
 
184
        Timeout object to ensure each one has its own start/stop configured.
 
185
 
 
186
        :return: a copy of the timeout object
 
187
        :rtype: :class:`Timeout`
 
188
        """
 
189
        # We can't use copy.deepcopy because that will also create a new object
 
190
        # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to
 
191
        # detect the user default.
 
192
        return Timeout(connect=self._connect, read=self._read,
 
193
                       total=self.total)
 
194
 
 
195
    def start_connect(self):
 
196
        """ Start the timeout clock, used during a connect() attempt
 
197
 
 
198
        :raises urllib3.exceptions.TimeoutStateError: if you attempt
 
199
            to start a timer that has been started already.
 
200
        """
 
201
        if self._start_connect is not None:
 
202
            raise TimeoutStateError("Timeout timer has already been started.")
 
203
        self._start_connect = current_time()
 
204
        return self._start_connect
 
205
 
 
206
    def get_connect_duration(self):
 
207
        """ Gets the time elapsed since the call to :meth:`start_connect`.
 
208
 
 
209
        :return: the elapsed time
 
210
        :rtype: float
 
211
        :raises urllib3.exceptions.TimeoutStateError: if you attempt
 
212
            to get duration for a timer that hasn't been started.
 
213
        """
 
214
        if self._start_connect is None:
 
215
            raise TimeoutStateError("Can't get connect duration for timer "
 
216
                                    "that has not started.")
 
217
        return current_time() - self._start_connect
 
218
 
 
219
    @property
 
220
    def connect_timeout(self):
 
221
        """ Get the value to use when setting a connection timeout.
 
222
 
 
223
        This will be a positive float or integer, the value None
 
224
        (never timeout), or the default system timeout.
 
225
 
 
226
        :return: the connect timeout
 
227
        :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None
 
228
        """
 
229
        if self.total is None:
 
230
            return self._connect
 
231
 
 
232
        if self._connect is None or self._connect is self.DEFAULT_TIMEOUT:
 
233
            return self.total
 
234
 
 
235
        return min(self._connect, self.total)
 
236
 
 
237
    @property
 
238
    def read_timeout(self):
 
239
        """ Get the value for the read timeout.
 
240
 
 
241
        This assumes some time has elapsed in the connection timeout and
 
242
        computes the read timeout appropriately.
 
243
 
 
244
        If self.total is set, the read timeout is dependent on the amount of
 
245
        time taken by the connect timeout. If the connection time has not been
 
246
        established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be
 
247
        raised.
 
248
 
 
249
        :return: the value to use for the read timeout
 
250
        :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None
 
251
        :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect`
 
252
            has not yet been called on this object.
 
253
        """
 
254
        if (self.total is not None and
 
255
            self.total is not self.DEFAULT_TIMEOUT and
 
256
            self._read is not None and
 
257
            self._read is not self.DEFAULT_TIMEOUT):
 
258
            # in case the connect timeout has not yet been established.
 
259
            if self._start_connect is None:
 
260
                return self._read
 
261
            return max(0, min(self.total - self.get_connect_duration(),
 
262
                              self._read))
 
263
        elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT:
 
264
            return max(0, self.total - self.get_connect_duration())
 
265
        else:
 
266
            return self._read
 
267
 
 
268
 
 
269
class Url(namedtuple('Url', ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment'])):
 
270
    """
 
271
    Datastructure for representing an HTTP URL. Used as a return value for
 
272
    :func:`parse_url`.
 
273
    """
 
274
    slots = ()
 
275
 
 
276
    def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None, query=None, fragment=None):
 
277
        return super(Url, cls).__new__(cls, scheme, auth, host, port, path, query, fragment)
 
278
 
 
279
    @property
 
280
    def hostname(self):
 
281
        """For backwards-compatibility with urlparse. We're nice like that."""
 
282
        return self.host
 
283
 
 
284
    @property
 
285
    def request_uri(self):
 
286
        """Absolute path including the query string."""
 
287
        uri = self.path or '/'
 
288
 
 
289
        if self.query is not None:
 
290
            uri += '?' + self.query
 
291
 
 
292
        return uri
 
293
 
 
294
    @property
 
295
    def netloc(self):
 
296
        """Network location including host and port"""
 
297
        if self.port:
 
298
            return '%s:%d' % (self.host, self.port)
 
299
        return self.host
 
300
 
 
301
 
 
302
def split_first(s, delims):
 
303
    """
 
304
    Given a string and an iterable of delimiters, split on the first found
 
305
    delimiter. Return two split parts and the matched delimiter.
 
306
 
 
307
    If not found, then the first part is the full input string.
 
308
 
 
309
    Example: ::
 
310
 
 
311
        >>> split_first('foo/bar?baz', '?/=')
 
312
        ('foo', 'bar?baz', '/')
 
313
        >>> split_first('foo/bar?baz', '123')
 
314
        ('foo/bar?baz', '', None)
 
315
 
 
316
    Scales linearly with number of delims. Not ideal for large number of delims.
 
317
    """
 
318
    min_idx = None
 
319
    min_delim = None
 
320
    for d in delims:
 
321
        idx = s.find(d)
 
322
        if idx < 0:
 
323
            continue
 
324
 
 
325
        if min_idx is None or idx < min_idx:
 
326
            min_idx = idx
 
327
            min_delim = d
 
328
 
 
329
    if min_idx is None or min_idx < 0:
 
330
        return s, '', None
 
331
 
 
332
    return s[:min_idx], s[min_idx+1:], min_delim
 
333
 
 
334
 
 
335
def parse_url(url):
 
336
    """
 
337
    Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is
 
338
    performed to parse incomplete urls. Fields not provided will be None.
 
339
 
 
340
    Partly backwards-compatible with :mod:`urlparse`.
 
341
 
 
342
    Example: ::
 
343
 
 
344
        >>> parse_url('http://google.com/mail/')
 
345
        Url(scheme='http', host='google.com', port=None, path='/', ...)
 
346
        >>> parse_url('google.com:80')
 
347
        Url(scheme=None, host='google.com', port=80, path=None, ...)
 
348
        >>> parse_url('/foo?bar')
 
349
        Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)
 
350
    """
 
351
 
 
352
    # While this code has overlap with stdlib's urlparse, it is much
 
353
    # simplified for our needs and less annoying.
 
354
    # Additionally, this implementations does silly things to be optimal
 
355
    # on CPython.
 
356
 
 
357
    scheme = None
 
358
    auth = None
 
359
    host = None
 
360
    port = None
 
361
    path = None
 
362
    fragment = None
 
363
    query = None
 
364
 
 
365
    # Scheme
 
366
    if '://' in url:
 
367
        scheme, url = url.split('://', 1)
 
368
 
 
369
    # Find the earliest Authority Terminator
 
370
    # (http://tools.ietf.org/html/rfc3986#section-3.2)
 
371
    url, path_, delim = split_first(url, ['/', '?', '#'])
 
372
 
 
373
    if delim:
 
374
        # Reassemble the path
 
375
        path = delim + path_
 
376
 
 
377
    # Auth
 
378
    if '@' in url:
 
379
        # Last '@' denotes end of auth part
 
380
        auth, url = url.rsplit('@', 1)
 
381
 
 
382
    # IPv6
 
383
    if url and url[0] == '[':
 
384
        host, url = url.split(']', 1)
 
385
        host += ']'
 
386
 
 
387
    # Port
 
388
    if ':' in url:
 
389
        _host, port = url.split(':', 1)
 
390
 
 
391
        if not host:
 
392
            host = _host
 
393
 
 
394
        if port:
 
395
            # If given, ports must be integers.
 
396
            if not port.isdigit():
 
397
                raise LocationParseError("Failed to parse: %s" % url)
 
398
            port = int(port)
 
399
        else:
 
400
            # Blank ports are cool, too. (rfc3986#section-3.2.3)
 
401
            port = None
 
402
 
 
403
    elif not host and url:
 
404
        host = url
 
405
 
 
406
    if not path:
 
407
        return Url(scheme, auth, host, port, path, query, fragment)
 
408
 
 
409
    # Fragment
 
410
    if '#' in path:
 
411
        path, fragment = path.split('#', 1)
 
412
 
 
413
    # Query
 
414
    if '?' in path:
 
415
        path, query = path.split('?', 1)
 
416
 
 
417
    return Url(scheme, auth, host, port, path, query, fragment)
 
418
 
 
419
 
 
420
def get_host(url):
 
421
    """
 
422
    Deprecated. Use :func:`.parse_url` instead.
 
423
    """
 
424
    p = parse_url(url)
 
425
    return p.scheme or 'http', p.hostname, p.port
 
426
 
 
427
 
 
428
def make_headers(keep_alive=None, accept_encoding=None, user_agent=None,
 
429
                 basic_auth=None, proxy_basic_auth=None):
 
430
    """
 
431
    Shortcuts for generating request headers.
 
432
 
 
433
    :param keep_alive:
 
434
        If ``True``, adds 'connection: keep-alive' header.
 
435
 
 
436
    :param accept_encoding:
 
437
        Can be a boolean, list, or string.
 
438
        ``True`` translates to 'gzip,deflate'.
 
439
        List will get joined by comma.
 
440
        String will be used as provided.
 
441
 
 
442
    :param user_agent:
 
443
        String representing the user-agent you want, such as
 
444
        "python-urllib3/0.6"
 
445
 
 
446
    :param basic_auth:
 
447
        Colon-separated username:password string for 'authorization: basic ...'
 
448
        auth header.
 
449
 
 
450
    :param proxy_basic_auth:
 
451
        Colon-separated username:password string for 'proxy-authorization: basic ...'
 
452
        auth header.
 
453
 
 
454
    Example: ::
 
455
 
 
456
        >>> make_headers(keep_alive=True, user_agent="Batman/1.0")
 
457
        {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'}
 
458
        >>> make_headers(accept_encoding=True)
 
459
        {'accept-encoding': 'gzip,deflate'}
 
460
    """
 
461
    headers = {}
 
462
    if accept_encoding:
 
463
        if isinstance(accept_encoding, str):
 
464
            pass
 
465
        elif isinstance(accept_encoding, list):
 
466
            accept_encoding = ','.join(accept_encoding)
 
467
        else:
 
468
            accept_encoding = 'gzip,deflate'
 
469
        headers['accept-encoding'] = accept_encoding
 
470
 
 
471
    if user_agent:
 
472
        headers['user-agent'] = user_agent
 
473
 
 
474
    if keep_alive:
 
475
        headers['connection'] = 'keep-alive'
 
476
 
 
477
    if basic_auth:
 
478
        headers['authorization'] = 'Basic ' + \
 
479
            b64encode(six.b(basic_auth)).decode('utf-8')
 
480
 
 
481
    if proxy_basic_auth:
 
482
        headers['proxy-authorization'] = 'Basic ' + \
 
483
            b64encode(six.b(proxy_basic_auth)).decode('utf-8')
 
484
 
 
485
    return headers
 
486
 
 
487
 
 
488
def is_connection_dropped(conn):  # Platform-specific
 
489
    """
 
490
    Returns True if the connection is dropped and should be closed.
 
491
 
 
492
    :param conn:
 
493
        :class:`httplib.HTTPConnection` object.
 
494
 
 
495
    Note: For platforms like AppEngine, this will always return ``False`` to
 
496
    let the platform handle connection recycling transparently for us.
 
497
    """
 
498
    sock = getattr(conn, 'sock', False)
 
499
    if not sock: # Platform-specific: AppEngine
 
500
        return False
 
501
 
 
502
    if not poll:
 
503
        if not select: # Platform-specific: AppEngine
 
504
            return False
 
505
 
 
506
        try:
 
507
            return select([sock], [], [], 0.0)[0]
 
508
        except SocketError:
 
509
            return True
 
510
 
 
511
    # This version is better on platforms that support it.
 
512
    p = poll()
 
513
    p.register(sock, POLLIN)
 
514
    for (fno, ev) in p.poll(0.0):
 
515
        if fno == sock.fileno():
 
516
            # Either data is buffered (bad), or the connection is dropped.
 
517
            return True
 
518
 
 
519
 
 
520
def resolve_cert_reqs(candidate):
 
521
    """
 
522
    Resolves the argument to a numeric constant, which can be passed to
 
523
    the wrap_socket function/method from the ssl module.
 
524
    Defaults to :data:`ssl.CERT_NONE`.
 
525
    If given a string it is assumed to be the name of the constant in the
 
526
    :mod:`ssl` module or its abbrevation.
 
527
    (So you can specify `REQUIRED` instead of `CERT_REQUIRED`.
 
528
    If it's neither `None` nor a string we assume it is already the numeric
 
529
    constant which can directly be passed to wrap_socket.
 
530
    """
 
531
    if candidate is None:
 
532
        return CERT_NONE
 
533
 
 
534
    if isinstance(candidate, str):
 
535
        res = getattr(ssl, candidate, None)
 
536
        if res is None:
 
537
            res = getattr(ssl, 'CERT_' + candidate)
 
538
        return res
 
539
 
 
540
    return candidate
 
541
 
 
542
 
 
543
def resolve_ssl_version(candidate):
 
544
    """
 
545
    like resolve_cert_reqs
 
546
    """
 
547
    if candidate is None:
 
548
        return PROTOCOL_SSLv23
 
549
 
 
550
    if isinstance(candidate, str):
 
551
        res = getattr(ssl, candidate, None)
 
552
        if res is None:
 
553
            res = getattr(ssl, 'PROTOCOL_' + candidate)
 
554
        return res
 
555
 
 
556
    return candidate
 
557
 
 
558
 
 
559
def assert_fingerprint(cert, fingerprint):
 
560
    """
 
561
    Checks if given fingerprint matches the supplied certificate.
 
562
 
 
563
    :param cert:
 
564
        Certificate as bytes object.
 
565
    :param fingerprint:
 
566
        Fingerprint as string of hexdigits, can be interspersed by colons.
 
567
    """
 
568
 
 
569
    # Maps the length of a digest to a possible hash function producing
 
570
    # this digest.
 
571
    hashfunc_map = {
 
572
        16: md5,
 
573
        20: sha1
 
574
    }
 
575
 
 
576
    fingerprint = fingerprint.replace(':', '').lower()
 
577
 
 
578
    digest_length, rest = divmod(len(fingerprint), 2)
 
579
 
 
580
    if rest or digest_length not in hashfunc_map:
 
581
        raise SSLError('Fingerprint is of invalid length.')
 
582
 
 
583
    # We need encode() here for py32; works on py2 and p33.
 
584
    fingerprint_bytes = unhexlify(fingerprint.encode())
 
585
 
 
586
    hashfunc = hashfunc_map[digest_length]
 
587
 
 
588
    cert_digest = hashfunc(cert).digest()
 
589
 
 
590
    if not cert_digest == fingerprint_bytes:
 
591
        raise SSLError('Fingerprints did not match. Expected "{0}", got "{1}".'
 
592
                       .format(hexlify(fingerprint_bytes),
 
593
                               hexlify(cert_digest)))
 
594
 
 
595
def is_fp_closed(obj):
 
596
    """
 
597
    Checks whether a given file-like object is closed.
 
598
 
 
599
    :param obj:
 
600
        The file-like object to check.
 
601
    """
 
602
    if hasattr(obj, 'fp'):
 
603
        # Object is a container for another file-like object that gets released
 
604
        # on exhaustion (e.g. HTTPResponse)
 
605
        return obj.fp is None
 
606
 
 
607
    return obj.closed
 
608
 
 
609
 
 
610
if SSLContext is not None:  # Python 3.2+
 
611
    def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
 
612
                        ca_certs=None, server_hostname=None,
 
613
                        ssl_version=None):
 
614
        """
 
615
        All arguments except `server_hostname` have the same meaning as for
 
616
        :func:`ssl.wrap_socket`
 
617
 
 
618
        :param server_hostname:
 
619
            Hostname of the expected certificate
 
620
        """
 
621
        context = SSLContext(ssl_version)
 
622
        context.verify_mode = cert_reqs
 
623
 
 
624
        # Disable TLS compression to migitate CRIME attack (issue #309)
 
625
        OP_NO_COMPRESSION = 0x20000
 
626
        context.options |= OP_NO_COMPRESSION
 
627
 
 
628
        if ca_certs:
 
629
            try:
 
630
                context.load_verify_locations(ca_certs)
 
631
            # Py32 raises IOError
 
632
            # Py33 raises FileNotFoundError
 
633
            except Exception as e:  # Reraise as SSLError
 
634
                raise SSLError(e)
 
635
        if certfile:
 
636
            # FIXME: This block needs a test.
 
637
            context.load_cert_chain(certfile, keyfile)
 
638
        if HAS_SNI:  # Platform-specific: OpenSSL with enabled SNI
 
639
            return context.wrap_socket(sock, server_hostname=server_hostname)
 
640
        return context.wrap_socket(sock)
 
641
 
 
642
else:  # Python 3.1 and earlier
 
643
    def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
 
644
                        ca_certs=None, server_hostname=None,
 
645
                        ssl_version=None):
 
646
        return wrap_socket(sock, keyfile=keyfile, certfile=certfile,
 
647
                           ca_certs=ca_certs, cert_reqs=cert_reqs,
 
648
                           ssl_version=ssl_version)