Skip to content

Make typing.Coroutine a protocol - #16419

Merged
AlexWaygood merged 1 commit into
mainfrom
alex/coro-proto
Sep 21, 2026
Merged

AlexWaygood merged 1 commit into
mainfrom
alex/coro-proto

Conversation

@AlexWaygood

@AlexWaygood AlexWaygood commented Sep 20, 2026

Copy link
Copy Markdown
Member

This was in the original diff for #10816 but got removed before the PR was merged -- it looks like the removal might have been an accidental change as part of a merge commit. At runtime isinstance() checks against this class use duck-typing, and we already have typing.Generator as a protocol:

>>> class MyCoro:
...     def __await__(self): ...
...     def throw(self): ...
...     def send(self): ...
...     def close(self): ...
...
>>> from collections.abc import Coroutine
>>> isinstance(MyCoro(), Coroutine)
True

@github-actions

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/utilities/asyncutils/__init__.py:361: error: Incompatible return value type (got "_Wrapped[P, Coroutine[Any, Any, Any], [VarArg(Any), DefaultNamedArg(bool | None, '_sync'), KwArg(Any)], Coroutine[Any, Any, Any]]", expected "Callable[P, R? | Coroutine[Any, Any, R?]]")  [return-value]
+ src/prefect/utilities/asyncutils/__init__.py:361: error: Incompatible return value type (got "_Wrapped[P, Coroutine[Any, Any, R?], [VarArg(Any), DefaultNamedArg(bool | None, '_sync'), KwArg(Any)], Coroutine[Any, Any, R?]]", expected "Callable[P, R? | Coroutine[Any, Any, R?]]")  [return-value]
- src/prefect/utilities/asyncutils/__init__.py:361: note: "_Wrapped[P, Coroutine[Any, Any, Any], [VarArg(Any), DefaultNamedArg(bool | None, '_sync'), KwArg(Any)], Coroutine[Any, Any, Any]].__call__" has type "def __call__(*args: Any, _sync: bool | None = ..., **kwargs: Any) -> Coroutine[Any, Any, Any]"
+ src/prefect/utilities/asyncutils/__init__.py:361: note: "_Wrapped[P, Coroutine[Any, Any, R?], [VarArg(Any), DefaultNamedArg(bool | None, '_sync'), KwArg(Any)], Coroutine[Any, Any, R?]].__call__" has type "def __call__(*args: Any, _sync: bool | None = ..., **kwargs: Any) -> Coroutine[Any, Any, R?]"

@AlexWaygood
AlexWaygood marked this pull request as ready for review September 20, 2026 19:28
Comment thread stdlib/typing.pyi
Comment on lines -607 to -608
__name__: str
__qualname__: str

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these aren't required for an isinstance() check to pass at runtime, and I don't think __name__ or __qualname__ attributes are really relevant to the abstract idea of what it means for a nominal class (like types.CoroutineType) to be coroutine-like. So I don't think it's appropriate for them to be listed here.

types.CoroutineType, the concrete, nominal type returned by async def functions at runtime, should have these attributes, of course, and still does on this branch:

typeshed/stdlib/types.pyi

Lines 428 to 431 in 57035b1

@final
class CoroutineType(Coroutine[_YieldT_co, _SendT_nd_contra, _ReturnT_nd_co]):
__name__: str
__qualname__: str

@AlexWaygood
AlexWaygood merged commit 97dbe07 into main Sep 21, 2026
88 checks passed
@AlexWaygood
AlexWaygood deleted the alex/coro-proto branch September 21, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants