Description
Bug Report
AbstractContextManager defines a __enter__
that returns self
- https://github.com/python/typeshed/blob/6a8d653a671925b0a3af61729ff8cf3f90c9c662/stdlib/contextlib.pyi#L42
- https://github.com/python/cpython/blob/5436d8b9c397c48d9b0d5f9d4ad5e1d5a5d500f6/Lib/contextlib.py#L25
But it's impossible to just inherit from contextlib.AbstractContextManager
and have the type of __enter__
be correctly assumed to be Self
, without a bit of boilerplate.
To Reproduce
class A(contextlib.AbstractContextManager):
pass
reveal_type(A().__enter__()) # should be Self but assumed to be Any
and mypy disallows writing
class B(contextlib.AbstractContextManager[Self]): # error: Self type is only allowed in annotations within class definition [misc]
pass
and doesn't issue a warning for this runtime error:
class C(contextlib.AbstractContextManager[C]):
pass
Full example here
https://mypy-play.net/?mypy=latest&python=3.11&gist=7e76e56be6c702005a7ffbb7846b69c2
Expected Behavior
Either Self
is allowed in the AbstractContextManager
parameter list, or the type vars work by default.
Actual Behavior
Errors. See the playground.
(Although pyright doesn't error when using Self in the parameter list, but it still wrongly infers Any
as the return of __enter__
)
Workaround
Repeat the class name, and repeat the __enter__
impelmentation
class E(contextlib.AbstractContextManager["E"]):
def __enter__(self) -> Self:
return self
Your Environment
- Mypy version used: 1.11.2
- Mypy command-line flags: n/a
- Python version used: 3.11