Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unittest.mock.ANY is unusable in a files lookup #276

Open
mikenerone opened this issue Nov 15, 2024 · 0 comments
Open

unittest.mock.ANY is unusable in a files lookup #276

mikenerone opened this issue Nov 15, 2024 · 0 comments

Comments

@mikenerone
Copy link

mikenerone commented Nov 15, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant