Open
Description
Python 3.12.7
respx 0.21.1
The documentation includes both of the following examples for files
lookups:
respx.post("https://example.org/", files={"some_file": ANY})
respx.post("https://example.org/", files={"some_file": ("filename.txt", ANY)})
These don't actually work because since e670690, routes are compared via their hash()
, and adding a route triggers a comparison to existing routes. ANY
is unhashable, so any route containing it (at least in a files
lookup) is also unhashable. Here's a minimal test to demonstrate (but to be clear, the same thing happens with the tuple form if it contains an ANY
):
from unittest.mock import ANY
import respx
def test_example():
# This first one succeeds because there are no existing routes yet, so no comparisons happen.
respx.post("/path", files={"filename1": ANY})
# This one causes a hash error when a comparison to the existing route is attempted
respx.post("/path", files={"filename2": ANY})
Output:
F [100%]
=================================================================================================== FAILURES ===================================================================================================
_________________________________________________________________________________________________ test_example _________________________________________________________________________________________________
def test_example():
# This first one succeeds because there are no existing routes yet, so no comparisons happen.
respx.post("/path", files={"filename1": ANY})
# This one causes a hash error when a comparison to the existing route is attempted
> respx.post("/path", files={"filename2": ANY})
tests/test_example.py:10:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.12/site-packages/respx/api.py:81: in post
return mock.post(url, name=name, **lookups)
.venv/lib/python3.12/site-packages/respx/router.py:182: in post
return self.request(method="POST", url=url, name=name, **lookups)
.venv/lib/python3.12/site-packages/respx/router.py:164: in request
return self.route(method=method, url=url, name=name, **lookups)
.venv/lib/python3.12/site-packages/respx/router.py:132: in route
return self.add(route, name=name)
.venv/lib/python3.12/site-packages/respx/router.py:145: in add
route = self.routes.add(route, name=name)
.venv/lib/python3.12/site-packages/respx/models.py:480: in add
if route in self._routes:
.venv/lib/python3.12/site-packages/respx/models.py:149: in __eq__
return self.pattern == other.pattern
.venv/lib/python3.12/site-packages/respx/patterns.py:133: in __eq__
return hash(self) == hash(other)
.venv/lib/python3.12/site-packages/respx/patterns.py:130: in __hash__
return hash((self.__class__, self.lookup, self.value))
.venv/lib/python3.12/site-packages/respx/patterns.py:130: in __hash__
return hash((self.__class__, self.lookup, self.value))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <Files contains {'filename1': (<ANY>, <ANY>)}>
def __hash__(self):
> return hash((self.__class__, self.lookup, self._multi_items(self.value)))
E TypeError: unhashable type: '_ANY'
.venv/lib/python3.12/site-packages/respx/patterns.py:306: TypeError
=========================================================================================== short test summary info ============================================================================================
FAILED tests/test_example.py::test_example - TypeError: unhashable type: '_ANY'
1 failed in 0.18s
Note that this problem doesn't appear to strike when using ANY
with a params
lookup instead of files
, so however it's handled there may be applicable here.