mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-09 01:03:24 +00:00
12
README.rst
12
README.rst
@@ -1,14 +1,16 @@
|
||||
|Build Status| |Stories in Ready| |Gitter|
|
||||
|
||||
VCR.py
|
||||
======
|
||||
|
||||
.. image:: vcr.png
|
||||
.. figure:: https://raw.github.com/kevin1024/vcrpy/master/vcr.png
|
||||
:alt: vcr.py
|
||||
|
||||
vcr.py
|
||||
|
||||
This is a Python version of `Ruby's VCR
|
||||
library <https://github.com/vcr/vcr>`__.
|
||||
|
||||
|Build Status| |Stories in Ready| |Gitter Chat|
|
||||
|
||||
What it does
|
||||
------------
|
||||
|
||||
@@ -607,7 +609,7 @@ new API in version 1.0.x
|
||||
|
||||
Changelog
|
||||
---------
|
||||
- 1.7.3 [#188] ``additional_matchers`` kwarg on ``use_cassette``.
|
||||
- 1.7.3 [#188] ``additional_matchers`` kwarg on ``use_casstte``.
|
||||
[#191] Actually support passing multiple before_record_request
|
||||
functions (thanks @agriffis).
|
||||
- 1.7.2 [#186] Get effective_url in tornado (thanks @mvschaik), [#187]
|
||||
@@ -756,6 +758,6 @@ more details
|
||||
:target: http://travis-ci.org/kevin1024/vcrpy
|
||||
.. |Stories in Ready| image:: https://badge.waffle.io/kevin1024/vcrpy.png?label=ready&title=Ready
|
||||
:target: https://waffle.io/kevin1024/vcrpy
|
||||
.. |Gitter Chat| image:: https://badges.gitter.im/Join%20Chat.svg
|
||||
.. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg
|
||||
:alt: Join the chat at https://gitter.im/kevin1024/vcrpy
|
||||
:target: https://gitter.im/kevin1024/vcrpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from six.moves 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
|
||||
|
||||
|
||||
def test_vcr_use_cassette():
|
||||
@@ -243,6 +245,7 @@ def test_path_transformer():
|
||||
|
||||
def test_cassette_name_generator_defaults_to_using_module_function_defined_in():
|
||||
vcr = VCR(inject_cassette=True)
|
||||
|
||||
@vcr.use_cassette
|
||||
def function_name(cassette):
|
||||
assert cassette._path == os.path.join(os.path.dirname(__file__),
|
||||
@@ -274,3 +277,29 @@ def test_additional_matchers():
|
||||
|
||||
function_defaults()
|
||||
function_additional()
|
||||
|
||||
|
||||
class TestVCRClass(VCR().test_case()):
|
||||
|
||||
def no_decoration(self):
|
||||
assert httplib.HTTPConnection == _HTTPConnection
|
||||
self.test_dynamically_added()
|
||||
assert httplib.HTTPConnection == _HTTPConnection
|
||||
|
||||
def test_one(self):
|
||||
with force_reset():
|
||||
self.no_decoration()
|
||||
with force_reset():
|
||||
self.test_two()
|
||||
assert httplib.HTTPConnection != _HTTPConnection
|
||||
|
||||
def test_two(self):
|
||||
assert httplib.HTTPConnection != _HTTPConnection
|
||||
|
||||
|
||||
def test_dynamically_added(self):
|
||||
assert httplib.HTTPConnection != _HTTPConnection
|
||||
|
||||
|
||||
TestVCRClass.test_dynamically_added = test_dynamically_added
|
||||
del test_dynamically_added
|
||||
|
||||
@@ -2,19 +2,25 @@ import copy
|
||||
import functools
|
||||
import inspect
|
||||
import os
|
||||
import types
|
||||
|
||||
import six
|
||||
|
||||
from .compat import collections
|
||||
from .cassette import Cassette
|
||||
from .serializers import yamlserializer, jsonserializer
|
||||
from .util import compose
|
||||
from .util import compose, auto_decorate
|
||||
from . import matchers
|
||||
from . import filters
|
||||
|
||||
|
||||
class VCR(object):
|
||||
|
||||
@staticmethod
|
||||
def is_test_method(method_name, function):
|
||||
return method_name.startswith('test') and \
|
||||
isinstance(function, types.FunctionType)
|
||||
|
||||
@staticmethod
|
||||
def ensure_suffix(suffix):
|
||||
def ensure(path):
|
||||
@@ -202,7 +208,7 @@ class VCR(object):
|
||||
if filter_query_parameters:
|
||||
filter_functions.append(functools.partial(
|
||||
filters.remove_query_parameters,
|
||||
query_parameters_to_remove=filter_query_parameters
|
||||
query_parameters_to_remove=filter_query_parameters
|
||||
))
|
||||
if filter_post_data_parameters:
|
||||
filter_functions.append(
|
||||
@@ -250,3 +256,7 @@ class VCR(object):
|
||||
|
||||
def register_matcher(self, name, matcher):
|
||||
self.matchers[name] = matcher
|
||||
|
||||
def test_case(self, predicate=None):
|
||||
predicate = predicate or self.is_test_method
|
||||
return six.with_metaclass(auto_decorate(self.use_cassette, predicate))
|
||||
|
||||
29
vcr/util.py
29
vcr/util.py
@@ -1,4 +1,6 @@
|
||||
import collections
|
||||
import types
|
||||
|
||||
|
||||
# Shamelessly stolen from https://github.com/kennethreitz/requests/blob/master/requests/structures.py
|
||||
class CaseInsensitiveDict(collections.MutableMapping):
|
||||
@@ -90,3 +92,30 @@ def read_body(request):
|
||||
if hasattr(request.body, 'read'):
|
||||
return request.body.read()
|
||||
return request.body
|
||||
|
||||
|
||||
def auto_decorate(
|
||||
decorator,
|
||||
predicate=lambda name, value: isinstance(value, types.FunctionType)
|
||||
):
|
||||
def maybe_decorate(attribute, value):
|
||||
if predicate(attribute, value):
|
||||
value = decorator(value)
|
||||
return value
|
||||
|
||||
class DecorateAll(type):
|
||||
|
||||
def __setattr__(cls, attribute, value):
|
||||
return super(DecorateAll, cls).__setattr__(
|
||||
attribute, maybe_decorate(attribute, value)
|
||||
)
|
||||
|
||||
def __new__(cls, name, bases, attributes_dict):
|
||||
new_attributes_dict = 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 DecorateAll
|
||||
|
||||
Reference in New Issue
Block a user