From 4a9c1e95457f253f87ef5db970ad8d59209c4715 Mon Sep 17 00:00:00 2001 From: Ali Hamdan Date: Sun, 11 Feb 2024 16:55:59 +0100 Subject: [PATCH] stubgen: Add support for PEP 570 positional-only parameters (#16904) This only adds support for Python modules (x-ref #14138) --- mypy/stubgen.py | 9 +++++++++ test-data/unit/stubgen.test | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/mypy/stubgen.py b/mypy/stubgen.py index c314fabc882d..36e8bd2acfb4 100755 --- a/mypy/stubgen.py +++ b/mypy/stubgen.py @@ -110,6 +110,7 @@ Var, ) from mypy.options import Options as MypyOptions +from mypy.sharedparse import MAGIC_METHODS_POS_ARGS_ONLY from mypy.stubdoc import ArgSig, FunctionSig from mypy.stubgenc import InspectionStubGenerator, generate_stub_for_c_module from mypy.stubutil import ( @@ -480,6 +481,9 @@ def get_default_function_sig(self, func_def: FuncDef, ctx: FunctionContext) -> F def _get_func_args(self, o: FuncDef, ctx: FunctionContext) -> list[ArgSig]: args: list[ArgSig] = [] + # Ignore pos-only status of magic methods whose args names are elided by mypy at parse + actually_pos_only_args = o.name not in MAGIC_METHODS_POS_ARGS_ONLY + pos_only_marker_position = 0 # Where to insert "/", if any for i, arg_ in enumerate(o.arguments): var = arg_.variable kind = arg_.kind @@ -500,6 +504,9 @@ def _get_func_args(self, o: FuncDef, ctx: FunctionContext) -> list[ArgSig]: if not isinstance(get_proper_type(annotated_type), AnyType): typename = self.print_annotation(annotated_type) + if actually_pos_only_args and arg_.pos_only: + pos_only_marker_position += 1 + if kind.is_named() and not any(arg.name.startswith("*") for arg in args): args.append(ArgSig("*")) @@ -518,6 +525,8 @@ def _get_func_args(self, o: FuncDef, ctx: FunctionContext) -> list[ArgSig]: args.append( ArgSig(name, typename, default=bool(arg_.initializer), default_value=default) ) + if pos_only_marker_position: + args.insert(pos_only_marker_position, ArgSig("/")) if ctx.class_info is not None and all( arg.type is None and arg.default is False for arg in args diff --git a/test-data/unit/stubgen.test b/test-data/unit/stubgen.test index 3b3bc658a14a..b5bccaa4cdbd 100644 --- a/test-data/unit/stubgen.test +++ b/test-data/unit/stubgen.test @@ -4231,3 +4231,25 @@ o = int | None def f1(a: int | tuple[int, int | None] | None) -> int: ... def f2(a: int | x.Union[int, int] | float | None) -> int: ... + +[case testPEP570PosOnlyParams] +def f(x=0, /): ... +def f1(x: int, /): ... +def f2(x: int, y: float = 1, /): ... +def f3(x: int, /, y: float): ... +def f4(x: int, /, y: float = 1): ... +def f5(x: int, /, *, y: float): ... +def f6(x: int = 0, /, *, y: float): ... +def f7(x: int, /, *, y: float = 1): ... +def f8(x: int = 0, /, *, y: float = 1): ... + +[out] +def f(x: int = 0, /) -> None: ... +def f1(x: int, /): ... +def f2(x: int, y: float = 1, /): ... +def f3(x: int, /, y: float): ... +def f4(x: int, /, y: float = 1): ... +def f5(x: int, /, *, y: float): ... +def f6(x: int = 0, /, *, y: float): ... +def f7(x: int, /, *, y: float = 1): ... +def f8(x: int = 0, /, *, y: float = 1): ...