Annotate sync/async code via Generic | generic TypeVar / Type aliases in Generic
未关闭
还没有人认领这个 Issue。
topic: feature
- 主要语言
- Python
- 星标
- 1.8k
- 派生
- 302
- 平均合并
- 23 小时
- 30 天内合并 PR
- 8
描述
Consider this case:
import asyncio
from typing import Any, Coroutine, Generic, TypeVar
from httpx import AsyncClient, Client, Response
ClientT = TypeVar("ClientT", bound=Client | AsyncClient)
class API(Generic[ClientT]):
client: ClientT
def __init__(self, client: ClientT) -> None:
self.client = client
def get_items(self) -> Response | Coroutine[Any, Any, Response]:
return self.client.request('get', 'https://example.com/api/v1/get_items')
response = API[Client](Client()).get_items()
response.json() # Item "Coroutine[Any, Any, Response]" of "Union[Response, Coroutine[Any, Any, Response]]" has no attribute "json" [union-attr]
response_coroutine = API[AsyncClient](AsyncClient()).get_items()
asyncio.run(response_coroutine) # Argument 1 to "run" has incompatible type "Union[Response, Coroutine[Any, Any, Response]]"; expected "Awaitable[Response]" [arg-type]mypy(error)
How can I express bound between ClientT and return type of API().get_items()?
How it could look like if Generic would support type aliases or TypeVar supported another type variables:
import asyncio
from typing import Annotated, Any, Awaitable, Coroutine, Generic, TypeVar
from typing_extensions import reveal_type
from httpx import AsyncClient, Client, Response
ClientT = TypeVar("ClientT", bound=Client | AsyncClient)
T = TypeVar("T")
# Using Annotated just as generic type that returns its argument as is
Sync = Annotated[T, ...]
MightBeAwaitable = TypeVar("MightBeAwaitable", bound=Awaitable | Sync)
# or MightBeAwaitable = Awaitable | Sync
class API(Generic[ClientT, MightBeAwaitable):
client: ClientT
def __init__(self, client: ClientT) -> None:
self.client = client
def get_items(self) -> MightBeAwaitable[Response]: # TypeError: 'TypeVar' object is not subscriptable
return self.client.request('get', 'https://example.com/api/v1/get_items')
response = API[Client, Sync](Client()).get_items()
reveal_type(response) # Revealed type is "Response"
response_coroutine = API[AsyncClient, Awaitable](AsyncClient()).get_items()
reveal_type(response_coroutine) # Revealed type is "typing.Awaitable[Any]"
Sorry if it's the wrong place/type for this issue.
贡献指南
这个仓库没有索引到贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从此 issue 中的 Python 示例及其使用的类型构造开始:Generic、TypeVar、类型别名、Annotated、Awaitable 和 Coroutine。确定客户端类型与 get_items() 返回类型之间的预期关系,然后记录一种受支持的类型设计及其预期显示类型。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python
- 领域
- developer-experience
- Issue 类型
- 功能
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 停滞
- 描述清晰度
- 需要澄清
- 新手友好度
- 20/100