I have a function in my app which look like:
def get_firebase_user(session: Session, firebase_user: FirebaseUser) -> users.User | None:
if some_condition:
return user_instance
And I have an utility module with basic functionality, so I decided to put function which throws an exception if model is None in this module. It's look like:
def throw_none_exception(inst, detail: str) -> None:
"""Throm exception with given detail if instance is None."""
if inst is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=detail,
)
And whole problem in my linter. If we declaring models with first function and raising errors with second. In this way of working linter can't detect how models changes so in code like:
user = get_firebase_user(session, firebase_user)
throw_none_exception(user, "Such user doesn't exists")
if user.id == some_random_id:
return 'You are the luckiest person i\'ve ever seen'
It returns me error
Item "None" of "Optional[User]" has no attribute "id"
Which is pretty annoying:) How can I re declare type of this model? Or how manage to do it with another way so linter won't give an error?
Here's a way to define throw_none_exception
in such a way that it transforms inst
to a non-Optional type:
from typing import TypeVar, Optional
_T = TypeVar("_T")
def throw_none_exception(inst: Optional[_T], detail: str) -> _T:
"""Throw exception with given detail if instance is None."""
if inst is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=detail,
)
return inst
Now if you do:
user = throw_none_exception(
get_firebase_user(session, firebase_user),
"Such user doesn't exists"
)
user
will have a non-Optional type and you should be able to access user.id
without typechecking errors.