Annotate sync/async code via Generic | generic TypeVar / Type aliases in Generic
オープン
まだ誰も着手していません。
topic: feature
- 主要言語
- Python
- スター
- 1.8k
- フォーク
- 302
- 平均マージ
- 23時間
- マージ済み PR(30日)
- 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 にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
この issue の Python 例と、それらが使用している型付け構造(Generic、TypeVar、型エイリアス、Annotated、Awaitable、Coroutine)から始めてください。client の型と get_items() の戻り値の型の意図された関係を確認し、サポートされる型付け設計と、想定される表示型を文書化してください。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- developer-experience
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 20/100