Skip to content

Commit e978e37

Browse files
committed
stubtest: ignore setattr and delattr inherited from object
__setattr__ and __delattr__ from object are special cased by type checkers, so defining them on an inheriting class, even with the same signature, has a different meaning.
1 parent c859cb1 commit e978e37

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

mypy/stubtest.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,9 +571,23 @@ def verify_typeinfo(
571571

572572
# If it came from the metaclass, consider the runtime_attr to be MISSING
573573
# for a more accurate message
574-
if runtime_attr is not MISSING and type(runtime) is not runtime:
575-
if getattr(runtime_attr, "__objclass__", None) is type(runtime):
576-
runtime_attr = MISSING
574+
if (
575+
runtime_attr is not MISSING
576+
and type(runtime) is not runtime
577+
and getattr(runtime_attr, "__objclass__", None) is type(runtime)
578+
):
579+
runtime_attr = MISSING
580+
581+
# __setattr__ and __delattr__ on object are a special case,
582+
# so if we only have these methods inherited from there, pretend that
583+
# we don't have them. See python/typeshed#7385.
584+
if (
585+
entry in ("__setattr__", "__delattr__")
586+
and runtime_attr is not MISSING
587+
and runtime is not object
588+
and getattr(runtime_attr, "__objclass__", None) is object
589+
):
590+
runtime_attr = MISSING
577591

578592
# Do not error for an object missing from the stub
579593
# If the runtime object is a types.WrapperDescriptorType object

mypy/test/teststubtest.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,24 @@ def __call__(*args, **kwds): ...
14701470
runtime="class ClassWithMetaclassOverride: ...",
14711471
error="ClassWithMetaclassOverride.__call__",
14721472
)
1473+
# Test that we ignore object.__setattr__ and object.__delattr__ inheritance
1474+
yield Case(
1475+
stub="""
1476+
from typing import Any
1477+
class FakeSetattrClass:
1478+
def __setattr__(self, name: str, value: Any, /) -> None: ...
1479+
""",
1480+
runtime="class FakeSetattrClass: ...",
1481+
error="FakeSetattrClass.__setattr__",
1482+
)
1483+
yield Case(
1484+
stub="""
1485+
class FakeDelattrClass:
1486+
def __delattr__(self, name: str, /) -> None: ...
1487+
""",
1488+
runtime="class FakeDelattrClass: ...",
1489+
error="FakeDelattrClass.__delattr__",
1490+
)
14731491

14741492
@collect_cases
14751493
def test_missing_no_runtime_all(self) -> Iterator[Case]:

0 commit comments

Comments
 (0)