mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-08 16:53:23 +00:00
v4.0.x - Remove legacy python and add python3.8 support (#499)
* Drop support for legacy Python 2.7 * Upgrade Python syntax with pyupgrade --py3-plus * Trim testing matrix to remove python2 * re-enable python3.8 in travis as tests that are not allowed to fail * Remove some six * The future is now * Remove Python 2 imports * Add back example, but change py27 to py36 * Remove redundant compat.py * Blacken * Credit hugovk in changelog WIP Updating Sphinx Docs and AutoDoc * Fix AutoDoc and update Sphinx theme to python_doc_theme * Fix #420, autodoc even undocumented (docstring-less) method signatures * Doc theme 'nature'. Add global TOC to doc sidebar * Comment last reference to package six * Changelog is now a consistent format * Yet another documentation fix for links and title hierarchy * Start work on new SVG logo test SVG in README trying to test new SVG logo in README Apply centering Apply readme logo centering Trying to align image Trying random shit trying align right add emoji Large logo has higher priority Change title hierarchy Actually use a H1 Try again try and organise badges revert link back to point at master * updated new take on VCR logo as SVG code * Testing modern logo in docs * Add sanitize for rendering SVG * Switch to alabaster theme * Update vcrpy logo (#503) * Add credit for V4 logo changes. * Add rewind and play animation * Add svg into ReadTheDocs static assets so that it can be hosted so the animations work. * Need to embedd the SVG for ReadTheDocs somewhere so I can get the link to later embed in the README Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com> Co-authored-by: Sean Bailey <sean@seanbailey.io>
This commit is contained in:
14
.travis.yml
14
.travis.yml
@@ -17,23 +17,11 @@ matrix:
|
|||||||
# Only run lint on a single 3.x
|
# Only run lint on a single 3.x
|
||||||
- env: TOX_SUFFIX="lint"
|
- env: TOX_SUFFIX="lint"
|
||||||
python: "3.7"
|
python: "3.7"
|
||||||
allow_failures:
|
|
||||||
- env: TOX_SUFFIX="aiohttp"
|
|
||||||
python: "pypy3"
|
|
||||||
- python: "3.8-dev"
|
|
||||||
exclude:
|
|
||||||
# Exclude aiohttp support
|
|
||||||
- env: TOX_SUFFIX="aiohttp"
|
|
||||||
python: "2.7"
|
|
||||||
- env: TOX_SUFFIX="aiohttp"
|
|
||||||
python: "pypy"
|
|
||||||
python:
|
python:
|
||||||
- "2.7"
|
|
||||||
- "3.5"
|
- "3.5"
|
||||||
- "3.6"
|
- "3.6"
|
||||||
- "3.7"
|
- "3.7"
|
||||||
- "3.8-dev"
|
- "3.8"
|
||||||
- "pypy"
|
|
||||||
- "pypy3"
|
- "pypy3"
|
||||||
install:
|
install:
|
||||||
- pip install tox-travis codecov
|
- pip install tox-travis codecov
|
||||||
|
|||||||
15
README.rst
15
README.rst
@@ -1,10 +1,17 @@
|
|||||||
|
|
||||||
|
#########
|
||||||
|
VCR.py 📼
|
||||||
|
#########
|
||||||
|
|
||||||
|
|
||||||
|PyPI| |Python versions| |Build Status| |CodeCov| |Gitter| |CodeStyleBlack|
|
|PyPI| |Python versions| |Build Status| |CodeCov| |Gitter| |CodeStyleBlack|
|
||||||
|
|
||||||
VCR.py
|
----
|
||||||
======
|
|
||||||
|
|
||||||
.. image:: https://raw.github.com/kevin1024/vcrpy/master/vcr.png
|
.. image:: https://raw.github.com/kevin1024/vcrpy/master/vcr.png
|
||||||
:alt: vcr.py
|
:alt: vcr.py logo
|
||||||
|
:align: right
|
||||||
|
|
||||||
|
|
||||||
This is a Python version of `Ruby's VCR
|
This is a Python version of `Ruby's VCR
|
||||||
library <https://github.com/vcr/vcr>`__.
|
library <https://github.com/vcr/vcr>`__.
|
||||||
@@ -42,7 +49,7 @@ all HTTP interactions, which will update them to correspond to the new
|
|||||||
API.
|
API.
|
||||||
|
|
||||||
License
|
License
|
||||||
=======
|
-------
|
||||||
|
|
||||||
This library uses the MIT license. See `LICENSE.txt <LICENSE.txt>`__ for
|
This library uses the MIT license. See `LICENSE.txt <LICENSE.txt>`__ for
|
||||||
more details
|
more details
|
||||||
|
|||||||
BIN
docs/_static/vcr.png
vendored
Normal file
BIN
docs/_static/vcr.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 114 KiB |
27
docs/_static/vcr.svg
vendored
Normal file
27
docs/_static/vcr.svg
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<svg width="634" height="346" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 10C0 4.477 4.477 0 10 0h614c5.523 0 10 4.477 10 10v326c0 5.523-4.477 10-10 10H10c-5.523 0-10-4.477-10-10V10z" fill="#181B19"/>
|
||||||
|
<rect x="36" y="83" width="561" height="234" rx="19" fill="#262927"/>
|
||||||
|
<mask id="a" maskUnits="userSpaceOnUse" x="66" y="104" width="503" height="192">
|
||||||
|
<path d="M161.434 120h310.431m-229.757 80c0 44.183-35.841 80-80.054 80S82 244.183 82 200s35.841-80 80.054-80 80.054 35.817 80.054 80zm310.432 0c0 44.183-35.841 80-80.054 80s-80.054-35.817-80.054-80 35.841-80 80.054-80 80.054 35.817 80.054 80z" stroke="#27DD7C" stroke-width="31" stroke-dasharray="503" stroke-dashoffset="0">
|
||||||
|
<animate attributeName="stroke-dashoffset" to="503" begin="1s" dur="1s"/>
|
||||||
|
<animate attributeName="stroke" to="#0" begin="1s" dur="1s"/>
|
||||||
|
|
||||||
|
<animate attributeName="stroke-dashoffset" from="503" to="0" begin="2s" dur="3s" />
|
||||||
|
<animate attributeName="stroke" from="#000" to="#27DD7C" begin="2s" dur="3s"/>
|
||||||
|
|
||||||
|
</path>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#a)">
|
||||||
|
<path fill="url(#paint0_linear)" d="M64 102h507v196H64z"/>
|
||||||
|
</g>
|
||||||
|
<path d="M0 10C0 4.477 4.477 0 10 0h614c5.523 0 10 4.477 10 10v40H0V10z" fill="#262927"/>
|
||||||
|
<rect x="189" y="6" width="256" height="38" rx="2" fill="#fff"/>
|
||||||
|
<path stroke="#E6E8E6" d="M198 14.5h238M198 25.5h238M198 36.5h238"/>
|
||||||
|
<path d="M261.207 18.61c-.443 0-.762-.098-.957-.294-.182-.195-.273-.54-.273-1.035 0-.494.091-.84.273-1.035.195-.195.514-.293.957-.293h6.914c.443 0 .755.098.938.293.195.195.293.54.293 1.035 0 .495-.098.84-.293 1.035-.183.196-.495.293-.938.293h-2.5l5.332 12.735 5.391-12.735h-1.699c-.443 0-.762-.097-.957-.293-.183-.195-.274-.54-.274-1.035 0-.494.091-.84.274-1.035.195-.195.514-.293.957-.293h6.132c.443 0 .756.098.938.293.195.195.293.54.293 1.035 0 .495-.098.84-.293 1.035-.182.196-.495.293-.938.293h-1.23l-6.309 14.551c-.182.443-.449.762-.8.957-.352.209-.853.313-1.504.313s-1.146-.105-1.485-.313c-.338-.208-.599-.527-.781-.957l-6.25-14.55h-1.211zm38.136 3.847a3.73 3.73 0 00-.352-1.621 3.392 3.392 0 00-1.054-1.27c-.456-.364-1.022-.644-1.7-.84-.677-.208-1.464-.312-2.363-.312-.95 0-1.829.163-2.637.488a6.03 6.03 0 00-2.05 1.367 6.354 6.354 0 00-1.348 2.09c-.325.795-.488 1.667-.488 2.618 0 .95.15 1.829.449 2.636a6.197 6.197 0 001.27 2.07 5.858 5.858 0 002.011 1.368c.781.325 1.647.488 2.598.488 1.198 0 2.357-.182 3.476-.547a10.295 10.295 0 003.086-1.62c.339-.261.658-.359.957-.294.3.065.586.326.86.781.221.352.312.716.273 1.094-.026.378-.228.703-.605.977-1.055.78-2.285 1.393-3.692 1.836a14.417 14.417 0 01-4.355.664c-1.432 0-2.728-.235-3.887-.703-1.159-.482-2.148-1.146-2.969-1.993a8.805 8.805 0 01-1.894-2.988c-.443-1.159-.664-2.415-.664-3.77 0-1.354.228-2.604.683-3.75a9.008 9.008 0 011.914-3.007 8.783 8.783 0 012.969-1.973c1.159-.482 2.442-.723 3.848-.723 1.185 0 2.259.215 3.223.645a6.591 6.591 0 012.441 1.797v-1.172c0-.456.104-.781.312-.977.222-.195.606-.293 1.153-.293s.924.098 1.133.293c.221.196.332.521.332.977v5.664c0 .456-.111.781-.332.977-.209.195-.586.293-1.133.293s-.931-.098-1.153-.293c-.208-.196-.312-.521-.312-.977zm12.394-3.848h-2.481c-.442 0-.761-.097-.957-.293-.182-.195-.273-.54-.273-1.035 0-.494.091-.84.273-1.035.196-.195.515-.293.957-.293h3.985c.442 0 .755.098.937.293.195.195.293.54.293 1.035v3.946a13.604 13.604 0 011.641-2.364 11.627 11.627 0 011.992-1.797 8.754 8.754 0 012.187-1.132 6.569 6.569 0 012.246-.41 5.53 5.53 0 012.852.78c.378.222.619.495.723.821.104.326.065.73-.117 1.21-.183.47-.417.802-.704.997-.273.195-.599.182-.976-.039a4.257 4.257 0 00-2.051-.527c-.586 0-1.185.11-1.797.332a7.489 7.489 0 00-1.758.898c-.56.378-1.087.84-1.582 1.387a10.586 10.586 0 00-1.289 1.777 9.542 9.542 0 00-.859 2.09 8.5 8.5 0 00-.313 2.305v3.789h6.582c.443 0 .756.097.938.293.195.195.293.54.293 1.035 0 .495-.098.84-.293 1.035-.182.195-.495.293-.938.293H308.67c-.442 0-.761-.098-.957-.293-.182-.195-.273-.54-.273-1.035 0-.495.091-.84.273-1.035.196-.196.515-.293.957-.293h3.067V18.609zm19.561 0h-1.601c-.443 0-.762-.097-.957-.293-.182-.195-.274-.54-.274-1.035 0-.494.092-.84.274-1.035.195-.195.514-.293.957-.293h3.105c.443 0 .756.098.938.293.195.195.293.54.293 1.035v1.563c.807-1.055 1.745-1.869 2.812-2.442 1.081-.586 2.272-.879 3.575-.879 1.21 0 2.33.209 3.359.625a7.4 7.4 0 012.656 1.758c.755.768 1.348 1.706 1.778 2.813.429 1.107.644 2.363.644 3.77 0 1.405-.215 2.662-.644 3.769-.43 1.107-1.023 2.044-1.778 2.812a7.62 7.62 0 01-2.656 1.778c-1.029.403-2.149.605-3.359.605-1.303 0-2.468-.26-3.497-.781-1.015-.534-1.914-1.29-2.695-2.266v8.614h4.336c.443 0 .755.097.938.292.195.196.293.54.293 1.036 0 .494-.098.84-.293 1.035-.183.195-.495.293-.938.293h-9.453c-.443 0-.762-.098-.957-.293-.182-.196-.274-.54-.274-1.035 0-.495.092-.84.274-1.035.195-.196.514-.294.957-.294h2.187V18.61zm2.93 5.88c0 .963.15 1.822.449 2.577.3.756.716 1.394 1.25 1.915a5.536 5.536 0 001.895 1.171c.742.274 1.543.41 2.402.41.886 0 1.673-.15 2.364-.449.69-.3 1.269-.716 1.738-1.25a5.696 5.696 0 001.074-1.933 7.692 7.692 0 00.371-2.442c0-.885-.124-1.699-.371-2.441a5.485 5.485 0 00-1.074-1.914 4.738 4.738 0 00-1.738-1.27c-.691-.3-1.478-.449-2.364-.449-.859 0-1.66.137-2.402.41a5.391 5.391 0 00-1.895 1.192c-.534.507-.95 1.139-1.25 1.894-.299.755-.449 1.615-.449 2.578zm37.687-8.536c.443 0 .755.098.937.293.196.195.293.54.293 1.035 0 .495-.097.84-.293 1.035-.182.196-.494.293-.937.293h-1.211l-7.988 16.368c-.625 1.276-1.237 2.356-1.836 3.242-.599.885-1.244 1.608-1.934 2.168s-1.452.97-2.285 1.23c-.82.274-1.764.43-2.832.469-.378.013-.697-.072-.957-.254-.248-.182-.397-.534-.449-1.055-.052-.573.013-.983.195-1.23.195-.247.469-.384.82-.41.899-.052 1.66-.176 2.285-.371a4.375 4.375 0 001.739-.977c.521-.469 1.028-1.12 1.523-1.953.508-.82 1.087-1.888 1.738-3.203l-7.148-14.024h-1.23c-.443 0-.762-.097-.958-.293-.182-.195-.273-.54-.273-1.035 0-.494.091-.84.273-1.035.196-.195.515-.293.958-.293h6.914c.442 0 .755.098.937.293.195.195.293.54.293 1.035 0 .495-.098.84-.293 1.035-.182.196-.495.293-.937.293h-2.5l5.507 10.977 5.254-10.977h-1.738c-.443 0-.762-.097-.957-.293-.182-.195-.273-.54-.273-1.035 0-.494.091-.84.273-1.035.195-.195.514-.293.957-.293h6.133z" fill="#262927"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear" x1="64" y1="298" x2="544.524" y2="50.579" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#27DD70"/>
|
||||||
|
<stop offset="1" stop-color="#27DDA6"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.2 KiB |
@@ -130,11 +130,11 @@ Finally, register your method with VCR to use your new request matcher.
|
|||||||
Register your own cassette persister
|
Register your own cassette persister
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
Create your own persistence class, see the :ref:`persister_example`.
|
Create your own persistence class, see the example below:
|
||||||
|
|
||||||
Your custom persister must implement both ``load_cassette`` and ``save_cassette``
|
Your custom persister must implement both ``load_cassette`` and ``save_cassette``
|
||||||
methods. The ``load_cassette`` method must return a deserialized cassette or raise
|
methods. The ``load_cassette`` method must return a deserialized cassette or raise
|
||||||
``ValueError`` if no cassette is found.
|
``ValueError`` if no cassette is found.
|
||||||
|
|
||||||
Once the persister class is defined, register with VCR like so...
|
Once the persister class is defined, register with VCR like so...
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ Once the persister class is defined, register with VCR like so...
|
|||||||
import vcr
|
import vcr
|
||||||
my_vcr = vcr.VCR()
|
my_vcr = vcr.VCR()
|
||||||
|
|
||||||
class CustomerPersister(object):
|
class CustomerPersister:
|
||||||
# implement Persister methods...
|
# implement Persister methods...
|
||||||
|
|
||||||
my_vcr.register_persister(CustomPersister)
|
my_vcr.register_persister(CustomPersister)
|
||||||
|
|||||||
@@ -7,14 +7,21 @@ For a full list of triaged issues, bugs and PRs and what release they are target
|
|||||||
|
|
||||||
All help in providing PRs to close out bug issues is appreciated. Even if that is providing a repo that fully replicates issues. We have very generous contributors that have added these to bug issues which meant another contributor picked up the bug and closed it out.
|
All help in providing PRs to close out bug issues is appreciated. Even if that is providing a repo that fully replicates issues. We have very generous contributors that have added these to bug issues which meant another contributor picked up the bug and closed it out.
|
||||||
|
|
||||||
- 4.0.0 (UNRELEASED)
|
- UNRELEASED
|
||||||
- Remove Python2 support
|
- ...
|
||||||
- Add Python 3.8 TravisCI support
|
|
||||||
|
|
||||||
|
- 4.0.0
|
||||||
|
- Remove Python2 support (@hugovk)
|
||||||
|
- Add Python 3.8 TravisCI support (@neozenith)
|
||||||
|
- Updated the logo to a modern material design (@sean0x42)
|
||||||
|
|
||||||
- 3.0.0
|
- 3.0.0
|
||||||
- This release is a breaking change as it changes how aiohttp follows redirects and your cassettes may need to be re-recorded with this update.
|
- This release is a breaking change as it changes how aiohttp follows redirects and your cassettes may need to be re-recorded with this update.
|
||||||
- Fix multiple requests being replayed per single request in aiohttp stub #495 (@nickdirienzo)
|
- Fix multiple requests being replayed per single request in aiohttp stub #495 (@nickdirienzo)
|
||||||
- Add support for `request_info` on mocked responses in aiohttp stub #495 (@nickdirienzo)
|
- Add support for `request_info` on mocked responses in aiohttp stub #495 (@nickdirienzo)
|
||||||
- doc: fixed variable name (a -> cass) in an example for rewind #492 (@yarikoptic)
|
- doc: fixed variable name (a -> cass) in an example for rewind #492 (@yarikoptic)
|
||||||
|
|
||||||
- 2.1.1
|
- 2.1.1
|
||||||
- Format code with black (@neozenith)
|
- Format code with black (@neozenith)
|
||||||
- Use latest pypy3 in Travis (@hugovk)
|
- Use latest pypy3 in Travis (@hugovk)
|
||||||
@@ -23,188 +30,199 @@ All help in providing PRs to close out bug issues is appreciated. Even if that i
|
|||||||
- Add `pytest-recording` to the documentation as an alternative Pytest plugin (@Stranger6667)
|
- Add `pytest-recording` to the documentation as an alternative Pytest plugin (@Stranger6667)
|
||||||
- Fix yarl and python3.5 version issue (@neozenith)
|
- Fix yarl and python3.5 version issue (@neozenith)
|
||||||
- Fix header matcher for boto3 - fixes #474 (@simahawk)
|
- Fix header matcher for boto3 - fixes #474 (@simahawk)
|
||||||
- 2.1.0 - Add a `rewind` method to reset a cassette (thanks @khamidou)
|
- 2.1.0
|
||||||
New error message with more details on why the cassette failed to play a request (thanks @arthurHamon2, @neozenith)
|
- Add a `rewind` method to reset a cassette (thanks @khamidou)
|
||||||
Handle connect tunnel URI (thanks @jeking3)
|
- New error message with more details on why the cassette failed to play a request (thanks @arthurHamon2, @neozenith)
|
||||||
Add code coverage to the project (thanks @neozenith)
|
- Handle connect tunnel URI (thanks @jeking3)
|
||||||
Drop support to python 3.4
|
- Add code coverage to the project (thanks @neozenith)
|
||||||
Add deprecation warning on python 2.7, next major release will drop python 2.7 support
|
- Drop support to python 3.4
|
||||||
Fix build problems on requests tests (thanks to @dunossauro)
|
- Add deprecation warning on python 2.7, next major release will drop python 2.7 support
|
||||||
Fix matching on 'body' failing when Unicode symbols are present in them (thanks @valgur)
|
- Fix build problems on requests tests (thanks to @dunossauro)
|
||||||
Fix bugs on aiohttp integration (thanks @graingert, @steinnes, @stj, @lamenezes, @lmazuel)
|
- Fix matching on 'body' failing when Unicode symbols are present in them (thanks @valgur)
|
||||||
Fix Biopython incompatibility (thanks @rishab121)
|
- Fix bugs on aiohttp integration (thanks @graingert, @steinnes, @stj, @lamenezes, @lmazuel)
|
||||||
Fix Boto3 integration (thanks @1oglop1, @arthurHamon2)
|
- Fix Biopython incompatibility (thanks @rishab121)
|
||||||
- 2.0.1 - Fix bug when using vcrpy with python 3.4
|
- Fix Boto3 integration (thanks @1oglop1, @arthurHamon2)
|
||||||
- 2.0.0 - Support python 3.7 (fix httplib2 and urllib2, thanks @felixonmars)
|
- 2.0.1
|
||||||
[#356] Fixes `before_record_response` so the original response isn't changed (thanks @kgraves)
|
- Fix bug when using vcrpy with python 3.4
|
||||||
Fix requests stub when using proxy (thanks @samuelfekete @daneoshiga)
|
- 2.0.0
|
||||||
(only for aiohttp stub) Drop support to python 3.4 asyncio.coroutine (aiohttp doesn't support python it anymore)
|
- Support python 3.7 (fix httplib2 and urllib2, thanks @felixonmars)
|
||||||
Fix aiohttp stub to work with aiohttp client (thanks @stj)
|
- [#356] Fixes `before_record_response` so the original response isn't changed (thanks @kgraves)
|
||||||
Fix aiohttp stub to accept content type passed
|
- Fix requests stub when using proxy (thanks @samuelfekete @daneoshiga)
|
||||||
Improve docs (thanks @adamchainz)
|
- (only for aiohttp stub) Drop support to python 3.4 asyncio.coroutine (aiohttp doesn't support python it anymore)
|
||||||
- 1.13.0 - Fix support to latest aiohttp version (3.3.2). Fix content-type bug in aiohttp stub. Save URL with query params properly when using aiohttp.
|
- Fix aiohttp stub to work with aiohttp client (thanks @stj)
|
||||||
- 1.12.0 - Fix support to latest aiohttp version (3.2.1), Adapted setup to PEP508, Support binary responses on aiohttp, Dropped support for EOL python versions (2.6 and 3.3)
|
- Fix aiohttp stub to accept content type passed
|
||||||
- 1.11.1 Fix compatibility with newest requests and urllib3 releases
|
- Improve docs (thanks @adamchainz)
|
||||||
- 1.11.0 Allow injection of persistence methods + bugfixes (thanks @j-funk and @IvanMalison),
|
|
||||||
Support python 3.6 + CI tests (thanks @derekbekoe and @graingert),
|
|
||||||
Support pytest-asyncio coroutines (thanks @graingert)
|
- 1.13.0
|
||||||
- 1.10.5 Added a fix to httplib2 (thanks @carlosds730), Fix an issue with
|
- Fix support to latest aiohttp version (3.3.2). Fix content-type bug in aiohttp stub. Save URL with query params properly when using aiohttp.
|
||||||
aiohttp (thanks @madninja), Add missing requirement yarl (thanks @lamenezes),
|
- 1.12.0
|
||||||
Remove duplicate mock triple (thanks @FooBarQuaxx)
|
- Fix support to latest aiohttp version (3.2.1), Adapted setup to PEP508, Support binary responses on aiohttp, Dropped support for EOL python versions (2.6 and 3.3)
|
||||||
- 1.10.4 Fix an issue with asyncio aiohttp (thanks @madninja)
|
- 1.11.1
|
||||||
- 1.10.3 Fix some issues with asyncio and params (thanks @anovikov1984 and
|
- Fix compatibility with newest requests and urllib3 releases
|
||||||
@lamenezes), Fix some issues with cassette serialize / deserialize and empty
|
- 1.11.0
|
||||||
response bodies (thanks @gRoussac and @dz0ny)
|
- Allow injection of persistence methods + bugfixes (thanks @j-funk and @IvanMalison),
|
||||||
- 1.10.2 Fix 1.10.1 release - add aiohttp support back in
|
- Support python 3.6 + CI tests (thanks @derekbekoe and @graingert),
|
||||||
- 1.10.1 [bad release] Fix build for Fedora package + python2 (thanks @puiterwijk and @lamenezes)
|
- Support pytest-asyncio coroutines (thanks @graingert)
|
||||||
- 1.10.0 Add support for aiohttp (thanks @lamenezes)
|
- 1.10.5
|
||||||
- 1.9.0 Add support for boto3 (thanks @desdm, @foorbarna). Fix deepcopy issue
|
- Added a fix to httplib2 (thanks @carlosds730), Fix an issue with
|
||||||
for response headers when `decode_compressed_response` is enabled (thanks
|
- aiohttp (thanks @madninja), Add missing requirement yarl (thanks @lamenezes),
|
||||||
@nickdirienzo)
|
- Remove duplicate mock triple (thanks @FooBarQuaxx)
|
||||||
- 1.8.0 Fix for Serialization errors with JSON adapter (thanks
|
- 1.10.4
|
||||||
@aliaksandrb). Avoid concatenating bytes with strings (thanks
|
- Fix an issue with asyncio aiohttp (thanks @madninja)
|
||||||
@jaysonsantos). Exclude __pycache__ dirs & compiled files in sdist
|
- 1.10.3
|
||||||
(thanks @koobs). Fix Tornado support behavior for Tornado 3 (thanks
|
- Fix some issues with asyncio and params (thanks @anovikov1984 and @lamenezes)
|
||||||
@abhinav). decode_compressed_response option and filter (thanks
|
- Fix some issues with cassette serialize / deserialize and empty response bodies (thanks @gRoussac and @dz0ny)
|
||||||
@jayvdb).
|
- 1.10.2
|
||||||
- 1.7.4 [#217] Make use_cassette decorated functions actually return a
|
- Fix 1.10.1 release - add aiohttp support back in
|
||||||
value (thanks @bcen). [#199] Fix path transfromation defaults.
|
- 1.10.1
|
||||||
Better headers dictionary management.
|
- [bad release] Fix build for Fedora package + python2 (thanks @puiterwijk and @lamenezes)
|
||||||
- 1.7.3 [#188] ``additional_matchers`` kwarg on ``use_cassette``.
|
- 1.10.0
|
||||||
[#191] Actually support passing multiple before_record_request
|
- Add support for aiohttp (thanks @lamenezes)
|
||||||
functions (thanks @agriffis).
|
- 1.9.0
|
||||||
- 1.7.2 [#186] Get effective_url in tornado (thanks @mvschaik), [#187]
|
- Add support for boto3 (thanks @desdm, @foorbarna).
|
||||||
Set request_time on Response object in tornado (thanks @abhinav).
|
- Fix deepcopy issue for response headers when `decode_compressed_response` is enabled (thanks @nickdirienzo)
|
||||||
- 1.7.1 [#183] Patch ``fetch_impl`` instead of the entire HTTPClient
|
- 1.8.0
|
||||||
class for Tornado (thanks @abhinav).
|
- Fix for Serialization errors with JSON adapter (thanks @aliaksandrb).
|
||||||
- 1.7.0 [#177] Properly support coroutine/generator decoration. [#178]
|
- Avoid concatenating bytes with strings (thanks @jaysonsantos).
|
||||||
Support distribute (thanks @graingert). [#163] Make compatibility
|
- Exclude __pycache__ dirs & compiled files in sdist (thanks @koobs).
|
||||||
between python2 and python3 recorded cassettes more robust (thanks
|
- Fix Tornado support behavior for Tornado 3 (thanks @abhinav).
|
||||||
@gward).
|
- decode_compressed_response option and filter (thanks @jayvdb).
|
||||||
- 1.6.1 [#169] Support conditional requirements in old versions of
|
- 1.7.4 [#217]
|
||||||
pip, Fix RST parse errors generated by pandoc, [Tornado] Fix
|
- Make use_cassette decorated functions actually return a value (thanks @bcen).
|
||||||
unsupported features exception not being raised, [#166]
|
- [#199] Fix path transfromation defaults.
|
||||||
content-aware body matcher.
|
- Better headers dictionary management.
|
||||||
- 1.6.0 [#120] Tornado support (thanks @abhinav), [#147] packaging fixes
|
- 1.7.3 [#188]
|
||||||
(thanks @graingert), [#158] allow filtering post params in requests
|
- ``additional_matchers`` kwarg on ``use_cassette``.
|
||||||
(thanks @MrJohz), [#140] add xmlrpclib support (thanks @Diaoul).
|
- [#191] Actually support passing multiple before_record_request functions (thanks @agriffis).
|
||||||
- 1.5.2 Fix crash when cassette path contains cassette library
|
- 1.7.2
|
||||||
directory (thanks @gazpachoking).
|
- [#186] Get effective_url in tornado (thanks @mvschaik)
|
||||||
- 1.5.0 Automatic cassette naming and 'application/json' post data
|
- [#187] Set request_time on Response object in tornado (thanks @abhinav).
|
||||||
filtering (thanks @marco-santamaria).
|
- 1.7.1
|
||||||
- 1.4.2 Fix a bug caused by requests 2.7 and chunked transfer encoding
|
- [#183] Patch ``fetch_impl`` instead of the entire HTTPClient class for Tornado (thanks @abhinav).
|
||||||
- 1.4.1 Include README, tests, LICENSE in package. Thanks @ralphbean.
|
- 1.7.0
|
||||||
- 1.4.0 Filter post data parameters (thanks @eadmundo), support for
|
- [#177] Properly support coroutine/generator decoration.
|
||||||
posting files through requests, inject\_cassette kwarg to access
|
- [#178] Support distribute (thanks @graingert). [#163] Make compatibility between python2 and python3 recorded cassettes more robust (thanks @gward).
|
||||||
cassette from ``use_cassette`` decorated function,
|
- 1.6.1
|
||||||
``with_current_defaults`` actually works (thanks @samstav).
|
- [#169] Support conditional requirements in old versions of pip
|
||||||
- 1.3.0 Fix/add support for urllib3 (thanks @aisch), fix default port
|
- Fix RST parse errors generated by pandoc
|
||||||
for https (thanks @abhinav).
|
- [Tornado] Fix unsupported features exception not being raised
|
||||||
- 1.2.0 Add custom\_patches argument to VCR/Cassette objects to allow
|
- [#166] content-aware body matcher.
|
||||||
users to stub custom classes when cassettes become active.
|
- 1.6.0
|
||||||
- 1.1.4 Add force reset around calls to actual connection from stubs,
|
- [#120] Tornado support (thanks @abhinav)
|
||||||
to ensure compatibility with the version of httplib/urlib2 in python
|
- [#147] packaging fixes (thanks @graingert)
|
||||||
2.7.9.
|
- [#158] allow filtering post params in requests (thanks @MrJohz)
|
||||||
- 1.1.3 Fix python3 headers field (thanks @rtaboada), fix boto test
|
- [#140] add xmlrpclib support (thanks @Diaoul).
|
||||||
(thanks @telaviv), fix new\_episodes record mode (thanks @jashugan),
|
- 1.5.2
|
||||||
fix Windows connectionpool stub bug (thanks @gazpachoking), add
|
- Fix crash when cassette path contains cassette library directory (thanks @gazpachoking).
|
||||||
support for requests 2.5
|
- 1.5.0
|
||||||
- 1.1.2 Add urllib==1.7.1 support. Make json serialize error handling
|
- Automatic cassette naming and 'application/json' post data filtering (thanks @marco-santamaria).
|
||||||
correct Improve logging of match failures.
|
- 1.4.2
|
||||||
- 1.1.1 Use function signature preserving ``wrapt.decorator`` to write
|
- Fix a bug caused by requests 2.7 and chunked transfer encoding
|
||||||
the decorator version of use\_cassette in order to ensure
|
- 1.4.1
|
||||||
compatibility with py.test fixtures and python 2. Move all request
|
- Include README, tests, LICENSE in package. Thanks @ralphbean.
|
||||||
filtering into the ``before_record_callable``.
|
- 1.4.0
|
||||||
- 1.1.0 Add ``before_record_response``. Fix several bugs related to the
|
- Filter post data parameters (thanks @eadmundo)
|
||||||
context management of cassettes.
|
- Support for posting files through requests, inject\_cassette kwarg to access cassette from ``use_cassette`` decorated function, ``with_current_defaults`` actually works (thanks @samstav).
|
||||||
- 1.0.3: Fix an issue with requests 2.4 and make sure case sensitivity
|
- 1.3.0
|
||||||
is consistent across python versions
|
- Fix/add support for urllib3 (thanks @aisch)
|
||||||
- 1.0.2: Fix an issue with requests 2.3
|
- Fix default port for https (thanks @abhinav).
|
||||||
- 1.0.1: Fix a bug with the new ignore requests feature and the once
|
- 1.2.0
|
||||||
record mode
|
- Add custom\_patches argument to VCR/Cassette objects to allow users to stub custom classes when cassettes become active.
|
||||||
- 1.0.0: *BACKWARDS INCOMPATIBLE*: Please see the 'upgrade' section in
|
- 1.1.4
|
||||||
the README. Take a look at the matcher section as well, you might
|
- Add force reset around calls to actual connection from stubs, to ensure compatibility with the version of httplib/urlib2 in python 2.7.9.
|
||||||
want to update your ``match_on`` settings. Add support for filtering
|
- 1.1.3
|
||||||
sensitive data from requests, matching query strings after the order
|
- Fix python3 headers field (thanks @rtaboada)
|
||||||
changes and improving the built-in matchers, (thanks to @mshytikov),
|
- fix boto test (thanks @telaviv)
|
||||||
support for ignoring requests to certain hosts, bump supported
|
- fix new\_episodes record mode (thanks @jashugan),
|
||||||
Python3 version to 3.4, fix some bugs with Boto support (thanks
|
- fix Windows connectionpool stub bug (thanks @gazpachoking)
|
||||||
@marusich), fix error with URL field capitalization in README (thanks
|
- add support for requests 2.5
|
||||||
@simon-weber), added some log messages to help with debugging, added
|
- 1.1.2
|
||||||
``all_played`` property on cassette (thanks @mshytikov)
|
- Add urllib==1.7.1 support.
|
||||||
- 0.7.0: VCR.py now supports Python 3! (thanks @asundg) Also I
|
- Make json serialize error handling correct
|
||||||
refactored the stub connections quite a bit to add support for the
|
- Improve logging of match failures.
|
||||||
putrequest and putheader calls. This version also adds support for
|
- 1.1.1
|
||||||
httplib2 (thanks @nilp0inter). I have added a couple tests for boto
|
- Use function signature preserving ``wrapt.decorator`` to write the decorator version of use\_cassette in order to ensure compatibility with py.test fixtures and python 2.
|
||||||
since it is an http client in its own right. Finally, this version
|
- Move all request filtering into the ``before_record_callable``.
|
||||||
includes a fix for a bug where requests wasn't being patched properly
|
- 1.1.0
|
||||||
(thanks @msabramo).
|
- Add ``before_record_response``. Fix several bugs related to the context management of cassettes.
|
||||||
- 0.6.0: Store response headers as a list since a HTTP response can
|
- 1.0.3
|
||||||
have the same header twice (happens with set-cookie sometimes). This
|
- Fix an issue with requests 2.4 and make sure case sensitivity is consistent across python versions
|
||||||
has the added benefit of preserving the order of headers. Thanks
|
- 1.0.2
|
||||||
@smallcode for the bug report leading to this change. I have made an
|
- Fix an issue with requests 2.3
|
||||||
effort to ensure backwards compatibility with the old cassettes'
|
- 1.0.1
|
||||||
header storage mechanism, but if you want to upgrade to the new
|
- Fix a bug with the new ignore requests feature and the once record mode
|
||||||
header storage, you should delete your cassettes and re-record them.
|
- 1.0.0
|
||||||
Also this release adds better error messages (thanks @msabramo) and
|
- *BACKWARDS INCOMPATIBLE*: Please see the 'upgrade' section in the README. Take a look at the matcher section as well, you might want to update your ``match_on`` settings.
|
||||||
adds support for using VCR as a decorator (thanks @smallcode for the
|
- Add support for filtering sensitive data from requests, matching query strings after the order changes and improving the built-in matchers, (thanks to @mshytikov)
|
||||||
motivation)
|
- Support for ignoring requests to certain hosts, bump supported Python3 version to 3.4, fix some bugs with Boto support (thanks @marusich)
|
||||||
- 0.5.0: Change the ``response_of`` method to ``responses_of`` since
|
- Fix error with URL field capitalization in README (thanks @simon-weber)
|
||||||
cassettes can now contain more than one response for a request. Since
|
- Added some log messages to help with debugging
|
||||||
this changes the API, I'm bumping the version. Also includes 2
|
- Added ``all_played`` property on cassette (thanks @mshytikov)
|
||||||
bugfixes: a better error message when attempting to overwrite a
|
|
||||||
cassette file, and a fix for a bug with requests sessions (thanks
|
- 0.7.0
|
||||||
@msabramo)
|
- VCR.py now supports Python 3! (thanks @asundg)
|
||||||
- 0.4.0: Change default request recording behavior for multiple
|
- Also I refactored the stub connections quite a bit to add support for the putrequest and putheader calls.
|
||||||
requests. If you make the same request multiple times to the same
|
- This version also adds support for httplib2 (thanks @nilp0inter).
|
||||||
URL, the response might be different each time (maybe the response
|
- I have added a couple tests for boto since it is an http client in its own right.
|
||||||
has a timestamp in it or something), so this will make the same
|
- Finally, this version includes a fix for a bug where requests wasn't being patched properly (thanks @msabramo).
|
||||||
request multiple times and save them all. Then, when you are
|
- 0.6.0
|
||||||
replaying the cassette, the responses will be played back in the same
|
- Store response headers as a list since a HTTP response can have the same header twice (happens with set-cookie sometimes).
|
||||||
order in which they were received. If you were making multiple
|
- This has the added benefit of preserving the order of headers.
|
||||||
requests to the same URL in a cassette before version 0.4.0, you
|
- Thanks @smallcode for the bug report leading to this change.
|
||||||
might need to regenerate your cassette files. Also, removes support
|
- I have made an effort to ensure backwards compatibility with the old cassettes' header storage mechanism, but if you want to upgrade to the new header storage, you should delete your cassettes and re-record them.
|
||||||
for the cassette.play\_count counter API, since individual requests
|
- Also this release adds better error messages (thanks @msabramo)
|
||||||
aren't unique anymore. A cassette might contain the same request
|
- and adds support for using VCR as a decorator (thanks @smallcode for the motivation)
|
||||||
several times. Also removes secure overwrite feature since that was
|
- 0.5.0
|
||||||
breaking overwriting files in Windows, and fixes a bug preventing
|
- Change the ``response_of`` method to ``responses_of`` since cassettes can now contain more than one response for a request.
|
||||||
request's automatic body decompression from working.
|
- Since this changes the API, I'm bumping the version.
|
||||||
- 0.3.5: Fix compatibility with requests 2.x
|
- Also includes 2 bugfixes:
|
||||||
- 0.3.4: Bugfix: close file before renaming it. This fixes an issue on
|
- a better error message when attempting to overwrite a cassette file,
|
||||||
Windows. Thanks @smallcode for the fix.
|
- and a fix for a bug with requests sessions (thanks @msabramo)
|
||||||
- 0.3.3: Bugfix for error message when an unreigstered custom matcher
|
- 0.4.0
|
||||||
was used
|
- Change default request recording behavior for multiple requests.
|
||||||
- 0.3.2: Fix issue with new config syntax and the ``match_on``
|
- If you make the same request multiple times to the same URL, the response might be different each time (maybe the response has a timestamp in it or something), so this will make the same request multiple times and save them all.
|
||||||
parameter. Thanks, @chromy!
|
- Then, when you are replaying the cassette, the responses will be played back in the same order in which they were received.
|
||||||
- 0.3.1: Fix issue causing full paths to be sent on the HTTP request
|
- If you were making multiple requests to the same URL in a cassette before version 0.4.0, you might need to regenerate your cassette files.
|
||||||
line.
|
- Also, removes support for the cassette.play\_count counter API, since individual requests aren't unique anymore.
|
||||||
- 0.3.0: *Backwards incompatible release* - Added support for record
|
- A cassette might contain the same request several times.
|
||||||
modes, and changed the default recording behavior to the "once"
|
- Also removes secure overwrite feature since that was breaking overwriting files in Windows
|
||||||
record mode. Please see the documentation on record modes for more.
|
- And fixes a bug preventing request's automatic body decompression from working.
|
||||||
Added support for custom request matching, and changed the default
|
- 0.3.5
|
||||||
request matching behavior to match only on the URL and method. Also,
|
- Fix compatibility with requests 2.x
|
||||||
improved the httplib mocking to add support for the
|
- 0.3.4
|
||||||
``HTTPConnection.send()`` method. This means that requests won't
|
- Bugfix: close file before renaming it. This fixes an issue on Windows. Thanks @smallcode for the fix.
|
||||||
actually be sent until the response is read, since I need to record
|
- 0.3.3
|
||||||
the entire request in order to match up the appropriate response. I
|
- Bugfix for error message when an unreigstered custom matcher was used
|
||||||
don't think this should cause any issues unless you are sending
|
- 0.3.2
|
||||||
requests without ever loading the response (which none of the
|
- Fix issue with new config syntax and the ``match_on`` parameter. Thanks, @chromy!
|
||||||
standard httplib wrappers do, as far as I know. Thanks to @fatuhoku
|
- 0.3.1
|
||||||
for some of the ideas and the motivation behind this release.
|
- Fix issue causing full paths to be sent on the HTTP request line.
|
||||||
- 0.2.1: Fixed missing modules in setup.py
|
- 0.3.0
|
||||||
- 0.2.0: Added configuration API, which lets you configure some
|
- *Backwards incompatible release*
|
||||||
settings on VCR (see the README). Also, VCR no longer saves cassettes
|
- Added support for record modes, and changed the default recording behavior to the "once" record mode. Please see the documentation on record modes for more.
|
||||||
if they haven't changed at all and supports JSON as well as YAML
|
- Added support for custom request matching, and changed the default request matching behavior to match only on the URL and method.
|
||||||
(thanks @sirpengi). Added amazing new skeumorphic logo, thanks
|
- Also, improved the httplib mocking to add support for the ``HTTPConnection.send()`` method.
|
||||||
@hairarrow.
|
- This means that requests won't actually be sent until the response is read, since I need to record the entire request in order to match up the appropriate response.
|
||||||
- 0.1.0: *backwards incompatible release - delete your old cassette
|
- I don't think this should cause any issues unless you are sending requests without ever loading the response (which none of the standard httplib wrappers do, as far as I know).
|
||||||
files*: This release adds the ability to access the cassette to make
|
- Thanks to @fatuhoku for some of the ideas and the motivation behind this release.
|
||||||
assertions on it, as well as a major code refactor thanks to
|
- 0.2.1
|
||||||
@dlecocq. It also fixes a couple longstanding bugs with redirects and
|
- Fixed missing modules in setup.py
|
||||||
HTTPS. [#3 and #4]
|
- 0.2.0
|
||||||
- 0.0.4: If you have libyaml installed, vcrpy will use the c bindings
|
- Added configuration API, which lets you configure some settings on VCR (see the README).
|
||||||
instead. Speed up your tests! Thanks @dlecocq
|
- Also, VCR no longer saves cassettes if they haven't changed at all and supports JSON as well as YAML (thanks @sirpengi).
|
||||||
- 0.0.3: Add support for requests 1.2.3. Support for older versions of
|
- Added amazing new skeumorphic logo, thanks @hairarrow.
|
||||||
requests dropped (thanks @vitormazzi and @bryanhelmig)
|
- 0.1.0
|
||||||
- 0.0.2: Add support for requests / urllib3
|
- *backwards incompatible release - delete your old cassette files*
|
||||||
- 0.0.1: Initial Release
|
- This release adds the ability to access the cassette to make assertions on it
|
||||||
|
- as well as a major code refactor thanks to @dlecocq.
|
||||||
|
- It also fixes a couple longstanding bugs with redirects and HTTPS. [#3 and #4]
|
||||||
|
- 0.0.4
|
||||||
|
- If you have libyaml installed, vcrpy will use the c bindings instead. Speed up your tests! Thanks @dlecocq
|
||||||
|
- 0.0.3
|
||||||
|
- Add support for requests 1.2.3. Support for older versions of requests dropped (thanks @vitormazzi and @bryanhelmig)
|
||||||
|
- 0.0.2
|
||||||
|
- Add support for requests / urllib3
|
||||||
|
- 0.0.1
|
||||||
|
- Initial Release
|
||||||
|
|
||||||
|
|||||||
75
docs/conf.py
75
docs/conf.py
@@ -12,8 +12,33 @@
|
|||||||
# All configuration values have a default; values that are commented out
|
# All configuration values have a default; values that are commented out
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
|
import codecs
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def read(*parts):
|
||||||
|
# intentionally *not* adding an encoding option to open, See:
|
||||||
|
# https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690
|
||||||
|
with codecs.open(os.path.join(here, *parts), "r") as fp:
|
||||||
|
return fp.read()
|
||||||
|
|
||||||
|
|
||||||
|
def find_version(*file_paths):
|
||||||
|
version_file = read(*file_paths)
|
||||||
|
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
|
||||||
|
if version_match:
|
||||||
|
return version_match.group(1)
|
||||||
|
|
||||||
|
raise RuntimeError("Unable to find version string.")
|
||||||
|
|
||||||
|
|
||||||
|
autodoc_default_options = {
|
||||||
|
"members": None,
|
||||||
|
"undoc-members": None,
|
||||||
|
}
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
@@ -27,7 +52,14 @@ import os
|
|||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx.ext.coverage", "sphinx.ext.viewcode"]
|
extensions = [
|
||||||
|
"sphinx.ext.autodoc",
|
||||||
|
"sphinx.ext.intersphinx",
|
||||||
|
"sphinx.ext.coverage",
|
||||||
|
"sphinx.ext.viewcode",
|
||||||
|
"sphinx.ext.todo",
|
||||||
|
"sphinx.ext.githubpages",
|
||||||
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ["_templates"]
|
templates_path = ["_templates"]
|
||||||
@@ -44,18 +76,18 @@ source_suffix = ".rst"
|
|||||||
master_doc = "index"
|
master_doc = "index"
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u"vcrpy"
|
project = "vcrpy"
|
||||||
copyright = u"2015, Kevin McCarthy"
|
copyright = "2015, Kevin McCarthy"
|
||||||
author = u"Kevin McCarthy"
|
author = "Kevin McCarthy"
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = "1.7.4"
|
# version = "1.7.4"
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = "1.7.4"
|
version = release = find_version("..", "vcr", "__init__.py")
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
@@ -106,11 +138,11 @@ todo_include_todos = False
|
|||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages.
|
# The theme to use for HTML and HTML Help pages.
|
||||||
# https://read-the-docs.readthedocs.io/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs
|
# https://read-the-docs.readthedocs.io/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs
|
||||||
if "READTHEDOCS" not in os.environ:
|
# if "READTHEDOCS" not in os.environ:
|
||||||
import sphinx_rtd_theme
|
# import sphinx_rtd_theme
|
||||||
|
#
|
||||||
html_theme = "sphinx_rtd_theme"
|
# html_theme = "sphinx_rtd_theme"
|
||||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
# html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
@@ -153,6 +185,8 @@ html_static_path = ["_static"]
|
|||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
# Custom sidebar templates, maps document names to template names.
|
||||||
# html_sidebars = {}
|
# html_sidebars = {}
|
||||||
|
html_sidebars = {"**": ["globaltoc.html", "relations.html", "sourcelink.html", "searchbox.html"]}
|
||||||
|
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
# template names.
|
# template names.
|
||||||
@@ -205,19 +239,21 @@ htmlhelp_basename = "vcrpydoc"
|
|||||||
|
|
||||||
latex_elements = {
|
latex_elements = {
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
#'papersize': 'letterpaper',
|
# 'papersize': 'letterpaper',
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
#'pointsize': '10pt',
|
# 'pointsize': '10pt',
|
||||||
# Additional stuff for the LaTeX preamble.
|
# Additional stuff for the LaTeX preamble.
|
||||||
#'preamble': '',
|
# 'preamble': '',
|
||||||
# Latex figure (float) alignment
|
# Latex figure (float) alignment
|
||||||
#'figure_align': 'htbp',
|
# 'figure_align': 'htbp',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [(master_doc, "vcrpy.tex", u"vcrpy Documentation", u"Kevin McCarthy", "manual")]
|
latex_documents = [
|
||||||
|
(master_doc, "vcrpy.tex", "vcrpy Documentation", "Kevin McCarthy", "manual"),
|
||||||
|
]
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
# the title page.
|
# the title page.
|
||||||
@@ -244,7 +280,7 @@ latex_documents = [(master_doc, "vcrpy.tex", u"vcrpy Documentation", u"Kevin McC
|
|||||||
|
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [(master_doc, "vcrpy", u"vcrpy Documentation", [author], 1)]
|
man_pages = [(master_doc, "vcrpy", "vcrpy Documentation", [author], 1)]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
# man_show_urls = False
|
# man_show_urls = False
|
||||||
@@ -259,12 +295,12 @@ texinfo_documents = [
|
|||||||
(
|
(
|
||||||
master_doc,
|
master_doc,
|
||||||
"vcrpy",
|
"vcrpy",
|
||||||
u"vcrpy Documentation",
|
"vcrpy Documentation",
|
||||||
author,
|
author,
|
||||||
"vcrpy",
|
"vcrpy",
|
||||||
"One line description of project.",
|
"One line description of project.",
|
||||||
"Miscellaneous",
|
"Miscellaneous",
|
||||||
)
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
@@ -282,3 +318,4 @@ texinfo_documents = [
|
|||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {"https://docs.python.org/": None}
|
intersphinx_mapping = {"https://docs.python.org/": None}
|
||||||
|
html_theme = "alabaster"
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
Contributing
|
Contributing
|
||||||
============
|
============
|
||||||
|
|
||||||
|
.. image:: _static/vcr.svg
|
||||||
|
:alt: vcr.py logo
|
||||||
|
:align: right
|
||||||
|
|
||||||
🚀 Milestones
|
🚀 Milestones
|
||||||
--------------
|
--------------
|
||||||
For anyone interested in the roadmap and projected release milestones please see the following link:
|
For anyone interested in the roadmap and projected release milestones please see the following link:
|
||||||
@@ -81,18 +85,22 @@ Running VCR's test suite
|
|||||||
|
|
||||||
The tests are all run automatically on `Travis
|
The tests are all run automatically on `Travis
|
||||||
CI <https://travis-ci.org/kevin1024/vcrpy>`__, but you can also run them
|
CI <https://travis-ci.org/kevin1024/vcrpy>`__, but you can also run them
|
||||||
yourself using `py.test <http://pytest.org/>`__ and
|
yourself using `pytest <http://pytest.org/>`__ and
|
||||||
`Tox <http://tox.testrun.org/>`__. Tox will automatically run them in
|
`Tox <http://tox.testrun.org/>`__.
|
||||||
all environments VCR.py supports. The test suite is pretty big and slow,
|
|
||||||
but you can tell tox to only run specific tests like this::
|
Tox will automatically run them in all environments VCR.py supports if they are available on your `PATH`. Alternatively you can use `tox-pyenv <https://pypi.org/project/tox-pyenv/>`_ with
|
||||||
|
`pyenv <https://github.com/pyenv/pyenv>`_.
|
||||||
|
We recommend you read the documentation for each and see the section further below.
|
||||||
|
|
||||||
|
The test suite is pretty big and slow, but you can tell tox to only run specific tests like this::
|
||||||
|
|
||||||
tox -e {pyNN}-{HTTP_LIBRARY} -- <pytest flags passed through>
|
tox -e {pyNN}-{HTTP_LIBRARY} -- <pytest flags passed through>
|
||||||
|
|
||||||
tox -e py27-requests -- -v -k "'test_status_code or test_gzip'"
|
tox -e py36-requests -- -v -k "'test_status_code or test_gzip'"
|
||||||
tox -e py37-requests -- -v --last-failed
|
tox -e py37-requests -- -v --last-failed
|
||||||
|
|
||||||
This will run only tests that look like ``test_status_code`` or
|
This will run only tests that look like ``test_status_code`` or
|
||||||
``test_gzip`` in the test suite, and only in the python 2.7 environment
|
``test_gzip`` in the test suite, and only in the python 3.6 environment
|
||||||
that has ``requests`` installed.
|
that has ``requests`` installed.
|
||||||
|
|
||||||
Also, in order for the boto tests to run, you will need an AWS key.
|
Also, in order for the boto tests to run, you will need an AWS key.
|
||||||
@@ -106,8 +114,8 @@ Using PyEnv with VCR's test suite
|
|||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
PyEnv is a tool for managing multiple installation of python on your system.
|
PyEnv is a tool for managing multiple installation of python on your system.
|
||||||
See the full documentation at their `github <https://github.com/pyenv/pyenv>`
|
See the full documentation at their `github <https://github.com/pyenv/pyenv>`_
|
||||||
but we are also going to use `tox-pyenv <https://pypi.org/project/tox-pyenv/>`
|
but we are also going to use `tox-pyenv <https://pypi.org/project/tox-pyenv/>`_
|
||||||
in this example::
|
in this example::
|
||||||
|
|
||||||
git clone https://github.com/pyenv/pyenv ~/.pyenv
|
git clone https://github.com/pyenv/pyenv ~/.pyenv
|
||||||
@@ -122,10 +130,10 @@ in this example::
|
|||||||
pip install tox tox-pyenv
|
pip install tox tox-pyenv
|
||||||
|
|
||||||
# Install supported versions (at time of writing), this does not activate them
|
# Install supported versions (at time of writing), this does not activate them
|
||||||
pyenv install 2.7.10 3.5.7 3.6.9 3.7.4 3.8-dev pypy2.6-7.1.1 pypy3.6-7.1.1
|
pyenv install 3.5.9 3.6.9 3.7.5 3.8.0 pypy3.6-7.2.0
|
||||||
|
|
||||||
# This activates them
|
# This activates them
|
||||||
pyenv local 2.7.10 3.5.7 3.6.9 3.7.4 3.8-dev pypy2.6-7.1.1 pypy3.6-7.1.1
|
pyenv local 3.5.9 3.6.9 3.7.5 3.8.0 pypy3.6-7.2.0
|
||||||
|
|
||||||
# Run the whole test suite
|
# Run the whole test suite
|
||||||
tox
|
tox
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ It can return multiple similar requests with :
|
|||||||
|
|
||||||
CannotOverwriteExistingCassetteException message example :
|
CannotOverwriteExistingCassetteException message example :
|
||||||
|
|
||||||
.. code:: python
|
.. code::
|
||||||
|
|
||||||
CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('cassette.yaml') in your current record mode ('once').
|
CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('cassette.yaml') in your current record mode ('once').
|
||||||
No match for the request (<Request (GET) https://www.googleapis.com/?alt=json&maxResults=200>) was found.
|
No match for the request (<Request (GET) https://www.googleapis.com/?alt=json&maxResults=200>) was found.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Contents
|
|||||||
========
|
========
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 3
|
||||||
|
|
||||||
installation
|
installation
|
||||||
usage
|
usage
|
||||||
@@ -15,6 +15,7 @@ Contents
|
|||||||
contributing
|
contributing
|
||||||
changelog
|
changelog
|
||||||
|
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ with pip::
|
|||||||
Compatibility
|
Compatibility
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
VCR.py supports Python 2.7 and 3.5+, and
|
VCR.py supports Python 3.5+, and `pypy <http://pypy.org>`__.
|
||||||
`pypy <http://pypy.org>`__.
|
|
||||||
|
|
||||||
The following HTTP libraries are supported:
|
The following HTTP libraries are supported:
|
||||||
|
|
||||||
|
|||||||
36
setup.py
36
setup.py
@@ -1,11 +1,31 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import codecs
|
||||||
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
from setuptools.command.test import test as TestCommand
|
from setuptools.command.test import test as TestCommand
|
||||||
|
|
||||||
long_description = open("README.rst", "r").read()
|
long_description = open("README.rst", "r").read()
|
||||||
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def read(*parts):
|
||||||
|
# intentionally *not* adding an encoding option to open, See:
|
||||||
|
# https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690
|
||||||
|
with codecs.open(os.path.join(here, *parts), "r") as fp:
|
||||||
|
return fp.read()
|
||||||
|
|
||||||
|
|
||||||
|
def find_version(*file_paths):
|
||||||
|
version_file = read(*file_paths)
|
||||||
|
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
|
||||||
|
if version_match:
|
||||||
|
return version_match.group(1)
|
||||||
|
|
||||||
|
raise RuntimeError("Unable to find version string.")
|
||||||
|
|
||||||
|
|
||||||
class PyTest(TestCommand):
|
class PyTest(TestCommand):
|
||||||
@@ -26,26 +46,20 @@ install_requires = [
|
|||||||
"PyYAML",
|
"PyYAML",
|
||||||
"wrapt",
|
"wrapt",
|
||||||
"six>=1.5",
|
"six>=1.5",
|
||||||
'contextlib2; python_version=="2.7"',
|
|
||||||
'mock; python_version=="2.7"',
|
|
||||||
'yarl; python_version>="3.6"',
|
'yarl; python_version>="3.6"',
|
||||||
'yarl<1.4; python_version=="3.5"',
|
'yarl<1.4; python_version=="3.5"',
|
||||||
]
|
]
|
||||||
|
|
||||||
excluded_packages = ["tests*"]
|
|
||||||
if sys.version_info[0] == 2:
|
|
||||||
excluded_packages.append("vcr.stubs.aiohttp_stubs")
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="vcrpy",
|
name="vcrpy",
|
||||||
version="3.0.0",
|
version=find_version("vcr", "__init__.py"),
|
||||||
description=("Automatically mock your HTTP interactions to simplify and " "speed up testing"),
|
description=("Automatically mock your HTTP interactions to simplify and " "speed up testing"),
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
author="Kevin McCarthy",
|
author="Kevin McCarthy",
|
||||||
author_email="me@kevinmccarthy.org",
|
author_email="me@kevinmccarthy.org",
|
||||||
url="https://github.com/kevin1024/vcrpy",
|
url="https://github.com/kevin1024/vcrpy",
|
||||||
packages=find_packages(exclude=excluded_packages),
|
packages=find_packages(exclude=["tests*"]),
|
||||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*",
|
python_requires=">=3.5",
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
license="MIT",
|
license="MIT",
|
||||||
tests_require=["pytest", "mock", "pytest-httpbin"],
|
tests_require=["pytest", "mock", "pytest-httpbin"],
|
||||||
@@ -54,12 +68,12 @@ setup(
|
|||||||
"Environment :: Console",
|
"Environment :: Console",
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"Programming Language :: Python",
|
"Programming Language :: Python",
|
||||||
"Programming Language :: Python :: 2",
|
|
||||||
"Programming Language :: Python :: 2.7",
|
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3.5",
|
"Programming Language :: Python :: 3.5",
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.6",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
"Programming Language :: Python :: Implementation :: PyPy",
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
"Topic :: Software Development :: Testing",
|
"Topic :: Software Development :: Testing",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# External imports
|
# External imports
|
||||||
import os
|
import os
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
# Internal imports
|
# Internal imports
|
||||||
import vcr
|
import vcr
|
||||||
|
|||||||
@@ -6,14 +6,9 @@ import boto # NOQA
|
|||||||
import boto.iam # NOQA
|
import boto.iam # NOQA
|
||||||
from boto.s3.connection import S3Connection # NOQA
|
from boto.s3.connection import S3Connection # NOQA
|
||||||
from boto.s3.key import Key # NOQA
|
from boto.s3.key import Key # NOQA
|
||||||
|
from configparser import DuplicateSectionError # NOQA
|
||||||
import vcr # NOQA
|
import vcr # NOQA
|
||||||
|
|
||||||
try: # NOQA
|
|
||||||
from ConfigParser import DuplicateSectionError # NOQA
|
|
||||||
except ImportError: # NOQA
|
|
||||||
# python3
|
|
||||||
from configparser import DuplicateSectionError # NOQA
|
|
||||||
|
|
||||||
|
|
||||||
def test_boto_stubs(tmpdir):
|
def test_boto_stubs(tmpdir):
|
||||||
with vcr.use_cassette(str(tmpdir.join("boto-stubs.yml"))):
|
with vcr.use_cassette(str(tmpdir.join("boto-stubs.yml"))):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
import pytest
|
import pytest
|
||||||
import vcr
|
import vcr
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
def test_set_serializer_default_config(tmpdir, httpbin):
|
def test_set_serializer_default_config(tmpdir, httpbin):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# External imports
|
# External imports
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
# Internal imports
|
# Internal imports
|
||||||
import vcr
|
import vcr
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import base64
|
import base64
|
||||||
import pytest
|
import pytest
|
||||||
from six.moves.urllib.request import urlopen, Request
|
from urllib.request import urlopen, Request
|
||||||
from six.moves.urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
from six.moves.urllib.error import HTTPError
|
from urllib.error import HTTPError
|
||||||
import vcr
|
import vcr
|
||||||
import json
|
import json
|
||||||
from assertions import assert_cassette_has_one_response, assert_is_json
|
from assertions import assert_cassette_has_one_response, assert_is_json
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from six.moves.urllib_parse import urlencode
|
from urllib.parse import urlencode
|
||||||
import pytest
|
import pytest
|
||||||
import pytest_httpbin.certs
|
import pytest_httpbin.certs
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ def test_post_data(tmpdir, httpbin_both):
|
|||||||
|
|
||||||
def test_post_unicode_data(tmpdir, httpbin_both):
|
def test_post_unicode_data(tmpdir, httpbin_both):
|
||||||
"""Ensure that it works when posting unicode data"""
|
"""Ensure that it works when posting unicode data"""
|
||||||
data = urlencode({"snowman": u"☃".encode("utf-8")})
|
data = urlencode({"snowman": "☃".encode()})
|
||||||
url = httpbin_both.url + "/post"
|
url = httpbin_both.url + "/post"
|
||||||
with vcr.use_cassette(str(tmpdir.join("post_data.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("post_data.yaml"))):
|
||||||
_, res1 = http().request(url, "POST", data)
|
_, res1 = http().request(url, "POST", data)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
import socket
|
import socket
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
import vcr
|
import vcr
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import vcr
|
import vcr
|
||||||
import pytest
|
import pytest
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_URI = "http://httpbin.org/get?p1=q1&p2=q2" # base uri for testing
|
DEFAULT_URI = "http://httpbin.org/get?p1=q1&p2=q2" # base uri for testing
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import vcr
|
import vcr
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
def test_making_extra_request_raises_exception(tmpdir, httpbin):
|
def test_making_extra_request_raises_exception(tmpdir, httpbin):
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from six.moves import socketserver, SimpleHTTPServer
|
import http.server
|
||||||
from six.moves.urllib.request import urlopen
|
import socketserver
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
# Internal imports
|
# Internal imports
|
||||||
import vcr
|
import vcr
|
||||||
@@ -15,7 +16,7 @@ import vcr
|
|||||||
requests = pytest.importorskip("requests")
|
requests = pytest.importorskip("requests")
|
||||||
|
|
||||||
|
|
||||||
class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
class Proxy(http.server.SimpleHTTPRequestHandler):
|
||||||
"""
|
"""
|
||||||
Simple proxy server.
|
Simple proxy server.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import vcr
|
import vcr
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
def test_once_record_mode(tmpdir, httpbin):
|
def test_once_record_mode(tmpdir, httpbin):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import vcr
|
import vcr
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
def true_matcher(r1, r2):
|
def true_matcher(r1, r2):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# External imports
|
# External imports
|
||||||
import os
|
import os
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
# Internal imports
|
# Internal imports
|
||||||
import vcr
|
import vcr
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
|
|
||||||
class MockSerializer(object):
|
class MockSerializer:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.serialize_count = 0
|
self.serialize_count = 0
|
||||||
self.deserialize_count = 0
|
self.deserialize_count = 0
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import vcr
|
import vcr
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
|
||||||
def test_recorded_request_uri_with_redirected_request(tmpdir, httpbin):
|
def test_recorded_request_uri_with_redirected_request(tmpdir, httpbin):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import vcr
|
import vcr
|
||||||
import zlib
|
import zlib
|
||||||
import json
|
import json
|
||||||
import six.moves.http_client as httplib
|
import http.client as httplib
|
||||||
|
|
||||||
from assertions import assert_is_json
|
from assertions import assert_is_json
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"""Integration tests with urllib2"""
|
"""Integration tests with urllib2"""
|
||||||
|
|
||||||
import ssl
|
import ssl
|
||||||
from six.moves.urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
from six.moves.urllib_parse import urlencode
|
from urllib.parse import urlencode
|
||||||
import pytest_httpbin.certs
|
import pytest_httpbin.certs
|
||||||
|
|
||||||
# Internal imports
|
# Internal imports
|
||||||
@@ -104,7 +104,7 @@ def test_post_data(httpbin_both, tmpdir):
|
|||||||
|
|
||||||
def test_post_unicode_data(httpbin_both, tmpdir):
|
def test_post_unicode_data(httpbin_both, tmpdir):
|
||||||
"""Ensure that it works when posting unicode data"""
|
"""Ensure that it works when posting unicode data"""
|
||||||
data = urlencode({"snowman": u"☃".encode("utf-8")}).encode("utf-8")
|
data = urlencode({"snowman": "☃".encode()}).encode("utf-8")
|
||||||
url = httpbin_both.url + "/post"
|
url = httpbin_both.url + "/post"
|
||||||
with vcr.use_cassette(str(tmpdir.join("post_data.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("post_data.yaml"))):
|
||||||
res1 = urlopen_with_cafile(url, data).read()
|
res1 = urlopen_with_cafile(url, data).read()
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
|
import http.client as httplib
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import pytest
|
import pytest
|
||||||
from six.moves import xmlrpc_client, xmlrpc_server
|
from xmlrpc.client import ServerProxy
|
||||||
|
from xmlrpc.server import SimpleXMLRPCServer
|
||||||
|
|
||||||
requests = pytest.importorskip("requests")
|
requests = pytest.importorskip("requests")
|
||||||
|
|
||||||
import vcr # NOQA
|
import vcr # NOQA
|
||||||
|
|
||||||
try:
|
|
||||||
import httplib
|
|
||||||
except ImportError:
|
|
||||||
import http.client as httplib
|
|
||||||
|
|
||||||
|
|
||||||
def test_domain_redirect():
|
def test_domain_redirect():
|
||||||
"""Ensure that redirects across domains are considered unique"""
|
"""Ensure that redirects across domains are considered unique"""
|
||||||
@@ -80,7 +77,7 @@ def test_amazon_doctype(tmpdir):
|
|||||||
|
|
||||||
|
|
||||||
def start_rpc_server(q):
|
def start_rpc_server(q):
|
||||||
httpd = xmlrpc_server.SimpleXMLRPCServer(("127.0.0.1", 0))
|
httpd = SimpleXMLRPCServer(("127.0.0.1", 0))
|
||||||
httpd.register_function(pow)
|
httpd.register_function(pow)
|
||||||
q.put("http://{}:{}".format(*httpd.server_address))
|
q.put("http://{}:{}".format(*httpd.server_address))
|
||||||
httpd.serve_forever()
|
httpd.serve_forever()
|
||||||
@@ -99,11 +96,11 @@ def rpc_server():
|
|||||||
|
|
||||||
def test_xmlrpclib(tmpdir, rpc_server):
|
def test_xmlrpclib(tmpdir, rpc_server):
|
||||||
with vcr.use_cassette(str(tmpdir.join("xmlrpcvideo.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("xmlrpcvideo.yaml"))):
|
||||||
roundup_server = xmlrpc_client.ServerProxy(rpc_server, allow_none=True)
|
roundup_server = ServerProxy(rpc_server, allow_none=True)
|
||||||
original_schema = roundup_server.pow(2, 4)
|
original_schema = roundup_server.pow(2, 4)
|
||||||
|
|
||||||
with vcr.use_cassette(str(tmpdir.join("xmlrpcvideo.yaml"))):
|
with vcr.use_cassette(str(tmpdir.join("xmlrpcvideo.yaml"))):
|
||||||
roundup_server = xmlrpc_client.ServerProxy(rpc_server, allow_none=True)
|
roundup_server = ServerProxy(rpc_server, allow_none=True)
|
||||||
second_schema = roundup_server.pow(2, 4)
|
second_schema = roundup_server.pow(2, 4)
|
||||||
|
|
||||||
assert original_schema == second_schema
|
assert original_schema == second_schema
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
import inspect
|
import inspect
|
||||||
|
import mock
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from six.moves import http_client as httplib
|
import http.client as httplib
|
||||||
import pytest
|
import pytest
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from vcr.compat import mock, contextlib
|
|
||||||
from vcr.cassette import Cassette
|
from vcr.cassette import Cassette
|
||||||
from vcr.errors import UnhandledHTTPRequestError
|
from vcr.errors import UnhandledHTTPRequestError
|
||||||
from vcr.patch import force_reset
|
from vcr.patch import force_reset
|
||||||
@@ -208,7 +209,7 @@ def test_nesting_context_managers_by_checking_references_of_http_connection():
|
|||||||
|
|
||||||
|
|
||||||
def test_custom_patchers():
|
def test_custom_patchers():
|
||||||
class Test(object):
|
class Test:
|
||||||
attribute = None
|
attribute = None
|
||||||
|
|
||||||
with Cassette.use(path="custom_patches", custom_patches=((Test, "attribute", VCRHTTPSConnection),)):
|
with Cassette.use(path="custom_patches", custom_patches=((Test, "attribute", VCRHTTPSConnection),)):
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from vcr.compat import mock
|
|
||||||
from vcr import errors
|
from vcr import errors
|
||||||
from vcr.cassette import Cassette
|
from vcr.cassette import Cassette
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from six import BytesIO
|
from io import BytesIO
|
||||||
from vcr.filters import (
|
from vcr.filters import (
|
||||||
remove_headers,
|
remove_headers,
|
||||||
replace_headers,
|
replace_headers,
|
||||||
@@ -8,10 +8,10 @@ from vcr.filters import (
|
|||||||
replace_post_data_parameters,
|
replace_post_data_parameters,
|
||||||
decode_response,
|
decode_response,
|
||||||
)
|
)
|
||||||
from vcr.compat import mock
|
|
||||||
from vcr.request import Request
|
from vcr.request import Request
|
||||||
import gzip
|
import gzip
|
||||||
import json
|
import json
|
||||||
|
import mock
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import itertools
|
import itertools
|
||||||
from vcr.compat import mock
|
import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
# coding: UTF-8
|
# coding: UTF-8
|
||||||
import io
|
import io
|
||||||
import unittest
|
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from vcr.stubs import VCRHTTPResponse
|
from vcr.stubs import VCRHTTPResponse
|
||||||
|
|
||||||
@@ -58,7 +55,6 @@ def test_response_headers_should_have_correct_values():
|
|||||||
assert response.headers.get("date") == "Fri, 24 Oct 2014 18:35:37 GMT"
|
assert response.headers.get("date") == "Fri, 24 Oct 2014 18:35:37 GMT"
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(six.PY2, "Regression test for Python3 only")
|
|
||||||
def test_response_parses_correctly_and_fp_attribute_error_is_not_thrown():
|
def test_response_parses_correctly_and_fp_attribute_error_is_not_thrown():
|
||||||
"""
|
"""
|
||||||
Regression test for https://github.com/kevin1024/vcrpy/issues/440
|
Regression test for https://github.com/kevin1024/vcrpy/issues/440
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from vcr.compat import mock
|
|
||||||
from vcr.request import Request
|
from vcr.request import Request
|
||||||
from vcr.serialize import deserialize, serialize
|
from vcr.serialize import deserialize, serialize
|
||||||
from vcr.serializers import yamlserializer, jsonserializer, compat
|
from vcr.serializers import yamlserializer, jsonserializer, compat
|
||||||
@@ -29,7 +30,7 @@ def test_deserialize_new_json_cassette():
|
|||||||
deserialize(f.read(), jsonserializer)
|
deserialize(f.read(), jsonserializer)
|
||||||
|
|
||||||
|
|
||||||
REQBODY_TEMPLATE = u"""\
|
REQBODY_TEMPLATE = """\
|
||||||
interactions:
|
interactions:
|
||||||
- request:
|
- request:
|
||||||
body: {req_body}
|
body: {req_body}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
import mock
|
||||||
|
|
||||||
from vcr.stubs import VCRHTTPSConnection
|
from vcr.stubs import VCRHTTPSConnection
|
||||||
from vcr.compat import mock
|
|
||||||
from vcr.cassette import Cassette
|
from vcr.cassette import Cassette
|
||||||
|
|
||||||
|
|
||||||
class TestVCRConnection(object):
|
class TestVCRConnection:
|
||||||
def test_setting_of_attributes_get_propogated_to_real_connection(self):
|
def test_setting_of_attributes_get_propogated_to_real_connection(self):
|
||||||
vcr_connection = VCRHTTPSConnection("www.examplehost.com")
|
vcr_connection = VCRHTTPSConnection("www.examplehost.com")
|
||||||
vcr_connection.ssl_version = "example_ssl_version"
|
vcr_connection.ssl_version = "example_ssl_version"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
import mock
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from six.moves import http_client as httplib
|
import http.client as httplib
|
||||||
|
|
||||||
from vcr import VCR, use_cassette
|
from vcr import VCR, use_cassette
|
||||||
from vcr.compat import mock
|
|
||||||
from vcr.request import Request
|
from vcr.request import Request
|
||||||
from vcr.stubs import VCRHTTPSConnection
|
from vcr.stubs import VCRHTTPSConnection
|
||||||
from vcr.patch import _HTTPConnection, force_reset
|
from vcr.patch import _HTTPConnection, force_reset
|
||||||
@@ -170,7 +170,7 @@ def test_fixtures_with_use_cassette(random_fixture):
|
|||||||
|
|
||||||
|
|
||||||
def test_custom_patchers():
|
def test_custom_patchers():
|
||||||
class Test(object):
|
class Test:
|
||||||
attribute = None
|
attribute = None
|
||||||
attribute2 = None
|
attribute2 = None
|
||||||
|
|
||||||
|
|||||||
35
tox.ini
35
tox.ini
@@ -3,8 +3,8 @@ skip_missing_interpreters=true
|
|||||||
envlist =
|
envlist =
|
||||||
cov-clean,
|
cov-clean,
|
||||||
lint,
|
lint,
|
||||||
{py27,py35,py36,py37,py38,pypy,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},
|
{py35,py36,py37,py38}-{requests,httplib2,urllib3,tornado4,boto3,aiohttp},
|
||||||
{py35,py36,py37,py38}-{aiohttp},
|
{pypy3}-{requests,httplib2,urllib3,tornado4,boto3},
|
||||||
cov-report
|
cov-report
|
||||||
|
|
||||||
|
|
||||||
@@ -34,6 +34,27 @@ deps =
|
|||||||
flake8
|
flake8
|
||||||
black
|
black
|
||||||
|
|
||||||
|
[testenv:docs]
|
||||||
|
# Running sphinx from inside the "docs" directory
|
||||||
|
# ensures it will not pick up any stray files that might
|
||||||
|
# get into a virtual environment under the top-level directory
|
||||||
|
# or other artifacts under build/
|
||||||
|
changedir = docs
|
||||||
|
# The only dependency is sphinx
|
||||||
|
# If we were using extensions packaged separately,
|
||||||
|
# we would specify them here.
|
||||||
|
# A better practice is to specify a specific version of sphinx.
|
||||||
|
deps =
|
||||||
|
sphinx
|
||||||
|
sphinx_rtd_theme
|
||||||
|
# This is the sphinx command to generate HTML.
|
||||||
|
# In other circumstances, we might want to generate a PDF or an ebook
|
||||||
|
commands =
|
||||||
|
sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
|
||||||
|
# We use Python 3.7. Tox sometimes tries to autodetect it based on the name of
|
||||||
|
# the testenv, but "docs" does not give useful clues so we have to be explicit.
|
||||||
|
basepython = python3.7
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
# Need to use develop install so that paths
|
# Need to use develop install so that paths
|
||||||
# for aggregate code coverage combine
|
# for aggregate code coverage combine
|
||||||
@@ -51,17 +72,17 @@ deps =
|
|||||||
requests: requests>=2.22.0
|
requests: requests>=2.22.0
|
||||||
httplib2: httplib2
|
httplib2: httplib2
|
||||||
urllib3: urllib3
|
urllib3: urllib3
|
||||||
{py27,py35,py36,pypy}-tornado4: tornado>=4,<5
|
{py35,py36}-tornado4: tornado>=4,<5
|
||||||
{py27,py35,py36,pypy}-tornado4: pytest-tornado
|
{py35,py36}-tornado4: pytest-tornado
|
||||||
{py27,py35,py36}-tornado4: pycurl
|
{py35,py36}-tornado4: pycurl
|
||||||
boto3: boto3
|
boto3: boto3
|
||||||
boto3: urllib3
|
boto3: urllib3
|
||||||
aiohttp: aiohttp
|
aiohttp: aiohttp
|
||||||
aiohttp: pytest-asyncio
|
aiohttp: pytest-asyncio
|
||||||
aiohttp: pytest-aiohttp
|
aiohttp: pytest-aiohttp
|
||||||
depends =
|
depends =
|
||||||
{py27,py35,py36,py37,pypy}-{lint,requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37}-{aiohttp}: cov-clean
|
lint,{py35,py36,py37,py38,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37,py38}-{aiohttp}: cov-clean
|
||||||
cov-report: {py27,py35,py36,py37,pypy}-{lint,requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37}-{aiohttp}
|
cov-report: lint,{py35,py36,py37,py38,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37,py38}-{aiohttp}
|
||||||
passenv =
|
passenv =
|
||||||
AWS_ACCESS_KEY_ID
|
AWS_ACCESS_KEY_ID
|
||||||
AWS_DEFAULT_REGION
|
AWS_DEFAULT_REGION
|
||||||
|
|||||||
BIN
vcr.png
BIN
vcr.png
Binary file not shown.
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 114 KiB |
@@ -1,23 +1,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import warnings
|
|
||||||
import sys
|
|
||||||
from .config import VCR
|
from .config import VCR
|
||||||
|
from logging import NullHandler
|
||||||
|
|
||||||
# Set default logging handler to avoid "No handler found" warnings.
|
__version__ = "4.0.0"
|
||||||
try: # Python 2.7+
|
|
||||||
from logging import NullHandler
|
|
||||||
except ImportError:
|
|
||||||
|
|
||||||
class NullHandler(logging.Handler):
|
|
||||||
def emit(self, record):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[0] == 2:
|
|
||||||
warnings.warn(
|
|
||||||
"Python 2.x support of vcrpy is deprecated and will be removed in an upcoming major release.",
|
|
||||||
DeprecationWarning,
|
|
||||||
)
|
|
||||||
|
|
||||||
logging.getLogger(__name__).addHandler(NullHandler())
|
logging.getLogger(__name__).addHandler(NullHandler())
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import collections
|
import collections
|
||||||
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
@@ -6,13 +7,13 @@ import logging
|
|||||||
|
|
||||||
import wrapt
|
import wrapt
|
||||||
|
|
||||||
from .compat import contextlib
|
|
||||||
from .errors import UnhandledHTTPRequestError
|
from .errors import UnhandledHTTPRequestError
|
||||||
from .matchers import requests_match, uri, method, get_matchers_results
|
from .matchers import requests_match, uri, method, get_matchers_results
|
||||||
from .patch import CassettePatcherBuilder
|
from .patch import CassettePatcherBuilder
|
||||||
from .serializers import yamlserializer
|
from .serializers import yamlserializer
|
||||||
from .persisters.filesystem import FilesystemPersister
|
from .persisters.filesystem import FilesystemPersister
|
||||||
from .util import partition_dict
|
from .util import partition_dict
|
||||||
|
from ._handle_coroutine import handle_coroutine
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from asyncio import iscoroutinefunction
|
from asyncio import iscoroutinefunction
|
||||||
@@ -22,18 +23,10 @@ except ImportError:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[:2] >= (3, 5):
|
|
||||||
from ._handle_coroutine import handle_coroutine
|
|
||||||
else:
|
|
||||||
|
|
||||||
def handle_coroutine(*args, **kwags):
|
|
||||||
raise NotImplementedError("Not implemented on Python 2")
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class CassetteContextDecorator(object):
|
class CassetteContextDecorator:
|
||||||
"""Context manager/decorator that handles installing the cassette and
|
"""Context manager/decorator that handles installing the cassette and
|
||||||
removing cassettes.
|
removing cassettes.
|
||||||
|
|
||||||
@@ -159,7 +152,7 @@ class CassetteContextDecorator(object):
|
|||||||
return new_args_getter
|
return new_args_getter
|
||||||
|
|
||||||
|
|
||||||
class Cassette(object):
|
class Cassette:
|
||||||
"""A container for recorded requests and responses"""
|
"""A container for recorded requests and responses"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
try:
|
|
||||||
from unittest import mock
|
|
||||||
except ImportError:
|
|
||||||
import mock
|
|
||||||
|
|
||||||
try:
|
|
||||||
import contextlib
|
|
||||||
except ImportError:
|
|
||||||
import contextlib2 as contextlib
|
|
||||||
else:
|
|
||||||
if not hasattr(contextlib, "ExitStack"):
|
|
||||||
import contextlib2 as contextlib
|
|
||||||
|
|
||||||
__all__ = ["mock", "contextlib"]
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
import copy
|
import copy
|
||||||
|
|
||||||
try:
|
from collections import abc as collections_abc
|
||||||
from collections import abc as collections_abc # only works on python 3.3+
|
|
||||||
except ImportError:
|
|
||||||
import collections as collections_abc
|
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
@@ -19,7 +16,7 @@ from . import matchers
|
|||||||
from . import filters
|
from . import filters
|
||||||
|
|
||||||
|
|
||||||
class VCR(object):
|
class VCR:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_test_method(method_name, function):
|
def is_test_method(method_name, function):
|
||||||
return method_name.startswith("test") and isinstance(function, types.FunctionType)
|
return method_name.startswith("test") and isinstance(function, types.FunctionType)
|
||||||
@@ -102,7 +99,7 @@ class VCR(object):
|
|||||||
return matchers
|
return matchers
|
||||||
|
|
||||||
def use_cassette(self, path=None, **kwargs):
|
def use_cassette(self, path=None, **kwargs):
|
||||||
if path is not None and not isinstance(path, six.string_types):
|
if path is not None and not isinstance(path, str):
|
||||||
function = path
|
function = path
|
||||||
# Assume this is an attempt to decorate a function
|
# Assume this is an attempt to decorate a function
|
||||||
return self._use_cassette(**kwargs)(function)
|
return self._use_cassette(**kwargs)(function)
|
||||||
@@ -251,4 +248,5 @@ class VCR(object):
|
|||||||
|
|
||||||
def test_case(self, predicate=None):
|
def test_case(self, predicate=None):
|
||||||
predicate = predicate or self.is_test_method
|
predicate = predicate or self.is_test_method
|
||||||
|
# TODO: Remove this reference to `six` in favor of the Python3 equivalent
|
||||||
return six.with_metaclass(auto_decorate(self.use_cassette, predicate))
|
return six.with_metaclass(auto_decorate(self.use_cassette, predicate))
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ class CannotOverwriteExistingCassetteException(Exception):
|
|||||||
self.cassette = kwargs["cassette"]
|
self.cassette = kwargs["cassette"]
|
||||||
self.failed_request = kwargs["failed_request"]
|
self.failed_request = kwargs["failed_request"]
|
||||||
message = self._get_message(kwargs["cassette"], kwargs["failed_request"])
|
message = self._get_message(kwargs["cassette"], kwargs["failed_request"])
|
||||||
super(CannotOverwriteExistingCassetteException, self).__init__(message)
|
super().__init__(message)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_message(cassette, failed_request):
|
def _get_message(cassette, failed_request):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from six import BytesIO, text_type
|
from io import BytesIO
|
||||||
from six.moves.urllib.parse import urlparse, urlencode, urlunparse
|
from urllib.parse import urlparse, urlencode, urlunparse
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import zlib
|
import zlib
|
||||||
@@ -8,13 +8,11 @@ from .util import CaseInsensitiveDict
|
|||||||
|
|
||||||
|
|
||||||
def replace_headers(request, replacements):
|
def replace_headers(request, replacements):
|
||||||
"""
|
"""Replace headers in request according to replacements.
|
||||||
Replace headers in request according to replacements. The replacements
|
The replacements should be a list of (key, value) pairs where the value can be any of:
|
||||||
should be a list of (key, value) pairs where the value can be any of:
|
|
||||||
1. A simple replacement string value.
|
1. A simple replacement string value.
|
||||||
2. None to remove the given header.
|
2. None to remove the given header.
|
||||||
3. A callable which accepts (key, value, request) and returns a string
|
3. A callable which accepts (key, value, request) and returns a string value or None.
|
||||||
value or None.
|
|
||||||
"""
|
"""
|
||||||
new_headers = request.headers.copy()
|
new_headers = request.headers.copy()
|
||||||
for k, rv in replacements:
|
for k, rv in replacements:
|
||||||
@@ -37,10 +35,9 @@ def remove_headers(request, headers_to_remove):
|
|||||||
|
|
||||||
|
|
||||||
def replace_query_parameters(request, replacements):
|
def replace_query_parameters(request, replacements):
|
||||||
"""
|
"""Replace query parameters in request according to replacements.
|
||||||
Replace query parameters in request according to replacements. The
|
|
||||||
replacements should be a list of (key, value) pairs where the value can be
|
The replacements should be a list of (key, value) pairs where the value can be any of:
|
||||||
any of:
|
|
||||||
1. A simple replacement string value.
|
1. A simple replacement string value.
|
||||||
2. None to remove the given header.
|
2. None to remove the given header.
|
||||||
3. A callable which accepts (key, value, request) and returns a string
|
3. A callable which accepts (key, value, request) and returns a string
|
||||||
@@ -73,10 +70,9 @@ def remove_query_parameters(request, query_parameters_to_remove):
|
|||||||
|
|
||||||
|
|
||||||
def replace_post_data_parameters(request, replacements):
|
def replace_post_data_parameters(request, replacements):
|
||||||
"""
|
"""Replace post data in request--either form data or json--according to replacements.
|
||||||
Replace post data in request--either form data or json--according to
|
|
||||||
replacements. The replacements should be a list of (key, value) pairs where
|
The replacements should be a list of (key, value) pairs where the value can be any of:
|
||||||
the value can be any of:
|
|
||||||
1. A simple replacement string value.
|
1. A simple replacement string value.
|
||||||
2. None to remove the given header.
|
2. None to remove the given header.
|
||||||
3. A callable which accepts (key, value, request) and returns a string
|
3. A callable which accepts (key, value, request) and returns a string
|
||||||
@@ -99,7 +95,7 @@ def replace_post_data_parameters(request, replacements):
|
|||||||
json_data[k] = rv
|
json_data[k] = rv
|
||||||
request.body = json.dumps(json_data).encode("utf-8")
|
request.body = json.dumps(json_data).encode("utf-8")
|
||||||
else:
|
else:
|
||||||
if isinstance(request.body, text_type):
|
if isinstance(request.body, str):
|
||||||
request.body = request.body.encode("utf-8")
|
request.body = request.body.encode("utf-8")
|
||||||
splits = [p.partition(b"=") for p in request.body.split(b"&")]
|
splits = [p.partition(b"=") for p in request.body.split(b"&")]
|
||||||
new_splits = []
|
new_splits = []
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
from six.moves import urllib, xmlrpc_client
|
import urllib
|
||||||
|
import xmlrpc.client
|
||||||
from .util import read_body
|
from .util import read_body
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ _checker_transformer_pairs = (
|
|||||||
lambda body: urllib.parse.parse_qs(body.decode("ascii")),
|
lambda body: urllib.parse.parse_qs(body.decode("ascii")),
|
||||||
),
|
),
|
||||||
(_header_checker("application/json"), _transform_json),
|
(_header_checker("application/json"), _transform_json),
|
||||||
(lambda request: _xml_header_checker(request) and _xmlrpc_header_checker(request), xmlrpc_client.loads),
|
(lambda request: _xml_header_checker(request) and _xmlrpc_header_checker(request), xmlrpc.client.loads),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
"""Utilities for patching in cassettes"""
|
"""Utilities for patching in cassettes"""
|
||||||
|
import contextlib
|
||||||
import functools
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
|
import mock
|
||||||
|
|
||||||
from .compat import contextlib, mock
|
|
||||||
from .stubs import VCRHTTPConnection, VCRHTTPSConnection
|
from .stubs import VCRHTTPConnection, VCRHTTPSConnection
|
||||||
from six.moves import http_client as httplib
|
import http.client as httplib
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ else:
|
|||||||
_AiohttpClientSessionRequest = aiohttp.client.ClientSession._request
|
_AiohttpClientSessionRequest = aiohttp.client.ClientSession._request
|
||||||
|
|
||||||
|
|
||||||
class CassettePatcherBuilder(object):
|
class CassettePatcherBuilder:
|
||||||
def _build_patchers_from_mock_triples_decorator(function):
|
def _build_patchers_from_mock_triples_decorator(function):
|
||||||
@functools.wraps(function)
|
@functools.wraps(function)
|
||||||
def wrapped(self, *args, **kwargs):
|
def wrapped(self, *args, **kwargs):
|
||||||
@@ -358,7 +359,7 @@ class CassettePatcherBuilder(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ConnectionRemover(object):
|
class ConnectionRemover:
|
||||||
def __init__(self, connection_class):
|
def __init__(self, connection_class):
|
||||||
self._connection_class = connection_class
|
self._connection_class = connection_class
|
||||||
self._connection_pool_to_connections = {}
|
self._connection_pool_to_connections = {}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import os
|
|||||||
from ..serialize import serialize, deserialize
|
from ..serialize import serialize, deserialize
|
||||||
|
|
||||||
|
|
||||||
class FilesystemPersister(object):
|
class FilesystemPersister:
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_cassette(cls, cassette_path, serializer):
|
def load_cassette(cls, cassette_path, serializer):
|
||||||
try:
|
try:
|
||||||
with open(cassette_path) as f:
|
with open(cassette_path) as f:
|
||||||
cassette_content = f.read()
|
cassette_content = f.read()
|
||||||
except IOError:
|
except OSError:
|
||||||
raise ValueError("Cassette not found.")
|
raise ValueError("Cassette not found.")
|
||||||
cassette = deserialize(cassette_content, serializer)
|
cassette = deserialize(cassette_content, serializer)
|
||||||
return cassette
|
return cassette
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import warnings
|
import warnings
|
||||||
from six import BytesIO, text_type
|
from io import BytesIO
|
||||||
from six.moves.urllib.parse import urlparse, parse_qsl
|
from urllib.parse import urlparse, parse_qsl
|
||||||
from .util import CaseInsensitiveDict
|
from .util import CaseInsensitiveDict
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Request(object):
|
class Request:
|
||||||
"""
|
"""
|
||||||
VCR's representation of a request.
|
VCR's representation of a request.
|
||||||
"""
|
"""
|
||||||
@@ -39,7 +39,7 @@ class Request(object):
|
|||||||
|
|
||||||
@body.setter
|
@body.setter
|
||||||
def body(self, value):
|
def body(self, value):
|
||||||
if isinstance(value, text_type):
|
if isinstance(value, str):
|
||||||
value = value.encode("utf-8")
|
value = value.encode("utf-8")
|
||||||
self._body = value
|
self._body = value
|
||||||
|
|
||||||
@@ -136,4 +136,4 @@ class HeadersDict(CaseInsensitiveDict):
|
|||||||
if old:
|
if old:
|
||||||
key = old[0]
|
key = old[0]
|
||||||
|
|
||||||
super(HeadersDict, self).__setitem__(key, value)
|
super().__setitem__(key, value)
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
import six
|
|
||||||
|
|
||||||
|
|
||||||
def convert_to_bytes(resp):
|
def convert_to_bytes(resp):
|
||||||
resp = convert_body_to_bytes(resp)
|
resp = convert_body_to_bytes(resp)
|
||||||
return resp
|
return resp
|
||||||
@@ -24,7 +21,7 @@ def convert_body_to_bytes(resp):
|
|||||||
http://pyyaml.org/wiki/PyYAMLDocumentation#Python3support
|
http://pyyaml.org/wiki/PyYAMLDocumentation#Python3support
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if resp["body"]["string"] is not None and not isinstance(resp["body"]["string"], six.binary_type):
|
if resp["body"]["string"] is not None and not isinstance(resp["body"]["string"], bytes):
|
||||||
resp["body"]["string"] = resp["body"]["string"].encode("utf-8")
|
resp["body"]["string"] = resp["body"]["string"].encode("utf-8")
|
||||||
except (KeyError, TypeError, UnicodeEncodeError):
|
except (KeyError, TypeError, UnicodeEncodeError):
|
||||||
# The thing we were converting either wasn't a dictionary or didn't
|
# The thing we were converting either wasn't a dictionary or didn't
|
||||||
@@ -44,7 +41,7 @@ def _convert_string_to_unicode(string):
|
|||||||
result = string
|
result = string
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if string is not None and not isinstance(string, six.text_type):
|
if string is not None and not isinstance(string, str):
|
||||||
result = string.decode("utf-8")
|
result = string.decode("utf-8")
|
||||||
except (TypeError, UnicodeDecodeError, AttributeError):
|
except (TypeError, UnicodeDecodeError, AttributeError):
|
||||||
# Sometimes the string actually is binary or StringIO object,
|
# Sometimes the string actually is binary or StringIO object,
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
"""Stubs for patching HTTP and HTTPS requests"""
|
"""Stubs for patching HTTP and HTTPS requests"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import six
|
from http.client import (
|
||||||
from six.moves.http_client import HTTPConnection, HTTPSConnection, HTTPResponse
|
HTTPConnection,
|
||||||
from six import BytesIO
|
HTTPSConnection,
|
||||||
|
HTTPResponse,
|
||||||
|
)
|
||||||
|
from io import BytesIO
|
||||||
from vcr.request import Request
|
from vcr.request import Request
|
||||||
from vcr.errors import CannotOverwriteExistingCassetteException
|
from vcr.errors import CannotOverwriteExistingCassetteException
|
||||||
from . import compat
|
from . import compat
|
||||||
@@ -11,7 +14,7 @@ from . import compat
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class VCRFakeSocket(object):
|
class VCRFakeSocket:
|
||||||
"""
|
"""
|
||||||
A socket that doesn't do anything!
|
A socket that doesn't do anything!
|
||||||
Used when playing back cassettes, when there
|
Used when playing back cassettes, when there
|
||||||
@@ -143,7 +146,7 @@ class VCRHTTPResponse(HTTPResponse):
|
|||||||
return self._content.readable()
|
return self._content.readable()
|
||||||
|
|
||||||
|
|
||||||
class VCRConnection(object):
|
class VCRConnection:
|
||||||
# A reference to the cassette that's currently being patched in
|
# A reference to the cassette that's currently being patched in
|
||||||
cassette = None
|
cassette = None
|
||||||
|
|
||||||
@@ -296,7 +299,6 @@ class VCRConnection(object):
|
|||||||
self.real_connection.sock = value
|
self.real_connection.sock = value
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if six.PY3:
|
|
||||||
kwargs.pop("strict", None) # apparently this is gone in py3
|
kwargs.pop("strict", None) # apparently this is gone in py3
|
||||||
|
|
||||||
# need to temporarily reset here because the real connection
|
# need to temporarily reset here because the real connection
|
||||||
@@ -328,7 +330,7 @@ class VCRConnection(object):
|
|||||||
# we're setting the real_connection itself for the first time
|
# we're setting the real_connection itself for the first time
|
||||||
pass
|
pass
|
||||||
|
|
||||||
super(VCRConnection, self).__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
"""
|
"""
|
||||||
@@ -340,7 +342,7 @@ class VCRConnection(object):
|
|||||||
# we're setting the real_connection itself for the first time
|
# we're setting the real_connection itself for the first time
|
||||||
return getattr(self.real_connection, name)
|
return getattr(self.real_connection, name)
|
||||||
|
|
||||||
return super(VCRConnection, self).__getattr__(name)
|
return super().__getattr__(name)
|
||||||
|
|
||||||
|
|
||||||
for k, v in HTTPConnection.__dict__.items():
|
for k, v in HTTPConnection.__dict__.items():
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
"""Stubs for aiohttp HTTP clients"""
|
"""Stubs for aiohttp HTTP clients"""
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
"""Stubs for boto3"""
|
"""Stubs for boto3"""
|
||||||
import six
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# boto using awsrequest
|
# boto using awsrequest
|
||||||
from botocore.awsrequest import AWSHTTPConnection as HTTPConnection
|
from botocore.awsrequest import AWSHTTPConnection as HTTPConnection
|
||||||
@@ -26,8 +24,7 @@ class VCRRequestsHTTPSConnection(VCRHTTPSConnection, VerifiedHTTPSConnection):
|
|||||||
_baseclass = VerifiedHTTPSConnection
|
_baseclass = VerifiedHTTPSConnection
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if six.PY3:
|
kwargs.pop("strict", None)
|
||||||
kwargs.pop("strict", None) # apparently this is gone in py3
|
|
||||||
|
|
||||||
# need to temporarily reset here because the real connection
|
# need to temporarily reset here because the real connection
|
||||||
# inherits from the thing that we are mocking out. Take out
|
# inherits from the thing that we are mocking out. Take out
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import six
|
from io import BytesIO
|
||||||
from six import BytesIO
|
import http.client
|
||||||
from six.moves.http_client import HTTPMessage
|
|
||||||
|
|
||||||
try:
|
|
||||||
import http.client
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -15,10 +9,7 @@ layer that tries to cope with this move.
|
|||||||
|
|
||||||
|
|
||||||
def get_header(message, name):
|
def get_header(message, name):
|
||||||
if six.PY3:
|
|
||||||
return message.getallmatchingheaders(name)
|
return message.getallmatchingheaders(name)
|
||||||
else:
|
|
||||||
return message.getheader(name)
|
|
||||||
|
|
||||||
|
|
||||||
def get_header_items(message):
|
def get_header_items(message):
|
||||||
@@ -29,16 +20,8 @@ def get_header_items(message):
|
|||||||
|
|
||||||
def get_headers(message):
|
def get_headers(message):
|
||||||
for key in set(message.keys()):
|
for key in set(message.keys()):
|
||||||
if six.PY3:
|
|
||||||
yield key, message.get_all(key)
|
yield key, message.get_all(key)
|
||||||
else:
|
|
||||||
yield key, message.getheaders(key)
|
|
||||||
|
|
||||||
|
|
||||||
def get_httpmessage(headers):
|
def get_httpmessage(headers):
|
||||||
if six.PY3:
|
|
||||||
return http.client.parse_headers(BytesIO(headers))
|
return http.client.parse_headers(BytesIO(headers))
|
||||||
msg = HTTPMessage(BytesIO(headers))
|
|
||||||
msg.fp.seek(0)
|
|
||||||
msg.readheaders()
|
|
||||||
return msg
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
"""Stubs for tornado HTTP clients"""
|
"""Stubs for tornado HTTP clients"""
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
from six import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from tornado import httputil
|
from tornado import httputil
|
||||||
from tornado.httpclient import HTTPResponse
|
from tornado.httpclient import HTTPResponse
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ def auto_decorate(decorator, predicate=lambda name, value: isinstance(value, typ
|
|||||||
|
|
||||||
class DecorateAll(type):
|
class DecorateAll(type):
|
||||||
def __setattr__(cls, attribute, value):
|
def __setattr__(cls, attribute, value):
|
||||||
return super(DecorateAll, cls).__setattr__(attribute, maybe_decorate(attribute, value))
|
return super().__setattr__(attribute, maybe_decorate(attribute, value))
|
||||||
|
|
||||||
def __new__(cls, name, bases, attributes_dict):
|
def __new__(cls, name, bases, attributes_dict):
|
||||||
new_attributes_dict = {
|
new_attributes_dict = {
|
||||||
attribute: maybe_decorate(attribute, value) for attribute, value in attributes_dict.items()
|
attribute: maybe_decorate(attribute, value) for attribute, value in attributes_dict.items()
|
||||||
}
|
}
|
||||||
return super(DecorateAll, cls).__new__(cls, name, bases, new_attributes_dict)
|
return super().__new__(cls, name, bases, new_attributes_dict)
|
||||||
|
|
||||||
return DecorateAll
|
return DecorateAll
|
||||||
|
|||||||
Reference in New Issue
Block a user