Make mypy happy across Python versions

I’m using itertools.batched which was added in 3.12. I also want to support older python versions, so I’m doing this:

from __future__ import annotations

try:
    from itertools import batched
except ImportError:
    from itertools import islice
    from typing import Iterable, Iterator, TypeVar

    T = TypeVar("T")

    def batched(iterable: Iterable[T], n: int) -> Iterator[tuple[T, ...]]:  # type: ignore[no-redef]
        if n < 1:
            raise ValueError("n must be at least one")
        it = iter(iterable)
        while batch := tuple(islice(it, n)):
            yield batch

This passes on Python 3.12. But on earlier versions, I get mypy errors:

4: error: Module "itertools" has no attribute "batched"  [attr-defined]
11: error: Unused "type: ignore" comment  [unused-ignore]

Is it possible to make mypy ignore certain lines only for certain python versions?

mypy understands version checks: if sys.version_info >= (3, 12): would mean that the code inside the if block only executes on Python 3.12 or above.

So rather than doing a try except, you can do:

from __future__ import annotations

import sys

if sys.version_info >= (3, 12):
    from itertools import batched
else:
    from itertools import islice
    from typing import Iterable, Iterator, TypeVar

    T = TypeVar("T")

    def batched(iterable: Iterable[T], n: int) -> Iterator[tuple[T, ...]]:
        if n < 1:
            raise ValueError("n must be at least one")
        it = iter(iterable)
        while batch := tuple(islice(it, n)):
            yield batch
2 Likes