Browse Source

Update requests

pull/4808/head
Ruud 10 years ago
parent
commit
ff01984ba7
  1. 8
      libs/requests/__init__.py
  2. 2
      libs/requests/adapters.py
  3. 31
      libs/requests/api.py
  4. 4
      libs/requests/auth.py
  5. 55
      libs/requests/compat.py
  6. 87
      libs/requests/cookies.py
  7. 13
      libs/requests/models.py
  8. 106
      libs/requests/packages/__init__.py
  9. 4
      libs/requests/packages/urllib3/__init__.py
  10. 222
      libs/requests/packages/urllib3/_collections.py
  11. 55
      libs/requests/packages/urllib3/connectionpool.py
  12. 5
      libs/requests/packages/urllib3/contrib/pyopenssl.py
  13. 5
      libs/requests/packages/urllib3/exceptions.py
  14. 19
      libs/requests/packages/urllib3/poolmanager.py
  15. 44
      libs/requests/packages/urllib3/response.py
  16. 1
      libs/requests/packages/urllib3/util/connection.py
  17. 2
      libs/requests/packages/urllib3/util/retry.py
  18. 24
      libs/requests/packages/urllib3/util/ssl_.py
  19. 5
      libs/requests/sessions.py
  20. 20
      libs/requests/utils.py

8
libs/requests/__init__.py

@ -36,17 +36,17 @@ usage:
The other HTTP methods are supported - see `requests.api`. Full documentation The other HTTP methods are supported - see `requests.api`. Full documentation
is at <http://python-requests.org>. is at <http://python-requests.org>.
:copyright: (c) 2014 by Kenneth Reitz. :copyright: (c) 2015 by Kenneth Reitz.
:license: Apache 2.0, see LICENSE for more details. :license: Apache 2.0, see LICENSE for more details.
""" """
__title__ = 'requests' __title__ = 'requests'
__version__ = '2.5.1' __version__ = '2.6.0'
__build__ = 0x020501 __build__ = 0x020503
__author__ = 'Kenneth Reitz' __author__ = 'Kenneth Reitz'
__license__ = 'Apache 2.0' __license__ = 'Apache 2.0'
__copyright__ = 'Copyright 2014 Kenneth Reitz' __copyright__ = 'Copyright 2015 Kenneth Reitz'
# Attempt to enable urllib3's SNI support, if possible # Attempt to enable urllib3's SNI support, if possible
try: try:

2
libs/requests/adapters.py

@ -11,10 +11,10 @@ and maintain connections.
import socket import socket
from .models import Response from .models import Response
from .packages.urllib3 import Retry
from .packages.urllib3.poolmanager import PoolManager, proxy_from_url from .packages.urllib3.poolmanager import PoolManager, proxy_from_url
from .packages.urllib3.response import HTTPResponse from .packages.urllib3.response import HTTPResponse
from .packages.urllib3.util import Timeout as TimeoutSauce from .packages.urllib3.util import Timeout as TimeoutSauce
from .packages.urllib3.util.retry import Retry
from .compat import urlparse, basestring from .compat import urlparse, basestring
from .utils import (DEFAULT_CA_BUNDLE_PATH, get_encoding_from_headers, from .utils import (DEFAULT_CA_BUNDLE_PATH, get_encoding_from_headers,
prepend_scheme_if_needed, get_auth_from_url, urldefragauth) prepend_scheme_if_needed, get_auth_from_url, urldefragauth)

31
libs/requests/api.py

@ -16,7 +16,6 @@ from . import sessions
def request(method, url, **kwargs): def request(method, url, **kwargs):
"""Constructs and sends a :class:`Request <Request>`. """Constructs and sends a :class:`Request <Request>`.
Returns :class:`Response <Response>` object.
:param method: method for the new :class:`Request` object. :param method: method for the new :class:`Request` object.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
@ -37,6 +36,8 @@ def request(method, url, **kwargs):
:param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided. :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided.
:param stream: (optional) if ``False``, the response content will be immediately downloaded. :param stream: (optional) if ``False``, the response content will be immediately downloaded.
:param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
:return: :class:`Response <Response>` object
:rtype: requests.Response
Usage:: Usage::
@ -55,10 +56,12 @@ def request(method, url, **kwargs):
def get(url, **kwargs): def get(url, **kwargs):
"""Sends a GET request. Returns :class:`Response` object. """Sends a GET request.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
:param \*\*kwargs: Optional arguments that ``request`` takes. :param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" """
kwargs.setdefault('allow_redirects', True) kwargs.setdefault('allow_redirects', True)
@ -66,10 +69,12 @@ def get(url, **kwargs):
def options(url, **kwargs): def options(url, **kwargs):
"""Sends a OPTIONS request. Returns :class:`Response` object. """Sends a OPTIONS request.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
:param \*\*kwargs: Optional arguments that ``request`` takes. :param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" """
kwargs.setdefault('allow_redirects', True) kwargs.setdefault('allow_redirects', True)
@ -77,10 +82,12 @@ def options(url, **kwargs):
def head(url, **kwargs): def head(url, **kwargs):
"""Sends a HEAD request. Returns :class:`Response` object. """Sends a HEAD request.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
:param \*\*kwargs: Optional arguments that ``request`` takes. :param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" """
kwargs.setdefault('allow_redirects', False) kwargs.setdefault('allow_redirects', False)
@ -88,44 +95,52 @@ def head(url, **kwargs):
def post(url, data=None, json=None, **kwargs): def post(url, data=None, json=None, **kwargs):
"""Sends a POST request. Returns :class:`Response` object. """Sends a POST request.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
:param json: (optional) json data to send in the body of the :class:`Request`. :param json: (optional) json data to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes. :param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" """
return request('post', url, data=data, json=json, **kwargs) return request('post', url, data=data, json=json, **kwargs)
def put(url, data=None, **kwargs): def put(url, data=None, **kwargs):
"""Sends a PUT request. Returns :class:`Response` object. """Sends a PUT request.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes. :param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" """
return request('put', url, data=data, **kwargs) return request('put', url, data=data, **kwargs)
def patch(url, data=None, **kwargs): def patch(url, data=None, **kwargs):
"""Sends a PATCH request. Returns :class:`Response` object. """Sends a PATCH request.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes. :param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" """
return request('patch', url, data=data, **kwargs) return request('patch', url, data=data, **kwargs)
def delete(url, **kwargs): def delete(url, **kwargs):
"""Sends a DELETE request. Returns :class:`Response` object. """Sends a DELETE request.
:param url: URL for the new :class:`Request` object. :param url: URL for the new :class:`Request` object.
:param \*\*kwargs: Optional arguments that ``request`` takes. :param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
""" """
return request('delete', url, **kwargs) return request('delete', url, **kwargs)

4
libs/requests/auth.py

@ -124,13 +124,15 @@ class HTTPDigestAuth(AuthBase):
s += os.urandom(8) s += os.urandom(8)
cnonce = (hashlib.sha1(s).hexdigest()[:16]) cnonce = (hashlib.sha1(s).hexdigest()[:16])
noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, HA2)
if _algorithm == 'MD5-SESS': if _algorithm == 'MD5-SESS':
HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce)) HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce))
if qop is None: if qop is None:
respdig = KD(HA1, "%s:%s" % (nonce, HA2)) respdig = KD(HA1, "%s:%s" % (nonce, HA2))
elif qop == 'auth' or 'auth' in qop.split(','): elif qop == 'auth' or 'auth' in qop.split(','):
noncebit = "%s:%s:%s:%s:%s" % (
nonce, ncvalue, cnonce, 'auth', HA2
)
respdig = KD(HA1, noncebit) respdig = KD(HA1, noncebit)
else: else:
# XXX handle auth-int. # XXX handle auth-int.

55
libs/requests/compat.py

@ -4,7 +4,7 @@
pythoncompat pythoncompat
""" """
import chardet from .packages import chardet
import sys import sys
@ -21,58 +21,6 @@ is_py2 = (_ver[0] == 2)
#: Python 3.x? #: Python 3.x?
is_py3 = (_ver[0] == 3) is_py3 = (_ver[0] == 3)
#: Python 3.0.x
is_py30 = (is_py3 and _ver[1] == 0)
#: Python 3.1.x
is_py31 = (is_py3 and _ver[1] == 1)
#: Python 3.2.x
is_py32 = (is_py3 and _ver[1] == 2)
#: Python 3.3.x
is_py33 = (is_py3 and _ver[1] == 3)
#: Python 3.4.x
is_py34 = (is_py3 and _ver[1] == 4)
#: Python 2.7.x
is_py27 = (is_py2 and _ver[1] == 7)
#: Python 2.6.x
is_py26 = (is_py2 and _ver[1] == 6)
#: Python 2.5.x
is_py25 = (is_py2 and _ver[1] == 5)
#: Python 2.4.x
is_py24 = (is_py2 and _ver[1] == 4) # I'm assuming this is not by choice.
# ---------
# Platforms
# ---------
# Syntax sugar.
_ver = sys.version.lower()
is_pypy = ('pypy' in _ver)
is_jython = ('jython' in _ver)
is_ironpython = ('iron' in _ver)
# Assume CPython, if nothing else.
is_cpython = not any((is_pypy, is_jython, is_ironpython))
# Windows-based system.
is_windows = 'win32' in str(sys.platform).lower()
# Standard Linux 2+ system.
is_linux = ('linux' in str(sys.platform).lower())
is_osx = ('darwin' in str(sys.platform).lower())
is_hpux = ('hpux' in str(sys.platform).lower()) # Complete guess.
is_solaris = ('solar==' in str(sys.platform).lower()) # Complete guess.
try: try:
import simplejson as json import simplejson as json
except (ImportError, SyntaxError): except (ImportError, SyntaxError):
@ -99,7 +47,6 @@ if is_py2:
basestring = basestring basestring = basestring
numeric_types = (int, long, float) numeric_types = (int, long, float)
elif is_py3: elif is_py3:
from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag
from urllib.request import parse_http_list, getproxies, proxy_bypass from urllib.request import parse_http_list, getproxies, proxy_bypass

87
libs/requests/cookies.py

@ -157,26 +157,28 @@ class CookieConflictError(RuntimeError):
class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping): class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
"""Compatibility class; is a cookielib.CookieJar, but exposes a dict interface. """Compatibility class; is a cookielib.CookieJar, but exposes a dict
interface.
This is the CookieJar we create by default for requests and sessions that This is the CookieJar we create by default for requests and sessions that
don't specify one, since some clients may expect response.cookies and don't specify one, since some clients may expect response.cookies and
session.cookies to support dict operations. session.cookies to support dict operations.
Don't use the dict interface internally; it's just for compatibility with Requests does not use the dict interface internally; it's just for
with external client code. All `requests` code should work out of the box compatibility with external client code. All requests code should work
with externally provided instances of CookieJar, e.g., LWPCookieJar and out of the box with externally provided instances of ``CookieJar``, e.g.
FileCookieJar. ``LWPCookieJar`` and ``FileCookieJar``.
Caution: dictionary operations that are normally O(1) may be O(n).
Unlike a regular CookieJar, this class is pickleable. Unlike a regular CookieJar, this class is pickleable.
"""
.. warning:: dictionary operations that are normally O(1) may be O(n).
"""
def get(self, name, default=None, domain=None, path=None): def get(self, name, default=None, domain=None, path=None):
"""Dict-like get() that also supports optional domain and path args in """Dict-like get() that also supports optional domain and path args in
order to resolve naming collisions from using one cookie jar over order to resolve naming collisions from using one cookie jar over
multiple domains. Caution: operation is O(n), not O(1).""" multiple domains.
.. warning:: operation is O(n), not O(1)."""
try: try:
return self._find_no_duplicates(name, domain, path) return self._find_no_duplicates(name, domain, path)
except KeyError: except KeyError:
@ -199,37 +201,38 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
return c return c
def iterkeys(self): def iterkeys(self):
"""Dict-like iterkeys() that returns an iterator of names of cookies from the jar. """Dict-like iterkeys() that returns an iterator of names of cookies
See itervalues() and iteritems().""" from the jar. See itervalues() and iteritems()."""
for cookie in iter(self): for cookie in iter(self):
yield cookie.name yield cookie.name
def keys(self): def keys(self):
"""Dict-like keys() that returns a list of names of cookies from the jar. """Dict-like keys() that returns a list of names of cookies from the
See values() and items().""" jar. See values() and items()."""
return list(self.iterkeys()) return list(self.iterkeys())
def itervalues(self): def itervalues(self):
"""Dict-like itervalues() that returns an iterator of values of cookies from the jar. """Dict-like itervalues() that returns an iterator of values of cookies
See iterkeys() and iteritems().""" from the jar. See iterkeys() and iteritems()."""
for cookie in iter(self): for cookie in iter(self):
yield cookie.value yield cookie.value
def values(self): def values(self):
"""Dict-like values() that returns a list of values of cookies from the jar. """Dict-like values() that returns a list of values of cookies from the
See keys() and items().""" jar. See keys() and items()."""
return list(self.itervalues()) return list(self.itervalues())
def iteritems(self): def iteritems(self):
"""Dict-like iteritems() that returns an iterator of name-value tuples from the jar. """Dict-like iteritems() that returns an iterator of name-value tuples
See iterkeys() and itervalues().""" from the jar. See iterkeys() and itervalues()."""
for cookie in iter(self): for cookie in iter(self):
yield cookie.name, cookie.value yield cookie.name, cookie.value
def items(self): def items(self):
"""Dict-like items() that returns a list of name-value tuples from the jar. """Dict-like items() that returns a list of name-value tuples from the
See keys() and values(). Allows client-code to call "dict(RequestsCookieJar) jar. See keys() and values(). Allows client-code to call
and get a vanilla python dict of key value pairs.""" ``dict(RequestsCookieJar)`` and get a vanilla python dict of key value
pairs."""
return list(self.iteritems()) return list(self.iteritems())
def list_domains(self): def list_domains(self):
@ -259,8 +262,9 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
return False # there is only one domain in jar return False # there is only one domain in jar
def get_dict(self, domain=None, path=None): def get_dict(self, domain=None, path=None):
"""Takes as an argument an optional domain and path and returns a plain old """Takes as an argument an optional domain and path and returns a plain
Python dict of name-value pairs of cookies that meet the requirements.""" old Python dict of name-value pairs of cookies that meet the
requirements."""
dictionary = {} dictionary = {}
for cookie in iter(self): for cookie in iter(self):
if (domain is None or cookie.domain == domain) and (path is None if (domain is None or cookie.domain == domain) and (path is None
@ -269,21 +273,24 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
return dictionary return dictionary
def __getitem__(self, name): def __getitem__(self, name):
"""Dict-like __getitem__() for compatibility with client code. Throws exception """Dict-like __getitem__() for compatibility with client code. Throws
if there are more than one cookie with name. In that case, use the more exception if there are more than one cookie with name. In that case,
explicit get() method instead. Caution: operation is O(n), not O(1).""" use the more explicit get() method instead.
.. warning:: operation is O(n), not O(1)."""
return self._find_no_duplicates(name) return self._find_no_duplicates(name)
def __setitem__(self, name, value): def __setitem__(self, name, value):
"""Dict-like __setitem__ for compatibility with client code. Throws exception """Dict-like __setitem__ for compatibility with client code. Throws
if there is already a cookie of that name in the jar. In that case, use the more exception if there is already a cookie of that name in the jar. In that
explicit set() method instead.""" case, use the more explicit set() method instead."""
self.set(name, value) self.set(name, value)
def __delitem__(self, name): def __delitem__(self, name):
"""Deletes a cookie given a name. Wraps cookielib.CookieJar's remove_cookie_by_name().""" """Deletes a cookie given a name. Wraps ``cookielib.CookieJar``'s
``remove_cookie_by_name()``."""
remove_cookie_by_name(self, name) remove_cookie_by_name(self, name)
def set_cookie(self, cookie, *args, **kwargs): def set_cookie(self, cookie, *args, **kwargs):
@ -300,10 +307,11 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
super(RequestsCookieJar, self).update(other) super(RequestsCookieJar, self).update(other)
def _find(self, name, domain=None, path=None): def _find(self, name, domain=None, path=None):
"""Requests uses this method internally to get cookie values. Takes as args name """Requests uses this method internally to get cookie values. Takes as
and optional domain and path. Returns a cookie.value. If there are conflicting cookies, args name and optional domain and path. Returns a cookie.value. If
_find arbitrarily chooses one. See _find_no_duplicates if you want an exception thrown there are conflicting cookies, _find arbitrarily chooses one. See
if there are conflicting cookies.""" _find_no_duplicates if you want an exception thrown if there are
conflicting cookies."""
for cookie in iter(self): for cookie in iter(self):
if cookie.name == name: if cookie.name == name:
if domain is None or cookie.domain == domain: if domain is None or cookie.domain == domain:
@ -313,10 +321,11 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path))
def _find_no_duplicates(self, name, domain=None, path=None): def _find_no_duplicates(self, name, domain=None, path=None):
"""__get_item__ and get call _find_no_duplicates -- never used in Requests internally. """Both ``__get_item__`` and ``get`` call this function: it's never
Takes as args name and optional domain and path. Returns a cookie.value. used elsewhere in Requests. Takes as args name and optional domain and
Throws KeyError if cookie is not found and CookieConflictError if there are path. Returns a cookie.value. Throws KeyError if cookie is not found
multiple cookies that match name and optionally domain and path.""" and CookieConflictError if there are multiple cookies that match name
and optionally domain and path."""
toReturn = None toReturn = None
for cookie in iter(self): for cookie in iter(self):
if cookie.name == name: if cookie.name == name:

13
libs/requests/models.py

@ -143,12 +143,13 @@ class RequestEncodingMixin(object):
else: else:
fn = guess_filename(v) or k fn = guess_filename(v) or k
fp = v fp = v
if isinstance(fp, str):
fp = StringIO(fp)
if isinstance(fp, bytes):
fp = BytesIO(fp)
rf = RequestField(name=k, data=fp.read(), if isinstance(fp, (str, bytes, bytearray)):
fdata = fp
else:
fdata = fp.read()
rf = RequestField(name=k, data=fdata,
filename=fn, headers=fh) filename=fn, headers=fh)
rf.make_multipart(content_type=ft) rf.make_multipart(content_type=ft)
new_fields.append(rf) new_fields.append(rf)
@ -688,6 +689,8 @@ class Response(object):
"""Iterates over the response data, one line at a time. When """Iterates over the response data, one line at a time. When
stream=True is set on the request, this avoids reading the stream=True is set on the request, this avoids reading the
content at once into memory for large responses. content at once into memory for large responses.
.. note:: This method is not reentrant safe.
""" """
pending = None pending = None

106
libs/requests/packages/__init__.py

@ -1,3 +1,107 @@
"""
Copyright (c) Donald Stufft, pip, and individual contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
from __future__ import absolute_import from __future__ import absolute_import
from . import urllib3 import sys
class VendorAlias(object):
def __init__(self, package_names):
self._package_names = package_names
self._vendor_name = __name__
self._vendor_pkg = self._vendor_name + "."
self._vendor_pkgs = [
self._vendor_pkg + name for name in self._package_names
]
def find_module(self, fullname, path=None):
if fullname.startswith(self._vendor_pkg):
return self
def load_module(self, name):
# Ensure that this only works for the vendored name
if not name.startswith(self._vendor_pkg):
raise ImportError(
"Cannot import %s, must be a subpackage of '%s'." % (
name, self._vendor_name,
)
)
if not (name == self._vendor_name or
any(name.startswith(pkg) for pkg in self._vendor_pkgs)):
raise ImportError(
"Cannot import %s, must be one of %s." % (
name, self._vendor_pkgs
)
)
# Check to see if we already have this item in sys.modules, if we do
# then simply return that.
if name in sys.modules:
return sys.modules[name]
# Check to see if we can import the vendor name
try:
# We do this dance here because we want to try and import this
# module without hitting a recursion error because of a bunch of
# VendorAlias instances on sys.meta_path
real_meta_path = sys.meta_path[:]
try:
sys.meta_path = [
m for m in sys.meta_path
if not isinstance(m, VendorAlias)
]
__import__(name)
module = sys.modules[name]
finally:
# Re-add any additions to sys.meta_path that were made while
# during the import we just did, otherwise things like
# requests.packages.urllib3.poolmanager will fail.
for m in sys.meta_path:
if m not in real_meta_path:
real_meta_path.append(m)
# Restore sys.meta_path with any new items.
sys.meta_path = real_meta_path
except ImportError:
# We can't import the vendor name, so we'll try to import the
# "real" name.
real_name = name[len(self._vendor_pkg):]
try:
__import__(real_name)
module = sys.modules[real_name]
except ImportError:
raise ImportError("No module named '%s'" % (name,))
# If we've gotten here we've found the module we're looking for, either
# as part of our vendored package, or as the real name, so we'll add
# it to sys.modules as the vendored name so that we don't have to do
# the lookup again.
sys.modules[name] = module
# Finally, return the loaded module
return module
sys.meta_path.append(VendorAlias(["urllib3", "chardet"]))

4
libs/requests/packages/urllib3/__init__.py

@ -4,7 +4,7 @@ urllib3 - Thread-safe connection pooling and re-using.
__author__ = 'Andrey Petrov (andrey.petrov@shazow.net)' __author__ = 'Andrey Petrov (andrey.petrov@shazow.net)'
__license__ = 'MIT' __license__ = 'MIT'
__version__ = 'dev' __version__ = '1.10.2'
from .connectionpool import ( from .connectionpool import (
@ -55,7 +55,7 @@ def add_stderr_logger(level=logging.DEBUG):
del NullHandler del NullHandler
# Set security warning to only go off once by default. # Set security warning to always go off by default.
import warnings import warnings
warnings.simplefilter('always', exceptions.SecurityWarning) warnings.simplefilter('always', exceptions.SecurityWarning)

222
libs/requests/packages/urllib3/_collections.py

@ -14,7 +14,7 @@ try: # Python 2.7+
from collections import OrderedDict from collections import OrderedDict
except ImportError: except ImportError:
from .packages.ordered_dict import OrderedDict from .packages.ordered_dict import OrderedDict
from .packages.six import iterkeys, itervalues from .packages.six import iterkeys, itervalues, PY3
__all__ = ['RecentlyUsedContainer', 'HTTPHeaderDict'] __all__ = ['RecentlyUsedContainer', 'HTTPHeaderDict']
@ -97,7 +97,14 @@ class RecentlyUsedContainer(MutableMapping):
return list(iterkeys(self._container)) return list(iterkeys(self._container))
class HTTPHeaderDict(MutableMapping): _dict_setitem = dict.__setitem__
_dict_getitem = dict.__getitem__
_dict_delitem = dict.__delitem__
_dict_contains = dict.__contains__
_dict_setdefault = dict.setdefault
class HTTPHeaderDict(dict):
""" """
:param headers: :param headers:
An iterable of field-value pairs. Must not contain multiple field names An iterable of field-value pairs. Must not contain multiple field names
@ -129,25 +136,75 @@ class HTTPHeaderDict(MutableMapping):
'foo=bar, baz=quxx' 'foo=bar, baz=quxx'
>>> headers['Content-Length'] >>> headers['Content-Length']
'7' '7'
If you want to access the raw headers with their original casing
for debugging purposes you can access the private ``._data`` attribute
which is a normal python ``dict`` that maps the case-insensitive key to a
list of tuples stored as (case-sensitive-original-name, value). Using the
structure from above as our example:
>>> headers._data
{'set-cookie': [('Set-Cookie', 'foo=bar'), ('set-cookie', 'baz=quxx')],
'content-length': [('content-length', '7')]}
""" """
def __init__(self, headers=None, **kwargs): def __init__(self, headers=None, **kwargs):
self._data = {} dict.__init__(self)
if headers is None: if headers is not None:
headers = {} if isinstance(headers, HTTPHeaderDict):
self.update(headers, **kwargs) self._copy_from(headers)
else:
self.extend(headers)
if kwargs:
self.extend(kwargs)
def __setitem__(self, key, val):
return _dict_setitem(self, key.lower(), (key, val))
def __getitem__(self, key):
val = _dict_getitem(self, key.lower())
return ', '.join(val[1:])
def __delitem__(self, key):
return _dict_delitem(self, key.lower())
def add(self, key, value): def __contains__(self, key):
return _dict_contains(self, key.lower())
def __eq__(self, other):
if not isinstance(other, Mapping) and not hasattr(other, 'keys'):
return False
if not isinstance(other, type(self)):
other = type(self)(other)
return dict((k1, self[k1]) for k1 in self) == dict((k2, other[k2]) for k2 in other)
def __ne__(self, other):
return not self.__eq__(other)
values = MutableMapping.values
get = MutableMapping.get
update = MutableMapping.update
if not PY3: # Python 2
iterkeys = MutableMapping.iterkeys
itervalues = MutableMapping.itervalues
__marker = object()
def pop(self, key, default=__marker):
'''D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
If key is not found, d is returned if given, otherwise KeyError is raised.
'''
# Using the MutableMapping function directly fails due to the private marker.
# Using ordinary dict.pop would expose the internal structures.
# So let's reinvent the wheel.
try:
value = self[key]
except KeyError:
if default is self.__marker:
raise
return default
else:
del self[key]
return value
def discard(self, key):
try:
del self[key]
except KeyError:
pass
def add(self, key, val):
"""Adds a (name, value) pair, doesn't overwrite the value if it already """Adds a (name, value) pair, doesn't overwrite the value if it already
exists. exists.
@ -156,43 +213,108 @@ class HTTPHeaderDict(MutableMapping):
>>> headers['foo'] >>> headers['foo']
'bar, baz' 'bar, baz'
""" """
self._data.setdefault(key.lower(), []).append((key, value)) key_lower = key.lower()
new_vals = key, val
# Keep the common case aka no item present as fast as possible
vals = _dict_setdefault(self, key_lower, new_vals)
if new_vals is not vals:
# new_vals was not inserted, as there was a previous one
if isinstance(vals, list):
# If already several items got inserted, we have a list
vals.append(val)
else:
# vals should be a tuple then, i.e. only one item so far
# Need to convert the tuple to list for further extension
_dict_setitem(self, key_lower, [vals[0], vals[1], val])
def extend(*args, **kwargs):
"""Generic import function for any type of header-like object.
Adapted version of MutableMapping.update in order to insert items
with self.add instead of self.__setitem__
"""
if len(args) > 2:
raise TypeError("update() takes at most 2 positional "
"arguments ({} given)".format(len(args)))
elif not args:
raise TypeError("update() takes at least 1 argument (0 given)")
self = args[0]
other = args[1] if len(args) >= 2 else ()
if isinstance(other, Mapping):
for key in other:
self.add(key, other[key])
elif hasattr(other, "keys"):
for key in other.keys():
self.add(key, other[key])
else:
for key, value in other:
self.add(key, value)
for key, value in kwargs.items():
self.add(key, value)
def getlist(self, key): def getlist(self, key):
"""Returns a list of all the values for the named field. Returns an """Returns a list of all the values for the named field. Returns an
empty list if the key doesn't exist.""" empty list if the key doesn't exist."""
return self[key].split(', ') if key in self else [] try:
vals = _dict_getitem(self, key.lower())
def copy(self): except KeyError:
h = HTTPHeaderDict() return []
for key in self._data: else:
for rawkey, value in self._data[key]: if isinstance(vals, tuple):
h.add(rawkey, value) return [vals[1]]
return h else:
return vals[1:]
def __eq__(self, other):
if not isinstance(other, Mapping): # Backwards compatibility for httplib
return False getheaders = getlist
other = HTTPHeaderDict(other) getallmatchingheaders = getlist
return dict((k1, self[k1]) for k1 in self._data) == \ iget = getlist
dict((k2, other[k2]) for k2 in other._data)
def __getitem__(self, key):
values = self._data[key.lower()]
return ', '.join(value[1] for value in values)
def __setitem__(self, key, value):
self._data[key.lower()] = [(key, value)]
def __delitem__(self, key): def __repr__(self):
del self._data[key.lower()] return "%s(%s)" % (type(self).__name__, dict(self.itermerged()))
def __len__(self): def _copy_from(self, other):
return len(self._data) for key in other:
val = _dict_getitem(other, key)
if isinstance(val, list):
# Don't need to convert tuples
val = list(val)
_dict_setitem(self, key, val)
def __iter__(self): def copy(self):
for headers in itervalues(self._data): clone = type(self)()
yield headers[0][0] clone._copy_from(self)
return clone
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, dict(self.items())) def iteritems(self):
"""Iterate over all header lines, including duplicate ones."""
for key in self:
vals = _dict_getitem(self, key)
for val in vals[1:]:
yield vals[0], val
def itermerged(self):
"""Iterate over all headers, merging duplicate ones together."""
for key in self:
val = _dict_getitem(self, key)
yield val[0], ', '.join(val[1:])
def items(self):
return list(self.iteritems())
@classmethod
def from_httplib(cls, message, duplicates=('set-cookie',)): # Python 2
"""Read headers from a Python 2 httplib message object."""
ret = cls(message.items())
# ret now contains only the last header line for each duplicate.
# Importing with all duplicates would be nice, but this would
# mean to repeat most of the raw parsing already done, when the
# message object was created. Extracting only the headers of interest
# separately, the cookies, should be faster and requires less
# extra code.
for key in duplicates:
ret.discard(key)
for val in message.getheaders(key):
ret.add(key, val)
return ret

55
libs/requests/packages/urllib3/connectionpool.py

@ -72,6 +72,21 @@ class ConnectionPool(object):
return '%s(host=%r, port=%r)' % (type(self).__name__, return '%s(host=%r, port=%r)' % (type(self).__name__,
self.host, self.port) self.host, self.port)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
# Return False to re-raise any potential exceptions
return False
def close():
"""
Close all pooled connections and disable the pool.
"""
pass
# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 # This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252
_blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK]) _blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK])
@ -266,6 +281,10 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
""" """
pass pass
def _prepare_proxy(self, conn):
# Nothing to do for HTTP connections.
pass
def _get_timeout(self, timeout): def _get_timeout(self, timeout):
""" Helper that always returns a :class:`urllib3.util.Timeout` """ """ Helper that always returns a :class:`urllib3.util.Timeout` """
if timeout is _Default: if timeout is _Default:
@ -349,7 +368,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
# Receive the response from the server # Receive the response from the server
try: try:
try: # Python 2.7+, use buffering of HTTP responses try: # Python 2.7, use buffering of HTTP responses
httplib_response = conn.getresponse(buffering=True) httplib_response = conn.getresponse(buffering=True)
except TypeError: # Python 2.6 and older except TypeError: # Python 2.6 and older
httplib_response = conn.getresponse() httplib_response = conn.getresponse()
@ -510,11 +529,18 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
try: try:
# Request a connection from the queue. # Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout) conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout
is_new_proxy_conn = self.proxy is not None and not getattr(conn, 'sock', None)
if is_new_proxy_conn:
self._prepare_proxy(conn)
# Make the request on the httplib connection object. # Make the request on the httplib connection object.
httplib_response = self._make_request(conn, method, url, httplib_response = self._make_request(conn, method, url,
timeout=timeout, timeout=timeout_obj,
body=body, headers=headers) body=body, headers=headers)
# If we're going to release the connection in ``finally:``, then # If we're going to release the connection in ``finally:``, then
@ -547,6 +573,14 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
conn = None conn = None
raise SSLError(e) raise SSLError(e)
except SSLError:
# Treat SSLError separately from BaseSSLError to preserve
# traceback.
if conn:
conn.close()
conn = None
raise
except (TimeoutError, HTTPException, SocketError, ConnectionError) as e: except (TimeoutError, HTTPException, SocketError, ConnectionError) as e:
if conn: if conn:
# Discard the connection for these exceptions. It will be # Discard the connection for these exceptions. It will be
@ -554,14 +588,13 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
conn.close() conn.close()
conn = None conn = None
stacktrace = sys.exc_info()[2]
if isinstance(e, SocketError) and self.proxy: if isinstance(e, SocketError) and self.proxy:
e = ProxyError('Cannot connect to proxy.', e) e = ProxyError('Cannot connect to proxy.', e)
elif isinstance(e, (SocketError, HTTPException)): elif isinstance(e, (SocketError, HTTPException)):
e = ProtocolError('Connection aborted.', e) e = ProtocolError('Connection aborted.', e)
retries = retries.increment(method, url, error=e, retries = retries.increment(method, url, error=e, _pool=self,
_pool=self, _stacktrace=stacktrace) _stacktrace=sys.exc_info()[2])
retries.sleep() retries.sleep()
# Keep track of the error for the retry warning. # Keep track of the error for the retry warning.
@ -673,7 +706,13 @@ class HTTPSConnectionPool(HTTPConnectionPool):
assert_fingerprint=self.assert_fingerprint) assert_fingerprint=self.assert_fingerprint)
conn.ssl_version = self.ssl_version conn.ssl_version = self.ssl_version
if self.proxy is not None: return conn
def _prepare_proxy(self, conn):
"""
Establish tunnel connection early, because otherwise httplib
would improperly set Host: header to proxy's IP:port.
"""
# Python 2.7+ # Python 2.7+
try: try:
set_tunnel = conn.set_tunnel set_tunnel = conn.set_tunnel
@ -685,12 +724,8 @@ class HTTPSConnectionPool(HTTPConnectionPool):
else: else:
set_tunnel(self.host, self.port, self.proxy_headers) set_tunnel(self.host, self.port, self.proxy_headers)
# Establish tunnel connection early, because otherwise httplib
# would improperly set Host: header to proxy's IP:port.
conn.connect() conn.connect()
return conn
def _new_conn(self): def _new_conn(self):
""" """
Return a fresh :class:`httplib.HTTPSConnection`. Return a fresh :class:`httplib.HTTPSConnection`.

5
libs/requests/packages/urllib3/contrib/pyopenssl.py

@ -191,6 +191,11 @@ class WrappedSocket(object):
return b'' return b''
else: else:
raise raise
except OpenSSL.SSL.ZeroReturnError as e:
if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
return b''
else:
raise
except OpenSSL.SSL.WantReadError: except OpenSSL.SSL.WantReadError:
rd, wd, ed = select.select( rd, wd, ed = select.select(
[self.socket], [], [], self.socket.gettimeout()) [self.socket], [], [], self.socket.gettimeout())

5
libs/requests/packages/urllib3/exceptions.py

@ -157,3 +157,8 @@ class InsecureRequestWarning(SecurityWarning):
class SystemTimeWarning(SecurityWarning): class SystemTimeWarning(SecurityWarning):
"Warned when system time is suspected to be wrong" "Warned when system time is suspected to be wrong"
pass pass
class InsecurePlatformWarning(SecurityWarning):
"Warned when certain SSL configuration is not available on a platform."
pass

19
libs/requests/packages/urllib3/poolmanager.py

@ -8,7 +8,7 @@ except ImportError:
from ._collections import RecentlyUsedContainer from ._collections import RecentlyUsedContainer
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool
from .connectionpool import port_by_scheme from .connectionpool import port_by_scheme
from .exceptions import LocationValueError from .exceptions import LocationValueError, MaxRetryError
from .request import RequestMethods from .request import RequestMethods
from .util.url import parse_url from .util.url import parse_url
from .util.retry import Retry from .util.retry import Retry
@ -64,6 +64,14 @@ class PoolManager(RequestMethods):
self.pools = RecentlyUsedContainer(num_pools, self.pools = RecentlyUsedContainer(num_pools,
dispose_func=lambda p: p.close()) dispose_func=lambda p: p.close())
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.clear()
# Return False to re-raise any potential exceptions
return False
def _new_pool(self, scheme, host, port): def _new_pool(self, scheme, host, port):
""" """
Create a new :class:`ConnectionPool` based on host, port and scheme. Create a new :class:`ConnectionPool` based on host, port and scheme.
@ -167,7 +175,14 @@ class PoolManager(RequestMethods):
if not isinstance(retries, Retry): if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect) retries = Retry.from_int(retries, redirect=redirect)
kw['retries'] = retries.increment(method, redirect_location) try:
retries = retries.increment(method, url, response=response, _pool=conn)
except MaxRetryError:
if retries.raise_on_redirect:
raise
return response
kw['retries'] = retries
kw['redirect'] = redirect kw['redirect'] = redirect
log.info("Redirecting %s -> %s" % (url, redirect_location)) log.info("Redirecting %s -> %s" % (url, redirect_location))

44
libs/requests/packages/urllib3/response.py

@ -4,12 +4,11 @@ from socket import timeout as SocketTimeout
from ._collections import HTTPHeaderDict from ._collections import HTTPHeaderDict
from .exceptions import ProtocolError, DecodeError, ReadTimeoutError from .exceptions import ProtocolError, DecodeError, ReadTimeoutError
from .packages.six import string_types as basestring, binary_type from .packages.six import string_types as basestring, binary_type, PY3
from .connection import HTTPException, BaseSSLError from .connection import HTTPException, BaseSSLError
from .util.response import is_fp_closed from .util.response import is_fp_closed
class DeflateDecoder(object): class DeflateDecoder(object):
def __init__(self): def __init__(self):
@ -21,6 +20,9 @@ class DeflateDecoder(object):
return getattr(self._obj, name) return getattr(self._obj, name)
def decompress(self, data): def decompress(self, data):
if not data:
return data
if not self._first_try: if not self._first_try:
return self._obj.decompress(data) return self._obj.decompress(data)
@ -36,9 +38,23 @@ class DeflateDecoder(object):
self._data = None self._data = None
class GzipDecoder(object):
def __init__(self):
self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)
def __getattr__(self, name):
return getattr(self._obj, name)
def decompress(self, data):
if not data:
return data
return self._obj.decompress(data)
def _get_decoder(mode): def _get_decoder(mode):
if mode == 'gzip': if mode == 'gzip':
return zlib.decompressobj(16 + zlib.MAX_WBITS) return GzipDecoder()
return DeflateDecoder() return DeflateDecoder()
@ -76,9 +92,10 @@ class HTTPResponse(io.IOBase):
strict=0, preload_content=True, decode_content=True, strict=0, preload_content=True, decode_content=True,
original_response=None, pool=None, connection=None): original_response=None, pool=None, connection=None):
self.headers = HTTPHeaderDict() if isinstance(headers, HTTPHeaderDict):
if headers: self.headers = headers
self.headers.update(headers) else:
self.headers = HTTPHeaderDict(headers)
self.status = status self.status = status
self.version = version self.version = version
self.reason = reason self.reason = reason
@ -202,7 +219,7 @@ class HTTPResponse(io.IOBase):
except BaseSSLError as e: except BaseSSLError as e:
# FIXME: Is there a better way to differentiate between SSLErrors? # FIXME: Is there a better way to differentiate between SSLErrors?
if not 'read operation timed out' in str(e): # Defensive: if 'read operation timed out' not in str(e): # Defensive:
# This shouldn't happen but just in case we're missing an edge # This shouldn't happen but just in case we're missing an edge
# case, let's avoid swallowing SSL errors. # case, let's avoid swallowing SSL errors.
raise raise
@ -267,14 +284,16 @@ class HTTPResponse(io.IOBase):
Remaining parameters are passed to the HTTPResponse constructor, along Remaining parameters are passed to the HTTPResponse constructor, along
with ``original_response=r``. with ``original_response=r``.
""" """
headers = r.msg
headers = HTTPHeaderDict() if not isinstance(headers, HTTPHeaderDict):
for k, v in r.getheaders(): if PY3: # Python 3
headers.add(k, v) headers = HTTPHeaderDict(headers.items())
else: # Python 2
headers = HTTPHeaderDict.from_httplib(headers)
# HTTPResponse objects in Python 3 don't have a .strict attribute # HTTPResponse objects in Python 3 don't have a .strict attribute
strict = getattr(r, 'strict', 0) strict = getattr(r, 'strict', 0)
return ResponseCls(body=r, resp = ResponseCls(body=r,
headers=headers, headers=headers,
status=r.status, status=r.status,
version=r.version, version=r.version,
@ -282,6 +301,7 @@ class HTTPResponse(io.IOBase):
strict=strict, strict=strict,
original_response=r, original_response=r,
**response_kw) **response_kw)
return resp
# Backwards-compatibility methods for httplib.HTTPResponse # Backwards-compatibility methods for httplib.HTTPResponse
def getheaders(self): def getheaders(self):

1
libs/requests/packages/urllib3/util/connection.py

@ -82,6 +82,7 @@ def create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
err = _ err = _
if sock is not None: if sock is not None:
sock.close() sock.close()
sock = None
if err is not None: if err is not None:
raise err raise err

2
libs/requests/packages/urllib3/util/retry.py

@ -190,7 +190,7 @@ class Retry(object):
return isinstance(err, (ReadTimeoutError, ProtocolError)) return isinstance(err, (ReadTimeoutError, ProtocolError))
def is_forced_retry(self, method, status_code): def is_forced_retry(self, method, status_code):
""" Is this method/response retryable? (Based on method/codes whitelists) """ Is this method/status code retryable? (Based on method/codes whitelists)
""" """
if self.method_whitelist and method.upper() not in self.method_whitelist: if self.method_whitelist and method.upper() not in self.method_whitelist:
return False return False

24
libs/requests/packages/urllib3/util/ssl_.py

@ -1,7 +1,7 @@
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from hashlib import md5, sha1 from hashlib import md5, sha1, sha256
from ..exceptions import SSLError from ..exceptions import SSLError, InsecurePlatformWarning
SSLContext = None SSLContext = None
@ -10,6 +10,7 @@ create_default_context = None
import errno import errno
import ssl import ssl
import warnings
try: # Test for SSL features try: # Test for SSL features
from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23 from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23
@ -29,8 +30,8 @@ try:
except ImportError: except ImportError:
_DEFAULT_CIPHERS = ( _DEFAULT_CIPHERS = (
'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:'
'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:ECDH+RC4:' 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:'
'DH+RC4:RSA+RC4:!aNULL:!eNULL:!MD5' '!eNULL:!MD5'
) )
try: try:
@ -69,6 +70,14 @@ except ImportError:
self.ciphers = cipher_suite self.ciphers = cipher_suite
def wrap_socket(self, socket, server_hostname=None): def wrap_socket(self, socket, server_hostname=None):
warnings.warn(
'A true SSLContext object is not available. This prevents '
'urllib3 from configuring SSL appropriately and may cause '
'certain SSL connections to fail. For more information, see '
'https://urllib3.readthedocs.org/en/latest/security.html'
'#insecureplatformwarning.',
InsecurePlatformWarning
)
kwargs = { kwargs = {
'keyfile': self.keyfile, 'keyfile': self.keyfile,
'certfile': self.certfile, 'certfile': self.certfile,
@ -96,7 +105,8 @@ def assert_fingerprint(cert, fingerprint):
# this digest. # this digest.
hashfunc_map = { hashfunc_map = {
16: md5, 16: md5,
20: sha1 20: sha1,
32: sha256,
} }
fingerprint = fingerprint.replace(':', '').lower() fingerprint = fingerprint.replace(':', '').lower()
@ -211,7 +221,9 @@ def create_urllib3_context(ssl_version=None, cert_reqs=ssl.CERT_REQUIRED,
context.verify_mode = cert_reqs context.verify_mode = cert_reqs
if getattr(context, 'check_hostname', None) is not None: # Platform-specific: Python 3.2 if getattr(context, 'check_hostname', None) is not None: # Platform-specific: Python 3.2
context.check_hostname = (context.verify_mode == ssl.CERT_REQUIRED) # We do our own verification, including fingerprints and alternative
# hostnames. So disable it here
context.check_hostname = False
return context return context

5
libs/requests/sessions.py

@ -171,7 +171,10 @@ class SessionRedirectMixin(object):
except KeyError: except KeyError:
pass pass
extract_cookies_to_jar(prepared_request._cookies, prepared_request, resp.raw) # Extract any cookies sent on the response to the cookiejar
# in the new request. Because we've mutated our copied prepared
# request, use the old one that we haven't yet touched.
extract_cookies_to_jar(prepared_request._cookies, req, resp.raw)
prepared_request._cookies.update(self.cookies) prepared_request._cookies.update(self.cookies)
prepared_request.prepare_cookies(prepared_request._cookies) prepared_request.prepare_cookies(prepared_request._cookies)

20
libs/requests/utils.py

@ -25,7 +25,8 @@ from . import __version__
from . import certs from . import certs
from .compat import parse_http_list as _parse_list_header from .compat import parse_http_list as _parse_list_header
from .compat import (quote, urlparse, bytes, str, OrderedDict, unquote, is_py2, from .compat import (quote, urlparse, bytes, str, OrderedDict, unquote, is_py2,
builtin_str, getproxies, proxy_bypass, urlunparse) builtin_str, getproxies, proxy_bypass, urlunparse,
basestring)
from .cookies import RequestsCookieJar, cookiejar_from_dict from .cookies import RequestsCookieJar, cookiejar_from_dict
from .structures import CaseInsensitiveDict from .structures import CaseInsensitiveDict
from .exceptions import InvalidURL from .exceptions import InvalidURL
@ -115,7 +116,8 @@ def get_netrc_auth(url):
def guess_filename(obj): def guess_filename(obj):
"""Tries to guess the filename of the given object.""" """Tries to guess the filename of the given object."""
name = getattr(obj, 'name', None) name = getattr(obj, 'name', None)
if name and isinstance(name, builtin_str) and name[0] != '<' and name[-1] != '>': if (name and isinstance(name, basestring) and name[0] != '<' and
name[-1] != '>'):
return os.path.basename(name) return os.path.basename(name)
@ -418,10 +420,18 @@ def requote_uri(uri):
This function passes the given URI through an unquote/quote cycle to This function passes the given URI through an unquote/quote cycle to
ensure that it is fully and consistently quoted. ensure that it is fully and consistently quoted.
""" """
safe_with_percent = "!#$%&'()*+,/:;=?@[]~"
safe_without_percent = "!#$&'()*+,/:;=?@[]~"
try:
# Unquote only the unreserved characters # Unquote only the unreserved characters
# Then quote only illegal characters (do not quote reserved, unreserved, # Then quote only illegal characters (do not quote reserved,
# or '%') # unreserved, or '%')
return quote(unquote_unreserved(uri), safe="!#$%&'()*+,/:;=?@[]~") return quote(unquote_unreserved(uri), safe=safe_with_percent)
except InvalidURL:
# We couldn't unquote the given URI, so let's try quoting it, but
# there may be unquoted '%'s in the URI. We need to make sure they're
# properly quoted so they do not cause issues elsewhere.
return quote(uri, safe=safe_without_percent)
def address_in_network(ip, net): def address_in_network(ip, net):

Loading…
Cancel
Save