Skip to content

Commit d45b862

Browse files
committed
allow starred args and kwargs in docstring params
1 parent d8a9b9c commit d45b862

File tree

5 files changed

+68
-2
lines changed

5 files changed

+68
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Use hatchling instead of setuptools
66
- Add support for typing.ParamSpec
7+
- Allow star prefixes for parameter names in docstring
78

89
## 1.19.2
910

src/sphinx_autodoc_typehints/__init__.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,49 @@ def process_docstring(
500500
delattr(app.config, "_annotation_globals")
501501

502502

503+
def _get_sphinx_line_keyword_and_argument(line: str) -> tuple[str, str | None] | None:
504+
"""
505+
Extract a keyword, and its optional argument out of a sphinx field option line.
506+
507+
For example
508+
>>> _get_sphinx_line_keyword_and_argument(":param parameter:")
509+
("param", "parameter")
510+
>>> _get_sphinx_line_keyword_and_argument(":return:")
511+
("return", None)
512+
>>> _get_sphinx_line_keyword_and_argument("some invalid line")
513+
None
514+
"""
515+
516+
param_line_without_description = line.split(":", maxsplit=2) # noqa: SC200
517+
if len(param_line_without_description) != 3:
518+
return None
519+
520+
split_directive_and_name = param_line_without_description[1].split(maxsplit=1) # noqa: SC200
521+
if len(split_directive_and_name) != 2:
522+
return (split_directive_and_name[0], None)
523+
524+
return tuple(split_directive_and_name) # type: ignore
525+
526+
527+
def _line_is_param_line_for_arg(line: str, arg_name: str) -> bool:
528+
"""Return True if `line` is a valid parameter line for `arg_name`, false otherwise."""
529+
keyword_and_name = _get_sphinx_line_keyword_and_argument(line)
530+
if keyword_and_name is None:
531+
return False
532+
533+
keyword, doc_name = keyword_and_name
534+
if doc_name is None:
535+
return False
536+
537+
if keyword not in {"param", "parameter", "arg", "argument"}:
538+
return False
539+
540+
for prefix in ("", r"\*", r"\**", r"\*\*"):
541+
if doc_name == prefix + arg_name:
542+
return True
543+
return False
544+
545+
503546
def _inject_types_to_docstring(
504547
type_hints: dict[str, Any],
505548
signature: inspect.Signature | None,
@@ -521,10 +564,12 @@ def _inject_types_to_docstring(
521564

522565
formatted_annotation = format_annotation(annotation, app.config)
523566

524-
search_for = {f":{field} {arg_name}:" for field in ("param", "parameter", "arg", "argument")}
525567
insert_index = None
526568
for at, line in enumerate(lines):
527-
if any(line.startswith(search_string) for search_string in search_for):
569+
if _line_is_param_line_for_arg(line, arg_name):
570+
# Get the arg_name from the doc to match up for type in case it has a star prefix.
571+
# Line is in the correct format so this is guaranteed to return tuple[str, str].
572+
_, arg_name = _get_sphinx_line_keyword_and_argument(line) # type: ignore[assignment, misc]
528573
insert_index = at
529574
break
530575

tests/roots/test-dummy/dummy_module.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ def function(x: bool, y: int, z_: typing.Optional[str] = None) -> str: # noqa:
126126
"""
127127

128128

129+
def function_with_starred_documentation_param_names(*args: int, **kwargs: str): # noqa: U100
130+
r"""
131+
Function docstring.
132+
133+
:param \*args: foo
134+
:param \**kwargs: bar
135+
"""
136+
137+
129138
def function_with_escaped_default(x: str = "\b"): # noqa: U100
130139
"""
131140
Function docstring.

tests/roots/test-dummy/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Dummy Module
1919

2020
.. autofunction:: dummy_module.function_with_typehint_comment
2121

22+
.. autofunction:: dummy_module.function_with_starred_documentation_param_names
23+
2224
.. autoclass:: dummy_module.ClassWithTypehints
2325
:members:
2426

tests/test_sphinx_autodoc_typehints.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,15 @@ class InnerClass
619619
Return type:
620620
"None"
621621
622+
dummy_module.function_with_starred_documentation_param_names(*args, **kwargs)
623+
624+
Function docstring.
625+
626+
Parameters:
627+
* ***args** ("int") -- foo
628+
629+
* ****kwargs** ("str") -- bar
630+
622631
class dummy_module.ClassWithTypehints(x)
623632
624633
Class docstring.

0 commit comments

Comments
 (0)