Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 190
Update types for h11 v0.13#526
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
7811c8b66644494207b8b3c46a89ca728c24de236c4347599ce5214171cc46d1ed1413668dce8f42eab92a10a0713b733be3c6335File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,16 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import enum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from types import TracebackType | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import AsyncIterable, AsyncIterator, List, Optional, Tuple, Type, Union | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AsyncIterable, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AsyncIterator, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Optional, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Tuple, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Union, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cast, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import h11 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @@ -17,15 +26,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from ..backends.base import AsyncNetworkStream | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .interfaces import AsyncConnectionInterface | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| H11Event = Union[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| h11.Request, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| h11.Response, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| h11.InformationalResponse, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| h11.Data, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| h11.EndOfMessage, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| h11.ConnectionClosed, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class HTTPConnectionState(enum.IntEnum): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NEW = 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @@ -127,14 +127,14 @@ async def _send_request_body(self, request: Request) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event = h11.Data(data=chunk) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._send_event(event, timeout=timeout) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event = h11.EndOfMessage() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._send_event(event, timeout=timeout) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._send_event(h11.EndOfMessage(), timeout=timeout) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def _send_event( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, event: H11Event, timeout: Optional[float] = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, event: h11.Event, timeout: Optional[float] = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bytes_to_send = self._h11_state.send(event) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._network_stream.write(bytes_to_send, timeout=timeout) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if bytes_to_send is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._network_stream.write(bytes_to_send, timeout=timeout) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Receiving the response... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @@ -168,12 +168,18 @@ async def _receive_response_body(self, request: Request) -> AsyncIterator[bytes] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif isinstance(event, (h11.EndOfMessage, h11.PAUSED)): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def _receive_event(self, timeout: Optional[float] = None) -> H11Event: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def _receive_event( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, timeout: Optional[float] = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Union[h11.Event, h11.PAUSED]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| while True: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with map_exceptions({h11.RemoteProtocolError: RemoteProtocolError}): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event = self._h11_state.next_event() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # The h11 type signature uses a private return type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event = cast( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Union[h11.Event, h11.NEED_DATA, h11.PAUSED], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._h11_state.next_event(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if event is h11.NEED_DATA: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if isinstance(event, h11.NEED_DATA): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+177
to
+182
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I worry how much this cast and isinstance will slow stuff down - as this is a hot loop
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ifTYPE_CHECKING: | |
| fromtyping_extensionsimportLiteral, Protocol, TypeAlias | |
| class_Sentinel(enum.Enum): | |
| PAUSED=enum.auto() | |
| NEED_DATA=enum.auto() | |
| _PausedType: TypeAlias=Literal[_Sentinel.PAUSED] | |
| _NeedDataType: TypeAlias=Literal[_Sentinel.NEED_DATA] | |
| _PAUSED: _PausedType=_Sentinel.PAUSED | |
| _NEED_DATA: _NeedDataType=_Sentinel.NEED_DATA | |
| class_NextEventType(Protocol): | |
| asyncdef__call__(self) ->Union[h11.Event, _PausedType, _NeedDataType]: | |
| ... | |
| else: | |
| _PausedType=_PAUSED=h11.PAUSED | |
| _NeedDataType=_NEED_DATA=h11.NEED_DATA | |
| _Sentinel=_NextEventType=object |
httpcore/httpcore/_async/http11.py
Lines 195 to 207 in 627db6c
| asyncdef_receive_event( | |
| self, timeout: Optional[float] =None | |
| ) ->Union[h11.Event, _PausedType]: | |
| # The h11 type signature uses a private return type | |
| next_event=cast(_NextEventType, self._h11_state.next_event) | |
| whileTrue: | |
| withmap_exceptions({h11.RemoteProtocolError: RemoteProtocolError}): | |
| event=next_event() | |
| ifeventis_NEED_DATA: | |
| data=awaitself._network_stream.read( | |
| self.READ_NUM_BYTES, timeout=timeout | |
| ) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,7 +1,16 @@ | ||||||
| import enum | ||||||
| import time | ||||||
| from types import TracebackType | ||||||
| from typing import Iterable, Iterator, List, Optional, Tuple, Type, Union | ||||||
| from typing import ( | ||||||
| Iterable, | ||||||
| Iterator, | ||||||
| List, | ||||||
| Optional, | ||||||
| Tuple, | ||||||
| Type, | ||||||
| Union, | ||||||
| cast, | ||||||
| ) | ||||||
| import h11 | ||||||
| @@ -17,15 +26,6 @@ | ||||||
| from ..backends.base import NetworkStream | ||||||
| from .interfaces import ConnectionInterface | ||||||
| H11Event = Union[ | ||||||
| h11.Request, | ||||||
| h11.Response, | ||||||
| h11.InformationalResponse, | ||||||
| h11.Data, | ||||||
| h11.EndOfMessage, | ||||||
| h11.ConnectionClosed, | ||||||
| ] | ||||||
| class HTTPConnectionState(enum.IntEnum): | ||||||
| NEW = 0 | ||||||
| @@ -127,14 +127,14 @@ def _send_request_body(self, request: Request) -> None: | ||||||
| event = h11.Data(data=chunk) | ||||||
| self._send_event(event, timeout=timeout) | ||||||
| event = h11.EndOfMessage() | ||||||
| self._send_event(event, timeout=timeout) | ||||||
| self._send_event(h11.EndOfMessage(), timeout=timeout) | ||||||
| def _send_event( | ||||||
| self, event: H11Event, timeout: Optional[float] = None | ||||||
| self, event: h11.Event, timeout: Optional[float] = None | ||||||
| ||||||
| self, event: h11.Event, timeout: Optional[float] =None | |
| self, event: H11SendEvent, timeout: Optional[float] =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.
👍 makes sense to me. Seems like we would need this with the overload for correct typing.
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.
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'll see if I can contribute that upstream
zaniebAug 26, 2022 •
edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
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.
Oof, this would actually be a pretty big change upstream as the following is not a valid overload:
@overloaddefsend(self, event: ConnectionClosed) ->None:
...
@overloaddefsend(self, event: Event) ->bytes:
...
defsend(self, event: Event) ->Optional[bytes]:h11/_connection.py:505: error: Overloaded function signatures 1 and 2 overlap with incompatible return types [misc]
We'd need to introduce a separate base type (like Event) that indicates a null return.
zaniebAug 26, 2022 •
edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
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'm also exploring a generic
SendType=TypeVar('SendType', None, bytes)
classEvent(ABC, Generic[SendType]):
...
classFoo(Event[bytes]):
...
classConnectionClosed(Event[None]):
...but this would break type-checks for any downstream library that uses Event without a value for the generic e.g.
h11/_state.py:192: error: Missing type parameters for generic type "Event" [type-arg]
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.
So I need to do this on uvicorn as well? 😞
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'm not sure if you do following release of python-hyper/h11#144 which updates that function's signature with narrowed return types.