33from __future__ import annotations
44
55import json
6- from collections import OrderedDict
7- from typing import Any , Iterator
86from unittest .mock import MagicMock
97
10- import pytest
8+ from multidict import CIMultiDict , CIMultiDictProxy
119
1210from together .error import (
13- TogetherException ,
11+ APIError ,
1412 AuthenticationError ,
1513 ResponseError ,
16- APIError ,
14+ TogetherException ,
1715)
1816
1917
20- class FakeMultiDictProxy :
21- """Simulates aiohttp's CIMultiDictProxy — not JSON serializable."""
22-
23- def __init__ (self , data : dict [str , str ]) -> None :
24- self ._data = data
25-
26- def __iter__ (self ) -> Iterator [str ]:
27- return iter (self ._data )
28-
29- def __len__ (self ) -> int :
30- return len (self ._data )
31-
32- def __getitem__ (self , key : str ) -> str :
33- return self ._data [key ]
34-
35- def __repr__ (self ) -> str :
36- return f"<FakeMultiDictProxy({ self ._data !r} )>"
37-
38-
3918class TestExceptionReprNonSerializable :
4019 """Verify __repr__ doesn't crash on non-JSON-serializable headers (issue #108)."""
4120
@@ -52,21 +31,28 @@ def test_repr_with_dict_headers(self) -> None:
5231 assert "test error" in result
5332
5433 def test_repr_with_multidict_proxy_headers (self ) -> None :
55- """CIMultiDictProxy-like headers must not crash repr (issue #108)."""
56- fake_headers = FakeMultiDictProxy (
57- {"Content-Type" : "application/json" , "X-Request-Id" : "abc" }
34+ """Real CIMultiDictProxy headers must not crash repr (issue #108)."""
35+ headers = CIMultiDictProxy (
36+ CIMultiDict (
37+ {"Content-Type" : "application/json" , "X-Request-Id" : "abc" }
38+ )
5839 )
5940 exc = TogetherException (
6041 message = "server error" ,
61- headers = fake_headers , # type: ignore[arg-type]
42+ headers = headers , # type: ignore[arg-type]
6243 http_status = 500 ,
6344 request_id = "req-456" ,
6445 )
65- # Before fix: TypeError: Object of type FakeMultiDictProxy
46+ # Before fix: TypeError: Object of type CIMultiDictProxy
6647 # is not JSON serializable
6748 result = repr (exc )
6849 assert "TogetherException" in result
6950 assert "server error" in result
51+ parsed = json .loads (result [len ("TogetherException(" ) + 1 : - 2 ])
52+ assert parsed ["headers" ] == {
53+ "Content-Type" : "application/json" ,
54+ "X-Request-Id" : "abc" ,
55+ }
7056
7157 def test_repr_with_none_headers (self ) -> None :
7258 """None headers (default) should work."""
@@ -110,12 +96,12 @@ def test_repr_output_is_valid_after_fix(self) -> None:
11096
11197 def test_subclass_repr_with_non_serializable_headers (self ) -> None :
11298 """Subclasses should also benefit from the fix."""
113- fake_headers = FakeMultiDictProxy ( {"X-Rate-Limit" : "100" })
99+ headers = CIMultiDictProxy ( CIMultiDict ( {"X-Rate-Limit" : "100" }) )
114100
115101 for ExcClass in (AuthenticationError , ResponseError , APIError ):
116102 exc = ExcClass (
117103 message = "subclass test" ,
118- headers = fake_headers , # type: ignore[arg-type]
104+ headers = headers , # type: ignore[arg-type]
119105 http_status = 429 ,
120106 )
121107 result = repr (exc )
0 commit comments