pylint-dev/astroid

false not-an-iterable for __truediv__ with @overload

Opened this issue · 2 comments

Steps to reproduce

from dataclasses import dataclass
from typing import Any, Iterable, Iterator, overload


@dataclass
class MyIterable(Iterable[int]):

    def __iter__(self) -> Iterator[int]:
        for n in range(1, 10):
            yield n


@dataclass
class IterableMaker():
    @overload
    def __truediv__(self, right: bool) -> bool:
        ...

    @overload
    def __truediv__(self, right: str) -> MyIterable:
        ...

    def __truediv__(self, right: Any):
        if isinstance(right, bool):
            return right
        return MyIterable()


for sensor in IterableMaker() / 'thing':
    print(sensor)

Current behavior

E1133: Non-iterable value IterableMaker() / 'thing' is used in an iterating context (not-an-iterable)

Expected behavior

No error.

python -c "from astroid import __pkginfo__; print(__pkginfo__.version)" output

3.2.2

I'd hoped this was fixed by #1015, but alas no.

It is specific to __truediv__.

I see something similar with:

from typing import overload, Iterator, Union


class Sequence:

    def __init__(self, data: list[str]) -> None:
        self._data = data

    @overload
    def __getitem__(self, idx: int) -> str:
        ...

    @overload
    def __getitem__(self, idx: slice) -> "Sequence":
        ...

    def __getitem__(self, idx: Union[int, slice]) -> Union[str, "Sequence"]:
        if isinstance(idx, slice):
            return self.__class__(*self._data[idx])
        else:
            return self._data[idx]


s = Sequence(["a", "b"])
print(s[0].upper())

where pylint complains: E1101: Instance of 'Sequence' has no 'upper' member (no-member)

For my real code (implementation, usage) this only started happening with pylint 3.2.1 and astroid 3.2.2 (but not 3.1.x). However, the minimal example seems to show the error even in older versions.