Cryptic "object is not iterable" warning when __iter__ is incorrectly annotated.
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
One issue that has bitten me a couple times was when I incorrectly wrote def __iter__(self) -> Iterable[...] instead of def __iter__(self) -> Iterator[...]. With the former code mypy produces the warning object is not iterable [misc] and I could not figure out why that was the case for a while... until I learned my lesson and am making this bug report.
To Reproduce
Consider the code.
from typing import Iterable, Iterator
class Foo1:
def __iter__(self):
return iter((1, 2))
x01, x11 = Foo1()
class Foo2:
def __iter__(self) -> Iterable[int]:
return iter((1, 2))
x02, x12 = Foo2()
class Foo3:
def __iter__(self) -> Iterator[int]:
return iter((1, 2))
x03, x13 = Foo3()
Actual Behavior
This produces the warnings
a.py:4: error: Function is missing a type annotation [no-untyped-def]
a.py:13: error: "Foo2" object is not iterable [misc]
These warnings are ALL correct. However, "Foo2" object is not iterable is tricky to understand because it mislead the developer thinks that the __iter__ method is not enough and something else is missing, while the other two implementations without and with annotations are accepted.
Expected Behavior
Mypy should report the following error message instead, for the line with def __iter__.
a.py:10: error: The return type of "Foo2.__iter__" should be "Iterator" or one of its supertypes [misc]
And this check is enforced at runtime, e.g., returning a tuple from __iter__ crashes.
The error message is already being used for other cases, e.g. this
def a() -> types.GeneratorType:
yield 1
produces
a.py:1: error: The return type of a generator function should be "Generator" or one of its supertypes [misc]
Your Environment
- Mypy version used: 1.13, 1.14
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini(and other config files):disallow_untyped_defs = true - Python version used: 3.11, 3.12
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the Python reproducer in the issue with mypy 1.13 or 1.14, then locate the type-checking path for incorrectly annotated iter methods. Add coverage for the Foo2 case and make the diagnostic identify the invalid return annotation; done means the misleading object-is-not-iterable error is replaced while the valid Foo1 and Foo3 cases remain accepted.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100