Missing autocompletion for request.app #7945
-
|
Describe the bug Is it maybe due to missing type hints? Or because the request instance is from Starlette and cannot be annotated in FastAPI? To Reproduce
from fastapi import FastAPI
from starlette.requests import Request
app = FastAPI()
@app.get('/')
def get(request: Request):
request.app
Expected behavior Screenshots Environment:
Additional context |
Beta Was this translation helpful? Give feedback.
Replies: 17 comments
-
|
It isn't working because has typehint |
Beta Was this translation helpful? Give feedback.
-
|
So would it be possible to have this Request object as a subclassed object in FastAPI where we can change the type annotation? |
Beta Was this translation helpful? Give feedback.
-
|
I think more correct will create issue in starlette |
Beta Was this translation helpful? Give feedback.
-
|
@tiangolo @dmontagu Would you be willing to accept a PR where we subclass the Starlette objects so that we can benefit from the type annotations in the A straightforward example would be: Another candidates apart from I am asking because this would also involve rewriting a couple of the documentation pages. |
Beta Was this translation helpful? Give feedback.
-
class FastAPIRequest(Request):
app: FastAPIThen use If this didn't work you could do something like the following which definitely would work (maybe requiring some minor tweaks to get mypy to like it): if typing.TYPE_CHECKING:
class FastAPIRequest(Request):
app: FastAPI
else:
FastAPIRequest = Request
|
Beta Was this translation helpful? Give feedback.
-
|
I am fine with only making these changes in my own project, @dmontagu. I just have trouble to understand how a better annotation in Starlette would help FastAPI. My assumption is that properties or methods that are only available in FastAPI cannot be made available via type annotations in Starlette (?). |
Beta Was this translation helpful? Give feedback.
-
|
That's right, but what properties or methods do you want to use that are only available in FastAPI? If there are important ones to support then I think it would make sense to try to address this. Usually the base Starlette ones are enough though, at least in my experience. |
Beta Was this translation helpful? Give feedback.
-
|
The ones that are not present in Starlette seem at least these to me: The ones I tried to access were |
Beta Was this translation helpful? Give feedback.
-
|
Is there a reason you couldn't access them on the app directly though? For example, adapting your initial example, let' say you wanted to return the from fastapi import FastAPI
from starlette.requests import Request
app = FastAPI()
@app.get('/')
def get(request: Request):
return request.app.docs_urlI agree it's annoying you don't get completion, but it seems to me you should just be using the from fastapi import FastAPI
from starlette.requests import Request
app = FastAPI()
@app.get('/')
def get(request: Request):
return app.docs_urlThat would give you access to the autocompletion you want. I think it could make sense to make it easier to get autocompletion for |
Beta Was this translation helpful? Give feedback.
-
|
Also, just to give an example, this is what I mean by subclassing to get autocompletion: class MyServerState:
database: Database
cache: Optional[FanoutCache]
orm: MyORM
search: SearchEngine
def __init__(self, database: Database, cache: FanoutCache = None) -> None:
self.database = database
self.cache = cache
self.orm = MyORM(self.database, self.cache)
self.search = SearchEngine(self.orm)
class MyServer(FastAPI):
state: MyServerState # type: ignore[assignment]
def setup_state(self, database: Database, cache: FanoutCache = None) -> None:
self.state = MyServerState(database, cache)
class MyRequest(Request):
app: MyServer |
Beta Was this translation helpful? Give feedback.
-
|
I understood the subclassing approach and will also follow it. I thought it might be a good idea to suggest this auto-completion improvement to have it for other users, as well. If that's not the case, feel free to close the issue. |
Beta Was this translation helpful? Give feedback.
-
|
I go back and forth; either way I'd be interested in @tiangolo's opinion on this. |
Beta Was this translation helpful? Give feedback.
-
|
It seems like the starlette people are not changing their implementation cf. Kludex/starlette#688. |
Beta Was this translation helpful? Give feedback.
-
|
The first thing would be, why do you want to access the app through the request? Maybe if we understand the use case better we can find the right solution for it. I think I can imagine a use case where it would be better to access the app through the request rather than directly as @dmontagu says. About accessing About About types for the TestClient, I think it's better to wait until the TestClient is based on HTTPX, to not lose that effort. Also, that itself might solve the problem. |
Beta Was this translation helpful? Give feedback.
-
|
I had two use cases for accessing fields of the
if any(browser in user_agent for browser in BROWSERS):
return RedirectResponse(url=request.app.docs_url)
return RedirectResponse(url=request.app.openapi_url)This would be solved by your suggestion to extract these values into a settings object.
I guess your same suggestion would apply here. I am fine with that and I missed the proposed options when creating the issue. |
Beta Was this translation helpful? Give feedback.
-
|
Great! Thanks for replying back @chbndrhnns . Then I think we can close this issue, right? |
Beta Was this translation helpful? Give feedback.
-
|
Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs. |
Beta Was this translation helpful? Give feedback.

The first thing would be, why do you want to access the app through the request?
Maybe if we understand the use case better we can find the right solution for it.
I think I can imagine a use case where it would be better to access the app through the request rather than directly as @dmontagu says.
About accessing
docs_urlandopenapi_url, if you need to use that in other parts of your code, maybe it would be a better idea to put them in a Pydantic'sBaseSettingsthat you can use everywhere.About
dependency_overrides, why would you want to access it in a path operation?About types for the TestClient, I think it's better to wait until the TestClient is based on HTTPX, to not lose that eff…