diff --git a/src/griffe/dataclasses.py b/src/griffe/dataclasses.py index 24c93f23..61d3d6f4 100644 --- a/src/griffe/dataclasses.py +++ b/src/griffe/dataclasses.py @@ -353,7 +353,7 @@ def has_docstrings(self) -> bool: if self.has_docstring: # noqa: DAR201 return True for member in self.members.values(): - if (not member.is_alias or member.resolved) and member.has_docstrings: # type: ignore[union-attr] + if member.has_docstrings: # type: ignore[union-attr] return True return False @@ -842,6 +842,16 @@ def endlineno(self) -> int | None: return self.target.endlineno return self.alias_endlineno + @property + def has_docstring(self) -> bool: + """Tell if this alias' target has a non-empty docstring.""" + return self.resolved and self.target.has_docstring # noqa: DAR201 + + @property + def has_docstrings(self) -> bool: + """Tell if this alias' target or any of its members has a non-empty docstring.""" + return self.resolved and self.target.has_docstrings # noqa: DAR201 + @property def parent(self) -> Module | Class | None: """Return the parent of this alias. diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py index d28b3f7a..14401249 100644 --- a/tests/test_dataclasses.py +++ b/tests/test_dataclasses.py @@ -1,6 +1,8 @@ """Tests for the `dataclasses` module.""" from griffe.dataclasses import Docstring, Module +from griffe.loader import GriffeLoader +from tests.helpers import module_vtree, temporary_pypackage def test_submodule_exports(): @@ -27,3 +29,31 @@ def test_has_docstrings(): module["b.c.d"].docstring = Docstring("Hello.") assert module.has_docstrings + +def test_handle_aliases_chain_in_has_docstrings(): + """Assert the `.has_docstrings` method can handle aliases chains in members.""" + with temporary_pypackage("package", ["mod_a.py", "mod_b.py"]) as tmp_package: + mod_a = tmp_package.path / "mod_a.py" + mod_b = tmp_package.path / "mod_b.py" + mod_a.write_text("from .mod_b import someobj") + mod_b.write_text("from somelib import someobj") + + loader = GriffeLoader(search_paths=[tmp_package.tmpdir]) + package = loader.load_module(tmp_package.name) + assert not package.has_docstrings + loader.resolve_aliases(only_exported=False) + assert not package.has_docstrings + + +def test_has_docstrings_does_not_trigger_alias_resolution(): + """Assert the `.has_docstrings` method does not trigger alias resolution.""" + with temporary_pypackage("package", ["mod_a.py", "mod_b.py"]) as tmp_package: + mod_a = tmp_package.path / "mod_a.py" + mod_b = tmp_package.path / "mod_b.py" + mod_a.write_text("from .mod_b import someobj") + mod_b.write_text("from somelib import someobj") + + loader = GriffeLoader(search_paths=[tmp_package.tmpdir]) + package = loader.load_module(tmp_package.name) + assert not package.has_docstrings + assert not package["mod_a.someobj"].resolved