python / python/mypy

[stubtest] Check `__slots__` better

Open
#13,906 1 comment 0 reactions 1 assignee View on GitHub

@sobolevn is already working on this.

Since Oct 16, 2022.

feature topic-stubtest
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Right now __slots__ has limited support in stubtest. For example, if we have a case like this:

# ex.py
class A: ...
class B:
    __slots__ = ('a', 'b')
class C:
    __slots__ = ('a',)

# ex.pyi
class A:
    __slots__ = ()
class B:
    __slots__ = ('a', 'c')
class C: ...

stubtest will only report:

» stubtest ex
error: ex.B.a is not present in stub
Stub: in file /Users/sobolev/Desktop/mypy/ex.pyi
MISSING
Runtime:
<member 'a' of 'B' objects>

error: ex.B.b is not present in stub
Stub: in file /Users/sobolev/Desktop/mypy/ex.pyi
MISSING
Runtime:
<member 'b' of 'B' objects>

error: ex.C.a is not present in stub
Stub: in file /Users/sobolev/Desktop/mypy/ex.pyi
MISSING
Runtime:
<member 'a' of 'C' objects>

Which is not correct.

I propose to check __slots__ to be exact on runtime and stub objects.

This is useful for cases like:

class SomeStub: ...  # defined in typeshed without actual `__slots__`


class A(SomeStub):  # user's code
    __slots__ = ("b",)

    def __init__(self) -> None:
        # All three will pass, because `SomeStub` parent has `__dict__`:
        self.a = 1
        self.b = 2
        self._one = 1

Compare it to the next case, where we have __slots__ defined:

class SomeStubWithSlots:  # defined in typeshed
    __slots__ = ("a",)


class A(SomeStubWithSlots):  # user's code
    __slots__ = ("b",)

    def __init__(self) -> None:
        self.a = 1
        self.b = 2
        self._one = 1  # E: Trying to assign name "_one" that is not in "__slots__" of type "ex.A"

Refs https://github.com/python/typeshed/issues/8832

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.