From c102973b3ed6d102ec351a77004193e5258791c6 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 21:54:54 -0700 Subject: [PATCH 01/14] add pos_only test --- test-data/pybind11_fixtures/src/main.cpp | 76 ++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/test-data/pybind11_fixtures/src/main.cpp b/test-data/pybind11_fixtures/src/main.cpp index 4d275ab1fd70..7e42f9c1433d 100644 --- a/test-data/pybind11_fixtures/src/main.cpp +++ b/test-data/pybind11_fixtures/src/main.cpp @@ -265,6 +265,82 @@ void bind_demo(py::module& m) { // Module-level attributes m.attr("PI") = std::acos(-1); m.attr("__version__") = "0.0.1"; + + // test_keyword_only_args + m.def( + "kw_only_all", + [](int i, int j) { return py::make_tuple(i, j); }, + py::kw_only(), + py::arg("i"), + py::arg("j")); + m.def( + "kw_only_some", + [](int i, int j, int k) { return py::make_tuple(i, j, k); }, + py::arg(), + py::kw_only(), + py::arg("j"), + py::arg("k")); + m.def( + "kw_only_with_defaults", + [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); }, + py::arg() = 3, + "j"_a = 4, + py::kw_only(), + "k"_a = 5, + "z"_a); + m.def( + "kw_only_mixed", + [](int i, int j) { return py::make_tuple(i, j); }, + "i"_a, + py::kw_only(), + "j"_a); + m.def( + "kw_only_plus_more", + [](int i, int j, int k, const py::kwargs &kwargs) { + return py::make_tuple(i, j, k, kwargs); + }, + py::arg() /* positional */, + py::arg("j") = -1 /* both */, + py::kw_only(), + py::arg("k") /* kw-only */); + + m.def("register_invalid_kw_only", [](py::module_ m) { + m.def( + "bad_kw_only", + [](int i, int j) { return py::make_tuple(i, j); }, + py::kw_only(), + py::arg() /* invalid unnamed argument */, + "j"_a); + }); + + // test_positional_only_args + m.def( + "pos_only_all", + [](int i, int j) { return py::make_tuple(i, j); }, + py::arg("i"), + py::arg("j"), + py::pos_only()); + m.def( + "pos_only_mix", + [](int i, int j) { return py::make_tuple(i, j); }, + py::arg("i"), + py::pos_only(), + py::arg("j")); + m.def( + "pos_kw_only_mix", + [](int i, int j, int k) { return py::make_tuple(i, j, k); }, + py::arg("i"), + py::pos_only(), + py::arg("j"), + py::kw_only(), + py::arg("k")); + m.def( + "pos_only_def_mix", + [](int i, int j, int k) { return py::make_tuple(i, j, k); }, + py::arg("i"), + py::arg("j") = 2, + py::pos_only(), + py::arg("k") = 3); } // ---------------------------------------------------------------------------- From 1dcda4153cbc2cd24e88e87e63551846313c5fa0 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 21:57:30 -0700 Subject: [PATCH 02/14] fix workflow --- .github/workflows/test_stubgenc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_stubgenc.yml b/.github/workflows/test_stubgenc.yml index 4676acf8695b..54ba79e80e78 100644 --- a/.github/workflows/test_stubgenc.yml +++ b/.github/workflows/test_stubgenc.yml @@ -11,7 +11,7 @@ on: - 'mypy/stubgenc.py' - 'mypy/stubdoc.py' - 'mypy/stubutil.py' - - 'test-data/stubgen/**' + - 'test-data/pybind11_features/**' permissions: contents: read From f4e847851c9118d3f9ddbdaf4e9539180bb742d4 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 21:58:45 -0700 Subject: [PATCH 03/14] fix spelling --- .github/workflows/test_stubgenc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_stubgenc.yml b/.github/workflows/test_stubgenc.yml index 54ba79e80e78..6cf3cb71c3ff 100644 --- a/.github/workflows/test_stubgenc.yml +++ b/.github/workflows/test_stubgenc.yml @@ -11,7 +11,7 @@ on: - 'mypy/stubgenc.py' - 'mypy/stubdoc.py' - 'mypy/stubutil.py' - - 'test-data/pybind11_features/**' + - 'test-data/pybind11_fixtures/**' permissions: contents: read From b21b2aba135f4c4ec71e1c5b61e6ef1f5be4fcbf Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 22:00:17 -0700 Subject: [PATCH 04/14] simplify test --- test-data/pybind11_fixtures/src/main.cpp | 47 ------------------------ 1 file changed, 47 deletions(-) diff --git a/test-data/pybind11_fixtures/src/main.cpp b/test-data/pybind11_fixtures/src/main.cpp index 7e42f9c1433d..fde1b391a222 100644 --- a/test-data/pybind11_fixtures/src/main.cpp +++ b/test-data/pybind11_fixtures/src/main.cpp @@ -266,53 +266,6 @@ void bind_demo(py::module& m) { m.attr("PI") = std::acos(-1); m.attr("__version__") = "0.0.1"; - // test_keyword_only_args - m.def( - "kw_only_all", - [](int i, int j) { return py::make_tuple(i, j); }, - py::kw_only(), - py::arg("i"), - py::arg("j")); - m.def( - "kw_only_some", - [](int i, int j, int k) { return py::make_tuple(i, j, k); }, - py::arg(), - py::kw_only(), - py::arg("j"), - py::arg("k")); - m.def( - "kw_only_with_defaults", - [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); }, - py::arg() = 3, - "j"_a = 4, - py::kw_only(), - "k"_a = 5, - "z"_a); - m.def( - "kw_only_mixed", - [](int i, int j) { return py::make_tuple(i, j); }, - "i"_a, - py::kw_only(), - "j"_a); - m.def( - "kw_only_plus_more", - [](int i, int j, int k, const py::kwargs &kwargs) { - return py::make_tuple(i, j, k, kwargs); - }, - py::arg() /* positional */, - py::arg("j") = -1 /* both */, - py::kw_only(), - py::arg("k") /* kw-only */); - - m.def("register_invalid_kw_only", [](py::module_ m) { - m.def( - "bad_kw_only", - [](int i, int j) { return py::make_tuple(i, j); }, - py::kw_only(), - py::arg() /* invalid unnamed argument */, - "j"_a); - }); - // test_positional_only_args m.def( "pos_only_all", From 1572b619c9213b031ba44926ea62fd096dfa0964 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 22:05:32 -0700 Subject: [PATCH 05/14] bump pybind --- test-data/pybind11_fixtures/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/pybind11_fixtures/pyproject.toml b/test-data/pybind11_fixtures/pyproject.toml index 773d036e62f5..ea3ed4734feb 100644 --- a/test-data/pybind11_fixtures/pyproject.toml +++ b/test-data/pybind11_fixtures/pyproject.toml @@ -4,7 +4,7 @@ requires = [ "wheel", # Officially supported pybind11 version. This is pinned to guarantee 100% reproducible CI. # As a result, the version needs to be bumped manually at will. - "pybind11==2.9.2", + "pybind11==2.13.6", ] build-backend = "setuptools.build_meta" From aa56a2f7daa6bbc6f5b31c03420d95088a4ecc76 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 22:41:49 -0700 Subject: [PATCH 06/14] test pos_only_index --- mypy/stubdoc.py | 9 ++++++++- mypy/test/teststubgen.py | 11 ++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index 89db6cb3378f..e1140ce90058 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -77,6 +77,8 @@ class FunctionSig(NamedTuple): name: str args: list[ArgSig] ret_type: str | None + pos_only_index: int | None = None + kwarg_only_index: int | None = None type_args: str = "" # TODO implement in stubgenc and remove the default docstring: str | None = None @@ -139,6 +141,11 @@ def format_sig( args.append(arg_def) + if self.pos_only_index: + args.insert(self.pos_only_index, '/') + if self.kwarg_only_index: + args.insert(self.kwarg_only_index, '*') + retfield = "" ret_type = self.ret_type if self.ret_type else any_val if ret_type is not None: @@ -342,7 +349,7 @@ def add_token(self, token: tokenize.TokenInfo) -> None: if self.found: self.signatures.append( - FunctionSig(name=self.function_name, args=self.args, ret_type=self.ret_type) + FunctionSig(name=self.function_name, args=self.args, pos_only_index=self.pos_only, kwarg_only_index=self.keyword_only, ret_type=self.ret_type) ) self.found = False self.args = [] diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 43974cf8ec68..e9af0da93d6b 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -477,17 +477,17 @@ def test_infer_sig_from_docstring_positional_only_arguments(self) -> None: def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None: assert_equal( infer_sig_from_docstring("func(*, x) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x")], ret_type="str")], + [FunctionSig(name="func", args=[ArgSig(name="x")], ret_type="str", pos_only_index=0)], ) assert_equal( infer_sig_from_docstring("func(x, *, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str")], + [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", pos_only_index=1)], ) assert_equal( infer_sig_from_docstring("func(*, x, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str")], + [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", pos_only_index=0)], ) assert_equal( @@ -497,6 +497,7 @@ def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None: name="func", args=[ArgSig(name="x"), ArgSig(name="kwonly"), ArgSig("**kwargs")], ret_type="str", + pos_only_index=1, ) ], ) @@ -514,6 +515,8 @@ def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> N name="func", args=[ArgSig(name="x"), ArgSig(name="y"), ArgSig(name="z")], ret_type="str", + pos_only_index=1, + kwarg_only_index=3 ) ], ) @@ -530,6 +533,8 @@ def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> N ArgSig("**kwargs"), ], ret_type="str", + pos_only_index=1, + kwarg_only_index=3 ) ], ) From fe5e404ceab40404090c129a32f049d2e9d37a13 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 22:45:26 -0700 Subject: [PATCH 07/14] fix order --- mypy/stubdoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index e1140ce90058..fd5e39b9dd99 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -77,10 +77,10 @@ class FunctionSig(NamedTuple): name: str args: list[ArgSig] ret_type: str | None - pos_only_index: int | None = None - kwarg_only_index: int | None = None type_args: str = "" # TODO implement in stubgenc and remove the default docstring: str | None = None + pos_only_index: int | None = None + kwarg_only_index: int | None = None def is_special_method(self) -> bool: return bool( From a6d174938f1392377242d50f207ed3b37985663e Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 22:57:12 -0700 Subject: [PATCH 08/14] update .pyi --- mypy/stubdoc.py | 3 ++- .../pybind11_fixtures/demo.pyi | 4 ++++ .../pybind11_fixtures/__init__.pyi | 4 ++-- .../pybind11_fixtures/demo.pyi | 15 ++++++++++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index fd5e39b9dd99..114ead0855dd 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -144,7 +144,8 @@ def format_sig( if self.pos_only_index: args.insert(self.pos_only_index, '/') if self.kwarg_only_index: - args.insert(self.kwarg_only_index, '*') + pos_offset = 1 if self.pos_only_index else 0 + args.insert(self.kwarg_only_index + pos_offset, '*') retfield = "" ret_type = self.ret_type if self.ret_type else any_val diff --git a/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi b/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi index 87b8ec0e4ad6..268514a72c84 100644 --- a/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi +++ b/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi @@ -57,5 +57,9 @@ class Point: def answer() -> int: ... def midpoint(left: float, right: float) -> float: ... +def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: +def pos_only_all(i: int, j: int, /) -> tuple: +def pos_only_def_mix(i: int, j: int = ..., /, k: int = ...) -> tuple: +def pos_only_mix(i: int, /, j: int) -> tuple: def sum(arg0: int, arg1: int) -> int: ... def weighted_midpoint(left: float, right: float, alpha: float = ...) -> float: ... diff --git a/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/__init__.pyi b/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/__init__.pyi index 0eeb788d4278..3c97d03938d7 100644 --- a/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/__init__.pyi +++ b/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/__init__.pyi @@ -48,8 +48,8 @@ def func_incomplete_signature(*args, **kwargs): def func_returning_optional() -> int | None: """func_returning_optional() -> Optional[int]""" def func_returning_pair() -> tuple[int, float]: - """func_returning_pair() -> Tuple[int, float]""" + """func_returning_pair() -> tuple[int, float]""" def func_returning_path() -> os.PathLike: """func_returning_path() -> os.PathLike""" def func_returning_vector() -> list[float]: - """func_returning_vector() -> List[float]""" + """func_returning_vector() -> list[float]""" diff --git a/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi b/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi index 6e285f202f1a..9c62284a29d8 100644 --- a/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi +++ b/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi @@ -96,7 +96,7 @@ class Point: 2. __init__(self: pybind11_fixtures.demo.Point, x: float, y: float) -> None """ def as_list(self) -> list[float]: - """as_list(self: pybind11_fixtures.demo.Point) -> List[float]""" + """as_list(self: pybind11_fixtures.demo.Point) -> list[float]""" @overload def distance_to(self, x: float, y: float) -> float: """distance_to(*args, **kwargs) @@ -126,6 +126,19 @@ def answer() -> int: ''' def midpoint(left: float, right: float) -> float: """midpoint(left: float, right: float) -> float""" + +def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: + """pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple""" + +def pos_only_all(i: int, j: int, /) -> tuple: + """pos_only_all(i: int, j: int, /) -> tuple""" + +def pos_only_def_mix(i: int, j: int = ..., /, k: int = ...) -> tuple: + """pos_only_def_mix(i: int, j: int = 2, /, k: int = 3) -> tuple""" + +def pos_only_mix(i: int, /, j: int) -> tuple: + """pos_only_mix(i: int, /, j: int) -> tuple""" + def sum(arg0: int, arg1: int) -> int: '''sum(arg0: int, arg1: int) -> int From 6653fbd017bb7ddd1cfb77e81cec1149a5f129ee Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 23:07:08 -0700 Subject: [PATCH 09/14] update kwarg only --- mypy/stubdoc.py | 7 ++++--- .../pybind11_fixtures/demo.pyi | 13 ++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index 114ead0855dd..2a0315845fa7 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -144,8 +144,7 @@ def format_sig( if self.pos_only_index: args.insert(self.pos_only_index, '/') if self.kwarg_only_index: - pos_offset = 1 if self.pos_only_index else 0 - args.insert(self.kwarg_only_index + pos_offset, '*') + args.insert(self.kwarg_only_index, '*') retfield = "" ret_type = self.ret_type if self.ret_type else any_val @@ -190,6 +189,7 @@ def __init__(self, function_name: str) -> None: self.args: list[ArgSig] = [] self.pos_only: int | None = None self.keyword_only: int | None = None + self.keyword_only_index: int | None = None # Valid signatures found so far. self.signatures: list[FunctionSig] = [] @@ -273,6 +273,7 @@ def add_token(self, token: tokenize.TokenInfo) -> None: self.reset() return self.keyword_only = len(self.args) + self.keyword_only_index = self.keyword_only self.accumulator = "" else: if self.accumulator.startswith("*"): @@ -350,7 +351,7 @@ def add_token(self, token: tokenize.TokenInfo) -> None: if self.found: self.signatures.append( - FunctionSig(name=self.function_name, args=self.args, pos_only_index=self.pos_only, kwarg_only_index=self.keyword_only, ret_type=self.ret_type) + FunctionSig(name=self.function_name, args=self.args, pos_only_index=self.pos_only, kwarg_only_index=self.keyword_only_index, ret_type=self.ret_type) ) self.found = False self.args = [] diff --git a/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi b/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi index 9c62284a29d8..2e8bbf21801a 100644 --- a/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi +++ b/test-data/pybind11_fixtures/expected_stubs_with_docs/pybind11_fixtures/demo.pyi @@ -28,9 +28,9 @@ class Point: """__ne__(self: object, other: object) -> bool""" @property def name(self) -> str: - """name(self: handle) -> str + """name(self: object) -> str - name(self: handle) -> str + name(self: object) -> str """ @property def value(self) -> int: @@ -63,9 +63,9 @@ class Point: """__ne__(self: object, other: object) -> bool""" @property def name(self) -> str: - """name(self: handle) -> str + """name(self: object) -> str - name(self: handle) -> str + name(self: object) -> str """ @property def value(self) -> int: @@ -126,19 +126,14 @@ def answer() -> int: ''' def midpoint(left: float, right: float) -> float: """midpoint(left: float, right: float) -> float""" - def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: """pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple""" - def pos_only_all(i: int, j: int, /) -> tuple: """pos_only_all(i: int, j: int, /) -> tuple""" - def pos_only_def_mix(i: int, j: int = ..., /, k: int = ...) -> tuple: """pos_only_def_mix(i: int, j: int = 2, /, k: int = 3) -> tuple""" - def pos_only_mix(i: int, /, j: int) -> tuple: """pos_only_mix(i: int, /, j: int) -> tuple""" - def sum(arg0: int, arg1: int) -> int: '''sum(arg0: int, arg1: int) -> int From a31eabdc7986deb82179cb8dbb7608767b97deca Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 23:20:33 -0700 Subject: [PATCH 10/14] update teststubgen --- mypy/test/teststubgen.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index e9af0da93d6b..ec8453aae4bc 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -437,28 +437,28 @@ def test_infer_sig_from_docstring_args_kwargs_errors(self) -> None: def test_infer_sig_from_docstring_positional_only_arguments(self) -> None: assert_equal( infer_sig_from_docstring("func(self, /) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="self")], ret_type="str")], + [FunctionSig(name="func", args=[ArgSig(name="self")], ret_type="str", pos_only_index=1)], ) assert_equal( infer_sig_from_docstring("func(self, x, /) -> str", "func"), [ FunctionSig( - name="func", args=[ArgSig(name="self"), ArgSig(name="x")], ret_type="str" + name="func", args=[ArgSig(name="self"), ArgSig(name="x")], ret_type="str", pos_only_index=2 ) ], ) assert_equal( infer_sig_from_docstring("func(x, /, y) -> int", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="int")], + [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="int", pos_only_index=1)], ) assert_equal( infer_sig_from_docstring("func(x, /, *args) -> str", "func"), [ FunctionSig( - name="func", args=[ArgSig(name="x"), ArgSig(name="*args")], ret_type="str" + name="func", args=[ArgSig(name="x"), ArgSig(name="*args")], ret_type="str", pos_only_index=1 ) ], ) @@ -470,6 +470,8 @@ def test_infer_sig_from_docstring_positional_only_arguments(self) -> None: name="func", args=[ArgSig(name="x"), ArgSig(name="kwonly"), ArgSig(name="**kwargs")], ret_type="str", + pos_only_index=1, + kwarg_only_index=2 ) ], ) @@ -477,17 +479,17 @@ def test_infer_sig_from_docstring_positional_only_arguments(self) -> None: def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None: assert_equal( infer_sig_from_docstring("func(*, x) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x")], ret_type="str", pos_only_index=0)], + [FunctionSig(name="func", args=[ArgSig(name="x")], ret_type="str", kwarg_only_index=0)], ) assert_equal( infer_sig_from_docstring("func(x, *, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", pos_only_index=1)], + [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", kwarg_only_index=1)], ) assert_equal( infer_sig_from_docstring("func(*, x, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", pos_only_index=0)], + [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", kwarg_only_index=0)], ) assert_equal( @@ -497,7 +499,7 @@ def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None: name="func", args=[ArgSig(name="x"), ArgSig(name="kwonly"), ArgSig("**kwargs")], ret_type="str", - pos_only_index=1, + kwarg_only_index=1, ) ], ) @@ -505,7 +507,7 @@ def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None: def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> None: assert_equal( infer_sig_from_docstring("func(x, /, *, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str")], + [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", pos_only_index=1, kwarg_only_index=2)], ) assert_equal( From 27a41e30ad3065054f80488f838946a148fe2526 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 23:21:05 -0700 Subject: [PATCH 11/14] add ... --- .../expected_stubs_no_docs/pybind11_fixtures/demo.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi b/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi index 268514a72c84..a7318b38908f 100644 --- a/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi +++ b/test-data/pybind11_fixtures/expected_stubs_no_docs/pybind11_fixtures/demo.pyi @@ -57,9 +57,9 @@ class Point: def answer() -> int: ... def midpoint(left: float, right: float) -> float: ... -def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: -def pos_only_all(i: int, j: int, /) -> tuple: -def pos_only_def_mix(i: int, j: int = ..., /, k: int = ...) -> tuple: -def pos_only_mix(i: int, /, j: int) -> tuple: +def pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple: ... +def pos_only_all(i: int, j: int, /) -> tuple: ... +def pos_only_def_mix(i: int, j: int = ..., /, k: int = ...) -> tuple: ... +def pos_only_mix(i: int, /, j: int) -> tuple: ... def sum(arg0: int, arg1: int) -> int: ... def weighted_midpoint(left: float, right: float, alpha: float = ...) -> float: ... From e8277e1ddb46d739c492caf78f4a6c0aec8f13e5 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 23:23:13 -0700 Subject: [PATCH 12/14] fix kwarg index --- mypy/stubdoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index 2a0315845fa7..f1fa9f9704f8 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -273,7 +273,7 @@ def add_token(self, token: tokenize.TokenInfo) -> None: self.reset() return self.keyword_only = len(self.args) - self.keyword_only_index = self.keyword_only + self.keyword_only_index = self.keyword_only + 1 if self.pos_only is not None else 0 self.accumulator = "" else: if self.accumulator.startswith("*"): From b656ae345363fa73279b8784ce8fb45bbf6a1d3e Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 23:30:43 -0700 Subject: [PATCH 13/14] lint --- mypy/stubdoc.py | 16 +++++++--- mypy/test/teststubgen.py | 65 +++++++++++++++++++++++++++++++++------- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index f1fa9f9704f8..e3f06906ad1d 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -142,9 +142,9 @@ def format_sig( args.append(arg_def) if self.pos_only_index: - args.insert(self.pos_only_index, '/') + args.insert(self.pos_only_index, "/") if self.kwarg_only_index: - args.insert(self.kwarg_only_index, '*') + args.insert(self.kwarg_only_index, "*") retfield = "" ret_type = self.ret_type if self.ret_type else any_val @@ -273,7 +273,9 @@ def add_token(self, token: tokenize.TokenInfo) -> None: self.reset() return self.keyword_only = len(self.args) - self.keyword_only_index = self.keyword_only + 1 if self.pos_only is not None else 0 + self.keyword_only_index = ( + self.keyword_only + 1 if self.pos_only is not None else 0 + ) self.accumulator = "" else: if self.accumulator.startswith("*"): @@ -351,7 +353,13 @@ def add_token(self, token: tokenize.TokenInfo) -> None: if self.found: self.signatures.append( - FunctionSig(name=self.function_name, args=self.args, pos_only_index=self.pos_only, kwarg_only_index=self.keyword_only_index, ret_type=self.ret_type) + FunctionSig( + name=self.function_name, + args=self.args, + pos_only_index=self.pos_only, + kwarg_only_index=self.keyword_only_index, + ret_type=self.ret_type, + ) ) self.found = False self.args = [] diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index ec8453aae4bc..8ee76547d4a2 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -437,28 +437,45 @@ def test_infer_sig_from_docstring_args_kwargs_errors(self) -> None: def test_infer_sig_from_docstring_positional_only_arguments(self) -> None: assert_equal( infer_sig_from_docstring("func(self, /) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="self")], ret_type="str", pos_only_index=1)], + [ + FunctionSig( + name="func", args=[ArgSig(name="self")], ret_type="str", pos_only_index=1 + ) + ], ) assert_equal( infer_sig_from_docstring("func(self, x, /) -> str", "func"), [ FunctionSig( - name="func", args=[ArgSig(name="self"), ArgSig(name="x")], ret_type="str", pos_only_index=2 + name="func", + args=[ArgSig(name="self"), ArgSig(name="x")], + ret_type="str", + pos_only_index=2, ) ], ) assert_equal( infer_sig_from_docstring("func(x, /, y) -> int", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="int", pos_only_index=1)], + [ + FunctionSig( + name="func", + args=[ArgSig(name="x"), ArgSig(name="y")], + ret_type="int", + pos_only_index=1, + ) + ], ) assert_equal( infer_sig_from_docstring("func(x, /, *args) -> str", "func"), [ FunctionSig( - name="func", args=[ArgSig(name="x"), ArgSig(name="*args")], ret_type="str", pos_only_index=1 + name="func", + args=[ArgSig(name="x"), ArgSig(name="*args")], + ret_type="str", + pos_only_index=1, ) ], ) @@ -471,7 +488,7 @@ def test_infer_sig_from_docstring_positional_only_arguments(self) -> None: args=[ArgSig(name="x"), ArgSig(name="kwonly"), ArgSig(name="**kwargs")], ret_type="str", pos_only_index=1, - kwarg_only_index=2 + kwarg_only_index=2, ) ], ) @@ -479,17 +496,35 @@ def test_infer_sig_from_docstring_positional_only_arguments(self) -> None: def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None: assert_equal( infer_sig_from_docstring("func(*, x) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x")], ret_type="str", kwarg_only_index=0)], + [ + FunctionSig( + name="func", args=[ArgSig(name="x")], ret_type="str", kwarg_only_index=0 + ) + ], ) assert_equal( infer_sig_from_docstring("func(x, *, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", kwarg_only_index=1)], + [ + FunctionSig( + name="func", + args=[ArgSig(name="x"), ArgSig(name="y")], + ret_type="str", + kwarg_only_index=1, + ) + ], ) assert_equal( infer_sig_from_docstring("func(*, x, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", kwarg_only_index=0)], + [ + FunctionSig( + name="func", + args=[ArgSig(name="x"), ArgSig(name="y")], + ret_type="str", + kwarg_only_index=0, + ) + ], ) assert_equal( @@ -507,7 +542,15 @@ def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None: def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> None: assert_equal( infer_sig_from_docstring("func(x, /, *, y) -> str", "func"), - [FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str", pos_only_index=1, kwarg_only_index=2)], + [ + FunctionSig( + name="func", + args=[ArgSig(name="x"), ArgSig(name="y")], + ret_type="str", + pos_only_index=1, + kwarg_only_index=2, + ) + ], ) assert_equal( @@ -518,7 +561,7 @@ def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> N args=[ArgSig(name="x"), ArgSig(name="y"), ArgSig(name="z")], ret_type="str", pos_only_index=1, - kwarg_only_index=3 + kwarg_only_index=3, ) ], ) @@ -536,7 +579,7 @@ def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> N ], ret_type="str", pos_only_index=1, - kwarg_only_index=3 + kwarg_only_index=3, ) ], ) From 6c51281b1b2b2e9cf618d8b3538a709281396711 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 24 Jun 2025 23:50:03 -0700 Subject: [PATCH 14/14] fix offset --- mypy/stubdoc.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index e3f06906ad1d..c5e918c01225 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -273,9 +273,8 @@ def add_token(self, token: tokenize.TokenInfo) -> None: self.reset() return self.keyword_only = len(self.args) - self.keyword_only_index = ( - self.keyword_only + 1 if self.pos_only is not None else 0 - ) + pos_offset = 1 if self.pos_only is not None else 0 + self.keyword_only_index = self.keyword_only + pos_offset self.accumulator = "" else: if self.accumulator.startswith("*"): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy