Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,13 @@ def verify_typeinfo(
# Catch all exceptions in case the runtime raises an unexpected exception
# from __getattr__ or similar.
continue

# If it came from the metaclass, consider the runtime_attr to be MISSING
# for a more accurate message
if runtime_attr is not MISSING and type(runtime) is not runtime:
if getattr(runtime_attr, "__objclass__", None) is type(runtime):
runtime_attr = MISSING

# Do not error for an object missing from the stub
# If the runtime object is a types.WrapperDescriptorType object
# and has a non-special dunder name.
Expand Down Expand Up @@ -1519,6 +1526,7 @@ def is_probably_a_function(runtime: Any) -> bool:
isinstance(runtime, (types.FunctionType, types.BuiltinFunctionType))
or isinstance(runtime, (types.MethodType, types.BuiltinMethodType))
or (inspect.ismethoddescriptor(runtime) and callable(runtime))
or (inspect.ismethodwrapper(runtime) and callable(runtime))
)


Expand Down
10 changes: 10 additions & 0 deletions mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,16 @@ def h(x: str): ...
runtime="__all__ += ['Z']\nclass Z:\n def __reduce__(self): return (Z,)",
error=None,
)
# __call__ exists on type, so it appears to exist on the class.
# This checks that we identify it as missing at runtime anyway.
yield Case(
stub="""
class ClassWithMetaclassOverride:
def __call__(*args, **kwds): ...
""",
runtime="class ClassWithMetaclassOverride: ...",
error="ClassWithMetaclassOverride.__call__",
)

@collect_cases
def test_missing_no_runtime_all(self) -> Iterator[Case]:
Expand Down
Loading