diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5c4ff15a89..3470dfee83 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,10 +1,7 @@ # Contribution Guidelines -Before opening any issues or proposing any pull requests, please do the -following: - -1. Read our [Contributor's Guide](https://requests.readthedocs.io/en/latest/dev/contributing/). -2. Understand our [development philosophy](https://requests.readthedocs.io/en/latest/dev/philosophy/). +Before opening any issues or proposing any pull requests, please read +our [Contributor's Guide](https://requests.readthedocs.io/en/latest/dev/contributing/). To get the greatest chance of helpful responses, please also observe the following additional notes. diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index daf7752402..603c7ff9c3 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -custom: ['https://www.python.org/psf/forms/sponsor-application/'] +custom: ['https://www.python.org/psf/sponsorship/'] diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000000..bf1463909c --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,66 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +name: "CodeQL" + +on: + push: + branches: [master] + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + schedule: + - cron: '0 23 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: "python" + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000000..e7273028cf --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,31 @@ +name: Tests + +on: [push, pull_request] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] + os: [ubuntu-18.04, macOS-latest, windows-latest] + include: + # pypy3 on Mac OS currently fails trying to compile + # brotlipy. Moving pypy3 to only test linux. + - python-version: pypy3 + os: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + make + - name: Run tests + run: | + make ci diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6d0962a865..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: python -# command to install dependencies -install: "make" -# command to run tests -script: - - make test-readme - - make ci -cache: pip -jobs: - include: - - stage: test - python: '2.7' - - stage: test - python: '3.5' - - stage: test - python: '3.6' - - stage: test - python: '3.7' - - stage: test - python: 'pypy3' - dist: xenial - - stage: test - python: '3.8' - - stage: coverage - python: '3.6' - script: codecov diff --git a/AUTHORS.rst b/AUTHORS.rst index 424493b149..f434910468 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -8,7 +8,7 @@ Keepers of the Crystals Previous Keepers of Crystals ```````````````````````````` -- Kenneth Reitz `@kennethreitz `_, reluctant Keeper of the Master Crystal. +- Kenneth Reitz `@ken-reitz `_, reluctant Keeper of the Master Crystal. - Cory Benfield `@lukasa `_ - Ian Cordasco `@sigmavirus24 `_. @@ -190,3 +190,4 @@ Patches and Suggestions - Antti Kaihola (`@akaihola `_) - "Dull Bananas" (`@dullbananas `_) - Alessio Izzo (`@aless10 `_) +- Sylvain Marié (`@smarie `_) diff --git a/HISTORY.md b/HISTORY.md index d42af0ca38..0331d187f7 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,35 @@ dev - \[Short description of non-trivial change.\] +2.25.1 (2020-12-16) +------------------- + +**Bugfixes** + +- Requests now treats `application/json` as `utf8` by default. Resolving + inconsistencies between `r.text` and `r.json` output. (#5673) + +**Dependencies** + +- Requests now supports chardet v4.x. + +2.25.0 (2020-11-11) +------------------ + +**Improvements** + +- Added support for NETRC environment variable. (#5643) + +**Dependencies** + +- Requests now supports urllib3 v1.26. + +**Deprecations** + +- Requests v2.25.x will be the last release series with support for Python 3.5. +- The `requests[security]` extra is officially deprecated and will be removed + in Requests v2.26.0. + 2.24.0 (2020-06-17) ------------------- diff --git a/LICENSE b/LICENSE index 13d91ddc7a..67db858821 100644 --- a/LICENSE +++ b/LICENSE @@ -1,13 +1,175 @@ -Copyright 2019 Kenneth Reitz - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ - https://www.apache.org/licenses/LICENSE-2.0 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/MANIFEST.in b/MANIFEST.in index 172ccc8412..633be369e2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ -include README.md LICENSE NOTICE HISTORY.md pytest.ini requirements.txt Pipfile Pipfile.lock +include README.md LICENSE NOTICE HISTORY.md pytest.ini requirements-dev.txt recursive-include tests *.py diff --git a/Makefile b/Makefile index 231ce35775..a3fa4c2edc 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,21 @@ .PHONY: docs init: - pip install pipenv --upgrade - pipenv install --dev + pip install -e .[socks] + pip install -r requirements-dev.txt test: # This runs all of the tests, on both Python 2 and Python 3. detox ci: - pipenv run py.test -n 8 --boxed --junitxml=report.xml + pytest tests --junitxml=report.xml test-readme: - @pipenv run python setup.py check --restructuredtext --strict && ([ $$? -eq 0 ] && echo "README.rst and HISTORY.rst ok") || echo "Invalid markup in README.rst or HISTORY.rst!" + python setup.py check --restructuredtext --strict && ([ $$? -eq 0 ] && echo "README.rst and HISTORY.rst ok") || echo "Invalid markup in README.rst or HISTORY.rst!" flake8: - pipenv run flake8 --ignore=E501,F401,E128,E402,E731,F821 requests + flake8 --ignore=E501,F401,E128,E402,E731,F821 requests coverage: - pipenv run py.test --cov-config .coveragerc --verbose --cov-report term --cov-report xml --cov=requests tests + pytest --cov-config .coveragerc --verbose --cov-report term --cov-report xml --cov=requests tests publish: pip install 'twine>=1.5.0' @@ -25,4 +25,4 @@ publish: docs: cd docs && make html - @echo "\033[95m\n\nBuild successful! View the docs homepage at docs/_build/html/index.html.\n\033[0m" \ No newline at end of file + @echo "\033[95m\n\nBuild successful! View the docs homepage at docs/_build/html/index.html.\n\033[0m" diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000000..1ff62db688 --- /dev/null +++ b/NOTICE @@ -0,0 +1,2 @@ +Requests +Copyright 2019 Kenneth Reitz diff --git a/Pipfile b/Pipfile deleted file mode 100644 index d18d4cc111..0000000000 --- a/Pipfile +++ /dev/null @@ -1,25 +0,0 @@ -[[source]] -url = "https://pypi.org/simple/" -verify_ssl = true -name = "pypi" - -[dev-packages] -alabaster = "*" -codecov = "*" -docutils = "*" -detox = "*" -"flake8" = "*" -httpbin = ">=0.7.0" -more-itertools = "<6.0" -pysocks = "*" -pytest = ">=2.8.0,<=3.10.1" -pytest-httpbin = ">=0.0.7,<1.0" -pytest-mock = "*" -pytest-cov = "*" -pytest-xdist = "<=1.25" -readme-renderer = "*" -sphinx = "<=1.5.5" -tox = "*" - -[packages] -"requests" = {path = ".", editable = true, extras = ["socks"]} diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 393ea0a09b..0000000000 --- a/Pipfile.lock +++ /dev/null @@ -1,765 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "9c8d31d74dee008bc23d846267f23665288b0b1bee2525baca681d1061726701" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple/", - "verify_ssl": true - } - ] - }, - "default": { - "certifi": { - "hashes": [ - "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", - "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" - ], - "version": "==2019.11.28" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "idna": { - "hashes": [ - "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", - "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" - ], - "version": "==2.9" - }, - "pysocks": { - "hashes": [ - "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", - "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", - "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" - ], - "version": "==1.7.1" - }, - "requests": { - "editable": true, - "extras": [ - "socks" - ], - "path": "." - }, - "urllib3": { - "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" - ], - "version": "==1.25.8" - } - }, - "develop": { - "alabaster": { - "hashes": [ - "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", - "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" - ], - "index": "pypi", - "version": "==0.7.12" - }, - "apipkg": { - "hashes": [ - "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6", - "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c" - ], - "version": "==1.5" - }, - "appdirs": { - "hashes": [ - "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", - "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" - ], - "version": "==1.4.3" - }, - "atomicwrites": { - "hashes": [ - "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", - "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" - ], - "version": "==1.3.0" - }, - "attrs": { - "hashes": [ - "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", - "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" - ], - "version": "==19.3.0" - }, - "babel": { - "hashes": [ - "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", - "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" - ], - "version": "==2.8.0" - }, - "bleach": { - "hashes": [ - "sha256:cc8da25076a1fe56c3ac63671e2194458e0c4d9c7becfd52ca251650d517903c", - "sha256:e78e426105ac07026ba098f04de8abe9b6e3e98b5befbf89b51a5ef0a4292b03" - ], - "version": "==3.1.4" - }, - "blinker": { - "hashes": [ - "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6" - ], - "version": "==1.4" - }, - "brotlipy": { - "hashes": [ - "sha256:07194f4768eb62a4f4ea76b6d0df6ade185e24ebd85877c351daa0a069f1111a", - "sha256:091b299bf36dd6ef7a06570dbc98c0f80a504a56c5b797f31934d2ad01ae7d17", - "sha256:09ec3e125d16749b31c74f021aba809541b3564e5359f8c265cbae442810b41a", - "sha256:0be698678a114addcf87a4b9496c552c68a2c99bf93cf8e08f5738b392e82057", - "sha256:0fa6088a9a87645d43d7e21e32b4a6bf8f7c3939015a50158c10972aa7f425b7", - "sha256:1379347337dc3d20b2d61456d44ccce13e0625db2611c368023b4194d5e2477f", - "sha256:1ea4e578241504b58f2456a6c69952c88866c794648bdc74baee74839da61d44", - "sha256:2699945a0a992c04fc7dc7fa2f1d0575a2c8b4b769f2874a08e8eae46bef36ae", - "sha256:2a80319ae13ea8dd60ecdc4f5ccf6da3ae64787765923256b62c598c5bba4121", - "sha256:2e5c64522364a9ebcdf47c5744a5ddeb3f934742d31e61ebfbbc095460b47162", - "sha256:36def0b859beaf21910157b4c33eb3b06d8ce459c942102f16988cca6ea164df", - "sha256:3a3e56ced8b15fbbd363380344f70f3b438e0fd1fcf27b7526b6172ea950e867", - "sha256:3c1d5e2cf945a46975bdb11a19257fa057b67591eb232f393d260e7246d9e571", - "sha256:4e4638b49835d567d447a2cfacec109f9a777f219f071312268b351b6839436d", - "sha256:50ca336374131cfad20612f26cc43c637ac0bfd2be3361495e99270883b52962", - "sha256:5de6f7d010b7558f72f4b061a07395c5c3fd57f0285c5af7f126a677b976a868", - "sha256:637847560d671657f993313ecc6c6c6666a936b7a925779fd044065c7bc035b9", - "sha256:653faef61241bf8bf99d73ca7ec4baa63401ba7b2a2aa88958394869379d67c7", - "sha256:786afc8c9bd67de8d31f46e408a3386331e126829114e4db034f91eacb05396d", - "sha256:79aaf217072840f3e9a3b641cccc51f7fc23037496bd71e26211856b93f4b4cb", - "sha256:7e31f7adcc5851ca06134705fcf3478210da45d35ad75ec181e1ce9ce345bb38", - "sha256:8b39abc3256c978f575df5cd7893153277216474f303e26f0e43ba3d3969ef96", - "sha256:9448227b0df082e574c45c983fa5cd4bda7bfb11ea6b59def0940c1647be0c3c", - "sha256:96bc59ff9b5b5552843dc67999486a220e07a0522dddd3935da05dc194fa485c", - "sha256:a07647886e24e2fb2d68ca8bf3ada398eb56fd8eac46c733d4d95c64d17f743b", - "sha256:af65d2699cb9f13b26ec3ba09e75e80d31ff422c03675fcb36ee4dabe588fdc2", - "sha256:b4c98b0d2c9c7020a524ca5bbff42027db1004c6571f8bc7b747f2b843128e7a", - "sha256:c6cc0036b1304dd0073eec416cb2f6b9e37ac8296afd9e481cac3b1f07f9db25", - "sha256:d2c1c724c4ac375feb2110f1af98ecdc0e5a8ea79d068efb5891f621a5b235cb", - "sha256:dc6c5ee0df9732a44d08edab32f8a616b769cc5a4155a12d2d010d248eb3fb07", - "sha256:fd1d1c64214af5d90014d82cee5d8141b13d44c92ada7a0c0ec0679c6f15a471" - ], - "version": "==0.7.0" - }, - "certifi": { - "hashes": [ - "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", - "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" - ], - "version": "==2019.11.28" - }, - "cffi": { - "hashes": [ - "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff", - "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b", - "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac", - "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0", - "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384", - "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26", - "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6", - "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b", - "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e", - "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd", - "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2", - "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66", - "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc", - "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8", - "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55", - "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4", - "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5", - "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d", - "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78", - "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa", - "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793", - "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f", - "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a", - "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f", - "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30", - "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f", - "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3", - "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c" - ], - "version": "==1.14.0" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "click": { - "hashes": [ - "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", - "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" - ], - "version": "==7.1.1" - }, - "codecov": { - "hashes": [ - "sha256:09fb045eb044a619cd2b9dacd7789ae8e322cb7f18196378579fd8d883e6b665", - "sha256:aeeefa3a03cac8a78e4f988e935b51a4689bb1f17f20d4e827807ee11135f845" - ], - "index": "pypi", - "version": "==2.0.22" - }, - "configparser": { - "hashes": [ - "sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c", - "sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df" - ], - "markers": "python_version < '3.2'", - "version": "==4.0.2" - }, - "contextlib2": { - "hashes": [ - "sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e", - "sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b" - ], - "markers": "python_version < '3.2'", - "version": "==0.6.0.post1" - }, - "coverage": { - "hashes": [ - "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0", - "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30", - "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b", - "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0", - "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823", - "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe", - "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037", - "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6", - "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31", - "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd", - "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892", - "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1", - "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78", - "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac", - "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006", - "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014", - "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2", - "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7", - "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8", - "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7", - "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9", - "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1", - "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307", - "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a", - "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435", - "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0", - "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5", - "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441", - "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732", - "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de", - "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1" - ], - "version": "==5.0.4" - }, - "decorator": { - "hashes": [ - "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760", - "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7" - ], - "version": "==4.4.2" - }, - "detox": { - "hashes": [ - "sha256:e650f95f0c7f5858578014b3b193e5dac76c89285c1bbe4bae598fd641bf9cd3", - "sha256:fcad009e2d20ce61176dc826a2c1562bd712fe53953ca603b455171cf819080f" - ], - "index": "pypi", - "version": "==0.19" - }, - "distlib": { - "hashes": [ - "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21" - ], - "version": "==0.3.0" - }, - "dnspython": { - "hashes": [ - "sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01", - "sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d" - ], - "version": "==1.16.0" - }, - "docutils": { - "hashes": [ - "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", - "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" - ], - "index": "pypi", - "version": "==0.16" - }, - "entrypoints": { - "hashes": [ - "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", - "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" - ], - "version": "==0.3" - }, - "enum34": { - "hashes": [ - "sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53", - "sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328", - "sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248" - ], - "markers": "python_version == '2.7' or python_version == '3.3'", - "version": "==1.1.10" - }, - "eventlet": { - "hashes": [ - "sha256:658b1cd80937adc1a4860de2841e0528f64e2ca672885c4e00fc0e2217bde6b1", - "sha256:6c9c625af48424c4680d89314dbe45a76cc990cf002489f9469ff214b044ffc1" - ], - "version": "==0.25.1" - }, - "execnet": { - "hashes": [ - "sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50", - "sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547" - ], - "version": "==1.7.1" - }, - "filelock": { - "hashes": [ - "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", - "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" - ], - "version": "==3.0.12" - }, - "flake8": { - "hashes": [ - "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", - "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" - ], - "index": "pypi", - "version": "==3.7.9" - }, - "flask": { - "hashes": [ - "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060", - "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557" - ], - "version": "==1.1.2" - }, - "funcsigs": { - "hashes": [ - "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", - "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" - ], - "markers": "python_version < '3.0'", - "version": "==1.0.2" - }, - "functools32": { - "hashes": [ - "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0", - "sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d" - ], - "markers": "python_version < '3.2'", - "version": "==3.2.3.post2" - }, - "greenlet": { - "hashes": [ - "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0", - "sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28", - "sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8", - "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304", - "sha256:51155342eb4d6058a0ffcd98a798fe6ba21195517da97e15fca3db12ab201e6e", - "sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0", - "sha256:7457d685158522df483196b16ec648b28f8e847861adb01a55d41134e7734122", - "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", - "sha256:e538b8dae561080b542b0f5af64d47ef859f22517f7eca617bb314e0e03fd7ef" - ], - "version": "==0.4.15" - }, - "httpbin": { - "hashes": [ - "sha256:7a04b5904c80b7aa04dd0a6af6520d68ce17a5db175e66a64b971f8e93d73a26", - "sha256:cbb37790c91575f4f15757f42ad41d9f729eb227d5edbe89e4ec175486db8dfa" - ], - "index": "pypi", - "version": "==0.7.0" - }, - "idna": { - "hashes": [ - "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", - "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" - ], - "version": "==2.9" - }, - "imagesize": { - "hashes": [ - "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", - "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" - ], - "version": "==1.2.0" - }, - "importlib-metadata": { - "hashes": [ - "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", - "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" - ], - "markers": "python_version < '3.8'", - "version": "==1.6.0" - }, - "importlib-resources": { - "hashes": [ - "sha256:4019b6a9082d8ada9def02bece4a76b131518866790d58fdda0b5f8c603b36c2", - "sha256:dd98ceeef3f5ad2ef4cc287b8586da4ebad15877f351e9688987ad663a0a29b8" - ], - "markers": "python_version < '3.7'", - "version": "==1.4.0" - }, - "itsdangerous": { - "hashes": [ - "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", - "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" - ], - "version": "==1.1.0" - }, - "jinja2": { - "hashes": [ - "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", - "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" - ], - "version": "==2.11.1" - }, - "markupsafe": { - "hashes": [ - "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", - "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", - "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", - "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", - "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", - "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", - "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", - "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", - "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", - "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", - "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", - "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", - "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", - "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", - "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:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" - ], - "version": "==1.1.1" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "mock": { - "hashes": [ - "sha256:83657d894c90d5681d62155c82bda9c1187827525880eda8ff5df4ec813437c3", - "sha256:d157e52d4e5b938c550f39eb2fd15610db062441a9c2747d3dbfa9298211d0f8" - ], - "markers": "python_version < '3.0'", - "version": "==3.0.5" - }, - "monotonic": { - "hashes": [ - "sha256:23953d55076df038541e648a53676fb24980f7a1be290cdda21300b3bc21dfb0", - "sha256:552a91f381532e33cbd07c6a2655a21908088962bb8fa7239ecbcc6ad1140cc7" - ], - "version": "==1.5" - }, - "more-itertools": { - "hashes": [ - "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", - "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", - "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9" - ], - "index": "pypi", - "version": "==5.0.0" - }, - "pathlib2": { - "hashes": [ - "sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db", - "sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868" - ], - "markers": "python_version < '3.6'", - "version": "==2.3.5" - }, - "pluggy": { - "hashes": [ - "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", - "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" - ], - "version": "==0.13.1" - }, - "py": { - "hashes": [ - "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", - "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" - ], - "version": "==1.8.1" - }, - "pycodestyle": { - "hashes": [ - "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", - "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" - ], - "version": "==2.5.0" - }, - "pycparser": { - "hashes": [ - "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", - "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" - ], - "version": "==2.20" - }, - "pyflakes": { - "hashes": [ - "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", - "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" - ], - "version": "==2.1.1" - }, - "pygments": { - "hashes": [ - "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b", - "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe" - ], - "version": "==2.5.2" - }, - "pysocks": { - "hashes": [ - "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", - "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", - "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" - ], - "version": "==1.7.1" - }, - "pytest": { - "hashes": [ - "sha256:3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", - "sha256:e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660" - ], - "index": "pypi", - "version": "==3.10.1" - }, - "pytest-cov": { - "hashes": [ - "sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b", - "sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626" - ], - "index": "pypi", - "version": "==2.8.1" - }, - "pytest-forked": { - "hashes": [ - "sha256:1805699ed9c9e60cb7a8179b8d4fa2b8898098e82d229b0825d8095f0f261100", - "sha256:1ae25dba8ee2e56fb47311c9638f9e58552691da87e82d25b0ce0e4bf52b7d87" - ], - "version": "==1.1.3" - }, - "pytest-httpbin": { - "hashes": [ - "sha256:8cd57e27418a7d7d205fcc9802eea246ed06170e3065abfa76c6d9b40553592c", - "sha256:d3919c5df0b644454129c0066a8ae62db40ac54bacb4cfd89d8cfa58615a4b42" - ], - "index": "pypi", - "version": "==0.3.0" - }, - "pytest-mock": { - "hashes": [ - "sha256:b35eb281e93aafed138db25c8772b95d3756108b601947f89af503f8c629413f", - "sha256:cb67402d87d5f53c579263d37971a164743dc33c159dfb4fb4a86f37c5552307" - ], - "index": "pypi", - "version": "==2.0.0" - }, - "pytest-xdist": { - "hashes": [ - "sha256:96f893094c89fddeaff3f4783f4807f7aeb138be1a0d87a8805057b6af1201b5", - "sha256:aab1402f2b063df48bf044b042707610f8fcc4c49d0eb9c10e79e30b3f26074f" - ], - "index": "pypi", - "version": "==1.25.0" - }, - "pytz": { - "hashes": [ - "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", - "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" - ], - "version": "==2019.3" - }, - "raven": { - "extras": [ - "flask" - ], - "hashes": [ - "sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54", - "sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4" - ], - "version": "==6.10.0" - }, - "readme-renderer": { - "hashes": [ - "sha256:1b6d8dd1673a0b293766b4106af766b6eff3654605f9c4f239e65de6076bc222", - "sha256:e67d64242f0174a63c3b727801a2fff4c1f38ebe5d71d95ff7ece081945a6cd4" - ], - "index": "pypi", - "version": "==25.0" - }, - "requests": { - "editable": true, - "extras": [ - "socks" - ], - "path": "." - }, - "scandir": { - "hashes": [ - "sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e", - "sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022", - "sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f", - "sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f", - "sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae", - "sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173", - "sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4", - "sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32", - "sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188", - "sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d", - "sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac" - ], - "markers": "python_version < '3.5'", - "version": "==1.10.0" - }, - "singledispatch": { - "hashes": [ - "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c", - "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8" - ], - "markers": "python_version < '3.4'", - "version": "==3.4.0.3" - }, - "six": { - "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" - ], - "version": "==1.14.0" - }, - "snowballstemmer": { - "hashes": [ - "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", - "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" - ], - "version": "==2.0.0" - }, - "sphinx": { - "hashes": [ - "sha256:11f271e7a9398385ed730e90f0bb41dc3815294bdcd395b46ed2d033bc2e7d87", - "sha256:4064ea6c56feeb268838cb8fbbee507d0c3d5d92fa63a7df935a916b52c9e2f5" - ], - "index": "pypi", - "version": "==1.5.5" - }, - "toml": { - "hashes": [ - "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", - "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" - ], - "version": "==0.10.0" - }, - "tox": { - "hashes": [ - "sha256:2a8d8a63660563e41e64e3b5b677e81ce1ffa5e2a93c2c565d3768c287445800", - "sha256:edfca7809925f49bdc110d0a2d9966bbf35a0c25637216d9586e7a5c5de17bfb" - ], - "index": "pypi", - "version": "==3.6.1" - }, - "typing": { - "hashes": [ - "sha256:91dfe6f3f706ee8cc32d38edbbf304e9b7583fb37108fef38229617f8b3eba23", - "sha256:c8cabb5ab8945cd2f54917be357d134db9cc1eb039e59d1606dc1e60cb1d9d36", - "sha256:f38d83c5a7a7086543a0f649564d661859c5146a85775ab90c0d2f93ffaa9714" - ], - "markers": "python_version < '3.5'", - "version": "==3.7.4.1" - }, - "urllib3": { - "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" - ], - "version": "==1.25.8" - }, - "virtualenv": { - "hashes": [ - "sha256:4e399f48c6b71228bf79f5febd27e3bbb753d9d5905776a86667bc61ab628a25", - "sha256:9e81279f4a9d16d1c0654a127c2c86e5bca2073585341691882c1e66e31ef8a5" - ], - "version": "==20.0.15" - }, - "webencodings": { - "hashes": [ - "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", - "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" - ], - "version": "==0.5.1" - }, - "werkzeug": { - "hashes": [ - "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43", - "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c" - ], - "version": "==1.0.1" - }, - "zipp": { - "hashes": [ - "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1", - "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921" - ], - "markers": "python_version < '3.8'", - "version": "==1.2.0" - } - } -} diff --git a/README.md b/README.md index f3b1eebf66..74d368952f 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,6 @@ +# Requests - - - -
-    
-    
-    
-

- Python 3.7.4 (default, Sep 7 2019, 18:27:02) - >>> import requests - >>> r = requests.get('https://api.github.com/repos/psf/requests') - >>> r.json()["description"] - 'A simple, yet elegant HTTP library.' -
- -

-This software has been designed for you, with much joy, -by Kenneth Reitz & is protected by The Python Software Foundation. -

-
- -
- -

 

 

- -

Requests is an elegant and simple HTTP library for Python, built with ♥.

- -

 

+**Requests** is a simple, yet elegant HTTP library. ```python >>> import requests @@ -43,84 +17,46 @@ by Kenneth Reitz & is protected by The < {'disk_usage': 368627, 'private_gists': 484, ...} ``` - - ---------------------------------------------------------------------- - -

 

- 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 `PUT` & `POST` data — but nowadays, just use the `json` method! - Requests is one of the most downloaded Python package today, pulling in around `14M downloads / week`— according to GitHub, Requests is currently [depended upon](https://github.com/psf/requests/network/dependents?package_id=UGFja2FnZS01NzA4OTExNg%3D%3D) by `500,000+` repositories. You may certainly put your trust in this code. +[![Downloads](https://pepy.tech/badge/requests/month)](https://pepy.tech/project/requests/month) +[![Supported Versions](https://img.shields.io/pypi/pyversions/requests.svg)](https://pypi.org/project/requests) +[![Contributors](https://img.shields.io/github/contributors/psf/requests.svg)](https://github.com/psf/requests/graphs/contributors) -

 

-

Downloads -image -image

+## Installing Requests and Supported Versions -

 

- -

Supported Features & Best–Practices

- -Requests is ready for the demands of building robust and reliable HTTP–speak applications, for the needs of today. - -
-         + International Domains and URLs       + Keep-Alive & Connection Pooling
-         + Sessions with Cookie Persistence     + Browser-style SSL Verification
-         + Basic & Digest Authentication        + Familiar `dict`–like Cookies
-         + Automatic Decompression of Content   + Automatic Content Decoding
-         + Automatic Connection Pooling         + Unicode Response Bodies*
-         + Multi-part File Uploads              + SOCKS Proxy Support
-         + Connection Timeouts                  + Streaming Downloads
-         + Automatic honoring of `.netrc`       + Chunked HTTP Requests
-
-                            &, of course, rock–solid stability!
-
- - -

- ✨ 🍰 ✨             -

- -

 

- -Requests Module Installation ----------------------------- - -The recommended way to install the `requests` module is to simply use [`pipenv`](https://pipenv.kennethreitz.org) (or `pip`, of -course): +Requests is available on PyPI: ```console -$ pipenv install requests -Adding requests to Pipfile's [packages]… -✔ Installation Succeeded -… +$ python -m pip install requests ``` Requests officially supports Python 2.7 & 3.5+. -------------------------------------- - -## P.S. — Documentation is available at [`requests.readthedocs.io`](https://requests.readthedocs.io/en/latest/). - -

- -

- +## Supported Features & Best–Practices ------------------- +Requests is ready for the demands of building robust and reliable HTTP–speaking applications, for the needs of today. +- Keep-Alive & Connection Pooling +- International Domains and URLs +- Sessions with Cookie Persistence +- Browser-style TLS/SSL Verification +- Basic & Digest Authentication +- Familiar `dict`–like Cookies +- Automatic Content Decompression and Decoding +- Multi-part File Uploads +- SOCKS Proxy Support +- Connection Timeouts +- Streaming Downloads +- Automatic honoring of `.netrc` +- Chunked HTTP Requests -

 

+## API Reference and User Guide available on [Read the Docs](https://requests.readthedocs.io) -

- -

+[![Read the Docs](https://raw.githubusercontent.com/psf/requests/master/ext/ss.png)](https://requests.readthedocs.io) -

 

+--- -

- -

+[![Kenneth Reitz](https://raw.githubusercontent.com/psf/requests/master/ext/kr.png)](https://kennethreitz.org) [![Python Software Foundation](https://raw.githubusercontent.com/psf/requests/master/ext/psf.png)](https://www.python.org/psf) diff --git a/_appveyor/install.ps1 b/_appveyor/install.ps1 deleted file mode 100644 index 160ba55c07..0000000000 --- a/_appveyor/install.ps1 +++ /dev/null @@ -1,229 +0,0 @@ -# Sample script to install Python and pip under Windows -# Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer -# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ - -$MINICONDA_URL = "http://repo.continuum.io/miniconda/" -$BASE_URL = "https://www.python.org/ftp/python/" -$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" -$GET_PIP_PATH = "C:\get-pip.py" - -$PYTHON_PRERELEASE_REGEX = @" -(?x) -(?\d+) -\. -(?\d+) -\. -(?\d+) -(?[a-z]{1,2}\d+) -"@ - - -function Download ($filename, $url) { - $webclient = New-Object System.Net.WebClient - - $basedir = $pwd.Path + "\" - $filepath = $basedir + $filename - if (Test-Path $filename) { - Write-Host "Reusing" $filepath - return $filepath - } - - # Download and retry up to 3 times in case of network transient errors. - Write-Host "Downloading" $filename "from" $url - $retry_attempts = 2 - for ($i = 0; $i -lt $retry_attempts; $i++) { - try { - $webclient.DownloadFile($url, $filepath) - break - } - Catch [Exception]{ - Start-Sleep 1 - } - } - if (Test-Path $filepath) { - Write-Host "File saved at" $filepath - } else { - # Retry once to get the error message if any at the last try - $webclient.DownloadFile($url, $filepath) - } - return $filepath -} - - -function ParsePythonVersion ($python_version) { - if ($python_version -match $PYTHON_PRERELEASE_REGEX) { - return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro, - $matches.prerelease) - } - $version_obj = [version]$python_version - return ($version_obj.major, $version_obj.minor, $version_obj.build, "") -} - - -function DownloadPython ($python_version, $platform_suffix) { - $major, $minor, $micro, $prerelease = ParsePythonVersion $python_version - - if (($major -le 2 -and $micro -eq 0) ` - -or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) ` - ) { - $dir = "$major.$minor" - $python_version = "$major.$minor$prerelease" - } else { - $dir = "$major.$minor.$micro" - } - - if ($prerelease) { - if (($major -le 2) ` - -or ($major -eq 3 -and $minor -eq 1) ` - -or ($major -eq 3 -and $minor -eq 2) ` - -or ($major -eq 3 -and $minor -eq 3) ` - ) { - $dir = "$dir/prev" - } - } - - if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) { - $ext = "msi" - if ($platform_suffix) { - $platform_suffix = ".$platform_suffix" - } - } else { - $ext = "exe" - if ($platform_suffix) { - $platform_suffix = "-$platform_suffix" - } - } - - $filename = "python-$python_version$platform_suffix.$ext" - $url = "$BASE_URL$dir/$filename" - $filepath = Download $filename $url - return $filepath -} - - -function InstallPython ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -eq "32") { - $platform_suffix = "" - } else { - $platform_suffix = "amd64" - } - $installer_path = DownloadPython $python_version $platform_suffix - $installer_ext = [System.IO.Path]::GetExtension($installer_path) - Write-Host "Installing $installer_path to $python_home" - $install_log = $python_home + ".log" - if ($installer_ext -eq '.msi') { - InstallPythonMSI $installer_path $python_home $install_log - } else { - InstallPythonEXE $installer_path $python_home $install_log - } - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallPythonEXE ($exepath, $python_home, $install_log) { - $install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home" - RunCommand $exepath $install_args -} - - -function InstallPythonMSI ($msipath, $python_home, $install_log) { - $install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home" - $uninstall_args = "/qn /x $msipath" - RunCommand "msiexec.exe" $install_args - if (-not(Test-Path $python_home)) { - Write-Host "Python seems to be installed else-where, reinstalling." - RunCommand "msiexec.exe" $uninstall_args - RunCommand "msiexec.exe" $install_args - } -} - -function RunCommand ($command, $command_args) { - Write-Host $command $command_args - Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru -} - - -function InstallPip ($python_home) { - $pip_path = $python_home + "\Scripts\pip.exe" - $python_path = $python_home + "\python.exe" - if (-not(Test-Path $pip_path)) { - Write-Host "Installing pip..." - $webclient = New-Object System.Net.WebClient - $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) - Write-Host "Executing:" $python_path $GET_PIP_PATH - & $python_path $GET_PIP_PATH - } else { - Write-Host "pip already installed." - } -} - - -function DownloadMiniconda ($python_version, $platform_suffix) { - if ($python_version -eq "3.4") { - $filename = "Miniconda3-3.5.5-Windows-" + $platform_suffix + ".exe" - } else { - $filename = "Miniconda-3.5.5-Windows-" + $platform_suffix + ".exe" - } - $url = $MINICONDA_URL + $filename - $filepath = Download $filename $url - return $filepath -} - - -function InstallMiniconda ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -eq "32") { - $platform_suffix = "x86" - } else { - $platform_suffix = "x86_64" - } - $filepath = DownloadMiniconda $python_version $platform_suffix - Write-Host "Installing" $filepath "to" $python_home - $install_log = $python_home + ".log" - $args = "/S /D=$python_home" - Write-Host $filepath $args - Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallMinicondaPip ($python_home) { - $pip_path = $python_home + "\Scripts\pip.exe" - $conda_path = $python_home + "\Scripts\conda.exe" - if (-not(Test-Path $pip_path)) { - Write-Host "Installing pip..." - $args = "install --yes pip" - Write-Host $conda_path $args - Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru - } else { - Write-Host "pip already installed." - } -} - -function main () { - InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON - InstallPip $env:PYTHON -} - -main diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 3b6cef631b..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,57 +0,0 @@ -# AppVeyor.yml from https://github.com/ogrisel/python-appveyor-demo -# License: CC0 1.0 Universal: https://creativecommons.org/publicdomain/zero/1.0/ - -build: off - -environment: - matrix: - - PYTHON: "C:\\Python27-x64" - PYTHON_VERSION: "2.7.x" - PYTHON_ARCH: "64" - TOXENV: "py27" - - - PYTHON: "C:\\Python34-x64" - PYTHON_VERSION: "3.4.x" - PYTHON_ARCH: "64" - TOXENV: "py34" - - - PYTHON: "C:\\Python35-x64" - PYTHON_VERSION: "3.5.x" - PYTHON_ARCH: "64" - TOXENV: "py35" - - - PYTHON: "C:\\Python36-x64" - PYTHON_VERSION: "3.6.x" - PYTHON_ARCH: "64" - TOXENV: "py36" - - - PYTHON: "C:\\Python37-x64" - PYTHON_VERSION: "3.7.x" - PYTHON_ARCH: "64" - TOXENV: "py37" - -install: - # Install Python (from the official .msi of https://www.python.org/) and pip when - # not already installed. - - ps: if (-not(Test-Path($env:PYTHON))) { & _appveyor\install.ps1 } - - # Prepend newly installed Python to the PATH of this build (this cannot be - # done from inside the powershell script as it would require to restart - # the parent CMD process). - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - # Check that we have the expected version and architecture for Python - - "python --version" - - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" - - # Upgrade to the latest version of pip to avoid it displaying warnings - # about it being out of date. - - "python -m pip install --upgrade pip wheel" - - "C:\\MinGW\\bin\\mingw32-make" - - "pipenv install -e .[socks] --skip-lock" - -test_script: - - "C:\\MinGW\\bin\\mingw32-make coverage" - -on_success: - - "pipenv run codecov -f coverage.xml" diff --git a/docs/_static/konami.js b/docs/_static/konami.js deleted file mode 100644 index d72cf9df89..0000000000 --- a/docs/_static/konami.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Konami-JS ~ - * :: Now with support for touch events and multiple instances for - * :: those situations that call for multiple easter eggs! - * Code: http://konami-js.googlecode.com/ - * Examples: http://www.snaptortoise.com/konami-js - * Copyright (c) 2009 George Mandis (georgemandis.com, snaptortoise.com) - * Version: 1.4.2 (9/2/2013) - * Licensed under the MIT License (http://opensource.org/licenses/MIT) - * Tested in: Safari 4+, Google Chrome 4+, Firefox 3+, IE7+, Mobile Safari 2.2.1 and Dolphin Browser - */ - -var Konami = function (callback) { - var konami = { - addEvent: function (obj, type, fn, ref_obj) { - if (obj.addEventListener) - obj.addEventListener(type, fn, false); - else if (obj.attachEvent) { - // IE - obj["e" + type + fn] = fn; - obj[type + fn] = function () { - obj["e" + type + fn](window.event, ref_obj); - }; - obj.attachEvent("on" + type, obj[type + fn]); - } - }, - input: "", - pattern: "38384040373937396665", - load: function (link) { - this.addEvent(document, "keydown", function (e, ref_obj) { - if (ref_obj) konami = ref_obj; // IE - konami.input += e ? e.keyCode : event.keyCode; - if (konami.input.length > konami.pattern.length) - konami.input = konami.input.substr((konami.input.length - konami.pattern.length)); - if (konami.input == konami.pattern) { - konami.code(link); - konami.input = ""; - e.preventDefault(); - return false; - } - }, this); - this.iphone.load(link); - }, - code: function (link) { - window.location = link - }, - iphone: { - start_x: 0, - start_y: 0, - stop_x: 0, - stop_y: 0, - tapTolerance: 8, - capture: false, - orig_keys: "", - keys: ["UP", "UP", "DOWN", "DOWN", "LEFT", "RIGHT", "LEFT", "RIGHT", "TAP", "TAP"], - code: function (link) { - konami.code(link); - }, - touchCapture: function(evt) { - konami.iphone.start_x = evt.changedTouches[0].pageX; - konami.iphone.start_y = evt.changedTouches[0].pageY; - konami.iphone.capture = true; - }, - load: function (link) { - this.orig_keys = this.keys; - konami.addEvent(document, "touchmove", function (e) { - if (e.touches.length == 1 && konami.iphone.capture == true) { - var touch = e.touches[0]; - konami.iphone.stop_x = touch.pageX; - konami.iphone.stop_y = touch.pageY; - konami.iphone.check_direction(); - } - }); - konami.addEvent(document, "touchend", function (evt) { - konami.touchCapture(evt); - konami.iphone.check_direction(link); - }, false); - konami.addEvent(document, "touchstart", function (evt) { - konami.touchCapture(evt); - }); - }, - check_direction: function (link) { - var x_magnitude = Math.abs(this.start_x - this.stop_x); - var y_magnitude = Math.abs(this.start_y - this.stop_y); - var hasMoved = (x_magnitude > this.tapTolerance || y_magnitude > this.tapTolerance); - var result; - if (this.capture === true && hasMoved) { - this.capture = false; - var x = ((this.start_x - this.stop_x) < 0) ? "RIGHT" : "LEFT"; - var y = ((this.start_y - this.stop_y) < 0) ? "DOWN" : "UP"; - var result = (x_magnitude > y_magnitude) ? x : y; - } - else if (this.capture === false && !hasMoved) { - result = (this.tap == true) ? "TAP" : result; - result = "TAP"; - } - if (result) { - if (result == this.keys[0]) this.keys = this.keys.slice(1, this.keys.length); - else this.keys = this.orig_keys; - } - if (this.keys.length == 0) { - this.keys = this.orig_keys; - this.code(link); - } - } - } - } - - typeof callback === "string" && konami.load(callback); - if (typeof callback === "function") { - konami.code = callback; - konami.load(); - } - - return konami; -}; diff --git a/docs/_static/requests-logo-small.jpg b/docs/_static/requests-logo-small.jpg deleted file mode 100644 index 43793ec117..0000000000 Binary files a/docs/_static/requests-logo-small.jpg and /dev/null differ diff --git a/docs/_static/requests-sidebar.jpg b/docs/_static/requests-sidebar.jpg deleted file mode 100644 index 3bcf8f8a04..0000000000 Binary files a/docs/_static/requests-sidebar.jpg and /dev/null differ diff --git a/docs/_templates/hacks.html b/docs/_templates/hacks.html index 3af2e578b6..eca5dffcb5 100644 --- a/docs/_templates/hacks.html +++ b/docs/_templates/hacks.html @@ -23,38 +23,8 @@ /* Have code blocks escape the document right-margin. */ div.highlight pre {margin-right: -30px;} } - - - - - - - - - - - - - - - diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html index 57911a597b..b5f51a0a3c 100644 --- a/docs/_templates/sidebarintro.html +++ b/docs/_templates/sidebarintro.html @@ -1,9 +1,3 @@ - -

@@ -42,23 +36,23 @@ src="//cdn.carbonads.com/carbon.js?zoneid=1673&serve=CKYI5K3E&placement=pythonrequestsorg" id="_carbonads_js"> -

Stay Informed

-

Receive updates on new releases and upcoming projects.

- -

-

Useful Links

diff --git a/docs/_templates/sidebarlogo.html b/docs/_templates/sidebarlogo.html index af66973d9c..56d6109563 100644 --- a/docs/_templates/sidebarlogo.html +++ b/docs/_templates/sidebarlogo.html @@ -1,8 +1,3 @@ -

@@ -37,19 +32,30 @@ development release.

-Sponsored by CERT Gouvernemental - GOVCERT.LU.

- -

Stay Informed

-

Receive updates on new releases and upcoming projects.

- -

Join Mailing List.

- -
+

Sponsored by CERT Gouvernemental - GOVCERT.LU.

+

Useful Links

+

Translations

diff --git a/docs/community/faq.rst b/docs/community/faq.rst index 9a20728102..c0177719bd 100644 --- a/docs/community/faq.rst +++ b/docs/community/faq.rst @@ -3,8 +3,6 @@ Frequently Asked Questions ========================== -.. image:: https://farm5.staticflickr.com/4290/35294660055_42c02b2316_k_d.jpg - This part of the documentation answers common questions about Requests. Encoded Data? @@ -66,7 +64,8 @@ and intend to maintain Python 2.7 support within Requests until `pip stops supporting Python 2.7 (there's no estimated date on that yet) `_. -That said, it is *highly* recommended users migrate to Python 3.5+ since Python 2.7 will no longer be receiving bug fixes or security updates after January 1, 2020. +That said, it is *highly* recommended users migrate to Python 3.6+ since Python +2.7 is no longer receiving bug fixes or security updates as of January 1, 2020. What are "hostname doesn't match" errors? ----------------------------------------- diff --git a/docs/community/out-there.rst b/docs/community/out-there.rst index 79b21c6da2..c33ab3c95b 100644 --- a/docs/community/out-there.rst +++ b/docs/community/out-there.rst @@ -1,8 +1,6 @@ Integrations ============ -.. image:: https://farm5.staticflickr.com/4239/34450900674_15863ddea0_k_d.jpg - Python for iOS -------------- diff --git a/docs/community/recommended.rst b/docs/community/recommended.rst index 045e533845..04387bc1ac 100644 --- a/docs/community/recommended.rst +++ b/docs/community/recommended.rst @@ -3,8 +3,6 @@ Recommended Packages and Extensions =================================== -.. image:: https://farm5.staticflickr.com/4218/35224319272_cfc0e621fb_k_d.jpg - Requests has a great variety of powerful and useful third-party extensions. This page provides an overview of some of the best of them. diff --git a/docs/community/release-process.rst b/docs/community/release-process.rst index 18f71168a5..4aa98f755e 100644 --- a/docs/community/release-process.rst +++ b/docs/community/release-process.rst @@ -1,8 +1,6 @@ Release Process and Rules ========================= -.. image:: https://farm5.staticflickr.com/4215/34450901614_b74ae720db_k_d.jpg - .. versionadded:: v2.6.2 Starting with the version to be released after ``v2.6.2``, the following rules diff --git a/docs/community/support.rst b/docs/community/support.rst index 23e3586852..ee905f543d 100644 --- a/docs/community/support.rst +++ b/docs/community/support.rst @@ -3,26 +3,16 @@ Support ======= -.. image:: https://farm5.staticflickr.com/4198/34080352913_5c13ffb336_k_d.jpg - If you have questions or issues about Requests, there are several options: Stack Overflow -------------- +-------------- If your question does not contain sensitive (possibly proprietary) information or can be properly anonymized, please ask a question on `Stack Overflow `_ and use the tag ``python-requests``. -Send a Tweet ------------- - -If your question is less than 280 characters, feel free to send a tweet to -`@kennethreitz `_, -`@sigmavirus24 `_, -`@lukasaoz `_, or -`@nateprewitt `_. File an Issue ------------- @@ -32,23 +22,10 @@ for a new feature, `file an issue on GitHub `_. -E-mail ------- - -I'm more than happy to answer any personal or in-depth questions about -Requests. Feel free to email -`requests@kennethreitz.com `_. - - -IRC ---- - -The official Freenode channel for Requests is -`#python-requests `_ - -The core developers of requests are on IRC throughout the day. -You can find them in ``#python-requests`` as: +Send a Tweet +------------ -- kennethreitz -- lukasa -- sigmavirus24 +If your question is less than 280 characters, feel free to send a tweet to +`@nateprewitt `_, +`@sethmlarson `_, or +`@sigmavirus24 `_. diff --git a/docs/community/updates.rst b/docs/community/updates.rst index ee08cdc572..c787c45bcf 100644 --- a/docs/community/updates.rst +++ b/docs/community/updates.rst @@ -4,8 +4,6 @@ Community Updates ================= -.. image:: https://farm5.staticflickr.com/4244/34080354873_516c283ad0_k_d.jpg - If you'd like to stay up to date on the community and development of Requests, there are several options: @@ -16,16 +14,5 @@ GitHub The best way to track the development of Requests is through `the GitHub repo `_. -Twitter -------- - -The author, Kenneth Reitz, often tweets about new features and releases of Requests. - -Follow `@kennethreitz `_ for updates. - - - -Release and Version History -=========================== .. include:: ../../HISTORY.md diff --git a/docs/community/vulnerabilities.rst b/docs/community/vulnerabilities.rst index 2c7ccf1807..63219b57b0 100644 --- a/docs/community/vulnerabilities.rst +++ b/docs/community/vulnerabilities.rst @@ -1,8 +1,6 @@ Vulnerability Disclosure ======================== -.. image:: https://farm5.staticflickr.com/4211/34709353644_b041e9e1c2_k_d.jpg - If you think you have found a potential security vulnerability in requests, please email `Nate `_ and `Seth `_ directly. **Do not file a public issue.** diff --git a/docs/conf.py b/docs/conf.py index eb556a81ba..edbd72ba82 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -58,7 +58,7 @@ # General information about the project. project = u"Requests" -copyright = u'MMXVIX. A Kenneth Reitz Project' +copyright = u'MMXVIX. A Kenneth Reitz Project' author = u"Kenneth Reitz" # The version info for the project you're documenting, acts as replacement for diff --git a/docs/dev/authors.rst b/docs/dev/authors.rst index 4cdd14cd43..e9799a9142 100644 --- a/docs/dev/authors.rst +++ b/docs/dev/authors.rst @@ -1,6 +1,4 @@ Authors ======= -.. image:: https://static1.squarespace.com/static/533ad9bde4b098d084a846b1/t/534f6e1ce4b09b70f38ee6c1/1432265542589/DSCF3147.jpg?format=2500w - .. include:: ../../AUTHORS.rst diff --git a/docs/dev/contributing.rst b/docs/dev/contributing.rst index 308fdd2585..6b1cef7b93 100644 --- a/docs/dev/contributing.rst +++ b/docs/dev/contributing.rst @@ -3,8 +3,6 @@ Contributor's Guide =================== -.. image:: https://farm5.staticflickr.com/4237/35550408335_7671fde302_k_d.jpg - If you're reading this, you're probably interested in contributing to Requests. Thank you very much! Open source projects live-and-die based on the support they receive from others, and the fact that you're even considering @@ -13,23 +11,17 @@ contributing to the Requests project is *very* generous of you. This document lays out guidelines and advice for contributing to this project. If you're thinking of contributing, please start by reading this document and getting a feel for how contributing to this project works. If you have any -questions, feel free to reach out to either `Ian Cordasco`_, `Cory Benfield`_, -or `Nate Prewitt`_, the primary maintainers. +questions, feel free to reach out to either `Nate Prewitt`_, `Ian Cordasco`_, +or `Seth Michael Larson`_, the primary maintainers. .. _Ian Cordasco: http://www.coglib.com/~icordasc/ -.. _Cory Benfield: https://lukasa.co.uk/about .. _Nate Prewitt: https://www.nateprewitt.com/ - -If you have non-technical feedback, philosophical ponderings, crazy ideas, or -other general thoughts about Requests or its position within the Python -ecosystem, the BDFL, `Kenneth Reitz`_, would love to hear from you. +.. _Seth Michael Larson: https://sethmlarson.dev/ The guide is split into sections based on the type of contribution you're thinking of making, with a section that covers general guidelines for all contributors. -.. _Kenneth Reitz: mailto:me@kennethreitz.org - Be Cordial ---------- diff --git a/docs/dev/philosophy.rst b/docs/dev/philosophy.rst deleted file mode 100644 index 1dc20b8609..0000000000 --- a/docs/dev/philosophy.rst +++ /dev/null @@ -1,47 +0,0 @@ -Development Philosophy -====================== - -.. image:: https://farm5.staticflickr.com/4231/34484831073_636008a23d_k_d.jpg - -Requests is an open but opinionated library, created by an open but opinionated developer. - - -Management Style -~~~~~~~~~~~~~~~~ - -`Kenneth Reitz `_ is the BDFL. He has final say in any decision related to the Requests project. Kenneth is responsible for the direction and form of the library, as well as its presentation. In addition to making decisions based on technical merit, he is responsible for making decisions based on the development philosophy of Requests. - -`Ian Cordasco `_, `Cory Benfield `_, and `Nate Prewitt `_ are the core contributors. They are responsible for triaging bug reports, reviewing pull requests and ensuring that Kenneth is kept up to speed with developments around the library. The day-to-day managing of the project is done by the core contributors. They are responsible for making judgements about whether or not a feature request is likely to be accepted by Kenneth. Their word is, in some ways, more final than Kenneth's. - -Values -~~~~~~ - -- Simplicity is always better than functionality. -- Listen to everyone, then disregard it. -- The API is all that matters. Everything else is secondary. -- Fit the 90% use-case. Ignore the nay-sayers. - -Semantic Versioning -~~~~~~~~~~~~~~~~~~~ - -For many years, the open source community has been plagued with version number dystonia. Numbers vary so greatly from project to project, they are practically meaningless. - -Requests uses `Semantic Versioning `_. This specification seeks to put an end to this madness with a small set of practical guidelines for you and your colleagues to use in your next project. - -Standard Library? -~~~~~~~~~~~~~~~~~ - -Requests has no *active* plans to be included in the standard library. This decision has been discussed at length with Guido as well as numerous core developers. - -.. raw:: html - - - -Essentially, the standard library is where a library goes to die. It is appropriate for a module to be included when active development is no longer necessary. - -Linux Distro Packages -~~~~~~~~~~~~~~~~~~~~~ - -Distributions have been made for many Linux repositories, including: Ubuntu, Debian, RHEL, and Arch. - -These distributions are sometimes divergent forks, or are otherwise not kept up-to-date with the latest code and bugfixes. PyPI (and its mirrors) and GitHub are the official distribution sources; alternatives are not supported by the Requests project. diff --git a/docs/dev/todo.rst b/docs/dev/todo.rst deleted file mode 100644 index d09fce398d..0000000000 --- a/docs/dev/todo.rst +++ /dev/null @@ -1,64 +0,0 @@ -How to Help -=========== - -.. image:: https://farm5.staticflickr.com/4290/34450900104_bc1d424213_k_d.jpg - -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 - 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 `_. - -Feature Freeze --------------- - -As of v1.0.0, Requests has now entered a feature freeze. Requests for new -features and Pull Requests implementing those features will not be accepted. - -Development Dependencies ------------------------- - -You'll need to install py.test in order to run the Requests' test suite:: - - $ venv .venv - $ source .venv/bin/activate - - $ make - $ python setup.py test - ============================= test session starts ============================== - platform darwin -- Python 3.4.4, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 - ... - collected 445 items - - tests/test_hooks.py ... - tests/test_lowlevel.py ............ - tests/test_requests.py ........................................................... - tests/test_structures.py .................... - tests/test_testserver.py ........... - tests/test_utils.py ..s........................................................... - - ============== 442 passed, 1 skipped, 2 xpassed in 46.48 seconds =============== - -You can also run ``$ make tests`` to run against all supported Python versions, using tox/detox. - -Runtime Environments --------------------- - -Requests currently supports the following versions of Python: - -- Python 2.7 -- Python 3.4 -- Python 3.5 -- Python 3.6 -- Python 3.7 -- PyPy - -Google AppEngine is not officially supported although support is available -with the `Requests-Toolbelt`_. - -.. _Requests-Toolbelt: https://toolbelt.readthedocs.io/ diff --git a/docs/index.rst b/docs/index.rst index 1099d5a8e8..4f8a9e4d86 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -45,7 +45,7 @@ See `similar code, sans Requests `_. **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 `_. +are 100% automatic, thanks to `urllib3 `_. Beloved Features ---------------- @@ -68,7 +68,7 @@ Requests is ready for today's web. - Chunked Requests - ``.netrc`` Support -Requests officially supports Python 2.7 & 3.4–3.7, and runs great on PyPy. +Requests officially supports Python 2.7 & 3.5+, and runs great on PyPy. The User Guide @@ -81,7 +81,6 @@ instructions for getting the most out of Requests. .. toctree:: :maxdepth: 2 - user/intro user/install user/quickstart user/advanced @@ -97,15 +96,18 @@ Requests ecosystem and community. .. toctree:: :maxdepth: 2 - community/sponsors community/recommended community/faq community/out-there community/support community/vulnerabilities - community/updates community/release-process +.. toctree:: + :maxdepth: 1 + + community/updates + The API Documentation / Guide ----------------------------- @@ -128,8 +130,6 @@ you. :maxdepth: 3 dev/contributing - dev/philosophy - dev/todo dev/authors There are no more guides. You are now guideless. diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 94a0eff872..d930a68d25 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -3,8 +3,6 @@ Advanced Usage ============== -.. image:: https://farm5.staticflickr.com/4263/35163665790_d182d84f5e_k_d.jpg - This document covers some of Requests more advanced features. .. _session-objects: @@ -238,12 +236,19 @@ or persistent:: the c_rehash utility supplied with OpenSSL. This list of trusted CAs can also be specified through the ``REQUESTS_CA_BUNDLE`` environment variable. +If ``REQUESTS_CA_BUNDLE`` is not set, ``CURL_CA_BUNDLE`` will be used as fallback. Requests can also ignore verifying the SSL certificate if you set ``verify`` to False:: >>> requests.get('https://kennethreitz.org', verify=False) +Note that when ``verify`` is set to ``False``, requests will accept any TLS +certificate presented by the server, and will ignore hostname mismatches +and/or expired certificates, which will make your application vulnerable to +man-in-the-middle (MitM) attacks. Setting verify to ``False`` may be useful +during local development or testing. + By default, ``verify`` is set to True. Option ``verify`` only applies to host certs. Client Side Certificates @@ -482,7 +487,7 @@ they are added. Custom Authentication --------------------- -Requests allows you to use specify your own authentication mechanism. +Requests allows you to specify your own authentication mechanism. Any callable which is passed as the ``auth`` argument to a request method will have the opportunity to modify the request before it is dispatched. @@ -584,10 +589,26 @@ If you need to use a proxy, you can configure individual requests with the requests.get('http://example.org', proxies=proxies) -You can also configure proxies by setting the environment variables -``HTTP_PROXY`` and ``HTTPS_PROXY``. +Alternatively you can configure it once for an entire +:class:`Session `:: -:: + import requests + + proxies = { + 'http': 'http://10.10.1.10:3128', + 'https': 'http://10.10.1.10:1080', + } + session = request.Session() + session.proxies.update(proxies) + + session.get('http://example.org') + +When the proxies configuration is not overridden in python as shown above, +by default Requests relies on the proxy configuration defined by standard +environment variables ``http_proxy``, ``https_proxy``, ``no_proxy`` and +``curl_ca_bundle``. Uppercase variants of these variables are also supported. +You can therefore set them to configure Requests (only set the ones relevant +to your needs):: $ export HTTP_PROXY="http://10.10.1.10:3128" $ export HTTPS_PROXY="http://10.10.1.10:1080" @@ -596,9 +617,17 @@ You can also configure proxies by setting the environment variables >>> import requests >>> requests.get('http://example.org') -To use HTTP Basic Auth with your proxy, use the `http://user:password@host/` syntax:: +To use HTTP Basic Auth with your proxy, use the `http://user:password@host/` +syntax in any of the above configuration entries:: - proxies = {'http': 'http://user:pass@10.10.1.10:3128/'} + $ export HTTPS_PROXY="http://user:pass@10.10.1.10:1080" + + $ python + >>> proxies = {'http': 'http://user:pass@10.10.1.10:3128/'} + +.. warning:: Storing sensitive username and password information in an + environment variable or a version-controled file is a security risk and is + highly discouraged. To give a proxy for a specific scheme and host, use the `scheme://hostname` form for the key. This will match for @@ -610,6 +639,23 @@ any request to the given scheme and exact hostname. Note that proxy URLs must include the scheme. +Finally, note that using a proxy for https connections typically requires your +local machine to trust the proxy's root certificate. By default the list of +certificates trusted by Requests can be found with:: + + from requests.utils import DEFAULT_CA_BUNDLE_PATH + print(DEFAULT_CA_BUNDLE_PATH) + +You override this default certificate bundle by setting the standard +``curl_ca_bundle`` environment variable to another file path:: + + $ export curl_ca_bundle="/usr/local/myproxy_info/cacert.pem" + $ export https_proxy="http://10.10.1.10:1080" + + $ python + >>> import requests + >>> requests.get('https://example.org') + SOCKS ^^^^^ @@ -623,7 +669,7 @@ You can get the dependencies for this feature from ``pip``: .. code-block:: bash - $ pip install requests[socks] + $ python -m pip install requests[socks] Once you've installed those dependencies, using a SOCKS proxy is just as easy as using a HTTP one:: @@ -976,12 +1022,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`_, `requests-futures`_, and `requests-async`_. +Some excellent examples are `requests-threads`_, `grequests`_, `requests-futures`_, and `httpx`_. .. _`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 +.. _`httpx`: https://github.com/encode/httpx Header Ordering --------------- diff --git a/docs/user/authentication.rst b/docs/user/authentication.rst index bff809861e..4d4040ebc4 100644 --- a/docs/user/authentication.rst +++ b/docs/user/authentication.rst @@ -3,8 +3,6 @@ Authentication ============== -.. image:: https://farm5.staticflickr.com/4258/35550409215_3b08d49d22_k_d.jpg - This document discusses using various kinds of authentication with Requests. Many web services require authentication, and there are many different types. diff --git a/docs/user/install.rst b/docs/user/install.rst index 6cd6d65586..ed205dbc6c 100644 --- a/docs/user/install.rst +++ b/docs/user/install.rst @@ -3,23 +3,16 @@ Installation of Requests ======================== -.. image:: https://farm5.staticflickr.com/4230/35550376215_da1bf77a8c_k_d.jpg - - This part of the documentation covers the installation of Requests. The first step to using any software package is getting it properly installed. -$ pipenv install requests -------------------------- +$ python -m pip install requests +-------------------------------- To install Requests, simply run this simple command in your terminal of choice:: - $ pipenv install requests - -If you don't have `pipenv `_ installed (tisk tisk!), head over to the Pipenv website for installation instructions. Or, if you prefer to just use pip and don't have it installed, -`this Python installation guide `_ -can guide you through the process. + $ python -m pip install requests Get the Source Code ------------------- @@ -40,4 +33,4 @@ Once you have a copy of the source, you can embed it in your own Python package, or install it into your site-packages easily:: $ cd requests - $ pip install . + $ python -m pip install . diff --git a/docs/user/intro.rst b/docs/user/intro.rst deleted file mode 100644 index be9dfaa8b3..0000000000 --- a/docs/user/intro.rst +++ /dev/null @@ -1,47 +0,0 @@ -.. _introduction: - -Introduction -============ - -.. image:: https://farm5.staticflickr.com/4317/35198386374_1939af3de6_k_d.jpg - -Philosophy ----------- - -Requests was developed with a few :pep:`20` idioms in mind. - - -#. Beautiful is better than ugly. -#. Explicit is better than implicit. -#. Simple is better than complex. -#. Complex is better than complicated. -#. Readability counts. - -All contributions to Requests should keep these important rules in mind. - -.. _`apache2`: - -Apache2 License ---------------- - -A large number of open source projects you find today are `GPL Licensed`_. -While the GPL has its time and place, it should most certainly not be your -go-to license for your next open source project. - -A project that is released as GPL cannot be used in any commercial product -without the product itself also being offered as open source. - -The MIT, BSD, ISC, and Apache2 licenses are great alternatives to the GPL -that allow your open-source software to be used freely in proprietary, -closed-source software. - -Requests is released under terms of `Apache2 License`_. - -.. _`GPL Licensed`: https://opensource.org/licenses/gpl-license.php -.. _`Apache2 License`: https://opensource.org/licenses/Apache-2.0 - - -Requests License ----------------- - - .. include:: ../../LICENSE diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst index 4570ec2924..7b0450c4fc 100644 --- a/docs/user/quickstart.rst +++ b/docs/user/quickstart.rst @@ -3,8 +3,6 @@ Quickstart ========== -.. image:: https://farm5.staticflickr.com/4259/35163667010_8bfcaef274_k_d.jpg - .. module:: requests.models Eager to get started? This page gives a good introduction in how to get started @@ -215,7 +213,8 @@ Note: Custom headers are given less precedence than more specific sources of inf * Authorization headers set with `headers=` will be overridden if credentials are specified in ``.netrc``, which in turn will be overridden by the ``auth=`` - parameter. + parameter. Requests will search for the netrc file at `~/.netrc`, `~/_netrc`, + or at the path specified by the `NETRC` environment variable. * Authorization headers will be removed if you get redirected off-host. * Proxy-Authorization headers will be overridden by proxy credentials provided in the URL. * Content-Length headers will be overridden when we can determine the length of the content. diff --git a/requests/__init__.py b/requests/__init__.py index db090aa70a..f8f94295f9 100644 --- a/requests/__init__.py +++ b/requests/__init__.py @@ -57,18 +57,16 @@ 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.25 + # urllib3 >= 1.21.1, <= 1.26 assert major == 1 assert minor >= 21 - assert minor <= 25 + assert minor <= 26 # Check chardet for compatibility. major, minor, patch = chardet_version.split('.')[:3] major, minor, patch = int(major), int(minor), int(patch) - # chardet >= 3.0.2, < 3.1.0 - assert major == 3 - assert minor < 1 - assert patch >= 2 + # chardet >= 3.0.2, < 5.0.0 + assert (3, 0, 2) <= (major, minor, patch) < (5, 0, 0) def _check_cryptography(cryptography_version): diff --git a/requests/__version__.py b/requests/__version__.py index 531e26ceb2..1267488d28 100644 --- a/requests/__version__.py +++ b/requests/__version__.py @@ -5,8 +5,8 @@ __title__ = 'requests' __description__ = 'Python HTTP for Humans.' __url__ = 'https://requests.readthedocs.io' -__version__ = '2.24.0' -__build__ = 0x022400 +__version__ = '2.25.1' +__build__ = 0x022501 __author__ = 'Kenneth Reitz' __author_email__ = 'me@kennethreitz.org' __license__ = 'Apache 2.0' diff --git a/requests/models.py b/requests/models.py index ae6eb70804..ec2edc20b5 100644 --- a/requests/models.py +++ b/requests/models.py @@ -273,7 +273,9 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): """The fully mutable :class:`PreparedRequest ` object, containing the exact bytes that will be sent to the server. - Generated from either a :class:`Request ` object or manually. + Instances are generated from a :class:`Request ` object, and + should not be instantiated manually; doing so may produce undesirable + effects. Usage:: diff --git a/requests/sessions.py b/requests/sessions.py index e8e2d609a7..45ab8a5d3f 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """ -requests.session -~~~~~~~~~~~~~~~~ +requests.sessions +~~~~~~~~~~~~~~~~~ This module provides a Session object to manage and persist settings across requests (cookies, auth, proxies). @@ -387,6 +387,13 @@ def __init__(self): self.stream = False #: SSL Verification default. + #: Defaults to `True`, requiring requests to verify the TLS certificate at the + #: remote end. + #: If verify is set to `False`, requests will accept any TLS certificate + #: presented by the server, and will ignore hostname mismatches and/or + #: expired certificates, which will make your application vulnerable to + #: man-in-the-middle (MitM) attacks. + #: Only set this to `False` for testing. self.verify = True #: SSL client certificate default, if String, path to ssl client @@ -495,7 +502,12 @@ def request(self, method, url, content. Defaults to ``False``. :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use. Defaults to ``True``. + to a CA bundle to use. Defaults to ``True``. When set to + ``False``, requests will accept any TLS certificate presented by + the server, and will ignore hostname mismatches and/or expired + certificates, which will make your application vulnerable to + man-in-the-middle (MitM) attacks. Setting verify to ``False`` + may be useful during local development or testing. :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. :rtype: requests.Response diff --git a/requests/utils.py b/requests/utils.py index c1700d7fe8..db67938e67 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -169,14 +169,20 @@ def super_len(o): def get_netrc_auth(url, raise_errors=False): """Returns the Requests tuple auth for a given url from netrc.""" + netrc_file = os.environ.get('NETRC') + if netrc_file is not None: + netrc_locations = (netrc_file,) + else: + netrc_locations = ('~/{}'.format(f) for f in NETRC_FILES) + try: from netrc import netrc, NetrcParseError netrc_path = None - for f in NETRC_FILES: + for f in netrc_locations: try: - loc = os.path.expanduser('~/{}'.format(f)) + loc = os.path.expanduser(f) except KeyError: # os.path.expanduser can fail when $HOME is undefined and # getpwuid fails. See https://bugs.python.org/issue20164 & @@ -212,7 +218,7 @@ def get_netrc_auth(url, raise_errors=False): if raise_errors: raise - # AppEngine hackiness. + # App Engine hackiness. except (ImportError, AttributeError): pass @@ -497,6 +503,10 @@ def get_encoding_from_headers(headers): if 'text' in content_type: return 'ISO-8859-1' + if 'application/json' in content_type: + # Assume UTF-8 based on RFC 4627: https://www.ietf.org/rfc/rfc4627.txt since the charset was unset + return 'utf-8' + def stream_decode_response_unicode(iterator, r): """Stream decodes a iterator.""" diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000000..b80a32e422 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,6 @@ +pytest>=2.8.0,<=3.10.1 +pytest-cov +pytest-httpbin<1.0 +pytest-mock==2.0.0 +httpbin==0.7.0 +wheel diff --git a/setup.py b/setup.py index 2da9ba07c5..7ba4b2a25f 100755 --- a/setup.py +++ b/setup.py @@ -42,9 +42,9 @@ def run_tests(self): packages = ['requests'] requires = [ - 'chardet>=3.0.2,<4', + 'chardet>=3.0.2,<5', 'idna>=2.5,<3', - 'urllib3>=1.21.1,<1.26,!=1.25.0,!=1.25.1', + 'urllib3>=1.21.1,<1.27', 'certifi>=2017.4.17' ] @@ -63,8 +63,6 @@ def run_tests(self): with open('README.md', 'r', 'utf-8') as f: readme = f.read() -with open('HISTORY.md', 'r', 'utf-8') as f: - history = f.read() setup( name=about['__title__'], @@ -76,7 +74,7 @@ def run_tests(self): author_email=about['__author_email__'], url=about['__url__'], packages=packages, - package_data={'': ['LICENSE', 'NOTICE'], 'requests': ['*.pem']}, + package_data={'': ['LICENSE', 'NOTICE']}, package_dir={'requests': 'requests'}, include_package_data=True, python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", @@ -96,6 +94,7 @@ def run_tests(self): 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy' ], diff --git a/tests/test_requests.py b/tests/test_requests.py index e730f7648b..5b6a7f5847 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -668,7 +668,7 @@ def test_POSTBIN_GET_POST_FILES(self, httpbin): post1 = requests.post(url, data={'some': 'data'}) assert post1.status_code == 200 - with open('Pipfile') as f: + with open('requirements-dev.txt') as f: post2 = requests.post(url, files={'some': f}) assert post2.status_code == 200 @@ -736,7 +736,7 @@ def test_POSTBIN_GET_POST_FILES_WITH_DATA(self, httpbin): post1 = requests.post(url, data={'some': 'data'}) assert post1.status_code == 200 - with open('Pipfile') as f: + with open('requirements-dev.txt') as f: post2 = requests.post(url, data={'some': 'data'}, files={'some': f}) assert post2.status_code == 200 @@ -773,7 +773,7 @@ def __len__(self): def test_conflicting_post_params(self, httpbin): url = httpbin('post') - with open('Pipfile') as f: + with open('requirements-dev.txt') as f: with pytest.raises(ValueError): requests.post(url, data='[{"some": "data"}]', files={'some': f}) with pytest.raises(ValueError):