1
0
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:
Josh Peak
2019-12-20 11:45:07 +11:00
committed by GitHub
parent 41ca5750e7
commit 4a8e80ee3e
57 changed files with 501 additions and 453 deletions

View File

@@ -17,23 +17,11 @@ matrix:
# Only run lint on a single 3.x
- env: TOX_SUFFIX="lint"
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:
- "2.7"
- "3.5"
- "3.6"
- "3.7"
- "3.8-dev"
- "pypy"
- "3.8"
- "pypy3"
install:
- pip install tox-travis codecov

View File

@@ -1,10 +1,17 @@
#########
VCR.py 📼
#########
|PyPI| |Python versions| |Build Status| |CodeCov| |Gitter| |CodeStyleBlack|
VCR.py
======
----
.. 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
library <https://github.com/vcr/vcr>`__.
@@ -42,7 +49,7 @@ all HTTP interactions, which will update them to correspond to the new
API.
License
=======
-------
This library uses the MIT license. See `LICENSE.txt <LICENSE.txt>`__ for
more details

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
View 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

View File

@@ -130,11 +130,11 @@ Finally, register your method with VCR to use your new request matcher.
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``
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...
@@ -143,7 +143,7 @@ Once the persister class is defined, register with VCR like so...
import vcr
my_vcr = vcr.VCR()
class CustomerPersister(object):
class CustomerPersister:
# implement Persister methods...
my_vcr.register_persister(CustomPersister)

View File

@@ -7,204 +7,222 @@ 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.
- 4.0.0 (UNRELEASED)
- Remove Python2 support
- Add Python 3.8 TravisCI support
- UNRELEASED
- ...
- 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
- 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)
- 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)
- 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)
- 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)
- 2.1.1
- Format code with black (@neozenith)
- Use latest pypy3 in Travis (@hugovk)
- Improve documentation about custom matchers (@gward)
- Fix exception when body is empty (@keithprickett)
- Add `pytest-recording` to the documentation as an alternative Pytest plugin (@Stranger6667)
- Fix yarl and python3.5 version issue (@neozenith)
- Fix header matcher for boto3 - fixes #474 (@simahawk)
- 2.1.0 - Add a `rewind` method to reset a cassette (thanks @khamidou)
New error message with more details on why the cassette failed to play a request (thanks @arthurHamon2, @neozenith)
Handle connect tunnel URI (thanks @jeking3)
Add code coverage to the project (thanks @neozenith)
Drop support to python 3.4
Add deprecation warning on python 2.7, next major release will drop python 2.7 support
Fix build problems on requests tests (thanks to @dunossauro)
Fix matching on 'body' failing when Unicode symbols are present in them (thanks @valgur)
Fix bugs on aiohttp integration (thanks @graingert, @steinnes, @stj, @lamenezes, @lmazuel)
Fix Biopython incompatibility (thanks @rishab121)
Fix Boto3 integration (thanks @1oglop1, @arthurHamon2)
- 2.0.1 - Fix bug when using vcrpy with python 3.4
- 2.0.0 - Support python 3.7 (fix httplib2 and urllib2, thanks @felixonmars)
[#356] Fixes `before_record_response` so the original response isn't changed (thanks @kgraves)
Fix requests stub when using proxy (thanks @samuelfekete @daneoshiga)
(only for aiohttp stub) Drop support to python 3.4 asyncio.coroutine (aiohttp doesn't support python it anymore)
Fix aiohttp stub to work with aiohttp client (thanks @stj)
Fix aiohttp stub to accept content type passed
Improve docs (thanks @adamchainz)
- 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.
- 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)
- 1.11.1 Fix compatibility with newest requests and urllib3 releases
- 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.10.5 Added a fix to httplib2 (thanks @carlosds730), Fix an issue with
aiohttp (thanks @madninja), Add missing requirement yarl (thanks @lamenezes),
Remove duplicate mock triple (thanks @FooBarQuaxx)
- 1.10.4 Fix an issue with asyncio aiohttp (thanks @madninja)
- 1.10.3 Fix some issues with asyncio and params (thanks @anovikov1984 and
@lamenezes), Fix some issues with cassette serialize / deserialize and empty
response bodies (thanks @gRoussac and @dz0ny)
- 1.10.2 Fix 1.10.1 release - add aiohttp support back in
- 1.10.1 [bad release] Fix build for Fedora package + python2 (thanks @puiterwijk and @lamenezes)
- 1.10.0 Add support for aiohttp (thanks @lamenezes)
- 1.9.0 Add support for boto3 (thanks @desdm, @foorbarna). Fix deepcopy issue
for response headers when `decode_compressed_response` is enabled (thanks
@nickdirienzo)
- 1.8.0 Fix for Serialization errors with JSON adapter (thanks
@aliaksandrb). Avoid concatenating bytes with strings (thanks
@jaysonsantos). Exclude __pycache__ dirs & compiled files in sdist
(thanks @koobs). Fix Tornado support behavior for Tornado 3 (thanks
@abhinav). decode_compressed_response option and filter (thanks
@jayvdb).
- 1.7.4 [#217] Make use_cassette decorated functions actually return a
value (thanks @bcen). [#199] Fix path transfromation defaults.
Better headers dictionary management.
- 1.7.3 [#188] ``additional_matchers`` kwarg on ``use_cassette``.
[#191] Actually support passing multiple before_record_request
functions (thanks @agriffis).
- 1.7.2 [#186] Get effective_url in tornado (thanks @mvschaik), [#187]
Set request_time on Response object in tornado (thanks @abhinav).
- 1.7.1 [#183] Patch ``fetch_impl`` instead of the entire HTTPClient
class for Tornado (thanks @abhinav).
- 1.7.0 [#177] Properly support coroutine/generator decoration. [#178]
Support distribute (thanks @graingert). [#163] Make compatibility
between python2 and python3 recorded cassettes more robust (thanks
@gward).
- 1.6.1 [#169] Support conditional requirements in old versions of
pip, Fix RST parse errors generated by pandoc, [Tornado] Fix
unsupported features exception not being raised, [#166]
content-aware body matcher.
- 1.6.0 [#120] Tornado support (thanks @abhinav), [#147] packaging fixes
(thanks @graingert), [#158] allow filtering post params in requests
(thanks @MrJohz), [#140] add xmlrpclib support (thanks @Diaoul).
- 1.5.2 Fix crash when cassette path contains cassette library
directory (thanks @gazpachoking).
- 1.5.0 Automatic cassette naming and 'application/json' post data
filtering (thanks @marco-santamaria).
- 1.4.2 Fix a bug caused by requests 2.7 and chunked transfer encoding
- 1.4.1 Include README, tests, LICENSE in package. Thanks @ralphbean.
- 1.4.0 Filter post data parameters (thanks @eadmundo), 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.3.0 Fix/add support for urllib3 (thanks @aisch), fix default port
for https (thanks @abhinav).
- 1.2.0 Add custom\_patches argument to VCR/Cassette objects to allow
users to stub custom classes when cassettes become active.
- 1.1.4 Add force reset around calls to actual connection from stubs,
to ensure compatibility with the version of httplib/urlib2 in python
2.7.9.
- 1.1.3 Fix python3 headers field (thanks @rtaboada), fix boto test
(thanks @telaviv), fix new\_episodes record mode (thanks @jashugan),
fix Windows connectionpool stub bug (thanks @gazpachoking), add
support for requests 2.5
- 1.1.2 Add urllib==1.7.1 support. Make json serialize error handling
correct Improve logging of match failures.
- 1.1.1 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. Move all request
filtering into the ``before_record_callable``.
- 1.1.0 Add ``before_record_response``. Fix several bugs related to the
context management of cassettes.
- 1.0.3: Fix an issue with requests 2.4 and make sure case sensitivity
is consistent across python versions
- 1.0.2: Fix an issue with requests 2.3
- 1.0.1: Fix a bug with the new ignore requests feature and the once
record mode
- 1.0.0: *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. Add support for filtering
sensitive data from requests, matching query strings after the order
changes and improving the built-in matchers, (thanks to @mshytikov),
support for ignoring requests to certain hosts, bump supported
Python3 version to 3.4, fix some bugs with Boto support (thanks
@marusich), fix error with URL field capitalization in README (thanks
@simon-weber), added some log messages to help with debugging, added
``all_played`` property on cassette (thanks @mshytikov)
- 0.7.0: VCR.py now supports Python 3! (thanks @asundg) Also I
refactored the stub connections quite a bit to add support for the
putrequest and putheader calls. This version also adds support for
httplib2 (thanks @nilp0inter). I have added a couple tests for boto
since it is an http client in its own right. Finally, this version
includes a fix for a bug where requests wasn't being patched properly
(thanks @msabramo).
- 0.6.0: Store response headers as a list since a HTTP response can
have the same header twice (happens with set-cookie sometimes). This
has the added benefit of preserving the order of headers. Thanks
@smallcode for the bug report leading to this change. 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.
Also this release adds better error messages (thanks @msabramo) and
adds support for using VCR as a decorator (thanks @smallcode for the
motivation)
- 0.5.0: Change the ``response_of`` method to ``responses_of`` since
cassettes can now contain more than one response for a request. Since
this changes the API, I'm bumping the version. Also includes 2
bugfixes: a better error message when attempting to overwrite a
cassette file, and a fix for a bug with requests sessions (thanks
@msabramo)
- 0.4.0: Change default request recording behavior for multiple
requests. 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. Then, when you are
replaying the cassette, the responses will be played back in the same
order in which they were received. 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. Also, removes support
for the cassette.play\_count counter API, since individual requests
aren't unique anymore. A cassette might contain the same request
several times. Also removes secure overwrite feature since that was
breaking overwriting files in Windows, and fixes a bug preventing
request's automatic body decompression from working.
- 0.3.5: Fix compatibility with requests 2.x
- 0.3.4: Bugfix: close file before renaming it. This fixes an issue on
Windows. Thanks @smallcode for the fix.
- 0.3.3: Bugfix for error message when an unreigstered custom matcher
was used
- 0.3.2: Fix issue with new config syntax and the ``match_on``
parameter. Thanks, @chromy!
- 0.3.1: Fix issue causing full paths to be sent on the HTTP request
line.
- 0.3.0: *Backwards incompatible release* - 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.
Added support for custom request matching, and changed the default
request matching behavior to match only on the URL and method. Also,
improved the httplib mocking to add support for the
``HTTPConnection.send()`` method. 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. 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. Thanks to @fatuhoku
for some of the ideas and the motivation behind this release.
- 0.2.1: Fixed missing modules in setup.py
- 0.2.0: Added configuration API, which lets you configure some
settings on VCR (see the README). Also, VCR no longer saves cassettes
if they haven't changed at all and supports JSON as well as YAML
(thanks @sirpengi). Added amazing new skeumorphic logo, thanks
@hairarrow.
- 0.1.0: *backwards incompatible release - delete your old cassette
files*: 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
- Format code with black (@neozenith)
- Use latest pypy3 in Travis (@hugovk)
- Improve documentation about custom matchers (@gward)
- Fix exception when body is empty (@keithprickett)
- Add `pytest-recording` to the documentation as an alternative Pytest plugin (@Stranger6667)
- Fix yarl and python3.5 version issue (@neozenith)
- Fix header matcher for boto3 - fixes #474 (@simahawk)
- 2.1.0
- Add a `rewind` method to reset a cassette (thanks @khamidou)
- New error message with more details on why the cassette failed to play a request (thanks @arthurHamon2, @neozenith)
- Handle connect tunnel URI (thanks @jeking3)
- Add code coverage to the project (thanks @neozenith)
- Drop support to python 3.4
- Add deprecation warning on python 2.7, next major release will drop python 2.7 support
- Fix build problems on requests tests (thanks to @dunossauro)
- Fix matching on 'body' failing when Unicode symbols are present in them (thanks @valgur)
- Fix bugs on aiohttp integration (thanks @graingert, @steinnes, @stj, @lamenezes, @lmazuel)
- Fix Biopython incompatibility (thanks @rishab121)
- Fix Boto3 integration (thanks @1oglop1, @arthurHamon2)
- 2.0.1
- Fix bug when using vcrpy with python 3.4
- 2.0.0
- Support python 3.7 (fix httplib2 and urllib2, thanks @felixonmars)
- [#356] Fixes `before_record_response` so the original response isn't changed (thanks @kgraves)
- Fix requests stub when using proxy (thanks @samuelfekete @daneoshiga)
- (only for aiohttp stub) Drop support to python 3.4 asyncio.coroutine (aiohttp doesn't support python it anymore)
- Fix aiohttp stub to work with aiohttp client (thanks @stj)
- Fix aiohttp stub to accept content type passed
- Improve docs (thanks @adamchainz)
- 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.
- 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)
- 1.11.1
- Fix compatibility with newest requests and urllib3 releases
- 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.10.5
- Added a fix to httplib2 (thanks @carlosds730), Fix an issue with
- aiohttp (thanks @madninja), Add missing requirement yarl (thanks @lamenezes),
- Remove duplicate mock triple (thanks @FooBarQuaxx)
- 1.10.4
- Fix an issue with asyncio aiohttp (thanks @madninja)
- 1.10.3
- Fix some issues with asyncio and params (thanks @anovikov1984 and @lamenezes)
- Fix some issues with cassette serialize / deserialize and empty response bodies (thanks @gRoussac and @dz0ny)
- 1.10.2
- Fix 1.10.1 release - add aiohttp support back in
- 1.10.1
- [bad release] Fix build for Fedora package + python2 (thanks @puiterwijk and @lamenezes)
- 1.10.0
- Add support for aiohttp (thanks @lamenezes)
- 1.9.0
- Add support for boto3 (thanks @desdm, @foorbarna).
- Fix deepcopy issue for response headers when `decode_compressed_response` is enabled (thanks @nickdirienzo)
- 1.8.0
- Fix for Serialization errors with JSON adapter (thanks @aliaksandrb).
- Avoid concatenating bytes with strings (thanks @jaysonsantos).
- Exclude __pycache__ dirs & compiled files in sdist (thanks @koobs).
- Fix Tornado support behavior for Tornado 3 (thanks @abhinav).
- decode_compressed_response option and filter (thanks @jayvdb).
- 1.7.4 [#217]
- Make use_cassette decorated functions actually return a value (thanks @bcen).
- [#199] Fix path transfromation defaults.
- Better headers dictionary management.
- 1.7.3 [#188]
- ``additional_matchers`` kwarg on ``use_cassette``.
- [#191] Actually support passing multiple before_record_request functions (thanks @agriffis).
- 1.7.2
- [#186] Get effective_url in tornado (thanks @mvschaik)
- [#187] Set request_time on Response object in tornado (thanks @abhinav).
- 1.7.1
- [#183] Patch ``fetch_impl`` instead of the entire HTTPClient class for Tornado (thanks @abhinav).
- 1.7.0
- [#177] Properly support coroutine/generator decoration.
- [#178] Support distribute (thanks @graingert). [#163] Make compatibility between python2 and python3 recorded cassettes more robust (thanks @gward).
- 1.6.1
- [#169] Support conditional requirements in old versions of pip
- Fix RST parse errors generated by pandoc
- [Tornado] Fix unsupported features exception not being raised
- [#166] content-aware body matcher.
- 1.6.0
- [#120] Tornado support (thanks @abhinav)
- [#147] packaging fixes (thanks @graingert)
- [#158] allow filtering post params in requests (thanks @MrJohz)
- [#140] add xmlrpclib support (thanks @Diaoul).
- 1.5.2
- Fix crash when cassette path contains cassette library directory (thanks @gazpachoking).
- 1.5.0
- Automatic cassette naming and 'application/json' post data filtering (thanks @marco-santamaria).
- 1.4.2
- Fix a bug caused by requests 2.7 and chunked transfer encoding
- 1.4.1
- Include README, tests, LICENSE in package. Thanks @ralphbean.
- 1.4.0
- Filter post data parameters (thanks @eadmundo)
- 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.3.0
- Fix/add support for urllib3 (thanks @aisch)
- Fix default port for https (thanks @abhinav).
- 1.2.0
- Add custom\_patches argument to VCR/Cassette objects to allow users to stub custom classes when cassettes become active.
- 1.1.4
- Add force reset around calls to actual connection from stubs, to ensure compatibility with the version of httplib/urlib2 in python 2.7.9.
- 1.1.3
- Fix python3 headers field (thanks @rtaboada)
- fix boto test (thanks @telaviv)
- fix new\_episodes record mode (thanks @jashugan),
- fix Windows connectionpool stub bug (thanks @gazpachoking)
- add support for requests 2.5
- 1.1.2
- Add urllib==1.7.1 support.
- Make json serialize error handling correct
- Improve logging of match failures.
- 1.1.1
- 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.
- Move all request filtering into the ``before_record_callable``.
- 1.1.0
- Add ``before_record_response``. Fix several bugs related to the context management of cassettes.
- 1.0.3
- Fix an issue with requests 2.4 and make sure case sensitivity is consistent across python versions
- 1.0.2
- Fix an issue with requests 2.3
- 1.0.1
- Fix a bug with the new ignore requests feature and the once record mode
- 1.0.0
- *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.
- Add support for filtering sensitive data from requests, matching query strings after the order changes and improving the built-in matchers, (thanks to @mshytikov)
- Support for ignoring requests to certain hosts, bump supported Python3 version to 3.4, fix some bugs with Boto support (thanks @marusich)
- Fix error with URL field capitalization in README (thanks @simon-weber)
- Added some log messages to help with debugging
- Added ``all_played`` property on cassette (thanks @mshytikov)
- 0.7.0
- VCR.py now supports Python 3! (thanks @asundg)
- Also I refactored the stub connections quite a bit to add support for the putrequest and putheader calls.
- This version also adds support for httplib2 (thanks @nilp0inter).
- I have added a couple tests for boto since it is an http client in its own right.
- Finally, this version includes a fix for a bug where requests wasn't being patched properly (thanks @msabramo).
- 0.6.0
- Store response headers as a list since a HTTP response can have the same header twice (happens with set-cookie sometimes).
- This has the added benefit of preserving the order of headers.
- Thanks @smallcode for the bug report leading to this change.
- 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.
- Also this release adds better error messages (thanks @msabramo)
- and adds support for using VCR as a decorator (thanks @smallcode for the motivation)
- 0.5.0
- Change the ``response_of`` method to ``responses_of`` since cassettes can now contain more than one response for a request.
- Since this changes the API, I'm bumping the version.
- Also includes 2 bugfixes:
- a better error message when attempting to overwrite a cassette file,
- and a fix for a bug with requests sessions (thanks @msabramo)
- 0.4.0
- Change default request recording behavior for multiple requests.
- 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.
- Then, when you are replaying the cassette, the responses will be played back in the same order in which they were received.
- 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.
- Also, removes support for the cassette.play\_count counter API, since individual requests aren't unique anymore.
- A cassette might contain the same request several times.
- Also removes secure overwrite feature since that was breaking overwriting files in Windows
- And fixes a bug preventing request's automatic body decompression from working.
- 0.3.5
- Fix compatibility with requests 2.x
- 0.3.4
- Bugfix: close file before renaming it. This fixes an issue on Windows. Thanks @smallcode for the fix.
- 0.3.3
- Bugfix for error message when an unreigstered custom matcher was used
- 0.3.2
- Fix issue with new config syntax and the ``match_on`` parameter. Thanks, @chromy!
- 0.3.1
- Fix issue causing full paths to be sent on the HTTP request line.
- 0.3.0
- *Backwards incompatible release*
- 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.
- Added support for custom request matching, and changed the default request matching behavior to match only on the URL and method.
- Also, improved the httplib mocking to add support for the ``HTTPConnection.send()`` method.
- 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.
- 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).
- Thanks to @fatuhoku for some of the ideas and the motivation behind this release.
- 0.2.1
- Fixed missing modules in setup.py
- 0.2.0
- Added configuration API, which lets you configure some settings on VCR (see the README).
- Also, VCR no longer saves cassettes if they haven't changed at all and supports JSON as well as YAML (thanks @sirpengi).
- Added amazing new skeumorphic logo, thanks @hairarrow.
- 0.1.0
- *backwards incompatible release - delete your old cassette files*
- 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

View File

@@ -12,8 +12,33 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import codecs
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,
# 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.
@@ -27,7 +52,14 @@ import os
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx.ext.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.
templates_path = ["_templates"]
@@ -44,18 +76,18 @@ source_suffix = ".rst"
master_doc = "index"
# General information about the project.
project = u"vcrpy"
copyright = u"2015, Kevin McCarthy"
author = u"Kevin McCarthy"
project = "vcrpy"
copyright = "2015, Kevin McCarthy"
author = "Kevin McCarthy"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = "1.7.4"
# version = "1.7.4"
# 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
# for a list of supported languages.
@@ -106,11 +138,11 @@ todo_include_todos = False
# 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
if "READTHEDOCS" not in os.environ:
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# if "READTHEDOCS" not in os.environ:
# import sphinx_rtd_theme
#
# html_theme = "sphinx_rtd_theme"
# html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# 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
@@ -153,6 +185,8 @@ html_static_path = ["_static"]
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
html_sidebars = {"**": ["globaltoc.html", "relations.html", "sourcelink.html", "searchbox.html"]}
# Additional templates that should be rendered to pages, maps page names to
# template names.
@@ -205,19 +239,21 @@ htmlhelp_basename = "vcrpydoc"
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# 'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [(master_doc, "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 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
# (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.
# man_show_urls = False
@@ -259,12 +295,12 @@ texinfo_documents = [
(
master_doc,
"vcrpy",
u"vcrpy Documentation",
"vcrpy Documentation",
author,
"vcrpy",
"One line description of project.",
"Miscellaneous",
)
),
]
# 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.
intersphinx_mapping = {"https://docs.python.org/": None}
html_theme = "alabaster"

View File

@@ -1,6 +1,10 @@
Contributing
============
.. image:: _static/vcr.svg
:alt: vcr.py logo
:align: right
🚀 Milestones
--------------
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
CI <https://travis-ci.org/kevin1024/vcrpy>`__, but you can also run them
yourself using `py.test <http://pytest.org/>`__ and
`Tox <http://tox.testrun.org/>`__. Tox will automatically run them in
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::
yourself using `pytest <http://pytest.org/>`__ and
`Tox <http://tox.testrun.org/>`__.
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 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
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.
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.
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/>`
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/>`_
in this example::
git clone https://github.com/pyenv/pyenv ~/.pyenv
@@ -122,10 +130,10 @@ in this example::
pip install tox tox-pyenv
# 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
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
tox

View File

@@ -44,7 +44,7 @@ It can return multiple similar requests with :
CannotOverwriteExistingCassetteException message example :
.. code:: python
.. code::
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.

View File

@@ -4,7 +4,7 @@ Contents
========
.. toctree::
:maxdepth: 2
:maxdepth: 3
installation
usage
@@ -15,6 +15,7 @@ Contents
contributing
changelog
==================
Indices and tables
==================

View File

@@ -9,8 +9,7 @@ with pip::
Compatibility
-------------
VCR.py supports Python 2.7 and 3.5+, and
`pypy <http://pypy.org>`__.
VCR.py supports Python 3.5+, and `pypy <http://pypy.org>`__.
The following HTTP libraries are supported:

View File

@@ -1,11 +1,31 @@
#!/usr/bin/env python
import codecs
import os
import re
import sys
from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand
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):
@@ -26,26 +46,20 @@ install_requires = [
"PyYAML",
"wrapt",
"six>=1.5",
'contextlib2; python_version=="2.7"',
'mock; python_version=="2.7"',
'yarl; python_version>="3.6"',
'yarl<1.4; python_version=="3.5"',
]
excluded_packages = ["tests*"]
if sys.version_info[0] == 2:
excluded_packages.append("vcr.stubs.aiohttp_stubs")
setup(
name="vcrpy",
version="3.0.0",
version=find_version("vcr", "__init__.py"),
description=("Automatically mock your HTTP interactions to simplify and " "speed up testing"),
long_description=long_description,
author="Kevin McCarthy",
author_email="me@kevinmccarthy.org",
url="https://github.com/kevin1024/vcrpy",
packages=find_packages(exclude=excluded_packages),
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*",
packages=find_packages(exclude=["tests*"]),
python_requires=">=3.5",
install_requires=install_requires,
license="MIT",
tests_require=["pytest", "mock", "pytest-httpbin"],
@@ -54,12 +68,12 @@ setup(
"Environment :: Console",
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Testing",

View File

@@ -3,7 +3,7 @@
# External imports
import os
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
# Internal imports
import vcr

View File

@@ -6,14 +6,9 @@ import boto # NOQA
import boto.iam # NOQA
from boto.s3.connection import S3Connection # NOQA
from boto.s3.key import Key # NOQA
from configparser import DuplicateSectionError # 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):
with vcr.use_cassette(str(tmpdir.join("boto-stubs.yml"))):

View File

@@ -2,7 +2,7 @@ import os
import json
import pytest
import vcr
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
def test_set_serializer_default_config(tmpdir, httpbin):

View File

@@ -4,7 +4,7 @@
# External imports
import os
import time
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
# Internal imports
import vcr

View File

@@ -1,8 +1,8 @@
import base64
import pytest
from six.moves.urllib.request import urlopen, Request
from six.moves.urllib.parse import urlencode
from six.moves.urllib.error import HTTPError
from urllib.request import urlopen, Request
from urllib.parse import urlencode
from urllib.error import HTTPError
import vcr
import json
from assertions import assert_cassette_has_one_response, assert_is_json

View File

@@ -3,7 +3,7 @@
import sys
from six.moves.urllib_parse import urlencode
from urllib.parse import urlencode
import pytest
import pytest_httpbin.certs
@@ -111,7 +111,7 @@ def test_post_data(tmpdir, httpbin_both):
def test_post_unicode_data(tmpdir, httpbin_both):
"""Ensure that it works when posting unicode data"""
data = urlencode({"snowman": u"".encode("utf-8")})
data = urlencode({"snowman": "".encode()})
url = httpbin_both.url + "/post"
with vcr.use_cassette(str(tmpdir.join("post_data.yaml"))):
_, res1 = http().request(url, "POST", data)

View File

@@ -1,4 +1,4 @@
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
import socket
from contextlib import contextmanager
import vcr

View File

@@ -1,6 +1,6 @@
import vcr
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

View File

@@ -1,6 +1,6 @@
import pytest
import vcr
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
def test_making_extra_request_raises_exception(tmpdir, httpbin):

View File

@@ -5,8 +5,9 @@
import multiprocessing
import pytest
from six.moves import socketserver, SimpleHTTPServer
from six.moves.urllib.request import urlopen
import http.server
import socketserver
from urllib.request import urlopen
# Internal imports
import vcr
@@ -15,7 +16,7 @@ import vcr
requests = pytest.importorskip("requests")
class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler):
class Proxy(http.server.SimpleHTTPRequestHandler):
"""
Simple proxy server.

View File

@@ -1,6 +1,6 @@
import pytest
import vcr
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
def test_once_record_mode(tmpdir, httpbin):

View File

@@ -1,5 +1,5 @@
import vcr
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
def true_matcher(r1, r2):

View File

@@ -3,7 +3,7 @@
# External imports
import os
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
# Internal imports
import vcr

View File

@@ -1,7 +1,7 @@
import vcr
class MockSerializer(object):
class MockSerializer:
def __init__(self):
self.serialize_count = 0
self.deserialize_count = 0

View File

@@ -1,5 +1,5 @@
import vcr
from six.moves.urllib.request import urlopen
from urllib.request import urlopen
def test_recorded_request_uri_with_redirected_request(tmpdir, httpbin):

View File

@@ -1,7 +1,7 @@
import vcr
import zlib
import json
import six.moves.http_client as httplib
import http.client as httplib
from assertions import assert_is_json

View File

@@ -2,8 +2,8 @@
"""Integration tests with urllib2"""
import ssl
from six.moves.urllib.request import urlopen
from six.moves.urllib_parse import urlencode
from urllib.request import urlopen
from urllib.parse import urlencode
import pytest_httpbin.certs
# Internal imports
@@ -104,7 +104,7 @@ def test_post_data(httpbin_both, tmpdir):
def test_post_unicode_data(httpbin_both, tmpdir):
"""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"
with vcr.use_cassette(str(tmpdir.join("post_data.yaml"))):
res1 = urlopen_with_cafile(url, data).read()

View File

@@ -1,16 +1,13 @@
import http.client as httplib
import multiprocessing
import pytest
from six.moves import xmlrpc_client, xmlrpc_server
from xmlrpc.client import ServerProxy
from xmlrpc.server import SimpleXMLRPCServer
requests = pytest.importorskip("requests")
import vcr # NOQA
try:
import httplib
except ImportError:
import http.client as httplib
def test_domain_redirect():
"""Ensure that redirects across domains are considered unique"""
@@ -80,7 +77,7 @@ def test_amazon_doctype(tmpdir):
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)
q.put("http://{}:{}".format(*httpd.server_address))
httpd.serve_forever()
@@ -99,11 +96,11 @@ def rpc_server():
def test_xmlrpclib(tmpdir, rpc_server):
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)
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)
assert original_schema == second_schema

View File

@@ -1,12 +1,13 @@
import contextlib
import copy
import inspect
import mock
import os
from six.moves import http_client as httplib
import http.client as httplib
import pytest
import yaml
from vcr.compat import mock, contextlib
from vcr.cassette import Cassette
from vcr.errors import UnhandledHTTPRequestError
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():
class Test(object):
class Test:
attribute = None
with Cassette.use(path="custom_patches", custom_patches=((Test, "attribute", VCRHTTPSConnection),)):

View File

@@ -1,6 +1,7 @@
import mock
import pytest
from vcr.compat import mock
from vcr import errors
from vcr.cassette import Cassette

View File

@@ -1,4 +1,4 @@
from six import BytesIO
from io import BytesIO
from vcr.filters import (
remove_headers,
replace_headers,
@@ -8,10 +8,10 @@ from vcr.filters import (
replace_post_data_parameters,
decode_response,
)
from vcr.compat import mock
from vcr.request import Request
import gzip
import json
import mock
import zlib

View File

@@ -1,5 +1,5 @@
import itertools
from vcr.compat import mock
import mock
import pytest

View File

@@ -1,8 +1,5 @@
# coding: UTF-8
import io
import unittest
import six
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"
@unittest.skipIf(six.PY2, "Regression test for Python3 only")
def test_response_parses_correctly_and_fp_attribute_error_is_not_thrown():
"""
Regression test for https://github.com/kevin1024/vcrpy/issues/440

View File

@@ -1,7 +1,8 @@
# -*- encoding: utf-8 -*-
import mock
import pytest
from vcr.compat import mock
from vcr.request import Request
from vcr.serialize import deserialize, serialize
from vcr.serializers import yamlserializer, jsonserializer, compat
@@ -29,7 +30,7 @@ def test_deserialize_new_json_cassette():
deserialize(f.read(), jsonserializer)
REQBODY_TEMPLATE = u"""\
REQBODY_TEMPLATE = """\
interactions:
- request:
body: {req_body}

View File

@@ -1,9 +1,10 @@
import mock
from vcr.stubs import VCRHTTPSConnection
from vcr.compat import mock
from vcr.cassette import Cassette
class TestVCRConnection(object):
class TestVCRConnection:
def test_setting_of_attributes_get_propogated_to_real_connection(self):
vcr_connection = VCRHTTPSConnection("www.examplehost.com")
vcr_connection.ssl_version = "example_ssl_version"

View File

@@ -1,10 +1,10 @@
import mock
import os
import pytest
from six.moves import http_client as httplib
import http.client as httplib
from vcr import VCR, use_cassette
from vcr.compat import mock
from vcr.request import Request
from vcr.stubs import VCRHTTPSConnection
from vcr.patch import _HTTPConnection, force_reset
@@ -170,7 +170,7 @@ def test_fixtures_with_use_cassette(random_fixture):
def test_custom_patchers():
class Test(object):
class Test:
attribute = None
attribute2 = None

35
tox.ini
View File

@@ -3,8 +3,8 @@ skip_missing_interpreters=true
envlist =
cov-clean,
lint,
{py27,py35,py36,py37,py38,pypy,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},
{py35,py36,py37,py38}-{aiohttp},
{py35,py36,py37,py38}-{requests,httplib2,urllib3,tornado4,boto3,aiohttp},
{pypy3}-{requests,httplib2,urllib3,tornado4,boto3},
cov-report
@@ -34,6 +34,27 @@ deps =
flake8
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]
# Need to use develop install so that paths
# for aggregate code coverage combine
@@ -51,17 +72,17 @@ deps =
requests: requests>=2.22.0
httplib2: httplib2
urllib3: urllib3
{py27,py35,py36,pypy}-tornado4: tornado>=4,<5
{py27,py35,py36,pypy}-tornado4: pytest-tornado
{py27,py35,py36}-tornado4: pycurl
{py35,py36}-tornado4: tornado>=4,<5
{py35,py36}-tornado4: pytest-tornado
{py35,py36}-tornado4: pycurl
boto3: boto3
boto3: urllib3
aiohttp: aiohttp
aiohttp: pytest-asyncio
aiohttp: pytest-aiohttp
depends =
{py27,py35,py36,py37,pypy}-{lint,requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37}-{aiohttp}: cov-clean
cov-report: {py27,py35,py36,py37,pypy}-{lint,requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37}-{aiohttp}
lint,{py35,py36,py37,py38,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37,py38}-{aiohttp}: cov-clean
cov-report: lint,{py35,py36,py37,py38,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py35,py36,py37,py38}-{aiohttp}
passenv =
AWS_ACCESS_KEY_ID
AWS_DEFAULT_REGION

BIN
vcr.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

@@ -1,23 +1,8 @@
import logging
import warnings
import sys
from .config import VCR
from logging import NullHandler
# Set default logging handler to avoid "No handler found" warnings.
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,
)
__version__ = "4.0.0"
logging.getLogger(__name__).addHandler(NullHandler())

View File

@@ -1,4 +1,5 @@
import collections
import contextlib
import copy
import sys
import inspect
@@ -6,13 +7,13 @@ import logging
import wrapt
from .compat import contextlib
from .errors import UnhandledHTTPRequestError
from .matchers import requests_match, uri, method, get_matchers_results
from .patch import CassettePatcherBuilder
from .serializers import yamlserializer
from .persisters.filesystem import FilesystemPersister
from .util import partition_dict
from ._handle_coroutine import handle_coroutine
try:
from asyncio import iscoroutinefunction
@@ -22,18 +23,10 @@ except ImportError:
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__)
class CassetteContextDecorator(object):
class CassetteContextDecorator:
"""Context manager/decorator that handles installing the cassette and
removing cassettes.
@@ -159,7 +152,7 @@ class CassetteContextDecorator(object):
return new_args_getter
class Cassette(object):
class Cassette:
"""A container for recorded requests and responses"""
@classmethod

View File

@@ -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"]

View File

@@ -1,9 +1,6 @@
import copy
try:
from collections import abc as collections_abc # only works on python 3.3+
except ImportError:
import collections as collections_abc
from collections import abc as collections_abc
import functools
import inspect
import os
@@ -19,7 +16,7 @@ from . import matchers
from . import filters
class VCR(object):
class VCR:
@staticmethod
def is_test_method(method_name, function):
return method_name.startswith("test") and isinstance(function, types.FunctionType)
@@ -102,7 +99,7 @@ class VCR(object):
return matchers
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
# Assume this is an attempt to decorate a function
return self._use_cassette(**kwargs)(function)
@@ -251,4 +248,5 @@ class VCR(object):
def test_case(self, predicate=None):
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))

View File

@@ -3,7 +3,7 @@ class CannotOverwriteExistingCassetteException(Exception):
self.cassette = kwargs["cassette"]
self.failed_request = kwargs["failed_request"]
message = self._get_message(kwargs["cassette"], kwargs["failed_request"])
super(CannotOverwriteExistingCassetteException, self).__init__(message)
super().__init__(message)
@staticmethod
def _get_message(cassette, failed_request):

View File

@@ -1,5 +1,5 @@
from six import BytesIO, text_type
from six.moves.urllib.parse import urlparse, urlencode, urlunparse
from io import BytesIO
from urllib.parse import urlparse, urlencode, urlunparse
import copy
import json
import zlib
@@ -8,13 +8,11 @@ from .util import CaseInsensitiveDict
def replace_headers(request, replacements):
"""
Replace headers in request according to replacements. The replacements
should be a list of (key, value) pairs where the value can be any of:
1. A simple replacement string value.
2. None to remove the given header.
3. A callable which accepts (key, value, request) and returns a string
value or None.
"""Replace headers in request according to replacements.
The replacements should be a list of (key, value) pairs where the value can be any of:
1. A simple replacement string value.
2. None to remove the given header.
3. A callable which accepts (key, value, request) and returns a string value or None.
"""
new_headers = request.headers.copy()
for k, rv in replacements:
@@ -37,10 +35,9 @@ def remove_headers(request, headers_to_remove):
def replace_query_parameters(request, replacements):
"""
Replace query parameters in request according to replacements. The
replacements should be a list of (key, value) pairs where the value can be
any of:
"""Replace query parameters in request according to replacements.
The replacements should be a list of (key, value) pairs where the value can be any of:
1. A simple replacement string value.
2. None to remove the given header.
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):
"""
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 value can be any of:
"""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 value can be any of:
1. A simple replacement string value.
2. None to remove the given header.
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
request.body = json.dumps(json_data).encode("utf-8")
else:
if isinstance(request.body, text_type):
if isinstance(request.body, str):
request.body = request.body.encode("utf-8")
splits = [p.partition(b"=") for p in request.body.split(b"&")]
new_splits = []

View File

@@ -1,5 +1,6 @@
import json
from six.moves import urllib, xmlrpc_client
import urllib
import xmlrpc.client
from .util import read_body
import logging
@@ -77,7 +78,7 @@ _checker_transformer_pairs = (
lambda body: urllib.parse.parse_qs(body.decode("ascii")),
),
(_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),
)

View File

@@ -1,10 +1,11 @@
"""Utilities for patching in cassettes"""
import contextlib
import functools
import itertools
import mock
from .compat import contextlib, mock
from .stubs import VCRHTTPConnection, VCRHTTPSConnection
from six.moves import http_client as httplib
import http.client as httplib
import logging
@@ -93,7 +94,7 @@ else:
_AiohttpClientSessionRequest = aiohttp.client.ClientSession._request
class CassettePatcherBuilder(object):
class CassettePatcherBuilder:
def _build_patchers_from_mock_triples_decorator(function):
@functools.wraps(function)
def wrapped(self, *args, **kwargs):
@@ -358,7 +359,7 @@ class CassettePatcherBuilder(object):
)
class ConnectionRemover(object):
class ConnectionRemover:
def __init__(self, connection_class):
self._connection_class = connection_class
self._connection_pool_to_connections = {}

View File

@@ -4,13 +4,13 @@ import os
from ..serialize import serialize, deserialize
class FilesystemPersister(object):
class FilesystemPersister:
@classmethod
def load_cassette(cls, cassette_path, serializer):
try:
with open(cassette_path) as f:
cassette_content = f.read()
except IOError:
except OSError:
raise ValueError("Cassette not found.")
cassette = deserialize(cassette_content, serializer)
return cassette

View File

@@ -1,13 +1,13 @@
import warnings
from six import BytesIO, text_type
from six.moves.urllib.parse import urlparse, parse_qsl
from io import BytesIO
from urllib.parse import urlparse, parse_qsl
from .util import CaseInsensitiveDict
import logging
log = logging.getLogger(__name__)
class Request(object):
class Request:
"""
VCR's representation of a request.
"""
@@ -39,7 +39,7 @@ class Request(object):
@body.setter
def body(self, value):
if isinstance(value, text_type):
if isinstance(value, str):
value = value.encode("utf-8")
self._body = value
@@ -136,4 +136,4 @@ class HeadersDict(CaseInsensitiveDict):
if old:
key = old[0]
super(HeadersDict, self).__setitem__(key, value)
super().__setitem__(key, value)

View File

@@ -1,6 +1,3 @@
import six
def convert_to_bytes(resp):
resp = convert_body_to_bytes(resp)
return resp
@@ -24,7 +21,7 @@ def convert_body_to_bytes(resp):
http://pyyaml.org/wiki/PyYAMLDocumentation#Python3support
"""
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")
except (KeyError, TypeError, UnicodeEncodeError):
# 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
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")
except (TypeError, UnicodeDecodeError, AttributeError):
# Sometimes the string actually is binary or StringIO object,

View File

@@ -1,9 +1,12 @@
"""Stubs for patching HTTP and HTTPS requests"""
import logging
import six
from six.moves.http_client import HTTPConnection, HTTPSConnection, HTTPResponse
from six import BytesIO
from http.client import (
HTTPConnection,
HTTPSConnection,
HTTPResponse,
)
from io import BytesIO
from vcr.request import Request
from vcr.errors import CannotOverwriteExistingCassetteException
from . import compat
@@ -11,7 +14,7 @@ from . import compat
log = logging.getLogger(__name__)
class VCRFakeSocket(object):
class VCRFakeSocket:
"""
A socket that doesn't do anything!
Used when playing back cassettes, when there
@@ -143,7 +146,7 @@ class VCRHTTPResponse(HTTPResponse):
return self._content.readable()
class VCRConnection(object):
class VCRConnection:
# A reference to the cassette that's currently being patched in
cassette = None
@@ -296,8 +299,7 @@ class VCRConnection(object):
self.real_connection.sock = value
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
# inherits from the thing that we are mocking out. Take out
@@ -328,7 +330,7 @@ class VCRConnection(object):
# we're setting the real_connection itself for the first time
pass
super(VCRConnection, self).__setattr__(name, value)
super().__setattr__(name, value)
def __getattr__(self, name):
"""
@@ -340,7 +342,7 @@ class VCRConnection(object):
# we're setting the real_connection itself for the first time
return getattr(self.real_connection, name)
return super(VCRConnection, self).__getattr__(name)
return super().__getattr__(name)
for k, v in HTTPConnection.__dict__.items():

View File

@@ -1,6 +1,4 @@
"""Stubs for aiohttp HTTP clients"""
from __future__ import absolute_import
import asyncio
import functools
import logging

View File

@@ -1,6 +1,4 @@
"""Stubs for boto3"""
import six
try:
# boto using awsrequest
from botocore.awsrequest import AWSHTTPConnection as HTTPConnection
@@ -26,8 +24,7 @@ class VCRRequestsHTTPSConnection(VCRHTTPSConnection, VerifiedHTTPSConnection):
_baseclass = VerifiedHTTPSConnection
def __init__(self, *args, **kwargs):
if six.PY3:
kwargs.pop("strict", None) # apparently this is gone in py3
kwargs.pop("strict", None)
# need to temporarily reset here because the real connection
# inherits from the thing that we are mocking out. Take out

View File

@@ -1,11 +1,5 @@
import six
from six import BytesIO
from six.moves.http_client import HTTPMessage
try:
import http.client
except ImportError:
pass
from io import BytesIO
import http.client
"""
@@ -15,10 +9,7 @@ layer that tries to cope with this move.
def get_header(message, name):
if six.PY3:
return message.getallmatchingheaders(name)
else:
return message.getheader(name)
return message.getallmatchingheaders(name)
def get_header_items(message):
@@ -29,16 +20,8 @@ def get_header_items(message):
def get_headers(message):
for key in set(message.keys()):
if six.PY3:
yield key, message.get_all(key)
else:
yield key, message.getheaders(key)
yield key, message.get_all(key)
def get_httpmessage(headers):
if six.PY3:
return http.client.parse_headers(BytesIO(headers))
msg = HTTPMessage(BytesIO(headers))
msg.fp.seek(0)
msg.readheaders()
return msg
return http.client.parse_headers(BytesIO(headers))

View File

@@ -1,8 +1,6 @@
"""Stubs for tornado HTTP clients"""
from __future__ import absolute_import
import functools
from six import BytesIO
from io import BytesIO
from tornado import httputil
from tornado.httpclient import HTTPResponse

View File

@@ -107,12 +107,12 @@ def auto_decorate(decorator, predicate=lambda name, value: isinstance(value, typ
class DecorateAll(type):
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):
new_attributes_dict = {
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