Skip to content

Initial fix to switch order of preference for using docstring annotat… #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions src/pytkdocs/parsers/docstrings/google.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ def _parse_parameters_section(self, lines: List[str], start_index: int) -> Tuple
except (AttributeError, KeyError):
self.error(f"No type annotation for parameter '{name}'")
else:
if signature_param.annotation is not empty:
annotation = signature_param.annotation
# if signature_param.annotation is not empty:
# annotation = signature_param.annotation
if signature_param.default is not empty:
default = signature_param.default
kind = signature_param.kind
Expand Down Expand Up @@ -388,23 +388,21 @@ def read_return_section(self, lines: List[str], start_index: int) -> Tuple[Optio
A tuple containing a `Section` (or `None`) and the index at which to continue parsing.
"""
text, i = self.read_block(lines, start_index)
annotation = self.context["annotation"]

if self.context["signature"]:
annotation = self.context["signature"].return_annotation
else:
annotation = self.context["annotation"]

if annotation is empty:
if text:
try:
type_, text = text.split(":", 1)
except ValueError:
self.error("No type in return description")
else:
annotation = type_.lstrip()
text = text.lstrip()
if text:
try:
type_, text = text.split(":", 1)
except ValueError:
self.error("No type in return description")
else:
self.error("No return type annotation")
annotation = type_.lstrip()
text = text.lstrip()
else:
self.error("No return type annotation")

if annotation is empty and self.context["signature"]:
annotation = self.context["signature"].return_annotation

if annotation is empty and not text:
self.error(f"Empty return section at line {start_index}")
Expand Down
42 changes: 36 additions & 6 deletions tests/test_parsers/test_docstrings/test_google.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def test_property_docstring():
prop = class_.attributes[0]
sections, errors = prop.docstring_sections, prop.docstring_errors
assert len(sections) == 2
assert not errors
assert len(errors) == 1


def test_function_without_annotations():
Expand Down Expand Up @@ -125,7 +125,7 @@ def f(x: int, y: int, *, z: int) -> int:

sections, errors = parse(inspect.getdoc(f), inspect.signature(f))
assert len(sections) == 4
assert not errors
assert len(errors) == 1


def test_function_with_examples():
Expand Down Expand Up @@ -305,21 +305,51 @@ def f(x: int, y: int, *, z: int) -> int:
The types are written both in the signature and in the docstring.

Parameters:
x (int): X value.
y (int): Y value.
x (str): X value.
y (str): Y value.

Keyword Args:
z (int): Z value.
z (str): Z value.

Returns:
int: Sum X + Y + Z.
str: Sum X + Y + Z.
"""
return x + y + z

sections, errors = parse(inspect.getdoc(f), inspect.signature(f))
assert len(sections) == 4
assert not errors

assert sections[0].type == Section.Type.MARKDOWN
assert sections[1].type == Section.Type.PARAMETERS
assert sections[2].type == Section.Type.KEYWORD_ARGS
assert sections[3].type == Section.Type.RETURN

x, y = sections[1].value
(z,) = sections[2].value
r = sections[3].value

assert x.name == "x"
assert x.annotation == "str"
assert x.description == "X value."
assert x.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD
assert x.default is inspect.Signature.empty

assert y.name == "y"
assert y.annotation == "str"
assert y.description == "Y value."
assert y.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD
assert y.default is inspect.Signature.empty

assert z.name == "z"
assert z.annotation == "str"
assert z.description == "Z value."
assert z.kind is inspect.Parameter.KEYWORD_ONLY
assert z.default is inspect.Signature.empty

assert r.annotation == "str"
assert r.description == "Sum X + Y + Z."


def test_close_sections():
"""Parse sections without blank lines in between."""
Expand Down
5 changes: 2 additions & 3 deletions tests/test_parsers/test_docstrings/test_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ class DummyObject:
def parse(docstring, signature=None, return_type=inspect.Signature.empty):
"""Helper to parse a doctring."""
return Numpy().parse(
dedent(docstring).strip(),
{"obj": DummyObject(), "signature": signature, "type": return_type},
dedent(docstring).strip(), {"obj": DummyObject(), "signature": signature, "type": return_type},
)


Expand Down Expand Up @@ -80,7 +79,7 @@ def test_property_docstring():
prop = class_.attributes[0]
sections, errors = prop.docstring_sections, prop.docstring_errors
assert len(sections) == 2
assert not errors
assert len(errors) == 1


def test_function_without_annotations():
Expand Down