-
-
Notifications
You must be signed in to change notification settings - Fork 953
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
Use mypy strict
#2180
Use mypy strict
#2180
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Just a few small comments
Please fix errors |
This is still WIP, I'm doing it in small parts to avoid having a single big commit |
Ok no worries, I’ll just remove the approval until you’re ready |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing approval until this is marked as ready for review
"ImmutableMultiDict", | ||
typing.Mapping, | ||
"ImmutableMultiDict[typing.Any, typing.Any]", | ||
typing.Mapping[typing.Any, typing.Any], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the signature of the ImmutableMultiDict
's __init__
method:
class ImmutableMultiDict(typing.Mapping[_KeyType, _CovariantValueType]):
_dict: typing.Dict[_KeyType, _CovariantValueType]
def __init__(
self,
*args: typing.Union[
"ImmutableMultiDict[_KeyType, _CovariantValueType]",
typing.Mapping[_KeyType, _CovariantValueType],
typing.Iterable[typing.Tuple[_KeyType, _CovariantValueType]],
],
**kwargs: typing.Any,
) -> None:
We should parametrize these ones as [str, str]
, but the following happens a few lines underneath:
self._list = [(str(k), str(v)) for k, v in self._list]
self._dict = {str(k): str(v) for k, v in self._dict.items()}
starlette/templating.py
Outdated
directory: typing.Union[ | ||
str, PathLike, typing.Sequence[typing.Union[str, PathLike]] | ||
], | ||
directory: "typing.Union[str, PathLike[typing.AnyStr], typing.Sequence[typing.Union[str, PathLike[typing.AnyStr]]]]", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is PathLike[AnyStr]
fine? Or we could enforce str paths. I often see PathLike[Any]
but doesn't feel right to me as PathLike
is generic wrt TypeVar("AnyStr_co", str, bytes, covariant=True)
@Viicos Do you need any help here? |
Hi @Kludex thanks for asking. The main blocking point is handling callables and coroutines together, as stated in #2180 (comment). The solution I provide should work but isn't pretty, and will add a lot of overhead to the code (considering this pattern is used a lot in the Apart from that I'll be able to fix the remaining |
|
Will be ready for review by the end of the week, as I can see |
Looks like the overrides from mypy is not working properly? 🤔 |
starlette/testclient.py:383: error: Name "httpx._client.CookieTypes" is not defined [name-defined]
...
starlette/testclient.py:699: error: Name "httpx._client.TimeoutTypes" is not defined [name-defined]
Lines 68 to 71 in 1be57fd
This one has no effect, |
@@ -23,10 +29,14 @@ def requires( | |||
scopes: typing.Union[str, typing.Sequence[str]], | |||
status_code: int = 403, | |||
redirect: typing.Optional[str] = None, | |||
) -> typing.Callable[[_CallableType], _CallableType]: | |||
) -> typing.Callable[ | |||
[typing.Callable[_P, typing.Any]], typing.Callable[_P, typing.Any] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for not using the following?
[typing.Callable[_P, typing.Any]], typing.Callable[_P, typing.Any] | |
[typing.Callable[_P, _T]], typing.Callable[_P, _T] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't make it work as it can be async or sync (same issue as #2180 (comment)) :/
starlette/routing.py
Outdated
@@ -773,7 +783,7 @@ def host( | |||
def add_route( | |||
self, | |||
path: str, | |||
endpoint: typing.Callable, | |||
endpoint: typing.Callable[..., typing.Any], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't an endpoint always Callable[[Request], typing.Any]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went for Callable[..., Any]
as this endpoint
argument is passed to routing.Route
, which is doing the following:
starlette/starlette/routing.py
Lines 209 to 234 in 2168e47
def __init__( | |
self, | |
path: str, | |
endpoint: typing.Callable, | |
*, | |
methods: typing.Optional[typing.List[str]] = None, | |
name: typing.Optional[str] = None, | |
include_in_schema: bool = True, | |
) -> None: | |
assert path.startswith("/"), "Routed paths must start with '/'" | |
self.path = path | |
self.endpoint = endpoint | |
self.name = get_name(endpoint) if name is None else name | |
self.include_in_schema = include_in_schema | |
endpoint_handler = endpoint | |
while isinstance(endpoint_handler, functools.partial): | |
endpoint_handler = endpoint_handler.func | |
if inspect.isfunction(endpoint_handler) or inspect.ismethod(endpoint_handler): | |
# Endpoint is function or method. Treat it as `func(request) -> response`. | |
self.app = request_response(endpoint) | |
if methods is None: | |
methods = ["GET"] | |
else: | |
# Endpoint is a class. Treat it as ASGI. | |
self.app = endpoint |
So it seems endpoint
can also be a ASGIApp
(+ there's a bunch of things related to functools.partial
)
starlette/routing.py
Outdated
self, path: str, endpoint: typing.Callable, name: typing.Optional[str] = None | ||
self, | ||
path: str, | ||
endpoint: typing.Callable[..., typing.Any], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't an endpoint always Callable[[WebSocket], typing.Any]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #2180 (comment) (same for #2180 (comment), #2180 (comment) if I'm not mistaken)
self, path: str, endpoint: typing.Callable, *, name: typing.Optional[str] = None | ||
self, | ||
path: str, | ||
endpoint: typing.Callable[..., typing.Any], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as comments below.
@@ -209,7 +209,7 @@ class Route(BaseRoute): | |||
def __init__( | |||
self, | |||
path: str, | |||
endpoint: typing.Callable, | |||
endpoint: typing.Callable[..., typing.Any], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as comments below.
handler: typing.Optional[ | ||
typing.Callable[[Request, Exception], typing.Any] | ||
] = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this supposed to be ExceptionHandler
as well? It's a question, not a suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it is, this was discussed earlier: #2180 (comment). We could keep it as Any
, or use Union[Reponse, Awaitable[Response]]
and then add some casts or type: ignore
Suggestions on what to do here? 😅 It looks like we are blocked by python/mypy#10045? |
I guess so. Maybe we could edit the |
I've asked on the |
In the meanwhile, I'll see if using a |
@Kludex let me know if the check script tweak is ok 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Viicos 🙏
Because his request for change was actually a dismissal of his previous approval
Fixes #2153.
mypy
config updated:no_implicit_optional
is now the default (and seems to have been replaced byimplicit_optional
)disallow_untyped_defs
is included bystrict
Checklist