| #!/usr/bin/env python |
| """ |
| Example utilities to export responses to a format compatible with VCR-based libraries, including: |
| * [vcrpy](https://github.com/kevin1024/vcrpy) |
| * [betamax](https://github.com/betamaxpy/betamax) |
| """ |
| from os import makedirs |
| from os.path import abspath, dirname, expanduser, join |
| from typing import Any, Dict, Iterable |
| from urllib.parse import urlparse |
| |
| import yaml |
| |
| from requests_cache import BaseCache, CachedResponse, CachedSession, __version__ |
| from requests_cache.serializers.preconf import yaml_preconf_stage |
| |
| |
| def to_vcr_cassette(cache: BaseCache, path: str): |
| """Export cached responses to a VCR-compatible YAML file (cassette) |
| |
| Args: |
| cache: Cache instance containing response data to export |
| path: Path for new cassette file |
| """ |
| |
| responses = cache.responses.values() |
| write_cassette(to_vcr_cassette_dict(responses), path) |
| |
| |
| def to_vcr_cassettes_by_host(cache: BaseCache, cassette_dir: str = '.'): |
| """Export cached responses as VCR-compatible YAML files (cassettes), split into separate files |
| based on request host |
| |
| Args: |
| cache: Cache instance containing response data to export |
| cassette_dir: Base directory for cassette library |
| """ |
| responses = cache.responses.values() |
| for host, cassette in to_vcr_cassette_dicts_by_host(responses).items(): |
| write_cassette(cassette, join(cassette_dir, f'{host}.yml')) |
| |
| |
| def to_vcr_cassette_dict(responses: Iterable[CachedResponse]) -> Dict: |
| """Convert responses to a VCR cassette dict""" |
| return { |
| 'http_interactions': [to_vcr_episode(r) for r in responses], |
| 'recorded_with': f'requests-cache {__version__}', |
| } |
| |
| |
| def to_vcr_episode(response: CachedResponse) -> Dict: |
| """Convert a single response to a VCR-compatible response ("episode") dict""" |
| # Do most of the work with cattrs + default YAML conversions |
| response_dict = yaml_preconf_stage.dumps(response) |
| |
| def _to_multidict(d): |
| return {k: [v] for k, v in d.items()} |
| |
| # Translate requests.Response structure into VCR format |
| return { |
| 'request': { |
| 'body': response_dict['request']['body'], |
| 'headers': _to_multidict(response_dict['request']['headers']), |
| 'method': response_dict['request']['method'], |
| 'uri': response_dict['request']['url'], |
| }, |
| 'response': { |
| 'body': {'string': response_dict['_content'], 'encoding': response_dict['encoding']}, |
| 'headers': _to_multidict(response_dict['headers']), |
| 'status': {'code': response_dict['status_code'], 'message': response_dict['reason']}, |
| 'url': response_dict['url'], |
| }, |
| 'recorded_at': response_dict['created_at'], |
| } |
| |
| |
| def to_vcr_cassette_dicts_by_host(responses: Iterable[CachedResponse]) -> Dict[str, Dict]: |
| responses_by_host: Dict[str, Any] = {} |
| for response in responses: |
| host = urlparse(response.request.url).netloc |
| responses_by_host.setdefault(host, []) |
| responses_by_host[host].append(response) |
| return {host: to_vcr_cassette_dict(responses) for host, responses in responses_by_host.items()} |
| |
| |
| def write_cassette(cassette, path): |
| path = abspath(expanduser(path)) |
| makedirs(dirname(path), exist_ok=True) |
| with open(path, 'w') as f: |
| f.write(yaml.safe_dump(cassette)) |
| |
| |
| # Create an example cache and export it to a cassette |
| if __name__ == '__main__': |
| cache_dir = 'example_cache' |
| session = CachedSession(join(cache_dir, 'http_cache.sqlite')) |
| session.get('https://httpbin.org/get') |
| session.get('https://httpbin.org/json') |
| to_vcr_cassette(session.cache, join(cache_dir, 'http_cache.yaml')) |