Skip to content

Commit e4f5648

Browse files
fixup! Support positional and keyword-only arguments
1 parent 6eb5932 commit e4f5648

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

mypy/stubdoc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ def add_token(self, token: tokenize.TokenInfo) -> None:
262262
self.keyword_only = len(self.args)
263263
self.accumulator = ""
264264
else:
265+
if self.accumulator.startswith("*"):
266+
self.keyword_only = len(self.args) + 1
265267
self.arg_name = self.accumulator
266268
if not (
267269
token.string == ")" and self.accumulator.strip() == ""
@@ -301,7 +303,7 @@ def add_token(self, token: tokenize.TokenInfo) -> None:
301303
self.accumulator = ""
302304
elif (
303305
token.type == tokenize.OP
304-
and (token.string in {"*", "/"})
306+
and token.string == "/"
305307
and self.state[-1] == STATE_ARGUMENT_LIST
306308
):
307309
if token.string == "/":
@@ -315,8 +317,6 @@ def add_token(self, token: tokenize.TokenInfo) -> None:
315317
self.pos_only = len(self.args)
316318
self.state.append(STATE_ARGUMENT_TYPE)
317319
self.accumulator = ""
318-
else:
319-
self.accumulator = "*"
320320

321321
elif token.type == tokenize.OP and token.string == "->" and self.state[-1] == STATE_INIT:
322322
self.accumulator = ""

mypy/test/teststubgen.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,19 @@ def test_infer_sig_from_docstring_args_kwargs(self) -> None:
421421
[FunctionSig(name="func", args=[ArgSig(name="**kwargs")], ret_type="int")],
422422
)
423423

424+
@pytest.mark.xfail(
425+
raises=AssertionError, reason="Arg and kwarg signature validation not implemented yet"
426+
)
427+
def test_infer_sig_from_docstring_args_kwargs_errors(self) -> None:
428+
# Double args
429+
assert_equal(infer_sig_from_docstring("func(*args, *args2) -> int", "func"), [])
430+
431+
# Double kwargs
432+
assert_equal(infer_sig_from_docstring("func(**kw, **kw2) -> int", "func"), [])
433+
434+
# args after kwargs
435+
assert_equal(infer_sig_from_docstring("func(**kwargs, *args) -> int", "func"), [])
436+
424437
def test_infer_sig_from_docstring_positional_only_arguments(self) -> None:
425438
assert_equal(
426439
infer_sig_from_docstring("func(self, /) -> str", "func"),
@@ -441,6 +454,26 @@ def test_infer_sig_from_docstring_positional_only_arguments(self) -> None:
441454
[FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="int")],
442455
)
443456

457+
assert_equal(
458+
infer_sig_from_docstring("func(x, /, *args) -> str", "func"),
459+
[
460+
FunctionSig(
461+
name="func", args=[ArgSig(name="x"), ArgSig(name="*args")], ret_type="str"
462+
)
463+
],
464+
)
465+
466+
assert_equal(
467+
infer_sig_from_docstring("func(x, /, *, kwonly, **kwargs) -> str", "func"),
468+
[
469+
FunctionSig(
470+
name="func",
471+
args=[ArgSig(name="x"), ArgSig(name="kwonly"), ArgSig(name="**kwargs")],
472+
ret_type="str",
473+
)
474+
],
475+
)
476+
444477
def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None:
445478
assert_equal(
446479
infer_sig_from_docstring("func(*, x) -> str", "func"),
@@ -457,6 +490,17 @@ def test_infer_sig_from_docstring_keyword_only_arguments(self) -> None:
457490
[FunctionSig(name="func", args=[ArgSig(name="x"), ArgSig(name="y")], ret_type="str")],
458491
)
459492

493+
assert_equal(
494+
infer_sig_from_docstring("func(x, *, kwonly, **kwargs) -> str", "func"),
495+
[
496+
FunctionSig(
497+
name="func",
498+
args=[ArgSig(name="x"), ArgSig(name="kwonly"), ArgSig("**kwargs")],
499+
ret_type="str",
500+
)
501+
],
502+
)
503+
460504
def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> None:
461505
assert_equal(
462506
infer_sig_from_docstring("func(x, /, *, y) -> str", "func"),
@@ -474,6 +518,22 @@ def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments(self) -> N
474518
],
475519
)
476520

521+
assert_equal(
522+
infer_sig_from_docstring("func(x, /, y, *, z, **kwargs) -> str", "func"),
523+
[
524+
FunctionSig(
525+
name="func",
526+
args=[
527+
ArgSig(name="x"),
528+
ArgSig(name="y"),
529+
ArgSig(name="z"),
530+
ArgSig("**kwargs"),
531+
],
532+
ret_type="str",
533+
)
534+
],
535+
)
536+
477537
def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments_errors(self) -> None:
478538
# / as first argument
479539
assert_equal(infer_sig_from_docstring("func(/, x) -> str", "func"), [])
@@ -494,6 +554,9 @@ def test_infer_sig_from_docstring_pos_only_and_keyword_only_arguments_errors(sel
494554

495555
assert_equal(infer_sig_from_docstring("func(x, /, *, y, *, z) -> str", "func"), [])
496556

557+
# *args and * are not allowed
558+
assert_equal(infer_sig_from_docstring("func(*args, *, kwonly) -> str", "func"), [])
559+
497560
def test_infer_arg_sig_from_anon_docstring(self) -> None:
498561
assert_equal(
499562
infer_arg_sig_from_anon_docstring("(*args, **kwargs)"),

0 commit comments

Comments
 (0)