Use positional only arguments for dunder methods in collections.abc
Currently, some dunder methods like Sequence.__getitem__ do not use positional-only arguments, which causes errors when trying to subclass with positional-only arguments. Therefore, dunder methods, especially operators like __getitem__, that are typically not called using keyword arguments, should probably be annotated using positional only arguments in the stubs.
Code sample in pyright playground
from typing import Protocol, Self, overload, Literal
class SupportsSequenceGetitemA[T](Protocol):
@overload
def __getitem__(self, index: int) -> T: ...
@overload
def __getitem__(self, index: slice) -> "SupportsSequenceGetitemA[T]": ...
class MySequenceA[T](SupportsSequenceGetitemA[T], Protocol):
@overload
def __getitem__(self, index: int, /) -> T: ...
@overload
def __getitem__(self, index: slice, /) -> Self: ... # ❌
class SupportsSequenceGetitemB[T](Protocol):
@overload
def __getitem__(self, index: int, /) -> T: ...
@overload
def __getitem__(self, index: slice, /) -> "SupportsSequenceGetitemB[T]": ...
class MySequenceB[T](SupportsSequenceGetitemB[T], Protocol):
@overload
def __getitem__(self, index: int, /) -> T: ...
@overload
def __getitem__(self, index: slice, /) -> Self: ... # ✅
While I do agree that these should be positional only, this should be done in CPython first. If the Python maintainers agree that this is a good idea, we can implement it in typeshed – and I'd be okay to do this for all Python versions in typeshed.
This is different with mypy. In mypy, dunder methods are implicitly positional-only, and your example type-checks without errors as is. I'm tempted to say that mypy is correct here, and this is a pyright problem, but I don't feel very strongly about it.
I opened https://github.com/python/cpython/issues/135312.
However, I do want to point out that the current stubs can actually lead to some false negatives. For instance, list does not allow calling __getitem__ with index as a keyword. Code sample in pyright playground
from collections.abc import Sequence
def get(x: Sequence[int], index: int) -> int:
return x.__getitem__(index=index)
get([1,2,3], 0) # TypeError at runtime
Also, I noticed that the stubs already use positional-only sometimes when CPython doesn't, for instance with Container.__contains__.