Skip to content

Commit 2e12056

Browse files
tysonholubtholub
authored andcommitted
fix httpx async invocation if already running event loop
1 parent acc1014 commit 2e12056

File tree

2 files changed

+41
-22
lines changed

2 files changed

+41
-22
lines changed

docs/contributing.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ in this example::
115115
pyenv local 3.12.0 pypy3.10
116116

117117
# Run the whole test suite
118-
pip install .[test]
119-
./run_tests.sh
118+
pip install .[tests]
119+
./runtests.sh
120120

121121

122122
Troubleshooting on MacOSX

vcr/stubs/httpx_stubs.py

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,34 @@ def _transform_headers(httpx_response):
3838

3939
async def _to_serialized_response(resp, aread):
4040
# The content shouldn't already have been read in by HTTPX.
41-
assert not hasattr(resp, "_decoder")
42-
43-
# Retrieve the content, but without decoding it.
44-
with patch.dict(resp.headers, {"Content-Encoding": ""}):
45-
if aread:
46-
await resp.aread()
47-
else:
48-
resp.read()
49-
50-
result = {
51-
"status": {"code": resp.status_code, "message": resp.reason_phrase},
52-
"headers": _transform_headers(resp),
53-
"body": {"string": resp.content},
54-
}
55-
56-
# As the content wasn't decoded, we restore the response to a state which
57-
# will be capable of decoding the content for the consumer.
58-
del resp._decoder
59-
resp._content = resp._get_content_decoder().decode(resp.content)
41+
42+
if not hasattr(resp, "_decoder"):
43+
# Retrieve the content, but without decoding it.
44+
with patch.dict(resp.headers, {"Content-Encoding": ""}):
45+
if aread:
46+
await resp.aread()
47+
else:
48+
resp.read()
49+
50+
result = {
51+
"status": {"code": resp.status_code, "message": resp.reason_phrase},
52+
"headers": _transform_headers(resp),
53+
"body": {"string": resp.content},
54+
}
55+
56+
# As the content wasn't decoded, we restore the response to a state which
57+
# will be capable of decoding the content for the consumer.
58+
del resp._decoder
59+
resp._content = resp._get_content_decoder().decode(resp.content)
60+
else:
61+
# The content has already been read in by HTTPX. Record it without an Encoding header.
62+
with patch.dict(resp.headers, {"Content-Encoding": ""}):
63+
result = {
64+
"status": {"code": resp.status_code, "message": resp.reason_phrase},
65+
"headers": _transform_headers(resp),
66+
"body": {"string": resp.content},
67+
}
68+
6069
return result
6170

6271

@@ -174,7 +183,17 @@ def _sync_vcr_send(cassette, real_send, *args, **kwargs):
174183
return response
175184

176185
real_response = real_send(*args, **kwargs)
177-
asyncio.run(_record_responses(cassette, vcr_request, real_response, aread=False))
186+
187+
try:
188+
loop = asyncio.get_running_loop()
189+
except RuntimeError:
190+
loop = None
191+
192+
if loop is not None:
193+
loop.create_task(_record_responses(cassette, vcr_request, real_response, aread=False))
194+
else:
195+
asyncio.run(_record_responses(cassette, vcr_request, real_response, aread=False))
196+
178197
return real_response
179198

180199

0 commit comments

Comments
 (0)