Skip to content

Commit

Permalink
feat: Support getting attribute annotation from parent in RST docstri…
Browse files Browse the repository at this point in the history
…ng parser
  • Loading branch information
pawamoy committed Jan 2, 2022
1 parent 62b0927 commit 25db61a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 39 deletions.
9 changes: 7 additions & 2 deletions src/griffe/docstrings/rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""

from __future__ import annotations
from contextlib import suppress

from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Callable, FrozenSet
Expand Down Expand Up @@ -242,16 +243,20 @@ def _read_attribute(docstring: Docstring, offset: int, parsed_values: ParsedValu
_warn(docstring, 0, f"Failed to parse field directive from '{parsed_directive.line}'")
return parsed_directive.next_index

annotation = None
annotation: str | Name | Expression | None = None

# Annotation precedence:
# - "vartype" directive type
# - annotation in the parent
# - none

parsed_attribute_type = parsed_values.attribute_types.get(name)
if parsed_attribute_type is not None:
annotation = parsed_attribute_type

else:
# try to use the annotation from the parent
with suppress(AttributeError, KeyError):
annotation = docstring.parent.attributes[name].annotation # type: ignore[union-attr]
if name in parsed_values.attributes:
_warn(docstring, 0, f"Duplicate attribute entry for '{name}'")
else:
Expand Down
73 changes: 36 additions & 37 deletions tests/test_docstrings/test_rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import pytest

from griffe.dataclasses import Class, Function, Parameter, Parameters
from griffe.dataclasses import Attribute, Class, Function, Module, Parameter, Parameters
from griffe.docstrings import rst
from griffe.docstrings.dataclasses import (
DocstringAttribute,
Expand Down Expand Up @@ -809,39 +809,38 @@ def test_parse__raise_no_name__error():
assert "Failed to parse exception directive from" in warnings[0]


# TODO: uncomment once Attribute is used
# def test_parse_module_attributes_section__expected_attributes_section():
# """Parse attributes section in modules."""
# docstring = """
# Let's describe some attributes.

# :var A: Alpha.
# :var B: Beta.
# :vartype B: bytes
# :var C: Gamma.
# :var D: Delta.
# :var E: Epsilon.
# :vartype E: float
# """

# module = Module("mod", filepath=None)
# module["A"] = Attribute("A") # annotation="int", value="0"
# module["B"] = Attribute("B") # annotation="str", value=repr("ŧ")
# module["C"] = Attribute("C") # annotation="bool", value="True"
# module["D"] = Attribute("D") # annotation=None, value="3.0"
# module["E"] = Attribute("E") # annotation=None, value="None"
# sections, warnings = parse(docstring)

# attr_section = sections[1]
# assert attr_section.kind is DocstringSectionKind.attributes
# assert len(attr_section.value) == 5
# expected_kwargs = [
# {"name": "A", "annotation": "int", "description": "Alpha."},
# {"name": "B", "annotation": "bytes", "description": "Beta."},
# {"name": "C", "annotation": "bool", "description": "Gamma."},
# {"name": "D", "annotation": None, "description": "Delta."},
# {"name": "E", "annotation": "float", "description": "Epsilon."},
# ]
# for index, expected in enumerate(expected_kwargs):
# assert_annotated_obj_equal(attr_section.value[index], DocstringAttribute(**expected))
# assert not warnings
def test_parse_module_attributes_section__expected_attributes_section():
"""Parse attributes section in modules."""
docstring = """
Let's describe some attributes.
:var A: Alpha.
:vartype B: bytes
:var B: Beta.
:var C: Gamma.
:var D: Delta.
:var E: Epsilon.
:vartype E: float
"""

module = Module("mod", filepath=None)
module["A"] = Attribute("A", annotation="int", value="0")
module["B"] = Attribute("B", annotation="str", value=repr("ŧ"))
module["C"] = Attribute("C", annotation="bool", value="True")
module["D"] = Attribute("D", annotation=None, value="3.0")
module["E"] = Attribute("E", annotation=None, value="None")
sections, warnings = parse(docstring, parent=module)

attr_section = sections[1]
assert attr_section.kind is DocstringSectionKind.attributes
assert len(attr_section.value) == 5
expected_kwargs = [
{"name": "A", "annotation": "int", "description": "Alpha."},
{"name": "B", "annotation": "bytes", "description": "Beta."},
{"name": "C", "annotation": "bool", "description": "Gamma."},
{"name": "D", "annotation": None, "description": "Delta."},
{"name": "E", "annotation": "float", "description": "Epsilon."},
]
for index, expected in enumerate(expected_kwargs):
assert_attribute_equal(attr_section.value[index], DocstringAttribute(**expected))
assert not warnings

0 comments on commit 25db61a

Please sign in to comment.