From 84ea8a4ad70e3a69fe845ee807367015cce3b5d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Thu, 23 Jan 2025 23:51:31 +0100 Subject: [PATCH 01/14] test: Ignore deprecation warning about fallback anchor function --- config/pytest.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/config/pytest.ini b/config/pytest.ini index 9d75f5c6..25f9c92e 100644 --- a/config/pytest.ini +++ b/config/pytest.ini @@ -12,6 +12,4 @@ filterwarnings = error # TODO: remove once pytest-xdist 4 is released ignore:.*rsyncdir:DeprecationWarning:xdist - # TODO: remove once Griffe releases v1 - ignore:.*`get_logger`:DeprecationWarning:_griffe - ignore:.*`name`:DeprecationWarning:_griffe + ignore:.*fallback anchor function:DeprecationWarning:mkdocstrings From 83823be2146d6a2ecedc5fe9c0cfd84098d780ca Mon Sep 17 00:00:00 2001 From: Uchechukwu Orji Date: Fri, 24 Jan 2025 00:12:18 +0100 Subject: [PATCH 02/14] feat: Add `force_inspection` option to force dynamic analysis Griffe supports this option but mkdocstrings-python didn't allow users to configure it. Issue-94: https://github.com/mkdocstrings/python/issues/94 PR-231: https://github.com/mkdocstrings/python/pull/231 --- docs/usage/configuration/general.md | 24 +++++++++++++++++++++ src/mkdocstrings_handlers/python/handler.py | 3 +++ 2 files changed, 27 insertions(+) diff --git a/docs/usage/configuration/general.md b/docs/usage/configuration/general.md index e2a6e169..461556bf 100644 --- a/docs/usage/configuration/general.md +++ b/docs/usage/configuration/general.md @@ -55,6 +55,30 @@ plugins: //// /// +## `force_inspection` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Whether to force inspecting modules (importing them) even if their source code is available. + +This option is useful when you know that dynamic analysis (inspection) yields better results than static analysis. Do not use this blindly: the recommended approach is to write a Griffe extension that will improve extracted API data. See [How to selectively inspect objects](https://mkdocstrings.github.io/griffe/guide/users/how-to/selectively-inspect/). + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + force_inspection: false +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.object + options: + force_inspection: true +``` + ## `show_bases` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 4171fd76..e57ae9e7 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -116,6 +116,7 @@ class PythonHandler(BaseHandler): "annotations_path": "brief", "preload_modules": None, "allow_inspection": True, + "force_inspection": False, "summary": False, "show_labels": True, "unwrap_annotated": False, @@ -127,6 +128,7 @@ class PythonHandler(BaseHandler): Attributes: General options: find_stubs_package (bool): Whether to load stubs package (package-stubs) when extracting docstrings. Default `False`. allow_inspection (bool): Whether to allow inspecting modules when visiting them is not possible. Default: `True`. + force_inspection (bool): Whether to force using dynamic analysis when loading data. Default: `False`. show_bases (bool): Show the base classes of a class. Default: `True`. show_inheritance_diagram (bool): Show the inheritance diagram of a class using Mermaid. Default: `False`. show_source (bool): Show the source code of this object. Default: `True`. @@ -318,6 +320,7 @@ def collect(self, identifier: str, config: Mapping[str, Any]) -> CollectorItem: modules_collection=self._modules_collection, lines_collection=self._lines_collection, allow_inspection=final_config["allow_inspection"], + force_inspection=final_config["force_inspection"], ) try: for pre_loaded_module in final_config.get("preload_modules") or []: From b0b813aa0b30e12afaea23b173da427bb71e6eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 29 Jan 2025 15:01:03 +0100 Subject: [PATCH 03/14] style: Remove trailing spaces --- CHANGELOG.md | 6 +++--- docs/.glossary.md | 2 +- docs/.overrides/main.html | 4 ++-- docs/.overrides/partials/comments.html | 2 +- docs/insiders/index.md | 4 ++-- docs/insiders/installation.md | 8 ++++---- docs/usage/configuration/general.md | 2 +- docs/usage/configuration/headings.md | 16 +++++++-------- docs/usage/configuration/signatures.md | 2 +- docs/usage/customization.md | 6 +++--- docs/usage/docstrings/google.md | 4 ++-- docs/usage/index.md | 10 +++++----- .../material/_base/attribute.html.jinja | 12 +++++------ .../material/_base/children.html.jinja | 2 +- .../templates/material/_base/class.html.jinja | 20 +++++++++---------- .../material/_base/docstring.html.jinja | 2 +- .../_base/docstring/admonition.html.jinja | 2 +- .../_base/docstring/attributes.html.jinja | 2 +- .../_base/docstring/classes.html.jinja | 2 +- .../_base/docstring/examples.html.jinja | 2 +- .../_base/docstring/functions.html.jinja | 2 +- .../_base/docstring/modules.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 +- .../material/_base/docstring/warns.html.jinja | 2 +- .../_base/docstring/yields.html.jinja | 2 +- .../material/_base/expression.html.jinja | 4 ++-- .../material/_base/function.html.jinja | 14 ++++++------- .../material/_base/labels.html.jinja | 2 +- .../material/_base/language.html.jinja | 2 +- .../material/_base/languages/en.html.jinja | 2 +- .../material/_base/languages/ja.html.jinja | 2 +- .../material/_base/languages/zh.html.jinja | 2 +- .../material/_base/module.html.jinja | 14 ++++++------- .../material/_base/signature.html.jinja | 2 +- .../material/_base/summary.html.jinja | 2 +- .../_base/summary/attributes.html.jinja | 2 +- .../material/_base/summary/classes.html.jinja | 2 +- .../_base/summary/functions.html.jinja | 2 +- .../material/_base/summary/modules.html.jinja | 2 +- .../_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 +- .../readthedocs/_base/language.html.jinja | 2 +- 52 files changed, 100 insertions(+), 100 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec519312..7cd3818a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -227,12 +227,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Release Insiders features of the $500/month funding goal ([bd30106](https://github.com/mkdocstrings/python/commit/bd301061fe9c647f9b91c2c9b4baa784c304eca7) by Timothée Mazzucotelli). The features and projects related to *mkdocstrings-python* are: - + - [Cross-references for type annotations in signatures](https://mkdocstrings.github.io/python/usage/configuration/signatures/#signature_crossrefs) - [Symbol types in headings and table of contents](https://mkdocstrings.github.io/python/usage/configuration/headings/#show_symbol_type_toc) - [`griffe-inherited-docstrings`](https://mkdocstrings.github.io/griffe-inherited-docstrings/), a Griffe extension for inheriting docstrings - [`griffe2md`](https://mkdocstrings.github.io/griffe2md/), a tool to output API docs to Markdown using Griffe - + See the complete list of features and projects here: https://pawamoy.github.io/insiders/#500-plasmavac-user-guide. @@ -464,7 +464,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. You can see how to use the filter in this commit's changes: [f686f4e4](https://github.com/mkdocstrings/python/commit/f686f4e4599cea64686d4ef4863b507dd096a513). - + **We take this as an opportunity to go out of beta and bump the version to 1.0.0. This will allow users to rely on semantic versioning.** diff --git a/docs/.glossary.md b/docs/.glossary.md index 917c95c4..e11a6781 100644 --- a/docs/.glossary.md +++ b/docs/.glossary.md @@ -6,7 +6,7 @@ [Griffe]: https://github.com/mkdocstrings/griffe [ReadTheDocs Sphinx theme]: https://sphinx-rtd-theme.readthedocs.io/en/stable/index.html [Spacy's documentation]: https://spacy.io/api/doc/ -[Black]: https://pypi.org/project/black/ +[Black]: https://pypi.org/project/black/ [Material for MkDocs]: https://squidfunk.github.io/mkdocs-material [Ruff]: https://docs.astral.sh/ruff diff --git a/docs/.overrides/main.html b/docs/.overrides/main.html index 1e956857..5bedfd03 100644 --- a/docs/.overrides/main.html +++ b/docs/.overrides/main.html @@ -1,13 +1,13 @@ {% extends "base.html" %} {% block announce %} - + Fund this project through sponsorship {% include ".icons/octicons/heart-fill-16.svg" %} — - + Follow @pawamoy on diff --git a/docs/.overrides/partials/comments.html b/docs/.overrides/partials/comments.html index 0dedc405..1d5c6051 100644 --- a/docs/.overrides/partials/comments.html +++ b/docs/.overrides/partials/comments.html @@ -31,7 +31,7 @@

Feedback

: "light" // Instruct Giscus to set theme - giscus.setAttribute("data-theme", theme) + giscus.setAttribute("data-theme", theme) } // Register event handlers after documented loaded diff --git a/docs/insiders/index.md b/docs/insiders/index.md index 17a11ce4..288075b1 100644 --- a/docs/insiders/index.md +++ b/docs/insiders/index.md @@ -161,7 +161,7 @@ You can cancel your sponsorship anytime.[^5] The following section lists all funding goals. Each goal contains a list of features prefixed with a checkmark symbol, denoting whether a feature is -:octicons-check-circle-fill-24:{ style="color: #00e676" } already available or +:octicons-check-circle-fill-24:{ style="color: #00e676" } already available or :octicons-check-circle-fill-24:{ style="color: var(--md-default-fg-color--lightest)" } planned, but not yet implemented. When the funding goal is hit, the features are released for general availability. @@ -221,7 +221,7 @@ by the [ISC License][license]. However, we kindly ask you to respect our - Please **don't distribute the source code** of Insiders. You may freely use it for public, private or commercial projects, privately fork or mirror it, - but please don't make the source code public, as it would counteract the + but please don't make the source code public, as it would counteract the sponsorware strategy. - If you cancel your subscription, you're automatically removed as a diff --git a/docs/insiders/installation.md b/docs/insiders/installation.md index 0e4628ca..3588e691 100644 --- a/docs/insiders/installation.md +++ b/docs/insiders/installation.md @@ -42,21 +42,21 @@ Or using HTTPS: pip install git+https://${GH_TOKEN}@github.com/pawamoy-insiders/mkdocstrings-python.git ``` ->? NOTE: **How to get a GitHub personal access token** +>? NOTE: **How to get a GitHub personal access token?** > The `GH_TOKEN` environment variable is a GitHub token. > It can be obtained by creating a [personal access token] for > your GitHub account. It will give you access to the Insiders repository, > programmatically, from the command line or GitHub Actions workflows: -> +> > 1. Go to https://github.com/settings/tokens > 2. Click on [Generate a new token] > 3. Enter a name and select the [`repo`][scopes] scope > 4. Generate the token and store it in a safe place -> +> > [personal access token]: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token > [Generate a new token]: https://github.com/settings/tokens/new > [scopes]: https://docs.github.com/en/developers/apps/scopes-for-oauth-apps#available-scopes -> +> > Note that the personal access > token must be kept secret at all times, as it allows the owner to access your > private repositories. diff --git a/docs/usage/configuration/general.md b/docs/usage/configuration/general.md index 461556bf..dd621735 100644 --- a/docs/usage/configuration/general.md +++ b/docs/usage/configuration/general.md @@ -274,7 +274,7 @@ plugins: ::: your_package.your_module options: preload_modules: - - their_package + - their_package ``` ```python title="your_package/your_module.py" diff --git a/docs/usage/configuration/headings.md b/docs/usage/configuration/headings.md index 467779e4..ef961ad4 100644 --- a/docs/usage/configuration/headings.md +++ b/docs/usage/configuration/headings.md @@ -286,15 +286,15 @@ More text. type: preview //// tab | With ToC entry -**Table of contents** -[Some heading](#permalink-to-some-heading){ title="#permalink-to-some-heading" } -[`object`](#permalink-to-object){ title="#permalink-to-object" } -[Other heading](#permalink-to-other-heading){ title="#permalink-to-other-heading" } +**Table of contents** +[Some heading](#permalink-to-some-heading){ title="#permalink-to-some-heading" } +[`object`](#permalink-to-object){ title="#permalink-to-object" } +[Other heading](#permalink-to-other-heading){ title="#permalink-to-other-heading" } //// //// tab | Without ToC entry -**Table of contents** -[Some heading](#permalink-to-some-heading){ title="#permalink-to-some-heading" } +**Table of contents** +[Some heading](#permalink-to-some-heading){ title="#permalink-to-some-heading" } [Other heading](#permalink-to-other-heading){ title="#permalink-to-other-heading" } //// /// @@ -400,7 +400,7 @@ plugins: Show the full Python path of every object. Same as for [`show_root_members_full_path`][], -but for every member, recursively. This option takes precedence over +but for every member, recursively. This option takes precedence over [`show_root_members_full_path`][]: `show_root_members_full_path` | `show_object_full_path` | Direct root members path @@ -454,7 +454,7 @@ When [grouped by categories][group_by_category], show a heading for each categor These category headings will appear in the table of contents, allowing you to link to them using their permalinks. -WARNING: **Not recommended with deeply nested object** +WARNING: **Not recommended with deeply nested objects.** When injecting documentation for deeply nested objects, you'll quickly run out of heading levels, and the objects at the bottom of the tree risk all getting documented diff --git a/docs/usage/configuration/signatures.md b/docs/usage/configuration/signatures.md index 879db6b1..345e1536 100644 --- a/docs/usage/configuration/signatures.md +++ b/docs/usage/configuration/signatures.md @@ -202,7 +202,7 @@ plugins: [: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 +**This feature also requires [Griffe Insiders](https://mkdocstrings.github.io/griffe/insiders/) to be installed.** diff --git a/docs/usage/customization.md b/docs/usage/customization.md index 907809c8..9e13da66 100644 --- a/docs/usage/customization.md +++ b/docs/usage/customization.md @@ -371,9 +371,9 @@ Available context: #### Docstring sections In `docstring/attributes.html`, -`docstring/functions.html`, -`docstring/classes.html`, -`docstring/modules.html`, +`docstring/functions.html`, +`docstring/classes.html`, +`docstring/modules.html`, `docstring/other_parameters.html`, `docstring/parameters.html`, `docstring/raises.html`, diff --git a/docs/usage/docstrings/google.md b/docs/usage/docstrings/google.md index de35d46e..1c843a3b 100644 --- a/docs/usage/docstrings/google.md +++ b/docs/usage/docstrings/google.md @@ -17,11 +17,11 @@ For example: This admonition has a custom title! """ ``` - + === "Result" NOTE: It looks like a section, but it will be rendered as an admonition. - TIP: **You can even choose a title.** + TIP: **You can even choose a title.** This admonition has a custom title! See [Napoleon's documentation](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html). diff --git a/docs/usage/index.md b/docs/usage/index.md index 57b9fdc1..87f0a13f 100644 --- a/docs/usage/index.md +++ b/docs/usage/index.md @@ -1,6 +1,6 @@ # Usage -TIP: **This is the documentation for the NEW Python handler.** +TIP: **This is the documentation for the NEW Python handler.** To read the documentation for the LEGACY handler, go to the [legacy handler documentation](https://mkdocstrings.github.io/python-legacy). @@ -94,7 +94,7 @@ When importing an inventory, you enable automatic cross-references to other documentation sites like the standard library docs or any third-party package docs. Typically, you want to import the inventories of your project's dependencies, at least those -that are used in the public API. +that are used in the public API. See [*mkdocstrings*' documentation on inventories][inventories] for more details. @@ -292,7 +292,7 @@ to make sure anyone can build your docs from any location on their filesystem. ### Using the PYTHONPATH environment variable -WARNING: **This method has limitations.** +WARNING: **This method has limitations.** This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend using the [`paths` method](#using-the-paths-option) instead. @@ -348,10 +348,10 @@ In Bash and other shells, you can run your command like this ```bash PYTHONPATH=src mkdocs build -f docs/mkdocs.yml ``` - + ### Installing your package in the current Python environment -WARNING: **This method has limitations.** +WARNING: **This method has limitations.** This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend using the [`paths` method](#using-the-paths-option) instead. diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja index 7f3707b6..0ee0151a 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja @@ -12,7 +12,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering " + attribute.path) }} @@ -44,7 +44,7 @@ Context: {% block heading scoped %} {#- Heading block. - + This block renders the heading for the attribute. -#} {% if config.show_symbol_type_heading %}{% endif %} @@ -60,7 +60,7 @@ Context: {% block labels scoped %} {#- Labels block. - + This block renders the labels for the attribute. -#} {% with labels = attribute.labels %} @@ -72,7 +72,7 @@ Context: {% block signature scoped %} {#- Signature block. - + This block renders the signature for the attribute. -#} {% if config.separate_signature %} @@ -99,14 +99,14 @@ Context:
{% block contents scoped %} {#- Contents block. - + This block renders the contents of the attribute. It contains other blocks that users can override. Overriding the contents block allows to rearrange the order of the blocks. -#} {% block docstring scoped %} {#- Docstring block. - + This block renders the docstring for the attribute. -#} {% with docstring_sections = attribute.docstring.parsed %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja index c9c23156..d8d7b87b 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja @@ -13,7 +13,7 @@ Context: {% if obj.all_members %} {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering children of " + obj.path) }} 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 ff5e51c9..11238337 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja @@ -11,7 +11,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering " + class.path) }} @@ -43,7 +43,7 @@ Context: {% block heading scoped %} {#- Heading block. - + This block renders the heading for the class. -#} {% if config.show_symbol_type_heading %}{% endif %} @@ -62,7 +62,7 @@ Context: {% block labels scoped %} {#- Labels block. - + This block renders the labels for the class. -#} {% with labels = class.labels %} @@ -74,7 +74,7 @@ Context: {% block signature scoped %} {#- Signature block. - + This block renders the signature for the class. Overloads of the `__init__` method are rendered if `merge_init_into_class` is enabled. The actual `__init__` method signature is only rendered if `separate_signature` is also enabled. @@ -117,14 +117,14 @@ Context:
{% block contents scoped %} {#- Contents block. - + This block renders the contents of the class. It contains other blocks that users can override. Overriding the contents block allows to rearrange the order of the blocks. -#} {% block bases scoped %} {#- Class bases block. - + This block renders the bases for the class. -#} {% if config.show_bases and class.bases %} @@ -138,7 +138,7 @@ Context: {% block docstring scoped %} {#- Docstring block. - + This block renders the docstring for the class. -#} {% with docstring_sections = class.docstring.parsed %} @@ -161,7 +161,7 @@ Context: {% block summary scoped %} {#- Summary block. - + This block renders auto-summaries for classes, methods, and attributes. -#} {% include "summary"|get_template with context %} @@ -169,7 +169,7 @@ Context: {% block source scoped %} {#- Source block. - + This block renders the source code for the class. -#} {% if config.show_source %} @@ -205,7 +205,7 @@ Context: {% block children scoped %} {#- Children block. - + This block renders the children (members) of the class. -#} {% set root = False %} 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 14d11d03..6983b2e1 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja @@ -14,7 +14,7 @@ Context: {% if docstring_sections %} {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering docstring") }} 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 ff6e9cbc..7f949130 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 @@ -8,7 +8,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering admonition") }} 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 0bb416e0..13bd15b2 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering attributes section") }} 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 82bae98c..73f39329 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering classes section") }} 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 5a086497..0caacc15 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering examples section") }} 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 f979f4e5..28bb0cae 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering functions section") }} 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 b18e69f0..d55f854e 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering modules section") }} 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 24c6b194..1689dcb8 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering other parameters section") }} 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 fef553b1..d4e9acb8 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering parameters section") }} 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 f796494b..d734e94a 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering raises section") }} 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 57df473f..3b618c66 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering receives section") }} 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 cab2ca77..af61fce5 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering returns section") }} 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 a892244a..782c0cdf 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering warns section") }} 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 96c373dd..6d3cfa14 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering yields section") }} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html.jinja index 4aea143d..5d7c07d5 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html.jinja @@ -6,14 +6,14 @@ which is a tree-like structure representing a Python expression. {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} {%- macro crossref(name, annotation_path) -%} {#- Output a cross-reference. - + This macro outputs a cross-reference to the given name. Parameters: diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja index 973c762e..38323217 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja @@ -11,7 +11,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering " + function.path) }} @@ -49,7 +49,7 @@ Context: {% block heading scoped %} {#- Heading block. - + This block renders the heading for the function. -#} {% if config.show_symbol_type_heading %}{% endif %} @@ -64,7 +64,7 @@ Context: {% block labels scoped %} {#- Labels block. - + This block renders the labels for the function. -#} {% with labels = function.labels %} @@ -76,7 +76,7 @@ Context: {% block signature scoped %} {#- Signature block. - + This block renders the signature for the function, as well as its overloaded signatures if any. -#} @@ -114,14 +114,14 @@ Context:
{% block contents scoped %} {#- Contents block. - + This block renders the contents of the function. It contains other blocks that users can override. Overriding the contents block allows to rearrange the order of the blocks. -#} {% block docstring scoped %} {#- Docstring block. - + This block renders the docstring for the function. -#} {% with docstring_sections = function.docstring.parsed %} @@ -131,7 +131,7 @@ Context: {% block source scoped %} {#- Source block. - + This block renders the source code for the function. -#} {% if config.show_source and function.source %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html.jinja index dced4913..bbd3a7c1 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html.jinja @@ -12,7 +12,7 @@ Context: {% if config.show_labels and labels %} {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering labels") }} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja index 5b643726..e3a614bb 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html.jinja index d988b6ab..bcdcce2d 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html.jinja index a6b7728b..76e59f2c 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html.jinja index f748b83c..1846960e 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja index 2085b95d..87463aa8 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja @@ -11,7 +11,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering " + module.path) }} @@ -43,7 +43,7 @@ Context: {% block heading scoped %} {#- Heading block. - + This block renders the heading for the module. -#} {% if config.show_symbol_type_heading %}{% endif %} @@ -56,7 +56,7 @@ Context: {% block labels scoped %} {#- Labels block. - + This block renders the labels for the module. -#} {% with labels = module.labels %} @@ -82,14 +82,14 @@ Context:
{% block contents scoped %} {#- Contents block. - + This block renders the contents of the module. It contains other blocks that users can override. Overriding the contents block allows to rearrange the order of the blocks. -#} {% block docstring scoped %} {#- Docstring block. - + This block renders the docstring for the module. -#} {% with docstring_sections = module.docstring.parsed %} @@ -99,7 +99,7 @@ Context: {% block summary scoped %} {#- Summary block. - + This block renders auto-summaries for classes, methods, and attributes. -#} {% include "summary"|get_template with context %} @@ -107,7 +107,7 @@ Context: {% block children scoped %} {#- Children block. - + This block renders the children (members) of the module. -#} {% set root = False %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja index 750cac30..eb8cf552 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja @@ -12,7 +12,7 @@ Context: {%- if config.show_signature -%} {%- block logs scoped -%} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug("Rendering signature") }} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja index 508e5660..0a4ee071 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja index 65b7c5b8..8bc8cb60 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja index b9792ada..1b1ef8f3 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja index ad8b6f88..f03dfba2 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja index 35d6e110..15e78088 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} 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 8df3f9f3..ad798971 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} 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 287bbf3d..beb4f678 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} 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 da30d60a..295ab082 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} 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 ffa3fad1..7fa8cd86 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} 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 40c77846..9ee189bc 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} 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 597d8932..2dbd21af 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} 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 d66ac431..61f3c839 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} 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 4d4fc3d5..0fa6fcbc 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 @@ -9,7 +9,7 @@ Context: {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {{ log.debug() }} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja index 1465471d..21163f47 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja @@ -2,7 +2,7 @@ {% block logs scoped %} {#- Logging block. - + This block can be used to log debug messages, deprecation messages, warnings, etc. -#} {% endblock logs %} From add00435a50ab29a67a1b7a1b908dae677ae0718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 29 Jan 2025 15:05:56 +0100 Subject: [PATCH 04/14] style: Format --- scripts/insiders.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/insiders.py b/scripts/insiders.py index 849c6314..a7da99bc 100644 --- a/scripts/insiders.py +++ b/scripts/insiders.py @@ -26,7 +26,7 @@ def human_readable_amount(amount: int) -> str: # noqa: D103 str_amount = str(amount) if len(str_amount) >= 4: # noqa: PLR2004 - return f"{str_amount[:len(str_amount)-3]},{str_amount[-3:]}" + return f"{str_amount[: len(str_amount) - 3]},{str_amount[-3:]}" return str_amount From 7cabacf13735dbc5066793baf5820d61cd342dc8 Mon Sep 17 00:00:00 2001 From: Yann Van Crombrugge <59556820+vancromy@users.noreply.github.com> Date: Wed, 29 Jan 2025 17:08:16 +0100 Subject: [PATCH 05/14] feat: Add `heading` and `toc_label` options Issue-mkdocstrings-725: https://github.com/mkdocstrings/mkdocstrings/issues/725 PR-236: https://github.com/mkdocstrings/python/pull/236 --- docs/usage/configuration/headings.md | 33 +++++++++++++++++++ src/mkdocstrings_handlers/python/handler.py | 4 +++ .../material/_base/attribute.html.jinja | 4 +-- .../templates/material/_base/class.html.jinja | 4 +-- .../material/_base/function.html.jinja | 4 +-- .../material/_base/module.html.jinja | 6 ++-- 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/docs/usage/configuration/headings.md b/docs/usage/configuration/headings.md index ef961ad4..33062baf 100644 --- a/docs/usage/configuration/headings.md +++ b/docs/usage/configuration/headings.md @@ -57,6 +57,39 @@ plugins: //// /// +## `heading` + +- **:octicons-package-24: Type [`str`][] :material-equal: `""`{ title="default value" }** + + +A custom string to use as the heading of the root object (i.e. the object specified directly after the identifier `:::`). This will override the default heading generated by the plugin. + +WARNING: **Not advised to be used as a global configuration option.** This option is not advised to be used as a global configuration option, as it will override the default heading for all objects. It is recommended to use it only in specific cases where you want to override the heading for a specific object. + +```md title="in docs/some_page.md (local configuration)" +::: path.to.module + options: + heading: "My fancy module" +``` + +## `toc_label` + +- **:octicons-package-24: Type [`str`][] :material-equal: `""`{ title="default value" }** + + +A custom string to use as the label in the Table of Contents for the root object (i.e. the one specified directly after the identifier `:::`). This will override the default label generated by the plugin. + +WARNING: **Not advised to be used as a global configuration option.** This option is not advised to be used as a global configuration option, as it will override the default label for all objects. It is recommended to use it only in specific cases where you want to override the label for a specific object. + +NOTE: **Use with/without `heading`.** If you use this option without specifying a custom `heading`, the default heading will be used in the page, but the label in the Table of Contents will be the one you specified. By providing both an option for `heading` and `toc_label`, we leave the customization entirely up to you. + +```md title="in docs/some_page.md (local configuration)" +::: path.to.module + options: + heading: "My fancy module" + toc_label: "My fancy module" +``` + ## `parameter_headings` [:octicons-tag-24: Insiders 1.6.0](../../insiders/changelog.md#1.6.0) diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index e57ae9e7..5725d566 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -107,6 +107,8 @@ class PythonHandler(BaseHandler): "show_inheritance_diagram": False, "show_submodules": False, "group_by_category": True, + "heading": "", + "toc_label": "", "heading_level": 2, "members_order": rendering.Order.alphabetical.value, "docstring_section_style": "table", @@ -143,6 +145,8 @@ class PythonHandler(BaseHandler): The modules must be listed as an array of strings. Default: `None`. Attributes: Headings options: + heading (str): A custom string to override the autogenerated heading of the root object. + toc_label (str): A custom string to override the autogenerated toc label of the root object. heading_level (int): The initial heading level to use. Default: `2`. parameter_headings (bool): Whether to render headings for parameters (therefore showing parameters in the ToC). Default: `False`. show_root_heading (bool): Show the heading of the object at the root of the documentation tree diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja index 0ee0151a..c13bb641 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja @@ -49,7 +49,7 @@ Context: -#} {% if config.show_symbol_type_heading %}{% endif %} {% if config.separate_signature %} - {{ attribute_name }} + {{ config.heading if config.heading and root else attribute_name }} {% else %} {%+ filter highlight(language="python", inline=True) %} {{ attribute_name }}{% if attribute.annotation and config.show_signature_annotations %}: {{ attribute.annotation }}{% endif %} @@ -88,7 +88,7 @@ Context: {% filter heading(heading_level, role="data" if attribute.parent.kind.value == "module" else "attr", id=html_id, - toc_label=(' '|safe if config.show_symbol_type_toc else '') + attribute.name, + toc_label=(' '|safe if config.show_symbol_type_toc else '') + (config.toc_label if config.toc_label and root else attribute_name), hidden=True, ) %} {% endfilter %} 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 11238337..aefa98d1 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja @@ -48,7 +48,7 @@ Context: -#} {% if config.show_symbol_type_heading %}{% endif %} {% if config.separate_signature %} - {{ class_name }} + {{ config.heading if config.heading and root else class_name }} {% elif config.merge_init_into_class and "__init__" in all_members %} {% with function = all_members["__init__"] %} {%+ filter highlight(language="python", inline=True) %} @@ -106,7 +106,7 @@ Context: {% filter heading(heading_level, role="class", id=html_id, - toc_label=(' '|safe if config.show_symbol_type_toc else '') + class.name, + toc_label=(' '|safe if config.show_symbol_type_toc else '') + (config.toc_label if config.toc_label and root else class.name), hidden=True, ) %} {% endfilter %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja index 38323217..5e803ffb 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja @@ -54,7 +54,7 @@ Context: -#} {% if config.show_symbol_type_heading %}{% endif %} {% if config.separate_signature %} - {{ function_name }} + {{ config.heading if config.heading and root else function_name }} {% else %} {%+ filter highlight(language="python", inline=True) %} {{ function_name }}{% include "signature"|get_template with context %} @@ -103,7 +103,7 @@ Context: heading_level, role="function", id=html_id, - toc_label=((' ')|safe if config.show_symbol_type_toc else '') + function.name, + toc_label=((' ')|safe if config.show_symbol_type_toc else '') + (config.toc_label if config.toc_label and root else function.name), hidden=True, ) %} {% endfilter %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja index 87463aa8..fa2d2e6a 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja @@ -38,7 +38,7 @@ Context: role="module", id=html_id, class="doc doc-heading", - toc_label=(' '|safe if config.show_symbol_type_toc else '') + module.name, + toc_label=(' '|safe if config.show_symbol_type_toc else '') + (config.toc_label if config.toc_label and root else module.name), ) %} {% block heading scoped %} @@ -48,7 +48,7 @@ Context: -#} {% if config.show_symbol_type_heading %}{% endif %} {% if config.separate_signature %} - {{ module_name }} + {{ config.heading if config.heading and root else module_name }} {% else %} {{ module_name }} {% endif %} @@ -71,7 +71,7 @@ Context: {% filter heading(heading_level, role="module", id=html_id, - toc_label=(' '|safe if config.show_symbol_type_toc else '') + module.name, + toc_label=(' '|safe if config.show_symbol_type_toc else '') + (config.toc_label if config.toc_label and root else module.name), hidden=True, ) %} {% endfilter %} From 7d608423a5103a4628f3ba06d6eca97541fd16e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 3 Feb 2025 17:07:13 +0100 Subject: [PATCH 06/14] ci: Ignore type warning about soup in test --- tests/test_end_to_end.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_end_to_end.py b/tests/test_end_to_end.py index 05dcfeb3..52340bc0 100644 --- a/tests/test_end_to_end.py +++ b/tests/test_end_to_end.py @@ -21,7 +21,7 @@ def _normalize_html(html: str) -> str: soup = bs4.BeautifulSoup(html, features="html.parser") - html = soup.prettify() + html = soup.prettify() # type: ignore[assignment] html = re.sub(r"\b(0x)[a-f0-9]+\b", r"\1...", html) html = re.sub(r"^(Build Date UTC ?:).+", r"\1...", html, flags=re.MULTILINE) html = re.sub(r"\b[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\b", r"...", html) From 5ebeda6fce1b1bc7cb3f5e27a5a90ac394a3de0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 13 Jan 2025 18:24:30 +0100 Subject: [PATCH 07/14] refactor: Use dataclasses for configuration/options and automate schema generation --- config/pytest.ini | 3 +- docs/schema.json | 316 ------ docs/usage/index.md | 7 - duties.py | 2 + mkdocs.yml | 5 + pyproject.toml | 5 +- scripts/griffe_extensions.py | 46 + scripts/mkdocs_hooks.py | 32 + src/mkdocstrings_handlers/python/config.py | 994 ++++++++++++++++++ src/mkdocstrings_handlers/python/handler.py | 409 +++---- src/mkdocstrings_handlers/python/rendering.py | 25 +- .../material/_base/children.html.jinja | 2 +- .../material/_base/summary/modules.html.jinja | 2 +- tests/helpers.py | 9 +- tests/test_end_to_end.py | 6 +- tests/test_handler.py | 60 +- tests/test_rendering.py | 16 +- tests/test_themes.py | 5 +- 18 files changed, 1265 insertions(+), 679 deletions(-) delete mode 100644 docs/schema.json create mode 100644 scripts/griffe_extensions.py create mode 100644 scripts/mkdocs_hooks.py create mode 100644 src/mkdocstrings_handlers/python/config.py diff --git a/config/pytest.ini b/config/pytest.ini index 25f9c92e..4f43c18e 100644 --- a/config/pytest.ini +++ b/config/pytest.ini @@ -10,6 +10,7 @@ testpaths = # action:message_regex:warning_class:module_regex:line filterwarnings = error - # TODO: remove once pytest-xdist 4 is released + # TODO: Remove once pytest-xdist 4 is released. ignore:.*rsyncdir:DeprecationWarning:xdist + # TODO: Remove once mkdocstrings stops setting fallback function. ignore:.*fallback anchor function:DeprecationWarning:mkdocstrings diff --git a/docs/schema.json b/docs/schema.json deleted file mode 100644 index e1863d26..00000000 --- a/docs/schema.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft-07/schema", - "title": "Python handler for mkdocstrings.", - "type": "object", - "properties": { - "python": { - "markdownDescription": "https://mkdocstrings.github.io/python/", - "type": "object", - "properties": { - "import": { - "title": "Inventories to import.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/#global-only-options", - "type": "array", - "items": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "object", - "properties": { - "url": { - "title": "URL of the inventory file.", - "type": "string" - }, - "base_url": { - "title": "Base URL used to build references URLs.", - "type": "string" - }, - "domains": { - "title": "Domains to import from the inventory.", - "description": "If not defined it will only import 'py' domain.", - "type": "array", - "items": { - "type": "string" - } - } - } - } - ] - } - }, - "paths": { - "title": "Local absolute/relative paths (relative to mkdocs.yml) to search packages into.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/#paths", - "type": "array", - "items": { - "type": "string", - "format": "path" - } - }, - "load_external_modules": { - "title": "Load external modules to resolve aliases.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/#load_external_modules", - "type": "boolean", - "default": false - }, - "options": { - "title": "Options for collecting and rendering objects.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/#globallocal-options", - "type": "object", - "properties": { - "docstring_style": { - "title": "The docstring style to use when parsing docstrings.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#docstring_style", - "enum": [ - "google", - "numpy", - "sphinx" - ], - "default": "google" - }, - "docstring_options": { - "title": "The options for the docstring parser.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#docstring_options", - "default": null, - "items": { - "$ref": "https://raw.githubusercontent.com/mkdocstrings/griffe/master/docs/schema-docstrings-options.json" - } - }, - "show_root_heading": { - "title": "Show the heading of the object at the root of the documentation tree.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_root_heading", - "type": "boolean", - "default": false - }, - "show_root_toc_entry": { - "title": "If the root heading is not shown, at least add a ToC entry for it.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_root_toc_entry", - "type": "boolean", - "default": true - }, - "show_root_full_path": { - "title": "Show the full Python path for the root object heading.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_root_full_path", - "type": "boolean", - "default": true - }, - "show_root_members_full_path": { - "title": "Show the full Python path of the root members.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_root_members_full_path", - "type": "boolean", - "default": false - }, - "show_object_full_path": { - "title": "Show the full Python path of every object.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_object_full_path", - "type": "boolean", - "default": false - }, - "show_symbol_type_heading": { - "title": "Show the symbol type in headings (e.g. mod, class, func and attr).", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_symbol_type_heading", - "type": "boolean", - "default": false - }, - "show_symbol_type_toc": { - "title": "Show the symbol type in the Table of Contents (e.g. mod, class, func and attr).", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_symbol_type_toc", - "type": "boolean", - "default": false - }, - "show_category_heading": { - "title": "When grouped by categories, show a heading for each category.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#show_category_heading", - "type": "boolean", - "default": false - }, - "show_if_no_docstring": { - "title": "Show the object heading even if it has no docstring or children with docstrings.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_if_no_docstring", - "type": "boolean", - "default": false - }, - "show_signature": { - "title": "Show methods and functions signatures.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/signatures/#show_signature", - "type": "boolean", - "default": true - }, - "show_signature_annotations": { - "title": "Show the type annotations in methods and functions signatures.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/signatures/#show_signature_annotations", - "type": "boolean", - "default": false - }, - "separate_signature": { - "title": "Whether to put the whole signature in a code block below the heading. If a formatter (Black or Ruff) is installed, the signature is also formatted using it.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/signatures/#separate_signature", - "type": "boolean", - "default": false - }, - "line_length": { - "title": "Maximum line length when formatting code/signatures.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/signatures/#line_length", - "type": "integer", - "default": 60 - }, - "merge_init_into_class": { - "title": "Whether to merge the `__init__` method into the class' signature and docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#merge_init_into_class", - "type": "boolean", - "default": false - }, - "show_docstring_attributes": { - "title": "Whether to display the \"Attributes\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_attributes", - "type": "boolean", - "default": true - }, - "show_docstring_description": { - "title": "Whether to display the textual block (including admonitions) in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_description", - "type": "boolean", - "default": true - }, - "show_docstring_examples": { - "title": "Whether to display the \"Examples\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_examples", - "type": "boolean", - "default": true - }, - "show_docstring_other_parameters": { - "title": "Whether to display the \"Other Parameters\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_other_parameters", - "type": "boolean", - "default": true - }, - "show_docstring_parameters": { - "title": "Whether to display the \"Parameters\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_parameters", - "type": "boolean", - "default": true - }, - "show_docstring_raises": { - "title": "Whether to display the \"Raises\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_raises", - "type": "boolean", - "default": true - }, - "show_docstring_receives": { - "title": "Whether to display the \"Receives\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_receives", - "type": "boolean", - "default": true - }, - "show_docstring_returns": { - "title": "Whether to display the \"Returns\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_returns", - "type": "boolean", - "default": true - }, - "show_docstring_warns": { - "title": "Whether to display the \"Warns\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_warns", - "type": "boolean", - "default": true - }, - "show_docstring_yields": { - "title": "Whether to display the \"Yields\" section in the object's docstring.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#show_docstring_yields", - "type": "boolean", - "default": true - }, - "show_source": { - "title": "Show the source code of this object.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/general/#show_source", - "type": "boolean", - "default": true - }, - "show_bases": { - "title": "Show the base classes of a class.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/general/#show_bases", - "type": "boolean", - "default": true - }, - "show_submodules": { - "title": "When rendering a module, show its submodules recursively.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/members/#show_submodules", - "type": "boolean", - "default": false - }, - "group_by_category": { - "title": "Group the object's children by categories: attributes, classes, functions, and modules.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/members/#group_by_category", - "type": "boolean", - "default": true - }, - "heading_level": { - "title": "The initial heading level to use.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/headings/#heading_level", - "type": "integer", - "default": 2 - }, - "members_order": { - "title": "The members ordering to use.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/members/#members_order", - "enum": [ - "alphabetical", - "source" - ], - "default": "alphabetical" - }, - "docstring_section_style": { - "title": "The style used to render docstring sections.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/docstrings/#docstring_section_style", - "enum": [ - "list", - "spacy", - "table" - ], - "default": "table" - }, - "members": { - "title": "An explicit list of members to render.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/members/#members", - "type": [ - "boolean", - "array" - ], - "default": null - }, - "filters": { - "title": "A list of filters applied to filter objects based on their name. A filter starting with `!` will exclude matching objects instead of including them. The `members` option takes precedence over `filters` (filters will still be applied recursively to lower members in the hierarchy).", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/members/#filters", - "type": "array", - "default": [ - "!^_[^_]" - ] - }, - "annotations_path": { - "title": "The verbosity for annotations path.", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/signatures/#annotations_path", - "enum": [ - "brief", - "source" - ], - "default": "brief" - }, - "preload_modules": { - "title": "Pre-load modules. It permits to resolve aliases pointing to these modules (packages), and therefore render members of an object that are external to the given object (originating from another package).", - "markdownDescription": "https://mkdocstrings.github.io/python/usage/configuration/general/#preload_modules", - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false -} \ No newline at end of file diff --git a/docs/usage/index.md b/docs/usage/index.md index 87f0a13f..8caafb48 100644 --- a/docs/usage/index.md +++ b/docs/usage/index.md @@ -199,13 +199,6 @@ in the following pages: - [Docstrings options](configuration/docstrings.md): options related to docstrings (parsing and rendering) - [Signature options](configuration/signatures.md): options related to signatures and type annotations -#### Options summary - -::: mkdocstrings_handlers.python.handler.PythonHandler.default_config - options: - show_root_heading: false - show_root_toc_entry: false - ## Finding modules There are multiple ways to tell the handler where to find your packages/modules. diff --git a/duties.py b/duties.py index bd051334..9e516ce5 100644 --- a/duties.py +++ b/duties.py @@ -88,6 +88,8 @@ def check_types(ctx: Context) -> None: ctx.run( tools.mypy(*PY_SRC_LIST, config_file="config/mypy.ini"), title=pyprefix("Type-checking"), + # TODO: Update when Pydantic supports 3.14. + nofail=sys.version_info >= (3, 14), ) diff --git a/mkdocs.yml b/mkdocs.yml index 2d546126..396f738f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,6 +13,9 @@ validation: absolute_links: warn unrecognized_links: warn +hooks: +- scripts/mkdocs_hooks.py + nav: - Home: - Overview: index.md @@ -160,6 +163,8 @@ plugins: docstring_options: ignore_init_summary: true docstring_section_style: list + extensions: + - scripts/griffe_extensions.py filters: ["!^_"] heading_level: 1 inherited_members: true diff --git a/pyproject.toml b/pyproject.toml index c6f3cc50..b4a453e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,9 +30,10 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "mkdocstrings>=0.26", + "mkdocstrings>=0.28", "mkdocs-autorefs>=1.2", "griffe>=0.49", + "typing-extensions>=4.0; python_version < '3.11'", ] [project.urls] @@ -106,6 +107,7 @@ dev = [ "mkdocs-git-revision-date-localized-plugin>=1.2", "mkdocs-literate-nav>=0.6", "mkdocs-material>=9.5", + "pydantic>=2.10", "mkdocs-minify-plugin>=0.8", # YORE: EOL 3.10: Remove line. "tomli>=2.0; python_version < '3.11'", @@ -113,3 +115,4 @@ dev = [ [tool.inline-snapshot] storage-dir = "tests/snapshots" +format-command = "ruff format --config config/ruff.toml --stdin-filename {filename}" diff --git a/scripts/griffe_extensions.py b/scripts/griffe_extensions.py new file mode 100644 index 00000000..4ff0c8cc --- /dev/null +++ b/scripts/griffe_extensions.py @@ -0,0 +1,46 @@ +"""Custom extensions for Griffe.""" + +from __future__ import annotations + +import ast +from typing import Any + +import griffe + +logger = griffe.get_logger("griffe_extensions") + + +class CustomFields(griffe.Extension): + """Support our custom dataclass fields.""" + + def on_attribute_instance( + self, + *, + attr: griffe.Attribute, + agent: griffe.Visitor | griffe.Inspector, + **kwargs: Any, # noqa: ARG002 + ) -> None: + """Fetch descriptions from `Field` annotations.""" + if attr.docstring: + return + try: + field: griffe.ExprCall = attr.annotation.slice.elements[1] # type: ignore[union-attr] + except AttributeError: + return + + if field.canonical_path == "mkdocstrings_handler.python.config.Field": + description = next( + attr.value + for attr in field.arguments + if isinstance(attr, griffe.ExprKeyword) and attr.name == "description" + ) + if not isinstance(description, str): + logger.warning(f"Field description of {attr.path} is not a static string") + description = str(description) + + attr.docstring = griffe.Docstring( + ast.literal_eval(description), + parent=attr, + parser=agent.docstring_parser, + parser_options=agent.docstring_options, + ) diff --git a/scripts/mkdocs_hooks.py b/scripts/mkdocs_hooks.py new file mode 100644 index 00000000..63e7578e --- /dev/null +++ b/scripts/mkdocs_hooks.py @@ -0,0 +1,32 @@ +"""Generate a JSON schema of the Python handler configuration.""" + +import json +from os.path import join +from typing import Any + +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.plugins import get_plugin_logger + +from mkdocstrings_handlers.python.config import PythonInputConfig + +# TODO: Update when Pydantic supports Python 3.14 (sources and duties as well). +try: + from pydantic import TypeAdapter +except ImportError: + TypeAdapter = None # type: ignore[assignment,misc] + + +logger = get_plugin_logger(__name__) + + +def on_post_build(config: MkDocsConfig, **kwargs: Any) -> None: # noqa: ARG001 + """Write `schema.json` to the site directory.""" + if TypeAdapter is None: + logger.info("Pydantic is not installed, skipping JSON schema generation") + return + adapter = TypeAdapter(PythonInputConfig) + schema = adapter.json_schema() + schema["$schema"] = "https://json-schema.org/draft-07/schema" + with open(join(config.site_dir, "schema.json"), "w") as file: + json.dump(schema, file, indent=2) + logger.debug("Generated JSON schema") diff --git a/src/mkdocstrings_handlers/python/config.py b/src/mkdocstrings_handlers/python/config.py new file mode 100644 index 00000000..07f34397 --- /dev/null +++ b/src/mkdocstrings_handlers/python/config.py @@ -0,0 +1,994 @@ +"""Configuration and options dataclasses.""" + +from __future__ import annotations + +import re +import sys +from dataclasses import field, fields +from typing import TYPE_CHECKING, Annotated, Any, Literal + +# YORE: EOL 3.10: Replace block with line 2. +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing_extensions import Self + +try: + # When Pydantic is available, use it to validate options (done automatically). + # Users can therefore opt into validation by installing Pydantic in development/CI. + # When building the docs to deploy them, Pydantic is not required anymore. + + # When building our own docs, Pydantic is always installed (see `docs` group in `pyproject.toml`) + # to allow automatic generation of a JSON Schema. The JSON Schema is then referenced by mkdocstrings, + # which is itself referenced by mkdocs-material's schema system. For example in VSCode: + # + # "yaml.schemas": { + # "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" + # } + from inspect import cleandoc + + from pydantic import Field as BaseField + from pydantic.dataclasses import dataclass + + _base_url = "https://mkdocstrings.github.io/python/usage" + + def Field( # noqa: N802, D103 + *args: Any, + description: str, + group: Literal["general", "headings", "members", "docstrings", "signatures"] | None = None, + parent: str | None = None, + **kwargs: Any, + ) -> None: + def _add_markdown_description(schema: dict[str, Any]) -> None: + url = f"{_base_url}/{f'configuration/{group}/' if group else ''}#{parent or schema['title']}" + schema["markdownDescription"] = f"[DOCUMENTATION]({url})\n\n{schema['description']}" + + return BaseField( + *args, + description=cleandoc(description), + field_title_generator=lambda name, _: name, + json_schema_extra=_add_markdown_description, + **kwargs, + ) +except ImportError: + from dataclasses import dataclass # type: ignore[no-redef] + + def Field(*args: Any, **kwargs: Any) -> None: # type: ignore[misc] # noqa: D103, N802 + pass + + +if TYPE_CHECKING: + from collections.abc import MutableMapping + + +# YORE: EOL 3.9: Remove block. +_dataclass_options = {"frozen": True} +if sys.version_info >= (3, 10): + _dataclass_options["kw_only"] = True + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class GoogleStyleOptions: + """Google style docstring options.""" + + ignore_init_summary: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="Whether to ignore the summary in `__init__` methods' docstrings.", + ), + ] = False + + returns_multiple_items: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="""Whether to parse multiple items in `Yields` and `Returns` sections. + + When true, each item's continuation lines must be indented. + When false (single item), no further indentation is required. + """, + ), + ] = True + + returns_named_value: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="""Whether to parse `Yields` and `Returns` section items as name and description, rather than type and description. + + When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`. + When false, parentheses are optional but the items cannot be named: `int: Description`. + """, + ), + ] = True + + returns_type_in_property_summary: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="Whether to parse the return type of properties at the beginning of their summary: `str: Summary of the property`.", + ), + ] = False + + receives_multiple_items: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="""Whether to parse multiple items in `Receives` sections. + + When true, each item's continuation lines must be indented. + When false (single item), no further indentation is required. + """, + ), + ] = True + + receives_named_value: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="""Whether to parse `Receives` section items as name and description, rather than type and description. + + When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`. + When false, parentheses are optional but the items cannot be named: `int: Description`. + """, + ), + ] = True + + trim_doctest_flags: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="Whether to remove doctest flags from Python example blocks.", + ), + ] = True + + warn_unknown_params: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="Warn about documented parameters not appearing in the signature.", + ), + ] = True + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class NumpyStyleOptions: + """Numpy style docstring options.""" + + ignore_init_summary: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="Whether to ignore the summary in `__init__` methods' docstrings.", + ), + ] = False + + trim_doctest_flags: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="Whether to remove doctest flags from Python example blocks.", + ), + ] = True + + warn_unknown_params: Annotated[ + bool, + Field( + group="docstrings", + parent="docstring_options", + description="Warn about documented parameters not appearing in the signature.", + ), + ] = True + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class SphinxStyleOptions: + """Sphinx style docstring options.""" + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class PerStyleOptions: + """Per style options.""" + + google: Annotated[ + GoogleStyleOptions, + Field( + group="docstrings", + parent="docstring_options", + description="Google-style options.", + ), + ] = field(default_factory=GoogleStyleOptions) + + numpy: Annotated[ + NumpyStyleOptions, + Field( + group="docstrings", + parent="docstring_options", + description="Numpydoc-style options.", + ), + ] = field(default_factory=NumpyStyleOptions) + + sphinx: Annotated[ + SphinxStyleOptions, + Field( + group="docstrings", + parent="docstring_options", + description="Sphinx-style options.", + ), + ] = field(default_factory=SphinxStyleOptions) + + @classmethod + def from_data(cls, **data: Any) -> Self: + """Create an instance from a dictionary.""" + if "google" in data: + data["google"] = GoogleStyleOptions(**data["google"]) + if "numpy" in data: + data["numpy"] = NumpyStyleOptions(**data["numpy"]) + if "sphinx" in data: + data["sphinx"] = SphinxStyleOptions(**data["sphinx"]) + return cls(**data) + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class AutoStyleOptions: + """Auto style docstring options.""" + + method: Annotated[ + Literal["heuristics", "max_sections"], + Field( + group="docstrings", + parent="docstring_options", + description="The method to use to determine the docstring style.", + ), + ] = "heuristics" + + style_order: Annotated[ + list[str], + Field( + group="docstrings", + parent="docstring_options", + description="The order of the docstring styles to try.", + ), + ] = field(default_factory=lambda: ["sphinx", "google", "numpy"]) + + default: Annotated[ + str | None, + Field( + group="docstrings", + parent="docstring_options", + description="The default docstring style to use if no other style is detected.", + ), + ] = None + + per_style_options: Annotated[ + PerStyleOptions, + Field( + group="docstrings", + parent="docstring_options", + description="Per-style options.", + ), + ] = field(default_factory=PerStyleOptions) + + @classmethod + def from_data(cls, **data: Any) -> Self: + """Create an instance from a dictionary.""" + if "per_style_options" in data: + data["per_style_options"] = PerStyleOptions.from_data(**data["per_style_options"]) + return cls(**data) + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class SummaryOption: + """Summary option.""" + + attributes: Annotated[ + bool, + Field( + group="members", + parent="summary", + description="Whether to render summaries of attributes.", + ), + ] = False + + functions: Annotated[ + bool, + Field( + group="members", + parent="summary", + description="Whether to render summaries of functions (methods).", + ), + ] = False + + classes: Annotated[ + bool, + Field( + group="members", + parent="summary", + description="Whether to render summaries of classes.", + ), + ] = False + + modules: Annotated[ + bool, + Field( + group="members", + parent="summary", + description="Whether to render summaries of modules.", + ), + ] = False + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class PythonInputOptions: + """Accepted input options.""" + + allow_inspection: Annotated[ + bool, + Field( + group="general", + description="Whether to allow inspecting modules when visiting them is not possible.", + ), + ] = True + + force_inspection: Annotated[ + bool, + Field( + group="general", + description="Whether to force using dynamic analysis when loading data.", + ), + ] = False + + annotations_path: Annotated[ + Literal["brief", "source", "full"], + Field( + group="signatures", + description="The verbosity for annotations path: `brief` (recommended), `source` (as written in the source), or `full`.", + ), + ] = "brief" + + docstring_options: Annotated[ + GoogleStyleOptions | NumpyStyleOptions | SphinxStyleOptions | AutoStyleOptions | None, + Field( + group="docstrings", + description="""The options for the docstring parser. + + See [docstring parsers](https://mkdocstrings.github.io/griffe/reference/docstrings/) and their options in Griffe docs. + """, + ), + ] = None + + docstring_section_style: Annotated[ + Literal["table", "list", "spacy"], + Field( + group="docstrings", + description="The style used to render docstring sections.", + ), + ] = "table" + + docstring_style: Annotated[ + Literal["auto", "google", "numpy", "sphinx"] | None, + Field( + group="docstrings", + description="The docstring style to use: `auto`, `google`, `numpy`, `sphinx`, or `None`.", + ), + ] = "google" + + extensions: Annotated[ + list[str | dict[str, Any]], + Field( + group="general", + description="A list of Griffe extensions to load.", + ), + ] = field(default_factory=list) + + filters: Annotated[ + list[str], + Field( + group="members", + description="""A list of filters applied to filter objects based on their name. + + A filter starting with `!` will exclude matching objects instead of including them. + The `members` option takes precedence over `filters` (filters will still be applied recursively + to lower members in the hierarchy). + """, + ), + ] = field(default_factory=lambda: ["!^_[^_]"]) + + find_stubs_package: Annotated[ + bool, + Field( + group="general", + description="Whether to load stubs package (package-stubs) when extracting docstrings.", + ), + ] = False + + group_by_category: Annotated[ + bool, + Field( + group="members", + description="Group the object's children by categories: attributes, classes, functions, and modules.", + ), + ] = True + + heading: Annotated[ + str, + Field( + group="headings", + description="A custom string to override the autogenerated heading of the root object.", + ), + ] = "" + + heading_level: Annotated[ + int, + Field( + group="headings", + description="The initial heading level to use.", + ), + ] = 2 + + inherited_members: Annotated[ + bool | list[str], + Field( + group="members", + description="""A boolean, or an explicit list of inherited members to render. + + If true, select all inherited members, which can then be filtered with `members`. + If false or empty list, do not select any inherited member. + """, + ), + ] = False + + line_length: Annotated[ + int, + Field( + group="signatures", + description="Maximum line length when formatting code/signatures.", + ), + ] = 60 + + members: Annotated[ + list[str] | bool | None, + Field( + group="members", + description="""A boolean, or an explicit list of members to render. + + If true, select all members without further filtering. + If false or empty list, do not render members. + If none, select all members and apply further filtering with filters and docstrings. + """, + ), + ] = None + + members_order: Annotated[ + Literal["alphabetical", "source"], + Field( + group="members", + description="""The members ordering to use. + + - `alphabetical`: order by the members names, + - `source`: order members as they appear in the source file. + """, + ), + ] = "alphabetical" + + merge_init_into_class: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to merge the `__init__` method into the class' signature and docstring.", + ), + ] = False + + modernize_annotations: Annotated[ + bool, + Field( + group="signatures", + description="Whether to modernize annotations, for example `Optional[str]` into `str | None`.", + ), + ] = False + + parameter_headings: Annotated[ + bool, + Field( + group="headings", + description="Whether to render headings for parameters (therefore showing parameters in the ToC).", + ), + ] = False + + preload_modules: Annotated[ + list[str], + Field( + group="general", + description="""Pre-load modules that are not specified directly in autodoc instructions (`::: identifier`). + + It is useful when you want to render documentation for a particular member of an object, + and this member is imported from another package than its parent. + + For an imported member to be rendered, you need to add it to the `__all__` attribute + of the importing module. + + The modules must be listed as an array of strings. + """, + ), + ] = field(default_factory=list) + + relative_crossrefs: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to enable the relative crossref syntax.", + ), + ] = False + + scoped_crossrefs: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to enable the scoped crossref ability.", + ), + ] = False + + separate_signature: Annotated[ + bool, + Field( + group="signatures", + description="""Whether to put the whole signature in a code block below the heading. + + If Black or Ruff are installed, the signature is also formatted using them. + """, + ), + ] = False + + show_bases: Annotated[ + bool, + Field( + group="general", + description="Show the base classes of a class.", + ), + ] = True + + show_category_heading: Annotated[ + bool, + Field( + group="headings", + description="When grouped by categories, show a heading for each category.", + ), + ] = False + + show_docstring_attributes: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Attributes' section in the object's docstring.", + ), + ] = True + + show_docstring_classes: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Classes' section in the object's docstring.", + ), + ] = True + + show_docstring_description: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the textual block (including admonitions) in the object's docstring.", + ), + ] = True + + show_docstring_examples: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Examples' section in the object's docstring.", + ), + ] = True + + show_docstring_functions: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Functions' or 'Methods' sections in the object's docstring.", + ), + ] = True + + show_docstring_modules: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Modules' section in the object's docstring.", + ), + ] = True + + show_docstring_other_parameters: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Other Parameters' section in the object's docstring.", + ), + ] = True + + show_docstring_parameters: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Parameters' section in the object's docstring.", + ), + ] = True + + show_docstring_raises: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Raises' section in the object's docstring.", + ), + ] = True + + show_docstring_receives: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Receives' section in the object's docstring.", + ), + ] = True + + show_docstring_returns: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Returns' section in the object's docstring.", + ), + ] = True + + show_docstring_warns: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Warns' section in the object's docstring.", + ), + ] = True + + show_docstring_yields: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to display the 'Yields' section in the object's docstring.", + ), + ] = True + + show_if_no_docstring: Annotated[ + bool, + Field( + group="docstrings", + description="Show the object heading even if it has no docstring or children with docstrings.", + ), + ] = False + + show_inheritance_diagram: Annotated[ + bool, + Field( + group="docstrings", + description="Show the inheritance diagram of a class using Mermaid.", + ), + ] = False + + show_labels: Annotated[ + bool, + Field( + group="docstrings", + description="Whether to show labels of the members.", + ), + ] = True + + show_object_full_path: Annotated[ + bool, + Field( + group="docstrings", + description="Show the full Python path of every object.", + ), + ] = False + + show_root_full_path: Annotated[ + bool, + Field( + group="docstrings", + description="Show the full Python path for the root object heading.", + ), + ] = True + + show_root_heading: Annotated[ + bool, + Field( + group="headings", + description="""Show the heading of the object at the root of the documentation tree. + + The root object is the object referenced by the identifier after `:::`. + """, + ), + ] = False + + show_root_members_full_path: Annotated[ + bool, + Field( + group="headings", + description="Show the full Python path of the root members.", + ), + ] = False + + show_root_toc_entry: Annotated[ + bool, + Field( + group="headings", + description="If the root heading is not shown, at least add a ToC entry for it.", + ), + ] = True + + show_signature_annotations: Annotated[ + bool, + Field( + group="signatures", + description="Show the type annotations in methods and functions signatures.", + ), + ] = False + + show_signature: Annotated[ + bool, + Field( + group="signatures", + description="Show methods and functions signatures.", + ), + ] = True + + show_source: Annotated[ + bool, + Field( + group="general", + description="Show the source code of this object.", + ), + ] = True + + show_submodules: Annotated[ + bool, + Field( + group="members", + description="When rendering a module, show its submodules recursively.", + ), + ] = False + + show_symbol_type_heading: Annotated[ + bool, + Field( + group="headings", + description="Show the symbol type in headings (e.g. mod, class, meth, func and attr).", + ), + ] = False + + show_symbol_type_toc: Annotated[ + bool, + Field( + group="headings", + description="Show the symbol type in the Table of Contents (e.g. mod, class, methd, func and attr).", + ), + ] = False + + signature_crossrefs: Annotated[ + bool, + Field( + group="signatures", + description="Whether to render cross-references for type annotations in signatures.", + ), + ] = False + + summary: Annotated[ + bool | SummaryOption, + Field( + group="members", + description="Whether to render summaries of modules, classes, functions (methods) and attributes.", + ), + ] = field(default_factory=SummaryOption) + + toc_label: Annotated[ + str, + Field( + group="headings", + description="A custom string to override the autogenerated toc label of the root object.", + ), + ] = "" + + unwrap_annotated: Annotated[ + bool, + Field( + group="signatures", + description="Whether to unwrap `Annotated` types to show only the type without the annotations.", + ), + ] = False + + extra: Annotated[ + dict[str, Any], + Field( + group="general", + description="Extra options.", + ), + ] = field(default_factory=dict) + + @classmethod + def _extract_extra(cls, data: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]: + field_names = {field.name for field in fields(cls)} + copy = data.copy() + return {name: copy.pop(name) for name in data if name not in field_names}, copy + + # YORE: Bump 2: Remove block. + def __init__(self, **kwargs: Any) -> None: + """Initialize the instance.""" + extra_fields = self._extract_extra(kwargs) + for name, value in kwargs.items(): + object.__setattr__(self, name, value) + if extra_fields: + object.__setattr__(self, "_extra", extra_fields) + + @classmethod + def coerce(cls, **data: Any) -> MutableMapping[str, Any]: + """Coerce data.""" + if "docstring_options" in data: + docstring_style = data.get("docstring_style", "google") + docstring_options = data["docstring_options"] + if docstring_options is not None: + if docstring_style == "auto": + docstring_options = AutoStyleOptions.from_data(**docstring_options) + elif docstring_style == "google": + docstring_options = GoogleStyleOptions(**docstring_options) + elif docstring_style == "numpy": + docstring_options = NumpyStyleOptions(**docstring_options) + elif docstring_style == "sphinx": + docstring_options = SphinxStyleOptions(**docstring_options) + data["docstring_options"] = docstring_options + if "summary" in data: + summary = data["summary"] + if summary is True: + summary = SummaryOption(attributes=True, functions=True, classes=True, modules=True) + elif summary is False: + summary = SummaryOption(attributes=False, functions=False, classes=False, modules=False) + else: + summary = SummaryOption(**summary) + data["summary"] = summary + return data + + @classmethod + def from_data(cls, **data: Any) -> Self: + """Create an instance from a dictionary.""" + return cls(**cls.coerce(**data)) + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class PythonOptions(PythonInputOptions): # type: ignore[override,unused-ignore] + """Final options passed as template context.""" + + filters: list[tuple[re.Pattern, bool]] = field(default_factory=list) # type: ignore[assignment] + """A list of filters applied to filter objects based on their name.""" + + summary: SummaryOption = field(default_factory=SummaryOption) + """Whether to render summaries of modules, classes, functions (methods) and attributes.""" + + @classmethod + def coerce(cls, **data: Any) -> MutableMapping[str, Any]: + """Create an instance from a dictionary.""" + if "filters" in data: + data["filters"] = [ + (re.compile(filtr.lstrip("!")), filtr.startswith("!")) for filtr in data["filters"] or () + ] + return super().coerce(**data) + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class Inventory: + """An inventory.""" + + url: Annotated[ + str, + Field( + parent="inventories", + description="The URL of the inventory.", + ), + ] + + base: Annotated[ + str | None, + Field( + parent="inventories", + description="The base URL of the inventory.", + ), + ] = None + + domains: Annotated[ + list[str], + Field( + parent="inventories", + description="The domains to load from the inventory.", + ), + ] = field(default_factory=lambda: ["py"]) + + @property + def _config(self) -> dict[str, Any]: + return {"base": self.base, "domains": self.domains} + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class PythonInputConfig: + """Python handler configuration.""" + + inventories: Annotated[ + list[str | Inventory], + Field(description="The inventories to load."), + ] = field(default_factory=list) + + paths: Annotated[ + list[str], + Field(description="The paths in which to search for Python packages."), + ] = field(default_factory=lambda: ["."]) + + load_external_modules: Annotated[ + bool | None, + Field(description="Whether to always load external modules/packages."), + ] = None + + options: Annotated[ + PythonInputOptions, + Field(description="Configuration options for collecting and rendering objects."), + ] = field(default_factory=PythonInputOptions) + + locale: Annotated[ + str | None, + Field(description="The locale to use when translating template strings."), + ] = None + + @classmethod + def coerce(cls, **data: Any) -> MutableMapping[str, Any]: + """Coerce data.""" + return data + + @classmethod + def from_data(cls, **data: Any) -> Self: + """Create an instance from a dictionary.""" + return cls(**cls.coerce(**data)) + + +# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. +@dataclass(**_dataclass_options) # type: ignore[call-overload] +class PythonConfig(PythonInputConfig): # type: ignore[override,unused-ignore] + """Python handler configuration.""" + + inventories: list[Inventory] = field(default_factory=list) # type: ignore[assignment] + options: dict[str, Any] = field(default_factory=dict) # type: ignore[assignment] + + @classmethod + def coerce(cls, **data: Any) -> MutableMapping[str, Any]: + """Coerce data.""" + if "inventories" in data: + data["inventories"] = [ + Inventory(url=inv) if isinstance(inv, str) else Inventory(**inv) for inv in data["inventories"] + ] + return data diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 5725d566..bf22876d 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -5,12 +5,12 @@ import glob import os import posixpath -import re import sys -from collections import ChainMap from contextlib import suppress +from dataclasses import asdict from pathlib import Path from typing import TYPE_CHECKING, Any, BinaryIO, ClassVar +from warnings import warn from griffe import ( AliasResolutionError, @@ -21,17 +21,18 @@ load_extensions, patch_loggers, ) -from mkdocstrings.extension import PluginError -from mkdocstrings.handlers.base import BaseHandler, CollectionError, CollectorItem +from mkdocs.exceptions import PluginError +from mkdocstrings.handlers.base import BaseHandler, CollectionError, CollectorItem, HandlerOptions from mkdocstrings.inventory import Inventory from mkdocstrings.loggers import get_logger from mkdocstrings_handlers.python import rendering +from mkdocstrings_handlers.python.config import PythonConfig, PythonOptions if TYPE_CHECKING: - from collections.abc import Iterator, Mapping, Sequence + from collections.abc import Iterator, Mapping, MutableMapping, Sequence - from markdown import Markdown + from mkdocs.config.defaults import MkDocsConfig if sys.version_info >= (3, 11): @@ -55,215 +56,78 @@ def chdir(path: str) -> Iterator[None]: # noqa: D103 patch_loggers(get_logger) +def _warn_extra_options(names: Sequence[str]) -> None: + warn( + "Passing extra options directly under `options` is deprecated. " + "Instead, pass them under `options.extra`, and update your templates. " + f"Current extra (unrecognized) options: {', '.join(sorted(names))}", + DeprecationWarning, + stacklevel=3, + ) + + class PythonHandler(BaseHandler): """The Python handler class.""" - name: str = "python" + name: ClassVar[str] = "python" """The handler's name.""" - domain: str = "py" # to match Sphinx's default domain + + domain: ClassVar[str] = "py" """The cross-documentation domain/language for this handler.""" - enable_inventory: bool = True + + enable_inventory: ClassVar[bool] = True """Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file.""" - fallback_theme = "material" + + fallback_theme: ClassVar[str] = "material" """The fallback theme.""" - fallback_config: ClassVar[dict] = {"fallback": True} - """The configuration used to collect item during autorefs fallback.""" - default_config: ClassVar[dict] = { - "find_stubs_package": False, - "docstring_style": "google", - "docstring_options": {}, - "show_symbol_type_heading": False, - "show_symbol_type_toc": False, - "show_root_heading": False, - "show_root_toc_entry": True, - "show_root_full_path": True, - "show_root_members_full_path": False, - "show_object_full_path": False, - "show_category_heading": False, - "show_if_no_docstring": False, - "show_signature": True, - "show_signature_annotations": False, - "signature_crossrefs": False, - "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, - "show_docstring_modules": True, - "show_docstring_description": True, - "show_docstring_examples": True, - "show_docstring_other_parameters": True, - "show_docstring_parameters": True, - "show_docstring_raises": True, - "show_docstring_receives": True, - "show_docstring_returns": True, - "show_docstring_warns": True, - "show_docstring_yields": True, - "show_source": True, - "show_bases": True, - "show_inheritance_diagram": False, - "show_submodules": False, - "group_by_category": True, - "heading": "", - "toc_label": "", - "heading_level": 2, - "members_order": rendering.Order.alphabetical.value, - "docstring_section_style": "table", - "members": None, - "inherited_members": False, - "filters": ["!^_[^_]"], - "annotations_path": "brief", - "preload_modules": None, - "allow_inspection": True, - "force_inspection": False, - "summary": False, - "show_labels": True, - "unwrap_annotated": False, - "parameter_headings": False, - "modernize_annotations": False, - } - """Default handler configuration. - - Attributes: General options: - find_stubs_package (bool): Whether to load stubs package (package-stubs) when extracting docstrings. Default `False`. - allow_inspection (bool): Whether to allow inspecting modules when visiting them is not possible. Default: `True`. - force_inspection (bool): Whether to force using dynamic analysis when loading data. Default: `False`. - show_bases (bool): Show the base classes of a class. Default: `True`. - show_inheritance_diagram (bool): Show the inheritance diagram of a class using Mermaid. Default: `False`. - show_source (bool): Show the source code of this object. Default: `True`. - preload_modules (list[str] | None): Pre-load modules that are - not specified directly in autodoc instructions (`::: identifier`). - It is useful when you want to render documentation for a particular member of an object, - and this member is imported from another package than its parent. - - For an imported member to be rendered, you need to add it to the `__all__` attribute - of the importing module. - - The modules must be listed as an array of strings. Default: `None`. - - Attributes: Headings options: - heading (str): A custom string to override the autogenerated heading of the root object. - toc_label (str): A custom string to override the autogenerated toc label of the root object. - heading_level (int): The initial heading level to use. Default: `2`. - parameter_headings (bool): Whether to render headings for parameters (therefore showing parameters in the ToC). Default: `False`. - show_root_heading (bool): Show the heading of the object at the root of the documentation tree - (i.e. the object referenced by the identifier after `:::`). Default: `False`. - show_root_toc_entry (bool): If the root heading is not shown, at least add a ToC entry for it. Default: `True`. - show_root_full_path (bool): Show the full Python path for the root object heading. Default: `True`. - show_root_members_full_path (bool): Show the full Python path of the root members. Default: `False`. - show_object_full_path (bool): Show the full Python path of every object. Default: `False`. - show_category_heading (bool): When grouped by categories, show a heading for each category. Default: `False`. - show_symbol_type_heading (bool): Show the symbol type in headings (e.g. mod, class, meth, func and attr). Default: `False`. - show_symbol_type_toc (bool): Show the symbol type in the Table of Contents (e.g. mod, class, methd, func and attr). Default: `False`. - - Attributes: Members options: - inherited_members (list[str] | bool | None): A boolean, or an explicit list of inherited members to render. - If true, select all inherited members, which can then be filtered with `members`. - If false or empty list, do not select any inherited member. Default: `False`. - members (list[str] | bool | None): A boolean, or an explicit list of members to render. - If true, select all members without further filtering. - If false or empty list, do not render members. - If none, select all members and apply further filtering with filters and docstrings. Default: `None`. - members_order (str): The members ordering to use. Options: `alphabetical` - order by the members names, - `source` - order members as they appear in the source file. Default: `"alphabetical"`. - filters (list[str] | None): A list of filters applied to filter objects based on their name. - A filter starting with `!` will exclude matching objects instead of including them. - The `members` option takes precedence over `filters` (filters will still be applied recursively - to lower members in the hierarchy). Default: `["!^_[^_]"]`. - group_by_category (bool): Group the object's children by categories: attributes, classes, functions, and modules. Default: `True`. - show_submodules (bool): When rendering a module, show its submodules recursively. Default: `False`. - summary (bool | dict[str, bool]): Whether to render summaries of modules, classes, functions (methods) and attributes. - show_labels (bool): Whether to show labels of the members. Default: `True`. - - Attributes: Docstrings options: - docstring_style (str): The docstring style to use: `google`, `numpy`, `sphinx`, or `None`. Default: `"google"`. - 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`. - show_docstring_classes (bool): Whether to display the "Classes" section in the object's docstring. Default: `True`. - show_docstring_modules (bool): Whether to display the "Modules" section in the object's docstring. Default: `True`. - show_docstring_description (bool): Whether to display the textual block (including admonitions) in the object's docstring. Default: `True`. - show_docstring_examples (bool): Whether to display the "Examples" section in the object's docstring. Default: `True`. - show_docstring_other_parameters (bool): Whether to display the "Other Parameters" section in the object's docstring. Default: `True`. - show_docstring_parameters (bool): Whether to display the "Parameters" section in the object's docstring. Default: `True`. - show_docstring_raises (bool): Whether to display the "Raises" section in the object's docstring. Default: `True`. - show_docstring_receives (bool): Whether to display the "Receives" section in the object's docstring. Default: `True`. - show_docstring_returns (bool): Whether to display the "Returns" section in the object's docstring. Default: `True`. - show_docstring_warns (bool): Whether to display the "Warns" section in the object's docstring. Default: `True`. - show_docstring_yields (bool): Whether to display the "Yields" section in the object's docstring. Default: `True`. - - Attributes: Signatures/annotations options: - annotations_path (str): The verbosity for annotations path: `brief` (recommended), or `source` (as written in the source). Default: `"brief"`. - line_length (int): Maximum line length when formatting code/signatures. Default: `60`. - show_signature (bool): Show methods and functions signatures. Default: `True`. - show_signature_annotations (bool): Show the type annotations in methods and functions signatures. Default: `False`. - signature_crossrefs (bool): Whether to render cross-references for type annotations in signatures. Default: `False`. - separate_signature (bool): Whether to put the whole signature in a code block below the heading. - If a formatter (Black or Ruff) is installed, the signature is also formatted using it. Default: `False`. - unwrap_annotated (bool): Whether to unwrap `Annotated` types to show only the type without the annotations. Default: `False`. - modernize_annotations (bool): Whether to modernize annotations, for example `Optional[str]` into `str | None`. Default: `False`. - """ - def __init__( - self, - *args: Any, - config_file_path: str | None = None, - paths: list[str] | None = None, - locale: str = "en", - load_external_modules: bool | None = None, - **kwargs: Any, - ) -> None: + def __init__(self, config: PythonConfig, base_dir: Path, **kwargs: Any) -> None: """Initialize the handler. Parameters: - *args: Handler name, theme and custom templates. - config_file_path: The MkDocs configuration file path. - paths: A list of paths to use as Griffe search paths. - locale: The locale to use when rendering content. - load_external_modules: Load external modules when resolving aliases. - **kwargs: Same thing, but with keyword arguments. + config: The handler configuration. + base_dir: The base directory of the project. + **kwargs: Arguments passed to the parent constructor. """ - super().__init__(*args, **kwargs) + super().__init__(**kwargs) + + self.config = config + self.base_dir = base_dir + + # YORE: Bump 2: Replace block with `self.global_options = config.options`. + global_extra, global_options = PythonOptions._extract_extra(config.options) + if global_extra: + _warn_extra_options(global_extra.keys()) # type: ignore[arg-type] + self._global_extra = global_extra + self.global_options = global_options # Warn if user overrides base templates. - if custom_templates := kwargs.get("custom_templates", ()): - config_dir = Path(config_file_path or "./mkdocs.yml").parent - for theme_dir in config_dir.joinpath(custom_templates, "python").iterdir(): + if self.custom_templates: + for theme_dir in base_dir.joinpath(self.custom_templates, "python").iterdir(): if theme_dir.joinpath("_base").is_dir(): logger.warning( f"Overriding base template '{theme_dir.name}/_base/