Skip to content

[stubtest] Check __slots__ better #13906

@sobolevn

Description

@sobolevn

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 python/typeshed#8832

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions