Skip to content

Skip Alias Resolution #213

@chrimaho

Description

@chrimaho

When I write a new module, with Python docstrings (in Google style), I want to render these docstrings on my docs page. This is typical. However, the challenge is in the resolution of Aliases through Griffe. Specifically, Griffe forces the loading and resolution of every single module which I am importing in to my script; even if those imported docs are not even necessary for my documentation.

Let me give you an example:

import pandas as pd
import numpy as np

def my_fancy_func():
    """
    Some documentation in Google style
    """
    return pd.DataFrame({'a': [1, 2, 3], 'b': ['a', 'b', 'c']})

In the above scenario, we have one module which imports two libraries: pandas and numpy, and one super simple function with basic documentation.

Now, when I try to load this documentation using the command:

mkdocs serve

I receive a HUGE and super complicated error:

(.venv) name@MACHINE:/path-to-dir$ mkdocs serve
INFO    -  DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
             File "/path-to-dir/.venv/lib/python3.10/site-packages/mike/mkdocs_plugin.py", line 6, in <module>
               from pkg_resources import iter_entry_points
             File "/path-to-dir/.venv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 118, in <module>
               warnings.warn(
INFO    -  Building documentation...
INFO    -  Cleaning site directory
INFO    -  DeprecationWarning: invalid escape sequence '\_'
             File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/agents/visitor.py", line 177, in get_module
               top_node = compile(self.code, mode="exec", filename=str(self.filepath), flags=ast.PyCF_ONLY_AST, optimize=1)
             File "/path-to-dir/.venv/lib/python3.10/site-packages/pyspark/pandas/supported_api_gen.py", line 355, in
               return func_str[:-1] + "\_"  # noqa: W605
ERROR   -  Error reading page 'docs/code/processing_times.md': Could not resolve alias src.databricks_helpers.processing_times.pd pointing at pandas (in
           src/databricks_helpers/processing_times.py:5)
Traceback (most recent call last):
  File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 1116, in _resolve_target
    resolved = self.modules_collection.get_member(self.target_path)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/mixins.py", line 77, in get_member
    return self.members[parts[0]]  # type: ignore[attr-defined]
KeyError: 'pandas'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/path-to-dir/.venv/bin/mkdocs", line 10, in <module>
    sys.exit(cli())
  File "/path-to-dir/.venv/lib/python3.10/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/path-to-dir/.venv/lib/python3.10/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocs/__main__.py", line 270, in serve_command
    serve.serve(**kwargs)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 86, in serve
    builder(config)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 67, in builder
    build(config, live_server=None if is_clean else server, dirty=is_dirty)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocs/commands/build.py", line 322, in build
    _populate_page(file.page, config, files, dirty)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocs/commands/build.py", line 175, in _populate_page
    page.render(config, files)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocs/structure/pages.py", line 271, in render
    self.content = md.convert(self.markdown)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/markdown/core.py", line 254, in convert
    root = self.parser.parseDocument(self.lines).getroot()
  File "/path-to-dir/.venv/lib/python3.10/site-packages/markdown/blockparser.py", line 84, in parseDocument
    self.parseChunk(self.root, '\n'.join(lines))
  File "/path-to-dir/.venv/lib/python3.10/site-packages/markdown/blockparser.py", line 99, in parseChunk
    self.parseBlocks(parent, text.split('\n\n'))
  File "/path-to-dir/.venv/lib/python3.10/site-packages/markdown/blockparser.py", line 117, in parseBlocks
    if processor.run(parent, blocks) is not False:
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings/extension.py", line 125, in run
    html, handler, data = self._process_block(identifier, block, heading_level)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings/extension.py", line 221, in _process_block
    rendered = handler.render(data, options)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/handler.py", line 338, in render
    return template.render(
  File "/path-to-dir/.venv/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/path-to-dir/.venv/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/module.html", line 1, in top-level template code
    {% extends "_base/module.html" %}
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/_base/module.html", line 55, in top-level template code
    {% block contents scoped %}
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/_base/module.html", line 62, in block 'contents'
    {% block children scoped %}
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/_base/module.html", line 65, in block 'children'
    {% include "children.html" with context %}
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/children.html", line 1, in top-level template code
    {% extends "_base/children.html" %}
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/templates/material/_base/children.html", line 110, in top-level template code
    {% for child in obj.all_members
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/rendering.py", line 184, in do_order_members
    return sorted(members, key=order_map[order])
  File "/path-to-dir/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/rendering.py", line 40, in _sort_key_source
    return item.lineno if item.lineno is not None else -1
  File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 816, in lineno
    return self.final_target.lineno
  File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 1092, in final_target
    target = target.target  # type: ignore[assignment]
  File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 1064, in target
    self.resolve_target()
  File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 1110, in resolve_target
    self._resolve_target()
  File "/path-to-dir/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 1118, in _resolve_target
    raise AliasResolutionError(self) from error
griffe.exceptions.AliasResolutionError: Could not resolve alias src.databricks_helpers.processing_times.pd pointing at pandas (in src/databricks_helpers/processing_times.py:5)

Which confuses me a lot. Why is my rendering failing because it's pointing at Pandas?

Through a LOT of searching through your documentation, I finally found how to resolve it. I needed to list pandas in the preload_modules section on the mkdocs.yml config file.

Like this:

plugins:
  - autorefs
  - mkdocstrings:
      default_handler: python
      handlers:
        python:
          options:
            allow_inspection: true
            docstring_style: google
            docstring_options:
              replace_admonitions: no
            show_root_heading: true
            show_root_toc_entry: false
            show_root_full_path: true
            show_source: true
            show_object_full_path: false
            show_signature_annotations: true
            show_category_heading: true
            show_if_no_docstring: true
            heading_level: 3
            members_order: source
            group_by_category: false
            paths:
              - src/databricks_helpers
            preload_modules:
              - __future__
              - typeguard
              - datetime
              - pandas
            filters:
              - "!^__all__"

Now, what happens when I do mkdocs serve, is that it takes over 2 minutes to load the docs eeeeeevery single time I save my files, which greatly reduces my efficiency in building my docs. The reason for this is that mkdocstrings-python will re-load every single module listed in preload_modules every single time one of the underlying files changes listed in paths. And because Pandas takes sooooooo long to load (that's a separate issue from this one), then therefore these mkdocstrings processes will also take so long to load them.

But I question why this is even necessary? The pandas package is not necessary for my docs rendering at all. It's needed for Unit Testing, that's fine. But not for docs rendering... So why does it even need to be preloaded? It's so that Griffe will be to render the Alias Resolution, right? But I don't want it to. I just want to build my docs quickly and easily.

Therefore, I'd like to recommend an additional option here to skip the Alias resolution process in Griffe. Therefore, I do not need to add my additional packages in this preload_modules section.

One other use case to consider is in packages that are not even loaded in to my local virtual environment. One such example is the DBUtils package, necessary for various processes on DataBricks environment. But when coding on my local PC, this pacakage is not installable, because it's only available in DataBricks workspace. But I need to include the import statement in my modules because when that package is run on DataBricks later, then that dbutils package will be available. However, as soon as I add this import statement to my script, then Griffe will expect to preload it... but it's not installed... so therefore Griffe will not allow my docs to even be rendered. But the challenge is, I don't even need DBUtils for my docs?? So therefore, I'd like to skip this Alias Resolution part alltogether.

Please help me with this one.

Here's my package versions:

  • Griffe: griffe 0.36.2
  • MkDocs: mkdocs 1.5.3
  • MkDocs-Material: mkdocs-material 9.4.2
  • MkDocStrings: mkdocstrings 0.23.0
  • MkDocStrings-Python: mkdocstrings-python 1.7.0

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions