Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3d7cf3f27 | ||
|
|
3c5ecfc9f5 | ||
|
|
d528106876 | ||
|
|
cbc7c2d1c9 | ||
|
|
e36083b89c | ||
|
|
308343508b | ||
|
|
ba21d14976 | ||
|
|
cee8fae65e | ||
|
|
1c2022cf86 | ||
|
|
8480cf937a | ||
|
|
f6952a9b8d | ||
|
|
d758f0cf97 | ||
|
|
c31a450c55 | ||
|
|
0a2dc74ecb | ||
|
|
f78a57936b | ||
|
|
218978601f | ||
|
|
cb9620780f | ||
|
|
963c78853f | ||
|
|
b670b61d54 | ||
|
|
9ec2005d9f | ||
|
|
f4ddf00c36 | ||
|
|
248f122970 | ||
|
|
be8ce365ab | ||
|
|
3393dc8221 | ||
|
|
7c67c4adf9 | ||
|
|
2a4dd64fb4 | ||
|
|
9e0fb37fff | ||
|
|
4f49f6b3ed | ||
|
|
8b3f20ca91 | ||
|
|
fdf426125b | ||
|
|
d6b57c6fb2 | ||
|
|
39b121d791 | ||
|
|
12c7456789 | ||
|
|
2629c0906e | ||
|
|
205755834d | ||
|
|
e2f5a135c3 | ||
|
|
8de858f0de | ||
|
|
667896c557 | ||
|
|
2b6f1e6236 | ||
|
|
b77c1a3deb | ||
|
|
9e8d403a21 | ||
|
|
6cc891fd32 | ||
|
|
49c44a0c08 | ||
|
|
c6e18b04e3 | ||
|
|
c10b8384e4 | ||
|
|
8d1228cd19 | ||
|
|
8e227aeb89 | ||
|
|
d8c2fdf92f | ||
|
|
cada19b300 | ||
|
|
c6a80640d1 | ||
|
|
649efc8c9b | ||
|
|
14176d1d63 | ||
|
|
1ea4e21958 | ||
|
|
51feabbc27 | ||
|
|
f6e07bb27f | ||
|
|
c054a722bb | ||
|
|
bbeb1c32d2 | ||
|
|
1263b8660d | ||
|
|
2fde9ee407 |
@@ -3,7 +3,6 @@ language: python
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
|
||||
@@ -10,13 +10,6 @@ Keepers of the Four Crystals
|
||||
- Nate Prewitt <nate.prewitt@gmail.com> `@nateprewitt <https://github.com/nateprewitt>`_
|
||||
|
||||
|
||||
|
||||
Urllib3
|
||||
```````
|
||||
|
||||
- Andrey Petrov <andrey.petrov@shazow.net>
|
||||
|
||||
|
||||
Patches and Suggestions
|
||||
```````````````````````
|
||||
|
||||
|
||||
35
HISTORY.rst
35
HISTORY.rst
@@ -3,6 +3,41 @@
|
||||
Release History
|
||||
---------------
|
||||
|
||||
2.18.4 (2017-08-15)
|
||||
+++++++++++++++++++
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Error messages for invalid headers now include the header name for easier debugging
|
||||
|
||||
**Dependencies**
|
||||
|
||||
- We now support idna v2.6.
|
||||
|
||||
2.18.3 (2017-08-02)
|
||||
+++++++++++++++++++
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Running ``$ python -m requests.help`` now includes the installed version of idna.
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- Fixed issue where Requests would raise ``ConnectionError`` instead of
|
||||
``SSLError`` when encountering SSL problems when using urllib3 v1.22.
|
||||
|
||||
2.18.2 (2017-07-25)
|
||||
+++++++++++++++++++
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- ``requests.help`` no longer fails on Python 2.6 due to the absence of
|
||||
``ssl.OPENSSL_VERSION_NUMBER``.
|
||||
|
||||
**Dependencies**
|
||||
|
||||
- We now support urllib3 v1.22.
|
||||
|
||||
2.18.1 (2017-06-14)
|
||||
+++++++++++++++++++
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
include README.rst LICENSE NOTICE HISTORY.rst pytest.ini
|
||||
include README.rst LICENSE NOTICE HISTORY.rst pytest.ini requirements.txt
|
||||
recursive-include tests *.py
|
||||
|
||||
@@ -93,7 +93,7 @@ To install Requests, simply:
|
||||
$ pip install requests
|
||||
✨🍰✨
|
||||
|
||||
Satisfaction, guaranteed.
|
||||
Satisfaction guaranteed.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
@@ -10,11 +10,6 @@ environment:
|
||||
PYTHON_ARCH: "64"
|
||||
TOXENV: "py27"
|
||||
|
||||
- PYTHON: "C:\\Python33-x64"
|
||||
PYTHON_VERSION: "3.3.x"
|
||||
PYTHON_ARCH: "64"
|
||||
TOXENV: "py33"
|
||||
|
||||
- PYTHON: "C:\\Python34-x64"
|
||||
PYTHON_VERSION: "3.4.x"
|
||||
PYTHON_ARCH: "64"
|
||||
|
||||
3
docs/_templates/sidebarintro.html
vendored
3
docs/_templates/sidebarintro.html
vendored
@@ -14,11 +14,8 @@
|
||||
human beings.
|
||||
</p>
|
||||
|
||||
|
||||
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=pythonrequestsorg" id="_carbonads_js"></script>
|
||||
|
||||
|
||||
|
||||
<h3>Stay Informed</h3>
|
||||
<p>Receive updates on new releases and upcoming projects.</p>
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ supported:
|
||||
|
||||
* Python 2.6
|
||||
* Python 2.7
|
||||
* Python 3.3
|
||||
* Python 3.4
|
||||
* Python 3.5
|
||||
* Python 3.6
|
||||
|
||||
@@ -51,7 +51,6 @@ Requests currently supports the following versions of Python:
|
||||
|
||||
- Python 2.6
|
||||
- Python 2.7
|
||||
- Python 3.3
|
||||
- Python 3.4
|
||||
- Python 3.5
|
||||
- Python 3.6
|
||||
|
||||
@@ -36,6 +36,7 @@ constantly reading documentation, depression, headaches, or even death.*
|
||||
|
||||
**Behold, the power of Requests**::
|
||||
|
||||
>>> import requests
|
||||
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
|
||||
>>> r.status_code
|
||||
200
|
||||
@@ -104,7 +105,7 @@ Requests is ready for today's web.
|
||||
- Chunked Requests
|
||||
- ``.netrc`` Support
|
||||
|
||||
Requests officially supports Python 2.6–2.7 & 3.3–3.7, and runs great on PyPy.
|
||||
Requests officially supports Python 2.6–2.7 & 3.4–3.7, and runs great on PyPy.
|
||||
|
||||
|
||||
The User Guide
|
||||
|
||||
@@ -593,6 +593,8 @@ as using a HTTP one::
|
||||
'https': 'socks5://user:pass@host:port'
|
||||
}
|
||||
|
||||
Using the scheme ``socks5`` causes the DNS resolution to happen on the client, rather than on the proxy server. This is in line with curl, which uses the scheme to decide whether to do the DNS resolution on the client or proxy. If you want to resolve the domains on the proxy server, use ``socks5h`` as the scheme.
|
||||
|
||||
.. _compliance:
|
||||
|
||||
Compliance
|
||||
|
||||
@@ -57,7 +57,7 @@ def check_compatibility(urllib3_version, chardet_version):
|
||||
# Check urllib3 for compatibility.
|
||||
major, minor, patch = urllib3_version # noqa: F811
|
||||
major, minor, patch = int(major), int(minor), int(patch)
|
||||
# urllib3 >= 1.21.1, < 1.22
|
||||
# urllib3 >= 1.21.1, <= 1.22
|
||||
assert major == 1
|
||||
assert minor >= 21
|
||||
assert minor <= 22
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
__title__ = 'requests'
|
||||
__description__ = 'Python HTTP for Humans.'
|
||||
__url__ = 'http://python-requests.org'
|
||||
__version__ = '2.18.1'
|
||||
__build__ = 0x021801
|
||||
__version__ = '2.18.4'
|
||||
__build__ = 0x021804
|
||||
__author__ = 'Kenneth Reitz'
|
||||
__author_email__ = 'me@kennethreitz.org'
|
||||
__license__ = 'Apache 2.0'
|
||||
|
||||
@@ -501,6 +501,10 @@ class HTTPAdapter(BaseAdapter):
|
||||
if isinstance(e.reason, _ProxyError):
|
||||
raise ProxyError(e, request=request)
|
||||
|
||||
if isinstance(e.reason, _SSLError):
|
||||
# This branch is for urllib3 v1.22 and later.
|
||||
raise SSLError(e, request=request)
|
||||
|
||||
raise ConnectionError(e, request=request)
|
||||
|
||||
except ClosedPoolError as e:
|
||||
@@ -511,6 +515,7 @@ class HTTPAdapter(BaseAdapter):
|
||||
|
||||
except (_SSLError, _HTTPError) as e:
|
||||
if isinstance(e, _SSLError):
|
||||
# This branch is for urllib3 versions earlier than v1.22
|
||||
raise SSLError(e, request=request)
|
||||
elif isinstance(e, ReadTimeoutError):
|
||||
raise ReadTimeout(e, request=request)
|
||||
|
||||
@@ -27,9 +27,7 @@ is_py3 = (_ver[0] == 3)
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except (ImportError, SyntaxError):
|
||||
# simplejson does not support Python 3.2, it throws a SyntaxError
|
||||
# because of u'...' Unicode literals.
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
# ---------
|
||||
|
||||
@@ -6,6 +6,7 @@ import platform
|
||||
import sys
|
||||
import ssl
|
||||
|
||||
import idna
|
||||
import urllib3
|
||||
import chardet
|
||||
|
||||
@@ -84,18 +85,26 @@ def info():
|
||||
cryptography_info = {
|
||||
'version': getattr(cryptography, '__version__', ''),
|
||||
}
|
||||
idna_info = {
|
||||
'version': getattr(idna, '__version__', ''),
|
||||
}
|
||||
|
||||
# OPENSSL_VERSION_NUMBER doesn't exist in the Python 2.6 ssl module.
|
||||
system_ssl = getattr(ssl, 'OPENSSL_VERSION_NUMBER', None)
|
||||
system_ssl_info = {
|
||||
'version': '%x' % system_ssl if system_ssl is not None else ''
|
||||
}
|
||||
|
||||
return {
|
||||
'platform': platform_info,
|
||||
'implementation': implementation_info,
|
||||
'system_ssl': {
|
||||
'version': '%x' % ssl.OPENSSL_VERSION_NUMBER,
|
||||
},
|
||||
'system_ssl': system_ssl_info,
|
||||
'using_pyopenssl': pyopenssl is not None,
|
||||
'pyOpenSSL': pyopenssl_info,
|
||||
'urllib3': urllib3_info,
|
||||
'chardet': chardet_info,
|
||||
'cryptography': cryptography_info,
|
||||
'idna': idna_info,
|
||||
'requests': {
|
||||
'version': requests_version,
|
||||
},
|
||||
|
||||
@@ -586,8 +586,6 @@ class Response(object):
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
super(Response, self).__init__()
|
||||
|
||||
self._content = False
|
||||
self._content_consumed = False
|
||||
self._next = None
|
||||
|
||||
@@ -97,6 +97,12 @@ class SessionRedirectMixin(object):
|
||||
|
||||
def get_redirect_target(self, resp):
|
||||
"""Receives a Response. Returns a redirect URI or ``None``"""
|
||||
# Due to the nature of how requests processes redirects this method will
|
||||
# be called at least once upon the original response and at least twice
|
||||
# on each subsequent redirect response (if any).
|
||||
# If a custom mixin is used to handle this logic, it may be advantageous
|
||||
# to cache the redirect location onto the response object as a private
|
||||
# attribute.
|
||||
if resp.is_redirect:
|
||||
location = resp.headers['location']
|
||||
# Currently the underlying http module on py3 decode headers
|
||||
@@ -704,7 +710,7 @@ class Session(SessionRedirectMixin):
|
||||
def mount(self, prefix, adapter):
|
||||
"""Registers a connection adapter to a prefix.
|
||||
|
||||
Adapters are sorted in descending order by key length.
|
||||
Adapters are sorted in descending order by prefix length.
|
||||
"""
|
||||
self.adapters[prefix] = adapter
|
||||
keys_to_move = [k for k in self.adapters if len(k) < len(prefix)]
|
||||
|
||||
@@ -868,8 +868,8 @@ def check_header_validity(header):
|
||||
if not pat.match(value):
|
||||
raise InvalidHeader("Invalid return character or leading space in header: %s" % name)
|
||||
except TypeError:
|
||||
raise InvalidHeader("Header value %s must be of type str or bytes, "
|
||||
"not %s" % (value, type(value)))
|
||||
raise InvalidHeader("Value for header {%s: %s} must be of type str or "
|
||||
"bytes, not %s" % (name, value, type(value)))
|
||||
|
||||
|
||||
def urldefragauth(url):
|
||||
|
||||
5
setup.py
5
setup.py
@@ -43,8 +43,8 @@ packages = ['requests']
|
||||
|
||||
requires = [
|
||||
'chardet>=3.0.2,<3.1.0',
|
||||
'idna>=2.5,<2.6',
|
||||
'urllib3>=1.21.1,<1.22',
|
||||
'idna>=2.5,<2.7',
|
||||
'urllib3>=1.21.1,<1.23',
|
||||
'certifi>=2017.4.17'
|
||||
|
||||
]
|
||||
@@ -83,7 +83,6 @@ setup(
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
|
||||
40
tests/test_help.py
Normal file
40
tests/test_help.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# -*- encoding: utf-8
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from requests.help import info
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info[:2] != (2,6), reason="Only run on Python 2.6")
|
||||
def test_system_ssl_py26():
|
||||
"""OPENSSL_VERSION_NUMBER isn't provided in Python 2.6, verify we don't
|
||||
blow up in this case.
|
||||
"""
|
||||
assert info()['system_ssl'] == {'version': ''}
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (2,7), reason="Only run on Python 2.7+")
|
||||
def test_system_ssl():
|
||||
"""Verify we're actually setting system_ssl when it should be available."""
|
||||
assert info()['system_ssl']['version'] != ''
|
||||
|
||||
|
||||
class VersionedPackage(object):
|
||||
def __init__(self, version):
|
||||
self.__version__ = version
|
||||
|
||||
|
||||
def test_idna_without_version_attribute(mocker):
|
||||
"""Older versions of IDNA don't provide a __version__ attribute, verify
|
||||
that if we have such a package, we don't blow up.
|
||||
"""
|
||||
mocker.patch('requests.help.idna', new=None)
|
||||
assert info()['idna'] == {'version': ''}
|
||||
|
||||
|
||||
def test_idna_with_version_attribute(mocker):
|
||||
"""Verify we're actually setting idna version when it should be available."""
|
||||
mocker.patch('requests.help.idna', new=VersionedPackage('2.6'))
|
||||
assert info()['idna'] == {'version': '2.6'}
|
||||
@@ -23,7 +23,7 @@ from requests.cookies import (
|
||||
from requests.exceptions import (
|
||||
ConnectionError, ConnectTimeout, InvalidSchema, InvalidURL,
|
||||
MissingSchema, ReadTimeout, Timeout, RetryError, TooManyRedirects,
|
||||
ProxyError, InvalidHeader, UnrewindableBodyError)
|
||||
ProxyError, InvalidHeader, UnrewindableBodyError, SSLError)
|
||||
from requests.models import PreparedRequest
|
||||
from requests.structures import CaseInsensitiveDict
|
||||
from requests.sessions import SessionRedirectMixin
|
||||
@@ -812,6 +812,15 @@ class TestRequests:
|
||||
item.category.__name__ for item in warning_records)
|
||||
assert warnings_category == warnings_expected
|
||||
|
||||
def test_certificate_failure(self, httpbin_secure):
|
||||
"""
|
||||
When underlying SSL problems occur, an SSLError is raised.
|
||||
"""
|
||||
with pytest.raises(SSLError):
|
||||
# Our local httpbin does not have a trusted CA, so this call will
|
||||
# fail if we use our default trust bundle.
|
||||
requests.get(httpbin_secure('status', '200'))
|
||||
|
||||
def test_urlencoded_get_query_multivalued_param(self, httpbin):
|
||||
|
||||
r = requests.get(httpbin('get'), params=dict(test=['foo', 'baz']))
|
||||
@@ -1392,14 +1401,17 @@ class TestRequests:
|
||||
headers_list = {'baz': ['foo', 'bar']}
|
||||
|
||||
# Test for int
|
||||
with pytest.raises(InvalidHeader):
|
||||
with pytest.raises(InvalidHeader) as excinfo:
|
||||
r = requests.get(httpbin('get'), headers=headers_int)
|
||||
assert 'foo' in str(excinfo.value)
|
||||
# Test for dict
|
||||
with pytest.raises(InvalidHeader):
|
||||
with pytest.raises(InvalidHeader) as excinfo:
|
||||
r = requests.get(httpbin('get'), headers=headers_dict)
|
||||
assert 'bar' in str(excinfo.value)
|
||||
# Test for list
|
||||
with pytest.raises(InvalidHeader):
|
||||
with pytest.raises(InvalidHeader) as excinfo:
|
||||
r = requests.get(httpbin('get'), headers=headers_list)
|
||||
assert 'baz' in str(excinfo.value)
|
||||
|
||||
def test_header_no_return_chars(self, httpbin):
|
||||
"""Ensure that a header containing return character sequences raise an
|
||||
|
||||
Reference in New Issue
Block a user