diff --git a/quartodoc/builder/blueprint.py b/quartodoc/builder/blueprint.py index a31d57ce..83ced27e 100644 --- a/quartodoc/builder/blueprint.py +++ b/quartodoc/builder/blueprint.py @@ -8,6 +8,7 @@ from griffe.loader import GriffeLoader from griffe.collections import ModulesCollection, LinesCollection from griffe.docstrings.parsers import Parser +from griffe.exceptions import AliasResolutionError from functools import partial from textwrap import indent @@ -120,6 +121,26 @@ def _non_default_entries(el: Auto): return {k: getattr(el, k) for k in el._fields_specified} +def _resolve_alias(obj: dc.Alias | dc.Object, get_object): + if not isinstance(obj, dc.Alias): + return obj + + # attempt to resolve alias, loading external modules when needed ---- + max_tries = 100 + + new_obj = obj + for ii in range(max_tries): + if not new_obj.is_alias: + break + + try: + new_obj = new_obj.target + except AliasResolutionError as e: + new_obj = get_object(e.alias.target_path) + + return new_obj + + class BlueprintTransformer(PydanticTransformer): def __init__(self, get_object=None, parser="numpy"): if get_object is None: @@ -296,8 +317,9 @@ def enter(self, el: Auto): # do no document submodules if ( - _is_external_alias(doc.obj, obj.package) - or doc.obj.kind.value == "module" + # _is_external_alias(doc.obj, obj.package) + doc.obj.kind.value + == "module" ): continue @@ -332,13 +354,19 @@ def enter(self, el: Auto): signature_name=el.signature_name, ) - @staticmethod - def _fetch_members(el: Auto, obj: dc.Object | dc.Alias): + def _fetch_members(self, el: Auto, obj: dc.Object | dc.Alias): + # Note that this could be a static method, if we passed in the griffe loader + if el.members is not None: return el.members options = obj.all_members if el.include_inherited else obj.members + # use the __all__ attribute of modules to filter members + # otherwise, all members are included in the initial options + if obj.is_module and obj.exports is not None: + options = {k: v for k, v in options.items() if v.is_exported} + if el.include: raise NotImplementedError("include argument currently unsupported.") @@ -348,9 +376,14 @@ def _fetch_members(el: Auto, obj: dc.Object | dc.Alias): if not el.include_private: options = {k: v for k, v in options.items() if not k.startswith("_")} - if not el.include_imports and not el.include_inherited: + if not (el.include_imports or el.include_inherited): options = {k: v for k, v in options.items() if not v.is_alias} + # resolve any remaining aliases ---- + # the reamining filters require attributes on the target object. + for obj in options.values(): + _resolve_alias(obj, self.get_object) + if not el.include_empty: options = {k: v for k, v in options.items() if v.docstring is not None} @@ -363,12 +396,6 @@ def _fetch_members(el: Auto, obj: dc.Object | dc.Alias): if not el.include_functions: options = {k: v for k, v in options.items() if not v.is_function} - # for modules, remove any Alias objects, since they were imported from - # other places. Sphinx has a flag for this behavior, so may be good - # to do something similar. - # if obj.is_module: - # options = {k: v for k, v in options.items() if not v.is_alias} - return sorted(options) diff --git a/quartodoc/tests/example_alias_target.py b/quartodoc/tests/example_alias_target.py index ccd46fb8..ce554eb7 100644 --- a/quartodoc/tests/example_alias_target.py +++ b/quartodoc/tests/example_alias_target.py @@ -1,5 +1,6 @@ from quartodoc.tests.example_alias_target__nested import ( # noqa: F401 nested_alias_target, + tabulate as external_alias, ) diff --git a/quartodoc/tests/example_alias_target__nested.py b/quartodoc/tests/example_alias_target__nested.py index 10f709f2..48d87476 100644 --- a/quartodoc/tests/example_alias_target__nested.py +++ b/quartodoc/tests/example_alias_target__nested.py @@ -2,6 +2,8 @@ This function gets imported in example_alias_target, and from there imported into example. """ +from tabulate import tabulate # noqa: F401 + def nested_alias_target(): """A nested alias target""" diff --git a/quartodoc/tests/test_builder_blueprint.py b/quartodoc/tests/test_builder_blueprint.py index fbc3c258..d8a854cd 100644 --- a/quartodoc/tests/test_builder_blueprint.py +++ b/quartodoc/tests/test_builder_blueprint.py @@ -1,13 +1,17 @@ +from functools import partial +from griffe.exceptions import AliasResolutionError from quartodoc import get_object from quartodoc import layout as lo from quartodoc.builder.blueprint import ( _non_default_entries, + _resolve_alias, BlueprintTransformer, blueprint, WorkaroundKeyError, ) import pytest + TEST_MOD = "quartodoc.tests.example" @@ -38,6 +42,17 @@ def bp(): return BlueprintTransformer() +def test_func_resolve_alias(): + obj = get_object("quartodoc.tests.example_alias_target.external_alias") + assert obj.is_alias + with pytest.raises(AliasResolutionError): + obj.target + + resolved = _resolve_alias(obj, get_object) + + assert resolved.path == "tabulate.tabulate" + + def test_non_default_entries_auto(): assert _non_default_entries(lo.Auto(name="a_func", include_attributes=False)) == { "name": "a_func",