mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-09 17:15:35 +00:00
Allow HTTPX stub to read cassettes generated by other stubs.
This was due to a custom format being defined in the HTTPX stub.
This commit is contained in:
committed by
Jair Henrique
parent
f1e0241673
commit
5fa7010712
41
tests/integration/cassettes/gzip_httpx_old_format.yaml
Normal file
41
tests/integration/cassettes/gzip_httpx_old_format.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
interactions:
|
||||||
|
- request:
|
||||||
|
body: ''
|
||||||
|
headers:
|
||||||
|
accept:
|
||||||
|
- '*/*'
|
||||||
|
accept-encoding:
|
||||||
|
- gzip, deflate, br
|
||||||
|
connection:
|
||||||
|
- keep-alive
|
||||||
|
host:
|
||||||
|
- httpbin.org
|
||||||
|
user-agent:
|
||||||
|
- python-httpx/0.23.0
|
||||||
|
method: GET
|
||||||
|
uri: https://httpbin.org/gzip
|
||||||
|
response:
|
||||||
|
content: "{\n \"gzipped\": true, \n \"headers\": {\n \"Accept\": \"*/*\",
|
||||||
|
\n \"Accept-Encoding\": \"gzip, deflate, br\", \n \"Host\": \"httpbin.org\",
|
||||||
|
\n \"User-Agent\": \"python-httpx/0.23.0\", \n \"X-Amzn-Trace-Id\": \"Root=1-62a62a8d-5f39b5c50c744da821d6ea99\"\n
|
||||||
|
\ }, \n \"method\": \"GET\", \n \"origin\": \"146.200.25.115\"\n}\n"
|
||||||
|
headers:
|
||||||
|
Access-Control-Allow-Credentials:
|
||||||
|
- 'true'
|
||||||
|
Access-Control-Allow-Origin:
|
||||||
|
- '*'
|
||||||
|
Connection:
|
||||||
|
- keep-alive
|
||||||
|
Content-Encoding:
|
||||||
|
- gzip
|
||||||
|
Content-Length:
|
||||||
|
- '230'
|
||||||
|
Content-Type:
|
||||||
|
- application/json
|
||||||
|
Date:
|
||||||
|
- Sun, 12 Jun 2022 18:03:57 GMT
|
||||||
|
Server:
|
||||||
|
- gunicorn/19.9.0
|
||||||
|
http_version: HTTP/1.1
|
||||||
|
status_code: 200
|
||||||
|
version: 1
|
||||||
42
tests/integration/cassettes/gzip_requests.yaml
Normal file
42
tests/integration/cassettes/gzip_requests.yaml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
interactions:
|
||||||
|
- request:
|
||||||
|
body: null
|
||||||
|
headers:
|
||||||
|
Accept:
|
||||||
|
- '*/*'
|
||||||
|
Accept-Encoding:
|
||||||
|
- gzip, deflate, br
|
||||||
|
Connection:
|
||||||
|
- keep-alive
|
||||||
|
User-Agent:
|
||||||
|
- python-requests/2.28.0
|
||||||
|
method: GET
|
||||||
|
uri: https://httpbin.org/gzip
|
||||||
|
response:
|
||||||
|
body:
|
||||||
|
string: !!binary |
|
||||||
|
H4sIAKwrpmIA/z2OSwrCMBCG956izLIkfQSxkl2RogfQA9R2bIM1iUkqaOndnYDIrGa+/zELDB9l
|
||||||
|
LfYgg5uRwYhtj86DXKDuOrQBJKR5Cuy38kZ3pld6oHu0sqTH29QGZMnVkepgtMYuKKNJcEe0vJ3U
|
||||||
|
C4mcjI9hpaiygqaUW7ETFYGLR8frAXXE9h1Go7nD54w++FxkYp8VsDJ4IBH6E47NmVzGqUHFkn8g
|
||||||
|
rJsvp2omYs8AAAA=
|
||||||
|
headers:
|
||||||
|
Access-Control-Allow-Credentials:
|
||||||
|
- 'true'
|
||||||
|
Access-Control-Allow-Origin:
|
||||||
|
- '*'
|
||||||
|
Connection:
|
||||||
|
- Close
|
||||||
|
Content-Encoding:
|
||||||
|
- gzip
|
||||||
|
Content-Length:
|
||||||
|
- '182'
|
||||||
|
Content-Type:
|
||||||
|
- application/json
|
||||||
|
Date:
|
||||||
|
- Sun, 12 Jun 2022 18:08:44 GMT
|
||||||
|
Server:
|
||||||
|
- Pytest-HTTPBIN/0.1.0
|
||||||
|
status:
|
||||||
|
code: 200
|
||||||
|
message: great
|
||||||
|
version: 1
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
import os
|
||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
asyncio = pytest.importorskip("asyncio")
|
asyncio = pytest.importorskip("asyncio")
|
||||||
@@ -218,8 +218,8 @@ def test_work_with_gzipped_data(httpbin, do_request, yml):
|
|||||||
with vcr.use_cassette(yml) as cassette:
|
with vcr.use_cassette(yml) as cassette:
|
||||||
cassette_response = do_request(headers=headers)("GET", url)
|
cassette_response = do_request(headers=headers)("GET", url)
|
||||||
|
|
||||||
assert cassette_response.headers["content-encoding"] == "gzip"
|
# Show we can read the content of the cassette.
|
||||||
assert cassette_response.read()
|
assert cassette_response.json()['gzipped'] == True
|
||||||
assert cassette.play_count == 1
|
assert cassette.play_count == 1
|
||||||
|
|
||||||
|
|
||||||
@@ -287,6 +287,34 @@ def test_stream(tmpdir, httpbin, do_request):
|
|||||||
assert cassette.play_count == 1
|
assert cassette.play_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
# Regular cassette formats support the status reason,
|
||||||
|
# but the old HTTPX cassette format does not.
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"cassette_name,reason",
|
||||||
|
[
|
||||||
|
("requests", "great"),
|
||||||
|
("httpx_old_format", "OK"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_load_gzipped(do_request, cassette_name, reason):
|
||||||
|
mydir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
yml = f"{mydir}/cassettes/gzip_{cassette_name}.yaml"
|
||||||
|
url = "https://httpbin.org/gzip"
|
||||||
|
|
||||||
|
with vcr.use_cassette(yml) as cassette:
|
||||||
|
cassette_response = do_request()("GET", url)
|
||||||
|
assert str(cassette_response.request.url) == url
|
||||||
|
assert cassette.play_count == 1
|
||||||
|
|
||||||
|
# Should be able to load up the JSON inside,
|
||||||
|
# regardless whether the content is the gzipped
|
||||||
|
# in the cassette or not.
|
||||||
|
json = cassette_response.json()
|
||||||
|
assert json["method"] == "GET", json
|
||||||
|
assert cassette_response.status_code == 200
|
||||||
|
assert cassette_response.reason_phrase == reason
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.online
|
@pytest.mark.online
|
||||||
def test_text_content_type(tmpdir, httpbin, do_request):
|
def test_text_content_type(tmpdir, httpbin, do_request):
|
||||||
url = httpbin.url + "/json"
|
url = httpbin.url + "/json"
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import httpx
|
|||||||
|
|
||||||
from vcr.errors import CannotOverwriteExistingCassetteException
|
from vcr.errors import CannotOverwriteExistingCassetteException
|
||||||
from vcr.request import Request as VcrRequest
|
from vcr.request import Request as VcrRequest
|
||||||
|
from vcr.filters import decode_response
|
||||||
|
from vcr.serializers.compat import convert_body_to_bytes
|
||||||
|
|
||||||
_httpx_signature = inspect.signature(httpx.Client.request)
|
_httpx_signature = inspect.signature(httpx.Client.request)
|
||||||
|
|
||||||
@@ -62,17 +64,30 @@ def _from_serialized_headers(headers):
|
|||||||
@patch("httpx.Response.close", MagicMock())
|
@patch("httpx.Response.close", MagicMock())
|
||||||
@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):
|
||||||
content = serialized_response.get("content")
|
|
||||||
if isinstance(content, str):
|
# HTTPX cassette format.
|
||||||
content = content.encode("utf-8")
|
if "status_code" in serialized_response:
|
||||||
|
serialized_response = decode_response(convert_body_to_bytes({
|
||||||
|
'headers': serialized_response['headers'],
|
||||||
|
'body': {'string': serialized_response['content']},
|
||||||
|
'status': {'code': serialized_response['status_code']},
|
||||||
|
}))
|
||||||
|
# We don't store the reason phrase in this format.
|
||||||
|
extensions = None
|
||||||
|
|
||||||
|
# Cassette format that all other stubs use.
|
||||||
|
else:
|
||||||
|
extensions = {"reason_phrase": serialized_response["status"]["message"].encode()}
|
||||||
|
|
||||||
response = httpx.Response(
|
response = httpx.Response(
|
||||||
status_code=serialized_response.get("status_code"),
|
status_code=serialized_response["status"]["code"],
|
||||||
request=request,
|
request=request,
|
||||||
headers=_from_serialized_headers(serialized_response.get("headers")),
|
headers=_from_serialized_headers(serialized_response["headers"]),
|
||||||
content=content,
|
content=serialized_response["body"]["string"],
|
||||||
history=history or [],
|
history=history or [],
|
||||||
|
extensions=extensions,
|
||||||
)
|
)
|
||||||
response._content = content
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user