Skip to content

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.

Options

References