Skip to content

Use positional only arguments for dunder methods in collections.abc #14071

Closed

Description

@randolf-scholz

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: ...  # ✅

Activity

  1. srittau commented on May 15, 2025

    @srittau
    Collaborator

    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.

  2. Akuli commented on May 15, 2025

    @Akuli
    Collaborator

    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.

  3. randolf-scholz commented on Jun 9, 2025

    @randolf-scholz
    ContributorAuthor

    I opened python/cpython#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__.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stubs: improvementImprove/refactor existing annotations, other stubs issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions