You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Extend contextmanager to asynccontextmanager (#11352)
Closes#9922
### Description
Extending the existing special case for `contextlib.contextmanager` to `contextlib.asynccontextmanager`. When used with `TypeVar` gives much better type.
## Test Plan
I hope I have included the unit test you need. My minimal reproduction is:
```
from contextlib import asynccontextmanager
from typing import AsyncGenerator, Type, TypeVar
R = TypeVar("R")
@asynccontextmanager
async def foo(
cls: Type[R],
) -> AsyncGenerator[R, None]:
yield cls()
async def bar() -> int:
async with foo(int) as foo_int:
return (
foo_int # error: Incompatible return value type (got "R", expected "int")
)
```
reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> contextlib.GeneratorContextManager[T`-1]"
39
+
40
+
with yield_id(1) as x:
41
+
reveal_type(x) # N: Revealed type is "builtins.int*"
42
+
43
+
f = yield_id
44
+
def g(x, y): pass
45
+
f = g # E: Incompatible types in assignment (expression has type "Callable[[Any, Any], Any]", variable has type "Callable[[T], GeneratorContextManager[T]]")
46
+
[typing fixtures/typing-medium.pyi]
47
+
[builtins fixtures/tuple.pyi]
48
+
49
+
[case testAsyncContextManagerWithGenericFunction]
50
+
# flags: --python-version 3.7
51
+
from contextlib import asynccontextmanager
52
+
from typing import TypeVar, AsyncIterator
53
+
54
+
T = TypeVar('T')
55
+
56
+
@asynccontextmanager
57
+
async def yield_id(item: T) -> AsyncIterator[T]:
58
+
yield item
59
+
60
+
reveal_type(yield_id) # N: Revealed type is "def [T] (item: T`-1) -> typing.AsyncContextManager[T`-1]"
61
+
62
+
async with yield_id(1) as x:
63
+
reveal_type(x) # N: Revealed type is "builtins.int*"
0 commit comments