Code sample in basedpyright playground
from collections.abc import Sequence
class Foo:
def __init__(self, value: Sequence[int]) -> None:
self.value = value
def __getitem__(self, i: int):
return self.value[i]
foo = Foo((1, 2, 3))
# works at runtime
print(list(foo)) # pyright error: "Foo" is incompatible with protocol "Iterable[_T@list]"
# works at runtime
for index, value in enumerate(foo): # pyright error: "Foo" is incompatible with protocol "Iterable[_T@list]"
print(f"{index=}, {value=}")
# works at runtime. objects with `__getitem__` are iterable (as long as `__getitem__` accepts `int`s)
for value in foo:
print(value)
i'm not sure if there's an existing protocol just for __getitem__, but if not, there probably should be. perhaps something like this:
class HasGetItem[K, V](Protocol):
def __getitem__(self, index: K) -> V: ...
type AnyIterable[T] = Iterable[T] | HasGetItem[int, T]
real world example
i bumped pyright to 1.1.410 and now it reports errors on code that enumerates calendar.day_name, due to #15738:
from calendar import day_name
for index, day_name in enumerate(day_name):
print(index, day_name)
Code sample in basedpyright playground
i'm not sure if there's an existing protocol just for
__getitem__, but if not, there probably should be. perhaps something like this:real world example
i bumped pyright to 1.1.410 and now it reports errors on code that enumerates
calendar.day_name, due to #15738: