Skip to content

Commit

Permalink
Merge branch 'main' of github.com:mkdocstrings/griffe
Browse files Browse the repository at this point in the history
  • Loading branch information
pawamoy committed Jan 15, 2024
2 parents a26ccdb + 1e311a4 commit 7978f88
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 12 deletions.
64 changes: 52 additions & 12 deletions src/griffe/docstrings/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
DocstringReceive,
DocstringReturn,
DocstringSection,
DocstringSectionAdmonition,
DocstringSectionAttributes,
DocstringSectionClasses,
DocstringSectionDeprecated,
Expand Down Expand Up @@ -720,6 +721,19 @@ def _read_examples_section(
return None, new_offset


def _append_section(sections: list, current: list[str], admonition_title: str) -> None:
if admonition_title:
sections.append(
DocstringSectionAdmonition(
kind=admonition_title.lower().replace(" ", "-"),
text="\n".join(current).rstrip("\n"),
title=admonition_title,
),
)
elif current and any(current):
sections.append(DocstringSectionText("\n".join(current).rstrip("\n")))


_section_reader = {
DocstringSectionKind.parameters: _read_parameters_section,
DocstringSectionKind.other_parameters: _read_other_parameters_section,
Expand Down Expand Up @@ -762,6 +776,7 @@ def parse(
"""
sections: list[DocstringSection] = []
current_section = []
admonition_title = ""

in_code_block = False
lines = docstring.lines
Expand All @@ -787,32 +802,57 @@ def parse(
while offset < len(lines):
line_lower = lines[offset].lower()

# Code blocks can contain dash lines that we must not interpret.
if in_code_block:
# End of code block.
if line_lower.lstrip(" ").startswith("```"):
in_code_block = False
# Lines in code block must not be interpreted in any way.
current_section.append(lines[offset])

elif line_lower in _section_kind and _is_dash_line(lines[offset + 1]):
if current_section:
if any(current_section):
sections.append(DocstringSectionText("\n".join(current_section).rstrip("\n")))
current_section = []
reader = _section_reader[_section_kind[line_lower]]
section, offset = reader(docstring, offset=offset + 2, **options) # type: ignore[operator]
if section:
sections.append(section)

# Start of code block.
elif line_lower.lstrip(" ").startswith("```"):
in_code_block = True
current_section.append(lines[offset])

# Dash lines after empty lines lose their meaning.
elif _is_empty_line(lines[offset]):
current_section.append("")

# End of the docstring, wrap up.
elif offset == len(lines) - 1:
current_section.append(lines[offset])
_append_section(sections, current_section, admonition_title)
admonition_title = ""
current_section = []

# Dash line after regular, non-empty line.
elif _is_dash_line(lines[offset + 1]):
# Finish reading current section.
_append_section(sections, current_section, admonition_title)
current_section = []

# Start parsing new (known) section.
if line_lower in _section_kind:
admonition_title = ""
reader = _section_reader[_section_kind[line_lower]]
section, offset = reader(docstring, offset=offset + 2, **options) # type: ignore[operator]
if section:
sections.append(section)

# Start parsing admonition.
else:
admonition_title = lines[offset]
offset += 1 # skip next dash line

# Regular line.
else:
current_section.append(lines[offset])

offset += 1

if current_section:
sections.append(DocstringSectionText("\n".join(current_section).rstrip("\n")))
# Finish current section.
_append_section(sections, current_section, admonition_title)

return sections

Expand Down
72 changes: 72 additions & 0 deletions tests/test_docstrings/test_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,78 @@ def test_doubly_indented_lines_in_section_items(parse_numpy: ParserType) -> None
assert lines[-1].startswith(4 * " " + "- ")


# =============================================================================================
# Admonitions
def test_admonition_see_also(parse_numpy: ParserType) -> None:
"""Test a "See Also" admonition.
Parameters:
parse_numpy: Fixture parser.
"""
docstring = """
Summary text.
See Also
--------
some_function
more text
"""

sections, _ = parse_numpy(docstring)
assert len(sections) == 2
assert sections[0].value == "Summary text."
assert sections[1].title == "See Also"
assert sections[1].value.description == "some_function\n\nmore text"


def test_admonition_empty(parse_numpy: ParserType) -> None:
"""Test an empty "See Also" admonition.
Parameters:
parse_numpy: Fixture parser.
"""
docstring = """
Summary text.
See Also
--------
"""

sections, _ = parse_numpy(docstring)
assert len(sections) == 2
assert sections[0].value == "Summary text."
assert sections[1].title == "See Also"
assert sections[1].value.description == ""


def test_isolated_dash_lines_do_not_create_sections(parse_numpy: ParserType) -> None:
"""An isolated dash-line (`---`) should not be parsed as a section.
Parameters:
parse_numpy: Fixture parser.
"""
docstring = """
Summary text.
---
Text.
Note
----
Note contents.
---
Text.
"""

sections, _ = parse_numpy(docstring)
assert len(sections) == 2
assert sections[0].value == "Summary text.\n\n---\nText."
assert sections[1].title == "Note"
assert sections[1].value.description == "Note contents.\n\n---\nText."


# =============================================================================================
# Annotations
def test_prefer_docstring_type_over_annotation(parse_numpy: ParserType) -> None:
Expand Down

0 comments on commit 7978f88

Please sign in to comment.