Skip to content

Commit

Permalink
fix: fix missing description with multiple args (#461)
Browse files Browse the repository at this point in the history
If one arg was missing this would result in a description syntax error

Signed-off-by: Stephen Whitlock <[email protected]>
  • Loading branch information
jshwi committed Sep 28, 2024
1 parent 4fe91cc commit 3312335
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 39 deletions.
1 change: 1 addition & 0 deletions changelog/461.fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fix missing description with multiple args
44 changes: 5 additions & 39 deletions docsig/_stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def __init__(
)

@classmethod
def from_ast( # pylint: disable=too-many-locals
def from_ast(
cls, node: _ast.Const, ignore_kwargs: bool = False
) -> Docstring:
"""Parse function docstring from ast.
Expand All @@ -331,49 +331,15 @@ def from_ast( # pylint: disable=too-many-locals
string = cls._normalize_docstring(node.value)
docstring = cls(string, ignore_kwargs)
indent_anomaly = cls._indent_anomaly(node.value)
# find out if parameter is missing a description
new = ""
for line in node.value.strip().splitlines()[2:]:
line = line.lstrip()
if not line.startswith(":"):
# it is not a parameter, it is a next line description
# append the next entry to the same line
new = f"{new[:-1]} "
new += f"{line}\n"
if not new:
missing_descriptions = True
else:
# if it ends with a colon, it's a parameter without a
# description
missing_descriptions = any(
i.endswith(":") for i in new.splitlines()
)

for line in string.splitlines():
strip_line = line.lstrip()
match = _re.split(":(.*?):", strip_line)[1:]
for match in _re.findall(r":(.*?):((?:.|\n)*?)(?=\n:|$)", string):
if match:
description = None
kinds = match[0].split()
if kinds:
kind = DocType.from_str(kinds[0])

if len(kinds) > 1:
name = kinds[1]
else:
# name could not be parsed
name = UNNAMED

if len(match) > 1:
second = match[1]
if second != "" or not missing_descriptions:
description = second

docstring.args.append(
Param(
kind,
name,
description,
DocType.from_str(kinds[0]),
UNNAMED if len(kinds) == 1 else kinds[1],
match[1] or None,
int(indent_anomaly),
)
)
Expand Down
29 changes: 29 additions & 0 deletions tests/fix_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,32 @@ def function(param1, param2, param3) -> None:
flake8(".", "--sig-check-class", "--sig-check-class-constructor")
std = capsys.readouterr()
assert docsig.messages.E[5].description in std.out


def test_description_missing_and_description_syntax_error_461(
capsys: pytest.CaptureFixture,
main: MockMainType,
init_file: InitFileFixtureType,
) -> None:
"""Test description missing raised with other description.
Other description would cause a syntax in description error if it
spanned over multiple lines.
:param capsys: Capture sys out.
:param main: Mock ``main`` function.
:param init_file: Initialize a test file.
"""
template = '''
def function(param1, param2) -> None:
"""
:param param1:
:param param2: This one does have a description however
and continues on the next line.
"""
'''
init_file(template)
main(".", test_flake8=False)
std = capsys.readouterr()
assert docsig.messages.E[301].description in std.out

0 comments on commit 3312335

Please sign in to comment.