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

Overriding does not work with non-primitive type objects in Litestar #122

Closed
nightblure opened this issue Nov 19, 2024 · 3 comments · Fixed by #123
Closed

Overriding does not work with non-primitive type objects in Litestar #122

nightblure opened this issue Nov 19, 2024 · 3 comments · Fixed by #123
Labels
bug Something isn't working litestar

Comments

@nightblure
Copy link
Contributor

I found a new test case. This is more of a Litestar problem, but still

Non-primitive objects cannot be overridden with any other type until we mark it with the Any annotation. Below is the code that will help reproduce this


class and container:

class SomeService:
    def do_smth(self) -> str:
        return "something"


class DIContainer(BaseContainer):
    bool_fn = providers.Factory(bool_fn, value=False)
    str_fn = providers.Factory(str_fn)
    list_fn = providers.Factory(list_fn)
    int_fn = providers.Factory(int_fn)
    some_service = providers.Factory(SomeService)

controller handler:

    @get(path="mock_overriding", dependencies={"some_service": Provide(DIContainer.some_service)})
    # does not works with some_service: SomeService type, but works with some_service: SomeService | Any
    async def mock_overriding_endpoint_handler(self, some_service: SomeService) -> dict[str, typing.Any]:
        return {"object": some_service.do_smth()}

test:

def test_litestar_endpoint_with_mock_overriding() -> None:
    some_service_mock = Mock(do_smth=lambda: "mock func")

    with DIContainer.some_service.override_context(some_service_mock), TestClient(app=app) as client:
        response = client.get("/router/controller/mock_overriding")

    assert response.json()["object"] == "mock func"

error:

TypeError: Unsupported type: <class 'unittest.mock.Mock'>
msgspec.ValidationError: Unsupported type: <class 'unittest.mock.Mock'> - at `$.some_service`
@lesnik512 lesnik512 added bug Something isn't working litestar labels Nov 19, 2024
@lesnik512
Copy link
Member

lesnik512 commented Nov 19, 2024

@nightblure Found another hack here litestar-org/litestar#2597 (comment)

Can be fixed by adding Dependency(skip_validation=True) like this:

@get(path="mock_overriding", dependencies={"some_service": Provide(DIContainer.some_service)})
async def mock_overriding_endpoint_handler(self, some_service: typing.Annotated[SomeService, Dependency(skip_validation=True)]) -> dict[str, typing.Any]:
    return {"object": some_service.do_smth()}

I think we need to document this behaviour and that's it. What do you think?

@nightblure
Copy link
Contributor Author

@lesnik512
It doesn't look that convenient, but it's good that it works

I can add this to the documentation with examples and tests

@lesnik512
Copy link
Member

@nightblure would be great 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working litestar
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants