Skip to content

Commit 54f0c50

Browse files
authored
Merge branch 'main' into git-metadata-regression-py-0.23.0
2 parents 216469e + db9f564 commit 54f0c50

1 file changed

Lines changed: 47 additions & 1 deletion

File tree

py/src/braintrust/conftest.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ def _patch_vcr_aiohttp_stubs():
3232
See: https://github.com/kevin1024/vcrpy/issues/927
3333
"""
3434
try:
35+
from aiohttp import streams
36+
37+
# VCR.py imports this aiohttp internals symbol at module import time, but
38+
# newer aiohttp releases removed it. Provide a no-op compatibility shim
39+
# before importing vcr.stubs.aiohttp_stubs so test collection does not fail.
40+
if not hasattr(streams, "AsyncStreamReaderMixin"):
41+
setattr(streams, "AsyncStreamReaderMixin", object)
42+
3543
from vcr.stubs import aiohttp_stubs
3644
except ImportError:
3745
return
@@ -41,17 +49,55 @@ def _patch_vcr_aiohttp_stubs():
4149

4250
import asyncio
4351
import gzip
52+
import inspect
4453

45-
from aiohttp import ClientConnectionError, streams
54+
from aiohttp import ClientConnectionError, ClientResponse, streams
55+
from aiohttp.helpers import TimerNoop
4656

4757
def _decompress_body(body):
4858
"""Decompress gzip body if needed."""
4959
if body and body[:2] == b"\x1f\x8b":
5060
return gzip.decompress(body)
5161
return body
5262

63+
if "stream_writer" in inspect.signature(ClientResponse.__init__).parameters:
64+
# aiohttp 3.13 added a required stream_writer keyword argument to
65+
# ClientResponse.__init__. VCR.py's MockClientResponse still calls the
66+
# older constructor, so patch it before any cassette playback builds one.
67+
class _MockStreamWriter:
68+
output_size = 0
69+
70+
def patched_response_init(self, method, url, request_info=None):
71+
super(aiohttp_stubs.MockClientResponse, self).__init__(
72+
method=method,
73+
url=url,
74+
writer=None,
75+
continue100=None,
76+
timer=TimerNoop(),
77+
request_info=request_info,
78+
traces=[],
79+
loop=asyncio.get_event_loop(),
80+
session=None,
81+
stream_writer=_MockStreamWriter(),
82+
)
83+
84+
aiohttp_stubs.MockClientResponse.__init__ = patched_response_init
85+
5386
aiohttp_stubs.MockStream.set_exception = lambda self, exc: None
5487

88+
if not hasattr(aiohttp_stubs.MockStream, "iter_chunked"):
89+
# Older aiohttp exposed iter_chunked via AsyncStreamReaderMixin. Since
90+
# that mixin is gone, VCR.py's MockStream needs the method directly for
91+
# clients that consume aiohttp responses through chunked iteration.
92+
async def iter_chunked(self, n):
93+
while True:
94+
chunk = await self.read(n)
95+
if not chunk:
96+
break
97+
yield chunk
98+
99+
aiohttp_stubs.MockStream.iter_chunked = iter_chunked
100+
55101
async def patched_text(self, encoding="utf-8", errors="strict"):
56102
return _decompress_body(self._body).decode(encoding, errors=errors)
57103

0 commit comments

Comments
 (0)