[Bug] Dependency injection not working with inheritance
guacs opened this issue · comments
Describe the bug
The dependency injection does not work when the type of the argument is set as the protocol and not the actual implementation of the said protocol.
To Reproduce
from typing import Protocol
from sanic import Sanic, text
from sanic import Request
class ExampleServiceProtocol(Protocol):
def some_method(self) -> int:
...
class ExampleServiceImplementation(ExampleServiceProtocol):
def some_method(self) -> int:
return 1
def protocol_route(request: Request, example_service: ExampleServiceProtocol):
return text("ok")
def implemented_route(request: Request, example_service: ExampleServiceImplementation):
return text("ok")
def create_app() -> Sanic:
app = Sanic("sample-app")
app.add_route(protocol_route, "/protocol")
app.add_route(implemented_route, "/implemented")
example_service = ExampleServiceImplementation()
app.ext.dependency(example_service)
return app
In the above example, requests to /implemented
works without any issues, but requests to /protocol
results in the following error:
⚠️ 500 — Internal Server Error
==============================
protocol_route() missing 1 required positional argument: 'example_service'
TypeError: protocol_route() missing 1 required positional argument: 'example_service' while handling path /protocol
Expected behavior
The argument should be passed if there is an instance in the registered dependencies that is a subclass of the type specified in the route handler signature.
Environment (please complete the following information):
- OS: Ubuntu 20.04.6 LTS (via WSL2 version 1.1.3.0)
- Sanic version: Sanic 23.3.0; Routing 22.8.0
- Sanic Ext version: 23.3.0
Additional context
Of all the issues, this is the closest issue I found which might be related to it.
Not a bug. Injection requires the type to be registered.
To be more specific, when you use the higher level dependency
method, the type of the object is inspected. When that type is found as an annotation, it is injected. Something like this should work:
app.ext.add_dependency(
ExampleServiceProtocol,
lambda: example_service)
Sorry for the brevity. On my phone from PTO. Hope this helps.
Oh the solution you gave works perfectly! My bad for marking it as a bug. I just misunderstood how the API worked.
No worries. good luck 😎