-
-
Notifications
You must be signed in to change notification settings - Fork 931
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 asgiref.typing instead of starlette.types #1374
Conversation
- `ASGISendEvent` - `ASGIReceiveEvent` - `WebSocketSendEvent` - `WebSocketReceiveEvent`
Most uses of `ASGIApp` become `ASGI3Application`. Starlette 0.12 updated to ASGI 3: https://www.starlette.io/release-notes/#0120
- `HTTPScope` - `LifespanScope` - `WebSocketScope` - `WWWScope`
Some `# type:ignore[index]` and `# type: ignore[typeddict-item]` comments are needed when indexing into `Scope` using keys not present in the asgiref types: - `scope["app"]` - `scope["auth"]` - `scope["path_params"]` - `scope["router"]` - `scope["session"]` - `scope["state"]` - `scope["user"]`
There was a simple syntax change needed. Now that the asgiref types are being used for events like `WebSocketSendEvent`, all keys will be there, so Starlette will never see conditions like `if "text" not in message`. Instead, the condition will be updated to `message.get("text") is None`, to check for `text=None` when text should have been provided.
These tests were failing because of a small change to `class Headers` in starlette/datastructures.py. The `headers` fields in the asgiref.typing `Scope` classes are `typing.Iterable[typing.Tuple[bytes, bytes]]`, but `starlette.datastructures.Headers._list` requires a list specifically. However, converting to a list with `self._list = list(scope["headers"])` raises a `KeyError` from `requests.datastructures.CaseInsensitiveDict`. The error is opaque, and the `TestClient` will be refactored for HTTPX anyway, so either `typing.cast()` or a `type:ignore[assignment]` comment work. There are several other non-parametrized `type: ignore` comments in the module, so a parametrized `type:ignore[assignment]` comment would be reasonable.
CI checks are passing, and the PR is now ready for review. Comments and suggestions welcome. |
asgiref types added to tests |
That's a well put together bit of work. Very neatly done. 😌 Having said that, I'm not sure about it yet. Can someone describe what we're gaining by switching to |
Thanks @tomchristie! 😄 It would be great to get some input from the other maintainers as well, as they're the ones who will be dealing with the types most often. From my perspective, the use of Starlette's types are broad: Lines 3 to 4 in 832bc85
In other words, For example, when instantiating a starlette/starlette/endpoints.py Lines 51 to 59 in 832bc85
We know
On the other hand, the greater specificity means type checking is more strict, hence the type narrowing and Either way, I enjoyed a chance to work broadly across the Starlette code, and I would be happy to help again in the future. |
It looks like we need to discuss this again, but I'm pretty much convinced to vendor Let's clean up the PRs we have around, and come back here after 0.19.1, and 0.20.0 are released. Check the milestone. |
Sounds good. I'll close this off for now. Vendoring We should make sure the other maintainers are on board though (encode/uvicorn#1209, encode/uvicorn#1305 (comment)). I think there's still more discussion needed. |
If you don't mind, I'd like to keep this open. 🙇 There's a lot of work that was done here, and in case there's a positive feedback from the others, the only work here would be to change the imports, and vendorizing |
I've been thinking about this... I don't think that adding I'm going to close this, and turn the issue this PR refers to into a discussion. Let's see what others have to say - I'd also like to read your opinion. |
Description
Resolves #1217
This PR will replace usage of the custom Starlette types with standard ASGI types from the asgiref package.
Changes
Changes are based on the suggestions from @Kludex in #1217 (comment).
Message
type usage toASGISendEvent
andASGIReceiveEvent
to match asgirefstarlette.types
to match asgirefASGIApp
->ASGI3Application
(Starlette 0.12 upgraded to ASGI 3)Receive
->ASGIReceiveCallable
Send
->ASGISendCallable
Scope
->HTTPScope | LifespanScope | WebSocketScope
asgiref>=3.4.0,<4
tosetup.py
(version matches Uvicorn, but with upper bound added)from starlette.types
->from asgiref.typing
starlette.types
tests/test_endpoints.py
tests/test_requests.py
tests/middleware/test_cors.py
tests/middleware/test_session.py
Notes
Event
andScope
instancesMany of the type errors were resolved by using the asgiref
TypedDict
classes for event and scope instances, instead of plain dicts.starlette/starlette/responses.py
Lines 161 to 170 in c3ba37c
Type narrowing
There are some
assert
statements added for type narrowing.starlette/starlette/endpoints.py
Lines 116 to 122 in c3ba37c
In these cases, the type checker thinks the object could be a broader type like
object
, and theassert
helps ensure that the type is correct.Scope
keysThere were a few
# type:ignore[index]
and# type: ignore[typeddict-item]
comments needed when indexing intoScope
using keys not present in the asgiref types:scope["app"]
scope["auth"]
scope["path_params"]
scope["router"]
scope["session"]
scope["state"]
scope["user"]
starlette/starlette/requests.py
Lines 151 to 156 in c3ba37c
In a future PR, we might consider setting up a
StarletteScope
datastructure that inherits fromTypedDict
or one of the asgirefScope
types to handle this.Related