Compare commits

...

192 Commits
3.0 ... v2.19.1

Author SHA1 Message Date
Nate Prewitt
883caaf145 v2.19.1 2018-06-14 06:26:27 -07:00
Ian Stapleton Cordasco
2530323faf Merge pull request #4683 from martindurant/docstrings_for_optimize
Do not alter status_codes docstring if it is None
2018-06-13 10:24:45 -05:00
Martin Durant
8031ec76b8 Do not alter status_codes docstring if it is None
With PYTHONOPTIMIZE=2, the current code breaks with TypeError.
2018-06-12 17:52:50 -04:00
Nate Prewitt
991e8b76b7 v2.19.0
* Updated HISTORY.rst.
* Moved version pin for idna to allow recent 2.7 release.
* Updated version warning for urllib3 to allow 1.23.
* Updated metadata dunders in __version__.py.
* Removed Python 2.6 trove classifier.
* Removed Python 2.6 reference from README.rst.
2018-06-12 07:38:10 -07:00
Raymond Hettinger
7e297ed95b Separate collections from collections.abc 2018-06-11 22:14:59 -07:00
Laurent Bachelier
10915e3b0d Add a public method to get the cookie policy 2018-06-11 22:13:07 -07:00
Laurent Bachelier
ace0c200f4 Add cookie policy related tests 2018-06-11 22:13:07 -07:00
Laurent Bachelier
3ef49272f2 Copy cookie policy when copying a CookieJar
Without it, the cookie policy would get lost while making a request.
That would be invisible to the user if the default cookie policy wasn't
changed, of course.
2018-06-11 22:13:07 -07:00
Nate Prewitt
d1aeb7ea8c Merge pull request #4672 from requests/remove_2.6_refs
remove references to 2.6 support in documentation
2018-06-11 07:13:13 -07:00
Nate Prewitt
de64f0f23f port pyopenssl fix from urllib3 2018-06-10 14:49:13 -07:00
Nate Prewitt
bc46de58e6 remove references to 2.6 support in documentation 2018-06-10 14:48:59 -07:00
Nate Prewitt
16fd7e03a9 Merge pull request #4676 from jdufresne/doc-py3
Update Python 2 doc links to Python 3
2018-06-10 08:37:08 -07:00
Jon Dufresne
35a1874912 Update Python 2 doc links to Python 3
The Python 3 docs are better maintained and are the future of Python
development.
2018-06-09 20:29:41 -07:00
Nate Prewitt
d98f881118 Merge pull request #4669 from michael-k/patch-1
Allow urllib3 1.23
2018-06-05 06:35:08 -07:00
Michael
ac944b7439 Allow urllib3 1.23
https://github.com/urllib3/urllib3/blob/1.23/CHANGES.rst#123-2018-06-04
2018-06-05 12:06:03 +00:00
Ian Stapleton Cordasco
00fd4c8eb4 Merge pull request #4661 from ofek/patch-2
Response.content minor perf improvement
2018-05-26 19:00:25 -05:00
Ofek Lev
c1b828bc95 Response.content minor perf improvement 2018-05-26 18:20:27 -04:00
Nate Prewitt
fe8290b3d0 updating HISTORY.rst 2018-05-17 13:56:17 -07:00
Rajiv Mayani
8546a15587 The library raises NoneType error when file-pointer (fp) resolves to None.
>>> from requests import post
>>> r = post("https://example.com", files={"file-name": None})

However, when a param value or json field is None they are not included in the request body.

>>> from requests import get
>>> r = get("https://example.com", params={"file-name": None})
>>> r.request.url

This commit makes the beahviour consistent for files.
2018-05-17 13:56:17 -07:00
Ian Stapleton Cordasco
5f09f0ca7e Merge pull request #4631 from pradyunsg/patch-1
Add long_description_content_type to setup.py
2018-05-17 09:34:06 -05:00
Ian Stapleton Cordasco
8bffd3da5f Merge branch 'master' into patch-1 2018-05-17 09:12:26 -05:00
Nate Prewitt
9b5071cdb6 Merge pull request #4648 from requests/update_lock_file
bring Pipfile.lock up to date with current constraints
2018-05-16 12:31:48 -07:00
Nate Prewitt
c6db87978f bring Pipfile.lock up to date with current constraints 2018-05-16 07:39:43 -07:00
Nate Prewitt
f3fc892b90 bring HISTORY.rst up to date with recent changes 2018-05-16 07:35:44 -07:00
Ian Stapleton Cordasco
161acb6a50 Merge pull request #4410 from linuxlizard/master
Add SHA-256 and SHA-512 digest auth algorithms
2018-05-16 09:06:57 -05:00
Ian Stapleton Cordasco
371ee7cbec Merge branch 'master' into master 2018-05-16 08:46:26 -05:00
Ian Stapleton Cordasco
80e2637a83 Merge pull request #4647 from requests/appveyor_test
fix appveyor
2018-05-16 08:14:37 -05:00
Nate Prewitt
9055b33f6f install Requests separately on appveyor to fix builds 2018-05-15 23:06:43 -07:00
Nate Prewitt
9616f82905 Merge pull request #4625 from nicktimko/patch-1
Certifi.io broken
2018-05-14 09:22:10 -07:00
Nick Timkovich
919c168cdb Certifi.io broken
http://certifi.io/ -> https://certifiio.readthedocs.io/
2018-05-14 09:55:33 -05:00
Kenneth Reitz
adceafd79d Update issue templates 2018-05-13 16:51:44 -04:00
Kenneth Reitz
e02effb774 Merge pull request #4632 from mingrammer/update-license
Update license copyright to 2018
2018-05-13 13:30:57 -04:00
Julien Prigent
60a5a393d8 Add a comment about lowercase env. variables precedence over uppercase 2018-05-13 06:15:56 -07:00
Kenneth Reitz
9e1d8edcb7 Merge branch 'master' into update-license 2018-05-12 17:10:24 -04:00
Ian Stapleton Cordasco
1e8a3142d2 Merge pull request #4634 from vshih/patch-1
Spelling.
2018-05-08 06:12:32 -05:00
Victor Shih
71e402fe40 Spelling. 2018-05-07 10:51:53 -07:00
Pradyun Gedam
048c926b46 README is in ReST 2018-05-07 00:23:38 +05:30
mingrammer
41c455182b Update license copyright to 2018 2018-05-05 09:57:14 +09:00
Pradyun Gedam
5f306dbe99 Add long_description_content_type to setup.py
See:
- https://packaging.python.org/guides/making-a-pypi-friendly-readme/
- https://pypi.org/p/requests/
2018-05-04 16:43:25 +05:30
Nate Prewitt
239ee19431 Merge pull request #4612 from Obeyed/patch-1
update json param's description to avoid confusion
2018-04-30 08:00:19 -07:00
Elias Obeid
75c57985b0 update json param's description to avoid confusion
- the Request class doesn't accept JSON, but a JSON serializable object
2018-04-30 16:50:23 +02:00
Ian Stapleton Cordasco
11b82ca87c Merge pull request #4620 from requests/appveyor_fix
fix windows builds
2018-04-29 18:56:09 -05:00
Nate Prewitt
cd1278ef99 fix windows builds
Appveyor isn't able to replace the running executable. We'll run it
from inside the interpreter to fix build issues.
2018-04-29 10:27:20 -07:00
Ian Stapleton Cordasco
2de907ad77 Merge pull request #4596 from jdufresne/pypi
Update all pypi.python.org URLs to pypi.org
2018-04-19 05:41:37 -05:00
Jon Dufresne
165804b25e Update all pypi.python.org URLs to pypi.org
For details on the new PyPI, see the blog post:

https://pythoninsider.blogspot.ca/2018/04/new-pypi-launched-legacy-pypi-shutting.html
2018-04-18 20:28:19 -07:00
Nate Prewitt
b66908e7b6 Merge pull request #4547 from Saraislet/json-kwarg-docs
add comment about json parameter changing content-type
2018-03-16 12:42:55 -07:00
Hackbright Student
35af0b077f add comment about json parameter changing content-type 2018-03-16 12:34:24 -07:00
Kenneth Reitz
8246b82a16 niteo
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-13 11:28:31 -04:00
Kenneth Reitz
cd6eb30b20 party time
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-12 17:11:08 -04:00
Kenneth Reitz
e203d50e10 every day 2018-03-12 17:07:37 -04:00
Kenneth Reitz
b920c6e3f8 no hr
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-12 17:05:01 -04:00
Kenneth Reitz
6576370b7b cleanup
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-12 17:04:31 -04:00
Kenneth Reitz
85e536f7eb reorder
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-12 17:04:14 -04:00
Kenneth Reitz
130773a2d3 sidebar updates
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-12 17:02:06 -04:00
Kenneth Reitz
87872b9587 sponsored by™ 2018-03-12 16:59:11 -04:00
Kenneth Reitz
3de173e1c9 🍰 2018-03-12 16:54:00 -04:00
Kenneth Reitz
b5eacad638 patron sponsors
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-12 13:50:12 -04:00
Kenneth Reitz
b1ba9173d0 linode
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-12 13:48:12 -04:00
Kenneth Reitz
ee58368c9f typo
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-09 17:02:15 -05:00
Kenneth Reitz
cf0b8ed291 azure
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-09 16:50:13 -05:00
Kenneth Reitz
280c8b2a72 azure
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-09 16:47:27 -05:00
Kenneth Reitz
16b56d822e twilio!
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-09 11:07:37 -05:00
Kenneth Reitz
742610c6b9 linode
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 16:15:31 -05:00
Kenneth Reitz
eb692cb1e1 hiring
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:57:33 -05:00
Kenneth Reitz
f9a9233058 slack improvements
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:56:40 -05:00
Kenneth Reitz
9de992e22c sign off
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:43:27 -05:00
Kenneth Reitz
c063938abb individuals
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:42:17 -05:00
Kenneth Reitz
667367d6b9 better formatting
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:38:55 -05:00
Kenneth Reitz
8ce2fd2557 change order
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:36:29 -05:00
Kenneth Reitz
d8cc045a2e contact
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:35:39 -05:00
Kenneth Reitz
dc10a5dadd sponsors
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:34:07 -05:00
Kenneth Reitz
bf32936955 cleanup
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:33:26 -05:00
Kenneth Reitz
05b1401795 links
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:32:18 -05:00
Kenneth Reitz
873e8914c1 some
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:31:18 -05:00
Kenneth Reitz
c55258792b cleanup
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:30:33 -05:00
Kenneth Reitz
afad1aab14 community
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:28:55 -05:00
Kenneth Reitz
d05840d34d sponsors
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:28:41 -05:00
Kenneth Reitz
3323e65e96 track fundraiser on personal site
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 15:11:59 -05:00
Kenneth Reitz
74cf6fc38e \o/
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 09:19:28 -05:00
Kenneth Reitz
d91b70bd29 512
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-08 06:29:53 -05:00
Kenneth Reitz
5daa6cc63c $253
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 20:06:13 -05:00
Kenneth Reitz
0730b231ec $203
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 20:02:12 -05:00
Kenneth Reitz
77aa42943e more info
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 19:42:03 -05:00
Kenneth Reitz
b98027af9e donations
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 19:41:24 -05:00
Kenneth Reitz
8ce2c1a182 one time
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 19:27:15 -05:00
Kenneth Reitz
327a54d29d sidebar
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 19:24:45 -05:00
Kenneth Reitz
38a1947957 $10
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 19:11:45 -05:00
Kenneth Reitz
f8ade96762 sidebar
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 18:52:24 -05:00
Kenneth Reitz
665bb2a687 fix
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 18:49:49 -05:00
Kenneth Reitz
f21fd19ac5 goals
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 18:44:36 -05:00
Kenneth Reitz
f51c489d38 fix
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:41:09 -05:00
Kenneth Reitz
773eeff1a2 authors
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:40:38 -05:00
Kenneth Reitz
ac0a7ed152 fix
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:38:05 -05:00
Kenneth Reitz
a4f313a0e5 development
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:36:35 -05:00
Kenneth Reitz
8ca453a8d7 white
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:35:21 -05:00
Kenneth Reitz
c436165a2d gitignore
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:34:04 -05:00
Kenneth Reitz
97b28fdf7f top bar
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:33:51 -05:00
Kenneth Reitz
40f4b984ef index
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:18:27 -05:00
Kenneth Reitz
529c423fb5 support for Requests 3.0
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:15:59 -05:00
Kenneth Reitz
e292f302b7 different form
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 17:01:50 -05:00
Kenneth Reitz
c95b63736d links
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 16:56:58 -05:00
Kenneth Reitz
2d357f9c3b cleanup
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 16:55:18 -05:00
Kenneth Reitz
7fb1d70b86 fix fix fix
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 16:54:40 -05:00
Kenneth Reitz
c78c5002b5 important
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 16:51:30 -05:00
Kenneth Reitz
d123e9fe78 fix broken things
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 16:48:44 -05:00
Kenneth Reitz
8ad24ad430 experiment
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-03-07 16:44:57 -05:00
David Poole
85ec7d759e Merge branch 'master' into master 2018-03-05 09:07:12 -07:00
Kenneth Reitz
4ea09e49f7 .org
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-02-27 10:19:31 -05:00
Kenneth Reitz
06e788e253 <li><a href="http://html.python-requests.com/">Requests-HTML</a></li>
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-02-27 09:18:00 -05:00
Kenneth Reitz
27aad3666c Merge branch 'master' of github.com:requests/requests 2018-02-27 08:44:37 -05:00
Kenneth Reitz
44dbf8cf40 updated copyright year
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-02-27 08:44:29 -05:00
Kenneth Reitz
6e76aaea45 nike
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-02-22 08:34:32 -05:00
Jon Dufresne
265ef609d5 Remove remaining references to removed, vendored packages (#4499)
As the vendored packages were removing in version 2.16, all remaining
doc references should be replaced with newer practices.
2018-02-17 08:15:54 -06:00
Nate Prewitt
cafa3c16c2 Merge pull request #4497 from jdufresne/docs-certfi
Clarify docs that Requests always uses certs from certifi
2018-02-15 17:56:00 -08:00
Jon Dufresne
9c0db92249 Clarify docs that Requests always uses certs from certifi
Since commit 0d7de6430e, certifi is always
used for certificates. Certify became a hard dependency of the package
in 628633143d.

Now update the docs to clarify that Request will always use certificates
from certifi.
2018-02-14 05:47:34 -08:00
Kenneth Reitz
3c1d36b827 Merge branch 'master' of github.com:requests/requests
# Conflicts:
#	docs/_templates/sidebarintro.html
#	docs/_templates/sidebarlogo.html

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-02-12 09:43:07 -05:00
Kenneth Reitz
3cd87fac5d new sidebar link
Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
2018-02-12 09:42:09 -05:00
Semen Zhydenko
22120d423e Fix typos
nonexistant -> nonexistent
neccessary -> necessary
2018-02-07 18:25:22 -06:00
Nate Prewitt
654da610e1 Merge pull request #4498 from jdufresne/ws
Trim trialing white space throughout the project
2018-02-05 08:37:19 -08:00
Jon Dufresne
e8205c0131 Trim trialing white space throughout the project
Many editors clean up trailing white space on save. By removing it all
in one go, it helps keep future diffs cleaner by avoiding spurious white
space changes on unrelated lines.
2018-02-05 06:23:53 -08:00
Ian Stapleton Cordasco
8da118dfeb Merge pull request #4493 from nateprewitt/3.7_testing
Start testing 3.7
2018-02-03 08:43:31 -06:00
Ian Stapleton Cordasco
d69c068ac2 Merge branch 'master' into 3.7_testing 2018-02-03 08:33:55 -06:00
Ian Stapleton Cordasco
3ad14bb54e Merge pull request #4496 from lolatravel/pass_send_kwargs_to_add_headers
Pass kwargs from adapter send call to add_headers, per documentation
2018-02-03 07:40:44 -06:00
Jonathan Elliott Blum
8e040523a4 pass kwargs from send call to add_headers, per documentation 2018-02-02 13:10:16 -05:00
Nate Prewitt
99533b0f0f start testing 3.7 2018-01-26 03:01:22 -08:00
Nate Prewitt
512066488e updating history 2018-01-21 11:06:33 -08:00
Nate Prewitt
d2e1130603 Merge pull request #4452 from nateprewitt/append_fragment_on_redirect
append previous url fragment on redirect
2018-01-21 10:41:46 -08:00
Nate Prewitt
f60324a3de append previous url fragment on redirect 2018-01-21 09:55:45 -08:00
Ian Stapleton Cordasco
f89c325fbe Merge pull request #4439 from nkonin/fix/certifi-broken-link
Fix broken link to Certifi
2018-01-21 08:36:31 -06:00
Ian Stapleton Cordasco
d55b81b964 Merge branch 'master' into fix/certifi-broken-link 2018-01-21 08:12:19 -06:00
Kenneth Reitz
6a74c70a3a merge 2018-01-20 09:02:15 -05:00
Kenneth Reitz
599a8f11f8 sidebar 2018-01-20 09:01:50 -05:00
Никита Конин
0813c865ee Fix broken link to Certifi 2018-01-18 20:14:33 +03:00
Ian Stapleton Cordasco
07372dc058 Merge pull request #4427 from ddormer/4275-use-hostname-not-netloc
Use hostname not netloc
2018-01-16 08:07:26 -06:00
Darren Dormer
2255c34a65 Fix DNS resolution by using hostname instead of netloc and strip username and password when comparing against proxy bypass items. 2018-01-16 10:18:06 +01:00
Nate Prewitt
020f96577f Merge pull request #4459 from jdufresne/pyreq
Pass python_requires argument to setuptools
2018-01-12 20:06:59 -08:00
Jon Dufresne
7cefa939f5 Pass python_requires argument to setuptools
Helps pip decide what version of the library to install.

https://packaging.python.org/tutorials/distributing-packages/#python-requires

> If your project only runs on certain Python versions, setting the
> python_requires argument to the appropriate PEP 440 version specifier
> string will prevent pip from installing the project on other Python
> versions.

https://setuptools.readthedocs.io/en/latest/setuptools.html#new-and-changed-setup-keywords

> python_requires
>
> A string corresponding to a version specifier (as defined in PEP 440)
> for the Python version, used to specify the Requires-Python defined in
> PEP 345.
2018-01-12 16:39:10 -08:00
Ian Stapleton Cordasco
b9d8e00cbc Merge pull request #4460 from jdufresne/py33
Remove unsupported Python 3.3 from tox.ini
2018-01-11 08:41:08 -06:00
Jon Dufresne
620a5391c3 Remove unsupported Python 3.3 from tox.ini
Python 3.3 is not a supported version so don't test it.
2018-01-10 18:37:22 -08:00
Nate Prewitt
c98e30b5cb Merge pull request #4451 from jdufresne/https
Prefer https over http for links in the documentation
2018-01-06 15:22:59 -08:00
Jon Dufresne
030dcce20c Prefer https over http for links in the documentation
- Fixed Read the Docs links
- Fixed GitHub links
- Fixed PyPI links
2018-01-06 11:23:50 -08:00
Ian Stapleton Cordasco
3dc84cde5b Merge pull request #4442 from DemetriosBairaktaris/master
Reduce overall memory usage by removing cgi dependency and writing a protected function
2018-01-04 16:32:39 -06:00
dbairaktaris1
e0ab287317 added more to test scenarios 2018-01-04 10:59:47 -06:00
dbairaktaris1
7deee699ad slice function removed 2018-01-04 10:48:17 -06:00
dbairaktaris1
cb0914407b Continue to refactor, remove list comprehension, add double quotes test case. 2018-01-04 10:30:50 -06:00
dbairaktaris1
80a790443e implement changes after code review 2018-01-03 23:41:41 -06:00
dbairaktaris1
071796d83f implement changes after code review 2018-01-03 23:40:08 -06:00
dbairaktaris1
1988d9cf72 Move nested function up to module level and rename. Add more tests for function. 2018-01-01 14:20:55 -06:00
dbairaktaris1
2dc51c887f added versions back 2018-01-01 00:43:13 -06:00
dbairaktaris1
19cfec28a8 CI 2017-12-31 22:18:19 -06:00
dbairaktaris1
cef0830419 clean 2017-12-31 15:02:39 -06:00
dbairaktaris1
d8666e1906 Reduce overall memory usage of Requests module by removing cgi module dependency in utils.py. Instead wrote a nested function to parse header and return content type and params. 2017-12-31 14:46:15 -06:00
David Poole
efacb9e312 Merge branch 'master' into master 2017-11-29 07:13:07 -07:00
David Poole
1e46cbb4f0 add test for HTTP Digest auth algorithms SHA-256 and SHA-512 2017-11-29 07:10:57 -07:00
Cory Benfield
24092b11d7 Merge pull request #4380 from afedchin/win10
utils: winreg module may not exist like on windows universal platform.
2017-11-27 20:39:15 +00:00
Anton Fedchin
351ec982bb update changelog 2017-11-25 17:21:59 +03:00
Anton Fedchin
714c9dc967 utils: winreg module may not exist like on windows universal platform. 2017-11-25 17:21:59 +03:00
Cory Benfield
d1fb1a29ab Merge pull request #4394 from zaneb/document-status_codes
Add documentation for available status codes
2017-11-23 20:19:12 +00:00
Cory Benfield
c2507013ab Merge branch 'master' into document-status_codes 2017-11-22 20:41:46 +00:00
Nate Prewitt
e68ef0ecad Merge pull request #4368 from danielroseman/patch-1
Clarify behaviour of `json` parameter.
2017-11-22 07:56:09 -08:00
Zane Bitter
19919b44c4 Add documentation for available status codes
There was no way to determine what actual names were available outside
of looking at the source code. They were not listed in the documentation
or accessible through the interactive help.

In addition, doing `pydoc requests.status_codes` displayed some pretty
unhelpful information - the utf-8 encoding string was included in the
module name, there was no description, and internal variables used for
initialisation leaked into the module scope:

    DATA
        code = 511
        codes = <lookup 'status_codes'>
        title = 'network_authentication'
        titles = ('network_authentication_required', 'network_auth', ...

This change prevents the internal variables from leaking, adds a
docstring (which has the side-effect of correcting the module name), and
appends information on the allowed status code names to the docstring
when the module is initialised.

The improved module documentation is then used in the API documentation
to provide another easy reference to the complete list of status codes.
2017-11-21 16:11:34 -05:00
Daniel Roseman
39446def39 Clarify behaviour of json parameter.
`json` is ignored if `data` or `files` is not empty.
2017-11-21 13:40:59 +00:00
Mingyuan Xia
acd2645444 #4373, fix possible winreg value type difference (#4377)
* #4373, fix possible winreg value type difference

* add a test for ProxyOverride and ProxyEnable on win32

* add tests for winreg key ProxyEnable with two possible types

* fixing AppVeyor failures
2017-11-20 20:01:04 +00:00
Ian Stapleton Cordasco
e4fc3539b4 Merge pull request #4390 from alexwlchan/ok-docs
[docs; tiny] Clarify that Response.ok will *only* return True/False
2017-11-20 07:18:00 -06:00
Alex Chan
775cde0914 Clarify that Response.ok will *only* return True/False 2017-11-20 09:16:35 +00:00
David Poole
a31531fb9c Merge branch 'master' into master 2017-11-19 08:45:25 -07:00
Cory Benfield
c3f2553114 Merge pull request #4387 from dave-shawley/clarify-docs
Clarify raw response reading in the quickstart.
2017-11-18 09:44:29 +00:00
Dave Shawley
7cc3d8dc6a docs/quickstart: clarify raw response reading. 2017-11-17 16:37:08 -05:00
Ian Stapleton Cordasco
6d69f944a4 Merge pull request #4384 from taleinat/quickstart_doc_http_to_html
Correct HTTP -> HTML in quickstart doc
2017-11-16 10:01:45 -06:00
Tal Einat
7f08ad3b6c Corrent HTTP -> HTML in quickstart doc 2017-11-16 09:59:00 +02:00
Nate Prewitt
d55de2d391 Merge pull request #4356 from nehaljwani/fix-4353
Check if host is invalid for proxy
2017-11-15 14:16:33 -08:00
Nehal J Wani
9a8a826f22 Check if host is invalid for proxy
According to RFC3986, the authority section can be empty for a given URL,
however, for a proxy URL, it shouldn't be. This patch adds a check to verify
that the parsed URL will have a valid host before creating the proxy manager.

Fixes #4353
2017-11-15 08:58:54 -05:00
David Poole
1dbaddd75e for RFC-7616 add SHA-256 and SHA-512 2017-11-08 18:32:59 -07:00
Cory Benfield
234f80af88 Merge pull request #4371 from Twistbioscience/zipfile_compat
support extraction of certificate bundle from a zip archive
2017-11-06 21:08:45 +00:00
Arthur Vigil
c86b09b3c6 support extraction of certificate bundle from a zip archive 2017-11-05 12:14:17 -08:00
Nate Prewitt
81b63419cb Merge pull request #4352 from alexwlchan/hooks-on-sessions
Add something to the docs about hooks on Session()
2017-10-24 11:50:03 -07:00
Alex Chan
c5ed41e00a Add an example of two hooks 2017-10-24 07:27:55 +01:00
Alex Chan
40c5a8b0c2 Clarify that a Session can have multiple hooks 2017-10-23 13:25:46 +01:00
Alex Chan
87f3b0a559 Switch to using dict literals, it's 2017 2017-10-23 13:25:31 +01:00
Alex Chan
2c4849defe Add something to the docs about hooks on Session() 2017-10-23 08:30:35 +01:00
Nate Prewitt
c4c031fc5c Merge pull request #4342 from jdufresne/wheel-license
Include license file in the generated wheel package
2017-10-21 16:53:01 -07:00
Jon Dufresne
1595e43812 Include license file in the generated wheel package
The wheel package format supports including the license file. This is
done using the [metadata] section in the setup.cfg file. For additional
information on this feature, see:

https://wheel.readthedocs.io/en/stable/index.html#including-the-license-in-the-generated-wheel-file
2017-10-21 16:39:48 -07:00
Cory Benfield
8982efa9e4 Merge pull request #4349 from alvarogzp/patch-1
Fix case-insensitive comparison in Session.get_adapter
2017-10-21 06:26:31 -07:00
Alvaro Gutierrez Perez
2afc1cb37b Merge branch 'master' into patch-1 2017-10-21 03:24:55 +02:00
Cory Benfield
db9da3e0d2 Merge pull request #4316 from methane/no-platform
Avoid importing platform
2017-10-19 17:47:40 -07:00
INADA Naoki
a05aac7007 avoid import platform
platform module is relatively large: it takes about 5ms to import
2017-10-20 02:49:22 +09:00
Alvaro Gutierrez Perez
d165b18b6e Split test in two better-defined tests 2017-10-19 17:04:48 +02:00
Alvaro Gutierrez Perez
e11989e8ec Add test for Session.get_adapter() prefix matching 2017-10-19 16:50:13 +02:00
Alvaro Gutierrez Perez
af88af64e6 Add test for Session.get_adapter() case-insensitivity 2017-10-19 16:50:13 +02:00
Alvaro Gutierrez Perez
d3f14af44d Fix case-insensitive comparison in get_adapter()
While trying to get the prefix for an url, the url was lowered before comparing but the prefix not, so if it contains non-lowercase characters (eg. https://api.example.com/sOmE_WeiRD_pReFIX/), it won't match.
2017-10-18 19:27:06 +02:00
Nate Prewitt
54ad3d6dcc Merge pull request #4343 from jdufresne/classifier
Add missing trove classifier to document Python2 support
2017-10-16 01:21:19 -07:00
Jon Dufresne
c14bd018ad Add missing trove classifier to document Python2 support 2017-10-15 19:48:10 -07:00
49 changed files with 1182 additions and 448 deletions

34
.github/ISSUE_TEMPLATE/Bug_report.md vendored Normal file
View File

@@ -0,0 +1,34 @@
---
name: Bug report
about: Create a report to help us improve
---
Summary.
## Expected Result
What you expected.
## Actual Result
What happened instead.
## Reproduction Steps
```python
import requests
```
## System Information
$ python -m requests.help
```
<paste here>
```
This command is only available on Requests v2.16.4 and greater. Otherwise,
please provide some basic information about your system (Python version,
operating system, &c).

7
.github/ISSUE_TEMPLATE/Custom.md vendored Normal file
View File

@@ -0,0 +1,7 @@
---
name: Request for Help
about: Guidance on using Requests.
---
Please refer to our [StackOverflow tag](https://stackoverflow.com/questions/tagged/python-requests) for guidance.

View File

@@ -0,0 +1,7 @@
---
name: Feature request
about: Suggest an idea for this project
---
Requests is not accepting feature requests at this time.

2
.gitignore vendored
View File

@@ -21,3 +21,5 @@ t.py
t2.py
dist
/.mypy_cache/

View File

@@ -6,7 +6,7 @@ python:
- "3.4"
- "3.5"
- "3.6"
# - "3.7-dev"
- "3.7-dev"
# - "pypy" -- appears to hang
# - "pypy3"
# command to install dependencies
@@ -27,5 +27,3 @@ jobs:
- stage: coverage
python: 3.6
script: codecov

View File

@@ -1,13 +1,17 @@
Requests is written and maintained by Kenneth Reitz and
various contributors:
Keepers of the Four Crystals
````````````````````````````
Keepers of the Crystals
```````````````````````
- Kenneth Reitz <me@kennethreitz.org> `@kennethreitz <https://github.com/kennethreitz>`_, Keeper of the Master Crystal.
- Ian Cordasco <graffatcolmingov@gmail.com> `@sigmavirus24 <https://github.com/sigmavirus24>`_.
- Nate Prewitt <nate.prewitt@gmail.com> `@nateprewitt <https://github.com/nateprewitt>`_.
Previous Keepers of Crystals
````````````````````````````
- Cory Benfield <cory@lukasa.co.uk> `@lukasa <https://github.com/lukasa>`_
- Ian Cordasco <graffatcolmingov@gmail.com> `@sigmavirus24 <https://github.com/sigmavirus24>`_
- Nate Prewitt <nate.prewitt@gmail.com> `@nateprewitt <https://github.com/nateprewitt>`_
Patches and Suggestions
@@ -179,3 +183,8 @@ Patches and Suggestions
- Ed Morley (`@edmorley <https://github.com/edmorley>`_)
- Matt Liu <liumatt@gmail.com> (`@mlcrazy <https://github.com/mlcrazy>`_)
- Taylor Hoff <primdevs@protonmail.com> (`@PrimordialHelios <https://github.com/PrimordialHelios>`_)
- Arthur Vigil (`@ahvigil <https://github.com/ahvigil>`_)
- Nehal J Wani (`@nehaljwani <https://github.com/nehaljwani>`_)
- Demetrios Bairaktaris (`@DemetriosBairaktaris <https://github.com/demetriosbairaktaris>`_)
- Darren Dormer (`@ddormer <https://github.com/ddormer>`_)
- Rajiv Mayani (`@mayani <https://github.com/mayani>`_)

View File

@@ -6,13 +6,45 @@ Release History
dev
+++
**Improvements**
- [Short description of non-trivial change.]
- Warn user about possible slowdown when using cryptography version < 1.3.4
2.19.1 (2018-06-14)
+++++++++++++++++++
**Bugfixes**
- Parsing empty ``Link`` headers with ``parse_header_links()`` no longer return one bogus entry
- Fixed issue where status_codes.py's ``init`` function failed trying to append to
a ``__doc__`` value of ``None``.
2.19.0 (2018-06-12)
+++++++++++++++++++
**Improvements**
- Warn user about possible slowdown when using cryptography version < 1.3.4
- Check for invalid host in proxy URL, before forwarding request to adapter.
- Fragments are now properly maintained across redirects. (RFC7231 7.1.2)
- Removed use of cgi module to expedite library load time.
- Added support for SHA-256 and SHA-512 digest auth algorithms.
- Minor performance improvement to ``Request.content``.
- Migrate to using collections.abc for 3.7 compatibility.
**Bugfixes**
- Parsing empty ``Link`` headers with ``parse_header_links()`` no longer return one bogus entry.
- Fixed issue where loading the default certificate bundle from a zip archive
would raise an ``IOError``.
- Fixed issue with unexpected ``ImportError`` on windows system which do not support ``winreg`` module.
- DNS resolution in proxy bypass no longer includes the username and password in
the request. This also fixes the issue of DNS queries failing on macOS.
- Properly normalize adapter prefixes for url comparison.
- Passing ``None`` as a file pointer to the ``files`` param no longer raises an exception.
- Calling ``copy`` on a ``RequestsCookieJar`` will now preserve the cookie policy correctly.
**Dependencies**
- We now support idna v2.7.
- We now support urllib3 v1.23.
2.18.4 (2017-08-15)
+++++++++++++++++++
@@ -124,7 +156,7 @@ dev
- Further restored the ``requests.packages`` namespace for compatibility reasons.
No code modification (noted below) should be neccessary any longer.
No code modification (noted below) should be necessary any longer.
2.16.1 (2017-05-27)
+++++++++++++++++++

View File

@@ -1,4 +1,4 @@
Copyright 2017 Kenneth Reitz
Copyright 2018 Kenneth Reitz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

18
Pipfile
View File

@@ -1,24 +1,24 @@
[[source]]
url = "https://pypi.python.org/simple"
url = "https://pypi.org/simple/"
verify_ssl = true
name = "pypi"
[dev-packages]
pytest = ">=2.8.0"
codecov = "*"
"pytest-httpbin" = "==0.0.7"
"pytest-mock" = "*"
"pytest-cov" = "*"
"pytest-xdist" = "*"
pytest-httpbin = ">=0.0.7"
pytest-mock = "*"
pytest-cov = "*"
pytest-xdist = "*"
alabaster = "*"
"readme-renderer" = "*"
readme-renderer = "*"
sphinx = "<=1.5.5"
pysocks = "*"
docutils = "*"
"flake8" = "*"
tox = "*"
detox = "*"
httpbin = "==0.5.0"
httpbin = ">=0.7.0"
[packages]
"e1839a8" = {path = ".", editable = true, extras=["socks"]}
"e1839a8" = {path = ".", editable = true, extras = ["socks"]}

540
Pipfile.lock generated
View File

@@ -1,26 +1,14 @@
{
"_meta": {
"hash": {
"sha256": "72b5a08e9c266b930d308024036e928e6b99ed4b7a50f22af377a463b7867a14"
},
"host-environment-markers": {
"implementation_name": "cpython",
"implementation_version": "3.6.2",
"os_name": "posix",
"platform_machine": "x86_64",
"platform_python_implementation": "CPython",
"platform_release": "16.7.0",
"platform_system": "Darwin",
"platform_version": "Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64",
"python_full_version": "3.6.2",
"python_version": "3.6",
"sys_platform": "darwin"
"sha256": "0735b243455d8e924fbd05188ed435bfd3917f4acdade9b9e8f14741f3fc47e9"
},
"pipfile-spec": 6,
"requires": {},
"sources": [
{
"url": "https://pypi.python.org/simple",
"name": "pypi",
"url": "https://pypi.org/simple/",
"verify_ssl": true
}
]
@@ -28,15 +16,15 @@
"default": {
"certifi": {
"hashes": [
"sha256:54a07c09c586b0e4c619f02a5e94e36619da8e2b053e20f594348c0611803704",
"sha256:40523d2efb60523e113b44602298f0960e900388cf3bb6043f645cf57ea9e3f5"
"sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
"sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
],
"version": "==2017.7.27.1"
"version": "==2018.4.16"
},
"chardet": {
"hashes": [
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"version": "==3.0.4"
},
@@ -49,17 +37,16 @@
},
"idna": {
"hashes": [
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
],
"version": "==2.6"
},
"pysocks": {
"hashes": [
"sha256:18842328a4e6061f084cfba70f6950d9140ecf7418b3df7cef558ebb217bac8d",
"sha256:d00329f27efa157db7efe3ca26fcd69033cd61f83822461ee3f8a353b48e33cf"
"sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672"
],
"version": "==1.6.7"
"version": "==1.6.8"
},
"urllib3": {
"hashes": [
@@ -75,40 +62,120 @@
"sha256:2eef172f44e8d301d25aff8068fddd65f767a3f04b5f15b0f4922f113aa1c732",
"sha256:37cdcb9e9954ed60912ebc1ca12a9d12178c26637abdf124e3cde2341c257fe0"
],
"index": "pypi",
"version": "==0.7.10"
},
"apipkg": {
"hashes": [
"sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9",
"sha256:2e38399dbe842891fe85392601aab8f40a8f4cc5a9053c326de35a1cc0297ac6"
"sha256:2e38399dbe842891fe85392601aab8f40a8f4cc5a9053c326de35a1cc0297ac6",
"sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9"
],
"version": "==1.4"
},
"attrs": {
"hashes": [
"sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
"sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
],
"version": "==18.1.0"
},
"babel": {
"hashes": [
"sha256:f20b2acd44f587988ff185d8949c3e208b4b3d5d20fcab7d91fe481ffa435528",
"sha256:6007daf714d0cd5524bbe436e2d42b3c20e68da66289559341e48d2cd6d25811"
"sha256:8ce4cb6fdd4393edd323227cba3a077bceb2a6ce5201c902c65e730046f41f14",
"sha256:ad209a68d7162c4cff4b29cdebe3dec4cef75492df501b0049a9433c96ce6f80"
],
"version": "==2.5.1"
"version": "==2.5.3"
},
"bleach": {
"hashes": [
"sha256:a6d9d5f5b7368c1689ad7f128af8e792beea23393688872b576c0271e6564a16",
"sha256:b9522130003e4caedf4f00a39c120a906dcd4242329c1c8f621f5370203cbc30"
"sha256:b8fa79e91f96c2c2cd9fd1f9eda906efb1b88b483048978ba62fef680e962b34",
"sha256:eb7386f632349d10d9ce9d4a838b134d4731571851149f9cc2c05a9a837a9a44"
],
"version": "==2.0.0"
"version": "==2.1.3"
},
"blinker": {
"hashes": [
"sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
],
"version": "==1.4"
},
"brotlipy": {
"hashes": [
"sha256:07194f4768eb62a4f4ea76b6d0df6ade185e24ebd85877c351daa0a069f1111a",
"sha256:091b299bf36dd6ef7a06570dbc98c0f80a504a56c5b797f31934d2ad01ae7d17",
"sha256:09ec3e125d16749b31c74f021aba809541b3564e5359f8c265cbae442810b41a",
"sha256:0be698678a114addcf87a4b9496c552c68a2c99bf93cf8e08f5738b392e82057",
"sha256:0fa6088a9a87645d43d7e21e32b4a6bf8f7c3939015a50158c10972aa7f425b7",
"sha256:1ea4e578241504b58f2456a6c69952c88866c794648bdc74baee74839da61d44",
"sha256:2699945a0a992c04fc7dc7fa2f1d0575a2c8b4b769f2874a08e8eae46bef36ae",
"sha256:2a80319ae13ea8dd60ecdc4f5ccf6da3ae64787765923256b62c598c5bba4121",
"sha256:2e5c64522364a9ebcdf47c5744a5ddeb3f934742d31e61ebfbbc095460b47162",
"sha256:36def0b859beaf21910157b4c33eb3b06d8ce459c942102f16988cca6ea164df",
"sha256:3a3e56ced8b15fbbd363380344f70f3b438e0fd1fcf27b7526b6172ea950e867",
"sha256:3c1d5e2cf945a46975bdb11a19257fa057b67591eb232f393d260e7246d9e571",
"sha256:50ca336374131cfad20612f26cc43c637ac0bfd2be3361495e99270883b52962",
"sha256:5de6f7d010b7558f72f4b061a07395c5c3fd57f0285c5af7f126a677b976a868",
"sha256:637847560d671657f993313ecc6c6c6666a936b7a925779fd044065c7bc035b9",
"sha256:653faef61241bf8bf99d73ca7ec4baa63401ba7b2a2aa88958394869379d67c7",
"sha256:786afc8c9bd67de8d31f46e408a3386331e126829114e4db034f91eacb05396d",
"sha256:79aaf217072840f3e9a3b641cccc51f7fc23037496bd71e26211856b93f4b4cb",
"sha256:7e31f7adcc5851ca06134705fcf3478210da45d35ad75ec181e1ce9ce345bb38",
"sha256:8b39abc3256c978f575df5cd7893153277216474f303e26f0e43ba3d3969ef96",
"sha256:9448227b0df082e574c45c983fa5cd4bda7bfb11ea6b59def0940c1647be0c3c",
"sha256:96bc59ff9b5b5552843dc67999486a220e07a0522dddd3935da05dc194fa485c",
"sha256:a07647886e24e2fb2d68ca8bf3ada398eb56fd8eac46c733d4d95c64d17f743b",
"sha256:af65d2699cb9f13b26ec3ba09e75e80d31ff422c03675fcb36ee4dabe588fdc2",
"sha256:b4c98b0d2c9c7020a524ca5bbff42027db1004c6571f8bc7b747f2b843128e7a",
"sha256:c6cc0036b1304dd0073eec416cb2f6b9e37ac8296afd9e481cac3b1f07f9db25",
"sha256:d2c1c724c4ac375feb2110f1af98ecdc0e5a8ea79d068efb5891f621a5b235cb",
"sha256:dc6c5ee0df9732a44d08edab32f8a616b769cc5a4155a12d2d010d248eb3fb07",
"sha256:fd1d1c64214af5d90014d82cee5d8141b13d44c92ada7a0c0ec0679c6f15a471"
],
"version": "==0.7.0"
},
"certifi": {
"hashes": [
"sha256:54a07c09c586b0e4c619f02a5e94e36619da8e2b053e20f594348c0611803704",
"sha256:40523d2efb60523e113b44602298f0960e900388cf3bb6043f645cf57ea9e3f5"
"sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
"sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
],
"version": "==2017.7.27.1"
"version": "==2018.4.16"
},
"cffi": {
"hashes": [
"sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743",
"sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef",
"sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50",
"sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f",
"sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93",
"sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257",
"sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3",
"sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc",
"sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04",
"sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6",
"sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359",
"sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596",
"sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b",
"sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd",
"sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95",
"sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e",
"sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6",
"sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca",
"sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31",
"sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1",
"sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085",
"sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801",
"sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4",
"sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184",
"sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917",
"sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f",
"sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb"
],
"version": "==1.11.5"
},
"chardet": {
"hashes": [
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"version": "==3.0.4"
},
@@ -119,193 +186,225 @@
],
"version": "==6.7"
},
"cmarkgfm": {
"hashes": [
"sha256:0186dccca79483e3405217993b83b914ba4559fe9a8396efc4eea56561b74061",
"sha256:1a625afc6f62da428df96ec325dc30866cc5781520cbd904ff4ec44cf018171c",
"sha256:275905bb371a99285c74931700db3f0c078e7603bed383e8cf1a09f3ee05a3de",
"sha256:50098f1c4950722521f0671e54139e0edc1837d63c990cf0f3d2c49607bb51a2",
"sha256:50ed116d0b60a07df0dc7b180c28569064b9d37d1578d4c9021cff04d725cb63",
"sha256:61a72def110eed903cd1848245897bcb80d295cd9d13944d4f9f30cba5b76655",
"sha256:64186fb75d973a06df0e6ea12879533b71f6e7ba1ab01ffee7fc3e7534758889",
"sha256:665303d34d7f14f10d7b0651082f25ebf7107f29ef3d699490cac16cdc0fc8ce",
"sha256:70b18f843aec58e4e64aadce48a897fe7c50426718b7753aaee399e72df64190",
"sha256:761ee7b04d1caee2931344ac6bfebf37102ffb203b136b676b0a71a3f0ea3c87",
"sha256:811527e9b7280b136734ed6cb6845e5fbccaeaa132ddf45f0246cbe544016957",
"sha256:987b0e157f70c72a84f3c2f9ef2d7ab0f26c08f2bf326c12c087ff9eebcb3ff5",
"sha256:9fc6a2183d0a9b0974ec7cdcdad42bd78a3be674cc3e65f87dd694419b3b0ab7",
"sha256:c573ea89dd95d41b6d8cf36799c34b6d5b1eac4aed0212dee0f0a11fb7b01e8f",
"sha256:c5f1b9e8592d2c448c44e6bc0d91224b16ea5f8293908b1561de1f6d2d0658b1",
"sha256:cbe581456357d8f0674d6a590b1aaf46c11d01dd0a23af147a51a798c3818034",
"sha256:cf219bec69e601fe27e3974b7307d2f06082ab385d42752738ad2eb630a47d65",
"sha256:d08bad67fa18f7e8ff738c090628ee0cbf0505d74a991c848d6d04abfe67b697",
"sha256:d6f716d7b1182bf35862b5065112f933f43dd1aa4f8097c9bcfb246f71528a34",
"sha256:e08e479102627641c7cb4ece421c6ed4124820b1758765db32201136762282d9",
"sha256:e20ac21418af0298437d29599f7851915497ce9f2866bc8e86b084d8911ee061",
"sha256:e25f53c37e319241b9a412382140dffac98ca756ba8f360ac7ab5e30cad9670a",
"sha256:f20900f16377f2109783ae9348d34bc80530808439591c3d3df73d5c7ef1a00c"
],
"version": "==0.4.2"
},
"codecov": {
"hashes": [
"sha256:ad82f054837b02081f86ed1eb6c04cddc029fbc734eaf92ff73da1db3a79188b",
"sha256:db1c182ca896244d8644d8410a33f6f6dd1cc24d80209907a65077445923f00c"
"sha256:8ed8b7c6791010d359baed66f84f061bba5bd41174bf324c31311e8737602788",
"sha256:ae00d68e18d8a20e9c3288ba3875ae03db3a8e892115bf9b83ef20507732bed4"
],
"version": "==2.0.9"
"index": "pypi",
"version": "==2.0.15"
},
"configparser": {
"hashes": [
"sha256:5308b47021bc2340965c371f0f058cc6971a04502638d4244225c49d80db273a"
],
"markers": "python_version < '3.2'",
"version": "==3.5.0"
},
"contextlib2": {
"hashes": [
"sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48",
"sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"
],
"markers": "python_version < '3.2'",
"version": "==0.5.5"
},
"coverage": {
"hashes": [
"sha256:c1456f66c536010cf9e4633a8853a9153e8fd588393695295afd4d0fc16c1d74",
"sha256:97a7ec51cdde3a386e390b159b20f247ccb478084d925c75f1faa3d26c01335e",
"sha256:83e955b975666b5a07d217135e7797857ce844eb340a99e46cc25525120417c4",
"sha256:483ed14080c5301048128bb027b77978c632dd9e92e3ecb09b7e28f5b92abfcf",
"sha256:ef574ab9640bcfa2f3c671831faf03f65788945fdf8efa4d4a1fffc034838e2a",
"sha256:c5a205b4da3c624f5119dc4d84240789b5906bb8468902ec22dcc4aad8aa4638",
"sha256:5dea90ed140e7fa9bc00463313f9bc4a6e6aff297b4969615e7a688615c4c4d2",
"sha256:f9e83b39d29c2815a38e4118d776b482d4082b5bf9c9147fbc99a3f83abe480a",
"sha256:700040c354f0230287906b1276635552a3def4b646e0145555bc9e2e5da9e365",
"sha256:7f1eacae700c66c3d7362a433b228599c9d94a5a3a52613dddd9474e04deb6bc",
"sha256:13ef9f799c8fb45c446a239df68034de3a6f3de274881b088bebd7f5661f79f8",
"sha256:dfb011587e2b7299112f08a2a60d2601706aac9abde37aa1177ea825adaed923",
"sha256:381be5d31d3f0d912334cf2c159bc7bea6bfe6b0e3df6061a3bf2bf88359b1f6",
"sha256:83a477ac4f55a6ef59552683a0544d47b68a85ce6a80fd0ca6b3dc767f6495fb",
"sha256:dfd35f1979da31bcabbe27bcf78d4284d69870731874af629082590023a77336",
"sha256:9681efc2d310cfc53863cc6f63e88ebe7a48124550fa822147996cb09390b6ab",
"sha256:53770b20ac5b4a12e99229d4bae57af0945be87cc257fce6c6c7571a39f0c5d4",
"sha256:8801880d32f11b6df11c32a961e186774b4634ae39d7c43235f5a24368a85f07",
"sha256:16db2c69a1acbcb3c13211e9f954e22b22a729909d81f983b6b9badacc466eda",
"sha256:ef43a06a960b46c73c018704051e023ee6082030f145841ffafc8728039d5a88",
"sha256:c3e2736664a6074fc9bd54fb643f5af0fc60bfedb2963b3d3f98c7450335e34c",
"sha256:17709e22e4c9f5412ba90f446fb13b245cc20bf4a60377021bbff6c0f1f63e7c",
"sha256:a2f7106d1167825c4115794c2ba57cc3b15feb6183db5328fa66f94c12902d8b",
"sha256:2a08e978f402696c6956eee9d1b7e95d3ad042959b71bafe1f3e4557cbd6e0ac",
"sha256:57f510bb16efaec0b6f371b64a8000c62e7e3b3e48e8b0a5745ade078d849814",
"sha256:0f1883eab9c19aa243f51308751b8a2a547b9b817b721cc0ecf3efb99fafbea7",
"sha256:e00fe141e22ce6e9395aa24d862039eb180c6b7e89df0bbaf9765e9aebe560a9",
"sha256:ec596e4401553caa6dd2e3349ce47f9ef82c1f1bcba5d8ac3342724f0df8d6ff",
"sha256:c820a533a943ebc860acc0ce6a00dd36e0fdf2c6f619ff8225755169428c5fa2",
"sha256:b7f7283eb7badd2b8a9c6a9d6eeca200a0a24db6be79baee2c11398f978edcaa",
"sha256:a5ed27ad3e8420b2d6b625dcbd3e59488c14ccc06030167bcf14ffb0f4189b77",
"sha256:d7b70b7b4eb14d0753d33253fe4f121ca99102612e2719f0993607deb30c6f33",
"sha256:4047dc83773869701bde934fb3c4792648eda7c0e008a77a0aec64157d246801",
"sha256:7a9c44400ee0f3b4546066e0710e1250fd75831adc02ab99dda176ad8726f424",
"sha256:0f649e68db74b1b5b8ca4161d08eb2b8fa8ae11af1ebfb80e80e112eb0ef5300",
"sha256:52964fae0fafef8bd283ad8e9a9665205a9fdf912535434defc0ec3def1da26b",
"sha256:36aa6c8db83bc27346ddcd8c2a60846a7178ecd702672689d3ea1828eb1a4d11",
"sha256:9824e15b387d331c0fc0fef905a539ab69784368a1d6ac3db864b4182e520948",
"sha256:4a678e1b9619a29c51301af61ab84122e2f8cc7a0a6b40854b808ac6be604300",
"sha256:8bb7c8dca54109b61013bc4114d96effbf10dea136722c586bce3a5d9fc4e730",
"sha256:1a41d621aa9b6ab6457b557a754d50aaff0813fad3453434de075496fca8a183",
"sha256:0fa423599fc3d9e18177f913552cdb34a8d9ad33efcf52a98c9d4b644edb42c5",
"sha256:e61a4ba0b2686040cb4828297c7e37bcaf3a1a1c0bc0dbe46cc789dde51a80fa",
"sha256:ce9ef0fc99d11d418662e36fd8de6d71b19ec87c2eab961a117cc9d087576e72"
"sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba",
"sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed",
"sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a",
"sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd",
"sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640",
"sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2",
"sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162",
"sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508",
"sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249",
"sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694",
"sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a",
"sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287",
"sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1",
"sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000",
"sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1",
"sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e",
"sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5",
"sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062",
"sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba",
"sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc",
"sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc",
"sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99",
"sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653",
"sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c",
"sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558",
"sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f",
"sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4",
"sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91",
"sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d",
"sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9",
"sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd",
"sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d",
"sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6",
"sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77",
"sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80",
"sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e"
],
"version": "==4.4.1"
"version": "==4.5.1"
},
"decorator": {
"hashes": [
"sha256:95a26b17806e284452bfd97fa20aa1e8cb4ee23542bda4dbac5e4562aa1642cd",
"sha256:7cb64d38cb8002971710c8899fbdfb859a23a364b7c99dab19d1f719c2ba16b5"
"sha256:2c51dff8ef3c447388fe5e4453d24a2bf128d3a4c32af3fabef1f01c6851ab82",
"sha256:c39efa13fbdeb4506c476c9b3babf6a718da943dab7811c206005a4a956c080c"
],
"version": "==4.1.2"
"version": "==4.3.0"
},
"detox": {
"hashes": [
"sha256:af0097ea01263f68f546826df69b9301458d6cec0ed278c53c01f9529fbd349e",
"sha256:4719ca48c4ea5ffd908b1bc3d5d1b593b41e71dee17180d58d8a3e7e8f588d45"
"sha256:cb24895a0e4f95c0bcb1087a201c453600e075568af00848e91518fb2b984568",
"sha256:f3119bca4444f1e8a1d7189b064c52cfdd9a89ad3a1c921d78b49bf7f5dc5b1b"
],
"version": "==0.11"
"index": "pypi",
"version": "==0.12"
},
"docutils": {
"hashes": [
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6",
"sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274"
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
],
"index": "pypi",
"version": "==0.14"
},
"enum-compat": {
"hashes": [
"sha256:939ceff18186a5762ae4db9fa7bfe017edbd03b66526b798dd8245394c8a4192"
],
"version": "==0.0.2"
},
"enum34": {
"hashes": [
"sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79",
"sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
"sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a",
"sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1",
"sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850"
"sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79",
"sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"
],
"markers": "python_version < '3.4'",
"version": "==1.1.6"
},
"eventlet": {
"hashes": [
"sha256:0a7d1e1d2f4dd2e0b2cb627dadf7a0f23de0eca88ba2d6af4229abe32a24dec9",
"sha256:08faffab88c1b08bd53ea28bf084a572c89f7e7648bd9d71e6116ac17a51a15d"
"sha256:06cffa55b335cc4fc32d0079242a81e8a9cddf2581d64d5f0543e2d412b26ca8",
"sha256:554a50dad7abee0a9775b0780ce9d9c0bd9123dda4743c46d4314170267c6c47"
],
"version": "==0.21.0"
"version": "==0.23.0"
},
"execnet": {
"hashes": [
"sha256:d2b909c7945832e1c19cfacd96e78da68bdadc656440cfc7dfe59b766744eb8c",
"sha256:f66dd4a7519725a1b7e14ad9ae7d3df8e09b2da88062386e08e941cafc0ef3e6"
"sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a",
"sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83"
],
"version": "==1.4.1"
"version": "==1.5.0"
},
"flake8": {
"hashes": [
"sha256:f1a9d8886a9cbefb52485f4f4c770832c7fb569c084a9a314fb1eaa37c0c2c86",
"sha256:c20044779ff848f67f89c56a0e4624c04298cd476e25253ac0c36f910a1a11d8"
"sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0",
"sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37"
],
"version": "==3.4.1"
"index": "pypi",
"version": "==3.5.0"
},
"flask": {
"hashes": [
"sha256:0749df235e3ff61ac108f69ac178c9770caeaccad2509cb762ce1f65570a8856",
"sha256:49f44461237b69ecd901cc7ce66feea0319b9158743dd27a2899962ab214dac1"
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
],
"version": "==0.12.2"
"version": "==1.0.2"
},
"funcsigs": {
"hashes": [
"sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
"sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
],
"markers": "python_version < '3.3'",
"version": "==1.0.2"
},
"future": {
"hashes": [
"sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb"
],
"version": "==0.16.0"
},
"greenlet": {
"hashes": [
"sha256:96888e47898a471073b394ea641b7d675c1d054c580dd4a04a382bd34e67d89e",
"sha256:d2d5103f6cba131e1be660230018e21f276911d2b68b629ead1c5cb5e5472ac7",
"sha256:bc339de0e0969de5118d0b62a080a7611e2ba729a90f4a3ad78559c51bc5576d",
"sha256:b8ab98f8ae25938326dc4c21e3689a933531500ae4f3bfcefe36e3e25fda4dbf",
"sha256:416a3328d7e0a19aa1df3ec09524a109061fd7b80e010ef0dff9f695b4ac5e20",
"sha256:21232907c8c26838b16915bd8fbbf82fc70c996073464cc70981dd4a96bc841c",
"sha256:6803d8c6b235c861c50afddf00c7467ffbcd5ab960d137ff0f9c36f2cb11ee4b",
"sha256:76dab055476dd4dabb00a967b4df1990b25542d17eaa40a18f66971d10193e0b",
"sha256:70b9ff28921f5a3c03df4896ec8c55f5f94c593d7a79abd98b4c5c4a692ba873",
"sha256:7114b757b4146f4c87a0f00f1e58abd4c4729836679af0fc37266910a4a72eb0",
"sha256:0d90c709355ed13f16676f84e5a9cd67826a9f5c5143381c21e8fc3100ade1f1",
"sha256:ebae83b6247f83b1e8d887733dfa8046ce6e29d8b3e2a7380256e9de5c6ae55d",
"sha256:e841e3ece633acae5e2bf6102140a605ffee7d5d4921dca1625c5fdc0f0b3248",
"sha256:3e5e9be157ece49e4f97f3225460caf758ccb00f934fcbc5db34367cc1ff0aee",
"sha256:e77b708c37b652c7501b9f8f6056b23633c567aaa0d29edfef1c11673c64b949",
"sha256:0da1fc809c3bdb93fbacd0f921f461aacd53e554a7b7d4e9953ba09131c4206e",
"sha256:66fa5b101fcf4521138c1a29668074268d938bbb7de739c8faa9f92ea1f05e1f",
"sha256:e5451e1ce06b74a4861576c2db74405a4398c4809a105774550a9e52cfc8c4da",
"sha256:9c407aa6adfd4eea1232e81aa9f3cb3d9b955a9891c4819bf9b498c77efba14b",
"sha256:b56ac981f07b77e72ad5154278b93396d706572ea52c2fce79fee2abfcc8bfa6",
"sha256:e4c99c6010a5d153d481fdaf63b8a0782825c0721506d880403a3b9b82ae347e"
"sha256:09ef2636ea35782364c830f07127d6c7a70542b178268714a9a9ba16318e7e8b",
"sha256:0fef83d43bf87a5196c91e73cb9772f945a4caaff91242766c5916d1dd1381e4",
"sha256:1b7df09c6598f5cfb40f843ade14ed1eb40596e75cd79b6fa2efc750ba01bb01",
"sha256:1fff21a2da5f9e03ddc5bd99131a6b8edf3d7f9d6bc29ba21784323d17806ed7",
"sha256:42118bf608e0288e35304b449a2d87e2ba77d1e373e8aa221ccdea073de026fa",
"sha256:50643fd6d54fd919f9a0a577c5f7b71f5d21f0959ab48767bd4bb73ae0839500",
"sha256:58798b5d30054bb4f6cf0f712f08e6092df23a718b69000786634a265e8911a9",
"sha256:5b49b3049697aeae17ef7bf21267e69972d9e04917658b4e788986ea5cc518e8",
"sha256:75c413551a436b462d5929255b6dc9c0c3c2b25cbeaee5271a56c7fda8ca49c0",
"sha256:769b740aeebd584cd59232be84fdcaf6270b8adc356596cdea5b2152c82caaac",
"sha256:ad2383d39f13534f3ca5c48fe1fc0975676846dc39c2cece78c0f1f9891418e0",
"sha256:b417bb7ff680d43e7bd7a13e2e08956fa6acb11fd432f74c97b7664f8bdb6ec1",
"sha256:b6ef0cabaf5a6ecb5ac122e689d25ba12433a90c7b067b12e5f28bdb7fb78254",
"sha256:c2de19c88bdb0366c976cc125dca1002ec1b346989d59524178adfd395e62421",
"sha256:c7b04a6dc74087b1598de8d713198de4718fa30ec6cbb84959b26426c198e041",
"sha256:f8f2a0ae8de0b49c7b5b2daca4f150fdd9c1173e854df2cce3b04123244f9f45",
"sha256:fcfadaf4bf68a27e5dc2f42cbb2f4b4ceea9f05d1d0b8f7787e640bed2801634"
],
"version": "==0.4.12"
"version": "==0.4.13"
},
"html5lib": {
"hashes": [
"sha256:b8934484cf22f1db684c0fae27569a0db404d0208d20163fbf51cc537245d008",
"sha256:ee747c0ffd3028d2722061936b5c65ee4fe13c8e4613519b4447123fc4546298"
"sha256:20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3",
"sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736"
],
"version": "==0.999999999"
"version": "==1.0.1"
},
"httpbin": {
"hashes": [
"sha256:710069973216d4bbf9ab6757f1e9a1f3be05832ce77da023adce0a98dfeecfee",
"sha256:79fbc5d27e4194ea908b0fa18e09a59d95d287c91667aa69bcd010342d1589b5"
"sha256:7a04b5904c80b7aa04dd0a6af6520d68ce17a5db175e66a64b971f8e93d73a26",
"sha256:cbb37790c91575f4f15757f42ad41d9f729eb227d5edbe89e4ec175486db8dfa"
],
"version": "==0.5.0"
"index": "pypi",
"version": "==0.7.0"
},
"idna": {
"hashes": [
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
],
"version": "==2.6"
},
"imagesize": {
"hashes": [
"sha256:6ebdc9e0ad188f9d1b2cdd9bc59cbe42bf931875e829e7a595e6b3abdc05cdfb",
"sha256:0ab2c62b87987e3252f89d30b7cedbec12a01af9274af9ffa48108f2c13c6062"
"sha256:3620cc0cadba3f7475f9940d22431fc4d407269f1be59ec9b8edcca26440cf18",
"sha256:5b326e4678b6925158ccc66a9fa3122b6106d7c876ee32d7de6ce59385b96315"
],
"version": "==0.7.1"
"version": "==1.0.0"
},
"itsdangerous": {
"hashes": [
@@ -315,10 +414,10 @@
},
"jinja2": {
"hashes": [
"sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054",
"sha256:ddaa01a212cd6d641401cb01b605f4a4d9f37bfc93043d7f760ec70fb99ff9ff"
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
],
"version": "==2.9.6"
"version": "==2.10"
},
"markupsafe": {
"hashes": [
@@ -338,41 +437,58 @@
"sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1",
"sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"
],
"markers": "python_version < '3.0'",
"version": "==2.0.0"
},
"more-itertools": {
"hashes": [
"sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea",
"sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e",
"sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44"
],
"version": "==4.1.0"
},
"pbr": {
"hashes": [
"sha256:60c25b7dfd054ef9bb0ae327af949dd4676aa09ac3a9471cdc871d8a9213f9ac",
"sha256:05f61c71aaefc02d8e37c0a3eeb9815ff526ea28b3b76324769e6158d7f95be1"
"sha256:680bf5ba9b28dd56e08eb7c267991a37c7a5f90a92c2e07108829931a50ff80a",
"sha256:6874feb22334a1e9a515193cba797664e940b763440c88115009ec323a7f2df5"
],
"version": "==3.1.1"
"version": "==4.0.3"
},
"pluggy": {
"hashes": [
"sha256:bd60171dbb250fdebafad46ed16d97065369da40568ae948ef7117eee8536e94"
"sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff",
"sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
"sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5"
],
"version": "==0.5.2"
"version": "==0.6.0"
},
"py": {
"hashes": [
"sha256:2ccb79b01769d99115aa600d7eed99f524bf752bba8f041dc1c184853514655a",
"sha256:0f2d585d22050e90c7d293b6451c83db097df77871974d90efd5a30dc12fcde3"
"sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881",
"sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a"
],
"version": "==1.4.34"
"version": "==1.5.3"
},
"pycodestyle": {
"hashes": [
"sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9",
"sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766"
"sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766",
"sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9"
],
"version": "==2.3.1"
},
"pycparser": {
"hashes": [
"sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226"
],
"version": "==2.18"
},
"pyflakes": {
"hashes": [
"sha256:cc5eadfb38041f8366128786b4ca12700ed05bbf1403d808e89d57d67a3875a7",
"sha256:aa0d4dff45c0cc2214ba158d29280f8fa1129f3e87858ef825930845146337f4"
"sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f",
"sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805"
],
"version": "==1.5.0"
"version": "==1.6.0"
},
"pygments": {
"hashes": [
@@ -383,72 +499,78 @@
},
"pysocks": {
"hashes": [
"sha256:18842328a4e6061f084cfba70f6950d9140ecf7418b3df7cef558ebb217bac8d",
"sha256:d00329f27efa157db7efe3ca26fcd69033cd61f83822461ee3f8a353b48e33cf"
"sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672"
],
"version": "==1.6.7"
"version": "==1.6.8"
},
"pytest": {
"hashes": [
"sha256:b84f554f8ddc23add65c411bf112b2d88e2489fd45f753b1cae5936358bdf314",
"sha256:f46e49e0340a532764991c498244a60e3a37d7424a532b3ff1a6a7653f1a403a"
"sha256:54713b26c97538db6ff0703a12b19aeaeb60b5e599de542e7fca0ec83b9038e8",
"sha256:829230122facf05a5f81a6d4dfe6454a04978ea3746853b2b84567ecf8e5c526"
],
"version": "==3.2.2"
"index": "pypi",
"version": "==3.5.1"
},
"pytest-cov": {
"hashes": [
"sha256:890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec",
"sha256:03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d"
"sha256:03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d",
"sha256:890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec"
],
"index": "pypi",
"version": "==2.5.1"
},
"pytest-forked": {
"hashes": [
"sha256:f275cb48a73fc61a6710726348e1da6d68a978f0ec0c54ece5a5fae5977e5a08",
"sha256:e4500cd0509ec4a26535f7d4112a8cc0f17d3a41c29ffd4eab479d2a55b30805"
"sha256:e4500cd0509ec4a26535f7d4112a8cc0f17d3a41c29ffd4eab479d2a55b30805",
"sha256:f275cb48a73fc61a6710726348e1da6d68a978f0ec0c54ece5a5fae5977e5a08"
],
"version": "==0.2"
},
"pytest-httpbin": {
"hashes": [
"sha256:f430f0b5742a9d325148a3428f890f538f331cb7b244a49873cc322f838c85ea",
"sha256:03af8a7055c8bbcb68b14d9a14c103c82c97aeb86a8f1b29cd63d83644c2f021"
"sha256:8cd57e27418a7d7d205fcc9802eea246ed06170e3065abfa76c6d9b40553592c",
"sha256:d3919c5df0b644454129c0066a8ae62db40ac54bacb4cfd89d8cfa58615a4b42"
],
"version": "==0.0.7"
"index": "pypi",
"version": "==0.3.0"
},
"pytest-mock": {
"hashes": [
"sha256:7ed6e7e8c636fd320927c5d73aedb77ac2eeb37196c3410e6176b7c92fdf2f69",
"sha256:920d1167af5c2c2ad3fa0717d0c6c52e97e97810160c15721ac895cac53abb1c"
"sha256:53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928",
"sha256:d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0"
],
"version": "==1.6.3"
"index": "pypi",
"version": "==1.10.0"
},
"pytest-xdist": {
"hashes": [
"sha256:7924d45c2430191fe3679a58116c74ceea13307d7822c169d65fd59a24b3a4fe"
"sha256:be2662264b035920ba740ed6efb1c816a83c8a22253df7766d129f6a7bfdbd35",
"sha256:e8f5744acc270b3e7d915bdb4d5f471670f049b6fbd163d4cbd52203b075d30f"
],
"version": "==1.20.0"
"index": "pypi",
"version": "==1.22.2"
},
"pytz": {
"hashes": [
"sha256:c883c2d6670042c7bc1688645cac73dd2b03193d1f7a6847b6154e96890be06d",
"sha256:03c9962afe00e503e2d96abab4e8998a0f84d4230fa57afe1e0528473698cdd9",
"sha256:487e7d50710661116325747a9cd1744d3323f8e49748e287bc9e659060ec6bf9",
"sha256:43f52d4c6a0be301d53ebd867de05e2926c35728b3260157d274635a0a947f1c",
"sha256:d1d6729c85acea5423671382868627129432fba9a89ecbb248d8d1c7a9f01c67",
"sha256:54a935085f7bf101f86b2aff75bd9672b435f51c3339db2ff616e66845f2b8f9",
"sha256:39504670abb5dae77f56f8eb63823937ce727d7cdd0088e6909e6dcac0f89043",
"sha256:ddc93b6d41cfb81266a27d23a79e13805d4a5521032b512643af8729041a81b4",
"sha256:f5c056e8f62d45ba8215e5cb8f50dfccb198b4b9fbea8500674f3443e4689589"
"sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555",
"sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749"
],
"version": "==2017.2"
"version": "==2018.4"
},
"raven": {
"hashes": [
"sha256:1c641e5ebc2d4185560608e253970ca0d4b98475f4edf67735015a415f9e1d48",
"sha256:95aecf76c414facaddbb056f3e98c7936318123e467728f2e50b3a66b65a6ef7"
],
"version": "==6.8.0"
},
"readme-renderer": {
"hashes": [
"sha256:c9637bfcf1ff40f7683b3439f4b97eb0f9a1cffc2a1fad5fa01debd667ddb111",
"sha256:9deab442963a63a71ab494bf581b1c844473995a2357f4b3228a1df1c8cba8da"
"sha256:bde909eaa84d65b7942f7e6998c8b427b90b568b2630ff0306f4ca75f6d2a909",
"sha256:e7e43a7ba49f08c3cb660d0f2e25b561f6b10b36c63f029060230aab2dc2875e"
],
"version": "==17.2"
"index": "pypi",
"version": "==20.0"
},
"requests": {
"hashes": [
@@ -459,15 +581,15 @@
},
"six": {
"hashes": [
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
],
"version": "==1.11.0"
},
"snowballstemmer": {
"hashes": [
"sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89",
"sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128"
"sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128",
"sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89"
],
"version": "==1.2.1"
},
@@ -476,14 +598,16 @@
"sha256:11f271e7a9398385ed730e90f0bb41dc3815294bdcd395b46ed2d033bc2e7d87",
"sha256:4064ea6c56feeb268838cb8fbbee507d0c3d5d92fa63a7df935a916b52c9e2f5"
],
"index": "pypi",
"version": "==1.5.5"
},
"tox": {
"hashes": [
"sha256:49d88f2c217352c499450e9f61ca82fd9c8873d01a45555bb342a32f2b6753a2",
"sha256:d9c279e707d2cfef8d77d10f13b38b3e68b7e470018b45747560f6c3c66d6b83"
"sha256:96efa09710a3daeeb845561ebbe1497641d9cef2ee0aea30db6969058b2bda2f",
"sha256:9ee7de958a43806402a38c0d2aa07fa8553f4d2c20a15b140e9f771c2afeade0"
],
"version": "==2.8.2"
"index": "pypi",
"version": "==3.0.0"
},
"urllib3": {
"hashes": [
@@ -494,10 +618,10 @@
},
"virtualenv": {
"hashes": [
"sha256:39d88b533b422825d644087a21e78c45cf5af0ef7a99a1fc9fbb7b481e5c85b0",
"sha256:02f8102c2436bb03b3ee6dede1919d1dac8a427541652e5ec95171ec8adbc93a"
"sha256:1d7e241b431e7afce47e77f8843a276f652699d1fa4f93b9d8ce0076fd7b0b54",
"sha256:e8e05d4714a1c51a2f5921e62f547fcb0f713ebbe959e0a7f585cc8bef71d11f"
],
"version": "==15.1.0"
"version": "==15.2.0"
},
"webencodings": {
"hashes": [
@@ -508,10 +632,10 @@
},
"werkzeug": {
"hashes": [
"sha256:e8549c143af3ce6559699a01e26fa4174f4c591dbee0a499f3cd4c3781cdec3d",
"sha256:903a7b87b74635244548b30d30db4c8947fe64c5198f58899ddcd3a13c23bb26"
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
],
"version": "==0.12.2"
"version": "==0.14.1"
}
}
}

View File

@@ -2,13 +2,13 @@ Requests: HTTP for Humans
=========================
.. image:: https://img.shields.io/pypi/v/requests.svg
:target: https://pypi.python.org/pypi/requests
:target: https://pypi.org/project/requests/
.. image:: https://img.shields.io/pypi/l/requests.svg
:target: https://pypi.python.org/pypi/requests
:target: https://pypi.org/project/requests/
.. image:: https://img.shields.io/pypi/pyversions/requests.svg
:target: https://pypi.python.org/pypi/requests
:target: https://pypi.org/project/requests/
.. image:: https://codecov.io/github/requests/requests/coverage.svg?branch=master
:target: https://codecov.io/github/requests/requests
@@ -77,7 +77,7 @@ Requests is ready for today's web.
- ``.netrc`` Support
- Chunked Requests
Requests officially supports Python 2.62.7 & 3.43.6, and runs great on PyPy.
Requests officially supports Python 2.7 & 3.43.6, and runs great on PyPy.
Installation
------------
@@ -105,6 +105,6 @@ How to Contribute
#. Write a test which shows that the bug was fixed or that the feature works as expected.
#. Send a pull request and bug the maintainer until it gets merged and published. :) Make sure to add yourself to AUTHORS_.
.. _`the repository`: http://github.com/requests/requests
.. _`the repository`: https://github.com/requests/requests
.. _AUTHORS: https://github.com/requests/requests/blob/master/AUTHORS.rst
.. _Contributor Friendly: https://github.com/requests/requests/issues?direction=desc&labels=Contributor+Friendly&page=1&sort=updated&state=open

View File

@@ -41,8 +41,9 @@ install:
# Upgrade to the latest version of pip to avoid it displaying warnings
# about it being out of date.
- "pip install --disable-pip-version-check --user --upgrade pip"
- "python -m pip install --upgrade pip wheel"
- "C:\\MinGW\\bin\\mingw32-make"
- "pipenv install -e .[socks] --skip-lock"
test_script:
- "C:\\MinGW\\bin\\mingw32-make coverage"

View File

@@ -1,3 +1,11 @@
body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-child(2) > td > select {
width: 100%!important;
}
#python27 > a {
color: white;
}
#carbonads {
display: block;
overflow: hidden;

View File

@@ -1,7 +1,6 @@
<!-- Alabaster (krTheme++) Hacks -->
<aside id="python27">
Python 3, the new best practice, is here to stay.
Python 2 will retire in only <time></time> months!
<a href="https://www.kennethreitz.org/requests3"><strong>Requests 3.0</strong> development is underway, and your financial help is appreciated!</a>
</aside>
<!-- Python 2 Death Clock™ -->
@@ -20,14 +19,14 @@
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script>
var death = new Date('2020-04-12');
var diff = moment.duration(death - moment());
document.querySelector('#python27 time').innerText = (diff.years() * 12) + diff.months();
</script>
</script> -->
<!-- CSS Adjustments (I'm very picky.) -->

View File

@@ -5,7 +5,7 @@
</p>
<p>
<iframe src="http://ghbtns.com/github-btn.html?user=requests&repo=requests&type=watch&count=true&size=large"
<iframe src="https://ghbtns.com/github-btn.html?user=requests&repo=requests&type=watch&count=true&size=large"
allowtransparency="true" frameborder="0" scrolling="0" width="200px" height="35px"></iframe>
</p>
@@ -13,24 +13,26 @@
Requests is an elegant and simple HTTP library for Python, built for
human beings.
</p>
<p>Sponsored by <strong><a href="https://linode.com/">Linode</a></strong> and <a href="http://docs.python-requests.org/en/master/community/sponsors/#patron-sponsors">other wonderful organizations</a>.</p>
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=pythonrequestsorg" id="_carbonads_js"></script>
<h3><a href="http://www.unixstickers.com/stickers/coding_stickers/requests-shaped-sticker">Stickers!</a></h3>
<p><a href="http://www.unixstickers.com/stickers/coding_stickers/requests-shaped-sticker">Requests Stickers!</a></p>
<h3>Stay Informed</h3>
<p>Receive updates on new releases and upcoming projects.</p>
<p><iframe src="http://ghbtns.com/github-btn.html?user=kennethreitz&type=follow&count=false"
<p><iframe src="https://ghbtns.com/github-btn.html?user=kennethreitz&type=follow&count=false"
allowtransparency="true" frameborder="0" scrolling="0" width="200" height="20"></iframe></p>
<p><a href="https://twitter.com/kennethreitz" class="twitter-follow-button" data-show-count="false">Follow @kennethreitz</a> <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script></p>
<p><a href="https://saythanks.io/to/kennethreitz">Say Thanks!</a></p>
<p><a href="http://tinyletter.com/kennethreitz">Join Mailing List</a>.</p>
<h3>Other Projects</h3>
<p>More <a href="http://kennethreitz.org/">Kenneth Reitz</a> projects:</p>
<ul>
<li><a href="http://edmsynths.com/">edmsynths.com</a></li>
<li><a href="http://html.python-requests.org/">Requests-HTML</a></li>
<li><a href="http://howtopython.org/">howtopython.org</a></li>
<li><a href="http://pipenv.org/">pipenv</a></li>
<li><a href="http://pep8.org/">pep8.org</a></li>
<li><a href="http://httpbin.org/">httpbin.org</a></li>
@@ -48,9 +50,9 @@
<p></p>
<li><a href="http://github.com/requests/requests">Requests @ GitHub</a></li>
<li><a href="http://pypi.python.org/pypi/requests">Requests @ PyPI</a></li>
<li><a href="http://github.com/requests/requests/issues">Issue Tracker</a></li>
<li><a href="https://github.com/requests/requests">Requests @ GitHub</a></li>
<li><a href="https://pypi.org/project/requests/">Requests @ PyPI</a></li>
<li><a href="https://github.com/requests/requests/issues">Issue Tracker</a></li>
<li><a href="http://docs.python-requests.org/en/latest/community/updates/#software-updates">Release History</a></li>
</ul>
@@ -67,4 +69,3 @@
<li><a href="http://it.python-requests.org/">Italian</a></li>
<li><a href="http://es.python-requests.org/">Spanish</a></li>
</ul>

View File

@@ -4,28 +4,31 @@
</a>
</p>
<p>
<iframe src="http://ghbtns.com/github-btn.html?user=requests&repo=requests&type=watch&count=true&size=large"
<iframe src="https://ghbtns.com/github-btn.html?user=requests&repo=requests&type=watch&count=true&size=large"
allowtransparency="true" frameborder="0" scrolling="0" width="200px" height="35px"></iframe>
</p>
<p>
Requests is an elegant and simple HTTP library for Python, built for
human beings. You are currently looking at the documentation of the
development release.
</p>
<h3><a href="http://www.unixstickers.com/stickers/coding_stickers/requests-shaped-sticker">Stickers!</a></h3>
<p>Sponsored by <strong><a href="https://linode.com/">Linode</a></strong> and <a href="http://docs.python-requests.org/en/master/community/sponsors/#patron-sponsors">other wonderful organizations</a>.</p>
<h3>Stay Informed</h3>
<p>Receive updates on new releases and upcoming projects.</p>
<p><a href="http://www.unixstickers.com/stickers/coding_stickers/requests-shaped-sticker">Requests Stickers!</a></p>
<p><a href="http://tinyletter.com/kennethreitz">Join Mailing List</a>.</p>
<hr/>
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=pythonrequestsorg" id="_carbonads_js"></script>
<p>If you enjoy using this project, <a href="https://saythanks.io/to/kennethreitz">Say Thanks!</a></p>
<p><iframe src="http://ghbtns.com/github-btn.html?user=kennethreitz&type=follow&count=false"
<p><iframe src="https://ghbtns.com/github-btn.html?user=kennethreitz&type=follow&count=false"
allowtransparency="true" frameborder="0" scrolling="0" width="200" height="20"></iframe></p>
<p><a href="https://twitter.com/kennethreitz" class="twitter-follow-button" data-show-count="false">Follow @kennethreitz</a> <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script></p>
@@ -35,7 +38,8 @@
<p>More <a href="http://kennethreitz.org/">Kenneth Reitz</a> projects:</p>
<ul>
<li><a href="http://edmsynths.com/">edmsynths.com</a></li>
<li><a href="http://html.python-requests.org/">Requests-HTML</a></li>
<li><a href="http://howtopython.org/">howtopython.org</a></li>
<li><a href="http://pipenv.org/">pipenv</a></li>
<li><a href="http://pep8.org/">pep8.org</a></li>
<li><a href="http://httpbin.org/">httpbin.org</a></li>
@@ -59,4 +63,3 @@
<li><a href="http://it.python-requests.org/">Italian</a></li>
<li><a href="http://es.python-requests.org/">Spanish</a></li>
</ul>

View File

@@ -109,17 +109,7 @@ Status Code Lookup
.. autoclass:: requests.codes
::
>>> requests.codes['temporary_redirect']
307
>>> requests.codes.teapot
418
>>> requests.codes['\o/']
200
.. automodule:: requests.status_codes
Migrating to 1.x
@@ -191,7 +181,7 @@ API Changes
logging.basicConfig() # you need to initialize logging, otherwise you will not see anything from requests
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log = logging.getLogger("urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

View File

@@ -56,7 +56,6 @@ Python 3 Support?
Yes! Here's a list of Python platforms that are officially
supported:
* Python 2.6
* Python 2.7
* Python 3.4
* Python 3.5
@@ -70,7 +69,7 @@ These errors occur when :ref:`SSL certificate verification <verification>`
fails to match the certificate the server responds with to the hostname
Requests thinks it's contacting. If you're certain the server's SSL setup is
correct (for example, because you can visit the site with your browser) and
you're using Python 2.6 or 2.7, a possible explanation is that you need
you're using Python 2.7, a possible explanation is that you need
Server-Name-Indication.
`Server-Name-Indication`_, or SNI, is an official extension to SSL where the

View File

@@ -18,7 +18,7 @@ Articles & Talks
- `Python for the Web <http://gun.io/blog/python-for-the-web/>`_ teaches how to use Python to interact with the web, using Requests.
- `Daniel Greenfeld's Review of Requests <http://pydanny.blogspot.com/2011/05/python-http-requests-for-humans.html>`_
- `My 'Python for Humans' talk <http://python-for-humans.heroku.com>`_ ( `audio <http://codeconf.s3.amazonaws.com/2011/pycodeconf/talks/PyCodeConf2011%20-%20Kenneth%20Reitz.m4a>`_ )
- `Issac Kelly's 'Consuming Web APIs' talk <http://issackelly.github.com/Consuming-Web-APIs-with-Python-Talk/slides/slides.html>`_
- `Issac Kelly's 'Consuming Web APIs' talk <https://issackelly.github.com/Consuming-Web-APIs-with-Python-Talk/slides/slides.html>`_
- `Blog post about Requests via Yum <http://arunsag.wordpress.com/2011/08/17/new-package-python-requests-http-for-humans/>`_
- `Russian blog post introducing Requests <http://habrahabr.ru/blogs/python/126262/>`_
- `Sending JSON in Requests <http://www.coglib.com/~icordasc/blog/2014/11/sending-json-in-requests.html>`_

View File

@@ -15,7 +15,7 @@ Certifi CA Bundle
validating the trustworthiness of SSL certificates while verifying the
identity of TLS hosts. It has been extracted from the Requests project.
.. _Certifi: http://certifi.io/en/latest/
.. _Certifi: https://github.com/certifi/python-certifi
CacheControl
------------
@@ -34,7 +34,7 @@ but do not belong in Requests proper. This library is actively maintained
by members of the Requests core team, and reflects the functionality most
requested by users within the community.
.. _Requests-Toolbelt: http://toolbelt.readthedocs.io/en/latest/index.html
.. _Requests-Toolbelt: https://toolbelt.readthedocs.io/en/latest/index.html
Requests-Threads
@@ -62,6 +62,3 @@ Betamax
A VCR imitation designed only for Python-Requests.
.. _betamax: https://github.com/sigmavirus24/betamax

View File

@@ -19,19 +19,18 @@ Breaking changes are changes that break backwards compatibility with prior
versions. If the project were to change the ``text`` attribute on a
``Response`` object to a method, that would only happen in a Major release.
Major releases may also include miscellaneous bug fixes and upgrades to
vendored packages. The core developers of Requests are committed to providing
a good user experience. This means we're also committed to preserving
backwards compatibility as much as possible. Major releases will be infrequent
and will need strong justifications before they are considered.
Major releases may also include miscellaneous bug fixes. The core developers of
Requests are committed to providing a good user experience. This means we're
also committed to preserving backwards compatibility as much as possible. Major
releases will be infrequent and will need strong justifications before they are
considered.
Minor Releases
--------------
A minor release will not include breaking changes but may include
miscellaneous bug fixes and upgrades to vendored packages. If the previous
version of Requests released was ``v10.2.7`` a minor release would be
versioned as ``v10.3.0``.
A minor release will not include breaking changes but may include miscellaneous
bug fixes. If the previous version of Requests released was ``v10.2.7`` a minor
release would be versioned as ``v10.3.0``.
Minor releases will be backwards compatible with releases that have the same
major version number. In other words, all versions that would start with

View File

@@ -0,0 +1,96 @@
Community Sponsors
==================
**tl;dr**: Requests development is currently `funded by the Python community <https://www.kennethreitz.org/requests3>`_, and
some wonderful organizations that utilize the software in their businesses.
-------------------
Requests is one of the most heavilyutilized Python packages in the world.
It is used by major corporations worldwide for all tasks, both small and large — from writing oneoff scripts to orchestrating millions of dollars of critical infrastructure.
It's even embedded within pip, that tool that you use to install packages and deploy with every day!
After losing our primary open source maintainer (who was sponsored by a company to work on Requests, and other projects, fulltime), we are seeking community financial contributions towards the development of Requests 3.0.
Patron Sponsors
----------------
`Linode — SSD Cloud Hosting & Linux Servers <https://www.linode.com>`_
//////////////////////////////////////////////////////////////////////
Whether youre just getting started or deploying a complex system, launching a Linode cloud server has never been easier. They offer the fastest hardware and network in the industry with scalable environments, and their 24x7 customer support team is always standing by to help with any questions.
✨🍰✨
//////
----------------------------------
This slot is reserved for ethical organizations willing to invest $10,000 or more in Requests per year.
By becoming a patronlevel sponsor, your organization will receive the following benefits:
- Prominent placement on the Requests documentation sidebar (~11,000 uniques / day).
- Honorable mention here, with logo.
- Peace of mind knowing that the infrastructure you rely on is being actively maintained.
Organizations that sign up will be listed in order — first come first serve!
Major Sponsors
--------------
The following organizations have significantly contributed towards Requests' sustainability:
`Slack — Bring your team together <https://slack.com>`_
///////////////////////////////////////////////////////
Slack was extremely kind to be the first organization to generously donate a large sum towards the `2018 Requests 3.0 fundraiser <https://www.kennethreitz.org/requests3>`_, surpassing our entire fundraising goal immediately! They are helping the world become a better place through connectiveness, and reducing the amount of email we all have
to deal with on a daily basis.
P.S. They're `hiring <https://slack.com/careers#openings>`_!
`Twilio — Voice, SMS, and Video for Humans <https://www.twilio.com>`_
/////////////////////////////////////////////////////////////////////
Twilio was the second organization to generously donate a large sum towards the `2018 Requests 3.0 fundraiser <https://www.kennethreitz.org/requests3>`_, matching the donation of Slack! They are helping the world become a better place through interconnectivity,
providing easytouse APIs, and empowering developers world-over to help humans communicate in meaningful and effictive ways.
`Azure Cloud Developer Advocates <https://developer.microsoft.com/en-us/advocates/>`_
/////////////////////////////////////////////////////////////////////////////////////
Azure was the third organization to generously donate a large sum towards the `2018 Requests 3.0 fundraiser <https://www.kennethreitz.org/requests3>`_, matching the donation of Twilio! Awesome group of generous folks :)
`Niteo — Web Systems Development <https://www.niteoweb.com>`_
/////////////////////////////////////////////////////////////
Niteo was the fourth company to generously donate towards the `2018 Requests 3.0 fundraiser <https://www.kennethreitz.org/requests3>`_. Niteo is a company employing tech enthusiasts from all over the world
who love to build great stuff.
`Heroku <https://heroku.com/python>`_
/////////////////////////////////////
Heroku has allowed Kenneth Reitz to work on some open source projects during work hours,
including Requests (but mostly Pipenv), from timetotime, so they are listed
here as an honorable mention.
----------------
If your organization is interested in becoming either a sponsor or a patron, please `send us an email <mailto:me@kennethreitz.org>`_.
Individual Sponsors
-------------------
Countless individuals, too many to list here, have individually contributed towards the sustainability of the Requests
project over the years. Some, financially, others, with code. Contributions (from humans) of all kinds are greatly
appreciated.
✨🍰✨

View File

@@ -29,4 +29,3 @@ Release and Version History
===========================
.. include:: ../../HISTORY.rst

View File

@@ -58,7 +58,7 @@ master_doc = 'index'
# General information about the project.
project = u'Requests'
copyright = u'MMXVII. A <a href="http://kennethreitz.com/pages/open-projects.html">Kenneth Reitz</a> Project'
copyright = u'MMXVIII. A <a href="http://kennethreitz.com/pages/open-projects.html">Kenneth Reitz</a> Project'
author = u'Kenneth Reitz'
# The version info for the project you're documenting, acts as replacement for
@@ -376,4 +376,4 @@ epub_exclude_files = ['search.html']
# If false, no index is generated.
#epub_use_index = True
intersphinx_mapping = {'urllib3': ('http://urllib3.readthedocs.io/en/latest', None)}
intersphinx_mapping = {'urllib3': ('https://urllib3.readthedocs.io/en/latest', None)}

View File

@@ -51,7 +51,6 @@ Runtime Environments
Requests currently supports the following versions of Python:
- Python 2.6
- Python 2.7
- Python 3.4
- Python 3.5
@@ -61,5 +60,4 @@ Requests currently supports the following versions of Python:
Google AppEngine is not officially supported although support is available
with the `Requests-Toolbelt`_.
.. _Requests-Toolbelt: http://toolbelt.readthedocs.io/
.. _Requests-Toolbelt: https://toolbelt.readthedocs.io/

View File

@@ -9,13 +9,13 @@ Requests: HTTP for Humans
Release v\ |version|. (:ref:`Installation <install>`)
.. image:: https://img.shields.io/pypi/l/requests.svg
:target: https://pypi.python.org/pypi/requests
:target: https://pypi.org/project/requests/
.. image:: https://img.shields.io/pypi/wheel/requests.svg
:target: https://pypi.python.org/pypi/requests
:target: https://pypi.org/project/requests/
.. image:: https://img.shields.io/pypi/pyversions/requests.svg
:target: https://pypi.python.org/pypi/requests
:target: https://pypi.org/project/requests/
.. image:: https://codecov.io/github/requests/requests/coverage.svg?branch=master
:target: https://codecov.io/github/requests/requests
@@ -30,8 +30,8 @@ consumption.
.. note:: The use of **Python 3** is *highly* preferred over Python 2. Consider upgrading your applications and infrastructure if you find yourself *still* using Python 2 in production today. If you are using Python 3, congratulations — you are indeed a person of excellent taste.
*Kenneth Reitz*
-------------------
**Behold, the power of Requests**::
@@ -59,12 +59,12 @@ are 100% automatic, thanks to `urllib3 <https://github.com/shazow/urllib3>`_.
User Testimonials
-----------------
Twitter, Spotify, Microsoft, Amazon, Lyft, BuzzFeed, Reddit, The NSA, Her Majesty's Government, Google, Twilio, Runscope, Mozilla, Heroku,
Nike, Twitter, Spotify, Microsoft, Amazon, Lyft, BuzzFeed, Reddit, The NSA, Her Majesty's Government, Google, Twilio, Runscope, Mozilla, Heroku,
PayPal, NPR, Obama for America, Transifex, Native Instruments, The Washington
Post, SoundCloud, Kippt, Sony, and Federal U.S.
Institutions that prefer to be unnamed claim to use Requests internally.
**Armin Ronacher**
**Armin Ronacher**, creator of Flask
*Requests is the perfect example how beautiful an API can be with the
right level of abstraction.*
@@ -74,14 +74,18 @@ Institutions that prefer to be unnamed claim to use Requests internally.
**Daniel Greenfeld**
*Nuked a 1200 LOC spaghetti code library with 10 lines of code thanks to
Kenneth Reitz's request library. Today has been AWESOME.*
Kenneth Reitz's Requests library. Today has been AWESOME.*
**Kenny Meyers**
*Python HTTP: When in doubt, or when not in doubt, use Requests. Beautiful,
simple, Pythonic.*
Requests is one of the most downloaded Python packages of all time, pulling in
over 13,000,000 downloads every month. All the cool kids are doing it!
over 400,000 downloads **each day**. Join the party!
If your organization uses Requests internally, consider `supporting the development of 3.0 <https://www.kennethreitz.org/requests3>`_. Your
generosity will be greatly appreciated, and help drive the project forward
into the future.
Beloved Features
----------------
@@ -104,7 +108,7 @@ Requests is ready for today's web.
- Chunked Requests
- ``.netrc`` Support
Requests officially supports Python 2.62.7 & 3.43.7, and runs great on PyPy.
Requests officially supports Python 2.7 & 3.43.7, and runs great on PyPy.
The User Guide
@@ -133,6 +137,7 @@ Requests ecosystem and community.
.. toctree::
:maxdepth: 2
community/sponsors
community/recommended
community/faq
community/out-there

View File

@@ -196,18 +196,18 @@ As a result an ``SSL: CERTIFICATE_VERIFY_FAILED`` is thrown.
You can get around this behaviour by explicity merging the environment settings into your session::
from requests import Request, Session
s = Session()
req = Request('GET', url)
prepped = s.prepare_request(req)
# Merge environment settings into session
settings = s.merge_environment_settings(prepped.url, None, None, None, None)
resp = s.send(prepped, **settings)
print(resp.status_code)
.. _verification:
SSL Cert Verification
@@ -274,21 +274,20 @@ If you specify a wrong path or an invalid cert, you'll get a SSLError::
CA Certificates
---------------
By default, Requests bundles a set of root CAs that it trusts, sourced from the
`Mozilla trust store`_. However, these are only updated once for each Requests
version. This means that if you pin a Requests version your certificates can
become extremely out of date.
Requests uses certificates from the package `certifi`_. This allows for users
to update their trusted certificates without changing the version of Requests.
From Requests version 2.4.0 onwards, Requests will attempt to use certificates
from `certifi`_ if it is present on the system. This allows for users to update
their trusted certificates without having to change the code that runs on their
system.
Before version 2.16, Requests bundled a set of root CAs that it trusted,
sourced from the `Mozilla trust store`_. The certificates were only updated
once for each Requests version. When ``certifi`` was not installed, this led to
extremely out-of-date certificate bundles when using significantly older
versions of Requests.
For the sake of security we recommend upgrading certifi frequently!
.. _HTTP persistent connection: https://en.wikipedia.org/wiki/HTTP_persistent_connection
.. _connection pooling: http://urllib3.readthedocs.io/en/latest/reference/index.html#module-urllib3.connectionpool
.. _certifi: http://certifi.io/
.. _connection pooling: https://urllib3.readthedocs.io/en/latest/reference/index.html#module-urllib3.connectionpool
.. _certifi: https://certifiio.readthedocs.io/
.. _Mozilla trust store: https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt
.. _body-content-workflow:
@@ -358,7 +357,7 @@ file-like object for your body::
be set to the number of *bytes* in the file. Errors may occur if
you open the file in *text mode*.
.. _binary mode: https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files
.. _binary mode: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
.. _chunk-encoding:
@@ -415,7 +414,7 @@ To do that, just set files to a list of tuples of ``(form_field_name, file_info)
be set to the number of *bytes* in the file. Errors may occur if
you open the file in *text mode*.
.. _binary mode: https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files
.. _binary mode: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
.. _event-hooks:
@@ -436,7 +435,7 @@ You can assign a hook function on a per-request basis by passing a
``{hook_name: callback_function}`` dictionary to the ``hooks`` request
parameter::
hooks=dict(response=print_url)
hooks={'response': print_url}
That ``callback_function`` will receive a chunk of data as its first
argument.
@@ -450,14 +449,38 @@ If an error occurs while executing your callback, a warning is given.
If the callback function returns a value, it is assumed that it is to
replace the data that was passed in. If the function doesn't return
anything, nothing else is effected.
anything, nothing else is affected.
::
def record_hook(r, *args, **kwargs):
r.hook_called = True
return r
Let's print some request method arguments at runtime::
>>> requests.get('http://httpbin.org', hooks=dict(response=print_url))
>>> requests.get('http://httpbin.org', hooks={'response': print_url})
http://httpbin.org
<Response [200]>
You can add multiple hooks to a single request. Let's call two hooks at once::
>>> r = requests.get('http://httpbin.org', hooks={'response': [print_url, record_hook]})
>>> r.hook_called
True
You can also add hooks to a ``Session`` instance. Any hooks you add will then
be called on every request made to the session. For example::
>>> s = requests.Session()
>>> s.hooks['response'].append(print_url)
>>> s.get('http://httpbin.org')
http://httpbin.org
<Response [200]>
A ``Session`` can have multiple hooks, which will be called in the order
they are added.
.. _custom-auth:
Custom Authentication
@@ -633,7 +656,7 @@ When you receive a response, Requests makes a guess at the encoding to
use for decoding the response when you access the :attr:`Response.text
<requests.Response.text>` attribute. Requests will first check for an
encoding in the HTTP header, and if none is present, will use `chardet
<http://pypi.python.org/pypi/chardet>`_ to attempt to guess the encoding.
<https://pypi.org/project/chardet/>`_ to attempt to guess the encoding.
The only time Requests will not do this is if no explicit charset
is present in the HTTP headers **and** the ``Content-Type``
@@ -860,7 +883,7 @@ Link Headers
Many HTTP APIs feature Link headers. They make APIs more self describing and
discoverable.
GitHub uses these for `pagination <http://developer.github.com/v3/#pagination>`_
GitHub uses these for `pagination <https://developer.github.com/v3/#pagination>`_
in their API, for example::
>>> url = 'https://api.github.com/users/kennethreitz/repos?page=1&per_page=10'
@@ -927,9 +950,9 @@ passed-through to `urllib3`. We'll make a Transport Adapter that instructs the
library to use SSLv3::
import ssl
from urllib3.poolmanager import PoolManager
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
class Ssl3HttpAdapter(HTTPAdapter):

View File

@@ -136,11 +136,11 @@ Further examples can be found under the `Requests organization`_ and in the
.. _OAuth: http://oauth.net/
.. _requests_oauthlib: https://github.com/requests/requests-oauthlib
.. _requests-oauthlib OAuth2 documentation: http://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html
.. _Web Application Flow: http://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#web-application-flow
.. _Mobile Application Flow: http://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#mobile-application-flow
.. _Legacy Application Flow: http://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#legacy-application-flow
.. _Backend Application Flow: http://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#backend-application-flow
.. _requests-oauthlib OAuth2 documentation: https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html
.. _Web Application Flow: https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#web-application-flow
.. _Mobile Application Flow: https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#mobile-application-flow
.. _Legacy Application Flow: https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#legacy-application-flow
.. _Backend Application Flow: https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#backend-application-flow
.. _Kerberos: https://github.com/requests/requests-kerberos
.. _NTLM: https://github.com/requests/requests-ntlm
.. _Requests organization: https://github.com/requests

View File

@@ -110,7 +110,7 @@ using, and change it, using the ``r.encoding`` property::
If you change the encoding, Requests will use the new value of ``r.encoding``
whenever you call ``r.text``. You might want to do this in any situation where
you can apply special logic to work out what the encoding of the content will
be. For example, HTTP and XML have the ability to specify their encoding in
be. For example, HTML and XML have the ability to specify their encoding in
their body. In situations like this, you should use ``r.content`` to find the
encoding, and then set ``r.encoding``. This will let you use ``r.text`` with
the correct encoding.
@@ -171,7 +171,7 @@ server, you can access ``r.raw``. If you want to do this, make sure you set
>>> r = requests.get('https://api.github.com/events', stream=True)
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
<urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
@@ -189,6 +189,14 @@ download, the above is the preferred and recommended way to retrieve the
content. Note that ``chunk_size`` can be freely adjusted to a number that
may better fit your use cases.
.. note::
An important note about using ``Response.iter_content`` versus ``Response.raw``.
``Response.iter_content`` will automatically decode the ``gzip`` and ``deflate``
transfer-encodings. ``Response.raw`` is a raw stream of bytes -- it does not
transform the response content. If you really need access to the bytes as they
were returned, use ``Response.raw``.
Custom Headers
--------------
@@ -273,6 +281,9 @@ the ``json`` parameter (added in version 2.4.2) and it will be encoded automatic
>>> r = requests.post(url, json=payload)
Note, the ``json`` parameter is ignored if either ``data`` or ``files`` is passed.
Using the ``json`` parameter in the request will change the ``Content-Type`` in the header to ``application/json``.
POST a Multipart-Encoded File
-----------------------------
@@ -337,7 +348,7 @@ section.
be set to the number of *bytes* in the file. Errors may occur if
you open the file in *text mode*.
.. _binary mode: https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files
.. _binary mode: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
Response Status Codes

View File

@@ -57,10 +57,10 @@ 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.23
assert major == 1
assert minor >= 21
assert minor <= 22
assert minor <= 23
# Check chardet for compatibility.
major, minor, patch = chardet_version.split('.')[:3]

View File

@@ -5,10 +5,10 @@
__title__ = 'requests'
__description__ = 'Python HTTP for Humans.'
__url__ = 'http://python-requests.org'
__version__ = '2.18.4'
__build__ = 0x021804
__version__ = '2.19.1'
__build__ = 0x021901
__author__ = 'Kenneth Reitz'
__author_email__ = 'me@kennethreitz.org'
__license__ = 'Apache 2.0'
__copyright__ = 'Copyright 2017 Kenneth Reitz'
__copyright__ = 'Copyright 2018 Kenneth Reitz'
__cake__ = u'\u2728 \U0001f370 \u2728'

View File

@@ -13,6 +13,7 @@ import socket
from urllib3.poolmanager import PoolManager, proxy_from_url
from urllib3.response import HTTPResponse
from urllib3.util import parse_url
from urllib3.util import Timeout as TimeoutSauce
from urllib3.util.retry import Retry
from urllib3.exceptions import ClosedPoolError
@@ -28,13 +29,13 @@ from urllib3.exceptions import ResponseError
from .models import Response
from .compat import urlparse, basestring
from .utils import (DEFAULT_CA_BUNDLE_PATH, get_encoding_from_headers,
prepend_scheme_if_needed, get_auth_from_url, urldefragauth,
select_proxy)
from .utils import (DEFAULT_CA_BUNDLE_PATH, extract_zipped_paths,
get_encoding_from_headers, prepend_scheme_if_needed,
get_auth_from_url, urldefragauth, select_proxy)
from .structures import CaseInsensitiveDict
from .cookies import extract_cookies_to_jar
from .exceptions import (ConnectionError, ConnectTimeout, ReadTimeout, SSLError,
ProxyError, RetryError, InvalidSchema)
ProxyError, RetryError, InvalidSchema, InvalidProxyURL)
from .auth import _basic_auth_str
try:
@@ -219,7 +220,7 @@ class HTTPAdapter(BaseAdapter):
cert_loc = verify
if not cert_loc:
cert_loc = DEFAULT_CA_BUNDLE_PATH
cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
if not cert_loc or not os.path.exists(cert_loc):
raise IOError("Could not find a suitable TLS CA certificate bundle, "
@@ -300,6 +301,10 @@ class HTTPAdapter(BaseAdapter):
if proxy:
proxy = prepend_scheme_if_needed(proxy, 'http')
proxy_url = parse_url(proxy)
if not proxy_url.host:
raise InvalidProxyURL("Please check proxy URL. It is malformed"
" and could be missing the host.")
proxy_manager = self.proxy_manager_for(proxy)
conn = proxy_manager.connection_from_url(url)
else:
@@ -406,7 +411,7 @@ class HTTPAdapter(BaseAdapter):
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(request)
self.add_headers(request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
chunked = not (request.body is None or 'Content-Length' in request.headers)

View File

@@ -20,7 +20,7 @@ def request(method, url, **kwargs):
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
:param data: (optional) Dictionary or list of tuples ``[(key, value)]`` (will be form-encoded), 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) A JSON serializable Python object to send in the body of the :class:`Request`.
:param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
:param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
:param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.

View File

@@ -153,6 +153,18 @@ class HTTPDigestAuth(AuthBase):
x = x.encode('utf-8')
return hashlib.sha1(x).hexdigest()
hash_utf8 = sha_utf8
elif _algorithm == 'SHA-256':
def sha256_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
return hashlib.sha256(x).hexdigest()
hash_utf8 = sha256_utf8
elif _algorithm == 'SHA-512':
def sha512_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
return hashlib.sha512(x).hexdigest()
hash_utf8 = sha512_utf8
KD = lambda s, d: hash_utf8("%s:%s" % (s, d))

View File

@@ -43,6 +43,7 @@ if is_py2:
import cookielib
from Cookie import Morsel
from StringIO import StringIO
from collections import Callable, Mapping, MutableMapping
from urllib3.packages.ordered_dict import OrderedDict
@@ -60,6 +61,7 @@ elif is_py3:
from http.cookies import Morsel
from io import StringIO
from collections import OrderedDict
from collections.abc import Callable, Mapping, MutableMapping
builtin_str = str
str = str

View File

@@ -12,10 +12,9 @@ requests.utils imports from here, so be careful with imports.
import copy
import time
import calendar
import collections
from ._internal_utils import to_native_string
from .compat import cookielib, urlparse, urlunparse, Morsel
from .compat import cookielib, urlparse, urlunparse, Morsel, MutableMapping
try:
import threading
@@ -169,7 +168,7 @@ class CookieConflictError(RuntimeError):
"""
class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
class RequestsCookieJar(cookielib.CookieJar, MutableMapping):
"""Compatibility class; is a cookielib.CookieJar, but exposes a dict
interface.
@@ -415,9 +414,14 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
def copy(self):
"""Return a copy of this RequestsCookieJar."""
new_cj = RequestsCookieJar()
new_cj.set_policy(self.get_policy())
new_cj.update(self)
return new_cj
def get_policy(self):
"""Return the CookiePolicy instance used."""
return self._policy
def _copy_cookie_jar(jar):
if jar is None:

View File

@@ -85,6 +85,10 @@ class InvalidHeader(RequestException, ValueError):
"""The header value provided was somehow invalid."""
class InvalidProxyURL(InvalidURL):
"""The proxy URL provided is invalid."""
class ChunkedEncodingError(RequestException):
"""The server declared chunked encoding but sent an invalid chunk."""

View File

@@ -13,7 +13,7 @@ import chardet
from . import __version__ as requests_version
try:
from .packages.urllib3.contrib import pyopenssl
from urllib3.contrib import pyopenssl
except ImportError:
pyopenssl = None
OpenSSL = None

View File

@@ -7,7 +7,6 @@ requests.models
This module contains the primary objects that power Requests.
"""
import collections
import datetime
import sys
@@ -37,6 +36,7 @@ from .utils import (
stream_decode_response_unicode, to_key_val_list, parse_header_links,
iter_slices, guess_json_utf, super_len, check_header_validity)
from .compat import (
Callable, Mapping,
cookielib, urlunparse, urlsplit, urlencode, str, bytes,
is_py2, chardet, builtin_str, basestring)
from .compat import json as complexjson
@@ -155,8 +155,12 @@ class RequestEncodingMixin(object):
if isinstance(fp, (str, bytes, bytearray)):
fdata = fp
else:
elif hasattr(fp, 'read'):
fdata = fp.read()
elif fp is None:
continue
else:
fdata = fp
rf = RequestField(name=k, data=fdata, filename=fn, headers=fh)
rf.make_multipart(content_type=ft)
@@ -174,10 +178,10 @@ class RequestHooksMixin(object):
if event not in self.hooks:
raise ValueError('Unsupported event specified, with event name "%s"' % (event))
if isinstance(hook, collections.Callable):
if isinstance(hook, Callable):
self.hooks[event].append(hook)
elif hasattr(hook, '__iter__'):
self.hooks[event].extend(h for h in hook if isinstance(h, collections.Callable))
self.hooks[event].extend(h for h in hook if isinstance(h, Callable))
def deregister_hook(self, event, hook):
"""Deregister a previously registered hook.
@@ -461,7 +465,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
is_stream = all([
hasattr(data, '__iter__'),
not isinstance(data, (basestring, list, tuple, collections.Mapping))
not isinstance(data, (basestring, list, tuple, Mapping))
])
try:
@@ -686,11 +690,11 @@ class Response(object):
@property
def ok(self):
"""Returns True if :attr:`status_code` is less than 400.
"""Returns True if :attr:`status_code` is less than 400, False if not.
This attribute checks if the status code of the response is between
400 and 600 to see if there was a client error or a server error. If
the status code, is between 200 and 400, this will return True. This
the status code is between 200 and 400, this will return True. This
is **not** a check to see if the response code is ``200 OK``.
"""
try:
@@ -820,7 +824,7 @@ class Response(object):
if self.status_code == 0 or self.raw is None:
self._content = None
else:
self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes()
self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b''
self._content_consumed = True
# don't need to release the connection; that's been handled by urllib3

View File

@@ -8,13 +8,12 @@ This module provides a Session object to manage and persist settings across
requests (cookies, auth, proxies).
"""
import os
import platform
import sys
import time
from collections import Mapping
from datetime import timedelta
from .auth import _basic_auth_str
from .compat import cookielib, is_py3, OrderedDict, urljoin, urlparse
from .compat import cookielib, is_py3, OrderedDict, urljoin, urlparse, Mapping
from .cookies import (
cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies)
from .models import Request, PreparedRequest, DEFAULT_REDIRECT_LIMIT
@@ -38,7 +37,7 @@ from .status_codes import codes
from .models import REDIRECT_STATI
# Preferred clock, based on which one is more accurate on a given system.
if platform.system() == 'Windows':
if sys.platform == 'win32':
try: # Python 3.4+
preferred_clock = time.perf_counter
except AttributeError: # Earlier than Python 3.
@@ -123,6 +122,7 @@ class SessionRedirectMixin(object):
hist = [] # keep track of history
url = self.get_redirect_target(resp)
previous_fragment = urlparse(req.url).fragment
while url:
prepared_request = req.copy()
@@ -147,8 +147,12 @@ class SessionRedirectMixin(object):
parsed_rurl = urlparse(resp.url)
url = '%s:%s' % (to_native_string(parsed_rurl.scheme), url)
# The scheme should be lower case...
# Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2)
parsed = urlparse(url)
if parsed.fragment == '' and previous_fragment:
parsed = parsed._replace(fragment=previous_fragment)
elif parsed.fragment:
previous_fragment = parsed.fragment
url = parsed.geturl()
# Facilitate relative 'location' headers, as allowed by RFC 7231.
@@ -696,7 +700,7 @@ class Session(SessionRedirectMixin):
"""
for (prefix, adapter) in self.adapters.items():
if url.lower().startswith(prefix):
if url.lower().startswith(prefix.lower()):
return adapter
# Nothing matches :-/

View File

@@ -1,5 +1,22 @@
# -*- coding: utf-8 -*-
"""
The ``codes`` object defines a mapping from common names for HTTP statuses
to their numerical codes, accessible either as attributes or as dictionary
items.
>>> requests.codes['temporary_redirect']
307
>>> requests.codes.teapot
418
>>> requests.codes['\o/']
200
Some codes have multiple names, and both upper- and lower-case versions of
the names are allowed. For example, ``codes.ok``, ``codes.OK``, and
``codes.okay`` all correspond to the HTTP status code 200.
"""
from .structures import LookupDict
_codes = {
@@ -84,8 +101,20 @@ _codes = {
codes = LookupDict(name='status_codes')
for code, titles in _codes.items():
for title in titles:
setattr(codes, title, code)
if not title.startswith(('\\', '/')):
setattr(codes, title.upper(), code)
def _init():
for code, titles in _codes.items():
for title in titles:
setattr(codes, title, code)
if not title.startswith(('\\', '/')):
setattr(codes, title.upper(), code)
def doc(code):
names = ', '.join('``%s``' % n for n in _codes[code])
return '* %d: %s' % (code, names)
global __doc__
__doc__ = (__doc__ + '\n' +
'\n'.join(doc(code) for code in sorted(_codes))
if __doc__ is not None else None)
_init()

View File

@@ -7,16 +7,14 @@ requests.structures
Data structures that power Requests.
"""
import collections
from .compat import OrderedDict
from .compat import OrderedDict, Mapping, MutableMapping
class CaseInsensitiveDict(collections.MutableMapping):
class CaseInsensitiveDict(MutableMapping):
"""A case-insensitive ``dict``-like object.
Implements all methods and operations of
``collections.MutableMapping`` as well as dict's ``copy``. Also
``MutableMapping`` as well as dict's ``copy``. Also
provides ``lower_items``.
All keys are expected to be strings. The structure remembers the
@@ -71,7 +69,7 @@ class CaseInsensitiveDict(collections.MutableMapping):
)
def __eq__(self, other):
if isinstance(other, collections.Mapping):
if isinstance(other, Mapping):
other = CaseInsensitiveDict(other)
else:
return NotImplemented

View File

@@ -8,17 +8,17 @@ This module provides utility functions that are used within Requests
that are also useful for external consumption.
"""
import cgi
import codecs
import collections
import contextlib
import io
import os
import platform
import re
import socket
import struct
import sys
import tempfile
import warnings
import zipfile
from .__version__ import __version__
from . import certs
@@ -28,7 +28,7 @@ from .compat import parse_http_list as _parse_list_header
from .compat import (
quote, urlparse, bytes, str, OrderedDict, unquote, getproxies,
proxy_bypass, urlunparse, basestring, integer_types, is_py3,
proxy_bypass_environment, getproxies_environment)
proxy_bypass_environment, getproxies_environment, Mapping)
from .cookies import cookiejar_from_dict
from .structures import CaseInsensitiveDict
from .exceptions import (
@@ -39,19 +39,25 @@ NETRC_FILES = ('.netrc', '_netrc')
DEFAULT_CA_BUNDLE_PATH = certs.where()
if platform.system() == 'Windows':
if sys.platform == 'win32':
# provide a proxy_bypass version on Windows without DNS lookups
def proxy_bypass_registry(host):
if is_py3:
import winreg
else:
import _winreg as winreg
try:
if is_py3:
import winreg
else:
import _winreg as winreg
except ImportError:
return False
try:
internetSettings = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r'Software\Microsoft\Windows\CurrentVersion\Internet Settings')
proxyEnable = winreg.QueryValueEx(internetSettings,
'ProxyEnable')[0]
# ProxyEnable could be REG_SZ or REG_DWORD, normalizing it
proxyEnable = int(winreg.QueryValueEx(internetSettings,
'ProxyEnable')[0])
# ProxyOverride is almost always a string
proxyOverride = winreg.QueryValueEx(internetSettings,
'ProxyOverride')[0]
except OSError:
@@ -216,6 +222,38 @@ def guess_filename(obj):
return os.path.basename(name)
def extract_zipped_paths(path):
"""Replace nonexistent paths that look like they refer to a member of a zip
archive with the location of an extracted copy of the target, or else
just return the provided path unchanged.
"""
if os.path.exists(path):
# this is already a valid path, no need to do anything further
return path
# find the first valid part of the provided path and treat that as a zip archive
# assume the rest of the path is the name of a member in the archive
archive, member = os.path.split(path)
while archive and not os.path.exists(archive):
archive, prefix = os.path.split(archive)
member = '/'.join([prefix, member])
if not zipfile.is_zipfile(archive):
return path
zip_file = zipfile.ZipFile(archive)
if member not in zip_file.namelist():
return path
# we have a valid zip archive and a valid member of that archive
tmp = tempfile.gettempdir()
extracted_path = os.path.join(tmp, *member.split('/'))
if not os.path.exists(extracted_path):
extracted_path = zip_file.extract(member, path=tmp)
return extracted_path
def from_key_val_list(value):
"""Take an object and test to see if it can be represented as a
dictionary. Unless it can not be represented as such, return an
@@ -262,7 +300,7 @@ def to_key_val_list(value):
if isinstance(value, (str, bytes, bool, int)):
raise ValueError('cannot encode objects that are not 2-tuples')
if isinstance(value, collections.Mapping):
if isinstance(value, Mapping):
value = value.items()
return list(value)
@@ -407,6 +445,31 @@ def get_encodings_from_content(content):
xml_re.findall(content))
def _parse_content_type_header(header):
"""Returns content type and parameters from given header
:param header: string
:return: tuple containing content type and dictionary of
parameters
"""
tokens = header.split(';')
content_type, params = tokens[0].strip(), tokens[1:]
params_dict = {}
items_to_strip = "\"' "
for param in params:
param = param.strip()
if param:
key, value = param, True
index_of_equals = param.find("=")
if index_of_equals != -1:
key = param[:index_of_equals].strip(items_to_strip)
value = param[index_of_equals + 1:].strip(items_to_strip)
params_dict[key] = value
return content_type, params_dict
def get_encoding_from_headers(headers):
"""Returns encodings from given HTTP Header Dict.
@@ -419,7 +482,7 @@ def get_encoding_from_headers(headers):
if not content_type:
return None
content_type, params = cgi.parse_header(content_type)
content_type, params = _parse_content_type_header(content_type)
if 'charset' in params:
return params['charset'].strip("'\"")
@@ -632,6 +695,8 @@ def should_bypass_proxies(url, no_proxy):
:rtype: bool
"""
# Prioritize lowercase environment variables over uppercase
# to keep a consistent behaviour with other http projects (curl, wget).
get_proxy = lambda k: os.environ.get(k) or os.environ.get(k.upper())
# First check whether no_proxy is defined. If it is, check that the URL
@@ -639,28 +704,31 @@ def should_bypass_proxies(url, no_proxy):
no_proxy_arg = no_proxy
if no_proxy is None:
no_proxy = get_proxy('no_proxy')
netloc = urlparse(url).netloc
parsed = urlparse(url)
if no_proxy:
# We need to check whether we match here. We need to see if we match
# the end of the netloc, both with and without the port.
# the end of the hostname, both with and without the port.
no_proxy = (
host for host in no_proxy.replace(' ', '').split(',') if host
)
ip = netloc.split(':')[0]
if is_ipv4_address(ip):
if is_ipv4_address(parsed.hostname):
for proxy_ip in no_proxy:
if is_valid_cidr(proxy_ip):
if address_in_network(ip, proxy_ip):
if address_in_network(parsed.hostname, proxy_ip):
return True
elif ip == proxy_ip:
elif parsed.hostname == proxy_ip:
# If no_proxy ip was defined in plain IP notation instead of cidr notation &
# matches the IP of the index
return True
else:
host_with_port = parsed.hostname
if parsed.port:
host_with_port += ':{0}'.format(parsed.port)
for host in no_proxy:
if netloc.endswith(host) or netloc.split(':')[0].endswith(host):
if parsed.hostname.endswith(host) or host_with_port.endswith(host):
# The URL does match something in no_proxy, so we don't want
# to apply the proxies on this URL.
return True
@@ -673,7 +741,7 @@ def should_bypass_proxies(url, no_proxy):
# legitimate problems.
with set_environ('no_proxy', no_proxy_arg):
try:
bypass = proxy_bypass(netloc)
bypass = proxy_bypass(parsed.hostname)
except (TypeError, socket.gaierror):
bypass = False

View File

@@ -1,2 +1,5 @@
[bdist_wheel]
universal = 1
[metadata]
license_file = LICENSE

View File

@@ -40,12 +40,18 @@ if sys.argv[-1] == 'publish':
os.system('twine upload dist/*')
sys.exit()
# pyOpenSSL version 18.0.0 dropped support for Python 2.6
if sys.version_info < (2, 7):
PYOPENSSL_VERSION = 'pyOpenSSL >= 0.14, < 18.0.0'
else:
PYOPENSSL_VERSION = 'pyOpenSSL >= 0.14'
packages = ['requests']
requires = [
'chardet>=3.0.2,<3.1.0',
'idna>=2.5,<2.7',
'urllib3>=1.21.1,<1.23',
'idna>=2.5,<2.8',
'urllib3>=1.21.1,<1.24',
'certifi>=2017.4.17'
]
@@ -65,6 +71,7 @@ setup(
version=about['__version__'],
description=about['__description__'],
long_description=readme + '\n\n' + history,
long_description_content_type='text/x-rst',
author=about['__author__'],
author_email=about['__author_email__'],
url=about['__url__'],
@@ -72,6 +79,7 @@ setup(
package_data={'': ['LICENSE', 'NOTICE'], 'requests': ['*.pem']},
package_dir={'requests': 'requests'},
include_package_data=True,
python_requires=">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
install_requires=requires,
license=about['__license__'],
zip_safe=False,
@@ -81,7 +89,7 @@ setup(
'Natural Language :: English',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
@@ -93,9 +101,8 @@ setup(
cmdclass={'test': PyTest},
tests_require=test_requirements,
extras_require={
'security': ['pyOpenSSL>=0.14', 'cryptography>=1.3.4', 'idna>=2.0.0'],
'security': [PYOPENSSL_VERSION, 'cryptography>=1.3.4', 'idna>=2.0.0'],
'socks': ['PySocks>=1.5.6, !=1.5.7'],
'socks:sys_platform == "win32" and (python_version == "2.7" or python_version == "2.6")': ['win_inet_pton'],
},
)

View File

@@ -235,3 +235,75 @@ def test_redirect_rfc1808_to_non_ascii_location():
assert r.url == u'{0}/{1}'.format(url, expected_path.decode('ascii'))
close_server.set()
def test_fragment_not_sent_with_request():
"""Verify that the fragment portion of a URI isn't sent to the server."""
def response_handler(sock):
req = consume_socket_content(sock, timeout=0.5)
sock.send(
b'HTTP/1.1 200 OK\r\n'
b'Content-Length: '+bytes(len(req))+b'\r\n'
b'\r\n'+req
)
close_server = threading.Event()
server = Server(response_handler, wait_to_close_event=close_server)
with server as (host, port):
url = 'http://{0}:{1}/path/to/thing/#view=edit&token=hunter2'.format(host, port)
r = requests.get(url)
raw_request = r.content
assert r.status_code == 200
headers, body = raw_request.split(b'\r\n\r\n', 1)
status_line, headers = headers.split(b'\r\n', 1)
assert status_line == b'GET /path/to/thing/ HTTP/1.1'
for frag in (b'view', b'edit', b'token', b'hunter2'):
assert frag not in headers
assert frag not in body
close_server.set()
def test_fragment_update_on_redirect():
"""Verify we only append previous fragment if one doesn't exist on new
location. If a new fragment is encounterd in a Location header, it should
be added to all subsequent requests.
"""
def response_handler(sock):
consume_socket_content(sock, timeout=0.5)
sock.send(
b'HTTP/1.1 302 FOUND\r\n'
b'Content-Length: 0\r\n'
b'Location: /get#relevant-section\r\n\r\n'
)
consume_socket_content(sock, timeout=0.5)
sock.send(
b'HTTP/1.1 302 FOUND\r\n'
b'Content-Length: 0\r\n'
b'Location: /final-url/\r\n\r\n'
)
consume_socket_content(sock, timeout=0.5)
sock.send(
b'HTTP/1.1 200 OK\r\n\r\n'
)
close_server = threading.Event()
server = Server(response_handler, wait_to_close_event=close_server)
with server as (host, port):
url = 'http://{0}:{1}/path/to/thing/#view=edit&token=hunter2'.format(host, port)
r = requests.get(url)
raw_request = r.content
assert r.status_code == 200
assert len(r.history) == 2
assert r.history[0].request.url == url
# Verify we haven't overwritten the location with our previous fragment.
assert r.history[1].request.url == 'http://{0}:{1}/get#relevant-section'.format(host, port)
# Verify previous fragment is used and not the original.
assert r.url == 'http://{0}:{1}/final-url/#relevant-section'.format(host, port)
close_server.set()

View File

@@ -23,12 +23,13 @@ from requests.cookies import (
from requests.exceptions import (
ConnectionError, ConnectTimeout, InvalidSchema, InvalidURL,
MissingSchema, ReadTimeout, Timeout, RetryError, TooManyRedirects,
ProxyError, InvalidHeader, UnrewindableBodyError, SSLError)
ProxyError, InvalidHeader, UnrewindableBodyError, SSLError, InvalidProxyURL)
from requests.models import PreparedRequest
from requests.structures import CaseInsensitiveDict
from requests.sessions import SessionRedirectMixin
from requests.models import urlencode
from requests.hooks import default_hooks
from requests.compat import MutableMapping
from .compat import StringIO, u
from .utils import override_environ
@@ -54,6 +55,8 @@ except AttributeError:
class TestRequests:
digest_auth_algo = ('MD5', 'SHA-256', 'SHA-512')
def test_entry_points(self):
requests.session
@@ -294,6 +297,14 @@ class TestRequests:
for header in purged_headers:
assert header not in next_resp.request.headers
def test_fragment_maintained_on_redirect(self, httpbin):
fragment = "#view=edit&token=hunter2"
r = requests.get(httpbin('redirect-to?url=get')+fragment)
assert len(r.history) > 0
assert r.history[0].request.url == httpbin('redirect-to?url=get')+fragment
assert r.url == httpbin('get')+fragment
def test_HTTP_200_OK_GET_WITH_PARAMS(self, httpbin):
heads = {'User-agent': 'Mozilla/5.0'}
@@ -526,6 +537,19 @@ class TestRequests:
with pytest.raises(ProxyError):
requests.get('http://localhost:1', proxies={'http': 'non-resolvable-address'})
def test_proxy_error_on_bad_url(self, httpbin, httpbin_secure):
with pytest.raises(InvalidProxyURL):
requests.get(httpbin_secure(), proxies={'https': 'http:/badproxyurl:3128'})
with pytest.raises(InvalidProxyURL):
requests.get(httpbin(), proxies={'http': 'http://:8080'})
with pytest.raises(InvalidProxyURL):
requests.get(httpbin_secure(), proxies={'https': 'https://'})
with pytest.raises(InvalidProxyURL):
requests.get(httpbin(), proxies={'http': 'http:///example.com:8080'})
def test_basicauth_with_netrc(self, httpbin):
auth = ('user', 'pass')
wrong_auth = ('wronguser', 'wrongpass')
@@ -561,70 +585,79 @@ class TestRequests:
def test_DIGEST_HTTP_200_OK_GET(self, httpbin):
auth = HTTPDigestAuth('user', 'pass')
url = httpbin('digest-auth', 'auth', 'user', 'pass')
for authtype in self.digest_auth_algo:
auth = HTTPDigestAuth('user', 'pass')
url = httpbin('digest-auth', 'auth', 'user', 'pass', authtype, 'never')
r = requests.get(url, auth=auth)
assert r.status_code == 200
r = requests.get(url, auth=auth)
assert r.status_code == 200
r = requests.get(url)
assert r.status_code == 401
r = requests.get(url)
assert r.status_code == 401
print(r.headers['WWW-Authenticate'])
s = requests.session()
s.auth = HTTPDigestAuth('user', 'pass')
r = s.get(url)
assert r.status_code == 200
s = requests.session()
s.auth = HTTPDigestAuth('user', 'pass')
r = s.get(url)
assert r.status_code == 200
def test_DIGEST_AUTH_RETURNS_COOKIE(self, httpbin):
url = httpbin('digest-auth', 'auth', 'user', 'pass')
auth = HTTPDigestAuth('user', 'pass')
r = requests.get(url)
assert r.cookies['fake'] == 'fake_value'
r = requests.get(url, auth=auth)
assert r.status_code == 200
for authtype in self.digest_auth_algo:
url = httpbin('digest-auth', 'auth', 'user', 'pass', authtype)
auth = HTTPDigestAuth('user', 'pass')
r = requests.get(url)
assert r.cookies['fake'] == 'fake_value'
r = requests.get(url, auth=auth)
assert r.status_code == 200
def test_DIGEST_AUTH_SETS_SESSION_COOKIES(self, httpbin):
url = httpbin('digest-auth', 'auth', 'user', 'pass')
auth = HTTPDigestAuth('user', 'pass')
s = requests.Session()
s.get(url, auth=auth)
assert s.cookies['fake'] == 'fake_value'
for authtype in self.digest_auth_algo:
url = httpbin('digest-auth', 'auth', 'user', 'pass', authtype)
auth = HTTPDigestAuth('user', 'pass')
s = requests.Session()
s.get(url, auth=auth)
assert s.cookies['fake'] == 'fake_value'
def test_DIGEST_STREAM(self, httpbin):
auth = HTTPDigestAuth('user', 'pass')
url = httpbin('digest-auth', 'auth', 'user', 'pass')
for authtype in self.digest_auth_algo:
auth = HTTPDigestAuth('user', 'pass')
url = httpbin('digest-auth', 'auth', 'user', 'pass', authtype)
r = requests.get(url, auth=auth, stream=True)
assert r.raw.read() != b''
r = requests.get(url, auth=auth, stream=True)
assert r.raw.read() != b''
r = requests.get(url, auth=auth, stream=False)
assert r.raw.read() == b''
r = requests.get(url, auth=auth, stream=False)
assert r.raw.read() == b''
def test_DIGESTAUTH_WRONG_HTTP_401_GET(self, httpbin):
auth = HTTPDigestAuth('user', 'wrongpass')
url = httpbin('digest-auth', 'auth', 'user', 'pass')
for authtype in self.digest_auth_algo:
auth = HTTPDigestAuth('user', 'wrongpass')
url = httpbin('digest-auth', 'auth', 'user', 'pass', authtype)
r = requests.get(url, auth=auth)
assert r.status_code == 401
r = requests.get(url, auth=auth)
assert r.status_code == 401
r = requests.get(url)
assert r.status_code == 401
r = requests.get(url)
assert r.status_code == 401
s = requests.session()
s.auth = auth
r = s.get(url)
assert r.status_code == 401
s = requests.session()
s.auth = auth
r = s.get(url)
assert r.status_code == 401
def test_DIGESTAUTH_QUOTES_QOP_VALUE(self, httpbin):
auth = HTTPDigestAuth('user', 'pass')
url = httpbin('digest-auth', 'auth', 'user', 'pass')
for authtype in self.digest_auth_algo:
auth = HTTPDigestAuth('user', 'pass')
url = httpbin('digest-auth', 'auth', 'user', 'pass', authtype)
r = requests.get(url, auth=auth)
assert '"auth"' in r.request.headers['Authorization']
r = requests.get(url, auth=auth)
assert '"auth"' in r.request.headers['Authorization']
def test_POSTBIN_GET_POST_FILES(self, httpbin):
@@ -644,6 +677,14 @@ class TestRequests:
with pytest.raises(ValueError):
requests.post(url, files=['bad file data'])
def test_invalid_files_input(self, httpbin):
url = httpbin('post')
post = requests.post(url,
files={"random-file-1": None, "random-file-2": 1})
assert b'name="random-file-1"' not in post.request.body
assert b'name="random-file-2"' in post.request.body
def test_POSTBIN_SEEKED_OBJECT_WITH_NO_ITER(self, httpbin):
class TestStream(object):
@@ -705,7 +746,7 @@ class TestRequests:
requests.post(url, files=['bad file data'])
def test_post_with_custom_mapping(self, httpbin):
class CustomMapping(collections.MutableMapping):
class CustomMapping(MutableMapping):
def __init__(self, *args, **kwargs):
self.data = dict(*args, **kwargs)
@@ -1131,6 +1172,14 @@ class TestRequests:
with pytest.raises(requests.cookies.CookieConflictError):
jar.get(key)
def test_cookie_policy_copy(self):
class MyCookiePolicy(cookielib.DefaultCookiePolicy):
pass
jar = requests.cookies.RequestsCookieJar()
jar.set_policy(MyCookiePolicy())
assert isinstance(jar.copy().get_policy(), MyCookiePolicy)
def test_time_elapsed_blank(self, httpbin):
r = requests.get(httpbin('get'))
td = r.elapsed
@@ -1351,6 +1400,44 @@ class TestRequests:
assert 'http://' in s2.adapters
assert 'https://' in s2.adapters
def test_session_get_adapter_prefix_matching(self, httpbin):
prefix = 'https://example.com'
more_specific_prefix = prefix + '/some/path'
url_matching_only_prefix = prefix + '/another/path'
url_matching_more_specific_prefix = more_specific_prefix + '/longer/path'
url_not_matching_prefix = 'https://another.example.com/'
s = requests.Session()
prefix_adapter = HTTPAdapter()
more_specific_prefix_adapter = HTTPAdapter()
s.mount(prefix, prefix_adapter)
s.mount(more_specific_prefix, more_specific_prefix_adapter)
assert s.get_adapter(url_matching_only_prefix) is prefix_adapter
assert s.get_adapter(url_matching_more_specific_prefix) is more_specific_prefix_adapter
assert s.get_adapter(url_not_matching_prefix) not in (prefix_adapter, more_specific_prefix_adapter)
def test_session_get_adapter_prefix_matching_mixed_case(self, httpbin):
mixed_case_prefix = 'hTtPs://eXamPle.CoM/MixEd_CAse_PREfix'
url_matching_prefix = mixed_case_prefix + '/full_url'
s = requests.Session()
my_adapter = HTTPAdapter()
s.mount(mixed_case_prefix, my_adapter)
assert s.get_adapter(url_matching_prefix) is my_adapter
def test_session_get_adapter_prefix_matching_is_case_insensitive(self, httpbin):
mixed_case_prefix = 'hTtPs://eXamPle.CoM/MixEd_CAse_PREfix'
url_matching_prefix_with_different_case = 'HtTpS://exaMPLe.cOm/MiXeD_caSE_preFIX/another_url'
s = requests.Session()
my_adapter = HTTPAdapter()
s.mount(mixed_case_prefix, my_adapter)
assert s.get_adapter(url_matching_prefix_with_different_case) is my_adapter
def test_header_remove_is_case_insensitive(self, httpbin):
# From issue #1321
s = requests.Session()

View File

@@ -2,15 +2,18 @@
import os
import copy
import filecmp
from io import BytesIO
import zipfile
from collections import deque
import pytest
from requests import compat
from requests.cookies import RequestsCookieJar
from requests.structures import CaseInsensitiveDict
from requests.utils import (
address_in_network, dotted_netmask,
get_auth_from_url, get_encoding_from_headers,
address_in_network, dotted_netmask, extract_zipped_paths,
get_auth_from_url, _parse_content_type_header, get_encoding_from_headers,
get_encodings_from_content, get_environ_proxies,
guess_filename, guess_json_utf, is_ipv4_address,
is_valid_cidr, iter_slices, parse_dict_header,
@@ -256,6 +259,32 @@ class TestGuessFilename:
assert isinstance(result, expected_type)
class TestExtractZippedPaths:
@pytest.mark.parametrize(
'path', (
'/',
__file__,
pytest.__file__,
'/etc/invalid/location',
))
def test_unzipped_paths_unchanged(self, path):
assert path == extract_zipped_paths(path)
def test_zipped_paths_extracted(self, tmpdir):
zipped_py = tmpdir.join('test.zip')
with zipfile.ZipFile(zipped_py.strpath, 'w') as f:
f.write(__file__)
_, name = os.path.splitdrive(__file__)
zipped_path = os.path.join(zipped_py.strpath, name.lstrip(r'\/'))
extracted_path = extract_zipped_paths(zipped_path)
assert extracted_path != zipped_path
assert os.path.exists(extracted_path)
assert filecmp.cmp(extracted_path, __file__)
class TestContentEncodingDetection:
def test_none(self):
@@ -441,6 +470,45 @@ def test_parse_dict_header(value, expected):
assert parse_dict_header(value) == expected
@pytest.mark.parametrize(
'value, expected', (
(
'application/xml',
('application/xml', {})
),
(
'application/json ; charset=utf-8',
('application/json', {'charset': 'utf-8'})
),
(
'text/plain',
('text/plain', {})
),
(
'multipart/form-data; boundary = something ; boundary2=\'something_else\' ; no_equals ',
('multipart/form-data', {'boundary': 'something', 'boundary2': 'something_else', 'no_equals': True})
),
(
'multipart/form-data; boundary = something ; boundary2="something_else" ; no_equals ',
('multipart/form-data', {'boundary': 'something', 'boundary2': 'something_else', 'no_equals': True})
),
(
'multipart/form-data; boundary = something ; \'boundary2=something_else\' ; no_equals ',
('multipart/form-data', {'boundary': 'something', 'boundary2': 'something_else', 'no_equals': True})
),
(
'multipart/form-data; boundary = something ; "boundary2=something_else" ; no_equals ',
('multipart/form-data', {'boundary': 'something', 'boundary2': 'something_else', 'no_equals': True})
),
(
'application/json ; ; ',
('application/json', {})
)
))
def test__parse_content_type_header(value, expected):
assert _parse_content_type_header(value) == expected
@pytest.mark.parametrize(
'value, expected', (
(
@@ -546,6 +614,7 @@ def test_urldefragauth(url, expected):
('http://172.16.1.1/', True),
('http://172.16.1.1:5000/', True),
('http://localhost.localdomain:5000/v1.0/', True),
('http://google.com:6000/', True),
('http://172.16.1.12/', False),
('http://172.16.1.12:5000/', False),
('http://google.com:5000/v1.0/', False),
@@ -554,11 +623,31 @@ def test_should_bypass_proxies(url, expected, monkeypatch):
"""Tests for function should_bypass_proxies to check if proxy
can be bypassed or not
"""
monkeypatch.setenv('no_proxy', '192.168.0.0/24,127.0.0.1,localhost.localdomain,172.16.1.1')
monkeypatch.setenv('NO_PROXY', '192.168.0.0/24,127.0.0.1,localhost.localdomain,172.16.1.1')
monkeypatch.setenv('no_proxy', '192.168.0.0/24,127.0.0.1,localhost.localdomain,172.16.1.1, google.com:6000')
monkeypatch.setenv('NO_PROXY', '192.168.0.0/24,127.0.0.1,localhost.localdomain,172.16.1.1, google.com:6000')
assert should_bypass_proxies(url, no_proxy=None) == expected
@pytest.mark.parametrize(
'url, expected', (
('http://172.16.1.1/', '172.16.1.1'),
('http://172.16.1.1:5000/', '172.16.1.1'),
('http://user:pass@172.16.1.1', '172.16.1.1'),
('http://user:pass@172.16.1.1:5000', '172.16.1.1'),
('http://hostname/', 'hostname'),
('http://hostname:5000/', 'hostname'),
('http://user:pass@hostname', 'hostname'),
('http://user:pass@hostname:5000', 'hostname'),
))
def test_should_bypass_proxies_pass_only_hostname(url, expected, mocker):
"""The proxy_bypass function should be called with a hostname or IP without
a port number or auth credentials.
"""
proxy_bypass = mocker.patch('requests.utils.proxy_bypass')
should_bypass_proxies(url, no_proxy=None)
proxy_bypass.assert_called_once_with(expected)
@pytest.mark.parametrize(
'cookiejar', (
compat.cookielib.CookieJar(),
@@ -638,6 +727,7 @@ def test_should_bypass_proxies_win_registry(url, expected, override,
pass
ie_settings = RegHandle()
proxyEnableValues = deque([1, "1"])
def OpenKey(key, subkey):
return ie_settings
@@ -645,7 +735,9 @@ def test_should_bypass_proxies_win_registry(url, expected, override,
def QueryValueEx(key, value_name):
if key is ie_settings:
if value_name == 'ProxyEnable':
return [1]
# this could be a string (REG_SZ) or a 32-bit number (REG_DWORD)
proxyEnableValues.rotate()
return [proxyEnableValues[0]]
elif value_name == 'ProxyOverride':
return [override]
@@ -656,6 +748,7 @@ def test_should_bypass_proxies_win_registry(url, expected, override,
monkeypatch.setenv('NO_PROXY', '')
monkeypatch.setattr(winreg, 'OpenKey', OpenKey)
monkeypatch.setattr(winreg, 'QueryValueEx', QueryValueEx)
assert should_bypass_proxies(url, None) == expected
@pytest.mark.parametrize(

View File

@@ -1,8 +1,8 @@
[tox]
envlist = py26,py27,py33,py34,py35,py36
envlist = py26,py27,py34,py35,py36
[testenv]
commands =
pip install -e .[socks]
python setup.py test
python setup.py test