From bb4be5be1b85be50f46c7889231a2d4a3bd05165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 3 Sep 2024 15:05:11 +0200 Subject: [PATCH 1/5] feat: Hook into autorefs to provide context around cross-ref errors --- pyproject.toml | 4 +- src/mkdocstrings_handlers/python/handler.py | 1 + src/mkdocstrings_handlers/python/rendering.py | 58 +++++++++++++++++ .../material/_base/docstring.html.jinja | 64 ++++++++++--------- .../_base/docstring/admonition.html.jinja | 4 +- .../_base/docstring/attributes.html.jinja | 6 +- .../_base/docstring/classes.html.jinja | 6 +- .../_base/docstring/examples.html.jinja | 2 +- .../_base/docstring/functions.html.jinja | 6 +- .../_base/docstring/modules.html.jinja | 6 +- .../docstring/other_parameters.html.jinja | 6 +- .../_base/docstring/parameters.html.jinja | 6 +- .../_base/docstring/raises.html.jinja | 6 +- .../_base/docstring/receives.html.jinja | 6 +- .../_base/docstring/returns.html.jinja | 6 +- .../material/_base/docstring/warns.html.jinja | 6 +- .../_base/docstring/yields.html.jinja | 6 +- .../_base/docstring/attributes.html.jinja | 2 +- .../docstring/other_parameters.html.jinja | 2 +- .../_base/docstring/parameters.html.jinja | 2 +- .../_base/docstring/raises.html.jinja | 2 +- .../_base/docstring/receives.html.jinja | 2 +- .../_base/docstring/returns.html.jinja | 2 +- .../_base/docstring/warns.html.jinja | 2 +- .../_base/docstring/yields.html.jinja | 2 +- 25 files changed, 138 insertions(+), 77 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f1ff7334..0eccf7fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,8 +29,8 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "mkdocstrings>=0.25", - "mkdocs-autorefs>=1.0", + "mkdocstrings>=0.26", + "mkdocs-autorefs>=1.2", "griffe>=0.49", ] diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index a4a5b47c..eb1d73c7 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -426,6 +426,7 @@ def update_env(self, md: Markdown, config: dict) -> None: self.env.filters["as_functions_section"] = rendering.do_as_functions_section self.env.filters["as_classes_section"] = rendering.do_as_classes_section self.env.filters["as_modules_section"] = rendering.do_as_modules_section + self.env.globals["AutorefsHook"] = rendering.AutorefsHook self.env.tests["existing_template"] = lambda template_name: template_name in self.env.list_templates() def get_anchors(self, data: CollectorItem) -> tuple[str, ...]: # noqa: D102 (ignore missing docstring) diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py index d5a88699..2c4a4893 100644 --- a/src/mkdocstrings_handlers/python/rendering.py +++ b/src/mkdocstrings_handlers/python/rendering.py @@ -22,6 +22,7 @@ ) from jinja2 import TemplateNotFound, pass_context, pass_environment from markupsafe import Markup +from mkdocs_autorefs.references import AutorefsHookInterface from mkdocstrings.loggers import get_logger if TYPE_CHECKING: @@ -571,3 +572,60 @@ def do_as_modules_section( A modules docstring section. """ return DocstringSectionModules([]) + + +class AutorefsHook(AutorefsHookInterface): + """Autorefs hook. + + With this hook, we're able to add context to autorefs (cross-references), + such as originating file path and line number, to improve error reporting. + """ + + def __init__(self, current_object: Object | Alias, config: dict[str, Any]) -> None: + """Initialize the hook. + + Parameters: + current_object: The object being rendered. + config: The configuration dictionary. + """ + self.current_object = current_object + self.config = config + + def expand_identifier(self, identifier: str) -> str: + """Expand an identifier. + + Parameters: + identifier: The identifier to expand. + + Returns: + The expanded identifier. + """ + return identifier + + def get_context(self) -> AutorefsHookInterface.Context: + """Get the context for the current object. + + Returns: + The context. + """ + role = { + "attribute": "data" if self.current_object.parent and self.current_object.parent.is_module else "attr", + "class": "class", + "function": "meth" if self.current_object.parent and self.current_object.parent.is_class else "func", + "module": "mod", + }.get(self.current_object.kind.value.lower(), "obj") + origin = self.current_object.path + try: + filepath = self.current_object.docstring.parent.filepath # type: ignore[union-attr] + lineno = self.current_object.docstring.lineno or 0 # type: ignore[union-attr] + except AttributeError: + filepath = self.current_object.filepath + lineno = 0 + + return AutorefsHookInterface.Context( + domain="py", + role=role, + origin=origin, + filepath=str(filepath), + lineno=lineno, + ) diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja index bc561b14..14d11d03 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja @@ -19,35 +19,37 @@ Context: -#} {{ log.debug("Rendering docstring") }} {% endblock logs %} - {% for section in docstring_sections %} - {% if config.show_docstring_description and section.kind.value == "text" %} - {{ section.value|convert_markdown(heading_level, html_id) }} - {% elif config.show_docstring_attributes and section.kind.value == "attributes" %} - {% include "docstring/attributes"|get_template with context %} - {% elif config.show_docstring_functions and section.kind.value == "functions" %} - {% include "docstring/functions"|get_template with context %} - {% elif config.show_docstring_classes and section.kind.value == "classes" %} - {% include "docstring/classes"|get_template with context %} - {% elif config.show_docstring_modules and section.kind.value == "modules" %} - {% include "docstring/modules"|get_template with context %} - {% elif config.show_docstring_parameters and section.kind.value == "parameters" %} - {% include "docstring/parameters"|get_template with context %} - {% elif config.show_docstring_other_parameters and section.kind.value == "other parameters" %} - {% include "docstring/other_parameters"|get_template with context %} - {% elif config.show_docstring_raises and section.kind.value == "raises" %} - {% include "docstring/raises"|get_template with context %} - {% elif config.show_docstring_warns and section.kind.value == "warns" %} - {% include "docstring/warns"|get_template with context %} - {% elif config.show_docstring_yields and section.kind.value == "yields" %} - {% include "docstring/yields"|get_template with context %} - {% elif config.show_docstring_receives and section.kind.value == "receives" %} - {% include "docstring/receives"|get_template with context %} - {% elif config.show_docstring_returns and section.kind.value == "returns" %} - {% include "docstring/returns"|get_template with context %} - {% elif config.show_docstring_examples and section.kind.value == "examples" %} - {% include "docstring/examples"|get_template with context %} - {% elif config.show_docstring_description and section.kind.value == "admonition" %} - {% include "docstring/admonition"|get_template with context %} - {% endif %} - {% endfor %} + {% with autoref_hook = AutorefsHook(obj, config) %} + {% for section in docstring_sections %} + {% if config.show_docstring_description and section.kind.value == "text" %} + {{ section.value|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }} + {% elif config.show_docstring_attributes and section.kind.value == "attributes" %} + {% include "docstring/attributes"|get_template with context %} + {% elif config.show_docstring_functions and section.kind.value == "functions" %} + {% include "docstring/functions"|get_template with context %} + {% elif config.show_docstring_classes and section.kind.value == "classes" %} + {% include "docstring/classes"|get_template with context %} + {% elif config.show_docstring_modules and section.kind.value == "modules" %} + {% include "docstring/modules"|get_template with context %} + {% elif config.show_docstring_parameters and section.kind.value == "parameters" %} + {% include "docstring/parameters"|get_template with context %} + {% elif config.show_docstring_other_parameters and section.kind.value == "other parameters" %} + {% include "docstring/other_parameters"|get_template with context %} + {% elif config.show_docstring_raises and section.kind.value == "raises" %} + {% include "docstring/raises"|get_template with context %} + {% elif config.show_docstring_warns and section.kind.value == "warns" %} + {% include "docstring/warns"|get_template with context %} + {% elif config.show_docstring_yields and section.kind.value == "yields" %} + {% include "docstring/yields"|get_template with context %} + {% elif config.show_docstring_receives and section.kind.value == "receives" %} + {% include "docstring/receives"|get_template with context %} + {% elif config.show_docstring_returns and section.kind.value == "returns" %} + {% include "docstring/returns"|get_template with context %} + {% elif config.show_docstring_examples and section.kind.value == "examples" %} + {% include "docstring/examples"|get_template with context %} + {% elif config.show_docstring_description and section.kind.value == "admonition" %} + {% include "docstring/admonition"|get_template with context %} + {% endif %} + {% endfor %} + {% endwith %} {% endif %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html.jinja index 70f462db..ff6e9cbc 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html.jinja @@ -15,6 +15,6 @@ Context: {% endblock logs %}
- {{ section.title|convert_markdown(heading_level, html_id, strip_paragraph=True) }} - {{ section.value.contents|convert_markdown(heading_level, html_id) }} + {{ section.title|convert_markdown(heading_level, html_id, strip_paragraph=True, autoref_hook=autoref_hook) }} + {{ section.value.contents|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja index 34aa0119..0bb416e0 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja @@ -43,7 +43,7 @@ Context:
- {{ attribute.description|convert_markdown(heading_level, html_id) }} + {{ attribute.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -66,7 +66,7 @@ Context: {% endif %} –
- {{ attribute.description|convert_markdown(heading_level, html_id) }} + {{ attribute.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -88,7 +88,7 @@ Context: {{ attribute.name }}
- {{ attribute.description|convert_markdown(heading_level, html_id) }} + {{ attribute.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}

{% if attribute.annotation %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja index a3b494c9..82bae98c 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja @@ -35,7 +35,7 @@ Context: {{ class.name }}

- {{ class.description|convert_markdown(heading_level, html_id) }} + {{ class.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -53,7 +53,7 @@ Context: {{ class.name }}
- {{ class.description|convert_markdown(heading_level, html_id) }} + {{ class.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -75,7 +75,7 @@ Context: {{ class.name }}
- {{ class.description|convert_markdown(heading_level, html_id) }} + {{ class.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja index 39a90fa0..dd0b503f 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja @@ -21,7 +21,7 @@ Context:

{{ section.title or lang.t("Examples:") }}

{% for section_type, sub_section in section.value %} {% if section_type.value == "text" %} - {{ sub_section|convert_markdown(heading_level, html_id) }} + {{ sub_section|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }} {% elif section_type.value == "examples" %} {{ sub_section|highlight(language="pycon", linenums=False) }} {% endif %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja index efaf9a37..f979f4e5 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja @@ -36,7 +36,7 @@ Context: {{ function.name }}
- {{ function.description|convert_markdown(heading_level, html_id) }} + {{ function.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -56,7 +56,7 @@ Context: {{ function.name }}
- {{ function.description|convert_markdown(heading_level, html_id) }} + {{ function.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endif %} @@ -80,7 +80,7 @@ Context: {{ function.name }}
- {{ function.description|convert_markdown(heading_level, html_id) }} + {{ function.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja index caec690f..b18e69f0 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja @@ -35,7 +35,7 @@ Context: {{ module.name }}
- {{ module.description|convert_markdown(heading_level, html_id) }} + {{ module.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -53,7 +53,7 @@ Context: {{ module.name }}
- {{ module.description|convert_markdown(heading_level, html_id) }} + {{ module.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -75,7 +75,7 @@ Context: {{ module.name }}
- {{ module.description|convert_markdown(heading_level, html_id) }} + {{ module.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja index a8730966..24c6b194 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja @@ -43,7 +43,7 @@ Context:
- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -66,7 +66,7 @@ Context: {% endif %} –
- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -88,7 +88,7 @@ Context: {{ parameter.name }}
- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}

{% if parameter.annotation %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja index a2db4900..8b0556f3 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja @@ -44,7 +44,7 @@ Context:

- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -81,7 +81,7 @@ Context: {% endif %} –
- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -103,7 +103,7 @@ Context: {{ parameter.name }}
- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}

{% if parameter.annotation %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja index 21490f4e..f796494b 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja @@ -41,7 +41,7 @@ Context:

- {{ raises.description|convert_markdown(heading_level, html_id) }} + {{ raises.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -63,7 +63,7 @@ Context: – {% endif %}
- {{ raises.description|convert_markdown(heading_level, html_id) }} + {{ raises.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -91,7 +91,7 @@ Context:
- {{ raises.description|convert_markdown(heading_level, html_id) }} + {{ raises.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja index 86420b39..57df473f 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja @@ -44,7 +44,7 @@ Context:
- {{ receives.description|convert_markdown(heading_level, html_id) }} + {{ receives.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -69,7 +69,7 @@ Context: {% endif %} –
- {{ receives.description|convert_markdown(heading_level, html_id) }} + {{ receives.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -101,7 +101,7 @@ Context:
- {{ receives.description|convert_markdown(heading_level, html_id) }} + {{ receives.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% if receives.name and receives.annotation %}

diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja index d402369a..cab2ca77 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja @@ -44,7 +44,7 @@ Context:

- {{ returns.description|convert_markdown(heading_level, html_id) }} + {{ returns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -69,7 +69,7 @@ Context: {% endif %} –
- {{ returns.description|convert_markdown(heading_level, html_id) }} + {{ returns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -101,7 +101,7 @@ Context:
- {{ returns.description|convert_markdown(heading_level, html_id) }} + {{ returns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% if returns.name and returns.annotation %}

diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja index 702b9351..a892244a 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja @@ -41,7 +41,7 @@ Context:

- {{ warns.description|convert_markdown(heading_level, html_id) }} + {{ warns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -63,7 +63,7 @@ Context: – {% endif %}
- {{ warns.description|convert_markdown(heading_level, html_id) }} + {{ warns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -91,7 +91,7 @@ Context:
- {{ warns.description|convert_markdown(heading_level, html_id) }} + {{ warns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja index c83c478b..96c373dd 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja @@ -44,7 +44,7 @@ Context:
- {{ yields.description|convert_markdown(heading_level, html_id) }} + {{ yields.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -69,7 +69,7 @@ Context: {% endif %} –
- {{ yields.description|convert_markdown(heading_level, html_id) }} + {{ yields.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} @@ -101,7 +101,7 @@ Context:
- {{ yields.description|convert_markdown(heading_level, html_id) }} + {{ yields.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% if yields.name and yields.annotation %}

diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja index f02e0b9c..8df3f9f3 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja @@ -38,7 +38,7 @@ Context: {% endif %} –

- {{ attribute.description|convert_markdown(heading_level, html_id) }} + {{ attribute.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja index 34264133..287bbf3d 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja @@ -38,7 +38,7 @@ Context: {% endif %} –
- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja index 369912e7..da30d60a 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja @@ -43,7 +43,7 @@ Context: {% endif %} –
- {{ parameter.description|convert_markdown(heading_level, html_id) }} + {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja index 43d134f8..ffa3fad1 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja @@ -37,7 +37,7 @@ Context: {% endif %} –
- {{ raises.description|convert_markdown(heading_level, html_id) }} + {{ raises.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja index 636c17e4..40c77846 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja @@ -40,7 +40,7 @@ Context: {% endif %} –
- {{ receives.description|convert_markdown(heading_level, html_id) }} + {{ receives.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja index a00732d9..597d8932 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja @@ -40,7 +40,7 @@ Context: {% endif %} –
- {{ returns.description|convert_markdown(heading_level, html_id) }} + {{ returns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja index b445639c..d66ac431 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja @@ -37,7 +37,7 @@ Context: {% endif %} –
- {{ warns.description|convert_markdown(heading_level, html_id) }} + {{ warns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja index 91097828..4d4fc3d5 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja @@ -40,7 +40,7 @@ Context: {% endif %} –
- {{ yields.description|convert_markdown(heading_level, html_id) }} + {{ yields.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %} From 446d72515e96ae734056fb5b351a2faf99621bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 3 Sep 2024 15:05:37 +0200 Subject: [PATCH 2/5] chore: Prepare release 1.11.0 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 947cfe99..ca12d3ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.11.0](https://github.com/mkdocstrings/python/releases/tag/1.11.0) - 2024-09-03 + +[Compare with 1.10.9](https://github.com/mkdocstrings/python/compare/1.10.9...1.11.0) + +### Features + +- Hook into autorefs to provide context around cross-ref errors ([bb4be5b](https://github.com/mkdocstrings/python/commit/bb4be5be1b85be50f46c7889231a2d4a3bd05165) by Timothée Mazzucotelli). + ## [1.10.9](https://github.com/mkdocstrings/python/releases/tag/1.10.9) - 2024-08-30 [Compare with 1.10.8](https://github.com/mkdocstrings/python/compare/1.10.8...1.10.9) From 7b11ba86a6ca6a1e8ec5d720e0d167062b44a4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 3 Sep 2024 19:13:38 +0200 Subject: [PATCH 3/5] docs: Update docs from insiders --- docs/insiders/changelog.md | 26 ++++++ docs/insiders/goals.yml | 19 +++- docs/snippets/package/__init__.py | 19 ++++ docs/snippets/package/modern.py | 3 + docs/usage/configuration/general.md | 85 +++++++++++++++++ docs/usage/configuration/headings.md | 123 +++++++++++++++++++++++++ docs/usage/configuration/signatures.md | 87 +++++++++++++++++ docs/usage/customization.md | 20 ++++ mkdocs.yml | 15 ++- 9 files changed, 391 insertions(+), 6 deletions(-) create mode 100644 docs/snippets/package/__init__.py create mode 100644 docs/snippets/package/modern.py diff --git a/docs/insiders/changelog.md b/docs/insiders/changelog.md index 3c8ac843..ab70887a 100644 --- a/docs/insiders/changelog.md +++ b/docs/insiders/changelog.md @@ -2,6 +2,32 @@ ## mkdocstrings-python Insiders +### 1.8.3 June 19, 2024 { id="1.8.3" } + +- Update code for Griffe 0.46+ to avoid deprecation warnings + +### 1.8.2 May 09, 2024 { id="1.8.2" } + +- Don't render cross-refs for default values when signatures aren't separated + +### 1.8.1 April 19, 2024 { id="1.8.1" } + +- Render enumeration instance name instead of just "value", allowing proper cross-reference + +### 1.8.0 March 24, 2024 { id="1.8.0" } + +- [Annotations modernization][modernize_annotations] + +### 1.7.0 March 24, 2024 { id="1.7.0" } + +- [Class inheritance diagrams with Mermaid][show_inheritance_diagram] + +### 1.6.0 January 30, 2024 { id="1.6.0" } + +- Render cross-references to parameters documentation in signatures and attribute values. +- Add [`parameter_headings`][parameter_headings] option to render headings for parameters (enabling permalinks and ToC/inventory entries). +- Render cross-references for default parameter values in signatures. + ### 1.5.1 September 12, 2023 { id="1.5.1" } - Prevent empty auto-summarized Methods section. diff --git a/docs/insiders/goals.yml b/docs/insiders/goals.yml index 381e5029..57985eae 100644 --- a/docs/insiders/goals.yml +++ b/docs/insiders/goals.yml @@ -16,9 +16,24 @@ goals: since: 2023/08/20 - name: Automatic rendering of function signature overloads since: 2023/09/05 + - name: Parameter headings + ref: /usage/configuration/headings/#parameter_headings + since: 2024/01/30 + - name: Automatic cross-references to parameters + ref: /usage/configuration/headings/#parameter_headings + since: 2024/01/30 + - name: Automatic cross-references for default parameter values in signatures + since: 2024/01/30 1500: name: HyperLamp Navigation Tips - features: [] + features: + - name: Class inheritance diagrams with Mermaid + ref: /usage/configuration/general/#show_inheritance_diagram + since: 2024/03/24 + - name: Annotations modernization + ref: /usage/configuration/signatures/#modernize_annotations + since: 2024/03/24 2000: name: FusionDrive Ejection Configuration - features: [] + features: + - name: Relative cross-references diff --git a/docs/snippets/package/__init__.py b/docs/snippets/package/__init__.py new file mode 100644 index 00000000..b19123b7 --- /dev/null +++ b/docs/snippets/package/__init__.py @@ -0,0 +1,19 @@ +from importlib import metadata + +def get_version(dist: str = "mkdocstrings-python") -> str: + """Get version of the given distribution. + + Parameters: + dist: A distribution name. + + Returns: + A version number. + """ + try: + return metadata.version(dist) + except metadata.PackageNotFoundError: + return "0.0.0" + + +current_version: str = get_version(dist="mkdocstrings-python") +"""Current package version.""" diff --git a/docs/snippets/package/modern.py b/docs/snippets/package/modern.py new file mode 100644 index 00000000..c992b5df --- /dev/null +++ b/docs/snippets/package/modern.py @@ -0,0 +1,3 @@ +from typing import Optional, Union, List + +example: Optional[Union[int, List[int]]] = None diff --git a/docs/usage/configuration/general.md b/docs/usage/configuration/general.md index d8d7f250..e2a6e169 100644 --- a/docs/usage/configuration/general.md +++ b/docs/usage/configuration/general.md @@ -92,6 +92,91 @@ plugins: //// /// +## `show_inheritance_diagram` + +[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } — +[:octicons-tag-24: Insiders 1.7.0](../../insiders/changelog.md#1.7.0) + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Show the inheritance diagram of a class using [Mermaid](https://mermaid.js.org/). + +With this option enabled, an inheritance diagram (as a flowchart) +will be displayed after a class signature. +Each node will act as a cross-reference +and will bring you to the relevant class' documentation +when clicking on it. + +It should work out of the box with [Material for MkDocs][]. +For other themes, you must include Mermaid's Javascript code manually: + +```yaml title="mkdocs.yml" +extra_javascript: +- https://unpkg.com/mermaid@10.9.0/dist/mermaid.min.js +``` + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + show_inheritance_diagram: true +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.object + options: + show_inheritance_diagram: false +``` + +/// admonition | Preview + type: preview + +With the following classes: + +```python +class SuperAbstract: + """Super abstract class.""" +class Mixin1: + """Mixin 1.""" +class Abstract(SuperAbstract, Mixin1): + """Abstract class.""" +class Mixin2A: + """Mixin 2A.""" +class Mixin2B(Mixin2A): + """Mixin 2B.""" +class Concrete(Abstract, Mixin2B): + """Concrete class.""" +class SuperConcrete(Concrete): + """Super concrete class.""" +``` + +The diagram for `SuperConcrete` will look like this: + +```mermaid +flowchart TD +SuperConcrete[SuperConcrete] +Concrete[Concrete] +Abstract[Abstract] +SuperAbstract[SuperAbstract] +Mixin1[Mixin1] +Mixin2B[Mixin2B] +Mixin2A[Mixin2A] + +Concrete --> SuperConcrete +Abstract --> Concrete +SuperAbstract --> Abstract +Mixin1 --> Abstract +Mixin2B --> Concrete +Mixin2A --> Mixin2B +``` + +*Nodes are not clickable in this example +because these classes do not exist in our documentation.* +/// + ## `show_source` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** diff --git a/docs/usage/configuration/headings.md b/docs/usage/configuration/headings.md index a9b75e6d..63950206 100644 --- a/docs/usage/configuration/headings.md +++ b/docs/usage/configuration/headings.md @@ -57,6 +57,129 @@ plugins: //// /// +## `parameter_headings` + +[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } — +[:octicons-tag-24: Insiders 1.6.0](../../insiders/changelog.md#1.6.0) + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Whether to render headings for function/method parameters. + +With this option enabled, each function/method parameter +(including parameters of `__init__` methods merged in their parent class +with the [`merge_init_into_class`][] option) +gets a permalink, an entry in the Table of Contents, +and an entry in the generated objects inventory. +The permalink and inventory entry allow cross-references +from internal and external pages. + +The identifier used in the permalink and inventory is of the following form: +`path.to.function(param_name)`. To manually cross-reference a parameter, +you can therefore use this Markdown syntax: + +```md +- Class parameter: [`param`][package.module.Class(param)] +- Method parameter: [`param`][package.module.Class.method(param)] +- Function parameter: [`param`][package.module.function(param)] +- Variadic positional parameters: [`*args`][package.module.function(*args)] +- Variadic keyword parameters: [`**kwargs`][package.module.function(**kwargs)] +``` + +Enabling this option along with [`signature_crossrefs`][] will automatically +render cross-references to parameters in class/function/method signatures +and attributes values. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + parameter_headings: false +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.module + options: + parameter_headings: true +``` + +/// admonition | Preview: Cross-references + type: preview + +```md exec="on" +::: package.get_version + options: + heading_level: 3 + parameter_headings: true + docstring_section_style: list + +::: package.current_version + options: + heading_level: 3 + line_length: 100 +``` + +/// + +/// admonition | Preview: Parameter sections + type: preview + +//// tab | Table style +```md exec="on" +::: package.get_version + options: + heading_level: 3 + show_root_heading: false + show_root_toc_entry: false + parameter_headings: true + docstring_section_style: table + show_docstring_returns: false + show_docstring_description: false +``` +//// + +//// tab | List style +```md exec="on" +::: package.get_version + options: + heading_level: 3 + show_root_heading: false + show_root_toc_entry: false + parameter_headings: true + docstring_section_style: list + show_docstring_returns: false + show_docstring_description: false +``` +//// + +//// tab | Spacy style +```md exec="on" +::: package.get_version + options: + heading_level: 3 + show_root_heading: false + show_root_toc_entry: false + parameter_headings: true + docstring_section_style: spacy + show_docstring_returns: false + show_docstring_description: false +``` +//// +/// + +/// admonition | Preview: Table of contents (with symbol types) + type: preview + + get_version
+ dist + +To customize symbols, see [Customizing symbol types](../customization.md/#symbol-types). + +/// + ## `show_root_heading` - **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** diff --git a/docs/usage/configuration/signatures.md b/docs/usage/configuration/signatures.md index da96dc5b..e5e4cb88 100644 --- a/docs/usage/configuration/signatures.md +++ b/docs/usage/configuration/signatures.md @@ -193,6 +193,93 @@ plugins: //// /// +## `modernize_annotations` + +[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } — +[:octicons-tag-24: Insiders 1.8.0](../../insiders/changelog.md#1.8.0) — +**This feature also requires +[Griffe Insiders](https://mkdocstrings.github.io/griffe/insiders/) +to be installed.** + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Modernize annotations with latest features and PEPs of the Python language. + +The Python language keeps evolving, and often library developers +must continue to support a few minor versions of Python. +Therefore they cannot use some features that were introduced +in the latest versions. + +Yet this doesn't mean they can't enjoy latest features in their docs: +Griffe allows to "modernize" expressions, for example +by replacing `typing.Union` with [PEP 604][pep-604] type unions `|`. +Thanks to this, mkdocstrings' Python handler +can automatically transform type annotations into their modern equivalent. +This improves consistency in your docs, and shows users +how to use your code with the latest features of the language. + +[pep-604]: https://peps.python.org/pep-0604/ + +Modernizations applied: + +- `typing.Dict[A, B]` becomes `dict[A, B]` +- `typing.List[A]` becomes `list[A]` +- `typing.Set[A]` becomes `set[A]` +- `typing.Tuple[A]` becomes `tuple[A]` +- `typing.Union[A, B]` becomes `A | B` +- `typing.Optional[A]` becomes `A | None` + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + modernize_annotations: true +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.object + options: + modernize_annotations: false +``` + +/// admonition | Preview + type: preview + +```python +--8<-- "docs/snippets/package/modern.py" +``` + +//// tab | Unchanged annotations + +```md exec="on" +::: package.modern.example + options: + modernize_annotations: false + show_symbol_type_heading: false + show_labels: false +``` + +//// + +//// tab | Modernized annotations + +```md exec="on" +::: package.modern.example + options: + modernize_annotations: true + show_symbol_type_heading: false + show_labels: false +``` + +//// + +/// + + + ## `show_signature` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** diff --git a/docs/usage/customization.md b/docs/usage/customization.md index 5e82001e..907809c8 100644 --- a/docs/usage/customization.md +++ b/docs/usage/customization.md @@ -89,12 +89,14 @@ by overriding the values of our CSS variables, for example: ```css title="docs/css/mkdocstrings.css" [data-md-color-scheme="default"] { + --doc-symbol-parameter-fg-color: #df50af; --doc-symbol-attribute-fg-color: #0079ff; --doc-symbol-function-fg-color: #00dfa2; --doc-symbol-method-fg-color: #00dfa2; --doc-symbol-class-fg-color: #d1b619; --doc-symbol-module-fg-color: #ff0060; + --doc-symbol-parameter-bg-color: #df50af1a; --doc-symbol-attribute-bg-color: #0079ff1a; --doc-symbol-function-bg-color: #00dfa21a; --doc-symbol-method-bg-color: #00dfa21a; @@ -103,12 +105,14 @@ by overriding the values of our CSS variables, for example: } [data-md-color-scheme="slate"] { + --doc-symbol-parameter-fg-color: #ffa8cc; --doc-symbol-attribute-fg-color: #963fb8; --doc-symbol-function-fg-color: #6d67e4; --doc-symbol-method-fg-color: #6d67e4; --doc-symbol-class-fg-color: #46c2cb; --doc-symbol-module-fg-color: #f2f7a1; + --doc-symbol-parameter-bg-color: #ffa8cc1a; --doc-symbol-attribute-bg-color: #963fb81a; --doc-symbol-function-bg-color: #6d67e41a; --doc-symbol-method-bg-color: #6d67e41a; @@ -124,12 +128,14 @@ otherwise just override the variables at root level: ```css title="docs/css/mkdocstrings.css" :root { + --doc-symbol-parameter-fg-color: #df50af; --doc-symbol-attribute-fg-color: #0079ff; --doc-symbol-function-fg-color: #00dfa2; --doc-symbol-method-fg-color: #00dfa2; --doc-symbol-class-fg-color: #d1b619; --doc-symbol-module-fg-color: #ff0060; + --doc-symbol-parameter-bg-color: #df50af1a; --doc-symbol-attribute-bg-color: #0079ff1a; --doc-symbol-function-bg-color: #00dfa21a; --doc-symbol-method-bg-color: #00dfa21a; @@ -144,12 +150,14 @@ otherwise just override the variables at root level:

Try cycling through the themes to see the colors for each theme: + @@ -189,6 +200,10 @@ You can also change the actual symbol names. For example, to use single letters instead of truncated types: ```css title="docs/css/mkdocstrings.css" +.doc-symbol-parameter::after { + content: "P"; +} + .doc-symbol-attribute::after { content: "A"; } @@ -215,6 +230,10 @@ For example, to use single letters instead of truncated types:

    +
  • Parameter:
  • Attribute:
  • Function:
  • Method:
  • diff --git a/mkdocs.yml b/mkdocs.yml index 040ab89b..19aa90d9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -116,14 +116,16 @@ markdown_extensions: emoji_generator: !!python/name:material.extensions.emoji.to_svg - pymdownx.highlight: pygments_lang_class: true -- pymdownx.inlinehilite: - style_plain_text: py3 - pymdownx.magiclink - pymdownx.snippets: auto_append: [docs/.glossary.md] base_path: [!relative $config_dir] check_paths: true -- pymdownx.superfences +- pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format - pymdownx.tabbed: alternate_style: true slugify: !!python/object/apply:pymdownx.slugs.slugify @@ -147,10 +149,11 @@ plugins: - mkdocstrings: handlers: python: - paths: [src] + paths: [src, docs/snippets] import: - https://docs.python.org/3/objects.inv - https://mkdocstrings.github.io/objects.inv + - https://mkdocstrings.github.io/autorefs/objects.inv - https://mkdocstrings.github.io/griffe/objects.inv - https://python-markdown.github.io/objects.inv options: @@ -163,7 +166,11 @@ plugins: merge_init_into_class: true parameter_headings: true preload_modules: [mkdocstrings] + relative_crossrefs: true + scoped_crossrefs: true separate_signature: true + show_bases: false + show_inheritance_diagram: true show_root_heading: true show_root_full_path: false show_signature_annotations: true From dd8b014a8ab3decc31d4b08bc22fe68577e1a02c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 3 Sep 2024 19:20:08 +0200 Subject: [PATCH 4/5] refactor: Prepare `relative_crossrefs` and `scoped_crossrefs` insiders features --- docs/insiders/changelog.md | 5 + docs/insiders/goals.yml | 5 + docs/usage/configuration/docstrings.md | 220 ++++++++++++++++++ src/mkdocstrings_handlers/python/handler.py | 4 + .../templates/material/_base/class.html.jinja | 6 +- 5 files changed, 238 insertions(+), 2 deletions(-) diff --git a/docs/insiders/changelog.md b/docs/insiders/changelog.md index ab70887a..a6c7b907 100644 --- a/docs/insiders/changelog.md +++ b/docs/insiders/changelog.md @@ -2,6 +2,11 @@ ## mkdocstrings-python Insiders +### 1.9.0 September 03, 2024 { id="1.9.0" } + +- [Relative cross-references][relative_crossrefs] +- [Scoped cross-references][scoped_crossrefs] + ### 1.8.3 June 19, 2024 { id="1.8.3" } - Update code for Griffe 0.46+ to avoid deprecation warnings diff --git a/docs/insiders/goals.yml b/docs/insiders/goals.yml index 57985eae..16d1d507 100644 --- a/docs/insiders/goals.yml +++ b/docs/insiders/goals.yml @@ -37,3 +37,8 @@ goals: name: FusionDrive Ejection Configuration features: - name: Relative cross-references + ref: /usage/configuration/docstrings/#relative_crossrefs + since: 2024/09/03 + - name: Scoped cross-references + ref: /usage/configuration/docstrings/#scoped_crossrefs + since: 2024/09/03 diff --git a/docs/usage/configuration/docstrings.md b/docs/usage/configuration/docstrings.md index 027ebaed..d88cbbfb 100644 --- a/docs/usage/configuration/docstrings.md +++ b/docs/usage/configuration/docstrings.md @@ -317,6 +317,226 @@ class Thing: //// /// +## `relative_crossrefs` + +[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } — +[:octicons-tag-24: Insiders 1.9.0](../../insiders/changelog.md#1.9.0) + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Whether to enable the relative-crossref syntax. + +The relative-crossref syntax lets you reference the current object or its parent by prefixing a crossref identifier with dots. For example, to cross-reference the current object's `name` member, you can write `[link to name attribute][.name]`. The "current object" is the object containing the docstring being rendered. + + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + relative_crossrefs: false +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.module + options: + relative_crossrefs: true +``` + +/// admonition | Examples + type: preview + +```python title="pkg/module.py" +"""Summary. + +- Link to [`module`][.]. +- Link to [`module_attribute`][.module_attribute]. +- Link to [`Class`][.Class]. +- Link to [`class_attribute`][.Class.class_attribute]. +- Link to [`instance_attribute`][.Class.instance_attribute]. +- Link to [`method`][.Class.method]. +""" + +module_attribute = 0 +"""Summary. + +- Link to [`module`][..]. +- Link to [`module_attribute`][.]. +- Link to [`Class`][..Class]. +- Link to [`class_attribute`][..Class.class_attribute]. +- Link to [`instance_attribute`][..Class.instance_attribute]. +- Link to [`method`][..Class.method]. +""" + +class Class: + """Summary. + + - Link to [`module`][..]. + - Link to [`module_attribute`][..module_attribute]. + - Link to [`Class`][.]. + - Link to [`class_attribute`][.class_attribute]. + - Link to [`instance_attribute`][.instance_attribute]. + - Link to [`method`][.method]. + """ + + class_attribute = 0 + """Summary. + + - Link to [`module`][...]. + - Link to [`module_attribute`][...module_attribute]. + - Link to [`Class`][..]. + - Link to [`class_attribute`][.]. + - Link to [`instance_attribute`][..instance_attribute]. + - Link to [`method`][..method]. + """ + + def __init__(self): + """Summary. + + - Link to [`module`][...]. + - Link to [`module_attribute`][...module_attribute]. + - Link to [`Class`][..]. + - Link to [`class_attribute`][..class_attribute]. + - Link to [`instance_attribute`][..instance_attribute]. + - Link to [`method`][..method]. + """ + self.instance_attribute = 0 + """Summary. + + - Link to [`module`][...]. + - Link to [`module_attribute`][...module_attribute]. + - Link to [`Class`][..]. + - Link to [`class_attribute`][..class_attribute]. + - Link to [`instance_attribute`][.]. + - Link to [`method`][..method]. + """ + + def method(self): + """Summary. + + - Link to [`module`][...]. + - Link to [`module_attribute`][...module_attribute]. + - Link to [`Class`][..]. + - Link to [`class_attribute`][..class_attribute]. + - Link to [`instance_attribute`][..instance_attribute]. + - Link to [`method`][.]. + """ +``` + +/// + + +## `scoped_crossrefs` + +[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } — +[:octicons-tag-24: Insiders 1.9.0](../../insiders/changelog.md#1.9.0) + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Whether to enable scoped cross-references. + +With scoped cross-references, you can write identifiers as if you wanted to access them from the current object's scope. The scoping rules do not exactly match Python's: you can reference members and siblings too, without prefixing with `self.` or `cls.`. + +The following order is applied when resolving a name in a given scope: + +1. member of the current object +2. parent class +3. repeat 1-2 within parent's scope + +In practice, it means that the name is first looked up in members, then it is compared against the parent name (only if it's a class), then it is looked up in siblings. It continues climbing up the object tree until there's no parent, in which case it raises a name resolution error. + +Cross-referencing an imported object will directly link to this object if the objects inventory of the project it comes from was [loaded][import]. You won't be able to cross-reference it within your own documentation with scoped references, if you happen to be rendering this external object too. In that case, you can use an absolute reference or a [relative][relative_crossrefs] one instead. + +Another limitation is that you won't be able to reference an external package if its name can be resolved in the current object's scope. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + scoped_crossrefs: false +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.module + options: + scoped_crossrefs: true +``` + +/// admonition | Examples + type: preview + +```python title="pkg/module.py" +"""Summary. + +- Link to [`module_attribute`][module_attribute]. +- Link to [`Class`][Class]. +- Link to [`class_attribute`][Class.class_attribute]. +- Link to [`instance_attribute`][Class.instance_attribute]. +- Link to [`method`][Class.method]. +""" + +module_attribute = 0 +"""Summary. + +- Link to [`Class`][Class]. +- Link to [`class_attribute`][Class.class_attribute]. +- Link to [`instance_attribute`][Class.instance_attribute]. +- Link to [`method`][Class.method]. +""" + +class Class: + """Summary. + + - Link to [`module_attribute`][module_attribute]. + - Link to [`class_attribute`][class_attribute]. + - Link to [`instance_attribute`][instance_attribute]. + - Link to [`method`][method]. + """ + + class_attribute = 0 + """Summary. + + - Link to [`module_attribute`][module_attribute]. + - Link to [`Class`][Class]. + - Link to [`instance_attribute`][instance_attribute]. + - Link to [`method`][method]. + """ + + def __init__(self): + """Summary. + + - Link to [`module_attribute`][module_attribute]. + - Link to [`Class`][Class]. + - Link to [`class_attribute`][class_attribute]. + - Link to [`instance_attribute`][instance_attribute]. + - Link to [`method`][method]. + """ + self.instance_attribute = 0 + """Summary. + + - Link to [`module_attribute`][module_attribute]. + - Link to [`Class`][Class]. + - Link to [`class_attribute`][class_attribute]. + - Link to [`method`][method]. + """ + + def method(self): + """Summary. + + - Link to [`module_attribute`][module_attribute]. + - Link to [`Class`][Class]. + - Link to [`class_attribute`][class_attribute]. + - Link to [`instance_attribute`][instance_attribute]. + """ +``` + +/// + ## `show_if_no_docstring` - **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index eb1d73c7..ef93ee3b 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -85,6 +85,8 @@ class PythonHandler(BaseHandler): "separate_signature": False, "line_length": 60, "merge_init_into_class": False, + "relative_crossrefs": False, + "scoped_crossrefs": False, "show_docstring_attributes": True, "show_docstring_functions": True, "show_docstring_classes": True, @@ -168,6 +170,8 @@ class PythonHandler(BaseHandler): docstring_options (dict): The options for the docstring parser. See [docstring parsers](https://mkdocstrings.github.io/griffe/reference/docstrings/) and their options in Griffe docs. docstring_section_style (str): The style used to render docstring sections. Options: `table`, `list`, `spacy`. Default: `"table"`. merge_init_into_class (bool): Whether to merge the `__init__` method into the class' signature and docstring. Default: `False`. + relative_crossrefs (bool): Whether to enable the relative crossref syntax. Default: `False`. + scoped_crossrefs (bool): Whether to enable the scoped crossref ability. Default: `False`. show_if_no_docstring (bool): Show the object heading even if it has no docstring or children with docstrings. Default: `False`. show_docstring_attributes (bool): Whether to display the "Attributes" section in the object's docstring. Default: `True`. show_docstring_functions (bool): Whether to display the "Functions" or "Methods" sections in the object's docstring. Default: `True`. diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja index 27a91d13..fd13661b 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja @@ -133,8 +133,10 @@ Context: {% endwith %} {% if config.merge_init_into_class %} {% if "__init__" in class.all_members and class.all_members["__init__"].has_docstring %} - {% with docstring_sections = class.all_members["__init__"].docstring.parsed %} - {% include "docstring"|get_template with context %} + {% with function = class.all_members["__init__"] %} + {% with obj = function, docstring_sections = function.docstring.parsed %} + {% include "docstring"|get_template with context %} + {% endwith %} {% endwith %} {% endif %} {% endif %} From 6dafa9ac307fb476ea4b2a17190718ca059c9811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 3 Sep 2024 19:20:36 +0200 Subject: [PATCH 5/5] chore: Prepare release 1.11.1 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca12d3ae..f1668147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.11.1](https://github.com/mkdocstrings/python/releases/tag/1.11.1) - 2024-09-03 + +[Compare with 1.11.0](https://github.com/mkdocstrings/python/compare/1.11.0...1.11.1) + +### Code Refactoring + +- Prepare `relative_crossrefs` and `scoped_crossrefs` insiders features ([dd8b014](https://github.com/mkdocstrings/python/commit/dd8b014a8ab3decc31d4b08bc22fe68577e1a02c) by Timothée Mazzucotelli). + ## [1.11.0](https://github.com/mkdocstrings/python/releases/tag/1.11.0) - 2024-09-03 [Compare with 1.10.9](https://github.com/mkdocstrings/python/compare/1.10.9...1.11.0)