context-manager-iterator (UP052)
Preview (since 0.16.10) · Related issues · View source
Derived from the pyupgrade linter.
Fix is sometimes available.
This rule is unstable and in preview. The --preview flag is required for use.
What it does
Checks for generator-based context managers annotated with Iterator or
AsyncIterator instead of Generator or AsyncGenerator.
Why is this bad?
contextlib.contextmanager and contextlib.asynccontextmanager require
generators, which support methods such as throw that are not guaranteed
by the iterator protocols. The iterator overloads of these decorators are
deprecated in typeshed.
Example
from collections.abc import Iterator
from contextlib import contextmanager
@contextmanager
def example() -> Iterator[int]:
yield 1
Use instead:
from collections.abc import Generator
from contextlib import contextmanager
@contextmanager
def example() -> Generator[int, None, None]:
yield 1
On Python 3.13 and later, the fix omits the default type arguments and uses
Generator[int] or AsyncGenerator[int].
Fix safety
The fix is unsafe because it changes the function's runtime annotations
and may add an import, introducing a new name in the module. For a generator
that returns a value, the fix uses object as the return type to accommodate
any return value.
Known limitations
The rule checks functions whose innermost decorator is a contextlib
context manager and whose bodies contain a yield or yield from.