diff --git a/.github/workflows/test_stubgenc.yml b/.github/workflows/test_stubgenc.yml index 4676acf8695b..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/stubgen/**' + - 'test-data/pybind11_fixtures/**' permissions: contents: read diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index 89db6cb3378f..c5e918c01225 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -79,6 +79,8 @@ class FunctionSig(NamedTuple): ret_type: str | 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( @@ -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: @@ -182,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] = [] @@ -265,6 +273,8 @@ def add_token(self, token: tokenize.TokenInfo) -> None: self.reset() return self.keyword_only = len(self.args) + 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("*"): @@ -342,7 +352,13 @@ 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_index, + ret_type=self.ret_type, + ) ) self.found = False self.args = [] diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 43974cf8ec68..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")], + [ + 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 +487,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 +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")], + [ + 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")], + [ + 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")], + [ + FunctionSig( + name="func", + args=[ArgSig(name="x"), ArgSig(name="y")], + ret_type="str", + kwarg_only_index=0, + ) + ], ) assert_equal( @@ -497,6 +534,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", + kwarg_only_index=1, ) ], ) @@ -504,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")], + [ + FunctionSig( + name="func", + args=[ArgSig(name="x"), ArgSig(name="y")], + ret_type="str", + pos_only_index=1, + kwarg_only_index=2, + ) + ], ) assert_equal( @@ -514,6 +560,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 +578,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, ) ], ) 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..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,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..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: @@ -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,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 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" diff --git a/test-data/pybind11_fixtures/src/main.cpp b/test-data/pybind11_fixtures/src/main.cpp index 4d275ab1fd70..fde1b391a222 100644 --- a/test-data/pybind11_fixtures/src/main.cpp +++ b/test-data/pybind11_fixtures/src/main.cpp @@ -265,6 +265,35 @@ void bind_demo(py::module& m) { // Module-level attributes m.attr("PI") = std::acos(-1); m.attr("__version__") = "0.0.1"; + + // 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); } // ---------------------------------------------------------------------------- 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