Skip to content

constructors for builtin iterables such as list should accept objects with __getitem__(self, i: int, /) #15826

Description

@DetachHead

Code sample in basedpyright playground

fromcollections.abcimportSequenceclassFoo:
def__init__(self, value: Sequence[int]) ->None:
self.value=valuedef__getitem__(self, i: int):
returnself.value[i]
foo=Foo((1, 2, 3))
# works at runtimeprint(list(foo)) # pyright error: "Foo" is incompatible with protocol "Iterable[_T@list]"# works at runtimeforindex, valueinenumerate(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)forvalueinfoo:
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:

classHasGetItem[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:

fromcalendarimportday_nameforindex, day_nameinenumerate(day_name):
print(index, day_name)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions