diff --git a/.gitignore b/.gitignore index cd0c32e95c..dd9e006f35 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,12 @@ requests.egg-info/ *.swp *.egg env/ +.venv/ +.eggs/ +.tox/ +.pytest_cache/ +.vscode/ +.eggs/ .workon diff --git a/.travis.yml b/.travis.yml index efb75ddec2..03c64b62af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,42 +1,22 @@ -sudo: false language: python # command to install dependencies install: "make" # command to run tests script: - - | - if [[ "$TRAVIS_PYTHON_VERSION" != "2.6" ]] ; then make test-readme; fi + - make test-readme - make ci cache: pip jobs: include: - stage: test - script: - - make test-readme - - make ci python: '2.7' - stage: test - script: - - make test-readme - - make ci - python: '3.4' - - stage: test - script: - - make test-readme - - make ci python: '3.5' - stage: test - script: - - make test-readme - - make ci python: '3.6' - stage: test - script: - - make test-readme - - make ci python: '3.7' - dist: xenial - sudo: true + dist: xenial - stage: coverage - python: 3.6 + python: '3.6' script: codecov diff --git a/AUTHORS.rst b/AUTHORS.rst index f0ee696b25..607f65e15e 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -189,3 +189,7 @@ Patches and Suggestions - Darren Dormer (`@ddormer `_) - Rajiv Mayani (`@mayani `_) - Antti Kaihola (`@akaihola `_) +- "Dull Bananas" (`@dullbananas `_) +- Alessio Izzo (`@aless10 `_) +- Belavin Denis (`@luckydenis `_) +- Dull Bananas (`@dullbananas `_) diff --git a/HISTORY.md b/HISTORY.md index 1d0bd07309..62c254f5e5 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,18 @@ dev - \[Short description of non-trivial change.\] +2.22.0 (2019-05-15) +------------------- + +**Dependencies** + +- Requests now supports urllib3 v1.25.2. + (note: 1.25.0 and 1.25.1 are incompatible) + +**Deprecations** + +- Requests has officially stopped support for Python 3.4. + 2.21.0 (2018-12-10) ------------------- @@ -537,7 +549,7 @@ Or, even better: **Bugfixes** -- For file-like objects that are not seeked to the very beginning, we +- For file-like objects that are not sought to the very beginning, we now send the content length for the number of bytes we will actually read, rather than the total size of the file, allowing partial file uploads. @@ -781,7 +793,7 @@ documentation](http://docs.python-requests.org/en/latest/community/release-proce - Unicode URL improvements for Python 2. - Re-order JSON param for backwards compat. - Automatically defrag authentication schemes from host/pass URIs. - ([\#2249](https://github.com/requests/requests/issues/2249)) + ([\#2249](https://github.com/psf/requests/issues/2249)) 2.4.2 (2014-10-05) ------------------ @@ -789,26 +801,26 @@ documentation](http://docs.python-requests.org/en/latest/community/release-proce **Improvements** - FINALLY! Add json parameter for uploads! - ([\#2258](https://github.com/requests/requests/pull/2258)) + ([\#2258](https://github.com/psf/requests/pull/2258)) - Support for bytestring URLs on Python 3.x - ([\#2238](https://github.com/requests/requests/pull/2238)) + ([\#2238](https://github.com/psf/requests/pull/2238)) **Bugfixes** - Avoid getting stuck in a loop - ([\#2244](https://github.com/requests/requests/pull/2244)) + ([\#2244](https://github.com/psf/requests/pull/2244)) - Multiple calls to iter\* fail with unhelpful error. - ([\#2240](https://github.com/requests/requests/issues/2240), - [\#2241](https://github.com/requests/requests/issues/2241)) + ([\#2240](https://github.com/psf/requests/issues/2240), + [\#2241](https://github.com/psf/requests/issues/2241)) **Documentation** - Correct redirection introduction - ([\#2245](https://github.com/requests/requests/pull/2245/)) + ([\#2245](https://github.com/psf/requests/pull/2245/)) - Added example of how to send multiple files in one request. - ([\#2227](https://github.com/requests/requests/pull/2227/)) + ([\#2227](https://github.com/psf/requests/pull/2227/)) - Clarify how to pass a custom set of CAs - ([\#2248](https://github.com/requests/requests/pull/2248/)) + ([\#2248](https://github.com/psf/requests/pull/2248/)) 2.4.1 (2014-09-09) ------------------ diff --git a/Makefile b/Makefile index 317a7c76fb..231ce35775 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: docs init: pip install pipenv --upgrade - pipenv install --dev --skip-lock + pipenv install --dev test: # This runs all of the tests, on both Python 2 and Python 3. detox diff --git a/Pipfile b/Pipfile index 3e0fd729eb..16f3aba781 100644 --- a/Pipfile +++ b/Pipfile @@ -4,12 +4,12 @@ verify_ssl = true name = "pypi" [dev-packages] -pytest = ">=2.8.0" +pytest = ">=2.8.0,<=3.10.1" codecov = "*" -pytest-httpbin = ">=0.0.7" +pytest-httpbin = ">=0.0.7,<1.0" pytest-mock = "*" pytest-cov = "*" -pytest-xdist = "*" +pytest-xdist = "<=1.25" alabaster = "*" readme-renderer = "*" sphinx = "<=1.5.5" diff --git a/Pipfile.lock b/Pipfile.lock index e712de41ab..b50f465016 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0735b243455d8e924fbd05188ed435bfd3917f4acdade9b9e8f14741f3fc47e9" + "sha256": "33206a3ef69c36187f33224ccf8e694a323ff4f7b2cc92c35fe8e71898b525a0" }, "pipfile-spec": 6, "requires": {}, @@ -16,10 +16,10 @@ "default": { "certifi": { "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", + "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" ], - "version": "==2018.4.16" + "version": "==2019.3.9" }, "chardet": { "hashes": [ @@ -37,61 +37,86 @@ }, "idna": { "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "version": "==2.6" + "version": "==2.8" }, "pysocks": { "hashes": [ - "sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672" + "sha256:15d38914b60dbcb231d276f64882a20435c049450160e953ca7d313d1405f16f", + "sha256:32238918ac0f19e9fd870a8692ac9bd14f5e8752b3c62624cda5851424642210", + "sha256:d9031ea45fdfacbe59a99273e9f0448ddb33c1580fe3831c1b09557c5718977c" ], - "version": "==1.6.8" + "version": "==1.7.0" + }, + "requests": { + "editable": true, + "extras": [ + "socks" + ], + "path": ".", + "version": "==2.22.0" }, "urllib3": { "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + "sha256:a53063d8b9210a7bdec15e7b272776b9d42b2fd6816401a0d43006ad2f9902db", + "sha256:d363e3607d8de0c220d31950a8f38b18d5ba7c0830facd71a1c6b1036b7ce06c" ], - "version": "==1.22" + "version": "==1.25.2" + }, + "win-inet-pton": { + "hashes": [ + "sha256:dd03d942c0d3e2b1cf8bab511844546dfa5f74cb61b241699fa379ad707dea4f", + "sha256:eaf0193cbe7152ac313598a0da7313fb479f769343c0c16c5308f64887dc885b" + ], + "markers": "sys_platform == 'win32' and python_version == '2.7'", + "version": "==1.1.0" } }, "develop": { "alabaster": { "hashes": [ - "sha256:2eef172f44e8d301d25aff8068fddd65f767a3f04b5f15b0f4922f113aa1c732", - "sha256:37cdcb9e9954ed60912ebc1ca12a9d12178c26637abdf124e3cde2341c257fe0" + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" ], "index": "pypi", - "version": "==0.7.10" + "version": "==0.7.12" }, "apipkg": { "hashes": [ - "sha256:2e38399dbe842891fe85392601aab8f40a8f4cc5a9053c326de35a1cc0297ac6", - "sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9" + "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6", + "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c" ], - "version": "==1.4" + "version": "==1.5" + }, + "atomicwrites": { + "hashes": [ + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" + ], + "version": "==1.3.0" }, "attrs": { "hashes": [ - "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", - "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" ], - "version": "==18.1.0" + "version": "==19.1.0" }, "babel": { "hashes": [ - "sha256:8ce4cb6fdd4393edd323227cba3a077bceb2a6ce5201c902c65e730046f41f14", - "sha256:ad209a68d7162c4cff4b29cdebe3dec4cef75492df501b0049a9433c96ce6f80" + "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", + "sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23" ], - "version": "==2.5.3" + "version": "==2.6.0" }, "bleach": { "hashes": [ - "sha256:b8fa79e91f96c2c2cd9fd1f9eda906efb1b88b483048978ba62fef680e962b34", - "sha256:eb7386f632349d10d9ce9d4a838b134d4731571851149f9cc2c05a9a837a9a44" + "sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16", + "sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa" ], - "version": "==2.1.3" + "version": "==3.1.0" }, "blinker": { "hashes": [ @@ -135,42 +160,43 @@ }, "certifi": { "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", + "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" ], - "version": "==2018.4.16" + "version": "==2019.3.9" }, "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" + "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774", + "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d", + "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90", + "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b", + "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63", + "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45", + "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25", + "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3", + "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b", + "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647", + "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016", + "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4", + "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb", + "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753", + "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7", + "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9", + "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f", + "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8", + "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f", + "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc", + "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42", + "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3", + "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909", + "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45", + "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d", + "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512", + "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff", + "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201" + ], + "version": "==1.12.3" }, "chardet": { "hashes": [ @@ -181,38 +207,10 @@ }, "click": { "hashes": [ - "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", - "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" - ], - "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" + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + ], + "version": "==7.0" }, "codecov": { "hashes": [ @@ -224,10 +222,11 @@ }, "configparser": { "hashes": [ - "sha256:5308b47021bc2340965c371f0f058cc6971a04502638d4244225c49d80db273a" + "sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32", + "sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75" ], "markers": "python_version < '3.2'", - "version": "==3.5.0" + "version": "==3.7.4" }, "contextlib2": { "hashes": [ @@ -239,59 +238,71 @@ }, "coverage": { "hashes": [ - "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.5.1" + "sha256:0c5fe441b9cfdab64719f24e9684502a59432df7570521563d7b1aff27ac755f", + "sha256:2b412abc4c7d6e019ce7c27cbc229783035eef6d5401695dccba80f481be4eb3", + "sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9", + "sha256:39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74", + "sha256:3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390", + "sha256:42692db854d13c6c5e9541b6ffe0fe921fe16c9c446358d642ccae1462582d3b", + "sha256:465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8", + "sha256:48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe", + "sha256:4ec30ade438d1711562f3786bea33a9da6107414aed60a5daa974d50a8c2c351", + "sha256:5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf", + "sha256:5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e", + "sha256:6899797ac384b239ce1926f3cb86ffc19996f6fa3a1efbb23cb49e0c12d8c18c", + "sha256:68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741", + "sha256:6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09", + "sha256:7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd", + "sha256:7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034", + "sha256:839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420", + "sha256:8e679d1bde5e2de4a909efb071f14b472a678b788904440779d2c449c0355b27", + "sha256:8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c", + "sha256:932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab", + "sha256:93f965415cc51604f571e491f280cff0f5be35895b4eb5e55b47ae90c02a497b", + "sha256:988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba", + "sha256:998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e", + "sha256:9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609", + "sha256:9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2", + "sha256:a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49", + "sha256:a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b", + "sha256:a9abc8c480e103dc05d9b332c6cc9fb1586330356fc14f1aa9c0ca5745097d19", + "sha256:aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d", + "sha256:bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce", + "sha256:bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9", + "sha256:c22ab9f96cbaff05c6a84e20ec856383d27eae09e511d3e6ac4479489195861d", + "sha256:c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4", + "sha256:c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773", + "sha256:c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723", + "sha256:ca58eba39c68010d7e87a823f22a081b5290e3e3c64714aac3c91481d8b34d22", + "sha256:df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c", + "sha256:f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f", + "sha256:f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1", + "sha256:f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260", + "sha256:fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a" + ], + "version": "==4.5.3" }, "decorator": { "hashes": [ - "sha256:2c51dff8ef3c447388fe5e4453d24a2bf128d3a4c32af3fabef1f01c6851ab82", - "sha256:c39efa13fbdeb4506c476c9b3babf6a718da943dab7811c206005a4a956c080c" + "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", + "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6" ], - "version": "==4.3.0" + "version": "==4.4.0" }, "detox": { "hashes": [ - "sha256:cb24895a0e4f95c0bcb1087a201c453600e075568af00848e91518fb2b984568", - "sha256:f3119bca4444f1e8a1d7189b064c52cfdd9a89ad3a1c921d78b49bf7f5dc5b1b" + "sha256:e650f95f0c7f5858578014b3b193e5dac76c89285c1bbe4bae598fd641bf9cd3", + "sha256:fcad009e2d20ce61176dc826a2c1562bd712fe53953ca603b455171cf819080f" ], "index": "pypi", - "version": "==0.12" + "version": "==0.19" + }, + "dnspython": { + "hashes": [ + "sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01", + "sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d" + ], + "version": "==1.16.0" }, "docutils": { "hashes": [ @@ -302,6 +313,13 @@ "index": "pypi", "version": "==0.14" }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" + }, "enum34": { "hashes": [ "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", @@ -314,25 +332,32 @@ }, "eventlet": { "hashes": [ - "sha256:06cffa55b335cc4fc32d0079242a81e8a9cddf2581d64d5f0543e2d412b26ca8", - "sha256:554a50dad7abee0a9775b0780ce9d9c0bd9123dda4743c46d4314170267c6c47" + "sha256:c584163e006e613707e224552fafc63e4e0aa31d7de0ab18b481ac0b385254c8", + "sha256:d9d31a3c8dbcedbcce5859a919956d934685b17323fc80e1077cb344a2ffa68d" ], - "version": "==0.23.0" + "version": "==0.24.1" }, "execnet": { "hashes": [ - "sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a", - "sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83" + "sha256:027ee5d961afa01e97b90d6ccc34b4ed976702bc58e7f092b3c513ea288cb6d2", + "sha256:752a3786f17416d491f833a29217dda3ea4a471fc5269c492eebcee8cc4772d3" + ], + "version": "==1.6.0" + }, + "filelock": { + "hashes": [ + "sha256:b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633", + "sha256:d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6" ], - "version": "==1.5.0" + "version": "==3.0.10" }, "flake8": { "hashes": [ - "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0", - "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37" + "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", + "sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8" ], "index": "pypi", - "version": "==3.5.0" + "version": "==3.7.7" }, "flask": { "hashes": [ @@ -346,43 +371,40 @@ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" ], - "markers": "python_version < '3.3'", + "markers": "python_version < '3.0'", "version": "==1.0.2" }, - "future": { + "functools32": { "hashes": [ - "sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb" + "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0", + "sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d" ], - "version": "==0.16.0" + "markers": "python_version < '3.2'", + "version": "==3.2.3.post2" }, "greenlet": { "hashes": [ - "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.13" - }, - "html5lib": { - "hashes": [ - "sha256:20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3", - "sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736" - ], - "version": "==1.0.1" + "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0", + "sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28", + "sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8", + "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304", + "sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0", + "sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214", + "sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043", + "sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6", + "sha256:8b4572c334593d449113f9dc8d19b93b7b271bdbe90ba7509eb178923327b625", + "sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc", + "sha256:9854f612e1b59ec66804931df5add3b2d5ef0067748ea29dc60f0efdcda9a638", + "sha256:99a26afdb82ea83a265137a398f570402aa1f2b5dfb4ac3300c026931817b163", + "sha256:a19bf883b3384957e4a4a13e6bd1ae3d85ae87f4beb5957e35b0be287f12f4e4", + "sha256:a9f145660588187ff835c55a7d2ddf6abfc570c2651c276d3d4be8a2766db490", + "sha256:ac57fcdcfb0b73bb3203b58a14501abb7e5ff9ea5e2edfa06bb03035f0cff248", + "sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939", + "sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87", + "sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720", + "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656" + ], + "version": "==0.4.15" }, "httpbin": { "hashes": [ @@ -394,36 +416,64 @@ }, "idna": { "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "version": "==2.6" + "version": "==2.8" }, "imagesize": { "hashes": [ - "sha256:3620cc0cadba3f7475f9940d22431fc4d407269f1be59ec9b8edcca26440cf18", - "sha256:5b326e4678b6925158ccc66a9fa3122b6106d7c876ee32d7de6ce59385b96315" + "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", + "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5" ], - "version": "==1.0.0" + "version": "==1.1.0" }, "itsdangerous": { "hashes": [ - "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" + "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", + "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" ], - "version": "==0.24" + "version": "==1.1.0" }, "jinja2": { "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", + "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" ], - "version": "==2.10" + "version": "==2.10.1" }, "markupsafe": { "hashes": [ - "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" - ], - "version": "==1.0" + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + ], + "version": "==1.1.1" }, "mccabe": { "hashes": [ @@ -434,97 +484,106 @@ }, "mock": { "hashes": [ - "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", - "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba" + "sha256:83657d894c90d5681d62155c82bda9c1187827525880eda8ff5df4ec813437c3", + "sha256:d157e52d4e5b938c550f39eb2fd15610db062441a9c2747d3dbfa9298211d0f8" ], "markers": "python_version < '3.0'", - "version": "==2.0.0" + "version": "==3.0.5" + }, + "monotonic": { + "hashes": [ + "sha256:23953d55076df038541e648a53676fb24980f7a1be290cdda21300b3bc21dfb0", + "sha256:552a91f381532e33cbd07c6a2655a21908088962bb8fa7239ecbcc6ad1140cc7" + ], + "version": "==1.5" }, "more-itertools": { "hashes": [ - "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", - "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e", - "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" + "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", + "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", + "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9" ], - "version": "==4.1.0" + "version": "==5.0.0" }, - "pbr": { + "pathlib2": { "hashes": [ - "sha256:680bf5ba9b28dd56e08eb7c267991a37c7a5f90a92c2e07108829931a50ff80a", - "sha256:6874feb22334a1e9a515193cba797664e940b763440c88115009ec323a7f2df5" + "sha256:25199318e8cc3c25dcb45cbe084cc061051336d5a9ea2a12448d3d8cb748f742", + "sha256:5887121d7f7df3603bca2f710e7219f3eca0eb69e0b7cc6e0a022e155ac931a7" ], - "version": "==4.0.3" + "markers": "python_version < '3.6'", + "version": "==2.3.3" }, "pluggy": { "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", - "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", - "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + "sha256:25a1bc1d148c9a640211872b4ff859878d422bccb59c9965e04eed468a0aa180", + "sha256:964cedd2b27c492fbf0b7f58b3284a09cf7f99b0f715941fb24a439b3af1bd1a" ], - "version": "==0.6.0" + "version": "==0.11.0" }, "py": { "hashes": [ - "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", - "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" ], - "version": "==1.5.3" + "version": "==1.8.0" }, "pycodestyle": { "hashes": [ - "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766", - "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9" + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" ], - "version": "==2.3.1" + "version": "==2.5.0" }, "pycparser": { "hashes": [ - "sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226" + "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" ], - "version": "==2.18" + "version": "==2.19" }, "pyflakes": { "hashes": [ - "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f", - "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805" + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" ], - "version": "==1.6.0" + "version": "==2.1.1" }, "pygments": { "hashes": [ - "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", - "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" + "sha256:31cba6ffb739f099a85e243eff8cb717089fdd3c7300767d9fc34cb8e1b065f5", + "sha256:5ad302949b3c98dd73f8d9fcdc7e9cb592f120e32a18e23efd7f3dc51194472b" ], - "version": "==2.2.0" + "version": "==2.4.0" }, "pysocks": { "hashes": [ - "sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672" + "sha256:15d38914b60dbcb231d276f64882a20435c049450160e953ca7d313d1405f16f", + "sha256:32238918ac0f19e9fd870a8692ac9bd14f5e8752b3c62624cda5851424642210", + "sha256:d9031ea45fdfacbe59a99273e9f0448ddb33c1580fe3831c1b09557c5718977c" ], - "version": "==1.6.8" + "version": "==1.7.0" }, "pytest": { "hashes": [ - "sha256:54713b26c97538db6ff0703a12b19aeaeb60b5e599de542e7fca0ec83b9038e8", - "sha256:829230122facf05a5f81a6d4dfe6454a04978ea3746853b2b84567ecf8e5c526" + "sha256:3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", + "sha256:e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660" ], "index": "pypi", - "version": "==3.5.1" + "version": "==3.10.1" }, "pytest-cov": { "hashes": [ - "sha256:03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d", - "sha256:890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec" + "sha256:2b097cde81a302e1047331b48cadacf23577e431b61e9c6f49a1170bbe3d3da6", + "sha256:e00ea4fdde970725482f1f35630d12f074e121a23801aabf2ae154ec6bdd343a" ], "index": "pypi", - "version": "==2.5.1" + "version": "==2.7.1" }, "pytest-forked": { "hashes": [ - "sha256:e4500cd0509ec4a26535f7d4112a8cc0f17d3a41c29ffd4eab479d2a55b30805", - "sha256:f275cb48a73fc61a6710726348e1da6d68a978f0ec0c54ece5a5fae5977e5a08" + "sha256:5fe33fbd07d7b1302c95310803a5e5726a4ff7f19d5a542b7ce57c76fed8135f", + "sha256:d352aaced2ebd54d42a65825722cb433004b4446ab5d2044851d9cc7a00c9e38" ], - "version": "==0.2" + "version": "==1.0.2" }, "pytest-httpbin": { "hashes": [ @@ -536,55 +595,76 @@ }, "pytest-mock": { "hashes": [ - "sha256:53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928", - "sha256:d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0" + "sha256:43ce4e9dd5074993e7c021bb1c22cbb5363e612a2b5a76bc6d956775b10758b7", + "sha256:5bf5771b1db93beac965a7347dc81c675ec4090cb841e49d9d34637a25c30568" ], "index": "pypi", - "version": "==1.10.0" + "version": "==1.10.4" }, "pytest-xdist": { "hashes": [ - "sha256:be2662264b035920ba740ed6efb1c816a83c8a22253df7766d129f6a7bfdbd35", - "sha256:e8f5744acc270b3e7d915bdb4d5f471670f049b6fbd163d4cbd52203b075d30f" + "sha256:96f893094c89fddeaff3f4783f4807f7aeb138be1a0d87a8805057b6af1201b5", + "sha256:aab1402f2b063df48bf044b042707610f8fcc4c49d0eb9c10e79e30b3f26074f" ], "index": "pypi", - "version": "==1.22.2" + "version": "==1.25.0" }, "pytz": { "hashes": [ - "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", - "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" + "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", + "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141" ], - "version": "==2018.4" + "version": "==2019.1" }, "raven": { + "extras": [ + "flask" + ], "hashes": [ - "sha256:1c641e5ebc2d4185560608e253970ca0d4b98475f4edf67735015a415f9e1d48", - "sha256:95aecf76c414facaddbb056f3e98c7936318123e467728f2e50b3a66b65a6ef7" + "sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54", + "sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4" ], - "version": "==6.8.0" + "version": "==6.10.0" }, "readme-renderer": { "hashes": [ - "sha256:bde909eaa84d65b7942f7e6998c8b427b90b568b2630ff0306f4ca75f6d2a909", - "sha256:e7e43a7ba49f08c3cb660d0f2e25b561f6b10b36c63f029060230aab2dc2875e" + "sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f", + "sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d" ], "index": "pypi", - "version": "==20.0" + "version": "==24.0" }, "requests": { + "editable": true, + "extras": [ + "socks" + ], + "path": ".", + "version": "==2.22.0" + }, + "scandir": { "hashes": [ - "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", - "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + "sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e", + "sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022", + "sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f", + "sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f", + "sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae", + "sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173", + "sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4", + "sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32", + "sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188", + "sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d", + "sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac" ], - "version": "==2.18.4" + "markers": "python_version < '3.5'", + "version": "==1.10.0" }, "six": { "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], - "version": "==1.11.0" + "version": "==1.12.0" }, "snowballstemmer": { "hashes": [ @@ -601,27 +681,44 @@ "index": "pypi", "version": "==1.5.5" }, + "toml": { + "hashes": [ + "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", + "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", + "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3" + ], + "version": "==0.10.0" + }, "tox": { "hashes": [ - "sha256:96efa09710a3daeeb845561ebbe1497641d9cef2ee0aea30db6969058b2bda2f", - "sha256:9ee7de958a43806402a38c0d2aa07fa8553f4d2c20a15b140e9f771c2afeade0" + "sha256:2a8d8a63660563e41e64e3b5b677e81ce1ffa5e2a93c2c565d3768c287445800", + "sha256:edfca7809925f49bdc110d0a2d9966bbf35a0c25637216d9586e7a5c5de17bfb" ], "index": "pypi", - "version": "==3.0.0" + "version": "==3.6.1" + }, + "typing": { + "hashes": [ + "sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", + "sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", + "sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a" + ], + "markers": "python_version < '3.5'", + "version": "==3.6.6" }, "urllib3": { "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + "sha256:a53063d8b9210a7bdec15e7b272776b9d42b2fd6816401a0d43006ad2f9902db", + "sha256:d363e3607d8de0c220d31950a8f38b18d5ba7c0830facd71a1c6b1036b7ce06c" ], - "version": "==1.22" + "version": "==1.25.2" }, "virtualenv": { "hashes": [ - "sha256:1d7e241b431e7afce47e77f8843a276f652699d1fa4f93b9d8ce0076fd7b0b54", - "sha256:e8e05d4714a1c51a2f5921e62f547fcb0f713ebbe959e0a7f585cc8bef71d11f" + "sha256:99acaf1e35c7ccf9763db9ba2accbca2f4254d61d1912c5ee364f9cc4a8942a0", + "sha256:fe51cdbf04e5d8152af06c075404745a7419de27495a83f0d72518ad50be3ce8" ], - "version": "==15.2.0" + "version": "==16.6.0" }, "webencodings": { "hashes": [ @@ -632,10 +729,10 @@ }, "werkzeug": { "hashes": [ - "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", - "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" + "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c", + "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6" ], - "version": "==0.14.1" + "version": "==0.15.4" } } } diff --git a/README.md b/README.md index ee3b2bf5e5..1027b10807 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,19 @@ Requests: HTTP for Humans™ ========================== -[![image](https://img.shields.io/pypi/v/requests.svg)](https://pypi.org/project/requests/) -[![image](https://img.shields.io/pypi/l/requests.svg)](https://pypi.org/project/requests/) +[![Downloads](https://pepy.tech/badge/requests)](https://pepy.tech/project/requests) [![image](https://img.shields.io/pypi/pyversions/requests.svg)](https://pypi.org/project/requests/) -[![codecov.io](https://codecov.io/github/requests/requests/coverage.svg?branch=master)](https://codecov.io/github/requests/requests) -[![image](https://img.shields.io/github/contributors/requests/requests.svg)](https://github.com/requests/requests/graphs/contributors) -[![image](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/kennethreitz) +[![image](https://img.shields.io/github/contributors/psf/requests.svg)](https://github.com/psf/requests/graphs/contributors) -**If you're interested in financially supporting Kenneth Reitz open source, consider [visiting this link](https://cash.me/$KennethReitz). Your support helps tremendously with sustainability of motivation, as Open Source is no longer part of my day job.** -Requests is the only *Non-GMO* HTTP library for Python, safe for human -consumption. +**Requests** is an elegant and simple HTTP library for Python, built for human beings. ![image](https://farm5.staticflickr.com/4317/35198386374_1939af3de6_k_d.jpg) Behold, the power of Requests: ``` {.sourceCode .python} +>>> import requests >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass')) >>> r.status_code 200 @@ -33,7 +29,7 @@ u'{"type":"User"...' See [the similar code, sans Requests](https://gist.github.com/973705). -[![image](https://raw.githubusercontent.com/requests/requests/master/docs/_static/requests-logo-small.png)](http://docs.python-requests.org/) +[![image](https://raw.githubusercontent.com/psf/requests/master/docs/_static/requests-logo-small.png)](http://docs.python-requests.org/) Requests allows you to send *organic, grass-fed* HTTP/1.1 requests, without the need for manual labor. There's no need to manually add query @@ -42,7 +38,7 @@ HTTP connection pooling are 100% automatic, thanks to [urllib3](https://github.com/shazow/urllib3). Besides, all the cool kids are doing it. Requests is one of the most -downloaded Python packages of all time, pulling in over 11,000,000 +downloaded Python packages of all time, pulling in over 50,000,000 downloads every month. You don't want to be left out! Feature Support @@ -66,7 +62,7 @@ Requests is ready for today's web. - `.netrc` Support - Chunked Requests -Requests officially supports Python 2.7 & 3.4–3.7, and runs great on +Requests officially supports Python 2.7 & 3.4–3.8, and runs great on PyPy. Installation @@ -91,17 +87,18 @@ Fantastic documentation is available at How to Contribute ----------------- -1. Check for open issues or open a fresh issue to start a discussion +1. Become more familiar with the project by reading our [Contributor's Guide](http://docs.python-requests.org/en/latest/dev/contributing/) and our [development philosophy](http://docs.python-requests.org/en/latest/dev/philosophy/). +2. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug. There is a [Contributor - Friendly](https://github.com/requests/requests/issues?direction=desc&labels=Contributor+Friendly&page=1&sort=updated&state=open) + Friendly](https://github.com/psf/requests/issues?direction=desc&labels=Contributor+Friendly&page=1&sort=updated&state=open) tag for issues that should be ideal for people who are not very familiar with the codebase yet. -2. Fork [the repository](https://github.com/requests/requests) on +3. Fork [the repository](https://github.com/psf/requests) on GitHub to start making your changes to the **master** branch (or branch off of it). -3. Write a test which shows that the bug was fixed or that the feature +4. Write a test which shows that the bug was fixed or that the feature works as expected. -4. Send a pull request and bug the maintainer until it gets merged and +5. Send a [pull request](https://help.github.com/en/articles/creating-a-pull-request-from-a-fork) and bug the maintainer until it gets merged and published. :) Make sure to add yourself to - [AUTHORS](https://github.com/requests/requests/blob/master/AUTHORS.rst). + [AUTHORS](https://github.com/psf/requests/blob/master/AUTHORS.rst). diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 52493c5b31..465e8a9a60 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -50,29 +50,21 @@ body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-ch /* Native CPC by BuySellAds */ -.native-js { - visibility: hidden; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, - Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, - sans-serif; - opacity: 0; - transition: all .25s ease-in-out; - transform: translateY(calc(100% - 35px)); - - flex-flow: column nowrap; -} - -.native-js[data-state=visible] { +#native-ribbon #_custom_ { position: fixed; + right: 0; bottom: 0; left: 0; - right: 0; - visibility: visible; box-shadow: 0 -1px 4px 1px hsla(0, 0%, 0%, .15); - opacity: 1; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, + Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif; + transition: all .25s ease-in-out; + transform: translateY(calc(100% - 35px)); + + flex-flow: column nowrap; } -.native-js[data-state=visible]:hover { +#native-ribbon #_custom_:hover { transform: translateY(0); } @@ -92,7 +84,7 @@ body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-ch transform-origin: left; } -.native-js[data-state=visible]:hover .native-sponsor { +#native-ribbon #_custom_:hover .native-sponsor { margin: 0 20px; opacity: 0; transform: scaleY(0); @@ -100,17 +92,14 @@ body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-ch .native-flex { display: flex; - padding: 0 20px 30px; + padding: 10px 20px 25px; text-decoration: none; flex-flow: row nowrap; + justify-content: center; align-items: center; } -.native-flex:hover { - text-decoration: none; -} - .native-main { display: flex; @@ -135,6 +124,7 @@ body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-ch .native-desc { letter-spacing: 1px; font-weight: 300; + font-size: 14px; line-height: 1.4; } @@ -158,6 +148,7 @@ body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-ch @media only screen and (min-width: 320px) and (max-width: 759px) { .native-flex { + padding: 5px 5px 15px; flex-direction: column; flex-wrap: wrap; @@ -165,6 +156,7 @@ body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-ch .native-img { margin: 0; + display: none; } .native-details { @@ -173,10 +165,13 @@ body > div.document > div.sphinxsidebar > div > form > table > tbody > tr:nth-ch .native-main { flex-direction: column; - margin-bottom: 20px; - text-align: center; + text-align: left; flex-wrap: wrap; align-content: center; } + + .native-cta { + display: none; + } } diff --git a/docs/_static/native.js b/docs/_static/native.js deleted file mode 100644 index 65aebecf20..0000000000 --- a/docs/_static/native.js +++ /dev/null @@ -1,131 +0,0 @@ -var _native = (function () { - var _options = {} - var _construct = function (e) { - var defaultOptions = { - carbonZoneKey: '', - fallback: '', - ignore: 'false', - placement: '', - prefix: 'native', - targetClass: 'native-ad' - } - - if (typeof e === 'undefined') return defaultOptions - Object.keys(defaultOptions).forEach((key, index) => { - if (typeof e[key] === 'undefined') { - e[key] = defaultOptions[key] - } - }) - return e - } - - var init = function (zone, options) { - _options = _construct(options) - - let jsonUrl = `https://srv.buysellads.com/ads/${zone}.json?callback=_native_go` - if (_options['placement'] !== '') { - jsonUrl += '&segment=placement:' + _options['placement'] - } - if (_options['ignore'] === 'true') { - jsonUrl += '&ignore=yes' - } - - let srv = document.createElement('script') - srv.src = jsonUrl - document.getElementsByTagName('head')[0].appendChild(srv) - } - - var carbon = function (e) { - let srv = document.createElement('script') - srv.src = '//cdn.carbonads.com/carbon.js?serve=' + e['carbonZoneKey'] + '&placement=' + e['placement'] - srv.id = '_carbonads_js' - - return srv - } - - var sanitize = function (ads) { - return ads - .filter(ad => { - return Object.keys(ad).length > 0 - }) - .filter(ad => { - return ad.hasOwnProperty('statlink') - }) - } - - var pixel = function (p, timestamp) { - let c = '' - if (p) { - p.split('||').forEach((pixel, index) => { - c += `` - }) - } - return c - } - - var options = function () { - return _options - } - - return { - carbon: carbon, - init: init, - options: options, - pixel: pixel, - sanitize: sanitize - } -})({}) - -var _native_go = function (json) { - let options = _native.options() - let ads = _native.sanitize(json['ads']) - let selectedClass = document.querySelectorAll('.' + options['targetClass']) - - if (ads.length < 1) { - selectedClass.forEach((className, index) => { - let selectedTarget = document.getElementsByClassName(options['targetClass'])[index] - - if (options['fallback'] !== '' || options['carbonZoneKey'] !== '') selectedTarget.setAttribute('data-state', 'visible') - selectedTarget.innerHTML = options['fallback'] - if (options['carbonZoneKey'] !== '') selectedTarget.appendChild(_native.carbon(options)) - }) - - // End at this line if no ads are found, avoiding unnecessary steps - return - } - - selectedClass.forEach((className, index) => { - let selectedTarget = document.getElementsByClassName(options['targetClass'])[index] - let adElement = selectedTarget.innerHTML - let prefix = options['prefix'] - let ad = ads[index] - - if (ad && className) { - let adInnerHtml = adElement - .replace(new RegExp('#' + prefix + '_bg_color#', 'g'), ad['backgroundColor']) - .replace(new RegExp('#' + prefix + '_bg_color_hover#', 'g'), ad['backgroundHoverColor']) - .replace(new RegExp('#' + prefix + '_company#', 'g'), ad['company']) - .replace(new RegExp('#' + prefix + '_cta#', 'g'), ad['callToAction']) - .replace(new RegExp('#' + prefix + '_cta_bg_color#', 'g'), ad['ctaBackgroundColor']) - .replace(new RegExp('#' + prefix + '_cta_bg_color_hover#', 'g'), ad['ctaBackgroundHoverColor']) - .replace(new RegExp('#' + prefix + '_cta_color#', 'g'), ad['ctaTextColor']) - .replace(new RegExp('#' + prefix + '_cta_color_hover#', 'g'), ad['ctaTextColorHover']) - .replace(new RegExp('#' + prefix + '_desc#', 'g'), ad['description']) - .replace(new RegExp('#' + prefix + '_index#', 'g'), prefix + '-' + ad['i']) - .replace(new RegExp('#' + prefix + '_img#', 'g'), ad['image']) - .replace(new RegExp('#' + prefix + '_small_img#', 'g'), ad['smallImage']) - .replace(new RegExp('#' + prefix + '_link#', 'g'), ad['statlink']) - .replace(new RegExp('#' + prefix + '_logo#', 'g'), ad['logo']) - .replace(new RegExp('#' + prefix + '_color#', 'g'), ad['textColor']) - .replace(new RegExp('#' + prefix + '_color_hover#', 'g'), ad['textColorHover']) - .replace(new RegExp('#' + prefix + '_title#', 'g'), ad['title']) - - selectedTarget.innerHTML = null - selectedTarget.innerHTML += adInnerHtml + _native.pixel(ad['pixel'], ad['timestamp']) - selectedTarget.setAttribute('data-state', 'visible') - } else { - selectedTarget.innerHTML = null - selectedTarget.style.display = 'none' - } - }) -} diff --git a/docs/_templates/hacks.html b/docs/_templates/hacks.html index 61252a5cca..3af2e578b6 100644 --- a/docs/_templates/hacks.html +++ b/docs/_templates/hacks.html @@ -57,47 +57,54 @@ - - + + +
+
-
-
Sponsored Ad by #native_company# — Learn More
- + diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html index 6bfc5cef12..1877a4518a 100644 --- a/docs/_templates/sidebarintro.html +++ b/docs/_templates/sidebarintro.html @@ -8,13 +8,33 @@

+ + + +

Requests is an elegant and simple HTTP library for Python, built for human beings.

-

Sponsored by Linode and other wonderful organizations.

- +

Sponsored by CERT Gouvernemental - GOVCERT.LU.

@@ -24,34 +44,15 @@

Stay Informed

-

-

Join Mailing List.

-

Other Projects

- -

More Kenneth Reitz projects:

- - -

Useful Links

@@ -69,41 +70,5 @@

Translations

  • Spanish
  • -
    -
    Sponsored by #native_company# — Learn More
    - - -
    - -
    - #native_title# - #native_desc# -
    -
    - #native_cta# -
    +
    diff --git a/docs/_templates/sidebarlogo.html b/docs/_templates/sidebarlogo.html index 7fe26493e7..37aa3da37b 100644 --- a/docs/_templates/sidebarlogo.html +++ b/docs/_templates/sidebarlogo.html @@ -7,7 +7,27 @@

    - + + + +

    Requests is an elegant and simple HTTP library for Python, built for @@ -15,7 +35,7 @@ development release.

    -

    Sponsored by Linode and other wonderful organizations.

    +Sponsored by CERT Gouvernemental - GOVCERT.LU.

    Stay Informed

    Receive updates on new releases and upcoming projects.

    @@ -26,28 +46,6 @@

    Stay Informed

    -

    - -

    - - -

    Other Projects

    - -

    More Kenneth Reitz projects:

    - -

    Translations

    diff --git a/docs/community/faq.rst b/docs/community/faq.rst index 945096dc64..44d3e6e857 100644 --- a/docs/community/faq.rst +++ b/docs/community/faq.rst @@ -21,7 +21,8 @@ Custom User-Agents? ------------------- Requests allows you to easily override User-Agent strings, along with -any other HTTP Header. +any other HTTP Header. See `documentation about headers `_. + Why not Httplib2? diff --git a/docs/community/sponsors.rst b/docs/community/sponsors.rst deleted file mode 100644 index d0569f2727..0000000000 --- a/docs/community/sponsors.rst +++ /dev/null @@ -1,96 +0,0 @@ -Community Sponsors -================== - -**tl;dr**: Requests development is currently `funded by the Python community `_, and -some wonderful organizations that utilize the software in their businesses. - - -------------------- - - -Requests is one of the most heavily–utilized Python packages in the world. - -It is used by major corporations worldwide for all tasks, both small and large — from writing one–off 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, full–time), we are seeking community financial contributions towards the development of Requests 3.0. - -Patron Sponsors ----------------- - - -`Linode — SSD Cloud Hosting & Linux Servers `_ -////////////////////////////////////////////////////////////////////// - -Whether you’re 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 patron–level 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 `_ -/////////////////////////////////////////////////////// - -Slack was extremely kind to be the first organization to generously donate a large sum towards the `2018 Requests 3.0 fundraiser `_, 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 `_! - - -`Twilio — Voice, SMS, and Video for Humans `_ -///////////////////////////////////////////////////////////////////// - -Twilio was the second organization to generously donate a large sum towards the `2018 Requests 3.0 fundraiser `_, matching the donation of Slack! They are helping the world become a better place through interconnectivity, -providing easy–to–use APIs, and empowering developers world-over to help humans communicate in meaningful and effective ways. - - -`Azure Cloud Developer Advocates `_ -///////////////////////////////////////////////////////////////////////////////////// - -Azure was the third organization to generously donate a large sum towards the `2018 Requests 3.0 fundraiser `_, matching the donation of Twilio! Awesome group of generous folks :) - - -`Niteo — Web Systems Development `_ -///////////////////////////////////////////////////////////// - -Niteo was the fourth company to generously donate towards the `2018 Requests 3.0 fundraiser `_. Niteo is a company employing tech enthusiasts from all over the world -who love to build great stuff. - - -`Heroku `_ -///////////////////////////////////// - -Heroku has allowed Kenneth Reitz to work on some open source projects during work hours, -including Requests (but mostly Pipenv), from time–to–time, 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 `_. - - -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. - -✨🍰✨ diff --git a/docs/community/support.rst b/docs/community/support.rst index 4b72bba813..23e3586852 100644 --- a/docs/community/support.rst +++ b/docs/community/support.rst @@ -29,7 +29,7 @@ File an Issue If you notice some unexpected behaviour in Requests, or want to see support for a new feature, -`file an issue on GitHub `_. +`file an issue on GitHub `_. E-mail diff --git a/docs/community/updates.rst b/docs/community/updates.rst index 3ae0589ff6..ee08cdc572 100644 --- a/docs/community/updates.rst +++ b/docs/community/updates.rst @@ -14,7 +14,7 @@ GitHub ------ The best way to track the development of Requests is through -`the GitHub repo `_. +`the GitHub repo `_. Twitter ------- diff --git a/docs/conf.py b/docs/conf.py index fb10abdbaf..eb556a81ba 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,11 +18,11 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # Insert Requests' path into the system. -sys.path.insert(0, os.path.abspath('..')) -sys.path.insert(0, os.path.abspath('_themes')) +sys.path.insert(0, os.path.abspath("..")) +sys.path.insert(0, os.path.abspath("_themes")) import requests @@ -30,36 +30,36 @@ # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.viewcode', + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.viewcode", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'Requests' -copyright = u'MMXVIII. A Kenneth Reitz Project' -author = u'Kenneth Reitz' +project = u"Requests" +copyright = u'MMXVIX. A Kenneth Reitz Project' +author = u"Kenneth Reitz" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -79,17 +79,17 @@ # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = False @@ -100,16 +100,16 @@ # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'flask_theme_support.FlaskyStyle' +pygments_style = "flask_theme_support.FlaskyStyle" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True @@ -119,52 +119,52 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { - 'show_powered_by': False, - 'github_user': 'requests', - 'github_repo': 'requests', - 'github_banner': True, - 'show_related': False, - 'note_bg': '#FFF59C' + "show_powered_by": False, + "github_user": "requests", + "github_repo": "requests", + "github_banner": True, + "show_related": False, + "note_bg": "#FFF59C", } # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. @@ -172,24 +172,29 @@ # Custom sidebar templates, maps document names to template names. html_sidebars = { - 'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html', - 'hacks.html'], - '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html', - 'sourcelink.html', 'searchbox.html', 'hacks.html'] + "index": ["sidebarintro.html", "sourcelink.html", "searchbox.html", "hacks.html"], + "**": [ + "sidebarlogo.html", + "localtoc.html", + "relations.html", + "sourcelink.html", + "searchbox.html", + "hacks.html", + ], } # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = False @@ -203,84 +208,77 @@ # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'Requestsdoc' +htmlhelp_basename = "Requestsdoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', + # Latex figure (float) alignment + #'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'Requests.tex', u'Requests Documentation', - u'Kenneth Reitz', 'manual'), + (master_doc, "Requests.tex", u"Requests Documentation", u"Kenneth Reitz", "manual") ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'requests', u'Requests Documentation', - [author], 1) -] +man_pages = [(master_doc, "requests", u"Requests Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -289,22 +287,28 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Requests', u'Requests Documentation', - author, 'Requests', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "Requests", + u"Requests Documentation", + author, + "Requests", + "One line description of project.", + "Miscellaneous", + ) ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False # -- Options for Epub output ---------------------------------------------- @@ -316,67 +320,67 @@ epub_copyright = copyright # The basename for the epub file. It defaults to the project name. -#epub_basename = project +# epub_basename = project # The HTML theme for the epub output. Since the default themes are not # optimized for small screen space, using the same theme for HTML and epub # output is usually not wise. This defaults to 'epub', a theme designed to save # visual space. -#epub_theme = 'epub' +# epub_theme = 'epub' # The language of the text. It defaults to the language option # or 'en' if the language is not set. -#epub_language = '' +# epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' +# epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. -#epub_identifier = '' +# epub_identifier = '' # A unique identification for the text. -#epub_uid = '' +# epub_uid = '' # A tuple containing the cover image and cover page html template filenames. -#epub_cover = () +# epub_cover = () # A sequence of (type, uri, title) tuples for the guide element of content.opf. -#epub_guide = () +# epub_guide = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. -#epub_pre_files = [] +# epub_pre_files = [] # HTML files that should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. -#epub_post_files = [] +# epub_post_files = [] # A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] +epub_exclude_files = ["search.html"] # The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 +# epub_tocdepth = 3 # Allow duplicate toc entries. -#epub_tocdup = True +# epub_tocdup = True # Choose between 'default' and 'includehidden'. -#epub_tocscope = 'default' +# epub_tocscope = 'default' # Fix unsupported image types using the Pillow. -#epub_fix_images = False +# epub_fix_images = False # Scale large images. -#epub_max_image_width = 0 +# epub_max_image_width = 0 # How to display URL addresses: 'footnote', 'no', or 'inline'. -#epub_show_urls = 'inline' +# epub_show_urls = 'inline' # If false, no index is generated. -#epub_use_index = True +# epub_use_index = True intersphinx_mapping = { - 'python': ('https://docs.python.org/3/', None), - 'urllib3': ('https://urllib3.readthedocs.io/en/latest', None), + "python": ("https://docs.python.org/3/", None), + "urllib3": ("https://urllib3.readthedocs.io/en/latest", None), } diff --git a/docs/dev/contributing.rst b/docs/dev/contributing.rst index d1171cb971..308fdd2585 100644 --- a/docs/dev/contributing.rst +++ b/docs/dev/contributing.rst @@ -130,7 +130,14 @@ the Requests codebase:: foo = long_function_name(var_one, var_two, var_three, var_four) -No. Just don't. Please. +No. Just don't. Please. This is much better:: + + foo = long_function_name( + var_one, + var_two, + var_three, + var_four, + ) Docstrings are to follow the following syntaxes:: @@ -190,7 +197,7 @@ through the `GitHub issues`_, **both open and closed**, to confirm that the bug hasn't been reported before. Duplicate bug reports are a huge drain on the time of other contributors, and should be avoided as much as possible. -.. _GitHub issues: https://github.com/requests/requests/issues +.. _GitHub issues: https://github.com/psf/requests/issues Feature Requests diff --git a/docs/dev/todo.rst b/docs/dev/todo.rst index 26cd9b716b..d09fce398d 100644 --- a/docs/dev/todo.rst +++ b/docs/dev/todo.rst @@ -8,11 +8,11 @@ Requests is under active development, and contributions are more than welcome! #. Check for open issues or open a fresh issue to start a discussion around a bug. There is a Contributor Friendly tag for issues that should be ideal for people who are not very familiar with the codebase yet. -#. Fork `the repository `_ on GitHub and start making your +#. Fork `the repository `_ on GitHub and start making your changes to a new branch. #. Write a test which shows that the bug was fixed. #. Send a pull request and bug the maintainer until it gets merged and published. :) - Make sure to add yourself to `AUTHORS `_. + Make sure to add yourself to `AUTHORS `_. Feature Freeze -------------- diff --git a/docs/index.rst b/docs/index.rst index 9e946dae09..aef02c2cbf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,6 +8,10 @@ Requests: HTTP for Humans™ Release v\ |version|. (:ref:`Installation `) + +.. image:: https://pepy.tech/badge/requests + :target: https://pepy.tech/project/request + .. image:: https://img.shields.io/pypi/l/requests.svg :target: https://pypi.org/project/requests/ @@ -17,23 +21,7 @@ Release v\ |version|. (:ref:`Installation `) .. image:: https://img.shields.io/pypi/pyversions/requests.svg :target: https://pypi.org/project/requests/ -.. image:: https://codecov.io/github/requests/requests/coverage.svg?branch=master - :target: https://codecov.io/github/requests/requests - :alt: codecov.io - -.. image:: https://img.shields.io/badge/Say%20Thanks!-🦉-1EAEDB.svg - :target: https://saythanks.io/to/kennethreitz - - -**Requests** is the only *Non-GMO* HTTP library for Python, safe for human -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* - - -If you're interested in financially supporting Kenneth Reitz open source, consider visiting `this link `_. Your support helps tremendously with sustainability of motivation, as Open Source is no longer part of my day job. - +**Requests** is an elegant and simple HTTP library for Python, built for human beings. ------------------- @@ -54,42 +42,11 @@ If you're interested in financially supporting Kenneth Reitz open source, consid See `similar code, sans Requests `_. -**Requests** allows you to send *organic, grass-fed* HTTP/1.1 requests, without the -need for manual labor. There's no need to manually add query strings to your +**Requests** allows you to send HTTP/1.1 requests extremely easily. +There's no need to manually add query strings to your URLs, or to form-encode your POST data. Keep-alive and HTTP connection pooling are 100% automatic, thanks to `urllib3 `_. -User Testimonials ------------------ - -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**, creator of Flask— - *Requests is the perfect example how beautiful an API can be with the - right level of abstraction.* - -**Matt DeBoard**— - *I'm going to get Kenneth Reitz's Python requests module tattooed - on my body, somehow. The whole thing.* - -**Daniel Greenfeld**— - *Nuked a 1200 LOC spaghetti code library with 10 lines of code thanks to - 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 400,000 downloads **each day**. Join the party! - -If your organization uses Requests internally, consider `supporting the development of 3.0 `_. Your -generosity will be greatly appreciated, and help drive the project forward -into the future. - Beloved Features ---------------- diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 9a615aae73..728ffbb684 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -193,7 +193,7 @@ When you are using the prepared request flow, keep in mind that it does not take This can cause problems if you are using environment variables to change the behaviour of requests. For example: Self-signed SSL certificates specified in ``REQUESTS_CA_BUNDLE`` will not be taken into account. 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:: +You can get around this behaviour by explicitly merging the environment settings into your session:: from requests import Request, Session @@ -203,7 +203,7 @@ You can get around this behaviour by explicity merging the environment settings prepped = s.prepare_request(req) # Merge environment settings into session - settings = s.merge_environment_settings(prepped.url, None, None, None, None) + settings = s.merge_environment_settings(prepped.url, {}, None, None, None) resp = s.send(prepped, **settings) print(resp.status_code) @@ -300,7 +300,7 @@ immediately. You can override this behaviour and defer downloading the response body until you access the :attr:`Response.content ` attribute with the ``stream`` parameter:: - tarball_url = 'https://github.com/requests/requests/tarball/master' + tarball_url = 'https://github.com/psf/requests/tarball/master' r = requests.get(tarball_url, stream=True) At this point only the response headers have been downloaded and the connection @@ -680,7 +680,7 @@ from GitHub. Suppose we wanted commit ``a050faf`` on Requests. We would get it like so:: >>> import requests - >>> r = requests.get('https://api.github.com/repos/requests/requests/git/commits/a050faf084662f3a352dd1a941f2c7c9f886d4ad') + >>> r = requests.get('https://api.github.com/repos/psf/requests/git/commits/a050faf084662f3a352dd1a941f2c7c9f886d4ad') We should confirm that GitHub responded correctly. If it has, we want to work out what type of content it is. Do this like so:: @@ -735,12 +735,12 @@ we should probably avoid making ham-handed POSTS to it. Instead, let's play with the Issues feature of GitHub. This documentation was added in response to -`Issue #482 `_. Given that +`Issue #482 `_. Given that this issue already exists, we will use it as an example. Let's start by getting it. :: - >>> r = requests.get('https://api.github.com/repos/requests/requests/issues/482') + >>> r = requests.get('https://api.github.com/repos/psf/requests/issues/482') >>> r.status_code 200 @@ -783,7 +783,7 @@ is to POST to the thread. Let's do it. :: >>> body = json.dumps({u"body": u"Sounds great! I'll get right on it!"}) - >>> url = u"https://api.github.com/repos/requests/requests/issues/482/comments" + >>> url = u"https://api.github.com/repos/psf/requests/issues/482/comments" >>> r = requests.post(url=url, data=body) >>> r.status_code @@ -817,7 +817,7 @@ that. 5804413 >>> body = json.dumps({u"body": u"Sounds great! I'll get right on it once I feed my cat."}) - >>> url = u"https://api.github.com/repos/requests/requests/issues/comments/5804413" + >>> url = u"https://api.github.com/repos/psf/requests/issues/comments/5804413" >>> r = requests.patch(url=url, data=body, auth=auth) >>> r.status_code @@ -976,11 +976,12 @@ response at a time. However, these calls will still block. If you are concerned about the use of blocking IO, there are lots of projects out there that combine Requests with one of Python's asynchronicity frameworks. -Some excellent examples are `requests-threads`_, `grequests`_, and `requests-futures`_. +Some excellent examples are `requests-threads`_, `grequests`_, `requests-futures`_, and `requests-async`_. .. _`requests-threads`: https://github.com/requests/requests-threads .. _`grequests`: https://github.com/kennethreitz/grequests .. _`requests-futures`: https://github.com/ross/requests-futures +.. _`requests-async`: https://github.com/encode/requests-async Header Ordering --------------- diff --git a/docs/user/install.rst b/docs/user/install.rst index 3888876ab2..73e69f2946 100644 --- a/docs/user/install.rst +++ b/docs/user/install.rst @@ -25,15 +25,15 @@ Get the Source Code ------------------- Requests is actively developed on GitHub, where the code is -`always available `_. +`always available `_. You can either clone the public repository:: - $ git clone git://github.com/requests/requests.git + $ git clone git://github.com/psf/requests.git -Or, download the `tarball `_:: +Or, download the `tarball `_:: - $ curl -OL https://github.com/requests/requests/tarball/master + $ curl -OL https://github.com/psf/requests/tarball/master # optionally, zipball is also available (for Windows users). Once you have a copy of the source, you can embed it in your own Python diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst index f47903cf4c..ca95a0208b 100644 --- a/docs/user/quickstart.rst +++ b/docs/user/quickstart.rst @@ -560,3 +560,6 @@ All exceptions that Requests explicitly raises inherit from ----------------------- Ready for more? Check out the :ref:`advanced ` section. + + +If you're on the job market, consider taking `this programming quiz `_. A substantial donation will be made to this project, if you find a job through this platform. diff --git a/pytest.ini b/pytest.ini index c1fa878547..13fa000028 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,3 @@ [pytest] -addopts = -p no:warnings \ No newline at end of file +addopts = -p no:warnings --doctest-modules +doctest_optionflags= NORMALIZE_WHITESPACE ELLIPSIS \ No newline at end of file diff --git a/requests/__init__.py b/requests/__init__.py index bc168ee533..3486f5e1fb 100644 --- a/requests/__init__.py +++ b/requests/__init__.py @@ -9,14 +9,14 @@ Requests HTTP Library ~~~~~~~~~~~~~~~~~~~~~ -Requests is an HTTP library, written in Python, for human beings. Basic GET -usage: +Requests is an HTTP library, written in Python, for human beings. +Basic GET usage: >>> import requests >>> r = requests.get('https://www.python.org') >>> r.status_code 200 - >>> 'Python is a programming language' in r.content + >>> b'Python is a programming language' in r.content True ... or POST: @@ -27,8 +27,8 @@ { ... "form": { - "key2": "value2", - "key1": "value1" + "key1": "value1", + "key2": "value2" }, ... } @@ -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.24 + # urllib3 >= 1.21.1, <= 1.25 assert major == 1 assert minor >= 21 - assert minor <= 24 + assert minor <= 25 # Check chardet for compatibility. major, minor, patch = chardet_version.split('.')[:3] diff --git a/requests/__version__.py b/requests/__version__.py index f5b5d03671..9844f740ab 100644 --- a/requests/__version__.py +++ b/requests/__version__.py @@ -5,10 +5,10 @@ __title__ = 'requests' __description__ = 'Python HTTP for Humans.' __url__ = 'http://python-requests.org' -__version__ = '2.21.0' -__build__ = 0x022100 +__version__ = '2.22.0' +__build__ = 0x022200 __author__ = 'Kenneth Reitz' __author_email__ = 'me@kennethreitz.org' __license__ = 'Apache 2.0' -__copyright__ = 'Copyright 2018 Kenneth Reitz' +__copyright__ = 'Copyright 2019 Kenneth Reitz' __cake__ = u'\u2728 \U0001f370 \u2728' diff --git a/requests/adapters.py b/requests/adapters.py index fa4d9b3cc9..97ea25b42a 100644 --- a/requests/adapters.py +++ b/requests/adapters.py @@ -435,64 +435,19 @@ def send(self, request, stream=False, timeout=None, verify=True, cert=None, prox timeout = TimeoutSauce(connect=timeout, read=timeout) try: - if not chunked: - resp = conn.urlopen( - method=request.method, - url=url, - body=request.body, - headers=request.headers, - redirect=False, - assert_same_host=False, - preload_content=False, - decode_content=False, - retries=self.max_retries, - timeout=timeout - ) - - # Send the request. - else: - if hasattr(conn, 'proxy_pool'): - conn = conn.proxy_pool - - low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT) - - try: - low_conn.putrequest(request.method, - url, - skip_accept_encoding=True) - - for header, value in request.headers.items(): - low_conn.putheader(header, value) - - low_conn.endheaders() - - for i in request.body: - low_conn.send(hex(len(i))[2:].encode('utf-8')) - low_conn.send(b'\r\n') - low_conn.send(i) - low_conn.send(b'\r\n') - low_conn.send(b'0\r\n\r\n') - - # Receive the response from the server - try: - # For Python 2.7, use buffering of HTTP responses - r = low_conn.getresponse(buffering=True) - except TypeError: - # For compatibility with Python 3.3+ - r = low_conn.getresponse() - - resp = HTTPResponse.from_httplib( - r, - pool=conn, - connection=low_conn, - preload_content=False, - decode_content=False - ) - except: - # If we hit any problems here, clean up the connection. - # Then, reraise so that we can handle the actual exception. - low_conn.close() - raise + resp = conn.urlopen( + method=request.method, + url=url, + body=request.body, + headers=request.headers, + redirect=False, + assert_same_host=False, + preload_content=False, + decode_content=False, + retries=self.max_retries, + timeout=timeout, + chunked=chunked + ) except (ProtocolError, socket.error) as err: raise ConnectionError(err, request=request) diff --git a/requests/api.py b/requests/api.py index ef71d0759e..e978e20311 100644 --- a/requests/api.py +++ b/requests/api.py @@ -16,7 +16,7 @@ def request(method, url, **kwargs): """Constructs and sends a :class:`Request `. - :param method: method for the new :class:`Request` object. + :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``. :param url: URL for the new :class:`Request` object. :param params: (optional) Dictionary, list of tuples or bytes to send in the query string for the :class:`Request`. @@ -50,6 +50,7 @@ def request(method, url, **kwargs): >>> import requests >>> req = requests.request('GET', 'https://httpbin.org/get') + >>> req """ @@ -92,7 +93,9 @@ def head(url, **kwargs): r"""Sends a HEAD request. :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. + :param \*\*kwargs: Optional arguments that ``request`` takes. If + `allow_redirects` is not provided, it will be set to `False` (as + opposed to the default :meth:`request` behavior). :return: :class:`Response ` object :rtype: requests.Response """ diff --git a/requests/auth.py b/requests/auth.py index bdde51c7fd..eeface39ae 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -50,7 +50,7 @@ def _basic_auth_str(username, password): "Non-string passwords will no longer be supported in Requests " "3.0.0. Please convert the object you've passed in ({!r}) to " "a string or bytes object in the near future to avoid " - "problems.".format(password), + "problems.".format(type(password)), category=DeprecationWarning, ) password = str(password) @@ -239,7 +239,7 @@ def handle_401(self, r, **kwargs): """ # If response is not 4xx, do not auth - # See https://github.com/requests/requests/issues/3772 + # See https://github.com/psf/requests/issues/3772 if not 400 <= r.status_code < 500: self._thread_local.num_401_calls = 1 return r diff --git a/requests/compat.py b/requests/compat.py index c44b35efb9..5de0769f50 100644 --- a/requests/compat.py +++ b/requests/compat.py @@ -43,6 +43,7 @@ import cookielib from Cookie import Morsel from StringIO import StringIO + # Keep OrderedDict for backwards compatibility. from collections import Callable, Mapping, MutableMapping, OrderedDict @@ -59,6 +60,7 @@ from http import cookiejar as cookielib from http.cookies import Morsel from io import StringIO + # Keep OrderedDict for backwards compatibility. from collections import OrderedDict from collections.abc import Callable, Mapping, MutableMapping diff --git a/requests/models.py b/requests/models.py index 62dcd0b7c8..a60b5f4490 100644 --- a/requests/models.py +++ b/requests/models.py @@ -12,7 +12,7 @@ # Import encoding now, to avoid implicit import later. # Implicit import within threads may cause LookupError when standard library is in a ZIP, -# such as in Embedded Python. See https://github.com/requests/requests/issues/3578. +# such as in Embedded Python. See https://github.com/psf/requests/issues/3578. import encodings.idna from urllib3.fields import RequestField @@ -280,6 +280,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): >>> import requests >>> req = requests.Request('GET', 'https://httpbin.org/get') >>> r = req.prepare() + >>> r >>> s = requests.Session() @@ -358,7 +359,7 @@ def prepare_url(self, url, params): #: We're unable to blindly call unicode/str functions #: as this will include the bytestring indicator (b'') #: on python 3.x. - #: https://github.com/requests/requests/pull/2238 + #: https://github.com/psf/requests/pull/2238 if isinstance(url, bytes): url = url.decode('utf8') else: @@ -608,7 +609,7 @@ def __init__(self): #: File-like object representation of response (for advanced usage). #: Use of ``raw`` requires that ``stream=True`` be set on the request. - # This requirement does not apply for use internally to Requests. + #: This requirement does not apply for use internally to Requests. self.raw = None #: Final URL location of Response. @@ -640,6 +641,10 @@ def __init__(self): #: is a response. self.request = None + #: If there was an error in the processing of content, + #: then save the error that would return the same error when you re-appeal. + self._error = None + def __enter__(self): return self @@ -749,12 +754,21 @@ def generate(): try: for chunk in self.raw.stream(chunk_size, decode_content=True): yield chunk + except ProtocolError as e: - raise ChunkedEncodingError(e) + self._error = ChunkedEncodingError(e) + except DecodeError as e: - raise ContentDecodingError(e) + self._error = ContentDecodingError(e) + except ReadTimeoutError as e: - raise ConnectionError(e) + self._error = ConnectionError(e) + + finally: + # if we had an error - throw the saved error + if self._error: + raise self._error + else: # Standard file-like object. while True: @@ -827,6 +841,10 @@ def content(self): else: self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b'' + # if we had an error - throw the saved error + if self._error is not None: + raise self._error + self._content_consumed = True # don't need to release the connection; that's been handled by urllib3 # since we exhausted the data. @@ -855,6 +873,9 @@ def text(self): # Fallback to auto-detected encoding. if self.encoding is None: encoding = self.apparent_encoding + # Forcefully remove BOM from UTF-8 + elif self.encoding.lower() == 'utf-8': + encoding = 'utf-8-sig' # Decode unicode from given encoding. try: diff --git a/requests/sessions.py b/requests/sessions.py index 756c82bfa5..4d7dd24f4b 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -11,9 +11,10 @@ import sys import time from datetime import timedelta +from collections import OrderedDict from .auth import _basic_auth_str -from .compat import cookielib, is_py3, OrderedDict, urljoin, urlparse, Mapping +from .compat import cookielib, is_py3, urljoin, urlparse, Mapping from .cookies import ( cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies) from .models import Request, PreparedRequest, DEFAULT_REDIRECT_LIMIT @@ -94,6 +95,10 @@ def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): class SessionRedirectMixin(object): + def __init__(self): + #: A list of domains that will be excluded from auth stripping + self.trusted_domains = [] + def get_redirect_target(self, resp): """Receives a Response. Returns a redirect URI or ``None``""" # Due to the nature of how requests processes redirects this method will @@ -119,7 +124,8 @@ def should_strip_auth(self, old_url, new_url): """Decide whether Authorization header should be removed when redirecting""" old_parsed = urlparse(old_url) new_parsed = urlparse(new_url) - if old_parsed.hostname != new_parsed.hostname: + if (old_parsed.hostname != new_parsed.hostname + and new_parsed.hostname not in self.trusted_domains): return True # Special case: allow http -> https redirect when using the standard # ports. This isn't specified by RFC 7235, but is kept to avoid @@ -162,7 +168,7 @@ def resolve_redirects(self, resp, req, stream=False, timeout=None, resp.raw.read(decode_content=False) if len(resp.history) >= self.max_redirects: - raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp) + raise TooManyRedirects('Exceeded {} redirects.'.format(self.max_redirects), response=resp) # Release the connection back into the pool. resp.close() @@ -170,7 +176,7 @@ def resolve_redirects(self, resp, req, stream=False, timeout=None, # Handle redirection without scheme (see: RFC 1808 Section 4) if url.startswith('//'): parsed_rurl = urlparse(resp.url) - url = '%s:%s' % (to_native_string(parsed_rurl.scheme), url) + url = ':'.join([to_native_string(parsed_rurl.scheme), url]) # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2) parsed = urlparse(url) @@ -192,19 +198,16 @@ def resolve_redirects(self, resp, req, stream=False, timeout=None, self.rebuild_method(prepared_request, resp) - # https://github.com/requests/requests/issues/1084 + # https://github.com/psf/requests/issues/1084 if resp.status_code not in (codes.temporary_redirect, codes.permanent_redirect): - # https://github.com/requests/requests/issues/3490 + # https://github.com/psf/requests/issues/3490 purged_headers = ('Content-Length', 'Content-Type', 'Transfer-Encoding') for header in purged_headers: prepared_request.headers.pop(header, None) prepared_request.body = None headers = prepared_request.headers - try: - del headers['Cookie'] - except KeyError: - pass + headers.pop('Cookie', None) # Extract any cookies sent on the response to the cookiejar # in the new request. Because we've mutated our copied prepared @@ -271,7 +274,6 @@ def rebuild_auth(self, prepared_request, response): if new_auth is not None: prepared_request.prepare_auth(new_auth) - return def rebuild_proxies(self, prepared_request, proxies): """This method re-evaluates the proxy configuration by considering the @@ -352,7 +354,7 @@ class Session(SessionRedirectMixin): Or as a context manager:: >>> with requests.Session() as s: - >>> s.get('https://httpbin.org/get') + ... s.get('https://httpbin.org/get') """ @@ -417,6 +419,8 @@ def __init__(self): self.mount('https://', HTTPAdapter()) self.mount('http://', HTTPAdapter()) + super().__init__() + def __enter__(self): return self @@ -728,7 +732,7 @@ def get_adapter(self, url): return adapter # Nothing matches :-/ - raise InvalidSchema("No connection adapters were found for '%s'" % url) + raise InvalidSchema("No connection adapters were found for {!r}".format(url)) def close(self): """Closes all adapters and as such the session""" diff --git a/requests/status_codes.py b/requests/status_codes.py index 813e8c4e62..4e99ad73df 100644 --- a/requests/status_codes.py +++ b/requests/status_codes.py @@ -4,7 +4,7 @@ The ``codes`` object defines a mapping from common names for HTTP statuses to their numerical codes, accessible either as attributes or as dictionary items. - +>>> import requests >>> requests.codes['temporary_redirect'] 307 >>> requests.codes.teapot diff --git a/requests/structures.py b/requests/structures.py index da930e2852..8ee0ba7a08 100644 --- a/requests/structures.py +++ b/requests/structures.py @@ -7,7 +7,9 @@ Data structures that power Requests. """ -from .compat import OrderedDict, Mapping, MutableMapping +from collections import OrderedDict + +from .compat import Mapping, MutableMapping class CaseInsensitiveDict(MutableMapping): diff --git a/requests/utils.py b/requests/utils.py index 8170a8d2c4..c1700d7fe8 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -19,6 +19,7 @@ import tempfile import warnings import zipfile +from collections import OrderedDict from .__version__ import __version__ from . import certs @@ -26,7 +27,7 @@ from ._internal_utils import to_native_string from .compat import parse_http_list as _parse_list_header from .compat import ( - quote, urlparse, bytes, str, OrderedDict, unquote, getproxies, + quote, urlparse, bytes, str, unquote, getproxies, proxy_bypass, urlunparse, basestring, integer_types, is_py3, proxy_bypass_environment, getproxies_environment, Mapping) from .cookies import cookiejar_from_dict @@ -179,7 +180,7 @@ def get_netrc_auth(url, raise_errors=False): except KeyError: # os.path.expanduser can fail when $HOME is undefined and # getpwuid fails. See https://bugs.python.org/issue20164 & - # https://github.com/requests/requests/issues/1846 + # https://github.com/psf/requests/issues/1846 return if os.path.exists(loc): @@ -266,6 +267,8 @@ def from_key_val_list(value): >>> from_key_val_list([('key', 'val')]) OrderedDict([('key', 'val')]) >>> from_key_val_list('string') + Traceback (most recent call last): + ... ValueError: cannot encode objects that are not 2-tuples >>> from_key_val_list({'key': 'val'}) OrderedDict([('key', 'val')]) @@ -292,7 +295,9 @@ def to_key_val_list(value): >>> to_key_val_list({'key': 'val'}) [('key', 'val')] >>> to_key_val_list('string') - ValueError: cannot encode objects that are not 2-tuples. + Traceback (most recent call last): + ... + ValueError: cannot encode objects that are not 2-tuples :rtype: list """ diff --git a/setup.py b/setup.py index 10ce2c6213..d0fb1e53ce 100755 --- a/setup.py +++ b/setup.py @@ -44,7 +44,7 @@ def run_tests(self): requires = [ 'chardet>=3.0.2,<3.1.0', 'idna>=2.5,<2.9', - 'urllib3>=1.21.1,<1.25', + 'urllib3>=1.21.1,<1.26,!=1.25.0,!=1.25.1', 'certifi>=2017.4.17' ] @@ -54,7 +54,7 @@ def run_tests(self): 'pytest-mock', 'pytest-xdist', 'PySocks>=1.5.6, !=1.5.7', - 'pytest>=2.8.0' + 'pytest>=3' ] about = {} @@ -79,7 +79,7 @@ def run_tests(self): package_data={'': ['LICENSE', 'NOTICE'], 'requests': ['*.pem']}, package_dir={'requests': 'requests'}, include_package_data=True, - python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", install_requires=requires, license=about['__license__'], zip_safe=False, @@ -92,10 +92,10 @@ def run_tests(self): 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy' ], @@ -106,4 +106,8 @@ def run_tests(self): 'socks': ['PySocks>=1.5.6, !=1.5.7'], 'socks:sys_platform == "win32" and python_version == "2.7"': ['win_inet_pton'], }, + project_urls={ + 'Documentation': 'http://docs.python-requests.org', + 'Source': 'https://github.com/kennethreitz/requests', + }, ) diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py index 82c3b25a1d..4178c78a9d 100644 --- a/tests/test_lowlevel.py +++ b/tests/test_lowlevel.py @@ -3,6 +3,7 @@ import pytest import threading import requests +from requests.exceptions import ChunkedEncodingError from tests.testserver.server import Server, consume_socket_content @@ -28,7 +29,7 @@ def test_digestauth_401_count_reset_on_redirect(): """Ensure we correctly reset num_401_calls after a successful digest auth, followed by a 302 redirect to another digest auth prompt. - See https://github.com/requests/requests/issues/1979. + See https://github.com/psf/requests/issues/1979. """ text_401 = (b'HTTP/1.1 401 UNAUTHORIZED\r\n' b'Content-Length: 0\r\n' @@ -138,7 +139,7 @@ def digest_failed_response_handler(sock): def test_digestauth_only_on_4xx(): """Ensure we only send digestauth on 4xx challenges. - See https://github.com/requests/requests/issues/3772. + See https://github.com/psf/requests/issues/3772. """ text_200_chal = (b'HTTP/1.1 200 OK\r\n' b'Content-Length: 0\r\n' @@ -307,3 +308,43 @@ def response_handler(sock): assert r.url == 'http://{}:{}/final-url/#relevant-section'.format(host, port) close_server.set() + + +def test_response_content_retains_error(): + """Verify that accessing response.content retains an error. + + See https://github.com/kennethreitz/requests/issues/4965 + """ + + data = "Some random stuff to read from remove server.\n" + + def response_handler(sock): + req = consume_socket_content(sock, timeout=0.5) + + # Send invalid chunked data (length mismatch) + sock.send( + b'HTTP/1.1 200 OK\r\n' + b'Transfer-Encoding: chunked\r\n' + b'\r\n2\r\n42\r\n8\r\n123\r\n' # 5 bytes missing + ) + + close_server = threading.Event() + server = Server(response_handler, wait_to_close_event=close_server) + + with server as (host, port): + url = 'http://{}:{}/path'.format(host, port) + r = requests.post(url, stream=True) + with pytest.raises(ChunkedEncodingError): + r.content + + # Access the bad response data again, I would expect the same + # error again. + + try: + content = r.content + except ChunkedEncodingError: + pass # fine, same exception + else: + assert False, "error response has content: {0!r}".format(content) + close_server.set() + diff --git a/tests/test_requests.py b/tests/test_requests.py index 4bc1924f03..7d4a4eb510 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -9,6 +9,7 @@ import collections import contextlib import warnings +import re import io import requests @@ -17,7 +18,7 @@ from requests.auth import HTTPDigestAuth, _basic_auth_str from requests.compat import ( Morsel, cookielib, getproxies, str, urlparse, - builtin_str, OrderedDict) + builtin_str) from requests.cookies import ( cookiejar_from_dict, morsel_to_cookie) from requests.exceptions import ( @@ -129,7 +130,7 @@ def test_params_are_added_before_fragment(self, url, expected): assert request.url == expected def test_params_original_order_is_preserved_by_default(self): - param_ordered_dict = OrderedDict((('z', 1), ('a', 1), ('k', 1), ('d', 1))) + param_ordered_dict = collections.OrderedDict((('z', 1), ('a', 1), ('k', 1), ('d', 1))) session = requests.Session() request = requests.Request('GET', 'http://example.com/', params=param_ordered_dict) prep = session.prepare_request(request) @@ -445,11 +446,11 @@ def test_headers_on_session_with_None_are_not_sent(self, httpbin): def test_headers_preserve_order(self, httpbin): """Preserve order when headers provided as OrderedDict.""" ses = requests.Session() - ses.headers = OrderedDict() + ses.headers = collections.OrderedDict() ses.headers['Accept-Encoding'] = 'identity' ses.headers['First'] = '1' ses.headers['Second'] = '2' - headers = OrderedDict([('Third', '3'), ('Fourth', '4')]) + headers = collections.OrderedDict([('Third', '3'), ('Fourth', '4')]) headers['Fifth'] = '5' headers['Second'] = '222' req = requests.Request('GET', httpbin('get'), headers=headers) @@ -465,7 +466,7 @@ def test_headers_preserve_order(self, httpbin): @pytest.mark.parametrize('key', ('User-agent', 'user-agent')) def test_user_agent_transfers(self, httpbin, key): - heads = {key: 'Mozilla/5.0 (github.com/requests/requests)'} + heads = {key: 'Mozilla/5.0 (github.com/psf/requests)'} r = requests.get(httpbin('user-agent'), headers=heads) assert heads[key] in r.text @@ -2211,7 +2212,7 @@ def test_total_timeout_connect(self, timeout): pass def test_encoded_methods(self, httpbin): - """See: https://github.com/requests/requests/issues/2316""" + """See: https://github.com/psf/requests/issues/2316""" r = requests.request(b'GET', httpbin('get')) assert r.ok @@ -2418,9 +2419,17 @@ class TestPreparingURLs(object): ) ) def test_preparing_url(self, url, expected): + + def normalize_percent_encode(x): + # Helper function that normalizes equivalent + # percent-encoded bytes before comparisons + for c in re.findall(r'%[a-fA-F0-9]{2}', x): + x = x.replace(c, c.upper()) + return x + r = requests.Request('GET', url=url) p = r.prepare() - assert p.url == expected + assert normalize_percent_encode(p.url) == expected @pytest.mark.parametrize( 'url', diff --git a/tests/test_testserver.py b/tests/test_testserver.py index aac529261b..9d9def2f1b 100644 --- a/tests/test_testserver.py +++ b/tests/test_testserver.py @@ -56,6 +56,36 @@ def test_text_response(self): assert r.text == u'roflol' assert r.headers['Content-Length'] == '6' + def test_text_bom_response(self): + """the text_response_server sends the given text with UTF-8 BOM""" + server = Server.text_response_server( + "HTTP/1.1 200 OK\r\n" + + "Content-Type: text/html; charset=UTF-8\r\n" + + u'\r\n\ufeffジェーピーニック' + ) + + with server as (host, port): + r = requests.get('http://{}:{}'.format(host, port)) + + assert r.status_code == 200 + assert r.text == u'ジェーピーニック' + assert r.headers['Content-Type'] == 'text/html; charset=UTF-8' + + def test_json_bom_response(self): + """the text_response_server sends the given JSON with UTF-8 BOM""" + server = Server.text_response_server( + "HTTP/1.1 200 OK\r\n" + + "Content-Type: application/json; charset=utf-8\r\n" + + u'\r\n\ufeff{"success": true}' + ) + + with server as (host, port): + r = requests.get('http://{}:{}'.format(host, port)) + + assert r.status_code == 200 + assert r.json() == {'success': True} + assert r.headers['Content-Type'] == 'application/json; charset=utf-8' + def test_basic_response(self): """the basic response server returns an empty http response""" with Server.basic_response_server() as (host, port): diff --git a/tests/test_utils.py b/tests/test_utils.py index 59b0b0efaf..ae51770556 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -33,7 +33,8 @@ class TestSuperLen: 'stream, value', ( (StringIO.StringIO, 'Test'), (BytesIO, b'Test'), - pytest.mark.skipif('cStringIO is None')((cStringIO, 'Test')), + pytest.param(cStringIO, 'Test', + marks=pytest.mark.skipif('cStringIO is None')), )) def test_io_streams(self, stream, value): """Ensures that we properly deal with different kinds of IO streams.""" @@ -332,6 +333,7 @@ def test_bad_utf_like_encoding(self): @pytest.mark.parametrize( ('encoding', 'expected'), ( + ('utf-8-sig', 'utf-8-sig'), ('utf-16-be', 'utf-16'), ('utf-16-le', 'utf-16'), ('utf-32-be', 'utf-32'), @@ -397,7 +399,7 @@ def test_get_auth_from_url(url, auth): ), )) def test_requote_uri_with_unquoted_percents(uri, expected): - """See: https://github.com/requests/requests/issues/2356""" + """See: https://github.com/psf/requests/issues/2356""" assert requote_uri(uri) == expected diff --git a/tox.ini b/tox.ini index de68e90d38..99c87ced01 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27,py34,py35,py36,py37 +envlist = py27,py35,py36,py37 [testenv]