@@ -294,6 +294,31 @@ def __init__(self, http_error: HTTPError) -> None:
294294 message , request = http_error .request , response = http_error .response
295295 )
296296
297+ def __copy__ (self ):
298+ """The fact that ConjureHTTPError is a BaseException but its __init__
299+ has a different signature causes a subtle issue for shallow copying.
300+ During copy.copy(), __init__ will be called with args defined by
301+ BaseException.__reduce_, which corresponds to default __init__. Since
302+ they're inconsistent, what http_error receives is actually message,
303+ hence an error.
304+
305+ By defining a __copy__ method, we give instructions to the intepreter
306+ on how to reconstruct a ConjureHTTPError instance. Alternatively, we
307+ could also fix it by changing the _init__ signature of this class.
308+ Although cleaner, unfortunately it will be a breaking change.
309+ """
310+
311+ # Create a shell object without calling __init__
312+ new_obj = type (self ).__new__ (type (self ))
313+
314+ for attr , value in self .__dict__ .items ():
315+ setattr (new_obj , attr , value )
316+
317+ # Exception args are not actually a part of __dict__...
318+ new_obj .args = self .args
319+
320+ return new_obj
321+
297322 @property
298323 def cause (self ) -> Optional [HTTPError ]:
299324 """The wrapped ``HTTPError`` that was the direct cause of
0 commit comments