Skip to content

Commit 1fd29ac

Browse files
authored
stubtest: fix pos-only handling in overload resolution (#16750)
1 parent edebe02 commit 1fd29ac

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

mypy/stubtest.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,10 @@ def from_overloadedfuncdef(stub: nodes.OverloadedFuncDef) -> Signature[nodes.Arg
826826
# argument. To accomplish this, we just make up a fake index-based name.
827827
name = (
828828
f"__{index}"
829-
if arg.variable.name.startswith("__") or assume_positional_only
829+
if arg.variable.name.startswith("__")
830+
or arg.pos_only
831+
or assume_positional_only
832+
or arg.variable.name.strip("_") == "self"
830833
else arg.variable.name
831834
)
832835
all_args.setdefault(name, []).append((arg, index))
@@ -870,6 +873,7 @@ def get_kind(arg_name: str) -> nodes.ArgKind:
870873
type_annotation=None,
871874
initializer=None,
872875
kind=get_kind(arg_name),
876+
pos_only=all(arg.pos_only for arg, _ in all_args[arg_name]),
873877
)
874878
if arg.kind.is_positional():
875879
sig.pos.append(arg)
@@ -905,6 +909,7 @@ def _verify_signature(
905909
if (
906910
runtime_arg.kind != inspect.Parameter.POSITIONAL_ONLY
907911
and (stub_arg.pos_only or stub_arg.variable.name.startswith("__"))
912+
and stub_arg.variable.name.strip("_") != "self"
908913
and not is_dunder(function_name, exclude_special=True) # noisy for dunder methods
909914
):
910915
yield (

mypy/test/teststubtest.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,13 @@ def test(*args: Any, **kwargs: Any) -> None:
210210
)
211211

212212
actual_errors = set(output.splitlines())
213-
assert actual_errors == expected_errors, output
213+
if actual_errors != expected_errors:
214+
output = run_stubtest(
215+
stub="\n\n".join(textwrap.dedent(c.stub.lstrip("\n")) for c in cases),
216+
runtime="\n\n".join(textwrap.dedent(c.runtime.lstrip("\n")) for c in cases),
217+
options=[],
218+
)
219+
assert actual_errors == expected_errors, output
214220

215221
return test
216222

@@ -660,6 +666,56 @@ def f6(self, x, /): pass
660666
""",
661667
error=None,
662668
)
669+
yield Case(
670+
stub="""
671+
@overload
672+
def f7(a: int, /) -> int: ...
673+
@overload
674+
def f7(b: str, /) -> str: ...
675+
""",
676+
runtime="def f7(x, /): pass",
677+
error=None,
678+
)
679+
yield Case(
680+
stub="""
681+
@overload
682+
def f8(a: int, c: int = 0, /) -> int: ...
683+
@overload
684+
def f8(b: str, d: int, /) -> str: ...
685+
""",
686+
runtime="def f8(x, y, /): pass",
687+
error="f8",
688+
)
689+
yield Case(
690+
stub="""
691+
@overload
692+
def f9(a: int, c: int = 0, /) -> int: ...
693+
@overload
694+
def f9(b: str, d: int, /) -> str: ...
695+
""",
696+
runtime="def f9(x, y=0, /): pass",
697+
error=None,
698+
)
699+
yield Case(
700+
stub="""
701+
class Bar:
702+
@overload
703+
def f1(self) -> int: ...
704+
@overload
705+
def f1(self, a: int, /) -> int: ...
706+
707+
@overload
708+
def f2(self, a: int, /) -> int: ...
709+
@overload
710+
def f2(self, a: str, /) -> int: ...
711+
""",
712+
runtime="""
713+
class Bar:
714+
def f1(self, *a) -> int: ...
715+
def f2(self, *a) -> int: ...
716+
""",
717+
error=None,
718+
)
663719

664720
@collect_cases
665721
def test_property(self) -> Iterator[Case]:

0 commit comments

Comments
 (0)