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.