Skip to content

Commit

Permalink
stubgen: Add support for PEP 570 positional-only parameters (#16904)
Browse files Browse the repository at this point in the history
This only adds support for Python modules (x-ref #14138)
  • Loading branch information
hamdanal committed Feb 11, 2024
1 parent 837f7e0 commit 4a9c1e9
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
9 changes: 9 additions & 0 deletions mypy/stubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
Expand All @@ -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("*"))

Expand All @@ -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
Expand Down
22 changes: 22 additions & 0 deletions test-data/unit/stubgen.test
Original file line number Diff line number Diff line change
Expand Up @@ -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): ...

0 comments on commit 4a9c1e9

Please sign in to comment.