### Install and Run VCR's Test Suite with Pyenv Source: https://vcrpy.readthedocs.io/en/latest/_sources/contributing.rst.txt This example demonstrates setting up Pyenv to manage Python versions and then running the VCR test suite. Ensure you have an AWS key if running boto3 tests. ```bash git clone https://github.com/pyenv/pyenv ~/.pyenv # Add ~/.pyenv/bin to your PATH export PATH="$PATH:~/.pyenv/bin" # Setup shim paths eval "$(pyenv init -)" # Install supported versions (at time of writing), this does not activate them pyenv install 3.12.0 pypy3.10 # This activates them pyenv local 3.12.0 pypy3.10 # Run the whole test suite pip install .[tests] ./runtests.sh ``` -------------------------------- ### Install VCR.py with pip Source: https://vcrpy.readthedocs.io/en/latest/_sources/installation.rst.txt Use this command to install the latest version of VCR.py from PyPI. ```bash pip3 install vcrpy ``` -------------------------------- ### Install libyaml on Ubuntu Source: https://vcrpy.readthedocs.io/en/latest/installation.html Install the libyaml development library on Ubuntu. This is a prerequisite for pyyaml to use libyaml extensions. ```bash apt-get install libyaml-dev # Ubuntu ``` -------------------------------- ### Install libyaml development headers Source: https://vcrpy.readthedocs.io/en/latest/_sources/installation.rst.txt Install the libyaml development libraries required for pyyaml to use its C extensions. Commands vary by operating system. ```bash brew install libyaml # Mac with Homebrew apt-get install libyaml-dev # Ubuntu dnf install libyaml-devel # Fedora ``` -------------------------------- ### Install libyaml on Fedora Source: https://vcrpy.readthedocs.io/en/latest/installation.html Install the libyaml development library on Fedora. This is a prerequisite for pyyaml to use libyaml extensions. ```bash dnf install libyaml-devel # Fedora ``` -------------------------------- ### Install libyaml on macOS Source: https://vcrpy.readthedocs.io/en/latest/installation.html Install the libyaml development library on macOS using Homebrew. This is a prerequisite for pyyaml to use libyaml extensions. ```bash brew install libyaml # Mac with Homebrew ``` -------------------------------- ### Install VCR.py using pip Source: https://vcrpy.readthedocs.io/en/latest/installation.html Install the VCR.py package using pip3. This is the standard method for adding VCR.py to your Python environment. ```bash pip3 install vcrpy ``` -------------------------------- ### CassetteContextDecorator Initialization Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Initializes the CassetteContextDecorator with a cassette class and an arguments getter function. This class acts as a context manager or decorator to handle cassette installation and removal. ```python class CassetteContextDecorator: _non_cassette_arguments = ( "path_transformer", "func_path_generator", "record_on_exception", ) @classmethod def from_args(cls, cassette_class, **kwargs): return cls(cassette_class, lambda: dict(kwargs)) def __init__(self, cls, args_getter): self.cls = cls self._args_getter = args_getter self.__finish = None self.__cassette = None ``` -------------------------------- ### VCR.py CannotOverwriteExistingCassetteException Example Source: https://vcrpy.readthedocs.io/en/latest/_sources/debugging.rst.txt This exception message shows which matchers succeeded and failed when a request couldn't be found in a cassette, helping to debug custom matchers. ```text CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('cassette.yaml') in your current record mode ('once'). No match for the request () was found. Found 1 similar requests with 1 different matchers : 1 - (). Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path'] Matchers failed : query - assertion failure : [('alt', 'json'), ('maxResults', '200')] != [('alt', 'json'), ('maxResults', '500')] ``` -------------------------------- ### Python Configuration Error Example Source: https://vcrpy.readthedocs.io/en/latest/_sources/contributing.rst.txt This snippet shows a common `ConfigurationError` that might occur when running tests on MacOSX if Curl is configured with SSL. ```python __main__.ConfigurationError: Curl is configured to use SSL, but we have ``` -------------------------------- ### Importing and Storing Original aiohttp Client Session Request Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html This code attempts to import the `aiohttp.client` module and stores the original `ClientSession._request` method if successful. This is part of VCRpy's setup to handle aiohttp requests. ```python try: import aiohttp.client except ImportError: # pragma: no cover pass else: _AiohttpClientSessionRequest = aiohttp.client.ClientSession._request ``` -------------------------------- ### Check requests Library Version Compatibility Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html Checks if the installed 'requests' library version is compatible with VCR.py, raising an error if it's too old. ```python try: import requests except ImportError: pass else: if requests.__build__ < 0x021602: raise RuntimeError( "vcrpy >=4.2.2 and requests <2.16.2 are not compatible" "; please upgrade requests (or downgrade vcrpy)", ) ``` -------------------------------- ### Get Matcher Results for Two Requests Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/matchers.html Compares two requests using a list of matchers. It aggregates successful and failed matches, including assertion details for failures. ```python def get_matchers_results(r1, r2, matchers): """ Get the comparison results of two requests as two list. The first returned list represents the matchers names that passed. The second list is the failed matchers as a string with failed assertion details if any. """ matches_success, matches_fails = [], [] for m in matchers: matcher_name = m.__name__ match, assertion_message = _evaluate_matcher(m, r1, r2) if match: matches_success.append(matcher_name) else: assertion_message = get_assertion_message(assertion_message) matches_fails.append((matcher_name, assertion_message)) return matches_success, matches_fails ``` -------------------------------- ### Instantiate VCR with Custom Configuration Source: https://vcrpy.readthedocs.io/en/latest/configuration.html Create a VCR instance with specific settings for serializer, cassette library directory, record mode, and request matching criteria. ```python import vcr my_vcr = vcr.VCR( serializer='json', cassette_library_dir='fixtures/cassettes', record_mode='once', match_on=['uri', 'method'], ) with my_vcr.use_cassette('test.json'): # your http code here ``` -------------------------------- ### VCR Initialization Configuration Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/config.html Demonstrates the various parameters available when initializing a VCR object to customize its behavior, such as path transformers, request/response filters, record modes, and serializers. ```python import copy import functools import inspect import os import types from collections import abc as collections_abc from pathlib import Path from . import filters, matchers from .cassette import Cassette from .persisters.filesystem import FilesystemPersister from .record_mode import RecordMode from .serializers import jsonserializer, yamlserializer from .util import auto_decorate, compose class VCR: @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): if not path.endswith(suffix): return path + suffix return path return ensure def __init__( self, path_transformer=None, before_record_request=None, custom_patches=(), filter_query_parameters=(), ignore_hosts=(), record_mode=RecordMode.ONCE, ignore_localhost=False, filter_headers=(), before_record_response=None, filter_post_data_parameters=(), match_on=("method", "scheme", "host", "port", "path", "query"), before_record=None, inject_cassette=False, serializer="yaml", cassette_library_dir=None, func_path_generator=None, decode_compressed_response=False, record_on_exception=True, drop_unused_requests=False, ): self.serializer = serializer self.match_on = match_on self.cassette_library_dir = cassette_library_dir self.serializers = {"yaml": yamlserializer, "json": jsonserializer} self.matchers = { "method": matchers.method, "uri": matchers.uri, "url": matchers.uri, # matcher for backwards compatibility "scheme": matchers.scheme, "host": matchers.host, "port": matchers.port, "path": matchers.path, "query": matchers.query, "headers": matchers.headers, "raw_body": matchers.raw_body, "body": matchers.body, } self.persister = FilesystemPersister self.record_mode = record_mode self.filter_headers = filter_headers self.filter_query_parameters = filter_query_parameters self.filter_post_data_parameters = filter_post_data_parameters self.before_record_request = before_record_request or before_record self.before_record_response = before_record_response self.ignore_hosts = ignore_hosts self.ignore_localhost = ignore_localhost self.inject_cassette = inject_cassette self.path_transformer = path_transformer self.func_path_generator = func_path_generator self.decode_compressed_response = decode_compressed_response self.record_on_exception = record_on_exception self._custom_patches = tuple(custom_patches) self.drop_unused_requests = drop_unused_requests def _get_serializer(self, serializer_name): try: serializer = self.serializers[serializer_name] except KeyError: raise KeyError(f"Serializer {serializer_name} doesn't exist or isn't registered") from None return serializer def _get_matchers(self, matcher_names): matchers = [] try: for m in matcher_names: matchers.append(self.matchers[m]) except KeyError: raise KeyError(f"Matcher {m} doesn't exist or isn't registered") from None return matchers def use_cassette(self, path=None, **kwargs): if path is not None and not isinstance(path, (str, Path)): function = path # Assume this is an attempt to decorate a function return self._use_cassette(**kwargs)(function) return self._use_cassette(path=path, **kwargs) def _use_cassette(self, with_current_defaults=False, **kwargs): if with_current_defaults: config = self.get_merged_config(**kwargs) return Cassette.use(**config) # This is made a function that evaluates every time a cassette # is made so that changes that are made to this VCR instance # that occur AFTER the `use_cassette` decorator is applied # still affect subsequent calls to the decorated function. args_getter = functools.partial(self.get_merged_config, **kwargs) return Cassette.use_arg_getter(args_getter) def get_merged_config(self, **kwargs): serializer_name = kwargs.get("serializer", self.serializer) matcher_names = kwargs.get("match_on", self.match_on) path_transformer = kwargs.get("path_transformer", self.path_transformer) func_path_generator = kwargs.get("func_path_generator", self.func_path_generator) ``` -------------------------------- ### Cassette Context Decorator Source: https://vcrpy.readthedocs.io/en/latest/api.html CassetteContextDecorator is a helper class for managing cassette installation and removal as a context manager or decorator. ```APIDOC ## `vcr.cassette.CassetteContextDecorator` Class ### Description Context manager/decorator that handles installing and removing cassettes. ### Methods - `__init__(_cls_, _args_getter_)`: Initializes the decorator. - `_classmethod _from_args(_cassette_class_, **kwargs)`: Creates a decorator instance from arguments. - `_static _get_function_name(_function_)`: Gets the name of a function. ``` -------------------------------- ### vcr.config.VCR Methods Source: https://vcrpy.readthedocs.io/en/latest/genindex.html Methods for configuring and managing the VCR instance. ```APIDOC ## VCR Methods ### `ensure_suffix()` (static method) * **Description**: Ensures a string has a specific suffix. * **Usage**: Utility method for string manipulation. ### `get_merged_config()` * **Description**: Retrieves the merged configuration for VCR. * **Usage**: Access the combined configuration settings. ### `is_test_method()` (static method) * **Description**: Checks if a given method is a test method. * **Usage**: Identify test methods within the codebase. ### `register_matcher()` * **Description**: Registers a custom request matcher. * **Usage**: Extend vcrpy's matching capabilities with custom logic. ### `register_persister()` * **Description**: Registers a custom cassette persister. * **Usage**: Implement custom storage mechanisms for cassettes. ### `register_serializer()` * **Description**: Registers a custom cassette serializer. * **Usage**: Define custom formats for serializing cassette data. ### `test_case()` * **Description**: Decorator or context manager for running tests with VCR. * **Usage**: Apply to test functions or methods to automatically manage cassettes. ### `use_cassette()` * **Description**: Context manager for using a specific cassette. * **Usage**: Wrap code blocks that should use a particular cassette. ``` -------------------------------- ### Cassette Instance Methods Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Describes the core methods for interacting with a Cassette instance, such as appending and playing back requests/responses. ```APIDOC ## Cassette.append ### Description Adds a request and its corresponding response to the cassette. The request and response may be modified by `before_record_request` and `before_record_response` hooks. ### Method `instance method` ### Parameters - **request** (object) - The request object to append. - **response** (object) - The response object to append. ### Response - None. Modifies the cassette in place and sets the `dirty` flag to True if data was added. ## Cassette.filter_request ### Description Applies the `before_record_request` hook to a given request. ### Method `instance method` ### Parameters - **request** (object) - The request object to filter. ### Response - The filtered request object, or None if the hook removed it. ## Cassette.can_play_response_for ### Description Determines if a response can be played back for a given request based on the cassette's state and record mode. ### Method `instance method` ### Parameters - **request** (object) - The request to check for. ### Response - True if a response can be played back, False otherwise. ## Cassette.play_response ### Description Retrieves and marks a response for a given request as played back, provided it hasn't been played before and playback is allowed. ### Method `instance method` ### Parameters - **request** (object) - The request for which to play back the response. ### Response - The corresponding response object if found and playable, otherwise behavior is not explicitly defined in this snippet but implies it would raise an error or return None if no match is found or playback is not possible. ``` -------------------------------- ### Custom HTTPConnection Patching Source: https://vcrpy.readthedocs.io/en/latest/_sources/advanced.rst.txt Use custom_patches to integrate VCR.py with custom HTTPConnection classes. This example shows how to patch a custom HTTPSConnection. ```python import where_the_custom_https_connection_lives from vcr.stubs import VCRHTTPSConnection my_vcr = config.VCR(custom_patches=((where_the_custom_https_connection_lives, 'CustomHTTPSConnection', VCRHTTPSConnection),)) ``` -------------------------------- ### Cassette Initialization Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Initializes a new Cassette instance with various configuration options for recording and playback. ```python def __init__( self, path, serializer=None, persister=None, record_mode=RecordMode.ONCE, match_on=(uri, method), before_record_request=None, before_record_response=None, custom_patches=(), inject=False, allow_playback_repeats=False, drop_unused_requests=False, ): self._persister = persister or FilesystemPersister self._path = path self._serializer = serializer or yamlserializer self._match_on = match_on self._before_record_request = before_record_request or (lambda x: x) log.info(self._before_record_request) self._before_record_response = before_record_response or (lambda x: x) self.inject = inject self.record_mode = record_mode self.custom_patches = custom_patches self.allow_playback_repeats = allow_playback_repeats self.drop_unused_requests = drop_unused_requests # self.data is the list of (req, resp) tuples self.data = [] self.play_counts = collections.Counter() self.dirty = False self.rewound = False # Subsets of self.data to store old and played interactions self._old_interactions = [] self._played_interactions = [] ``` -------------------------------- ### Mutate Request URI in Callback Source: https://vcrpy.readthedocs.io/en/latest/_sources/advanced.rst.txt Demonstrates mutating a request within a `before_record_request` callback. This example removes query parameters from requests to '/login'. ```python import urllib def scrub_login_request(request): if request.path == '/login': request.uri, _ = urllib.splitquery(request.uri) return request my_vcr = vcr.VCR( before_record_request=scrub_login_request, ) with my_vcr.use_cassette('test.yml'): # your http code here ``` -------------------------------- ### Cassette Initialization and Properties Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Details the constructor for the Cassette class and its important properties. ```APIDOC ## Cassette.__init__ ### Description Initializes a new Cassette instance with various configuration options. ### Parameters - **path** (string) - The path to the cassette file. - **serializer** (object, optional) - The serializer to use for saving/loading (defaults to yamlserializer). - **persister** (object, optional) - The persister to use for I/O (defaults to FilesystemPersister). - **record_mode** (RecordMode, optional) - The recording mode (e.g., ONCE, ALL, NONE). - **match_on** (tuple, optional) - Criteria for matching requests. - **before_record_request** (callable, optional) - Hook to modify requests before recording. - **before_record_response** (callable, optional) - Hook to modify responses before recording. - **custom_patches** (tuple, optional) - Custom patches to apply. - **inject** (bool, optional) - Whether to inject the cassette into the context. - **allow_playback_repeats** (bool, optional) - Whether to allow playing back responses multiple times. - **drop_unused_requests** (bool, optional) - Whether to drop unused requests when saving. ### Properties - **play_count** (int) - The total number of responses played back. - **all_played** (bool) - True if all responses have been played back, False otherwise. - **requests** (list) - A list of all recorded requests. - **responses** (list) - A list of all recorded responses. - **write_protected** (bool) - True if the cassette is write-protected (e.g., rewound and in ONCE mode, or in NONE mode). ``` -------------------------------- ### Custom Request Filtering Callback Source: https://vcrpy.readthedocs.io/en/latest/_sources/advanced.rst.txt Register a `before_record_request` callback to manipulate or ignore requests before they are recorded. This example prevents requests to '/login' from being recorded. ```python def before_record_cb(request): if request.path == '/login': return None return request my_vcr = vcr.VCR( before_record_request=before_record_cb, ) with my_vcr.use_cassette('test.yml'): # your http code here ``` -------------------------------- ### Basic VCRMixin Usage with unittest Source: https://vcrpy.readthedocs.io/en/latest/_sources/usage.rst.txt Demonstrates how to use VCRMixin with a unittest TestCase. Ensure VCRMixin is inherited before unittest.TestCase. ```python class MyTestMixin(VCRMixin): def test_something(self): response = requests.get(self.url) class MyTestCase(MyTestMixin, unittest.TestCase): url = 'http://example.com' ``` -------------------------------- ### Migrate VCR.py cassettes Source: https://vcrpy.readthedocs.io/en/latest/_sources/installation.rst.txt Run the VCR.py migration script to upgrade cassettes from the 0.x format to the 1.x format. Provide the path to the cassette directory or a single cassette file. ```bash python3 -m vcr.migration PATH ``` -------------------------------- ### Get Matching Responses for a Request Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Internal method to retrieve an iterator of all responses that match a given request based on configured matching rules. ```python def _responses(self, request): """ internal API, returns an iterator with all responses matching the request. """ request = self._before_record_request(request) for index, (stored_request, response) in enumerate(self.data): if requests_match(request, stored_request, self._match_on): yield index, response ``` -------------------------------- ### Custom Request Filtering: Mutate URI Source: https://vcrpy.readthedocs.io/en/latest/advanced.html Use a `before_record_request` callback to modify the request URI, for example, by removing query parameters from '/login' requests. ```python def scrub_login_request(request): if request.path == '/login': request.uri, _ = urllib.splitquery(request.uri) return request my_vcr = vcr.VCR( before_record_request=scrub_login_request, ) with my_vcr.use_cassette('test.yml'): # your http code here ``` -------------------------------- ### Building All Patchers Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html The `build` method aggregates patchers from various HTTP libraries including httplib, requests, boto3, urllib3, httplib2, tornado, aiohttp, httpcore, and custom patches defined in the cassette. ```python return itertools.chain( self._httplib(), self._requests(), self._boto3(), self._urllib3(), self._httplib2(), self._tornado(), self._aiohttp(), self._httpcore(), self._build_patchers_from_mock_triples(self._cassette.custom_patches), ) ``` -------------------------------- ### Basic Usage with Context Manager Source: https://vcrpy.readthedocs.io/en/latest/_sources/usage.rst.txt Use VCR.py as a context manager to record or replay HTTP requests within a specific block of code. The cassette file is automatically created or read from the specified path. ```python import vcr import urllib.request with vcr.use_cassette('fixtures/vcr_cassettes/synopsis.yaml'): response = urllib.request.urlopen('http://www.iana.org/domains/reserved').read() assert b'Example domains' in response ``` -------------------------------- ### Custom Response Filtering Callback Source: https://vcrpy.readthedocs.io/en/latest/_sources/advanced.rst.txt Use the `before_record_response` configuration option to mutate response bodies or prevent recording. This example scrubs sensitive strings from the response body. ```python def scrub_string(string, replacement=''): def before_record_response(response): response['body']['string'] = response['body']['string'].replace(string, replacement) return response return before_record_response my_vcr = vcr.VCR( before_record_response=scrub_string(settings.USERNAME, 'username'), ) with my_vcr.use_cassette('test.yml'): # your http code here ``` -------------------------------- ### Cassette Context Manager Entry Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Handles entering the cassette context. It loads the cassette, sets up patching, and yields the cassette instance. Asserts that the cassette is not already open to prevent reentrancy issues. ```python def __enter__(self): assert self.__finish is None, "Cassette already open." other_kwargs, cassette_kwargs = partition_dict( lambda key, _: key in self._non_cassette_arguments, self._args_getter(), ) if other_kwargs.get("path_transformer"): transformer = other_kwargs["path_transformer"] cassette_kwargs["path"] = transformer(cassette_kwargs["path"]) self.__cassette = self.cls.load(**cassette_kwargs) self.__finish = self._patch_generator(self.__cassette) return next(self.__finish) ``` -------------------------------- ### Patching Tornado SimpleAsyncHTTPClient Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html This snippet demonstrates patching the `fetch_impl` method of Tornado's `SimpleAsyncHTTPClient` to integrate with VCR.py. It's used within a context manager to ensure the patch is applied only when needed. ```python yield mock.patch.object(simple.SimpleAsyncHTTPClient, "fetch_impl", _SimpleAsyncHTTPClient_fetch_impl) ``` -------------------------------- ### Getting or Building Cassette Subclass Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html This method retrieves a cassette subclass for a given base class. If the base class already has a `cassette` attribute, it's returned directly. Otherwise, it either retrieves a cached subclass or builds a new one. ```python if klass.cassette is not None: return klass if klass not in self._class_to_cassette_subclass: subclass = self._build_cassette_subclass(klass) self._class_to_cassette_subclass[klass] = subclass return self._class_to_cassette_subclass[klass] ``` -------------------------------- ### Enable VCR.py INFO Logging Source: https://vcrpy.readthedocs.io/en/latest/_sources/debugging.rst.txt Enable INFO level logging for VCR.py to see when requests are sent to real servers or played from cassettes. Ensure logging is initialized. ```python import vcr import requests import logging logging.basicConfig() # you need to initialize logging, otherwise you will not see anything from vcrpy vcr_log = logging.getLogger("vcr") vcr_log.setLevel(logging.INFO) with vcr.use_cassette('headers.yml'): requests.get('http://httpbin.org/headers') ``` -------------------------------- ### Cassette Class Methods Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Provides an overview of the static and class methods available on the Cassette class for managing cassette instances. ```APIDOC ## Cassette.load ### Description Instantiates and loads a cassette from a specified path. ### Method `classmethod` ### Parameters None explicitly documented for this method signature, but initialization parameters are passed to the constructor. ### Response - Returns a new `Cassette` instance loaded with data. ## Cassette.use_arg_getter ### Description Creates a `CassetteContextDecorator` that uses a custom argument getter for cassette configuration. ### Method `classmethod` ### Parameters - **arg_getter** (callable) - A function that provides arguments for cassette configuration. ### Response - Returns a `CassetteContextDecorator` instance. ## Cassette.use ### Description Creates a `CassetteContextDecorator` for a cassette, allowing for configuration via keyword arguments. ### Method `classmethod` ### Parameters - **kwargs** - Arbitrary keyword arguments to configure the cassette. ### Response - Returns a `CassetteContextDecorator` instance. ``` -------------------------------- ### Importing and Storing Original Tornado HTTP Client Implementations Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html This code block attempts to import specific Tornado HTTP client implementations and stores their original `fetch_impl` methods if the imports are successful. This is useful for preserving the original behavior before patching. ```python try: import tornado.simple_httpclient except ImportError: # pragma: no cover pass else: _SimpleAsyncHTTPClient_fetch_impl = tornado.simple_httpclient.SimpleAsyncHTTPClient.fetch_impl try: import tornado.curl_httpclient except ImportError: # pragma: no cover pass else: _CurlAsyncHTTPClient_fetch_impl = tornado.curl_httpclient.CurlAsyncHTTPClient.fetch_impl ``` -------------------------------- ### vcr.patch.CassettePatcherBuilder Methods Source: https://vcrpy.readthedocs.io/en/latest/genindex.html Methods for building cassette patchers. ```APIDOC ## CassettePatcherBuilder Methods ### `build()` * **Description**: Builds and returns a cassette patcher. * **Usage**: Create a patcher instance. ``` -------------------------------- ### Cassette Context Decorator from Arguments Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Creates a CassetteContextDecorator from provided arguments, enabling the cassette to be used as a context manager. ```python @classmethod def use(cls, **kwargs): return CassetteContextDecorator.from_args(cls, **kwargs) ``` -------------------------------- ### Global VCR Configuration Source: https://vcrpy.readthedocs.io/en/latest/_sources/configuration.rst.txt Configure VCR globally by instantiating the VCR class with desired options. This sets defaults for all subsequent cassette uses. ```python import vcr my_vcr = vcr.VCR( serializer='json', cassette_library_dir='fixtures/cassettes', record_mode='once', match_on=['uri', 'method'], ) with my_vcr.use_cassette('test.json'): # your http code here ``` -------------------------------- ### Rebuild pyyaml with libyaml Source: https://vcrpy.readthedocs.io/en/latest/_sources/installation.rst.txt Uninstall the current pyyaml and reinstall it, ensuring the --no-cache-dir flag is used to force a rebuild that utilizes libyaml if available. ```bash pip3 uninstall pyyaml pip3 --no-cache-dir install pyyaml ``` -------------------------------- ### Importing and Storing Original httpcore Connection Pool Methods Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html This code block imports `httpcore` and stores the original `ConnectionPool.handle_request` and `AsyncConnectionPool.handle_async_request` methods. This is done to preserve the original functionality before VCRpy applies its patches. ```python try: import httpcore except ImportError: # pragma: no cover pass else: _HttpcoreConnectionPool_handle_request = httpcore.ConnectionPool.handle_request _HttpcoreAsyncConnectionPool_handle_async_request = httpcore.AsyncConnectionPool.handle_async_request ``` -------------------------------- ### Advanced Header Filtering with Tuples Source: https://vcrpy.readthedocs.io/en/latest/advanced.html Demonstrates replacing header values with static strings or using callables for dynamic replacement. ```python # original (still works) vcr = VCR(filter_headers=['authorization']) # new vcr = VCR(filter_headers=[('authorization', None)]) ``` ```python # replace with a static value (most common) vcr = VCR(filter_headers=[('authorization', 'XXXXXX')]) ``` ```python # replace with a callable, for example when testing # lots of different kinds of authorization. def replace_auth(key, value, request): auth_type = value.split(' ', 1)[0] return '{} {}'.format(auth_type, 'XXXXXX') ``` -------------------------------- ### Build Merged Configuration Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/config.html Constructs a merged configuration dictionary from instance attributes and keyword arguments. Handles cassette library directory, path transformers, and function path generators. ```python cassette_library_dir = kwargs.get("cassette_library_dir", self.cassette_library_dir) additional_matchers = kwargs.get("additional_matchers", ()) record_on_exception = kwargs.get("record_on_exception", self.record_on_exception) if cassette_library_dir: def add_cassette_library_dir(path): if not path.startswith(cassette_library_dir): return os.path.join(cassette_library_dir, path) return path path_transformer = compose(add_cassette_library_dir, path_transformer) elif not func_path_generator: # If we don't have a library dir, use the functions # location to build a full path for cassettes. func_path_generator = self._build_path_from_func_using_module merged_config = { "serializer": self._get_serializer(serializer_name), "persister": self.persister, "match_on": self._get_matchers(tuple(matcher_names) + tuple(additional_matchers)), "record_mode": kwargs.get("record_mode", self.record_mode), "before_record_request": self._build_before_record_request(kwargs), "before_record_response": self._build_before_record_response(kwargs), "custom_patches": self._custom_patches + kwargs.get("custom_patches", ()), "inject": kwargs.get("inject_cassette", self.inject_cassette), "path_transformer": path_transformer, "func_path_generator": func_path_generator, "allow_playback_repeats": kwargs.get("allow_playback_repeats", False), "record_on_exception": record_on_exception, "drop_unused_requests": kwargs.get("drop_unused_requests", self.drop_unused_requests), } path = kwargs.get("path") if path: merged_config["path"] = path return merged_config ``` -------------------------------- ### CassettePatcherBuilder Initialization Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html Initializes the `CassettePatcherBuilder` with a cassette object. It also sets up a dictionary to map classes to their cassette subclass replacements. ```python def __init__(self, cassette): self._cassette = cassette self._class_to_cassette_subclass = {} ``` -------------------------------- ### Cassette Load Class Method Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Instantiates and loads a cassette from a specified path. This is a class method used to create and initialize a cassette object. ```python @classmethod def load(cls, **kwargs): """Instantiate and load the cassette stored at the specified path.""" new_cassette = cls(**kwargs) new_cassette._load() return new_cassette ``` -------------------------------- ### Registering a Custom Serializer Source: https://vcrpy.readthedocs.io/en/latest/advanced.html Implement `serialize` and `deserialize` methods in a class and register it with VCR to handle custom cassette formats. ```python import vcr class BogoSerializer: """ Must implement serialize() and deserialize() methods """ pass my_vcr = vcr.VCR() my_vcr.register_serializer('bogo', BogoSerializer()) with my_vcr.use_cassette('test.bogo', serializer='bogo'): # your http here # After you register, you can set the default serializer to your new serializer my_vcr.serializer = 'bogo' with my_vcr.use_cassette('test.bogo'): # your http here ``` -------------------------------- ### Registering a Custom Cassette Persister Source: https://vcrpy.readthedocs.io/en/latest/advanced.html Implement `load_cassette` and `save_cassette` methods in a class to create a custom way to persist and load cassette data. ```python import vcr my_vcr = vcr.VCR() class CustomerPersister: # implement Persister methods... my_vcr.register_persister(CustomPersister) ``` -------------------------------- ### Usage with Decorator (with path) Source: https://vcrpy.readthedocs.io/en/latest/_sources/usage.rst.txt Apply VCR.py as a decorator to a test function to automatically manage cassette recording and playback for that function. The cassette path must be explicitly provided. ```python @vcr.use_cassette('fixtures/vcr_cassettes/synopsis.yaml') def test_iana(): response = urllib.request.urlopen('http://www.iana.org/domains/reserved').read() assert b'Example domains' in response ``` -------------------------------- ### Request Scheme, Host, Port, Path, and Query Properties Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/request.html Provides properties to access parsed components of the request URI, including scheme, host, port, path, and sorted query parameters. ```python @property def scheme(self): return self.parsed_uri.scheme @property def host(self): return self.parsed_uri.hostname @property def port(self): port = self.parsed_uri.port if port is None: with suppress(KeyError): port = {"https": 443, "http": 80}[self.parsed_uri.scheme] return port @property def path(self): return self.parsed_uri.path @property def query(self): q = self.parsed_uri.query return sorted(parse_qsl(q)) ``` -------------------------------- ### Request Class Initialization Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/request.html Initializes a Request object with method, URI, body, and headers. Handles different body types like files, iterators, or direct values. ```python import logging import warnings from contextlib import suppress from io import BytesIO from urllib.parse import parse_qsl, urlparse from .util import CaseInsensitiveDict, _is_nonsequence_iterator log = logging.getLogger(__name__) class Request: """ VCR's representation of a request. """ def __init__(self, method, uri, body, headers): self.method = method self.uri = uri self._was_file = hasattr(body, "read") self._was_iter = _is_nonsequence_iterator(body) if self._was_file: self.body = body.read() elif self._was_iter: self.body = list(body) else: self.body = body self.headers = headers log.debug("Invoking Request %s", self.uri) ``` -------------------------------- ### Create a Test Case Decorator Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/config.html Creates a metaclass that can be used to automatically decorate test methods with `use_cassette`. A predicate function can be provided to control which methods are decorated. ```python def test_case(self, predicate=None): predicate = predicate or self.is_test_method metaclass = auto_decorate(self.use_cassette, predicate) return metaclass("temporary_class", (), {}) ``` -------------------------------- ### Request URL and Protocol Aliases Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/request.html Provides alias properties 'url' for 'uri' and 'protocol' for 'scheme' for backwards compatibility. ```python # alias for backwards compatibility @property def url(self): return self.uri # alias for backwards compatibility @property def protocol(self): return self.scheme ``` -------------------------------- ### Test pyyaml libyaml build Source: https://vcrpy.readthedocs.io/en/latest/_sources/installation.rst.txt Verify if pyyaml was compiled with libyaml extensions. This should execute without errors if the build was successful. ```python python3 -c 'from yaml import CLoader' ``` -------------------------------- ### Patching tornado SimpleAsyncHTTPClient Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html Applies a VCRpy-specific fetch implementation to tornado's SimpleAsyncHTTPClient. This allows VCRpy to intercept and manage requests made by this client. ```python @_build_patchers_from_mock_triples_decorator def _tornado(self): try: import tornado.simple_httpclient as simple except ImportError: # pragma: no cover pass else: from .stubs.tornado_stubs import vcr_fetch_impl new_fetch_impl = vcr_fetch_impl(self._cassette, _SimpleAsyncHTTPClient_fetch_impl) yield simple.SimpleAsyncHTTPClient, "fetch_impl", new_fetch_impl ``` -------------------------------- ### VCRMixin for Existing Class Hierarchies Source: https://vcrpy.readthedocs.io/en/latest/usage.html Use VCRMixin as an alternative to VCRTestCase when inheriting from VCRTestCase is not feasible due to existing class hierarchies. It provides similar functionality. ```python from vcr.unittest import VCRMixin import requests import unittest class MyTestMixin(VCRMixin): def test_something(self): response = requests.get(self.url) class MyTestCase(MyTestMixin, unittest.TestCase): url = 'http://example.com' ``` -------------------------------- ### Automatic Cassette Naming with Empty Path Source: https://vcrpy.readthedocs.io/en/latest/_sources/advanced.rst.txt An alternative syntax for automatic cassette naming using an empty path argument in use_cassette. ```python @my_vcr.use_cassette() def my_test_function(): ... ``` -------------------------------- ### Building a Cassette Subclass Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html Dynamically creates a new class that inherits from a given `base_class` and assigns the current cassette object to a `cassette` attribute on the new class. This is used to support nested cassette contexts. ```python bases = (base_class,) if not issubclass(base_class, object): # Check for old style class bases += (object,) return type(f"{base_class.__name__}{self._cassette._path}", bases, {"cassette": self._cassette}) ``` -------------------------------- ### Building a Single Patcher Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html This method creates a `mock.patch.object` instance for a given object, attribute, and replacement class. It returns `None` if the attribute does not exist on the object. ```python if not hasattr(obj, patched_attribute): return return mock.patch.object( obj, patched_attribute, self._recursively_apply_get_cassette_subclass(replacement_class), ) ``` -------------------------------- ### Build Used Interactions Dictionary Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/cassette.html Constructs a dictionary containing all interactions that have been played or are new. This is used when saving the cassette, especially when dropping unused requests. ```python interactions = self._played_interactions + self._new_interactions() cassete_dict = { "requests": [request for request, _ in interactions], "responses": [response for _, response in interactions], } return cassete_dict ``` -------------------------------- ### Per-Cassette Configuration Overrides Source: https://vcrpy.readthedocs.io/en/latest/_sources/configuration.rst.txt Override VCR configuration options on a per-cassette basis. These settings take precedence over global configurations. ```python with vcr.use_cassette('test.yml', serializer='json', record_mode='once'): # your http code here ``` -------------------------------- ### Unittest Integration with VCRTestCase Source: https://vcrpy.readthedocs.io/en/latest/_sources/usage.rst.txt Inherit from VCRTestCase to automatically integrate VCR.py with Python's unittest framework. Cassettes are managed automatically based on test class and method names. ```python from vcr.unittest import VCRTestCase import requests class MyTestCase(VCRTestCase): def test_something(self): response = requests.get('http://example.com') ``` -------------------------------- ### Registering a Custom Request Matcher Source: https://vcrpy.readthedocs.io/en/latest/advanced.html Define a function that takes two requests and returns a boolean or raises an AssertionError to customize how requests are matched during playback. ```python import vcr def jurassic_matcher(r1, r2): assert r1.uri == r2.uri and 'JURASSIC PARK' in r1.body, \ 'required string (JURASSIC PARK) not found in request body' my_vcr = vcr.VCR() my_vcr.register_matcher('jurassic', jurassic_matcher) with my_vcr.use_cassette('test.yml', match_on=['jurassic']): # your http here # After you register, you can set the default match_on to use your new matcher my_vcr.match_on = ['jurassic'] with my_vcr.use_cassette('test.yml'): # your http here ``` -------------------------------- ### Register a Persister Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/config.html Registers a custom persister with VCR.py. Persisters handle saving and loading cassette data. ```python def register_persister(self, persister): # Singleton, no name required self.persister = persister ``` -------------------------------- ### Advanced Header Filtering with Callables Source: https://vcrpy.readthedocs.io/en/latest/_sources/advanced.rst.txt Demonstrates advanced filtering for HTTP headers using a list of tuples. Values can be static replacements, `None` to remove, or a callable for dynamic filtering. ```python vcr = VCR(filter_headers=[('authorization', 'XXXXXX')]) ``` ```python def replace_auth(key, value, request): auth_type = value.split(' ', 1)[0] return '{} {}'.format(auth_type, 'XXXXXX') vcr = VCR(filter_headers=[('authorization', replace_auth)]) ``` -------------------------------- ### vcr.patch.ConnectionRemover Methods Source: https://vcrpy.readthedocs.io/en/latest/genindex.html Methods for managing and removing network connections. ```APIDOC ## ConnectionRemover Methods ### `add_connection_to_pool_entry()` * **Description**: Adds a connection to the connection pool entry. * **Usage**: Manages connection pooling. ``` -------------------------------- ### Import and Save Original HTTPConnection Types Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html Imports necessary modules and saves original HTTPConnection and HTTPSConnection types from http.client for later restoration. ```python import contextlib import functools import http.client as httplib import itertools import logging from unittest import mock from .stubs import VCRHTTPConnection, VCRHTTPSConnection log = logging.getLogger(__name__) # Save some of the original types for the purposes of unpatching _HTTPConnection = httplib.HTTPConnection _HTTPSConnection = httplib.HTTPSConnection ``` -------------------------------- ### Allowing Playback Repeats Source: https://vcrpy.readthedocs.io/en/latest/advanced.html Enable repeated playback of responses from a cassette without needing to rewind it by setting `allow_playback_repeats=True`. ```python with vcr.use_cassette('fixtures/vcr_cassettes/synopsis.yaml', allow_playback_repeats=True) as cass: for x in range(10): response = urllib2.urlopen('http://www.zombo.com/').read() assert cass.all_played ``` -------------------------------- ### Set SSL Backend Environment Variables Source: https://vcrpy.readthedocs.io/en/latest/_sources/contributing.rst.txt Set these environment variables to specify the SSL backend for PycURL. This is often necessary when PycURL cannot automatically detect the SSL library. ```bash export PYCURL_SSL_LIBRARY=openssl export LDFLAGS=-L/usr/local/opt/openssl/lib export CPPFLAGS=-I/usr/local/opt/openssl/include ``` -------------------------------- ### Accessing Cassette Information Source: https://vcrpy.readthedocs.io/en/latest/advanced.html Use the `vcr.use_cassette` context manager to access cassette properties like the number of requests and their URIs after making HTTP calls. ```python import vcr import urllib2 with vcr.use_cassette('fixtures/vcr_cassettes/synopsis.yaml') as cass: response = urllib2.urlopen('http://www.zombo.com/').read() # cass should have 1 request inside it assert len(cass) == 1 # the request uri should have been http://www.zombo.com/ assert cass.requests[0].uri == 'http://www.zombo.com/' ``` -------------------------------- ### Decorator for Building Patchers from Mock Triples Source: https://vcrpy.readthedocs.io/en/latest/_modules/vcr/patch.html This decorator, `_build_patchers_from_mock_triples_decorator`, wraps a function that returns mock triples. It then processes these triples to build patchers, ensuring that the original function's output is correctly handled. ```python @functools.wraps(function) def wrapped(self, *args, **kwargs): return self._build_patchers_from_mock_triples(function(self, *args, **kwargs)) return wrapped ``` -------------------------------- ### Register Custom Serializer Source: https://vcrpy.readthedocs.io/en/latest/_sources/advanced.rst.txt Create a custom serializer by implementing `deserialize` and `serialize` methods, then register it with VCR. This allows VCR.py to handle cassette data in formats other than JSON or YAML. ```python import vcr class BogoSerializer: """ Must implement serialize() and deserialize() methods """ pass my_vcr = vcr.VCR() my_vcr.register_serializer('bogo', BogoSerializer()) with my_vcr.use_cassette('test.bogo', serializer='bogo'): # your http here # After you register, you can set the default serializer to your new serializer my_vcr.serializer = 'bogo' with my_vcr.use_cassette('test.bogo'): # your http here ```