1
0
mirror of https://github.com/kevin1024/vcrpy.git synced 2025-12-09 01:03:24 +00:00

HTTPX stub now generates cassettes in the same format as other stubs.

As part of this, I've removed the tests which inspect the
data type of the response content in the cassette. That
behaviour should be controlled via the inbuilt serializers.
This commit is contained in:
Allan Crooks
2024-01-20 17:46:52 +00:00
committed by Jair Henrique
parent 5fa7010712
commit 5cf23298ac
2 changed files with 20 additions and 47 deletions

View File

@@ -314,30 +314,3 @@ def test_load_gzipped(do_request, cassette_name, reason):
assert cassette_response.status_code == 200 assert cassette_response.status_code == 200
assert cassette_response.reason_phrase == reason assert cassette_response.reason_phrase == reason
@pytest.mark.online
def test_text_content_type(tmpdir, httpbin, do_request):
url = httpbin.url + "/json"
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))):
response = do_request()("GET", url)
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))) as cassette:
cassette_response = do_request()("GET", url)
assert cassette_response.content == response.content
assert cassette.play_count == 1
assert isinstance(cassette.responses[0]["content"], str)
@pytest.mark.online
def test_binary_content_type(tmpdir, httpbin, do_request):
url = httpbin.url + "/bytes/1024"
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))):
response = do_request()("GET", url)
with vcr.use_cassette(str(tmpdir.join("json_type.yaml"))) as cassette:
cassette_response = do_request()("GET", url)
assert cassette_response.content == response.content
assert cassette.play_count == 1
assert isinstance(cassette.responses[0]["content"], bytes)

View File

@@ -1,3 +1,4 @@
import asyncio
import functools import functools
import inspect import inspect
import logging import logging
@@ -35,17 +36,17 @@ def _transform_headers(httpx_response):
return out return out
def _to_serialized_response(httpx_response): async def _to_serialized_response(resp, aread):
try:
content = httpx_response.content.decode("utf-8") if aread:
except UnicodeDecodeError: await resp.aread()
content = httpx_response.content else:
resp.read()
return { return {
"status_code": httpx_response.status_code, "status": dict(code=resp.status_code, message=resp.reason_phrase),
"http_version": httpx_response.http_version, "headers": _transform_headers(resp),
"headers": _transform_headers(httpx_response), "body": {"string": resp.content},
"content": content,
} }
@@ -65,17 +66,16 @@ def _from_serialized_headers(headers):
@patch("httpx.Response.read", MagicMock()) @patch("httpx.Response.read", MagicMock())
def _from_serialized_response(request, serialized_response, history=None): def _from_serialized_response(request, serialized_response, history=None):
# HTTPX cassette format. # Cassette format generated for HTTPX requests by older versions of
# vcrpy. We restructure the content to resemble what a regular
# cassette looks like.
if "status_code" in serialized_response: if "status_code" in serialized_response:
serialized_response = decode_response(convert_body_to_bytes({ serialized_response = decode_response(convert_body_to_bytes({
'headers': serialized_response['headers'], 'headers': serialized_response['headers'],
'body': {'string': serialized_response['content']}, 'body': {'string': serialized_response['content']},
'status': {'code': serialized_response['status_code']}, 'status': {'code': serialized_response['status_code']},
})) }))
# We don't store the reason phrase in this format.
extensions = None extensions = None
# Cassette format that all other stubs use.
else: else:
extensions = {"reason_phrase": serialized_response["status"]["message"].encode()} extensions = {"reason_phrase": serialized_response["status"]["message"].encode()}
@@ -113,17 +113,17 @@ def _shared_vcr_send(cassette, real_send, *args, **kwargs):
return vcr_request, None return vcr_request, None
def _record_responses(cassette, vcr_request, real_response): async def _record_responses(cassette, vcr_request, real_response, aread):
for past_real_response in real_response.history: for past_real_response in real_response.history:
past_vcr_request = _make_vcr_request(past_real_response.request) past_vcr_request = _make_vcr_request(past_real_response.request)
cassette.append(past_vcr_request, _to_serialized_response(past_real_response)) cassette.append(past_vcr_request, await _to_serialized_response(past_real_response, aread))
if real_response.history: if real_response.history:
# If there was a redirection keep we want the request which will hold the # If there was a redirection keep we want the request which will hold the
# final redirect value # final redirect value
vcr_request = _make_vcr_request(real_response.request) vcr_request = _make_vcr_request(real_response.request)
cassette.append(vcr_request, _to_serialized_response(real_response)) cassette.append(vcr_request, await _to_serialized_response(real_response, aread))
return real_response return real_response
@@ -141,8 +141,8 @@ async def _async_vcr_send(cassette, real_send, *args, **kwargs):
return response return response
real_response = await real_send(*args, **kwargs) real_response = await real_send(*args, **kwargs)
await real_response.aread() await _record_responses(cassette, vcr_request, real_response, aread=True)
return _record_responses(cassette, vcr_request, real_response) return real_response
def async_vcr_send(cassette, real_send): def async_vcr_send(cassette, real_send):
@@ -161,8 +161,8 @@ def _sync_vcr_send(cassette, real_send, *args, **kwargs):
return response return response
real_response = real_send(*args, **kwargs) real_response = real_send(*args, **kwargs)
real_response.read() asyncio.run(_record_responses(cassette, vcr_request, real_response, aread=False))
return _record_responses(cassette, vcr_request, real_response) return real_response
def sync_vcr_send(cassette, real_send): def sync_vcr_send(cassette, real_send):