Skip to content

Commit 530bdc5

Browse files
authored
stubtest: additional guidance on errors when runtime is object.__init__ (#19733)
Fixes #19732 This is a simple check to point users in the right direction when they get errors because their class uses `__new__` but they wrote stubs for `__init__`. I don't feel strongly about the exact wording used here. I also considered "Maybe you meant to define `__new__` instead of `__init__`?".
1 parent 8bfecd4 commit 530bdc5

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

mypy/stubtest.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,10 @@ def get_kind(arg_name: str) -> nodes.ArgKind:
10531053

10541054

10551055
def _verify_signature(
1056-
stub: Signature[nodes.Argument], runtime: Signature[inspect.Parameter], function_name: str
1056+
stub: Signature[nodes.Argument],
1057+
runtime: Signature[inspect.Parameter],
1058+
function_name: str,
1059+
warn_runtime_is_object_init: bool = False,
10571060
) -> Iterator[str]:
10581061
# Check positional arguments match up
10591062
for stub_arg, runtime_arg in zip(stub.pos, runtime.pos):
@@ -1098,6 +1101,8 @@ def _verify_signature(
10981101
msg = f'runtime does not have parameter "{stub_arg.variable.name}"'
10991102
if runtime.varkw is not None:
11001103
msg += ". Maybe you forgot to make it keyword-only in the stub?"
1104+
elif warn_runtime_is_object_init:
1105+
msg += ". You may need to write stubs for __new__ instead of __init__."
11011106
yield msg
11021107
else:
11031108
yield f'stub parameter "{stub_arg.variable.name}" is not keyword-only'
@@ -1137,7 +1142,11 @@ def _verify_signature(
11371142
if arg not in {runtime_arg.name for runtime_arg in runtime.pos[len(stub.pos) :]}:
11381143
yield f'runtime parameter "{arg}" is not keyword-only'
11391144
else:
1140-
yield f'runtime does not have parameter "{arg}"'
1145+
msg = f'runtime does not have parameter "{arg}"'
1146+
if warn_runtime_is_object_init:
1147+
msg += ". You may need to write stubs for __new__ instead of __init__."
1148+
yield msg
1149+
11411150
for arg in sorted(set(runtime.kwonly) - set(stub.kwonly)):
11421151
if arg in {stub_arg.variable.name for stub_arg in stub.pos}:
11431152
# Don't report this if we've reported it before
@@ -1223,7 +1232,12 @@ def verify_funcitem(
12231232
if not signature:
12241233
return
12251234

1226-
for message in _verify_signature(stub_sig, runtime_sig, function_name=stub.name):
1235+
for message in _verify_signature(
1236+
stub_sig,
1237+
runtime_sig,
1238+
function_name=stub.name,
1239+
warn_runtime_is_object_init=runtime is object.__init__,
1240+
):
12271241
yield Error(
12281242
object_path,
12291243
"is inconsistent, " + message,
@@ -1333,7 +1347,12 @@ def verify_overloadedfuncdef(
13331347
stub_sig = Signature.from_overloadedfuncdef(stub)
13341348
runtime_sig = Signature.from_inspect_signature(signature)
13351349

1336-
for message in _verify_signature(stub_sig, runtime_sig, function_name=stub.name):
1350+
for message in _verify_signature(
1351+
stub_sig,
1352+
runtime_sig,
1353+
function_name=stub.name,
1354+
warn_runtime_is_object_init=runtime is object.__init__,
1355+
):
13371356
# TODO: This is a little hacky, but the addition here is super useful
13381357
if "has a default value of type" in message:
13391358
message += (

0 commit comments

Comments
 (0)