Literal ["flat", "tree", False]
:material-equal: `False`{ title="default value" }**
+
+The `backlinks` option enables rendering of backlinks within your API documentation.
+
+When an arbitrary section of your documentation links to an API symbol, this link will be collected as a backlink, and rendered below your API symbol. In short, the API symbol will link back to the section that links to it. Such backlinks will help your users navigate the documentation, as they will immediately which functions return a specific symbol, or where a specific symbol is accepted as parameter, etc..
+
+Each backlink is a list of breadcrumbs that represent the navigation, from the root page down to the given section.
+
+The available styles for rendering backlinks are **`flat`** and **`tree`**.
+
+- **`flat`** will render backlinks as a single-layer list. This can lead to repetition of breadcrumbs.
+- **`tree`** will combine backlinks into a tree, to remove repetition of breadcrumbs.
+
+WARNING: **Global-only option.** For now, the option only works when set globally in `mkdocs.yml`.
```yaml title="in mkdocs.yml (global configuration)"
plugins:
@@ -68,36 +87,36 @@ plugins:
handlers:
python:
options:
- show_bases: true
-```
-
-```md title="or in docs/some_page.md (local configuration)"
-::: path.to.object
- options:
- show_bases: false
+ backlinks: tree
```
/// admonition | Preview
type: preview
-//// tab | With bases
-SomeClass()
Bases: SomeBaseClass
Docstring of the class.
+//// tab | Flat + //// -//// tab | Without bases -SomeClass()
Docstring of the class.
+//// tab | Tree + //// /// -## `show_source` +[](){#option-extensions} +## `extensions` -- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** - +- **:octicons-package-24: Typelist [str | dict [str , dict [str , Any ]]]
:material-equal: `[]`{ title="default value" }**
+
-Show the source code of this object.
+The `extensions` option lets you enable [Griffe extensions](https://mkdocstrings.github.io/griffe/extensions/), which enhance or modify the data collected from Python sources (or compiled modules).
+
+Elements in the list can be strings or dictionaries.
+
+Strings denote the path to an extension module, like `griffe_typingdoc`, or to an extension class directly, like `griffe_typingdoc.TypingDocExtension`. When using a module path, all extensions within that module will be loaded and enabled. Strings can also be the path to a Python module, and a class name separated with `:`, like `scripts/griffe_extensions.py` or `scripts/griffe_extensions.py:MyExtension`.
+
+Dictionaries have a single key, which is the module/class path (as a dot-separated qualifier or file path and colon-separated class name, like above), and its value is another dictionary specifying options that will be passed when to class constructors when instantiating extensions.
+
+WARNING: **Packages are loaded only once.** When mkdocstrings-python collects data from a Python package (thanks to [Griffe](https://mkdocstrings.github.io/griffe/)), it collects *the entire package* and *caches it*. Next time an object from the same package is rendered, the package is retrieved from the cache and not collected again. Only the extensions specified the first time the package is loaded will be used. You cannot use a different set of extensions for specific objects rendered afterwards, and you cannot deactivate extensions for objects rendered afterwards either.
```yaml title="in mkdocs.yml (global configuration)"
plugins:
@@ -105,38 +124,152 @@ plugins:
handlers:
python:
options:
- show_source: true
+ extensions:
+ - griffe_sphinx
+ - griffe_pydantic: {schema: true}
+ - scripts/exts.py:DynamicDocstrings:
+ paths: [mypkg.mymod.myobj]
```
```md title="or in docs/some_page.md (local configuration)"
-::: path.to.object
+::: your_package.your_module.your_func
options:
- show_source: false
+ extensions:
+ - griffe_typingdoc
```
-/// admonition | Preview
- type: preview
+[](){#option-extra}
+## `extra`
-//// tab | With source
-some_function()
Docstring of the function.
+- **:octicons-package-24: Type [`dict`][] :material-equal: `{}`{ title="default value" }** + -///// details | Source code in `package/module.py` - type: quote +The `extra` option lets you inject additional variables into the Jinja context used when rendering templates. You can then use this extra context in your [overridden templates][templates]. -```python linenums="1" -def some_function(): +Local `extra` options will be merged into the global `extra` option: + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + extra: + hello: world +``` + +```md title="in docs/some_page.md (local configuration)" +::: your_package.your_module.your_func + options: + extra: + foo: bar +``` + +...will inject both `hello` and `foo` into the Jinja context when rendering `your_package.your_module.your_func`. + +> WARNING: Previously, extra options were supported directly under the `options` key. +> +> ```yaml +> plugins: +> - mkdocstrings: +> handlers: +> python: +> options: +> hello: world +> ``` +> +> Now that we introduced optional validation of options and automatic JSON schema generation thanks to Pydantic, we require extra options to be put under `options.extra`. Extra options directly under `options` are still supported, but deprecated, and will emit deprecation warnings. Support will be removed in a future version of mkdocstrings-python. + +[](){#option-find_stubs_package} +## `find_stubs_package` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +When looking for documentation specified in [autodoc instructions][autodoc syntax] (`::: identifier`), also look for +the stubs package as defined in [PEP 561](https://peps.python.org/pep-0561/) if it exists. This is useful when +most of your documentation is separately provided by such a package and not inline in your main package. + +WARNING: **Packages are loaded only once.** When mkdocstrings-python collects data from a Python package (thanks to [Griffe](https://mkdocstrings.github.io/griffe/)), it collects *the entire package* and *caches it*. Next time an object from the same package is rendered, the package is retrieved from the cache and not collected again. The `find_stubs_package` option will therefore only have an effect the first time a package is collected, and will do nothing for objects rendered afterwards. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + find_stubs_package: true +``` + +```md title="or in docs/some_page.md (local configuration)" +::: your_package.your_module.your_func + options: + find_stubs_package: true +``` + +```python title="your_package/your_module.py" + +def your_func(a, b): + # Function code ... + +# rest of your code ``` -///// + +```python title="your_package-stubs/your_module.pyi" + +def your_func(a: int, b: str): + """ +your_func
Function docstring
//// -//// tab | Without source -some_function()
Docstring of the function.
+//// tab | Without find_stubs_package +your_func
list [str ] | None
:material-equal: `None`{ title="default value" }**
@@ -165,7 +298,7 @@ plugins:
::: your_package.your_module
options:
preload_modules:
- - their_package
+ - their_package
```
```python title="your_package/your_module.py"
@@ -192,14 +325,68 @@ __all__ = ["their_object"]
////
///
-## `find_stubs_package`
+[](){#option-show_bases}
+## `show_bases`
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
+
+
+Show the base classes of a class.
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ show_bases: true
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.object
+ options:
+ show_bases: false
+```
+
+/// admonition | Preview
+ type: preview
+
+//// tab | With bases
+SomeClass()
Bases: SomeBaseClass
Docstring of the class.
+//// + +//// tab | Without bases +SomeClass()
Docstring of the class.
+//// +/// + +[](){#option-show_inheritance_diagram} +## `show_inheritance_diagram` + +[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } — +[:octicons-tag-24: Insiders 1.7.0](../../insiders/changelog.md#1.7.0) - **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** -When looking for documentation specified in [autodoc instructions][autodoc syntax] (`::: identifier`), also look for -the stubs package as defined in [PEP 561](https://peps.python.org/pep-0561/) if it exists. This is useful when -most of your documentation is separately provided by such a package and not inline in your main package. +Show the inheritance diagram of a class using [Mermaid](https://mermaid.js.org/). + +With this option enabled, an inheritance diagram (as a flowchart) +will be displayed after a class signature. +Each node will act as a cross-reference +and will bring you to the relevant class' documentation +when clicking on it. + +It should work out of the box with [Material for MkDocs][]. +For other themes, you must include Mermaid's Javascript code manually: + +```yaml title="mkdocs.yml" +extra_javascript: +- https://unpkg.com/mermaid@10.9.0/dist/mermaid.min.js +``` ```yaml title="in mkdocs.yml (global configuration)" plugins: @@ -207,44 +394,103 @@ plugins: handlers: python: options: - find_stubs_package: true + show_inheritance_diagram: true ``` ```md title="or in docs/some_page.md (local configuration)" -::: your_package.your_module.your_func +::: path.to.object options: - find_stubs_package: true + show_inheritance_diagram: false ``` -```python title="your_package/your_module.py" +/// admonition | Preview + type: preview -def your_func(a, b): - # Function code - ... +With the following classes: + +```python +class SuperAbstract: + """Super abstract class.""" +class Mixin1: + """Mixin 1.""" +class Abstract(SuperAbstract, Mixin1): + """Abstract class.""" +class Mixin2A: + """Mixin 2A.""" +class Mixin2B(Mixin2A): + """Mixin 2B.""" +class Concrete(Abstract, Mixin2B): + """Concrete class.""" +class SuperConcrete(Concrete): + """Super concrete class.""" +``` -# rest of your code +The diagram for `SuperConcrete` will look like this: + +```mermaid +flowchart TD +SuperConcrete[SuperConcrete] +Concrete[Concrete] +Abstract[Abstract] +SuperAbstract[SuperAbstract] +Mixin1[Mixin1] +Mixin2B[Mixin2B] +Mixin2A[Mixin2A] + +Concrete --> SuperConcrete +Abstract --> Concrete +SuperAbstract --> Abstract +Mixin1 --> Abstract +Mixin2B --> Concrete +Mixin2A --> Mixin2B ``` -```python title="your_package-stubs/your_module.pyi" +*Nodes are not clickable in this example +because these classes do not exist in our documentation.* +/// -def your_func(a: int, b: str): - """ -your_func
Function docstring
+//// tab | With source +some_function()
Docstring of the function.
+ +///// details | Source code in `package/module.py` + type: quote + +```python linenums="1" +def some_function(): + ... +``` +///// //// -//// tab | Without find_stubs_package -your_func
some_function()
Docstring of the function.
//// /// diff --git a/docs/usage/configuration/headings.md b/docs/usage/configuration/headings.md index a9b75e6d..b4314b77 100644 --- a/docs/usage/configuration/headings.md +++ b/docs/usage/configuration/headings.md @@ -1,5 +1,22 @@ # Headings options +[](){#option-heading} +## `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. See also the [`toc_label` option][option-toc_label]. + +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" +``` + +[](){#option-heading_level} ## `heading_level` - **:octicons-package-24: Type [`int`][] :material-equal: `2`{ title="default value" }** @@ -57,6 +74,130 @@ plugins: //// /// +[](){#option-parameter_headings} +## `parameter_headings` + +[:octicons-tag-24: Insiders 1.6.0](../../insiders/changelog.md#1.6.0) + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Whether to render headings for function/method parameters. + +With this option enabled, each function/method parameter +(including parameters of `__init__` methods merged in their parent class +with the [`merge_init_into_class`][] option) +gets a permalink, an entry in the Table of Contents, +and an entry in the generated objects inventory. +The permalink and inventory entry allow cross-references +from internal and external pages. + +The identifier used in the permalink and inventory is of the following form: +`path.to.function(param_name)`. To manually cross-reference a parameter, +you can therefore use this Markdown syntax: + +```md +- Class parameter: [`param`][package.module.Class(param)] +- Method parameter: [`param`][package.module.Class.method(param)] +- Function parameter: [`param`][package.module.function(param)] +- Variadic positional parameters: [`*args`][package.module.function(*args)] +- Variadic keyword parameters: [`**kwargs`][package.module.function(**kwargs)] +``` + +Enabling this option along with [`signature_crossrefs`][] will automatically +render cross-references to parameters in class/function/method signatures +and attributes values. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + parameter_headings: false +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.module + options: + parameter_headings: true +``` + +/// admonition | Preview: Cross-references + type: preview + +```md exec="on" +::: package.get_version + options: + heading_level: 3 + parameter_headings: true + docstring_section_style: list + +::: package.current_version + options: + heading_level: 3 + line_length: 100 +``` + +/// + +/// admonition | Preview: Parameter sections + type: preview + +//// tab | Table style +```md exec="on" +::: package.get_version + options: + heading_level: 3 + show_root_heading: false + show_root_toc_entry: false + parameter_headings: true + docstring_section_style: table + show_docstring_returns: false + show_docstring_description: false +``` +//// + +//// tab | List style +```md exec="on" +::: package.get_version + options: + heading_level: 3 + show_root_heading: false + show_root_toc_entry: false + parameter_headings: true + docstring_section_style: list + show_docstring_returns: false + show_docstring_description: false +``` +//// + +//// tab | Spacy style +```md exec="on" +::: package.get_version + options: + heading_level: 3 + show_root_heading: false + show_root_toc_entry: false + parameter_headings: true + docstring_section_style: spacy + show_docstring_returns: false + show_docstring_description: false +``` +//// +/// + +/// admonition | Preview: Table of contents (with symbol types) + type: preview + +
get_version
dist
+
+To customize symbols, see [Customizing symbol types](../customization.md/#symbol-types).
+
+///
+
+[](){#option-show_root_heading}
## `show_root_heading`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -120,6 +261,7 @@ plugins:
////
///
+[](){#option-show_root_toc_entry}
## `show_root_toc_entry`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
@@ -164,19 +306,20 @@ 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" }
////
///
+[](){#option-show_root_full_path}
## `show_root_full_path`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
@@ -222,6 +365,7 @@ plugins:
////
///
+[](){#option-show_root_members_full_path}
## `show_root_members_full_path`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -270,6 +414,7 @@ plugins:
////
///
+[](){#option-show_object_full_path}
## `show_object_full_path`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -278,7 +423,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
@@ -323,6 +468,7 @@ plugins:
////
///
+[](){#option-show_category_heading}
## `show_category_heading`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -332,7 +478,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
@@ -388,6 +534,7 @@ plugins:
////
///
+[](){#option-show_symbol_type_heading}
## `show_symbol_type_heading`
[:octicons-tag-24: Insiders 1.1.0](../../insiders/changelog.md#1.1.0)
@@ -452,6 +599,7 @@ plugins:
////
///
+[](){#option-show_symbol_type_toc}
## `show_symbol_type_toc`
[:octicons-tag-24: Insiders 1.1.0](../../insiders/changelog.md#1.1.0)
@@ -515,3 +663,22 @@ plugins:
////
///
+
+[](){#option-toc_label}
+## `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. See also the [`heading` option][option-heading].
+
+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"
+```
diff --git a/docs/usage/configuration/members.md b/docs/usage/configuration/members.md
index 119d8294..7a5069a1 100644
--- a/docs/usage/configuration/members.md
+++ b/docs/usage/configuration/members.md
@@ -1,5 +1,6 @@
# Members options
+[](){#option-members}
## `members`
- **:octicons-package-24: Type list [str ] |
@@ -95,6 +96,7 @@ this_attribute = 0
INFO: **The default behavior (with unspecified `members` or `members: null`) is to use [`filters`][].**
+[](){#option-inherited_members}
## `inherited_members`
- **:octicons-package-24: Type list [str ] |
@@ -259,15 +261,17 @@ class Main(Base):
///
+[](){#option-members_order}
## `members_order`
-- **:octicons-package-24: Type [`str`][] :material-equal: `"alphabetical"`{ title="default value" }**
+- **:octicons-package-24: Type `str | list[str]` :material-equal: `"alphabetical"`{ title="default value" }**
The members ordering to use. Possible values:
-- `alphabetical`: order by the members names.
-- `source`: order members as they appear in the source file.
+- `__all__` ([:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } — [:octicons-tag-24: Insiders 1.12.0](../../insiders/changelog.md#1.12.0)): Order according to `__all__` attributes. Since classes do not define `__all__` attributes, you can specify a second ordering method by using a list.
+- `alphabetical`: Order by the members names.
+- `source`: Order members as they appear in the source file.
The order applies for all members, recursively.
The order will be ignored for members that are explicitely sorted using the [`members`][] option.
@@ -289,6 +293,12 @@ plugins:
members_order: source
```
+```md title="or in docs/some_page.md (local configuration)"
+::: package.module
+ options:
+ members_order: [__all__, source]
+```
+
```python title="package/module.py"
"""Module docstring."""
@@ -329,12 +339,24 @@ def function_c():
////
///
+[](){#option-filters}
## `filters`
-- **:octicons-package-24: Type list [str ] | None
:material-equal: `["!^_[^_]"]`{ title="default value" }**
+- **:octicons-package-24: Type list [str ] | Literal ["public"] | None
:material-equal: `["!^_[^_]"]`{ title="default value" }**
-A list of filters applied to filter objects based on their name.
+A list of filters, or `"public"`.
+
+**Filtering methods**
+
+[](){#option-filters-public}
+
+[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } —
+[:octicons-tag-24: Insiders 1.11.0](../../insiders/changelog.md#1.11.0)
+
+The `public` filtering method will include only public objects: those added to the `__all__` attribute of modules, or not starting with a single underscore. Special methods and attributes ("dunder" methods/attributes, starting and ending with two underscores), like `__init__`, `__call__`, `__mult__`, etc., are always considered public.
+
+**List of filters**
Filters are regular expressions. These regular expressions are evaluated by Python
and so must match the syntax supported by the [`re`][] module.
@@ -375,13 +397,13 @@ plugins:
python:
options:
filters:
- - "!^_"
+ - "!^_[^_]"
```
```md title="or in docs/some_page.md (local configuration)"
::: package.module
options:
- filters: []
+ filters: public
```
```python title="package/module.py"
@@ -427,6 +449,7 @@ Here are some common filters that you might to want to use.
- `["!^_[^_]"]`: exclude all private/protected objects, keep special ones (default filters)
///
+[](){#option-group_by_category}
## `group_by_category`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
@@ -496,6 +519,7 @@ def function_d():
////
///
+[](){#option-show_submodules}
## `show_submodules`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -550,9 +574,9 @@ package
////
///
+[](){#option-summary}
## `summary`
-[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } —
[:octicons-tag-24: Insiders 1.2.0](../../insiders/changelog.md#1.2.0)
- **:octicons-package-24: Type bool | dict [str , bool ]
:material-equal: `False`{ title="default value" }**
@@ -644,6 +668,7 @@ plugins:
////
///
+[](){#option-show_labels}
## `show_labels`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
diff --git a/docs/usage/configuration/signatures.md b/docs/usage/configuration/signatures.md
index da96dc5b..98c865e5 100644
--- a/docs/usage/configuration/signatures.md
+++ b/docs/usage/configuration/signatures.md
@@ -1,5 +1,6 @@
# Signatures options
+[](){#option-annotations_path}
## `annotations_path`
- **:octicons-package-24: Type [`str`][] :material-equal: `"brief"`{ title="default value" }**
@@ -146,6 +147,7 @@ def convert(text: str, md: Markdown) -> Markup:
////
///
+[](){#option-line_length}
## `line_length`
- **:octicons-package-24: Type [`int`][] :material-equal: `60`{ title="default value" }**
@@ -154,10 +156,15 @@ def convert(text: str, md: Markdown) -> Markup:
Maximum line length when formatting code/signatures.
When separating signatures from headings with the [`separate_signature`][] option,
-the Python handler will try to format the signatures using [Black] and
+the Python handler will try to format the signatures using a formatter and
the specified line length.
-If Black is not installed, the handler issues an INFO log once.
+The handler will automatically try to format using :
+
+1. [Black]
+2. [Ruff]
+
+If a formatter is not found, the handler issues an INFO log once.
```yaml title="in mkdocs.yml (global configuration)"
plugins:
@@ -193,6 +200,93 @@ plugins:
////
///
+[](){#option-modernize_annotations}
+## `modernize_annotations`
+
+[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } —
+[:octicons-tag-24: Insiders 1.8.0](../../insiders/changelog.md#1.8.0) —
+**This feature also requires
+[Griffe Insiders](https://mkdocstrings.github.io/griffe/insiders/)
+to be installed.**
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
+
+
+Modernize annotations with latest features and PEPs of the Python language.
+
+The Python language keeps evolving, and often library developers
+must continue to support a few minor versions of Python.
+Therefore they cannot use some features that were introduced
+in the latest versions.
+
+Yet this doesn't mean they can't enjoy latest features in their docs:
+Griffe allows to "modernize" expressions, for example
+by replacing `typing.Union` with [PEP 604][pep-604] type unions `|`.
+Thanks to this, mkdocstrings' Python handler
+can automatically transform type annotations into their modern equivalent.
+This improves consistency in your docs, and shows users
+how to use your code with the latest features of the language.
+
+[pep-604]: https://peps.python.org/pep-0604/
+
+Modernizations applied:
+
+- `typing.Dict[A, B]` becomes `dict[A, B]`
+- `typing.List[A]` becomes `list[A]`
+- `typing.Set[A]` becomes `set[A]`
+- `typing.Tuple[A]` becomes `tuple[A]`
+- `typing.Union[A, B]` becomes `A | B`
+- `typing.Optional[A]` becomes `A | None`
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ modernize_annotations: true
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.object
+ options:
+ modernize_annotations: false
+```
+
+/// admonition | Preview
+ type: preview
+
+```python
+--8<-- "docs/snippets/package/modern.py"
+```
+
+//// tab | Unchanged annotations
+
+```md exec="on"
+::: package.modern.example
+ options:
+ modernize_annotations: false
+ show_symbol_type_heading: false
+ show_labels: false
+```
+
+////
+
+//// tab | Modernized annotations
+
+```md exec="on"
+::: package.modern.example
+ options:
+ modernize_annotations: true
+ show_symbol_type_heading: false
+ show_labels: false
+```
+
+////
+
+///
+
+[](){#option-show_signature}
## `show_signature`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
@@ -231,6 +325,7 @@ plugins:
////
///
+[](){#option-show_signature_annotations}
## `show_signature_annotations`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -285,6 +380,7 @@ function(param1, param2=None)
////
///
+[](){#option-separate_signature}
## `separate_signature`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -293,10 +389,15 @@ function(param1, param2=None)
Whether to put the whole signature in a code block below the heading.
When separating signatures from headings,
-the Python handler will try to format the signatures using [Black] and
+the Python handler will try to format the signatures using a formatter and
the specified [line length][line_length].
-If Black is not installed, the handler issues an INFO log once.
+The handler will automatically try to format using :
+
+1. [Black]
+2. [Ruff]
+
+If a formatter is not found, the handler issues an INFO log once.
```yaml title="in mkdocs.yml (global configuration)"
plugins:
@@ -332,6 +433,56 @@ function(param1, param2=None)
////
///
+[](){#option-show_overloads}
+## `show_overloads`
+
+Whether to render function / method overloads.
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ show_overloads: true
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ show_overloads: false
+```
+
+/// admonition | Preview
+ type: preview
+//// tab | With overloads
+function
+
+
+```python
+@overload
+function(param1: int): ...
+
+@overload
+function(param1: str): ...
+
+function(param1: str | int)
+```
+Function docstring.
+
+////
+//// tab | Without overloads
+function
+
+```python
+function(param1: str | int)
+```
+Function docstring.
+
+////
+///
+
+[](){#option-signature_crossrefs}
## `signature_crossrefs`
[:octicons-tag-24: Insiders 1.0.0](../../insiders/changelog.md#1.0.0)
@@ -379,6 +530,7 @@ plugins:
////
///
+[](){#option-unwrap_annotated}
## `unwrap_annotated`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
diff --git a/docs/usage/customization.md b/docs/usage/customization.md
index 5e82001e..8239c2e9 100644
--- a/docs/usage/customization.md
+++ b/docs/usage/customization.md
@@ -89,12 +89,14 @@ by overriding the values of our CSS variables, for example:
```css title="docs/css/mkdocstrings.css"
[data-md-color-scheme="default"] {
+ --doc-symbol-parameter-fg-color: #df50af;
--doc-symbol-attribute-fg-color: #0079ff;
--doc-symbol-function-fg-color: #00dfa2;
--doc-symbol-method-fg-color: #00dfa2;
--doc-symbol-class-fg-color: #d1b619;
--doc-symbol-module-fg-color: #ff0060;
+ --doc-symbol-parameter-bg-color: #df50af1a;
--doc-symbol-attribute-bg-color: #0079ff1a;
--doc-symbol-function-bg-color: #00dfa21a;
--doc-symbol-method-bg-color: #00dfa21a;
@@ -103,12 +105,14 @@ by overriding the values of our CSS variables, for example:
}
[data-md-color-scheme="slate"] {
+ --doc-symbol-parameter-fg-color: #ffa8cc;
--doc-symbol-attribute-fg-color: #963fb8;
--doc-symbol-function-fg-color: #6d67e4;
--doc-symbol-method-fg-color: #6d67e4;
--doc-symbol-class-fg-color: #46c2cb;
--doc-symbol-module-fg-color: #f2f7a1;
+ --doc-symbol-parameter-bg-color: #ffa8cc1a;
--doc-symbol-attribute-bg-color: #963fb81a;
--doc-symbol-function-bg-color: #6d67e41a;
--doc-symbol-method-bg-color: #6d67e41a;
@@ -124,12 +128,14 @@ otherwise just override the variables at root level:
```css title="docs/css/mkdocstrings.css"
:root {
+ --doc-symbol-parameter-fg-color: #df50af;
--doc-symbol-attribute-fg-color: #0079ff;
--doc-symbol-function-fg-color: #00dfa2;
--doc-symbol-method-fg-color: #00dfa2;
--doc-symbol-class-fg-color: #d1b619;
--doc-symbol-module-fg-color: #ff0060;
+ --doc-symbol-parameter-bg-color: #df50af1a;
--doc-symbol-attribute-bg-color: #0079ff1a;
--doc-symbol-function-bg-color: #00dfa21a;
--doc-symbol-method-bg-color: #00dfa21a;
@@ -144,12 +150,14 @@ otherwise just override the variables at root level:
Try cycling through the themes to see the colors for each theme:
+
@@ -189,6 +200,10 @@ You can also change the actual symbol names.
For example, to use single letters instead of truncated types:
```css title="docs/css/mkdocstrings.css"
+.doc-symbol-parameter::after {
+ content: "P";
+}
+
.doc-symbol-attribute::after {
content: "A";
}
@@ -215,6 +230,10 @@ For example, to use single letters instead of truncated types:
+ - Parameter:
- Attribute:
- Function:
- Method:
@@ -263,7 +283,7 @@ for filepath in sorted(path for path in Path(basedir).rglob("*") if "_base" not
)
```
-See them [in the repository](https://github.com/mkdocstrings/python/tree/master/src/mkdocstrings_handlers/python/templates/).
+See them [in the repository](https://github.com/mkdocstrings/python/tree/main/src/mkdocstrings_handlers/python/templates/).
See the general *mkdocstrings* documentation to learn how to override them: https://mkdocstrings.github.io/theming/#templates.
Each one of these templates extends a base version in `theme/_base`. Example:
@@ -351,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`,
@@ -419,4 +439,4 @@ div.doc-contents:not(.first) {
padding-left: 25px;
border-left: .05rem solid rgba(200, 200, 200, 0.2);
}
-```
\ No newline at end of file
+```
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..b2a00955 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).
@@ -75,10 +75,11 @@ plugins:
Some options are **global only**, and go directly under the handler's name.
-#### `import`
+[](){#setting-inventories}
+#### `inventories`
-This option is used to import Sphinx-compatible objects inventories from other
-documentation sites. For example, you can import the standard library
+This option is used to load Sphinx-compatible objects inventories from other
+documentation sites. For example, you can load the standard library
objects inventory like this:
```yaml title="mkdocs.yml"
@@ -86,23 +87,23 @@ plugins:
- mkdocstrings:
handlers:
python:
- import:
- - https://docs.python-requests.org/en/master/objects.inv
+ inventories:
+ - https://docs.python.org/3/objects.inv
```
-When importing an inventory, you enable automatic cross-references
+When loading 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
+or any third-party package docs. Typically, you want to load
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.
[inventories]: https://mkdocstrings.github.io/usage/#cross-references-to-other-projects-inventories
-Additionally, the Python handler accepts a `domains` option in the import items,
-which allows to select the inventory domains to select.
+Additionally, the Python handler accepts a `domains` option in the inventory options,
+which allows to select the inventory domains to load.
By default the Python handler only selects the `py` domain (for Python objects).
You might find useful to also enable the [`std` domain][std domain]:
@@ -113,29 +114,12 @@ plugins:
- mkdocstrings:
handlers:
python:
- import:
+ inventories:
- url: https://docs.python-requests.org/en/master/objects.inv
domains: [std, py]
```
-NOTE: The `import` option is common to *all* handlers, however
-they might implement it differently, or not even implement it.
-
-#### `paths`
-
-This option is used to provide filesystem paths in which to search for Python modules.
-Non-absolute paths are computed as relative to MkDocs configuration file. Example:
-
-```yaml title="mkdocs.yml"
-plugins:
-- mkdocstrings:
- handlers:
- python:
- paths: [src] # search packages in the src folder
-```
-
-More details at [Finding modules](#finding-modules).
-
+[](){#setting-load_external_modules}
#### `load_external_modules`
This option allows resolving aliases (imports) to any external module.
@@ -165,6 +149,28 @@ plugins:
[__all__]: https://docs.python.org/3/tutorial/modules.html#importing-from-a-package
+[](){#setting-locale}
+#### `locale`
+
+The locale to use when translating template strings. The translation system is not fully ready yet, so we don't recommend setting the option for now.
+
+[](){#setting-paths}
+#### `paths`
+
+This option is used to provide filesystem paths in which to search for Python modules.
+Non-absolute paths are computed as relative to MkDocs configuration file. Example:
+
+```yaml title="mkdocs.yml"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ paths: [src] # search packages in the src folder
+```
+
+More details at [Finding modules](#finding-modules).
+
+[](){#setting-options}
### Global/local options
The other options can be used both globally *and* locally, under the `options` key.
@@ -199,13 +205,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.
@@ -292,7 +291,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 +347,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/duties.py b/duties.py
index f1909cc1..18282747 100644
--- a/duties.py
+++ b/duties.py
@@ -3,15 +3,19 @@
from __future__ import annotations
import os
+import re
import sys
from contextlib import contextmanager
+from functools import wraps
from importlib.metadata import version as pkgversion
from pathlib import Path
-from typing import TYPE_CHECKING, Iterator
+from typing import TYPE_CHECKING, Any, Callable
from duty import duty, tools
if TYPE_CHECKING:
+ from collections.abc import Iterator
+
from duty.context import Context
@@ -24,15 +28,30 @@
MULTIRUN = os.environ.get("MULTIRUN", "0") == "1"
-def pyprefix(title: str) -> str: # noqa: D103
+def pyprefix(title: str) -> str:
if MULTIRUN:
prefix = f"(python{sys.version_info.major}.{sys.version_info.minor})"
return f"{prefix:14}{title}"
return title
+def not_from_insiders(func: Callable) -> Callable:
+ @wraps(func)
+ def wrapper(ctx: Context, *args: Any, **kwargs: Any) -> None:
+ origin = ctx.run("git config --get remote.origin.url", silent=True)
+ if "pawamoy-insiders/griffe" in origin:
+ ctx.run(
+ lambda: False,
+ title="Not running this task from insiders repository (do that from public repo instead!)",
+ )
+ return
+ func(ctx, *args, **kwargs)
+
+ return wrapper
+
+
@contextmanager
-def material_insiders() -> Iterator[bool]: # noqa: D103
+def material_insiders() -> Iterator[bool]:
if "+insiders" in pkgversion("mkdocs-material"):
os.environ["MATERIAL_INSIDERS"] = "true"
try:
@@ -43,6 +62,12 @@ def material_insiders() -> Iterator[bool]: # noqa: D103
yield False
+def _get_changelog_version() -> str:
+ changelog_version_re = re.compile(r"^## \[(\d+\.\d+\.\d+)\].*$")
+ with Path(__file__).parent.joinpath("CHANGELOG.md").open("r", encoding="utf8") as file:
+ return next(filter(bool, map(changelog_version_re.match, file))).group(1) # type: ignore[union-attr]
+
+
@duty
def changelog(ctx: Context, bump: str = "") -> None:
"""Update the changelog in-place with latest commits.
@@ -51,9 +76,10 @@ def changelog(ctx: Context, bump: str = "") -> None:
bump: Bump option passed to git-changelog.
"""
ctx.run(tools.git_changelog(bump=bump or None), title="Updating changelog")
+ ctx.run(tools.yore.check(bump=bump or _get_changelog_version()), title="Checking legacy code")
-@duty(pre=["check_quality", "check_types", "check_docs", "check-api"])
+@duty(pre=["check-quality", "check-types", "check-docs", "check-api"])
def check(ctx: Context) -> None:
"""Check it all!"""
@@ -83,9 +109,12 @@ def check_docs(ctx: Context) -> None:
def check_types(ctx: Context) -> None:
"""Check that the code is correctly typed."""
os.environ["MYPYPATH"] = "src"
+ os.environ["FORCE_COLOR"] = "1"
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),
)
@@ -116,23 +145,33 @@ def docs(ctx: Context, *cli_args: str, host: str = "127.0.0.1", port: int = 8000
@duty
-def docs_deploy(ctx: Context) -> None:
- """Deploy the documentation to GitHub pages."""
+def docs_deploy(ctx: Context, *, force: bool = False) -> None:
+ """Deploy the documentation to GitHub pages.
+
+ Parameters:
+ force: Whether to force deployment, even from non-Insiders version.
+ """
os.environ["DEPLOY"] = "true"
with material_insiders() as insiders:
if not insiders:
ctx.run(lambda: False, title="Not deploying docs without Material for MkDocs Insiders!")
- origin = ctx.run("git config --get remote.origin.url", silent=True)
+ origin = ctx.run("git config --get remote.origin.url", silent=True, allow_overrides=False)
if "pawamoy-insiders/mkdocstrings-python" in origin:
ctx.run(
"git remote add upstream git@github.com:mkdocstrings/python",
silent=True,
nofail=True,
+ allow_overrides=False,
)
ctx.run(
tools.mkdocs.gh_deploy(remote_name="upstream", force=True),
title="Deploying documentation",
)
+ elif force:
+ ctx.run(
+ tools.mkdocs.gh_deploy(force=True),
+ title="Deploying documentation",
+ )
else:
ctx.run(
lambda: False,
@@ -162,6 +201,7 @@ def build(ctx: Context) -> None:
@duty
+@not_from_insiders
def publish(ctx: Context) -> None:
"""Publish source and wheel distributions to PyPI."""
if not Path("dist").exists():
@@ -175,18 +215,13 @@ def publish(ctx: Context) -> None:
@duty(post=["build", "publish", "docs-deploy"])
+@not_from_insiders
def release(ctx: Context, version: str = "") -> None:
"""Release a new Python package.
Parameters:
version: The new version number to use.
"""
- origin = ctx.run("git config --get remote.origin.url", silent=True)
- if "pawamoy-insiders/mkdocstrings-python" in origin:
- ctx.run(
- lambda: False,
- title="Not releasing from insiders repository (do that from public repo instead!)",
- )
if not (version := (version or input("> Version to release: ")).strip()):
ctx.run("false", title="A version must be provided")
ctx.run("git add pyproject.toml CHANGELOG.md", title="Staging files", pty=PTY)
@@ -205,20 +240,26 @@ def coverage(ctx: Context) -> None:
@duty
-def test(ctx: Context, *cli_args: str, match: str = "") -> None:
+def test(ctx: Context, *cli_args: str, match: str = "", snapshot: str = "report") -> None:
"""Run the test suite.
Parameters:
match: A pytest expression to filter selected tests.
+ snapshot: Whether to "create", "fix", "trim", or "update" snapshots.
"""
py_version = f"{sys.version_info.major}{sys.version_info.minor}"
os.environ["COVERAGE_FILE"] = f".coverage.{py_version}"
+ args = list(cli_args)
+ if snapshot == "disable" or not snapshot:
+ args = ["-n", "auto", "--inline-snapshot=disable"]
+ else:
+ args = [f"--inline-snapshot={snapshot}"]
ctx.run(
tools.pytest(
"tests",
config_file="config/pytest.ini",
select=match,
color="yes",
- ).add_args("-n", "auto", *cli_args),
+ ).add_args(*args),
title=pyprefix("Running tests"),
)
diff --git a/mkdocs.yml b/mkdocs.yml
index 040ab89b..0199ea9a 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
@@ -34,9 +37,7 @@ nav:
- Advanced:
- Customization: usage/customization.md
- Extensions: usage/extensions.md
-# defer to gen-files + literate-nav
-- API reference:
- - mkdocstrings-python: reference/
+- API reference: reference/api.md
- Development:
- Contributing: contributing.md
- Code of Conduct: code_of_conduct.md
@@ -60,7 +61,8 @@ theme:
- content.code.copy
- content.tooltips
- navigation.footer
- - navigation.indexes
+ - navigation.instant.preview
+ - navigation.path
- navigation.sections
- navigation.tabs
- navigation.tabs.sticky
@@ -116,14 +118,16 @@ markdown_extensions:
emoji_generator: !!python/name:material.extensions.emoji.to_svg
- pymdownx.highlight:
pygments_lang_class: true
-- pymdownx.inlinehilite:
- style_plain_text: py3
- pymdownx.magiclink
- pymdownx.snippets:
auto_append: [docs/.glossary.md]
base_path: [!relative $config_dir]
check_paths: true
-- pymdownx.superfences
+- pymdownx.superfences:
+ custom_fences:
+ - name: mermaid
+ class: mermaid
+ format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
slugify: !!python/object/apply:pymdownx.slugs.slugify
@@ -135,35 +139,39 @@ markdown_extensions:
permalink: "¤"
plugins:
-- autorefs
- search
+- autorefs
- markdown-exec
-- gen-files:
- scripts:
- - scripts/gen_ref_nav.py
-- literate-nav:
- nav_file: SUMMARY.md
+- section-index
# - coverage
- mkdocstrings:
handlers:
python:
- paths: [src]
- import:
+ paths: [src, docs/snippets]
+ inventories:
- https://docs.python.org/3/objects.inv
- https://mkdocstrings.github.io/objects.inv
+ - https://mkdocstrings.github.io/autorefs/objects.inv
- https://mkdocstrings.github.io/griffe/objects.inv
- https://python-markdown.github.io/objects.inv
options:
+ backlinks: tree
docstring_options:
ignore_init_summary: true
docstring_section_style: list
- filters: ["!^_"]
+ extensions: [scripts/griffe_extensions.py]
+ filters: public
heading_level: 1
inherited_members: true
+ line_length: 88
merge_init_into_class: true
parameter_headings: true
preload_modules: [mkdocstrings]
+ relative_crossrefs: true
+ scoped_crossrefs: true
separate_signature: true
+ show_bases: false
+ show_inheritance_diagram: true
show_root_heading: true
show_root_full_path: false
show_signature_annotations: true
@@ -173,11 +181,27 @@ plugins:
signature_crossrefs: true
summary: true
unwrap_annotated: true
-- git-committers:
+- llmstxt:
+ full_output: llms-full.txt
+ sections:
+ Usage:
+ - index.md
+ API:
+ - reference/api.md
+- git-revision-date-localized:
enabled: !ENV [DEPLOY, false]
- repository: mkdocstrings/python
+ enable_creation_date: true
+ type: timeago
- minify:
minify_html: !ENV [DEPLOY, false]
+- redirects:
+ redirect_maps:
+ reference/mkdocstrings_handlers/python/index.md: reference/api.md
+ reference/mkdocstrings_handlers/python/config.md: reference/api.md#mkdocstrings_handlers.python.config
+ reference/mkdocstrings_handlers/python/debug.md: reference/api.md#mkdocstrings_handlers.python.debug
+ reference/mkdocstrings_handlers/python/handler.md: reference/api.md#mkdocstrings_handlers.python.handler
+ reference/mkdocstrings_handlers/python/rendering.md: reference/api.md#mkdocstrings_handlers.python.rendering
+
- group:
enabled: !ENV [MATERIAL_INSIDERS, false]
plugins:
diff --git a/pyproject.toml b/pyproject.toml
index 0eccf7fe..d93cb20c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,9 +6,10 @@ build-backend = "pdm.backend"
name = "mkdocstrings-python"
description = "A Python handler for mkdocstrings."
authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}]
-license = {text = "ISC"}
+license = "ISC"
+license-files = ["LICENSE"]
readme = "README.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
keywords = []
dynamic = ["version"]
classifiers = [
@@ -17,21 +18,23 @@ classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
- "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
"Topic :: Documentation",
"Topic :: Software Development",
+ "Topic :: Software Development :: Documentation",
"Topic :: Utilities",
"Typing :: Typed",
]
dependencies = [
- "mkdocstrings>=0.26",
- "mkdocs-autorefs>=1.2",
- "griffe>=0.49",
+ "mkdocstrings>=0.28.3",
+ "mkdocs-autorefs>=1.4",
+ "griffe>=1.6.2",
+ "typing-extensions>=4.0; python_version < '3.11'",
]
[project.urls]
@@ -44,21 +47,23 @@ Discussions = "https://github.com/mkdocstrings/python/discussions"
Gitter = "https://gitter.im/mkdocstrings/python"
Funding = "https://github.com/sponsors/pawamoy"
-[tool.pdm]
-version = {source = "scm"}
+[tool.pdm.version]
+source = "call"
+getter = "scripts.get_version:get_version"
[tool.pdm.build]
package-dir = "src"
includes = ["src/mkdocstrings_handlers"]
editable-backend = "editables"
-excludes = ["**/.pytest_cache"]
+
+# Include as much as possible in the source distribution, to help redistributors.
+excludes = ["**/.pytest_cache", "**/.mypy_cache"]
source-includes = [
"config",
"docs",
"scripts",
"share",
"tests",
- "devdeps.txt",
"duties.py",
"mkdocs.yml",
"*.md",
@@ -66,6 +71,54 @@ source-includes = [
]
[tool.pdm.build.wheel-data]
+# Manual pages can be included in the wheel.
+# Depending on the installation tool, they will be accessible to users.
+# pipx supports it, uv does not yet, see https://github.com/astral-sh/uv/issues/4731.
data = [
{path = "share/**/*", relative-to = "."},
]
+
+[dependency-groups]
+maintain = [
+ "build>=1.2",
+ "git-changelog>=2.5",
+ "twine>=5.1",
+ "yore>=0.3.3",
+]
+ci = [
+ "black>=25.1",
+ "duty>=1.6",
+ "ruff>=0.4",
+ "pytest>=8.2",
+ "pytest-cov>=5.0",
+ "pytest-randomly>=3.15",
+ "pytest-xdist>=3.6",
+ "beautifulsoup4>=4.12.3",
+ "inline-snapshot>=0.18",
+ "mypy>=1.10",
+ "types-markdown>=3.6",
+ "types-pyyaml>=6.0",
+]
+ docs = [
+ "markdown-callouts>=0.4",
+ "markdown-exec>=1.8",
+ "mkdocs>=1.6",
+ "mkdocs-coverage>=1.0",
+ "mkdocs-git-revision-date-localized-plugin>=1.2",
+ "mkdocs-llmstxt>=0.2",
+ "mkdocs-material>=9.5",
+ "mkdocs-minify-plugin>=0.8",
+ "mkdocs-redirects>=1.2",
+ "mkdocs-section-index>=0.3",
+ "mkdocstrings>=0.29",
+ "pydantic>=2.10",
+ # YORE: EOL 3.10: Remove line.
+ "tomli>=2.0; python_version < '3.11'",
+]
+
+[tool.inline-snapshot]
+storage-dir = "tests/snapshots"
+format-command = "ruff format --config config/ruff.toml --stdin-filename {filename}"
+
+[tool.uv]
+default-groups = ["maintain", "ci", "docs"]
diff --git a/scripts/gen_credits.py b/scripts/gen_credits.py
index b2f6d3e4..6a81e239 100644
--- a/scripts/gen_credits.py
+++ b/scripts/gen_credits.py
@@ -1,21 +1,22 @@
-"""Script to generate the project's credits."""
+# Script to generate the project's credits.
from __future__ import annotations
import os
import sys
from collections import defaultdict
+from collections.abc import Iterable
from importlib.metadata import distributions
from itertools import chain
from pathlib import Path
from textwrap import dedent
-from typing import Dict, Iterable, Union
+from typing import Union
from jinja2 import StrictUndefined
from jinja2.sandbox import SandboxedEnvironment
from packaging.requirements import Requirement
-# TODO: Remove once support for Python 3.10 is dropped.
+# YORE: EOL 3.10: Replace block with line 2.
if sys.version_info >= (3, 11):
import tomllib
else:
@@ -26,11 +27,10 @@
pyproject = tomllib.load(pyproject_file)
project = pyproject["project"]
project_name = project["name"]
-with project_dir.joinpath("devdeps.txt").open() as devdeps_file:
- devdeps = [line.strip() for line in devdeps_file if line.strip() and not line.strip().startswith(("-e", "#"))]
+devdeps = [dep for group in pyproject["dependency-groups"].values() for dep in group if not dep.startswith("-e")]
-PackageMetadata = Dict[str, Union[str, Iterable[str]]]
-Metadata = Dict[str, PackageMetadata]
+PackageMetadata = dict[str, Union[str, Iterable[str]]]
+Metadata = dict[str, PackageMetadata]
def _merge_fields(metadata: dict) -> PackageMetadata:
diff --git a/scripts/gen_ref_nav.py b/scripts/gen_ref_nav.py
deleted file mode 100644
index 6939e864..00000000
--- a/scripts/gen_ref_nav.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""Generate the code reference pages and navigation."""
-
-from pathlib import Path
-
-import mkdocs_gen_files
-
-nav = mkdocs_gen_files.Nav()
-mod_symbol = '
'
-
-root = Path(__file__).parent.parent
-src = root / "src"
-
-for path in sorted(src.rglob("*.py")):
- module_path = path.relative_to(src).with_suffix("")
- doc_path = path.relative_to(src).with_suffix(".md")
- full_doc_path = Path("reference", doc_path)
-
- parts = tuple(module_path.parts)
-
- if parts[-1] == "__init__":
- parts = parts[:-1]
- doc_path = doc_path.with_name("index.md")
- full_doc_path = full_doc_path.with_name("index.md")
- elif parts[-1].startswith("_"):
- continue
-
- nav_parts = [f"{mod_symbol} {part}" for part in parts]
- nav[tuple(nav_parts)] = doc_path.as_posix()
-
- with mkdocs_gen_files.open(full_doc_path, "w") as fd:
- ident = ".".join(parts)
- fd.write(f"---\ntitle: {ident}\n---\n\n::: {ident}")
-
- mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path.relative_to(root))
-
-with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file:
- nav_file.writelines(nav.build_literate_nav())
diff --git a/scripts/get_version.py b/scripts/get_version.py
new file mode 100644
index 00000000..6734e5b6
--- /dev/null
+++ b/scripts/get_version.py
@@ -0,0 +1,26 @@
+# Get current project version from Git tags or changelog.
+
+import re
+from contextlib import suppress
+from pathlib import Path
+
+from pdm.backend.hooks.version import SCMVersion, Version, default_version_formatter, get_version_from_scm
+
+_root = Path(__file__).parent.parent
+_changelog = _root / "CHANGELOG.md"
+_changelog_version_re = re.compile(r"^## \[(\d+\.\d+\.\d+)\].*$")
+_default_scm_version = SCMVersion(Version("0.0.0"), None, False, None, None) # noqa: FBT003
+
+
+def get_version() -> str:
+ scm_version = get_version_from_scm(_root) or _default_scm_version
+ if scm_version.version <= Version("0.1"): # Missing Git tags?
+ with suppress(OSError, StopIteration): # noqa: SIM117
+ with _changelog.open("r", encoding="utf8") as file:
+ match = next(filter(None, map(_changelog_version_re.match, file)))
+ scm_version = scm_version._replace(version=Version(match.group(1)))
+ return default_version_formatter(scm_version)
+
+
+if __name__ == "__main__":
+ print(get_version())
diff --git a/scripts/griffe_extensions.py b/scripts/griffe_extensions.py
new file mode 100644
index 00000000..eb50f5f2
--- /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_handlers.python._internal.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/insiders.py b/scripts/insiders.py
index 15212486..4cd438d4 100644
--- a/scripts/insiders.py
+++ b/scripts/insiders.py
@@ -1,4 +1,4 @@
-"""Functions related to Insiders funding goals."""
+# Functions related to Insiders funding goals.
from __future__ import annotations
@@ -10,35 +10,34 @@
from datetime import date, datetime, timedelta
from itertools import chain
from pathlib import Path
-from typing import Iterable, cast
+from typing import TYPE_CHECKING, cast
from urllib.error import HTTPError
from urllib.parse import urljoin
from urllib.request import urlopen
import yaml
+if TYPE_CHECKING:
+ from collections.abc import Iterable
+
logger = logging.getLogger(f"mkdocs.logs.{__name__}")
-def human_readable_amount(amount: int) -> str: # noqa: D103
+def human_readable_amount(amount: int) -> str:
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
@dataclass
class Project:
- """Class representing an Insiders project."""
-
name: str
url: str
@dataclass
class Feature:
- """Class representing an Insiders feature."""
-
name: str
ref: str | None
since: date | None
@@ -65,8 +64,6 @@ def render(self, rel_base: str = "..", *, badge: bool = False) -> None: # noqa:
@dataclass
class Goal:
- """Class representing an Insiders goal."""
-
name: str
amount: int
features: list[Feature]
@@ -91,16 +88,6 @@ def render(self, rel_base: str = "..") -> None: # noqa: D102
def load_goals(data: str, funding: int = 0, project: Project | None = None) -> dict[int, Goal]:
- """Load goals from JSON data.
-
- Parameters:
- data: The JSON data.
- funding: The current total funding, per month.
- origin: The origin of the data (URL).
-
- Returns:
- A dictionaries of goals, keys being their target monthly amount.
- """
goals_data = yaml.safe_load(data)["goals"]
return {
amount: Goal(
@@ -148,15 +135,6 @@ def _load_goals(source: str | tuple[str, str, str], funding: int = 0) -> dict[in
def funding_goals(source: str | list[str | tuple[str, str, str]], funding: int = 0) -> dict[int, Goal]:
- """Load funding goals from a given data source.
-
- Parameters:
- source: The data source (local file path or URL).
- funding: The current total funding, per month.
-
- Returns:
- A dictionaries of goals, keys being their target monthly amount.
- """
if isinstance(source, str):
return _load_goals_from_disk(source, funding)
goals = {}
@@ -171,18 +149,10 @@ def funding_goals(source: str | list[str | tuple[str, str, str]], funding: int =
def feature_list(goals: Iterable[Goal]) -> list[Feature]:
- """Extract feature list from funding goals.
-
- Parameters:
- goals: A list of funding goals.
-
- Returns:
- A list of features.
- """
return list(chain.from_iterable(goal.features for goal in goals))
-def load_json(url: str) -> str | list | dict: # noqa: D103
+def load_json(url: str) -> str | list | dict:
with urlopen(url) as response: # noqa: S310
return json.loads(response.read().decode())
@@ -198,6 +168,6 @@ def load_json(url: str) -> str | list | dict: # noqa: D103
ongoing_goals = [goal for goal in goals.values() if not goal.complete]
unreleased_features = sorted(
(ft for ft in feature_list(ongoing_goals) if ft.since),
- key=lambda ft: cast(date, ft.since),
+ key=lambda ft: cast("date", ft.since),
reverse=True,
)
diff --git a/scripts/make b/scripts/make
deleted file mode 100755
index d898022e..00000000
--- a/scripts/make
+++ /dev/null
@@ -1,210 +0,0 @@
-#!/usr/bin/env python3
-"""Management commands."""
-
-from __future__ import annotations
-
-import os
-import shutil
-import subprocess
-import sys
-from contextlib import contextmanager
-from pathlib import Path
-from typing import Any, Iterator
-
-PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.8 3.9 3.10 3.11 3.12 3.13").split()
-
-exe = ""
-prefix = ""
-
-
-def shell(cmd: str, capture_output: bool = False, **kwargs: Any) -> str | None:
- """Run a shell command."""
- if capture_output:
- return subprocess.check_output(cmd, shell=True, text=True, **kwargs) # noqa: S602
- subprocess.run(cmd, shell=True, check=True, stderr=subprocess.STDOUT, **kwargs) # noqa: S602
- return None
-
-
-@contextmanager
-def environ(**kwargs: str) -> Iterator[None]:
- """Temporarily set environment variables."""
- original = dict(os.environ)
- os.environ.update(kwargs)
- try:
- yield
- finally:
- os.environ.clear()
- os.environ.update(original)
-
-
-def uv_install() -> None:
- """Install dependencies using uv."""
- uv_opts = ""
- if "UV_RESOLUTION" in os.environ:
- uv_opts = f"--resolution={os.getenv('UV_RESOLUTION')}"
- requirements = shell(f"uv pip compile {uv_opts} pyproject.toml devdeps.txt", capture_output=True)
- shell("uv pip install -r -", input=requirements, text=True)
- if "CI" not in os.environ:
- shell("uv pip install --no-deps -e .")
- else:
- shell("uv pip install --no-deps .")
-
-
-def setup() -> None:
- """Setup the project."""
- if not shutil.which("uv"):
- raise ValueError("make: setup: uv must be installed, see https://github.com/astral-sh/uv")
-
- print("Installing dependencies (default environment)") # noqa: T201
- default_venv = Path(".venv")
- if not default_venv.exists():
- shell("uv venv --python python")
- uv_install()
-
- if PYTHON_VERSIONS:
- for version in PYTHON_VERSIONS:
- print(f"\nInstalling dependencies (python{version})") # noqa: T201
- venv_path = Path(f".venvs/{version}")
- if not venv_path.exists():
- shell(f"uv venv --python {version} {venv_path}")
- with environ(VIRTUAL_ENV=str(venv_path.resolve())):
- uv_install()
-
-
-def activate(path: str) -> None:
- """Activate a virtual environment."""
- global exe, prefix # noqa: PLW0603
-
- if (bin := Path(path, "bin")).exists():
- activate_script = bin / "activate_this.py"
- elif (scripts := Path(path, "Scripts")).exists():
- activate_script = scripts / "activate_this.py"
- exe = ".exe"
- prefix = f"{path}/Scripts/"
- else:
- raise ValueError(f"make: activate: Cannot find activation script in {path}")
-
- if not activate_script.exists():
- raise ValueError(f"make: activate: Cannot find activation script in {path}")
-
- exec(activate_script.read_text(), {"__file__": str(activate_script)}) # noqa: S102
-
-
-def run(version: str, cmd: str, *args: str, **kwargs: Any) -> None:
- """Run a command in a virtual environment."""
- kwargs = {"check": True, **kwargs}
- if version == "default":
- activate(".venv")
- subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510
- else:
- activate(f".venvs/{version}")
- os.environ["MULTIRUN"] = "1"
- subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510
-
-
-def multirun(cmd: str, *args: str, **kwargs: Any) -> None:
- """Run a command for all configured Python versions."""
- if PYTHON_VERSIONS:
- for version in PYTHON_VERSIONS:
- run(version, cmd, *args, **kwargs)
- else:
- run("default", cmd, *args, **kwargs)
-
-
-def allrun(cmd: str, *args: str, **kwargs: Any) -> None:
- """Run a command in all virtual environments."""
- run("default", cmd, *args, **kwargs)
- if PYTHON_VERSIONS:
- multirun(cmd, *args, **kwargs)
-
-
-def clean() -> None:
- """Delete build artifacts and cache files."""
- paths_to_clean = ["build", "dist", "htmlcov", "site", ".coverage*", ".pdm-build"]
- for path in paths_to_clean:
- shell(f"rm -rf {path}")
-
- cache_dirs = [".cache", ".pytest_cache", ".mypy_cache", ".ruff_cache", "__pycache__"]
- for dirpath in Path(".").rglob("*"):
- if any(dirpath.match(pattern) for pattern in cache_dirs) and not (dirpath.match(".venv") or dirpath.match(".venvs")):
- shutil.rmtree(path, ignore_errors=True)
-
-
-def vscode() -> None:
- """Configure VSCode to work on this project."""
- Path(".vscode").mkdir(parents=True, exist_ok=True)
- shell("cp -v config/vscode/* .vscode")
-
-
-def main() -> int:
- """Main entry point."""
- args = list(sys.argv[1:])
- if not args or args[0] == "help":
- if len(args) > 1:
- run("default", "duty", "--help", args[1])
- else:
- print("Available commands") # noqa: T201
- print(" help Print this help. Add task name to print help.") # noqa: T201
- print(" setup Setup all virtual environments (install dependencies).") # noqa: T201
- print(" run Run a command in the default virtual environment.") # noqa: T201
- print(" multirun Run a command for all configured Python versions.") # noqa: T201
- print(" allrun Run a command in all virtual environments.") # noqa: T201
- print(" 3.x Run a command in the virtual environment for Python 3.x.") # noqa: T201
- print(" clean Delete build artifacts and cache files.") # noqa: T201
- print(" vscode Configure VSCode to work on this project.") # noqa: T201
- try:
- run("default", "python", "-V", capture_output=True)
- except (subprocess.CalledProcessError, ValueError):
- pass
- else:
- print("\nAvailable tasks") # noqa: T201
- run("default", "duty", "--list")
- return 0
-
- while args:
- cmd = args.pop(0)
-
- if cmd == "run":
- run("default", *args)
- return 0
-
- if cmd == "multirun":
- multirun(*args)
- return 0
-
- if cmd == "allrun":
- allrun(*args)
- return 0
-
- if cmd.startswith("3."):
- run(cmd, *args)
- return 0
-
- opts = []
- while args and (args[0].startswith("-") or "=" in args[0]):
- opts.append(args.pop(0))
-
- if cmd == "clean":
- clean()
- elif cmd == "setup":
- setup()
- elif cmd == "vscode":
- vscode()
- elif cmd == "check":
- multirun("duty", "check-quality", "check-types", "check-docs")
- run("default", "duty", "check-api")
- elif cmd in {"check-quality", "check-docs", "check-types", "test"}:
- multirun("duty", cmd, *opts)
- else:
- run("default", "duty", cmd, *opts)
-
- return 0
-
-
-if __name__ == "__main__":
- try:
- sys.exit(main())
- except subprocess.CalledProcessError as process:
- if process.output:
- print(process.output, file=sys.stderr) # noqa: T201
- sys.exit(process.returncode)
diff --git a/scripts/make b/scripts/make
new file mode 120000
index 00000000..c2eda0df
--- /dev/null
+++ b/scripts/make
@@ -0,0 +1 @@
+make.py
\ No newline at end of file
diff --git a/scripts/make.py b/scripts/make.py
new file mode 100755
index 00000000..5a7fb4c2
--- /dev/null
+++ b/scripts/make.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import os
+import shutil
+import subprocess
+import sys
+from contextlib import contextmanager
+from pathlib import Path
+from textwrap import dedent
+from typing import TYPE_CHECKING, Any
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+
+
+PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13").split()
+
+
+def shell(cmd: str, *, capture_output: bool = False, **kwargs: Any) -> str | None:
+ """Run a shell command."""
+ if capture_output:
+ return subprocess.check_output(cmd, shell=True, text=True, **kwargs) # noqa: S602
+ subprocess.run(cmd, shell=True, check=True, stderr=subprocess.STDOUT, **kwargs) # noqa: S602
+ return None
+
+
+@contextmanager
+def environ(**kwargs: str) -> Iterator[None]:
+ """Temporarily set environment variables."""
+ original = dict(os.environ)
+ os.environ.update(kwargs)
+ try:
+ yield
+ finally:
+ os.environ.clear()
+ os.environ.update(original)
+
+
+def uv_install(venv: Path) -> None:
+ """Install dependencies using uv."""
+ with environ(UV_PROJECT_ENVIRONMENT=str(venv), PYO3_USE_ABI3_FORWARD_COMPATIBILITY="1"):
+ if "CI" in os.environ:
+ shell("uv sync --no-editable")
+ else:
+ shell("uv sync")
+
+
+def setup() -> None:
+ """Setup the project."""
+ if not shutil.which("uv"):
+ raise ValueError("make: setup: uv must be installed, see https://github.com/astral-sh/uv")
+
+ print("Installing dependencies (default environment)")
+ default_venv = Path(".venv")
+ if not default_venv.exists():
+ shell("uv venv")
+ uv_install(default_venv)
+
+ if PYTHON_VERSIONS:
+ for version in PYTHON_VERSIONS:
+ print(f"\nInstalling dependencies (python{version})")
+ venv_path = Path(f".venvs/{version}")
+ if not venv_path.exists():
+ shell(f"uv venv --python {version} {venv_path}")
+ with environ(UV_PROJECT_ENVIRONMENT=str(venv_path.resolve())):
+ uv_install(venv_path)
+
+
+def run(version: str, cmd: str, *args: str, **kwargs: Any) -> None:
+ """Run a command in a virtual environment."""
+ kwargs = {"check": True, **kwargs}
+ uv_run = ["uv", "run", "--no-sync"]
+ if version == "default":
+ with environ(UV_PROJECT_ENVIRONMENT=".venv"):
+ subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510
+ else:
+ with environ(UV_PROJECT_ENVIRONMENT=f".venvs/{version}", MULTIRUN="1"):
+ subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510
+
+
+def multirun(cmd: str, *args: str, **kwargs: Any) -> None:
+ """Run a command for all configured Python versions."""
+ if PYTHON_VERSIONS:
+ for version in PYTHON_VERSIONS:
+ run(version, cmd, *args, **kwargs)
+ else:
+ run("default", cmd, *args, **kwargs)
+
+
+def allrun(cmd: str, *args: str, **kwargs: Any) -> None:
+ """Run a command in all virtual environments."""
+ run("default", cmd, *args, **kwargs)
+ if PYTHON_VERSIONS:
+ multirun(cmd, *args, **kwargs)
+
+
+def clean() -> None:
+ """Delete build artifacts and cache files."""
+ paths_to_clean = ["build", "dist", "htmlcov", "site", ".coverage*", ".pdm-build"]
+ for path in paths_to_clean:
+ shutil.rmtree(path, ignore_errors=True)
+
+ cache_dirs = {".cache", ".pytest_cache", ".mypy_cache", ".ruff_cache", "__pycache__"}
+ for dirpath in Path(".").rglob("*/"):
+ if dirpath.parts[0] not in (".venv", ".venvs") and dirpath.name in cache_dirs:
+ shutil.rmtree(dirpath, ignore_errors=True)
+
+
+def vscode() -> None:
+ """Configure VSCode to work on this project."""
+ shutil.copytree("config/vscode", ".vscode", dirs_exist_ok=True)
+
+
+def main() -> int:
+ """Main entry point."""
+ args = list(sys.argv[1:])
+ if not args or args[0] == "help":
+ if len(args) > 1:
+ run("default", "duty", "--help", args[1])
+ else:
+ print(
+ dedent(
+ """
+ Available commands
+ help Print this help. Add task name to print help.
+ setup Setup all virtual environments (install dependencies).
+ run Run a command in the default virtual environment.
+ multirun Run a command for all configured Python versions.
+ allrun Run a command in all virtual environments.
+ 3.x Run a command in the virtual environment for Python 3.x.
+ clean Delete build artifacts and cache files.
+ vscode Configure VSCode to work on this project.
+ """,
+ ),
+ flush=True,
+ )
+ if os.path.exists(".venv"):
+ print("\nAvailable tasks", flush=True)
+ run("default", "duty", "--list")
+ return 0
+
+ while args:
+ cmd = args.pop(0)
+
+ if cmd == "run":
+ run("default", *args)
+ return 0
+
+ if cmd == "multirun":
+ multirun(*args)
+ return 0
+
+ if cmd == "allrun":
+ allrun(*args)
+ return 0
+
+ if cmd.startswith("3."):
+ run(cmd, *args)
+ return 0
+
+ opts = []
+ while args and (args[0].startswith("-") or "=" in args[0]):
+ opts.append(args.pop(0))
+
+ if cmd == "clean":
+ clean()
+ elif cmd == "setup":
+ setup()
+ elif cmd == "vscode":
+ vscode()
+ elif cmd == "check":
+ multirun("duty", "check-quality", "check-types", "check-docs")
+ run("default", "duty", "check-api")
+ elif cmd in {"check-quality", "check-docs", "check-types", "test"}:
+ multirun("duty", cmd, *opts)
+ else:
+ run("default", "duty", cmd, *opts)
+
+ return 0
+
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except subprocess.CalledProcessError as process:
+ if process.output:
+ print(process.output, file=sys.stderr)
+ sys.exit(process.returncode)
diff --git a/scripts/mkdocs_hooks.py b/scripts/mkdocs_hooks.py
new file mode 100644
index 00000000..739f93b3
--- /dev/null
+++ b/scripts/mkdocs_hooks.py
@@ -0,0 +1,46 @@
+# Generate a JSON schema of the Python handler configuration.
+
+import json
+from dataclasses import dataclass, fields
+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 import PythonInputConfig, PythonInputOptions
+
+# 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
+
+ @dataclass
+ class PythonHandlerSchema:
+ python: PythonInputConfig
+
+ adapter = TypeAdapter(PythonHandlerSchema)
+ 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")
+
+ autorefs = config["plugins"]["autorefs"]
+ for field in fields(PythonInputConfig):
+ if f"setting-{field.name}" not in autorefs._primary_url_map:
+ _logger.warning(f"Handler setting `{field.name}` is not documented")
+ for field in fields(PythonInputOptions):
+ if f"option-{field.name}" not in autorefs._primary_url_map:
+ _logger.warning(f"Configuration option `{field.name}` is not documented")
diff --git a/src/mkdocstrings_handlers/python/__init__.py b/src/mkdocstrings_handlers/python/__init__.py
index 0432a90d..faa9b9f4 100644
--- a/src/mkdocstrings_handlers/python/__init__.py
+++ b/src/mkdocstrings_handlers/python/__init__.py
@@ -1,5 +1,70 @@
"""Python handler for mkdocstrings."""
-from mkdocstrings_handlers.python.handler import get_handler
+from mkdocstrings_handlers.python._internal.config import (
+ AutoStyleOptions,
+ GoogleStyleOptions,
+ Inventory,
+ NumpyStyleOptions,
+ PerStyleOptions,
+ PythonConfig,
+ PythonInputConfig,
+ PythonInputOptions,
+ PythonOptions,
+ SphinxStyleOptions,
+ SummaryOption,
+)
+from mkdocstrings_handlers.python._internal.handler import PythonHandler, get_handler
+from mkdocstrings_handlers.python._internal.rendering import (
+ AutorefsHook,
+ Order,
+ Tree,
+ do_as_attributes_section,
+ do_as_classes_section,
+ do_as_functions_section,
+ do_as_modules_section,
+ do_backlink_tree,
+ do_crossref,
+ do_filter_objects,
+ do_format_attribute,
+ do_format_code,
+ do_format_signature,
+ do_get_template,
+ do_multi_crossref,
+ do_order_members,
+ do_split_path,
+ do_stash_crossref,
+)
-__all__ = ["get_handler"]
+__all__ = [
+ "AutoStyleOptions",
+ "AutorefsHook",
+ "GoogleStyleOptions",
+ "Inventory",
+ "NumpyStyleOptions",
+ "Order",
+ "PerStyleOptions",
+ "PythonConfig",
+ "PythonHandler",
+ "PythonInputConfig",
+ "PythonInputOptions",
+ "PythonOptions",
+ "SphinxStyleOptions",
+ "SummaryOption",
+ "Tree",
+ "do_as_attributes_section",
+ "do_as_classes_section",
+ "do_as_functions_section",
+ "do_as_modules_section",
+ "do_backlink_tree",
+ "do_crossref",
+ "do_filter_objects",
+ "do_format_attribute",
+ "do_format_code",
+ "do_format_signature",
+ "do_get_template",
+ "do_multi_crossref",
+ "do_order_members",
+ "do_split_path",
+ "do_stash_crossref",
+ "get_handler",
+]
diff --git a/src/mkdocstrings_handlers/python/_internal/__init__.py b/src/mkdocstrings_handlers/python/_internal/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/mkdocstrings_handlers/python/_internal/config.py b/src/mkdocstrings_handlers/python/_internal/config.py
new file mode 100644
index 00000000..210f8fe2
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/config.py
@@ -0,0 +1,1058 @@
+# 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
+
+from mkdocstrings import get_logger
+
+from mkdocstrings_handlers.python._internal.rendering import Order # noqa: TC001
+
+# 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
+
+
+_logger = get_logger(__name__)
+
+_DEFAULT_FILTERS = ["!^_[^_]"]
+
+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"
+ # }
+ import pydantic
+
+ if getattr(pydantic, "__version__", "1.").startswith("1."):
+ raise ImportError # noqa: TRY301
+
+ # YORE: EOL 3.9: Remove block.
+ if sys.version_info < (3, 10):
+ try:
+ import eval_type_backport # noqa: F401
+ except ImportError:
+ _logger.debug(
+ "Pydantic needs the `eval-type-backport` package to be installed "
+ "for modern type syntax to work on Python 3.9. "
+ "Deactivating Pydantic validation for Python handler options.",
+ )
+ raise
+
+ 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
+ *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: 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"
+
+ backlinks: Annotated[
+ Literal["flat", "tree", False],
+ _Field(
+ group="general",
+ description="Whether to render backlinks, and how.",
+ ),
+ ] = False
+
+ 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] | Literal["public"],
+ _Field(
+ group="members",
+ description="""A list of filters, or `"public"`.
+
+ **List of filters**
+
+ 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).
+
+ **Filtering methods**
+
+ [:octicons-heart-fill-24:{ .pulse } Sponsors only](../insiders/index.md){ .insiders } —
+ [:octicons-tag-24: Insiders 1.11.0](../insiders/changelog.md#1.11.0)
+
+ The `public` method will include only public objects:
+ those added to `__all__` or not starting with an underscore (except for special methods/attributes).
+ """,
+ ),
+ ] = field(default_factory=lambda: _DEFAULT_FILTERS.copy())
+
+ 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[
+ Order | list[Order],
+ _Field(
+ group="members",
+ description="""The members ordering to use.
+
+ - `__all__`: order members according to `__all__` module attributes, if declared;
+ - `alphabetical`: order members alphabetically;
+ - `source`: order members as they appear in the source file.
+
+ Since `__all__` is a module-only attribute, it can't be used to sort class members,
+ therefore the `members_order` option accepts a list of ordering methods,
+ indicating ordering preferences.
+ """,
+ ),
+ ] = "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
+
+ show_overloads: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Show the overloads of a function or method.",
+ ),
+ ] = True
+
+ 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
+
+ @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]] | Literal["public"] = field( # type: ignore[assignment]
+ default_factory=lambda: [
+ (re.compile(filtr.removeprefix("!")), filtr.startswith("!")) for filtr in _DEFAULT_FILTERS
+ ],
+ )
+ """A list of filters, or `"public"`."""
+
+ 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:
+ # Non-insiders: transform back to default filters.
+ # Next: `if "filters" in data and not isinstance(data["filters"], str):`.
+ if data["filters"] == "public":
+ data["filters"] = _DEFAULT_FILTERS
+ # Filters are `None` or a sequence of strings (tests use tuples).
+ data["filters"] = [
+ (re.compile(filtr.removeprefix("!")), 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_url: 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_url": self.base_url, "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: Annotated[
+ list[Inventory],
+ _Field(description="The object inventories to load."),
+ ] = field(default_factory=list) # type: ignore[assignment]
+
+ options: Annotated[
+ dict[str, Any],
+ _Field(description="Configuration options for collecting and rendering objects."),
+ ] = 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/debug.py b/src/mkdocstrings_handlers/python/_internal/debug.py
similarity index 80%
rename from src/mkdocstrings_handlers/python/debug.py
rename to src/mkdocstrings_handlers/python/_internal/debug.py
index e44f2be5..5fff669f 100644
--- a/src/mkdocstrings_handlers/python/debug.py
+++ b/src/mkdocstrings_handlers/python/_internal/debug.py
@@ -1,5 +1,3 @@
-"""Debugging utilities."""
-
from __future__ import annotations
import os
@@ -10,7 +8,7 @@
@dataclass
-class Variable:
+class _Variable:
"""Dataclass describing an environment variable."""
name: str
@@ -20,7 +18,7 @@ class Variable:
@dataclass
-class Package:
+class _Package:
"""Dataclass describing a Python package."""
name: str
@@ -30,7 +28,7 @@ class Package:
@dataclass
-class Environment:
+class _Environment:
"""Dataclass to store environment information."""
interpreter_name: str
@@ -41,9 +39,9 @@ class Environment:
"""Path to Python executable."""
platform: str
"""Operating System."""
- packages: list[Package]
+ packages: list[_Package]
"""Installed packages."""
- variables: list[Variable]
+ variables: list[_Variable]
"""Environment variables."""
@@ -58,7 +56,7 @@ def _interpreter_name_version() -> tuple[str, str]:
return "", "0.0.0"
-def get_version(dist: str = "mkdocstrings-python") -> str:
+def _get_version(dist: str = "mkdocstrings-python") -> str:
"""Get version of the given distribution.
Parameters:
@@ -73,28 +71,28 @@ def get_version(dist: str = "mkdocstrings-python") -> str:
return "0.0.0"
-def get_debug_info() -> Environment:
+def _get_debug_info() -> _Environment:
"""Get debug/environment information.
Returns:
Environment information.
"""
py_name, py_version = _interpreter_name_version()
- packages = ["mkdocs", "mkdocstrings", "mkdocstrings-python", "griffe"]
+ packages = ["mkdocstrings-python"]
variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("MKDOCSTRINGS_PYTHON")]]
- return Environment(
+ return _Environment(
interpreter_name=py_name,
interpreter_version=py_version,
interpreter_path=sys.executable,
platform=platform.platform(),
- variables=[Variable(var, val) for var in variables if (val := os.getenv(var))],
- packages=[Package(pkg, get_version(pkg)) for pkg in packages],
+ variables=[_Variable(var, val) for var in variables if (val := os.getenv(var))],
+ packages=[_Package(pkg, _get_version(pkg)) for pkg in packages],
)
-def print_debug_info() -> None:
+def _print_debug_info() -> None:
"""Print debug/environment information."""
- info = get_debug_info()
+ info = _get_debug_info()
print(f"- __System__: {info.platform}")
print(f"- __Python__: {info.interpreter_name} {info.interpreter_version} ({info.interpreter_path})")
print("- __Environment variables__:")
@@ -106,4 +104,4 @@ def print_debug_info() -> None:
if __name__ == "__main__":
- print_debug_info()
+ _print_debug_info()
diff --git a/src/mkdocstrings_handlers/python/_internal/handler.py b/src/mkdocstrings_handlers/python/_internal/handler.py
new file mode 100644
index 00000000..158d7ddc
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/handler.py
@@ -0,0 +1,416 @@
+# This module implements a handler for the Python language.
+
+from __future__ import annotations
+
+import glob
+import os
+import posixpath
+import sys
+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,
+ GriffeLoader,
+ LinesCollection,
+ ModulesCollection,
+ Parser,
+ load_extensions,
+ patch_loggers,
+)
+from mkdocs.exceptions import PluginError
+from mkdocstrings import BaseHandler, CollectionError, CollectorItem, HandlerOptions, Inventory, get_logger
+
+from mkdocstrings_handlers.python._internal import rendering
+from mkdocstrings_handlers.python._internal.config import PythonConfig, PythonOptions
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator, Mapping, MutableMapping, Sequence
+
+ from mkdocs.config.defaults import MkDocsConfig
+
+
+# YORE: EOL 3.10: Replace block with line 2.
+if sys.version_info >= (3, 11):
+ from contextlib import chdir
+else:
+ from contextlib import contextmanager
+
+ @contextmanager
+ def chdir(path: str) -> Iterator[None]:
+ old_wd = os.getcwd()
+ os.chdir(path)
+ try:
+ yield
+ finally:
+ os.chdir(old_wd)
+
+
+_logger = get_logger(__name__)
+
+patch_loggers(get_logger)
+
+
+# YORE: Bump 2: Remove block.
+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: ClassVar[str] = "python"
+ """The handler's name."""
+
+ domain: ClassVar[str] = "py"
+ """The cross-documentation domain/language for this handler."""
+
+ enable_inventory: ClassVar[bool] = True
+ """Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file."""
+
+ fallback_theme: ClassVar[str] = "material"
+ """The fallback theme."""
+
+ def __init__(self, config: PythonConfig, base_dir: Path, **kwargs: Any) -> None:
+ """Initialize the handler.
+
+ Parameters:
+ config: The handler configuration.
+ base_dir: The base directory of the project.
+ **kwargs: Arguments passed to the parent constructor.
+ """
+ super().__init__(**kwargs)
+
+ self.config = config
+ """The handler configuration."""
+ self.base_dir = base_dir
+ """The base directory of the project."""
+
+ # YORE: Bump 2: Remove block.
+ 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
+ """The global configuration options (in `mkdocs.yml`)."""
+
+ # YORE: Bump 2: Replace `# ` with `` within block.
+ # self.global_options = config.options
+ # """The global configuration options (in `mkdocs.yml`)."""
+
+ # Warn if user overrides base templates.
+ 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/.html.jinja' is not supported, "
+ f"override '{theme_dir.name}/.html.jinja' instead",
+ )
+
+ paths = config.paths or []
+
+ # Expand paths with glob patterns.
+ with chdir(str(base_dir)):
+ resolved_globs = [glob.glob(path) for path in paths]
+ paths = [path for glob_list in resolved_globs for path in glob_list]
+
+ # By default, add the base directory to the search paths.
+ if not paths:
+ paths.append(str(base_dir))
+
+ # Initialize search paths from `sys.path`, eliminating empty paths.
+ search_paths = [path for path in sys.path if path]
+
+ for path in reversed(paths):
+ # If it's not absolute, make path relative to the config file path, then make it absolute.
+ if not os.path.isabs(path):
+ path = os.path.abspath(base_dir / path) # noqa: PLW2901
+ # Remove pre-listed paths.
+ if path in search_paths:
+ search_paths.remove(path)
+ # Give precedence to user-provided paths.
+ search_paths.insert(0, path)
+
+ self._paths = search_paths
+ self._modules_collection: ModulesCollection = ModulesCollection()
+ self._lines_collection: LinesCollection = LinesCollection()
+
+ def get_inventory_urls(self) -> list[tuple[str, dict[str, Any]]]:
+ """Return the URLs of the inventory files to download."""
+ return [(inv.url, inv._config) for inv in self.config.inventories]
+
+ @staticmethod
+ def load_inventory(
+ in_file: BinaryIO,
+ url: str,
+ base_url: str | None = None,
+ domains: list[str] | None = None,
+ **kwargs: Any, # noqa: ARG004
+ ) -> Iterator[tuple[str, str]]:
+ """Yield items and their URLs from an inventory file streamed from `in_file`.
+
+ This implements mkdocstrings' `load_inventory` "protocol" (see [`mkdocstrings.plugin`][]).
+
+ Arguments:
+ in_file: The binary file-like object to read the inventory from.
+ url: The URL that this file is being streamed from (used to guess `base_url`).
+ base_url: The URL that this inventory's sub-paths are relative to.
+ domains: A list of domain strings to filter the inventory by, when not passed, "py" will be used.
+ **kwargs: Ignore additional arguments passed from the config.
+
+ Yields:
+ Tuples of (item identifier, item URL).
+ """
+ domains = domains or ["py"]
+ if base_url is None:
+ base_url = posixpath.dirname(url)
+
+ for item in Inventory.parse_sphinx(in_file, domain_filter=domains).values():
+ yield item.name, posixpath.join(base_url, item.uri)
+
+ def get_options(self, local_options: Mapping[str, Any]) -> HandlerOptions:
+ """Get combined default, global and local options.
+
+ Arguments:
+ local_options: The local options.
+
+ Returns:
+ The combined options.
+ """
+ # YORE: Bump 2: Remove block.
+ local_extra, local_options = PythonOptions._extract_extra(local_options) # type: ignore[arg-type]
+ if local_extra:
+ _warn_extra_options(local_extra.keys()) # type: ignore[arg-type]
+ unknown_extra = self._global_extra | local_extra
+
+ extra = {**self.global_options.get("extra", {}), **local_options.get("extra", {})}
+ options = {**self.global_options, **local_options, "extra": extra}
+ try:
+ # YORE: Bump 2: Replace `opts =` with `return` within line.
+ opts = PythonOptions.from_data(**options)
+ except Exception as error:
+ raise PluginError(f"Invalid options: {error}") from error
+
+ # YORE: Bump 2: Remove block.
+ for key, value in unknown_extra.items():
+ object.__setattr__(opts, key, value)
+ return opts
+
+ def collect(self, identifier: str, options: PythonOptions) -> CollectorItem:
+ """Collect the documentation for the given identifier.
+
+ Parameters:
+ identifier: The identifier of the object to collect.
+ options: The options to use for the collection.
+
+ Returns:
+ The collected item.
+ """
+ module_name = identifier.split(".", 1)[0]
+ unknown_module = module_name not in self._modules_collection
+ reapply = True
+ if options == {}:
+ if unknown_module:
+ raise CollectionError("Not loading additional modules during fallback")
+ options = self.get_options({})
+ reapply = False
+
+ parser_name = options.docstring_style
+ parser = parser_name and Parser(parser_name)
+ parser_options = options.docstring_options and asdict(options.docstring_options)
+
+ if unknown_module:
+ extensions = self.normalize_extension_paths(options.extensions)
+ loader = GriffeLoader(
+ extensions=load_extensions(*extensions),
+ search_paths=self._paths,
+ docstring_parser=parser,
+ docstring_options=parser_options, # type: ignore[arg-type]
+ modules_collection=self._modules_collection,
+ lines_collection=self._lines_collection,
+ allow_inspection=options.allow_inspection,
+ force_inspection=options.force_inspection,
+ )
+ try:
+ for pre_loaded_module in options.preload_modules:
+ if pre_loaded_module not in self._modules_collection:
+ loader.load(
+ pre_loaded_module,
+ try_relative_path=False,
+ find_stubs_package=options.find_stubs_package,
+ )
+ loader.load(
+ module_name,
+ try_relative_path=False,
+ find_stubs_package=options.find_stubs_package,
+ )
+ except ImportError as error:
+ raise CollectionError(str(error)) from error
+ unresolved, iterations = loader.resolve_aliases(
+ implicit=False,
+ external=self.config.load_external_modules,
+ )
+ if unresolved:
+ _logger.debug(f"{len(unresolved)} aliases were still unresolved after {iterations} iterations")
+ _logger.debug(f"Unresolved aliases: {', '.join(sorted(unresolved))}")
+
+ try:
+ doc_object = self._modules_collection[identifier]
+ except KeyError as error:
+ raise CollectionError(f"{identifier} could not be found") from error
+ except AliasResolutionError as error:
+ raise CollectionError(str(error)) from error
+
+ if not unknown_module and reapply:
+ with suppress(AliasResolutionError):
+ if doc_object.docstring is not None:
+ doc_object.docstring.parser = parser
+ doc_object.docstring.parser_options = parser_options or {}
+
+ return doc_object
+
+ def render(self, data: CollectorItem, options: PythonOptions) -> str:
+ """Render the collected data.
+
+ Parameters:
+ data: The collected data.
+ options: The options to use for rendering.
+
+ Returns:
+ The rendered data (HTML).
+ """
+ template_name = rendering.do_get_template(self.env, data)
+ template = self.env.get_template(template_name)
+
+ return template.render(
+ **{
+ "config": options,
+ data.kind.value: data,
+ # Heading level is a "state" variable, that will change at each step
+ # of the rendering recursion. Therefore, it's easier to use it as a plain value
+ # than as an item in a dictionary.
+ "heading_level": options.heading_level,
+ "root": True,
+ "locale": self.config.locale,
+ },
+ )
+
+ def update_env(self, config: Any) -> None: # noqa: ARG002
+ """Update the Jinja environment with custom filters and tests.
+
+ Parameters:
+ config: The SSG configuration.
+ """
+ self.env.trim_blocks = True
+ self.env.lstrip_blocks = True
+ self.env.keep_trailing_newline = False
+ self.env.filters["split_path"] = rendering.do_split_path
+ self.env.filters["crossref"] = rendering.do_crossref
+ self.env.filters["multi_crossref"] = rendering.do_multi_crossref
+ self.env.filters["order_members"] = rendering.do_order_members
+ self.env.filters["format_code"] = rendering.do_format_code
+ self.env.filters["format_signature"] = rendering.do_format_signature
+ self.env.filters["format_attribute"] = rendering.do_format_attribute
+ self.env.filters["filter_objects"] = rendering.do_filter_objects
+ self.env.filters["stash_crossref"] = rendering.do_stash_crossref
+ self.env.filters["get_template"] = rendering.do_get_template
+ self.env.filters["as_attributes_section"] = rendering.do_as_attributes_section
+ self.env.filters["as_functions_section"] = rendering.do_as_functions_section
+ self.env.filters["as_classes_section"] = rendering.do_as_classes_section
+ self.env.filters["as_modules_section"] = rendering.do_as_modules_section
+ self.env.filters["backlink_tree"] = rendering.do_backlink_tree
+ self.env.globals["AutorefsHook"] = rendering.AutorefsHook
+ self.env.tests["existing_template"] = lambda template_name: template_name in self.env.list_templates()
+
+ def get_aliases(self, identifier: str) -> tuple[str, ...]:
+ """Get the aliases for the given identifier.
+
+ Parameters:
+ identifier: The identifier to get the aliases for.
+
+ Returns:
+ The aliases.
+ """
+ if "(" in identifier:
+ identifier, parameter = identifier.split("(", 1)
+ parameter.removesuffix(")")
+ else:
+ parameter = ""
+ try:
+ data = self._modules_collection[identifier]
+ except (KeyError, AliasResolutionError):
+ return ()
+ aliases = [data.path]
+ try:
+ for alias in [data.canonical_path, *data.aliases]:
+ if alias not in aliases:
+ aliases.append(alias)
+ except AliasResolutionError:
+ pass
+ if parameter:
+ return tuple(f"{alias}({parameter})" for alias in aliases)
+ return tuple(aliases)
+
+ def normalize_extension_paths(self, extensions: Sequence) -> list[str | dict[str, Any]]:
+ """Resolve extension paths relative to config file.
+
+ Parameters:
+ extensions: The extensions (configuration) to normalize.
+
+ Returns:
+ The normalized extensions.
+ """
+ normalized: list[str | dict[str, Any]] = []
+
+ for ext in extensions:
+ if isinstance(ext, dict):
+ pth, options = next(iter(ext.items()))
+ pth = str(pth)
+ else:
+ pth = str(ext)
+ options = None
+
+ if pth.endswith(".py") or ".py:" in pth or "/" in pth or "\\" in pth:
+ # This is a system path. Normalize it, make it absolute relative to config file path.
+ pth = os.path.abspath(self.base_dir / pth)
+
+ if options is not None:
+ normalized.append({pth: options})
+ else:
+ normalized.append(pth)
+
+ return normalized
+
+
+def get_handler(
+ handler_config: MutableMapping[str, Any],
+ tool_config: MkDocsConfig,
+ **kwargs: Any,
+) -> PythonHandler:
+ """Return an instance of `PythonHandler`.
+
+ Parameters:
+ handler_config: The handler configuration.
+ tool_config: The tool (SSG) configuration.
+
+ Returns:
+ An instance of `PythonHandler`.
+ """
+ base_dir = Path(tool_config.config_file_path or "./mkdocs.yml").parent
+ if "inventories" not in handler_config and "import" in handler_config:
+ warn("The 'import' key is renamed 'inventories' for the Python handler", FutureWarning, stacklevel=1)
+ handler_config["inventories"] = handler_config.pop("import", [])
+ return PythonHandler(
+ config=PythonConfig.from_data(**handler_config),
+ base_dir=base_dir,
+ **kwargs,
+ )
diff --git a/src/mkdocstrings_handlers/python/_internal/rendering.py b/src/mkdocstrings_handlers/python/_internal/rendering.py
new file mode 100644
index 00000000..897b6572
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/rendering.py
@@ -0,0 +1,834 @@
+# This module implements rendering utilities.
+
+from __future__ import annotations
+
+import random
+import re
+import string
+import subprocess
+import sys
+import warnings
+from collections import defaultdict
+from contextlib import suppress
+from dataclasses import replace
+from functools import lru_cache
+from pathlib import Path
+from re import Match, Pattern
+from typing import TYPE_CHECKING, Any, Callable, ClassVar, Literal, TypeVar
+
+from griffe import (
+ Alias,
+ AliasResolutionError,
+ CyclicAliasError,
+ DocstringAttribute,
+ DocstringClass,
+ DocstringFunction,
+ DocstringModule,
+ DocstringSectionAttributes,
+ DocstringSectionClasses,
+ DocstringSectionFunctions,
+ DocstringSectionModules,
+ Object,
+)
+from jinja2 import TemplateNotFound, pass_context, pass_environment
+from markupsafe import Markup
+from mkdocs_autorefs import AutorefsHookInterface, Backlink, BacklinkCrumb
+from mkdocstrings import get_logger
+
+if TYPE_CHECKING:
+ from collections.abc import Iterable, Iterator, Sequence
+
+ from griffe import Attribute, Class, Function, Module
+ from jinja2 import Environment
+ from jinja2.runtime import Context
+ from mkdocstrings import CollectorItem
+
+_logger = get_logger(__name__)
+
+
+def _sort_key_alphabetical(item: CollectorItem) -> str:
+ # `chr(sys.maxunicode)` is a string that contains the final unicode character,
+ # so if `name` isn't found on the object, the item will go to the end of the list.
+ return item.name or chr(sys.maxunicode)
+
+
+def _sort_key_source(item: CollectorItem) -> float:
+ # If `lineno` is none, the item will go to the end of the list.
+ if item.is_alias:
+ return item.alias_lineno if item.alias_lineno is not None else float("inf")
+ return item.lineno if item.lineno is not None else float("inf")
+
+
+def _sort__all__(item: CollectorItem) -> float: # noqa: ARG001
+ raise ValueError("Not implemented in public version of mkdocstrings-python")
+
+
+Order = Literal["__all__", "alphabetical", "source"]
+"""Ordering methods.
+
+- `__all__`: order members according to `__all__` module attributes, if declared;
+- `alphabetical`: order members alphabetically;
+- `source`: order members as they appear in the source file.
+"""
+
+_order_map: dict[str, Callable[[Object | Alias], str | float]] = {
+ "alphabetical": _sort_key_alphabetical,
+ "source": _sort_key_source,
+ "__all__": _sort__all__,
+}
+
+
+def do_format_code(code: str, line_length: int) -> str:
+ """Format code.
+
+ Parameters:
+ code: The code to format.
+ line_length: The line length.
+
+ Returns:
+ The same code, formatted.
+ """
+ code = code.strip()
+ if len(code) < line_length:
+ return code
+ formatter = _get_formatter()
+ return formatter(code, line_length)
+
+
+class _StashCrossRefFilter:
+ stash: ClassVar[dict[str, str]] = {}
+
+ @staticmethod
+ def _gen_key(length: int) -> str:
+ return "_" + "".join(random.choice(string.ascii_letters + string.digits) for _ in range(max(1, length - 1))) # noqa: S311
+
+ def _gen_stash_key(self, length: int) -> str:
+ key = self._gen_key(length)
+ while key in self.stash:
+ key = self._gen_key(length)
+ return key
+
+ def __call__(self, crossref: str, *, length: int) -> str:
+ key = self._gen_stash_key(length)
+ self.stash[key] = crossref
+ return key
+
+
+do_stash_crossref = _StashCrossRefFilter()
+"""Filter to stash cross-references (and restore them after formatting and highlighting)."""
+
+
+def _format_signature(name: Markup, signature: str, line_length: int) -> str:
+ name = str(name).strip() # type: ignore[assignment]
+ signature = signature.strip()
+ if len(name + signature) < line_length:
+ return name + signature
+
+ # Black cannot format names with dots, so we replace
+ # the whole name with a string of equal length
+ name_length = len(name)
+ formatter = _get_formatter()
+ formatable = f"def {'x' * name_length}{signature}: pass"
+ formatted = formatter(formatable, line_length)
+
+ # We put back the original name
+ # and remove starting `def ` and trailing `: pass`
+ return name + formatted[4:-5].strip()[name_length:-1]
+
+
+@pass_context
+def do_format_signature(
+ context: Context,
+ callable_path: Markup,
+ function: Function,
+ line_length: int,
+ *,
+ annotations: bool | None = None,
+ crossrefs: bool = False, # noqa: ARG001
+) -> str:
+ """Format a signature.
+
+ Parameters:
+ context: Jinja context, passed automatically.
+ callable_path: The path of the callable we render the signature of.
+ function: The function we render the signature of.
+ line_length: The line length.
+ annotations: Whether to show type annotations.
+ crossrefs: Whether to cross-reference types in the signature.
+
+ Returns:
+ The same code, formatted.
+ """
+ env = context.environment
+ # YORE: Bump 2: Replace `do_get_template(env, "signature")` with `"signature.html.jinja"` within line.
+ template = env.get_template(do_get_template(env, "signature"))
+
+ if annotations is None:
+ new_context = context.parent
+ else:
+ new_context = dict(context.parent)
+ new_context["config"] = replace(new_context["config"], show_signature_annotations=annotations)
+
+ signature = template.render(new_context, function=function, signature=True)
+ signature = _format_signature(callable_path, signature, line_length)
+ signature = str(
+ env.filters["highlight"](
+ Markup.escape(signature),
+ language="python",
+ inline=False,
+ classes=["doc-signature"],
+ linenums=False,
+ ),
+ )
+
+ # Since we highlight the signature without `def`,
+ # Pygments sees it as a function call and not a function definition.
+ # The result is that the function name is not parsed as such,
+ # but instead as a regular name: `n` CSS class instead of `nf`.
+ # When the function name is a known special name like `__exit__`,
+ # Pygments will set an `fm` (function -> magic) CSS class.
+ # To fix this, we replace the CSS class in the first span with `nf`,
+ # unless we already found an `nf` span.
+ if not re.search(r'', signature):
+ signature = re.sub(r'', '', signature, count=1)
+
+ if stash := env.filters["stash_crossref"].stash:
+ for key, value in stash.items():
+ signature = re.sub(rf"\b{key}\b", value, signature)
+ stash.clear()
+
+ return signature
+
+
+@pass_context
+def do_format_attribute(
+ context: Context,
+ attribute_path: Markup,
+ attribute: Attribute,
+ line_length: int,
+ *,
+ crossrefs: bool = False, # noqa: ARG001
+) -> str:
+ """Format an attribute.
+
+ Parameters:
+ context: Jinja context, passed automatically.
+ attribute_path: The path of the callable we render the signature of.
+ attribute: The attribute we render the signature of.
+ line_length: The line length.
+ crossrefs: Whether to cross-reference types in the signature.
+
+ Returns:
+ The same code, formatted.
+ """
+ env = context.environment
+ # YORE: Bump 2: Replace `do_get_template(env, "expression")` with `"expression.html.jinja"` within line.
+ template = env.get_template(do_get_template(env, "expression"))
+ annotations = context.parent["config"].show_signature_annotations
+
+ signature = str(attribute_path).strip()
+ if annotations and attribute.annotation:
+ annotation = template.render(
+ context.parent,
+ expression=attribute.annotation,
+ signature=True,
+ backlink_type="returned-by",
+ )
+ signature += f": {annotation}"
+ if attribute.value:
+ value = template.render(context.parent, expression=attribute.value, signature=True, backlink_type="used-by")
+ signature += f" = {value}"
+
+ signature = do_format_code(signature, line_length)
+ signature = str(
+ env.filters["highlight"](
+ Markup.escape(signature),
+ language="python",
+ inline=False,
+ classes=["doc-signature"],
+ linenums=False,
+ ),
+ )
+
+ if stash := env.filters["stash_crossref"].stash:
+ for key, value in stash.items():
+ signature = re.sub(rf"\b{key}\b", value, signature)
+ stash.clear()
+
+ return signature
+
+
+def do_order_members(
+ members: Sequence[Object | Alias],
+ order: Order | list[Order],
+ members_list: bool | list[str] | None,
+) -> Sequence[Object | Alias]:
+ """Order members given an ordering method.
+
+ Parameters:
+ members: The members to order.
+ order: The ordering method.
+ members_list: An optional member list (manual ordering).
+
+ Returns:
+ The same members, ordered.
+ """
+ if isinstance(members_list, list) and members_list:
+ sorted_members = []
+ members_dict = {member.name: member for member in members}
+ for name in members_list:
+ if name in members_dict:
+ sorted_members.append(members_dict[name])
+ return sorted_members
+ if isinstance(order, str):
+ order = [order]
+ for method in order:
+ with suppress(ValueError):
+ return sorted(members, key=_order_map[method])
+ return members
+
+
+# YORE: Bump 2: Remove block.
+@lru_cache
+def _warn_crossref() -> None:
+ warnings.warn(
+ "The `crossref` filter is deprecated and will be removed in a future version",
+ DeprecationWarning,
+ stacklevel=1,
+ )
+
+
+# YORE: Bump 2: Remove block.
+def do_crossref(path: str, *, brief: bool = True) -> Markup:
+ """Deprecated. Filter to create cross-references.
+
+ Parameters:
+ path: The path to link to.
+ brief: Show only the last part of the path, add full path as hover.
+
+ Returns:
+ Markup text.
+ """
+ _warn_crossref()
+ full_path = path
+ if brief:
+ path = full_path.split(".")[-1]
+ return Markup("{path} ").format(
+ full_path=full_path,
+ path=path,
+ )
+
+
+# YORE: Bump 2: Remove block.
+@lru_cache
+def _warn_multi_crossref() -> None:
+ warnings.warn(
+ "The `multi_crossref` filter is deprecated and will be removed in a future version",
+ DeprecationWarning,
+ stacklevel=1,
+ )
+
+
+# YORE: Bump 2: Remove block.
+def do_multi_crossref(text: str, *, code: bool = True) -> Markup:
+ """Deprecated. Filter to create cross-references.
+
+ Parameters:
+ text: The text to scan.
+ code: Whether to wrap the result in a code tag.
+
+ Returns:
+ Markup text.
+ """
+ _warn_multi_crossref()
+ group_number = 0
+ variables = {}
+
+ def repl(match: Match) -> str:
+ nonlocal group_number
+ group_number += 1
+ path = match.group()
+ path_var = f"path{group_number}"
+ variables[path_var] = path
+ return f"{{{path_var}}} "
+
+ text = re.sub(r"([\w.]+)", repl, text)
+ if code:
+ text = f"{text}
"
+ return Markup(text).format(**variables) # noqa: S704
+
+
+_split_path_re = re.compile(r"([.(]?)([\w]+)(\))?")
+_splitable_re = re.compile(r"[().]")
+
+
+def do_split_path(path: str, full_path: str) -> Iterator[tuple[str, str, str, str]]:
+ """Split object paths for building cross-references.
+
+ Parameters:
+ path: The path to split.
+ full_path: The full path, used to compute correct paths for each part of the path.
+
+ Yields:
+ 4-tuples: prefix, word, full path, suffix.
+ """
+ # Path is a single word, yield full path directly.
+ if not _splitable_re.search(path):
+ yield ("", path, full_path, "")
+ return
+
+ current_path = ""
+ if path == full_path:
+ # Split full path and yield directly without storing data in a dict.
+ for match in _split_path_re.finditer(full_path):
+ prefix, word, suffix = match.groups()
+ current_path = f"{current_path}{prefix}{word}{suffix or ''}" if current_path else word
+ yield prefix or "", word, current_path, suffix or ""
+ return
+
+ # Split full path first to store tuples in a dict.
+ elements = {}
+ for match in _split_path_re.finditer(full_path):
+ prefix, word, suffix = match.groups()
+ current_path = f"{current_path}{prefix}{word}{suffix or ''}" if current_path else word
+ elements[word] = (prefix or "", word, current_path, suffix or "")
+
+ # Then split path and pick tuples from the dict.
+ first = True
+ for match in _split_path_re.finditer(path):
+ prefix, word, current_path, suffix = elements[match.group(2)]
+ yield "" if first else prefix, word, current_path, suffix
+ first = False
+
+
+def _keep_object(name: str, filters: Sequence[tuple[Pattern, bool]]) -> bool:
+ keep = None
+ rules = set()
+ for regex, exclude in filters:
+ rules.add(exclude)
+ if regex.search(name):
+ keep = not exclude
+ if keep is None:
+ # When we only include stuff, no match = reject.
+ # When we only exclude stuff, or include and exclude stuff, no match = keep.
+ return rules != {False}
+ return keep
+
+
+def _parents(obj: Alias) -> set[str]:
+ parent: Object | Alias = obj.parent # type: ignore[assignment]
+ parents = {obj.path, parent.path}
+ if parent.is_alias:
+ parents.add(parent.final_target.path) # type: ignore[union-attr]
+ while parent.parent:
+ parent = parent.parent
+ parents.add(parent.path)
+ if parent.is_alias:
+ parents.add(parent.final_target.path) # type: ignore[union-attr]
+ return parents
+
+
+def _remove_cycles(objects: list[Object | Alias]) -> Iterator[Object | Alias]:
+ suppress_errors = suppress(AliasResolutionError, CyclicAliasError)
+ for obj in objects:
+ if obj.is_alias:
+ with suppress_errors:
+ if obj.final_target.path in _parents(obj): # type: ignore[arg-type,union-attr]
+ continue
+ yield obj
+
+
+def do_filter_objects(
+ objects_dictionary: dict[str, Object | Alias],
+ *,
+ filters: Sequence[tuple[Pattern, bool]] | Literal["public"] | None = None,
+ members_list: bool | list[str] | None = None,
+ inherited_members: bool | list[str] = False,
+ keep_no_docstrings: bool = True,
+) -> list[Object | Alias]:
+ """Filter a dictionary of objects based on their docstrings.
+
+ Parameters:
+ objects_dictionary: The dictionary of objects.
+ filters: Filters to apply, based on members' names, or `"public"`.
+ Each element is a tuple: a pattern, and a boolean indicating whether
+ to reject the object if the pattern matches.
+ members_list: An optional, explicit list of members to keep.
+ When given and empty, return an empty list.
+ When given and not empty, ignore filters and docstrings presence/absence.
+ inherited_members: Whether to keep inherited members or exclude them.
+ keep_no_docstrings: Whether to keep objects with no/empty docstrings (recursive check).
+
+ Returns:
+ A list of objects.
+ """
+ inherited_members_specified = False
+ if inherited_members is True:
+ # Include all inherited members.
+ objects = list(objects_dictionary.values())
+ elif inherited_members is False:
+ # Include no inherited members.
+ objects = [obj for obj in objects_dictionary.values() if not obj.inherited]
+ else:
+ # Include specific inherited members.
+ inherited_members_specified = True
+ objects = [
+ obj for obj in objects_dictionary.values() if not obj.inherited or obj.name in set(inherited_members)
+ ]
+
+ if members_list is True:
+ # Return all pre-selected members.
+ return objects
+
+ if members_list is False or members_list == []:
+ # Return selected inherited members, if any.
+ return [obj for obj in objects if obj.inherited]
+
+ if members_list is not None:
+ # Return selected members (keeping any pre-selected inherited members).
+ return [
+ obj for obj in objects if obj.name in set(members_list) or (inherited_members_specified and obj.inherited)
+ ]
+
+ # Use filters and docstrings.
+ if filters == "public":
+ objects = [obj for obj in objects if obj.is_public]
+ elif filters:
+ objects = [
+ obj for obj in objects if _keep_object(obj.name, filters) or (inherited_members_specified and obj.inherited)
+ ]
+ if not keep_no_docstrings:
+ objects = [obj for obj in objects if obj.has_docstrings or (inherited_members_specified and obj.inherited)]
+
+ # Prevent infinite recursion.
+ if objects:
+ objects = list(_remove_cycles(objects))
+
+ return objects
+
+
+@lru_cache(maxsize=1)
+def _get_formatter() -> Callable[[str, int], str]:
+ for formatter_function in [
+ _get_black_formatter,
+ _get_ruff_formatter,
+ ]:
+ if (formatter := formatter_function()) is not None:
+ return formatter
+
+ _logger.info("Formatting signatures requires either Black or Ruff to be installed.")
+ return lambda text, _: text
+
+
+def _get_ruff_formatter() -> Callable[[str, int], str] | None:
+ try:
+ from ruff.__main__ import find_ruff_bin
+ except ImportError:
+ return None
+
+ try:
+ ruff_bin = find_ruff_bin()
+ except FileNotFoundError:
+ ruff_bin = "ruff"
+
+ def formatter(code: str, line_length: int) -> str:
+ try:
+ completed_process = subprocess.run( # noqa: S603
+ [
+ ruff_bin,
+ "format",
+ "--config",
+ f"line-length={line_length}",
+ "--stdin-filename",
+ "file.py",
+ "-",
+ ],
+ check=True,
+ capture_output=True,
+ text=True,
+ input=code,
+ )
+ except subprocess.CalledProcessError:
+ return code
+ else:
+ return completed_process.stdout
+
+ return formatter
+
+
+def _get_black_formatter() -> Callable[[str, int], str] | None:
+ try:
+ from black import InvalidInput, Mode, format_str
+ except ModuleNotFoundError:
+ return None
+
+ def formatter(code: str, line_length: int) -> str:
+ mode = Mode(line_length=line_length)
+ try:
+ return format_str(code, mode=mode)
+ except InvalidInput:
+ return code
+
+ return formatter
+
+
+# YORE: Bump 2: Remove line.
+@pass_environment
+# YORE: Bump 2: Replace `env: Environment, ` with `` within line.
+# YORE: Bump 2: Replace `str | ` with `` within line.
+def do_get_template(env: Environment, obj: str | Object) -> str:
+ """Get the template name used to render an object.
+
+ Parameters:
+ env: The Jinja environment, passed automatically.
+ obj: A Griffe object, or a template name.
+
+ Returns:
+ A template name.
+ """
+ name = obj
+ if isinstance(obj, (Alias, Object)):
+ extra_data = getattr(obj, "extra", {}).get("mkdocstrings", {})
+ if name := extra_data.get("template", ""):
+ return name
+ name = obj.kind.value
+ # YORE: Bump 2: Replace block with `return f"{name}.html.jinja"`.
+ try:
+ template = env.get_template(f"{name}.html")
+ except TemplateNotFound:
+ return f"{name}.html.jinja"
+ our_template = Path(template.filename).is_relative_to(Path(__file__).parent.parent) # type: ignore[arg-type]
+ if our_template:
+ return f"{name}.html.jinja"
+ _logger.warning(
+ f"DeprecationWarning: Overriding '{name}.html' is deprecated, override '{name}.html.jinja' instead. ",
+ once=True,
+ )
+ return f"{name}.html"
+
+
+@pass_context
+def do_as_attributes_section(
+ context: Context, # noqa: ARG001
+ attributes: Sequence[Attribute],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionAttributes:
+ """Build an attributes section from a list of attributes.
+
+ Parameters:
+ attributes: The attributes to build the section from.
+ check_public: Whether to check if the attribute is public.
+
+ Returns:
+ An attributes docstring section.
+ """
+
+ def _parse_docstring_summary(attribute: Attribute) -> str:
+ if attribute.docstring is None:
+ return ""
+ line = attribute.docstring.value.split("\n", 1)[0]
+ if ":" in line and attribute.docstring.parser_options.get("returns_type_in_property_summary", False):
+ _, line = line.split(":", 1)
+ return line
+
+ return DocstringSectionAttributes(
+ [
+ DocstringAttribute(
+ name=attribute.name,
+ description=_parse_docstring_summary(attribute),
+ annotation=attribute.annotation,
+ value=attribute.value, # type: ignore[arg-type]
+ )
+ for attribute in attributes
+ if not check_public or attribute.is_public
+ ],
+ )
+
+
+@pass_context
+def do_as_functions_section(
+ context: Context,
+ functions: Sequence[Function],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionFunctions:
+ """Build a functions section from a list of functions.
+
+ Parameters:
+ functions: The functions to build the section from.
+ check_public: Whether to check if the function is public.
+
+ Returns:
+ A functions docstring section.
+ """
+ keep_init_method = not context.parent["config"].merge_init_into_class
+ return DocstringSectionFunctions(
+ [
+ DocstringFunction(
+ name=function.name,
+ description=function.docstring.value.split("\n", 1)[0] if function.docstring else "",
+ )
+ for function in functions
+ if (not check_public or function.is_public) and (function.name != "__init__" or keep_init_method)
+ ],
+ )
+
+
+@pass_context
+def do_as_classes_section(
+ context: Context, # noqa: ARG001
+ classes: Sequence[Class],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionClasses:
+ """Build a classes section from a list of classes.
+
+ Parameters:
+ classes: The classes to build the section from.
+ check_public: Whether to check if the class is public.
+
+ Returns:
+ A classes docstring section.
+ """
+ return DocstringSectionClasses(
+ [
+ DocstringClass(
+ name=cls.name,
+ description=cls.docstring.value.split("\n", 1)[0] if cls.docstring else "",
+ )
+ for cls in classes
+ if not check_public or cls.is_public
+ ],
+ )
+
+
+@pass_context
+def do_as_modules_section(
+ context: Context, # noqa: ARG001
+ modules: Sequence[Module],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionModules:
+ """Build a modules section from a list of modules.
+
+ Parameters:
+ modules: The modules to build the section from.
+ check_public: Whether to check if the module is public.
+
+ Returns:
+ A modules docstring section.
+ """
+ return DocstringSectionModules(
+ [
+ DocstringModule(
+ name=module.name,
+ description=module.docstring.value.split("\n", 1)[0] if module.docstring else "",
+ )
+ for module in modules
+ if not check_public or module.is_public
+ ],
+ )
+
+
+class AutorefsHook(AutorefsHookInterface):
+ """Autorefs hook.
+
+ With this hook, we're able to add context to autorefs (cross-references),
+ such as originating file path and line number, to improve error reporting.
+ """
+
+ def __init__(self, current_object: Object | Alias, config: dict[str, Any]) -> None:
+ """Initialize the hook.
+
+ Parameters:
+ current_object: The object being rendered.
+ config: The configuration dictionary.
+ """
+ self.current_object = current_object
+ """The current object being rendered."""
+ self.config = config
+ """The configuration options."""
+
+ def expand_identifier(self, identifier: str) -> str:
+ """Expand an identifier.
+
+ Parameters:
+ identifier: The identifier to expand.
+
+ Returns:
+ The expanded identifier.
+ """
+ return identifier
+
+ def get_context(self) -> AutorefsHookInterface.Context:
+ """Get the context for the current object.
+
+ Returns:
+ The context.
+ """
+ role = {
+ "attribute": "data" if self.current_object.parent and self.current_object.parent.is_module else "attr",
+ "class": "class",
+ "function": "meth" if self.current_object.parent and self.current_object.parent.is_class else "func",
+ "module": "mod",
+ }.get(self.current_object.kind.value.lower(), "obj")
+ origin = self.current_object.path
+ try:
+ filepath = self.current_object.docstring.parent.filepath # type: ignore[union-attr]
+ lineno = self.current_object.docstring.lineno or 0 # type: ignore[union-attr]
+ except AttributeError:
+ filepath = self.current_object.filepath
+ lineno = 0
+
+ return AutorefsHookInterface.Context(
+ domain="py",
+ role=role,
+ origin=origin,
+ filepath=str(filepath),
+ lineno=lineno,
+ )
+
+
+_T = TypeVar("_T")
+_Tree = dict[_T, "_Tree"]
+_rtree = lambda: defaultdict(_rtree) # type: ignore[has-type,var-annotated] # noqa: E731
+
+Tree = dict[tuple[_T, ...], "Tree"]
+"""A tree type. Each node holds a tuple of items."""
+
+
+def _tree(data: Iterable[tuple[_T, ...]]) -> _Tree:
+ new_tree = _rtree()
+ for nav in data:
+ *path, leaf = nav
+ node = new_tree
+ for key in path:
+ node = node[key]
+ node[leaf] = _rtree()
+ return new_tree
+
+
+def _compact_tree(tree: _Tree) -> Tree:
+ new_tree = _rtree()
+ for key, value in tree.items():
+ child = _compact_tree(value)
+ if len(child) == 1:
+ child_key, child_value = next(iter(child.items()))
+ new_key = (key, *child_key)
+ new_tree[new_key] = child_value
+ else:
+ new_tree[(key,)] = child
+ return new_tree
+
+
+def do_backlink_tree(backlinks: list[Backlink]) -> Tree[BacklinkCrumb]:
+ """Build a tree of backlinks.
+
+ Parameters:
+ backlinks: The list of backlinks.
+
+ Returns:
+ A tree of backlinks.
+ """
+ return _compact_tree(_tree(backlink.crumbs for backlink in backlinks))
diff --git a/src/mkdocstrings_handlers/python/config.py b/src/mkdocstrings_handlers/python/config.py
new file mode 100644
index 00000000..5edab089
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/config.py
@@ -0,0 +1,17 @@
+"""Deprecated. Import from `mkdocstrings_handlers.python` directly."""
+
+# YORE: Bump 2: Remove file.
+
+import warnings
+from typing import Any
+
+from mkdocstrings_handlers.python._internal import config
+
+
+def __getattr__(name: str) -> Any:
+ warnings.warn(
+ "Importing from `mkdocstrings_handlers.python.config` is deprecated. Import from `mkdocstrings_handlers.python` directly.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return getattr(config, name)
diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py
index eb1d73c7..5b334860 100644
--- a/src/mkdocstrings_handlers/python/handler.py
+++ b/src/mkdocstrings_handlers/python/handler.py
@@ -1,506 +1,17 @@
-"""This module implements a handler for the Python language."""
+"""Deprecated. Import from `mkdocstrings_handlers.python` directly."""
-from __future__ import annotations
+# YORE: Bump 2: Remove file.
-import glob
-import os
-import posixpath
-import re
-import sys
-from collections import ChainMap
-from contextlib import suppress
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, BinaryIO, ClassVar, Iterator, Mapping, Sequence
+import warnings
+from typing import Any
-from griffe import (
- AliasResolutionError,
- GriffeLoader,
- LinesCollection,
- ModulesCollection,
- Parser,
- load_extensions,
- patch_loggers,
-)
-from mkdocstrings.extension import PluginError
-from mkdocstrings.handlers.base import BaseHandler, CollectionError, CollectorItem
-from mkdocstrings.inventory import Inventory
-from mkdocstrings.loggers import get_logger
+from mkdocstrings_handlers.python._internal import handler
-from mkdocstrings_handlers.python import rendering
-if TYPE_CHECKING:
- from markdown import Markdown
-
-
-if sys.version_info >= (3, 11):
- from contextlib import chdir
-else:
- # TODO: remove once support for Python 3.10 is dropped
- from contextlib import contextmanager
-
- @contextmanager
- def chdir(path: str) -> Iterator[None]: # noqa: D103
- old_wd = os.getcwd()
- os.chdir(path)
- try:
- yield
- finally:
- os.chdir(old_wd)
-
-
-logger = get_logger(__name__)
-
-patch_loggers(get_logger)
-
-
-class PythonHandler(BaseHandler):
- """The Python handler class."""
-
- name: str = "python"
- """The handler's name."""
- domain: str = "py" # to match Sphinx's default domain
- """The cross-documentation domain/language for this handler."""
- enable_inventory: bool = True
- """Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file."""
- fallback_theme = "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,
- "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_submodules": False,
- "group_by_category": True,
- "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,
- "summary": False,
- "show_labels": True,
- "unwrap_annotated": 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`.
- show_bases (bool): Show the base classes of a class. Default: `True`.
- 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_level (int): The initial heading level to use. Default: `2`.
- 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`.
- 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 Black 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`.
- """
-
- 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:
- """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.
- """
- super().__init__(*args, **kwargs)
-
- # 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 theme_dir.joinpath("_base").is_dir():
- logger.warning(
- f"Overriding base template '{theme_dir.name}/_base/.html.jinja' is not supported, "
- f"override '{theme_dir.name}/.html.jinja' instead",
- )
-
- self._config_file_path = config_file_path
- self._load_external_modules = load_external_modules
- paths = paths or []
-
- # Expand paths with glob patterns.
- glob_base_dir = os.path.dirname(os.path.abspath(config_file_path)) if config_file_path else "."
- with chdir(glob_base_dir):
- resolved_globs = [glob.glob(path) for path in paths]
- paths = [path for glob_list in resolved_globs for path in glob_list]
-
- # By default, add the directory of the config file to the search paths.
- if not paths and config_file_path:
- paths.append(os.path.dirname(config_file_path))
-
- # Initialize search paths from `sys.path`, eliminating empty paths.
- search_paths = [path for path in sys.path if path]
-
- for path in reversed(paths):
- # If it's not absolute, make path relative to the config file path, then make it absolute.
- if not os.path.isabs(path) and config_file_path:
- path = os.path.abspath(os.path.join(os.path.dirname(config_file_path), path)) # noqa: PLW2901
- # Don't add duplicates.
- if path not in search_paths:
- search_paths.insert(0, path)
-
- self._paths = search_paths
- self._modules_collection: ModulesCollection = ModulesCollection()
- self._lines_collection: LinesCollection = LinesCollection()
- self._locale = locale
-
- @classmethod
- def load_inventory(
- cls,
- in_file: BinaryIO,
- url: str,
- base_url: str | None = None,
- domains: list[str] | None = None,
- **kwargs: Any, # noqa: ARG003
- ) -> Iterator[tuple[str, str]]:
- """Yield items and their URLs from an inventory file streamed from `in_file`.
-
- This implements mkdocstrings' `load_inventory` "protocol" (see [`mkdocstrings.plugin`][mkdocstrings.plugin]).
-
- Arguments:
- in_file: The binary file-like object to read the inventory from.
- url: The URL that this file is being streamed from (used to guess `base_url`).
- base_url: The URL that this inventory's sub-paths are relative to.
- domains: A list of domain strings to filter the inventory by, when not passed, "py" will be used.
- **kwargs: Ignore additional arguments passed from the config.
-
- Yields:
- Tuples of (item identifier, item URL).
- """
- domains = domains or ["py"]
- if base_url is None:
- base_url = posixpath.dirname(url)
-
- for item in Inventory.parse_sphinx(in_file, domain_filter=domains).values():
- yield item.name, posixpath.join(base_url, item.uri)
-
- def collect(self, identifier: str, config: Mapping[str, Any]) -> CollectorItem: # noqa: D102
- module_name = identifier.split(".", 1)[0]
- unknown_module = module_name not in self._modules_collection
- if config.get("fallback", False) and unknown_module:
- raise CollectionError("Not loading additional modules during fallback")
-
- final_config = ChainMap(config, self.default_config) # type: ignore[arg-type]
- parser_name = final_config["docstring_style"]
- parser_options = final_config["docstring_options"]
- parser = parser_name and Parser(parser_name)
-
- if unknown_module:
- extensions = self.normalize_extension_paths(final_config.get("extensions", []))
- loader = GriffeLoader(
- extensions=load_extensions(*extensions),
- search_paths=self._paths,
- docstring_parser=parser,
- docstring_options=parser_options,
- modules_collection=self._modules_collection,
- lines_collection=self._lines_collection,
- allow_inspection=final_config["allow_inspection"],
- )
- try:
- for pre_loaded_module in final_config.get("preload_modules") or []:
- if pre_loaded_module not in self._modules_collection:
- loader.load(
- pre_loaded_module,
- try_relative_path=False,
- find_stubs_package=final_config["find_stubs_package"],
- )
- loader.load(
- module_name,
- try_relative_path=False,
- find_stubs_package=final_config["find_stubs_package"],
- )
- except ImportError as error:
- raise CollectionError(str(error)) from error
- unresolved, iterations = loader.resolve_aliases(
- implicit=False,
- external=self._load_external_modules,
- )
- if unresolved:
- logger.debug(f"{len(unresolved)} aliases were still unresolved after {iterations} iterations")
- logger.debug(f"Unresolved aliases: {', '.join(sorted(unresolved))}")
-
- try:
- doc_object = self._modules_collection[identifier]
- except KeyError as error:
- raise CollectionError(f"{identifier} could not be found") from error
- except AliasResolutionError as error:
- raise CollectionError(str(error)) from error
-
- if not unknown_module:
- with suppress(AliasResolutionError):
- if doc_object.docstring is not None:
- doc_object.docstring.parser = parser
- doc_object.docstring.parser_options = parser_options
-
- return doc_object
-
- def render(self, data: CollectorItem, config: Mapping[str, Any]) -> str: # noqa: D102 (ignore missing docstring)
- final_config = ChainMap(config, self.default_config) # type: ignore[arg-type]
-
- template_name = rendering.do_get_template(self.env, data)
- template = self.env.get_template(template_name)
-
- # Heading level is a "state" variable, that will change at each step
- # of the rendering recursion. Therefore, it's easier to use it as a plain value
- # than as an item in a dictionary.
- heading_level = final_config["heading_level"]
- try:
- final_config["members_order"] = rendering.Order(final_config["members_order"])
- except ValueError as error:
- choices = "', '".join(item.value for item in rendering.Order)
- raise PluginError(
- f"Unknown members_order '{final_config['members_order']}', choose between '{choices}'.",
- ) from error
-
- if final_config["filters"]:
- final_config["filters"] = [
- (re.compile(filtr.lstrip("!")), filtr.startswith("!")) for filtr in final_config["filters"]
- ]
-
- summary = final_config["summary"]
- if summary is True:
- final_config["summary"] = {
- "attributes": True,
- "functions": True,
- "classes": True,
- "modules": True,
- }
- elif summary is False:
- final_config["summary"] = {
- "attributes": False,
- "functions": False,
- "classes": False,
- "modules": False,
- }
- else:
- final_config["summary"] = {
- "attributes": summary.get("attributes", False),
- "functions": summary.get("functions", False),
- "classes": summary.get("classes", False),
- "modules": summary.get("modules", False),
- }
-
- return template.render(
- **{
- "config": final_config,
- data.kind.value: data,
- "heading_level": heading_level,
- "root": True,
- "locale": self._locale,
- },
- )
-
- def update_env(self, md: Markdown, config: dict) -> None:
- """Update the Jinja environment with custom filters and tests.
-
- Parameters:
- md: The Markdown instance.
- config: The configuration dictionary.
- """
- super().update_env(md, config)
- self.env.trim_blocks = True
- self.env.lstrip_blocks = True
- self.env.keep_trailing_newline = False
- self.env.filters["split_path"] = rendering.do_split_path
- self.env.filters["crossref"] = rendering.do_crossref
- self.env.filters["multi_crossref"] = rendering.do_multi_crossref
- self.env.filters["order_members"] = rendering.do_order_members
- self.env.filters["format_code"] = rendering.do_format_code
- self.env.filters["format_signature"] = rendering.do_format_signature
- self.env.filters["format_attribute"] = rendering.do_format_attribute
- self.env.filters["filter_objects"] = rendering.do_filter_objects
- self.env.filters["stash_crossref"] = lambda ref, length: ref
- self.env.filters["get_template"] = rendering.do_get_template
- self.env.filters["as_attributes_section"] = rendering.do_as_attributes_section
- self.env.filters["as_functions_section"] = rendering.do_as_functions_section
- self.env.filters["as_classes_section"] = rendering.do_as_classes_section
- self.env.filters["as_modules_section"] = rendering.do_as_modules_section
- self.env.globals["AutorefsHook"] = rendering.AutorefsHook
- self.env.tests["existing_template"] = lambda template_name: template_name in self.env.list_templates()
-
- def get_anchors(self, data: CollectorItem) -> tuple[str, ...]: # noqa: D102 (ignore missing docstring)
- anchors = [data.path]
- try:
- if data.canonical_path != data.path:
- anchors.append(data.canonical_path)
- for anchor in data.aliases:
- if anchor not in anchors:
- anchors.append(anchor)
- except AliasResolutionError:
- return tuple(anchors)
- return tuple(anchors)
-
- def normalize_extension_paths(self, extensions: Sequence) -> Sequence:
- """Resolve extension paths relative to config file."""
- if self._config_file_path is None:
- return extensions
-
- base_path = os.path.dirname(self._config_file_path)
- normalized = []
-
- for ext in extensions:
- if isinstance(ext, dict):
- pth, options = next(iter(ext.items()))
- pth = str(pth)
- else:
- pth = str(ext)
- options = None
-
- if pth.endswith(".py") or ".py:" in pth or "/" in pth or "\\" in pth: # noqa: SIM102
- # This is a sytem path. Normalize it.
- if not os.path.isabs(pth):
- # Make path absolute relative to config file path.
- pth = os.path.normpath(os.path.join(base_path, pth))
-
- if options is not None:
- normalized.append({pth: options})
- else:
- normalized.append(pth)
-
- return normalized
-
-
-def get_handler(
- *,
- theme: str,
- custom_templates: str | None = None,
- config_file_path: str | None = None,
- paths: list[str] | None = None,
- locale: str = "en",
- load_external_modules: bool | None = None,
- **config: Any, # noqa: ARG001
-) -> PythonHandler:
- """Simply return an instance of `PythonHandler`.
-
- Arguments:
- theme: The theme to use when rendering contents.
- custom_templates: Directory containing 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.
- **config: Configuration passed to the handler.
-
- Returns:
- An instance of `PythonHandler`.
- """
- return PythonHandler(
- handler="python",
- theme=theme,
- custom_templates=custom_templates,
- config_file_path=config_file_path,
- paths=paths,
- locale=locale,
- load_external_modules=load_external_modules,
+def __getattr__(name: str) -> Any:
+ warnings.warn(
+ "Importing from `mkdocstrings_handlers.python.handler` is deprecated. Import from `mkdocstrings_handlers.python` directly.",
+ DeprecationWarning,
+ stacklevel=2,
)
+ return getattr(handler, name)
diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py
index 2c4a4893..5cd4d200 100644
--- a/src/mkdocstrings_handlers/python/rendering.py
+++ b/src/mkdocstrings_handlers/python/rendering.py
@@ -1,631 +1,17 @@
-"""This module implements rendering utilities."""
+"""Deprecated. Import from `mkdocstrings_handlers.python` directly."""
-from __future__ import annotations
+# YORE: Bump 2: Remove file.
-import enum
-import random
-import re
-import string
-import sys
import warnings
-from functools import lru_cache, partial
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, Callable, Match, Pattern, Sequence
+from typing import Any
-from griffe import (
- Alias,
- DocstringSectionAttributes,
- DocstringSectionClasses,
- DocstringSectionFunctions,
- DocstringSectionModules,
- Object,
-)
-from jinja2 import TemplateNotFound, pass_context, pass_environment
-from markupsafe import Markup
-from mkdocs_autorefs.references import AutorefsHookInterface
-from mkdocstrings.loggers import get_logger
+from mkdocstrings_handlers.python._internal import rendering
-if TYPE_CHECKING:
- from griffe import Attribute, Class, Function, Module
- from jinja2 import Environment, Template
- from jinja2.runtime import Context
- from mkdocstrings.handlers.base import CollectorItem
-logger = get_logger(__name__)
-
-
-class Order(enum.Enum):
- """Enumeration for the possible members ordering."""
-
- alphabetical = "alphabetical"
- """Alphabetical order."""
- source = "source"
- """Source code order."""
-
-
-def _sort_key_alphabetical(item: CollectorItem) -> Any:
- # chr(sys.maxunicode) is a string that contains the final unicode
- # character, so if 'name' isn't found on the object, the item will go to
- # the end of the list.
- return item.name or chr(sys.maxunicode)
-
-
-def _sort_key_source(item: CollectorItem) -> Any:
- # if 'lineno' is none, the item will go to the start of the list.
- if item.is_alias:
- return item.alias_lineno if item.alias_lineno is not None else -1
- return item.lineno if item.lineno is not None else -1
-
-
-order_map = {
- Order.alphabetical: _sort_key_alphabetical,
- Order.source: _sort_key_source,
-}
-
-
-def do_format_code(code: str, line_length: int) -> str:
- """Format code using Black.
-
- Parameters:
- code: The code to format.
- line_length: The line length to give to Black.
-
- Returns:
- The same code, formatted.
- """
- code = code.strip()
- if len(code) < line_length:
- return code
- formatter = _get_black_formatter()
- return formatter(code, line_length)
-
-
-_stash_key_alphabet = string.ascii_letters + string.digits
-
-
-def _gen_key(length: int) -> str:
- return "_" + "".join(random.choice(_stash_key_alphabet) for _ in range(max(1, length - 1))) # noqa: S311
-
-
-def _gen_stash_key(stash: dict[str, str], length: int) -> str:
- key = _gen_key(length)
- while key in stash:
- key = _gen_key(length)
- return key
-
-
-def _stash_crossref(stash: dict[str, str], crossref: str, *, length: int) -> str:
- key = _gen_stash_key(stash, length)
- stash[key] = crossref
- return key
-
-
-def _format_signature(name: Markup, signature: str, line_length: int) -> str:
- name = str(name).strip() # type: ignore[assignment]
- signature = signature.strip()
- if len(name + signature) < line_length:
- return name + signature
-
- # Black cannot format names with dots, so we replace
- # the whole name with a string of equal length
- name_length = len(name)
- formatter = _get_black_formatter()
- formatable = f"def {'x' * name_length}{signature}: pass"
- formatted = formatter(formatable, line_length)
-
- # We put back the original name
- # and remove starting `def ` and trailing `: pass`
- return name + formatted[4:-5].strip()[name_length:-1]
-
-
-@pass_context
-def do_format_signature(
- context: Context,
- callable_path: Markup,
- function: Function,
- line_length: int,
- *,
- annotations: bool | None = None,
- crossrefs: bool = False,
-) -> str:
- """Format a signature using Black.
-
- Parameters:
- context: Jinja context, passed automatically.
- callable_path: The path of the callable we render the signature of.
- function: The function we render the signature of.
- line_length: The line length to give to Black.
- annotations: Whether to show type annotations.
- crossrefs: Whether to cross-reference types in the signature.
-
- Returns:
- The same code, formatted.
- """
- env = context.environment
- # TODO: Stop using `do_get_template` when `*.html` templates are removed.
- template = env.get_template(do_get_template(env, "signature"))
- config_annotations = context.parent["config"]["show_signature_annotations"]
- old_stash_ref_filter = env.filters["stash_crossref"]
-
- stash: dict[str, str] = {}
- if (annotations or config_annotations) and crossrefs:
- env.filters["stash_crossref"] = partial(_stash_crossref, stash)
-
- if annotations is None:
- new_context = context.parent
- else:
- new_context = dict(context.parent)
- new_context["config"] = dict(new_context["config"])
- new_context["config"]["show_signature_annotations"] = annotations
- try:
- signature = template.render(new_context, function=function, signature=True)
- finally:
- env.filters["stash_crossref"] = old_stash_ref_filter
-
- signature = _format_signature(callable_path, signature, line_length)
- signature = str(
- env.filters["highlight"](
- Markup.escape(signature),
- language="python",
- inline=False,
- classes=["doc-signature"],
- ),
- )
-
- # Since we highlight the signature without `def`,
- # Pygments sees it as a function call and not a function definition.
- # The result is that the function name is not parsed as such,
- # but instead as a regular name: `n` CSS class instead of `nf`.
- # To fix it, we replace the first occurrence of an `n` CSS class
- # with an `nf` one, unless we found `nf` already.
- if signature.find('class="nf"') == -1:
- signature = signature.replace('class="n"', 'class="nf"', 1)
-
- if stash:
- for key, value in stash.items():
- signature = re.sub(rf"\b{key}\b", value, signature)
-
- return signature
-
-
-@pass_context
-def do_format_attribute(
- context: Context,
- attribute_path: Markup,
- attribute: Attribute,
- line_length: int,
- *,
- crossrefs: bool = False,
-) -> str:
- """Format an attribute using Black.
-
- Parameters:
- context: Jinja context, passed automatically.
- attribute_path: The path of the callable we render the signature of.
- attribute: The attribute we render the signature of.
- line_length: The line length to give to Black.
- crossrefs: Whether to cross-reference types in the signature.
-
- Returns:
- The same code, formatted.
- """
- env = context.environment
- # TODO: Stop using `do_get_template` when `*.html` templates are removed.
- template = env.get_template(do_get_template(env, "expression"))
- annotations = context.parent["config"]["show_signature_annotations"]
- separate_signature = context.parent["config"]["separate_signature"]
- old_stash_ref_filter = env.filters["stash_crossref"]
-
- stash: dict[str, str] = {}
- if separate_signature and crossrefs:
- env.filters["stash_crossref"] = partial(_stash_crossref, stash)
-
- try:
- signature = str(attribute_path).strip()
- if annotations and attribute.annotation:
- annotation = template.render(context.parent, expression=attribute.annotation, signature=True)
- signature += f": {annotation}"
- if attribute.value:
- value = template.render(context.parent, expression=attribute.value, signature=True)
- signature += f" = {value}"
- finally:
- env.filters["stash_crossref"] = old_stash_ref_filter
-
- signature = do_format_code(signature, line_length)
- signature = str(
- env.filters["highlight"](
- Markup.escape(signature),
- language="python",
- inline=False,
- classes=["doc-signature"],
- ),
- )
-
- if stash:
- for key, value in stash.items():
- signature = re.sub(rf"\b{key}\b", value, signature)
-
- return signature
-
-
-def do_order_members(
- members: Sequence[Object | Alias],
- order: Order,
- members_list: bool | list[str] | None,
-) -> Sequence[Object | Alias]:
- """Order members given an ordering method.
-
- Parameters:
- members: The members to order.
- order: The ordering method.
- members_list: An optional member list (manual ordering).
-
- Returns:
- The same members, ordered.
- """
- if isinstance(members_list, list) and members_list:
- sorted_members = []
- members_dict = {member.name: member for member in members}
- for name in members_list:
- if name in members_dict:
- sorted_members.append(members_dict[name])
- return sorted_members
- return sorted(members, key=order_map[order])
-
-
-@lru_cache
-def _warn_crossref() -> None:
+def __getattr__(name: str) -> Any:
warnings.warn(
- "The `crossref` filter is deprecated and will be removed in a future version",
+ "Importing from `mkdocstrings_handlers.python.rendering` is deprecated. Import from `mkdocstrings_handlers.python` directly.",
DeprecationWarning,
- stacklevel=1,
+ stacklevel=2,
)
-
-
-def do_crossref(path: str, *, brief: bool = True) -> Markup:
- """Deprecated. Filter to create cross-references.
-
- Parameters:
- path: The path to link to.
- brief: Show only the last part of the path, add full path as hover.
-
- Returns:
- Markup text.
- """
- _warn_crossref()
- full_path = path
- if brief:
- path = full_path.split(".")[-1]
- return Markup("{path} ").format(
- full_path=full_path,
- path=path,
- )
-
-
-@lru_cache
-def _warn_multi_crossref() -> None:
- warnings.warn(
- "The `multi_crossref` filter is deprecated and will be removed in a future version",
- DeprecationWarning,
- stacklevel=1,
- )
-
-
-def do_multi_crossref(text: str, *, code: bool = True) -> Markup:
- """Deprecated. Filter to create cross-references.
-
- Parameters:
- text: The text to scan.
- code: Whether to wrap the result in a code tag.
-
- Returns:
- Markup text.
- """
- _warn_multi_crossref()
- group_number = 0
- variables = {}
-
- def repl(match: Match) -> str:
- nonlocal group_number
- group_number += 1
- path = match.group()
- path_var = f"path{group_number}"
- variables[path_var] = path
- return f"{{{path_var}}} "
-
- text = re.sub(r"([\w.]+)", repl, text)
- if code:
- text = f"{text}
"
- return Markup(text).format(**variables)
-
-
-def do_split_path(path: str, full_path: str) -> list[tuple[str, str]]:
- """Split object paths for building cross-references.
-
- Parameters:
- path: The path to split.
-
- Returns:
- A list of pairs (title, full path).
- """
- if "." not in path:
- return [(path, full_path)]
- pairs = []
- full_path = ""
- for part in path.split("."):
- if full_path:
- full_path += f".{part}"
- else:
- full_path = part
- pairs.append((part, full_path))
- return pairs
-
-
-def _keep_object(name: str, filters: Sequence[tuple[Pattern, bool]]) -> bool:
- keep = None
- rules = set()
- for regex, exclude in filters:
- rules.add(exclude)
- if regex.search(name):
- keep = not exclude
- if keep is None:
- # When we only include stuff, no match = reject.
- # When we only exclude stuff, or include and exclude stuff, no match = keep.
- return rules != {False}
- return keep
-
-
-def do_filter_objects(
- objects_dictionary: dict[str, Object | Alias],
- *,
- filters: Sequence[tuple[Pattern, bool]] | None = None,
- members_list: bool | list[str] | None = None,
- inherited_members: bool | list[str] = False,
- keep_no_docstrings: bool = True,
-) -> list[Object | Alias]:
- """Filter a dictionary of objects based on their docstrings.
-
- Parameters:
- objects_dictionary: The dictionary of objects.
- filters: Filters to apply, based on members' names.
- Each element is a tuple: a pattern, and a boolean indicating whether
- to reject the object if the pattern matches.
- members_list: An optional, explicit list of members to keep.
- When given and empty, return an empty list.
- When given and not empty, ignore filters and docstrings presence/absence.
- inherited_members: Whether to keep inherited members or exclude them.
- keep_no_docstrings: Whether to keep objects with no/empty docstrings (recursive check).
-
- Returns:
- A list of objects.
- """
- inherited_members_specified = False
- if inherited_members is True:
- # Include all inherited members.
- objects = list(objects_dictionary.values())
- elif inherited_members is False:
- # Include no inherited members.
- objects = [obj for obj in objects_dictionary.values() if not obj.inherited]
- else:
- # Include specific inherited members.
- inherited_members_specified = True
- objects = [
- obj for obj in objects_dictionary.values() if not obj.inherited or obj.name in set(inherited_members)
- ]
-
- if members_list is True:
- # Return all pre-selected members.
- return objects
-
- if members_list is False or members_list == []:
- # Return selected inherited members, if any.
- return [obj for obj in objects if obj.inherited]
-
- if members_list is not None:
- # Return selected members (keeping any pre-selected inherited members).
- return [
- obj for obj in objects if obj.name in set(members_list) or (inherited_members_specified and obj.inherited)
- ]
-
- # Use filters and docstrings.
- if filters:
- objects = [
- obj for obj in objects if _keep_object(obj.name, filters) or (inherited_members_specified and obj.inherited)
- ]
- if keep_no_docstrings:
- return objects
-
- return [obj for obj in objects if obj.has_docstrings or (inherited_members_specified and obj.inherited)]
-
-
-@lru_cache(maxsize=1)
-def _get_black_formatter() -> Callable[[str, int], str]:
- try:
- from black import InvalidInput, Mode, format_str
- except ModuleNotFoundError:
- logger.info("Formatting signatures requires Black to be installed.")
- return lambda text, _: text
-
- def formatter(code: str, line_length: int) -> str:
- mode = Mode(line_length=line_length)
- try:
- return format_str(code, mode=mode)
- except InvalidInput:
- return code
-
- return formatter
-
-
-@pass_environment
-def do_get_template(env: Environment, obj: str | Object) -> str | Template:
- """Get the template name used to render an object.
-
- Parameters:
- env: The Jinja environment, passed automatically.
- obj: A Griffe object, or a template name.
-
- Returns:
- A template name.
- """
- name = obj
- if isinstance(obj, (Alias, Object)):
- extra_data = getattr(obj, "extra", {}).get("mkdocstrings", {})
- if name := extra_data.get("template", ""):
- return name
- name = obj.kind.value
- try:
- template = env.get_template(f"{name}.html")
- except TemplateNotFound:
- return f"{name}.html.jinja"
- # TODO: Remove once support for Python 3.8 is dropped.
- if sys.version_info < (3, 9):
- try:
- Path(template.filename).relative_to(Path(__file__).parent) # type: ignore[arg-type]
- except ValueError:
- our_template = False
- else:
- our_template = True
- else:
- our_template = Path(template.filename).is_relative_to(Path(__file__).parent) # type: ignore[arg-type]
- if our_template:
- return f"{name}.html.jinja"
- # TODO: Switch to a warning log after some time.
- logger.info(
- f"DeprecationWarning: Overriding '{name}.html' is deprecated, override '{name}.html.jinja' instead. "
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
- once=True,
- )
- return f"{name}.html"
-
-
-@pass_context
-def do_as_attributes_section(
- context: Context, # noqa: ARG001
- attributes: Sequence[Attribute], # noqa: ARG001
- *,
- check_public: bool = True, # noqa: ARG001
-) -> DocstringSectionAttributes:
- """Build an attributes section from a list of attributes.
-
- Parameters:
- attributes: The attributes to build the section from.
- check_public: Whether to check if the attribute is public.
-
- Returns:
- An attributes docstring section.
- """
- return DocstringSectionAttributes([])
-
-
-@pass_context
-def do_as_functions_section(
- context: Context, # noqa: ARG001
- functions: Sequence[Function], # noqa: ARG001
- *,
- check_public: bool = True, # noqa: ARG001
-) -> DocstringSectionFunctions:
- """Build a functions section from a list of functions.
-
- Parameters:
- functions: The functions to build the section from.
- check_public: Whether to check if the function is public.
-
- Returns:
- A functions docstring section.
- """
- return DocstringSectionFunctions([])
-
-
-@pass_context
-def do_as_classes_section(
- context: Context, # noqa: ARG001
- classes: Sequence[Class], # noqa: ARG001
- *,
- check_public: bool = True, # noqa: ARG001
-) -> DocstringSectionClasses:
- """Build a classes section from a list of classes.
-
- Parameters:
- classes: The classes to build the section from.
- check_public: Whether to check if the class is public.
-
- Returns:
- A classes docstring section.
- """
- return DocstringSectionClasses([])
-
-
-@pass_context
-def do_as_modules_section(
- context: Context, # noqa: ARG001
- modules: Sequence[Module], # noqa: ARG001
- *,
- check_public: bool = True, # noqa: ARG001
-) -> DocstringSectionModules:
- """Build a modules section from a list of modules.
-
- Parameters:
- modules: The modules to build the section from.
- check_public: Whether to check if the module is public.
-
- Returns:
- A modules docstring section.
- """
- return DocstringSectionModules([])
-
-
-class AutorefsHook(AutorefsHookInterface):
- """Autorefs hook.
-
- With this hook, we're able to add context to autorefs (cross-references),
- such as originating file path and line number, to improve error reporting.
- """
-
- def __init__(self, current_object: Object | Alias, config: dict[str, Any]) -> None:
- """Initialize the hook.
-
- Parameters:
- current_object: The object being rendered.
- config: The configuration dictionary.
- """
- self.current_object = current_object
- self.config = config
-
- def expand_identifier(self, identifier: str) -> str:
- """Expand an identifier.
-
- Parameters:
- identifier: The identifier to expand.
-
- Returns:
- The expanded identifier.
- """
- return identifier
-
- def get_context(self) -> AutorefsHookInterface.Context:
- """Get the context for the current object.
-
- Returns:
- The context.
- """
- role = {
- "attribute": "data" if self.current_object.parent and self.current_object.parent.is_module else "attr",
- "class": "class",
- "function": "meth" if self.current_object.parent and self.current_object.parent.is_class else "func",
- "module": "mod",
- }.get(self.current_object.kind.value.lower(), "obj")
- origin = self.current_object.path
- try:
- filepath = self.current_object.docstring.parent.filepath # type: ignore[union-attr]
- lineno = self.current_object.docstring.lineno or 0 # type: ignore[union-attr]
- except AttributeError:
- filepath = self.current_object.filepath
- lineno = 0
-
- return AutorefsHookInterface.Context(
- domain="py",
- role=role,
- origin=origin,
- filepath=str(filepath),
- lineno=lineno,
- )
+ return getattr(rendering, name)
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
index 7effc590..37c8702c 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/attribute.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/attribute.html' is deprecated, extend '_base/attribute.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/attribute.html' is deprecated, extend '_base/attribute.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 0716b171..519590e5 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) }}
@@ -39,20 +39,22 @@ Context:
role="data" if attribute.parent.kind.value == "module" else "attr",
id=html_id,
class="doc doc-heading",
- 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),
) %}
{% block heading scoped %}
{#- Heading block.
-
+
This block renders the heading for the attribute.
-#}
{% if config.show_symbol_type_heading %}
{% endif %}
- {% if config.separate_signature %}
+ {% if config.heading and root %}
+ {{ config.heading }}
+ {% elif config.separate_signature %}
{{ attribute_name }}
{% else %}
{%+ filter highlight(language="python", inline=True) %}
- {{ attribute_name }}{% if attribute.annotation %}: {{ attribute.annotation }}{% endif %}
+ {{ attribute_name }}{% if attribute.annotation and config.show_signature_annotations %}: {{ attribute.annotation }}{% endif %}
{% if attribute.value %} = {{ attribute.value }}{% endif %}
{% endfilter %}
{% endif %}
@@ -60,10 +62,11 @@ Context:
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the attribute.
-#}
{% with labels = attribute.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -72,7 +75,7 @@ Context:
{% block signature scoped %}
{#- Signature block.
-
+
This block renders the signature for the attribute.
-#}
{% if config.separate_signature %}
@@ -88,7 +91,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 %}
@@ -99,20 +102,25 @@ 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 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% endblock docstring %}
+
+ {% if config.backlinks %}
+
+ {% endif %}
{% endblock contents %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/backlinks.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/backlinks.html.jinja
new file mode 100644
index 00000000..2ab16038
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/backlinks.html.jinja
@@ -0,0 +1,17 @@
+{#- Template for backlinks.
+
+This template renders backlinks.
+
+Context:
+ backlinks (Mapping[str, Iterable[str]]): The backlinks to render.
+ config (dict): The configuration options.
+ verbose_type (Mapping[str, str]): The verbose backlink types.
+ default_crumb (BacklinkCrumb): A default, empty crumb.
+-#}
+
+{% 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/children.html b/src/mkdocstrings_handlers/python/templates/material/_base/children.html
index 15fada5a..eada68e8 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/children.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/children.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/children.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/children.html' is deprecated, extend '_base/children.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/children.html' is deprecated, extend '_base/children.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..0b9fcd64 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) }}
@@ -49,7 +49,7 @@ Context:
{% endif %}
{% with heading_level = heading_level + extra_level %}
{% for attribute in attributes|order_members(config.members_order, members_list) %}
- {% if members_list is not none or (not attribute.is_imported or attribute.is_public) %}
+ {% if config.filters == "public" or members_list is not none or (not attribute.is_imported or attribute.is_public) %}
{% include attribute|get_template with context %}
{% endif %}
{% endfor %}
@@ -69,7 +69,7 @@ Context:
{% endif %}
{% with heading_level = heading_level + extra_level %}
{% for class in classes|order_members(config.members_order, members_list) %}
- {% if members_list is not none or (not class.is_imported or class.is_public) %}
+ {% if config.filters == "public" or members_list is not none or (not class.is_imported or class.is_public) %}
{% include class|get_template with context %}
{% endif %}
{% endfor %}
@@ -90,7 +90,7 @@ Context:
{% with heading_level = heading_level + extra_level %}
{% for function in functions|order_members(config.members_order, members_list) %}
{% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %}
- {% if members_list is not none or (not function.is_imported or function.is_public) %}
+ {% if config.filters == "public" or members_list is not none or (not function.is_imported or function.is_public) %}
{% include function|get_template with context %}
{% endif %}
{% endif %}
@@ -111,8 +111,8 @@ Context:
{% filter heading(heading_level, id=html_id ~ "-modules") %}Modules{% endfilter %}
{% endif %}
{% with heading_level = heading_level + extra_level %}
- {% for module in modules|order_members(config.members_order.alphabetical, members_list) %}
- {% if members_list is not none or (not module.is_alias or module.is_public) %}
+ {% for module in modules|order_members("alphabetical", members_list) %}
+ {% if config.filters == "public" or members_list is not none or (not module.is_alias or module.is_public) %}
{% include module|get_template with context %}
{% endif %}
{% endfor %}
@@ -137,7 +137,7 @@ Context:
{% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %}
- {% if members_list is not none or child.is_public %}
+ {% if config.filters == "public" or members_list is not none or child.is_public %}
{% if child.is_attribute %}
{% with attribute = child %}
{% include attribute|get_template with context %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html b/src/mkdocstrings_handlers/python/templates/material/_base/class.html
index ac3e421e..0fb87f5b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/class.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
index 27a91d13..8a54dd1b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
@@ -11,14 +11,14 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering " + class.path) }}
{% endblock logs %}
- {% with obj = class, html_id = class.path %}
+ {% with obj = class, html_id = class.path, all_members = class.all_members %}
{% if root %}
{% set show_full_path = config.show_root_full_path %}
@@ -38,22 +38,25 @@ Context:
role="class",
id=html_id,
class="doc doc-heading",
- 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),
) %}
{% block heading scoped %}
{#- Heading block.
-
+
This block renders the heading for the class.
-#}
{% if config.show_symbol_type_heading %}
{% endif %}
- {% if config.separate_signature %}
+ {% if config.heading and root %}
+ {{ config.heading }}
+ {% elif config.separate_signature %}
{{ class_name }}
- {% elif config.merge_init_into_class and "__init__" in class.all_members %}
- {% with function = class.all_members["__init__"] %}
- {%+ filter highlight(language="python", inline=True) %}
+ {% elif config.merge_init_into_class and "__init__" in all_members %}
+ {% with function = all_members["__init__"] %}
+ {%+ filter highlight(language="python", inline=True) -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{{ class_name }}{% include "signature"|get_template with context %}
- {% endfilter %}
+ {%- endfilter %}
{% endwith %}
{% else %}
{{ class_name }}
@@ -62,10 +65,11 @@ Context:
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the class.
-#}
{% with labels = class.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -74,15 +78,28 @@ 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.
-#}
- {% if config.separate_signature and config.merge_init_into_class %}
- {% if "__init__" in class.all_members %}
- {% with function = class.all_members["__init__"] %}
- {% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %}
- {{ class.name }}
- {% endfilter %}
+ {% if config.merge_init_into_class %}
+ {% if "__init__" in all_members %}
+ {% with function = all_members["__init__"] %}
+ {% if function.overloads and config.show_overloads %}
+
+ {% for overload in function.overloads %}
+ {% filter format_signature(overload, config.line_length, annotations=True, crossrefs=config.signature_crossrefs) %}
+ {{ class.name }}
+ {% endfilter %}
+ {% endfor %}
+
+ {% endif %}
+ {% if config.separate_signature %}
+ {% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %}
+ {{ class.name }}
+ {% endfilter %}
+ {% endif %}
{% endwith %}
{% endif %}
{% endif %}
@@ -93,7 +110,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 %}
@@ -104,20 +121,25 @@ 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 %}
Bases: {% for expression in class.bases -%}
- {% include "expression"|get_template with context %}
{% if not loop.last %}, {% endif %}
+
+ {%- with backlink_type = "subclassed-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
+ {%- include "expression"|get_template with context -%}
+ {%- endwith -%}
+
{% if not loop.last %}, {% endif %}
{% endfor -%}
{% endif %}
@@ -125,30 +147,51 @@ Context:
{% block docstring scoped %}
{#- Docstring block.
-
+
This block renders the docstring for the class.
-#}
{% with docstring_sections = class.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% if config.merge_init_into_class %}
- {% if "__init__" in class.all_members and class.all_members["__init__"].has_docstring %}
- {% with docstring_sections = class.all_members["__init__"].docstring.parsed %}
- {% include "docstring"|get_template with context %}
- {% endwith %}
- {% endif %}
+ {# We don't want to merge the inherited `__init__` method docstring into the class docstring #}
+ {# if such inherited method was not selected through `inherited_members`. #}
+ {% with check_members = all_members if (config.inherited_members is true or (config.inherited_members is iterable and "__init__" in config.inherited_members)) else class.members %}
+ {% if "__init__" in check_members and check_members["__init__"].has_docstring %}
+ {% with function = check_members["__init__"] %}
+ {% with obj = function, docstring_sections = function.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "docstring"|get_template with context %}
+ {% endwith %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
{% endif %}
{% endblock docstring %}
+ {% if config.backlinks %}
+
+ {% endif %}
+
+ {% block summary scoped %}
+ {#- Summary block.
+
+ This block renders auto-summaries for classes, methods, and attributes.
+ -#}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "summary"|get_template with context %}
+ {% endblock summary %}
+
{% block source scoped %}
{#- Source block.
-
+
This block renders the source code for the class.
-#}
{% if config.show_source %}
{% if config.merge_init_into_class %}
- {% if "__init__" in class.all_members and class.all_members["__init__"].source %}
- {% with init = class.all_members["__init__"] %}
+ {% if "__init__" in all_members and all_members["__init__"].source %}
+ {% with init = all_members["__init__"] %}
Source code in
{%- if init.relative_filepath.is_absolute() -%}
@@ -178,11 +221,12 @@ Context:
{% block children scoped %}
{#- Children block.
-
+
This block renders the children (members) of the class.
-#}
{% set root = False %}
{% set heading_level = heading_level + 1 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "children"|get_template with context %}
{% endblock children %}
{% endblock contents %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html
index 5ef9da3e..c487550b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring.html' is deprecated, extend '_base/docstring.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring.html' is deprecated, extend '_base/docstring.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..c560668e 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") }}
@@ -24,30 +24,43 @@ Context:
{% if config.show_docstring_description and section.kind.value == "text" %}
{{ section.value|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% elif config.show_docstring_attributes and section.kind.value == "attributes" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/attributes"|get_template with context %}
{% elif config.show_docstring_functions and section.kind.value == "functions" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/functions"|get_template with context %}
{% elif config.show_docstring_classes and section.kind.value == "classes" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/classes"|get_template with context %}
{% elif config.show_docstring_modules and section.kind.value == "modules" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/modules"|get_template with context %}
{% elif config.show_docstring_parameters and section.kind.value == "parameters" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/parameters"|get_template with context %}
{% elif config.show_docstring_other_parameters and section.kind.value == "other parameters" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/other_parameters"|get_template with context %}
{% elif config.show_docstring_raises and section.kind.value == "raises" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/raises"|get_template with context %}
{% elif config.show_docstring_warns and section.kind.value == "warns" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/warns"|get_template with context %}
{% elif config.show_docstring_yields and section.kind.value == "yields" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/yields"|get_template with context %}
{% elif config.show_docstring_receives and section.kind.value == "receives" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/receives"|get_template with context %}
{% elif config.show_docstring_returns and section.kind.value == "returns" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/returns"|get_template with context %}
{% elif config.show_docstring_examples and section.kind.value == "examples" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/examples"|get_template with context %}
{% elif config.show_docstring_description and section.kind.value == "admonition" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/admonition"|get_template with context %}
{% endif %}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html
index a8a75542..e94d6e61 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/admonition.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/admonition.html' is deprecated, extend '_base/docstring/admonition.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/admonition.html' is deprecated, extend '_base/docstring/admonition.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html
index cd4b05be..9f2abcd1 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..03104333 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering attributes section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -37,6 +38,7 @@ Context:
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -61,6 +63,7 @@ Context:
{{ attribute.name }}
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
@@ -95,6 +98,7 @@ Context:
TYPE:
{% with expression = attribute.annotation %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
index 78b47e2d..9c04b145 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/classes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/classes.html' is deprecated, extend '_base/docstring/classes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/classes.html' is deprecated, extend '_base/docstring/classes.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..09a5b758 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering classes section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html
index 37674811..4f66600f 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/examples.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/examples.html' is deprecated, extend '_base/docstring/examples.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/examples.html' is deprecated, extend '_base/docstring/examples.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 dd0b503f..09293cfb 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering examples section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -23,6 +24,6 @@ Context:
{% if section_type.value == "text" %}
{{ sub_section|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% elif section_type.value == "examples" %}
- {{ sub_section|highlight(language="pycon", linenums=False) }}
+ {{ sub_section|highlight(language="pycon") }}
{% endif %}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html
index a61c48fb..906658b4 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/functions.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/functions.html' is deprecated, extend '_base/docstring/functions.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/functions.html' is deprecated, extend '_base/docstring/functions.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..dd33984f 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering functions section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html
index d0b303b4..7b0dcc51 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/modules.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/modules.html' is deprecated, extend '_base/docstring/modules.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/modules.html' is deprecated, extend '_base/docstring/modules.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..106e6bf6 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering modules section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html
index eae60aa7..02261331 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..66940069 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,12 +9,13 @@ 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") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -36,7 +37,8 @@ Context:
{{ parameter.name }}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -60,7 +62,8 @@ Context:
-
{{ parameter.name }}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
@@ -94,7 +97,8 @@ Context:
{% if parameter.annotation %}
{{ lang.t("TYPE:") }}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
index f5745464..f5292150 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 8b0556f3..1035ddf7 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering parameters section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -34,10 +35,25 @@ Context:
{% for parameter in section.value %}
- {{ parameter.name }}
+
+ {% if config.parameter_headings %}
+ {% filter heading(
+ heading_level + 1,
+ role="param",
+ id=html_id ~ "(" ~ parameter.name ~ ")",
+ class="doc doc-heading doc-heading-parameter",
+ toc_label=('
'|safe if config.show_symbol_type_toc else '') + parameter.name,
+ ) %}
+ {{ parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ parameter.name }}
+ {% endif %}
+
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -49,7 +65,8 @@ Context:
{% if parameter.default %}
- {% with expression = parameter.default %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% else %}
@@ -68,12 +85,26 @@ Context:
{% for parameter in section.value %}
-
-
{{ parameter.name }}
+ {% if config.parameter_headings %}
+ {% filter heading(
+ heading_level + 1,
+ role="param",
+ id=html_id ~ "(" ~ parameter.name ~ ")",
+ class="doc doc-heading doc-heading-parameter",
+ toc_label=('
'|safe if config.show_symbol_type_toc else '') + parameter.name,
+ ) %}
+ {{ parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ parameter.name }}
+ {% endif %}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
{%- if parameter.default %}, {{ lang.t("default:") }}
- {% with expression = parameter.default %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %})
@@ -100,7 +131,21 @@ Context:
{% for parameter in section.value %}
- {{ parameter.name }}
+
+ {% if config.parameter_headings %}
+ {% filter heading(
+ heading_level + 1,
+ role="param",
+ id=html_id ~ "(" ~ parameter.name ~ ")",
+ class="doc doc-heading doc-heading-parameter",
+ toc_label=('
'|safe if config.show_symbol_type_toc else '') + parameter.name,
+ ) %}
+ {{ parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ parameter.name }}
+ {% endif %}
+
{{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
@@ -109,7 +154,8 @@ Context:
{% if parameter.annotation %}
{{ lang.t("TYPE:") }}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -117,7 +163,8 @@ Context:
{% if parameter.default %}
{{ lang.t("DEFAULT:") }}
- {% with expression = parameter.default %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
index 361b9732..38a21e89 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..cd034c0e 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering raises section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -34,7 +35,8 @@ Context:
{% if raises.annotation %}
- {% with expression = raises.annotation %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -57,7 +59,8 @@ Context:
{% for raises in section.value %}
-
{% if raises.annotation %}
- {% with expression = raises.annotation %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
–
@@ -84,7 +87,8 @@ Context:
- {% with expression = raises.annotation %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html
index e5a115c1..d9c404b6 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..3ecc5b41 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering receives section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -37,7 +38,8 @@ Context:
{% if name_column %} {% if receives.name %}{{ receives.name }}
{% endif %} {% endif %}
{% if receives.annotation %}
- {% with expression = receives.annotation %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -61,8 +63,9 @@ Context:
-
{% if receives.name %}
{{ receives.name }}
{% endif %}
{% if receives.annotation %}
- {% with expression = receives.annotation %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
{% if receives.name %} ({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if receives.name %}){% endif %}
{% endwith %}
@@ -93,7 +96,8 @@ Context:
{{ receives.name }}
{% elif receives.annotation %}
- {% with expression = receives.annotation %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -107,7 +111,8 @@ Context:
{{ lang.t("TYPE:") }}
- {% with expression = receives.annotation %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html
index 0e7807ac..b608af5f 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..bc8ee4ff 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering returns section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -37,7 +38,8 @@ Context:
{% if name_column %}
{% if returns.name %}{{ returns.name }}
{% endif %} {% endif %}
{% if returns.annotation %}
- {% with expression = returns.annotation %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -61,8 +63,9 @@ Context:
-
{% if returns.name %}
{{ returns.name }}
{% endif %}
{% if returns.annotation %}
- {% with expression = returns.annotation %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
{% if returns.name %} ({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if returns.name %}){% endif %}
{% endwith %}
@@ -93,7 +96,8 @@ Context:
{{ returns.name }}
{% elif returns.annotation %}
- {% with expression = returns.annotation %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -107,7 +111,8 @@ Context:
{{ lang.t("TYPE:") }}
- {% with expression = returns.annotation %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html
index b7b937a9..9eba72ab 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..d5a24262 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering warns section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -34,7 +35,8 @@ Context:
{% if warns.annotation %}
- {% with expression = warns.annotation %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -57,7 +59,8 @@ Context:
{% for warns in section.value %}
-
{% if warns.annotation %}
- {% with expression = warns.annotation %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
–
@@ -84,7 +87,8 @@ Context:
- {% with expression = warns.annotation %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html
index ecd6f513..6ec31dd0 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..154d0202 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering yields section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -37,7 +38,8 @@ Context:
{% if name_column %} {% if yields.name %}{{ yields.name }}
{% endif %} {% endif %}
{% if yields.annotation %}
- {% with expression = yields.annotation %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -61,8 +63,9 @@ Context:
-
{% if yields.name %}
{{ yields.name }}
{% endif %}
{% if yields.annotation %}
- {% with expression = yields.annotation %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
{% if yields.name %} ({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if yields.name %}){% endif %}
{% endwith %}
@@ -93,7 +96,8 @@ Context:
{{ yields.name }}
{% elif yields.annotation %}
- {% with expression = yields.annotation %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -107,7 +111,8 @@ Context:
{{ lang.t("TYPE:") }}:
- {% with expression = yields.annotation %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
index 556b3e2b..8c84928c 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/expression.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/expression.html' is deprecated, extend '_base/expression.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/expression.html' is deprecated, extend '_base/expression.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 f150afd1..d49e43be 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) -%}
+{%- macro crossref(name, annotation_path, backlink_type="") -%}
{#- Output a cross-reference.
-
+
This macro outputs a cross-reference to the given name.
Parameters:
@@ -31,20 +31,48 @@ which is a tree-like structure representing a Python expression.
{%- elif annotation_path == "full" -%}
{%- set annotation = full -%}
{%- endif -%}
- {%- for title, path in annotation|split_path(full) -%}
- {%- if not signature or config.signature_crossrefs -%}
+ {%- for prefix, title, path, suffix in annotation|split_path(full) -%}
+ {{ prefix }}
+ {%- if not signature -%}
+ {#- Always render cross-references outside of signatures. We don't need to stash them. -#}
+ {{ title }}
+ {%- elif config.signature_crossrefs -%}
+ {#- We're in a signature and cross-references are enabled, we must render one and stash it. -#}
{%- filter stash_crossref(length=title|length) -%}
- {{ title }}
+ {{ title }}
{%- endfilter -%}
{%- else -%}
+ {#- We're in a signature but cross-references are disabled, we just render the title. -#}
{{ title }}
{%- endif -%}
- {%- if not loop.last -%}.{%- endif -%}
+ {{ suffix }}
{%- endfor -%}
{%- endwith -%}
{%- endmacro -%}
-{%- macro render(expression, annotations_path) -%}
+{%- macro param_crossref(expression) -%}
+ {#- Render a cross-reference to a parameter heading.
+
+ Parameters:
+ expression (griffe.expressions.Expr): The expression to render.
+
+ Returns:
+ The autorefs cross-reference, or the parameter name.
+ -#}
+ {%- if config.signature_crossrefs -%}
+ {%- if signature -%}
+ {%- filter stash_crossref(length=expression.name|length) -%}
+ {{ expression.name }}
+ {%- endfilter -%}
+ {%- else -%}
+ {{ expression.name }}
+ {%- endif -%}
+ {%- else -%}
+ {{ expression.name }}
+ {%- endif -%}
+{%- endmacro -%}
+
+{%- macro render(expression, annotations_path, backlink_type="") -%}
{#- Render an expression.
Parameters:
@@ -57,13 +85,13 @@ which is a tree-like structure representing a Python expression.
{%- if expression is string -%}
{%- if signature -%}{{ expression|safe }}{%- else -%}{{ expression }}{%- endif -%}
{%- elif expression.classname == "ExprName" -%}
- {{ crossref(expression, annotations_path) }}
+ {{ crossref(expression, annotations_path, backlink_type) }}
{%- elif config.unwrap_annotated and expression.classname == "ExprSubscript" and expression.canonical_path in ("typing.Annotated", "typing_extensions.Annotated") -%}
{{ render(expression.slice.elements[0], annotations_path) }}
{%- elif expression.classname == "ExprAttribute" -%}
{%- if annotations_path == "brief" -%}
{%- if expression.last.is_enum_value -%}
- {{ crossref(expression.last.parent, "brief") }}.value
+ {{ crossref(expression.last.parent, "brief", backlink_type) }}.value
{%- else -%}
{{ render(expression.last, "brief") }}
{%- endif -%}
@@ -79,6 +107,8 @@ which is a tree-like structure representing a Python expression.
{{ render(element, annotations_path) }}
{%- endfor -%}
{%- endif -%}
+ {%- elif expression.classname == "ExprKeyword" -%}
+ {{ param_crossref(expression) }}={{ render(expression.value, annotations_path) }}
{%- else -%}
{%- for element in expression -%}
{{ render(element, annotations_path) }}
@@ -86,4 +116,4 @@ which is a tree-like structure representing a Python expression.
{%- endif -%}
{%- endmacro -%}
-{{ render(expression, config.annotations_path) }}
+{{ render(expression, config.annotations_path, backlink_type|default("")) }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html b/src/mkdocstrings_handlers/python/templates/material/_base/function.html
index 07be5abb..4afd930b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/function.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/function.html' is deprecated, extend '_base/function.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/function.html' is deprecated, extend '_base/function.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 3631b699..21888939 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja
@@ -11,12 +11,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug("Rendering " + function.path) }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -44,30 +45,34 @@ Context:
role="function",
id=html_id,
class="doc doc-heading",
- 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),
) %}
{% block heading scoped %}
{#- Heading block.
-
+
This block renders the heading for the function.
-#}
{% if config.show_symbol_type_heading %}
{% endif %}
- {% if config.separate_signature %}
+ {% if config.heading and root %}
+ {{ config.heading }}
+ {% elif config.separate_signature %}
{{ function_name }}
{% else %}
- {%+ filter highlight(language="python", inline=True) %}
+ {%+ filter highlight(language="python", inline=True) -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{{ function_name }}{% include "signature"|get_template with context %}
- {% endfilter %}
+ {%- endfilter %}
{% endif %}
{% endblock heading %}
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the function.
-#}
{% with labels = function.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -76,9 +81,19 @@ Context:
{% block signature scoped %}
{#- Signature block.
-
- This block renders the signature for the function.
+
+ This block renders the signature for the function,
+ as well as its overloaded signatures if any.
-#}
+ {% if function.overloads and config.show_overloads %}
+
+ {% for overload in function.overloads %}
+ {% filter format_signature(overload, config.line_length, annotations=True, crossrefs=config.signature_crossrefs) %}
+ {{ overload.name }}
+ {% endfilter %}
+ {% endfor %}
+
+ {% endif %}
{% if config.separate_signature %}
{% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %}
{{ function.name }}
@@ -93,7 +108,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 %}
@@ -104,24 +119,29 @@ 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 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% endblock docstring %}
+ {% if config.backlinks %}
+
+ {% endif %}
+
{% 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 b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
index 784150c4..cda79114 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/labels.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/labels.html' is deprecated, extend '_base/labels.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/labels.html' is deprecated, extend '_base/labels.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 b/src/mkdocstrings_handlers/python/templates/material/_base/language.html
index c97d0c31..a5a86545 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/language.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/language.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..5a4b773e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja
@@ -2,17 +2,20 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
+{# YORE: Bump 2: Replace `| get_template` with `~ ".html.jinja"` within line. #}
{% set lang_pth = "languages/" ~ locale | get_template %}
{% if lang_pth is existing_template %}
- {% import lang_pth as lang %}
- {% import "languages/en"|get_template as fallback %}
- {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %}
+ {% import lang_pth as lang %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% import "languages/en"|get_template as fallback %}
+ {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %}
{% else %}
- {% import "languages/en"|get_template as lang %}
- {% macro t(key) %}{{ lang.t(key) }}{% endmacro %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% import "languages/en"|get_template as lang %}
+ {% macro t(key) %}{{ lang.t(key) }}{% endmacro %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html
index eab87415..2f050a32 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. ",
once=True,
) }}
{% 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 b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
index 14319499..1f3095f4 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. ",
once=True,
) }}
{% 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..0393ca03 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 %}
@@ -10,20 +10,20 @@
{% macro t(key) %}{{ {
"ATTRIBUTE": "属性",
"Attributes:": "属性:",
- "Classes:": "",
- "CLASS": "",
+ "Classes:": "クラス:",
+ "CLASS": "クラス",
"DEFAULT:": "デフォルト:",
"Default": "デフォルト",
"default:": "デフォルト:",
"DESCRIPTION": "デスクリプション",
"Description": "デスクリプション",
"Examples:": "例:",
- "Functions:": "",
- "FUNCTION": "",
- "Methods:": "",
- "METHOD": "",
- "Modules:": "",
- "MODULE": "",
+ "Functions:": "関数:",
+ "FUNCTION": "関数",
+ "Methods:": "メソッド:",
+ "METHOD": "メソッド",
+ "Modules:": "モジュール:",
+ "MODULE": "モジュール",
"Name": "名前",
"Other Parameters:": "他の引数:",
"PARAMETER": "引数",
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
index 0b281195..b58b0479 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. ",
once=True,
) }}
{% 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..e57169ad 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 %}
@@ -10,20 +10,20 @@
{% macro t(key) %}{{ {
"ATTRIBUTE": "属性",
"Attributes:": "属性:",
- "Classes:": "",
- "CLASS": "",
+ "Classes:": "类:",
+ "CLASS": "类",
"DEFAULT:": "默认:",
"Default": "默认",
"default:": "默认:",
"DESCRIPTION": "描述",
"Description": "描述",
"Examples:": "示例:",
- "Functions:": "",
- "FUNCTION": "",
- "Methods:": "",
- "METHOD": "",
- "Modules:": "",
- "MODULE": "",
+ "Functions:": "函数:",
+ "FUNCTION": "函数",
+ "Methods:": "方法:",
+ "METHOD": "方法",
+ "Modules:": "模块:",
+ "MODULE": "模块",
"Name": "名称",
"Other Parameters:": "其他参数:",
"PARAMETER": "参数",
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/module.html b/src/mkdocstrings_handlers/python/templates/material/_base/module.html
index 918ab6d0..dcda15ea 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/module.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/module.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/module.html' is deprecated, extend '_base/module.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/module.html' is deprecated, extend '_base/module.html.jinja' instead. ",
once=True,
) }}
{% 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 ae7d88d9..283f2654 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) }}
@@ -38,16 +38,18 @@ 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 %}
{#- Heading block.
-
+
This block renders the heading for the module.
-#}
{% if config.show_symbol_type_heading %}
{% endif %}
- {% if config.separate_signature %}
+ {% if config.heading and root %}
+ {{ config.heading }}
+ {% elif config.separate_signature %}
{{ module_name }}
{% else %}
{{ module_name }}
@@ -56,10 +58,11 @@ Context:
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the module.
-#}
{% with labels = module.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -71,7 +74,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 %}
@@ -82,28 +85,43 @@ 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 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% endblock docstring %}
+ {% if config.backlinks %}
+
+ {% endif %}
+
+ {% block summary scoped %}
+ {#- Summary block.
+
+ This block renders auto-summaries for classes, methods, and attributes.
+ -#}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "summary"|get_template with context %}
+ {% endblock summary %}
+
{% block children scoped %}
{#- Children block.
-
+
This block renders the children (members) of the module.
-#}
{% set root = False %}
{% set heading_level = heading_level + 1 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "children"|get_template with context %}
{% endblock children %}
{% endblock contents %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
index 623879db..6f05fed7 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/signature.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/signature.html' is deprecated, extend '_base/signature.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/signature.html' is deprecated, extend '_base/signature.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 1107458c..0e0678a1 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") }}
@@ -25,6 +25,7 @@ Context:
render_kw_only_separator=True,
annotation="",
equal="=",
+ default=False,
) -%}
(
@@ -46,9 +47,12 @@ Context:
{#- Prepare type annotation. -#}
{%- if config.show_signature_annotations and parameter.annotation is not none -%}
{%- set ns.equal = " = " -%}
- {%- if config.separate_signature and config.signature_crossrefs -%}
+ {%- if config.separate_signature -%}
{%- with expression = parameter.annotation -%}
- {%- set ns.annotation -%}: {% include "expression"|get_template with context %}{%- endset -%}
+ {%- set ns.annotation -%}: {% with backlink_type = "used-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
+ {%- include "expression"|get_template with context -%}
+ {%- endwith -%}{%- endset -%}
{%- endwith -%}
{%- else -%}
{%- set ns.annotation = ": " + parameter.annotation|safe -%}
@@ -60,7 +64,9 @@ Context:
{#- Prepare default value. -#}
{%- if parameter.default is not none and parameter.kind.value != "variadic positional" and parameter.kind.value != "variadic keyword" -%}
- {%- set default = ns.equal + parameter.default|safe -%}
+ {%- set ns.default = True -%}
+ {%- else -%}
+ {%- set ns.default = False -%}
{%- endif -%}
{#- TODO: Move inside kind handling above? -#}
@@ -68,9 +74,46 @@ Context:
{%- set ns.render_kw_only_separator = False -%}
{%- endif -%}
- {#- Render name, annotation and default. -#}
- {% if parameter.kind.value == "variadic positional" %}*{% elif parameter.kind.value == "variadic keyword" %}**{% endif -%}
- {{ parameter.name }}{{ ns.annotation }}{{ default }}
+ {#- Prepare name. -#}
+ {%- set param_prefix -%}
+ {%- if parameter.kind.value == "variadic positional" -%}
+ *
+ {%- elif parameter.kind.value == "variadic keyword" -%}
+ **
+ {%- endif -%}
+ {%- endset -%}
+
+ {#- Render parameter name with optional cross-reference to its heading. -#}
+ {{ param_prefix }}
+ {%- if config.separate_signature and config.parameter_headings and config.signature_crossrefs -%}
+ {%- filter stash_crossref(length=parameter.name|length) -%}
+ {%- with func_path = function.path -%}
+ {%- if config.merge_init_into_class and func_path.endswith(".__init__") -%}
+ {%- set func_path = func_path[:-9] -%}
+ {%- endif -%}
+ {{ parameter.name }}
+ {%- endwith -%}
+ {%- endfilter -%}
+ {%- else -%}
+ {{ parameter.name }}
+ {%- endif -%}
+
+ {#- Render parameter annotation. -#}
+ {{ ns.annotation }}
+
+ {#- Render parameter default value. -#}
+ {%- if ns.default -%}
+ {{ ns.equal }}
+ {%- if config.signature_crossrefs and config.separate_signature -%}
+ {%- with expression = parameter.default, backlink_type = "used-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
+ {%- include "expression"|get_template with context -%}
+ {%- endwith -%}
+ {%- else -%}
+ {{ parameter.default|safe }}
+ {%- endif -%}
+ {%- endif -%}
+
{%- if not loop.last %}, {% endif -%}
{%- endif -%}
@@ -82,7 +125,10 @@ Context:
and function.annotation
and not (config.merge_init_into_class and function.name == "__init__" )
%} -> {% if config.separate_signature and config.signature_crossrefs -%}
- {%- with expression = function.annotation %}{% include "expression"|get_template with context %}{%- endwith -%}
+ {%- with expression = function.annotation, backlink_type = "returned-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
+ {%- include "expression"|get_template with context -%}
+ {%- endwith -%}
{%- else -%}
{{ function.annotation|safe }}
{%- endif -%}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html
index aa33dc9c..b970164d 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary.html' is deprecated, extend '_base/summary.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary.html' is deprecated, extend '_base/summary.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 5770fdb0..78b0b9d7 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,29 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
+
+{% with members_list = config.members if root_members else None %}
+ {% if config.summary.modules %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "summary/modules"|get_template with context %}
+ {% endif %}
+
+ {% if config.summary.classes %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "summary/classes"|get_template with context %}
+ {% endif %}
+
+ {% if config.summary.functions %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "summary/functions"|get_template with context %}
+ {% endif %}
+
+ {% if config.summary.attributes %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "summary/attributes"|get_template with context %}
+ {% endif %}
+{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html
index f2643791..8e575a44 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/attributes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/attributes.html' is deprecated, extend '_base/summary/attributes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/attributes.html' is deprecated, extend '_base/summary/attributes.html.jinja' instead. ",
once=True,
) }}
{% 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 cb966fb1..52f9a43a 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,23 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
+
+{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "attributes") | list %}
+ {% with section = obj.attributes
+ |filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ )
+ |order_members(config.members_order, members_list)
+ |as_attributes_section(check_public=not members_list)
+ %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% if section %}{% include "docstring/attributes"|get_template with context %}{% endif %}
+ {% endwith %}
+{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html
index 5c6275b4..a74eff99 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/classes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/classes.html' is deprecated, extend '_base/summary/classes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/classes.html' is deprecated, extend '_base/summary/classes.html.jinja' instead. ",
once=True,
) }}
{% 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 94456775..628d4133 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,23 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
+
+{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "classes") | list %}
+ {% with section = obj.classes
+ |filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ )
+ |order_members(config.members_order, members_list)
+ |as_classes_section(check_public=not members_list)
+ %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% if section %}{% include "docstring/classes"|get_template with context %}{% endif %}
+ {% endwith %}
+{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html
index 31887e0a..ff95f246 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/functions.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/functions.html' is deprecated, extend '_base/summary/functions.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/functions.html' is deprecated, extend '_base/summary/functions.html.jinja' instead. ",
once=True,
) }}
{% 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 5e8305aa..a82f2f87 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,23 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
+
+{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "functions") | list %}
+ {% with section = obj.functions
+ |filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ )
+ |order_members(config.members_order, members_list)
+ |as_functions_section(check_public=not members_list)
+ %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% if section %}{% include "docstring/functions"|get_template with context %}{% endif %}
+ {% endwith %}
+{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html
index 31dcb5f0..51e964c1 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/modules.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/modules.html' is deprecated, extend '_base/summary/modules.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/modules.html' is deprecated, extend '_base/summary/modules.html.jinja' instead. ",
once=True,
) }}
{% 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 04387b32..109b34a9 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,23 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
+
+{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "modules") | list %}
+ {% with section = obj.modules
+ |filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ )
+ |order_members("alphabetical", members_list)
+ |as_modules_section(check_public=not members_list)
+ %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% if section %}{% include "docstring/modules"|get_template with context %}{% endif %}
+ {% endwith %}
+{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/attribute.html b/src/mkdocstrings_handlers/python/templates/material/attribute.html
index a3c27503..aaf56880 100644
--- a/src/mkdocstrings_handlers/python/templates/material/attribute.html
+++ b/src/mkdocstrings_handlers/python/templates/material/attribute.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/attribute.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/backlinks.html.jinja b/src/mkdocstrings_handlers/python/templates/material/backlinks.html.jinja
new file mode 100644
index 00000000..08ba4922
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/backlinks.html.jinja
@@ -0,0 +1 @@
+{% extends "_base/backlinks.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/children.html b/src/mkdocstrings_handlers/python/templates/material/children.html
index 2c2a73ab..312346ec 100644
--- a/src/mkdocstrings_handlers/python/templates/material/children.html
+++ b/src/mkdocstrings_handlers/python/templates/material/children.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/children.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/class.html b/src/mkdocstrings_handlers/python/templates/material/class.html
index 5e7329df..7ee0f690 100644
--- a/src/mkdocstrings_handlers/python/templates/material/class.html
+++ b/src/mkdocstrings_handlers/python/templates/material/class.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/class.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring.html b/src/mkdocstrings_handlers/python/templates/material/docstring.html
index a7ccd66c..cb91e77a 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html b/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html
index e9da5e9a..943c883f 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/admonition.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html
index 4ac364b0..6a67cafb 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html b/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html
index 035b3102..fce82b60 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/classes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html b/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html
index 34e9c4ba..334796a6 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/examples.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html b/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html
index f3eaed78..9f07107e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/functions.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html b/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html
index 8ea02a33..23a9965e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/modules.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html
index 7c50379b..a7024661 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html
index 70c557fb..fb49b54d 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html
index f8c3cf03..1365fc5e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html
index 004ff00e..9521ee68 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html
index 979ce9ef..93413ed8 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
index bb06cc85..95523fde 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html
index 717ef5d4..58bccc7b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/expression.html b/src/mkdocstrings_handlers/python/templates/material/expression.html
index 60c64d79..5edd5520 100644
--- a/src/mkdocstrings_handlers/python/templates/material/expression.html
+++ b/src/mkdocstrings_handlers/python/templates/material/expression.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/expression.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/function.html b/src/mkdocstrings_handlers/python/templates/material/function.html
index 54bba061..c90df9b5 100644
--- a/src/mkdocstrings_handlers/python/templates/material/function.html
+++ b/src/mkdocstrings_handlers/python/templates/material/function.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/function.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/labels.html b/src/mkdocstrings_handlers/python/templates/material/labels.html
index 51cb29d6..124caf19 100644
--- a/src/mkdocstrings_handlers/python/templates/material/labels.html
+++ b/src/mkdocstrings_handlers/python/templates/material/labels.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/labels.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/language.html b/src/mkdocstrings_handlers/python/templates/material/language.html
index b905cff4..6da4f8df 100644
--- a/src/mkdocstrings_handlers/python/templates/material/language.html
+++ b/src/mkdocstrings_handlers/python/templates/material/language.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/en.html b/src/mkdocstrings_handlers/python/templates/material/languages/en.html
index 931967c1..bcc4121e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/material/languages/en.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/ja.html b/src/mkdocstrings_handlers/python/templates/material/languages/ja.html
index 17070edf..87827f60 100644
--- a/src/mkdocstrings_handlers/python/templates/material/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/material/languages/ja.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/zh.html b/src/mkdocstrings_handlers/python/templates/material/languages/zh.html
index e4ea3116..37c36ff0 100644
--- a/src/mkdocstrings_handlers/python/templates/material/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/material/languages/zh.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/module.html b/src/mkdocstrings_handlers/python/templates/material/module.html
index 9d8efea5..ea043657 100644
--- a/src/mkdocstrings_handlers/python/templates/material/module.html
+++ b/src/mkdocstrings_handlers/python/templates/material/module.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/module.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/signature.html b/src/mkdocstrings_handlers/python/templates/material/signature.html
index 33b266c8..e6573985 100644
--- a/src/mkdocstrings_handlers/python/templates/material/signature.html
+++ b/src/mkdocstrings_handlers/python/templates/material/signature.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/signature.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/style.css b/src/mkdocstrings_handlers/python/templates/material/style.css
index 154be85d..b8c3e639 100644
--- a/src/mkdocstrings_handlers/python/templates/material/style.css
+++ b/src/mkdocstrings_handlers/python/templates/material/style.css
@@ -9,6 +9,11 @@
display: inline;
}
+/* No text transformation from Material for MkDocs for H5 headings. */
+.md-typeset h5 .doc-object-name {
+ text-transform: none;
+}
+
/* Max width for docstring sections tables. */
.doc .md-typeset__table,
.doc .md-typeset__table table {
@@ -25,20 +30,60 @@
float: right;
}
+/* Parameter headings must be inline, not blocks. */
+.doc-heading-parameter {
+ display: inline;
+}
+
+/* Default font size for parameter headings. */
+.md-typeset .doc-heading-parameter {
+ font-size: inherit;
+}
+
+/* Prefer space on the right, not the left of parameter permalinks. */
+.doc-heading-parameter .headerlink {
+ margin-left: 0 !important;
+ margin-right: 0.2rem;
+}
+
/* Backward-compatibility: docstring section titles in bold. */
.doc-section-title {
font-weight: bold;
}
+/* Backlinks crumb separator. */
+.doc-backlink-crumb {
+ display: inline-flex;
+ gap: .2rem;
+ white-space: nowrap;
+ align-items: center;
+ vertical-align: middle;
+}
+.doc-backlink-crumb:not(:first-child)::before {
+ background-color: var(--md-default-fg-color--lighter);
+ content: "";
+ display: inline;
+ height: 1rem;
+ --md-path-icon: url('data:image/svg+xml;charset=utf-8,');
+ -webkit-mask-image: var(--md-path-icon);
+ mask-image: var(--md-path-icon);
+ width: 1rem;
+}
+.doc-backlink-crumb.last {
+ font-weight: bold;
+}
+
/* Symbols in Navigation and ToC. */
-:root,
+:root, :host,
[data-md-color-scheme="default"] {
+ --doc-symbol-parameter-fg-color: #df50af;
--doc-symbol-attribute-fg-color: #953800;
--doc-symbol-function-fg-color: #8250df;
--doc-symbol-method-fg-color: #8250df;
--doc-symbol-class-fg-color: #0550ae;
--doc-symbol-module-fg-color: #5cad0f;
+ --doc-symbol-parameter-bg-color: #df50af1a;
--doc-symbol-attribute-bg-color: #9538001a;
--doc-symbol-function-bg-color: #8250df1a;
--doc-symbol-method-bg-color: #8250df1a;
@@ -47,12 +92,14 @@
}
[data-md-color-scheme="slate"] {
+ --doc-symbol-parameter-fg-color: #ffa8cc;
--doc-symbol-attribute-fg-color: #ffa657;
--doc-symbol-function-fg-color: #d2a8ff;
--doc-symbol-method-fg-color: #d2a8ff;
--doc-symbol-class-fg-color: #79c0ff;
--doc-symbol-module-fg-color: #baff79;
+ --doc-symbol-parameter-bg-color: #ffa8cc1a;
--doc-symbol-attribute-bg-color: #ffa6571a;
--doc-symbol-function-bg-color: #d2a8ff1a;
--doc-symbol-method-bg-color: #d2a8ff1a;
@@ -67,7 +114,18 @@ code.doc-symbol {
font-weight: bold;
}
-code.doc-symbol-attribute {
+code.doc-symbol-parameter,
+a code.doc-symbol-parameter {
+ color: var(--doc-symbol-parameter-fg-color);
+ background-color: var(--doc-symbol-parameter-bg-color);
+}
+
+code.doc-symbol-parameter::after {
+ content: "param";
+}
+
+code.doc-symbol-attribute,
+a code.doc-symbol-attribute {
color: var(--doc-symbol-attribute-fg-color);
background-color: var(--doc-symbol-attribute-bg-color);
}
@@ -76,7 +134,8 @@ code.doc-symbol-attribute::after {
content: "attr";
}
-code.doc-symbol-function {
+code.doc-symbol-function,
+a code.doc-symbol-function {
color: var(--doc-symbol-function-fg-color);
background-color: var(--doc-symbol-function-bg-color);
}
@@ -85,7 +144,8 @@ code.doc-symbol-function::after {
content: "func";
}
-code.doc-symbol-method {
+code.doc-symbol-method,
+a code.doc-symbol-method {
color: var(--doc-symbol-method-fg-color);
background-color: var(--doc-symbol-method-bg-color);
}
@@ -94,7 +154,8 @@ code.doc-symbol-method::after {
content: "meth";
}
-code.doc-symbol-class {
+code.doc-symbol-class,
+a code.doc-symbol-class {
color: var(--doc-symbol-class-fg-color);
background-color: var(--doc-symbol-class-bg-color);
}
@@ -103,7 +164,8 @@ code.doc-symbol-class::after {
content: "class";
}
-code.doc-symbol-module {
+code.doc-symbol-module,
+a code.doc-symbol-module {
color: var(--doc-symbol-module-fg-color);
background-color: var(--doc-symbol-module-bg-color);
}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary.html b/src/mkdocstrings_handlers/python/templates/material/summary.html
index 59eddea0..604624e7 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html b/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html
index c69755c6..a0fdbb04 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/attributes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/classes.html b/src/mkdocstrings_handlers/python/templates/material/summary/classes.html
index 825eb1bb..c01b2094 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/classes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/classes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/functions.html b/src/mkdocstrings_handlers/python/templates/material/summary/functions.html
index fc609bda..90ca63e0 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/functions.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/functions.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/modules.html b/src/mkdocstrings_handlers/python/templates/material/summary/modules.html
index 46db0023..1f69b3dc 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/modules.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/modules.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
index cd4b05be..9f2abcd1 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. ",
once=True,
) }}
{% 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..e8804310 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -33,6 +34,7 @@ Context:
{{ attribute.name }}
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
index eae60aa7..02261331 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..6605e48d 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,7 +33,8 @@ Context:
-
{{ parameter.name }}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
index f5745464..f5292150 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..de01dcbe 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,10 +33,12 @@ Context:
-
{{ parameter.name }}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
{%- if parameter.default %}, {{ lang.t("default:") }}
- {% with expression = parameter.default %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %})
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
index 361b9732..38a21e89 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..cf7d0b01 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -31,7 +32,8 @@ Context:
{% for raises in section.value %}
-
{% if raises.annotation %}
- {% with expression = raises.annotation %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
index e5a115c1..d9c404b6 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..84d6c1bc 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,8 +33,9 @@ Context:
-
{% if receives.name %}
{{ receives.name }}
{% endif %}
{% if receives.annotation %}
- {% with expression = receives.annotation %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
{% if receives.name %}({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if receives.name %}){% endif %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
index 0e7807ac..b608af5f 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..c1171c7e 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,8 +33,9 @@ Context:
-
{% if returns.name %}
{{ returns.name }}
{% endif %}
{% if returns.annotation %}
- {% with expression = returns.annotation %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
{% if returns.name %}({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if returns.name %}){% endif %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
index b7b937a9..9eba72ab 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..5570ca37 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -31,7 +32,8 @@ Context:
{% for warns in section.value %}
-
{% if warns.annotation %}
- {% with expression = warns.annotation %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
index ecd6f513..6ec31dd0 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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..712776fe 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,12 +9,13 @@ Context:
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,8 +33,9 @@ Context:
-
{% if yields.name %}{{ yields.name }}{% endif %}
{% if yields.annotation %}
- {% with expression = yields.annotation %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
{% if yields.name %}({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if yields.name %}){% endif %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
index c97d0c31..a5a86545 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
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 5b643726..5a4b773e 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja
@@ -2,17 +2,20 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
+{# YORE: Bump 2: Replace `| get_template` with `~ ".html.jinja"` within line. #}
{% set lang_pth = "languages/" ~ locale | get_template %}
{% if lang_pth is existing_template %}
- {% import lang_pth as lang %}
- {% import "languages/en"|get_template as fallback %}
- {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %}
+ {% import lang_pth as lang %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% import "languages/en"|get_template as fallback %}
+ {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %}
{% else %}
- {% import "languages/en"|get_template as lang %}
- {% macro t(key) %}{{ lang.t(key) }}{% endmacro %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% import "languages/en"|get_template as lang %}
+ {% macro t(key) %}{{ lang.t(key) }}{% endmacro %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html
index eab87415..2f050a32 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html
index 14319499..1f3095f4 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html.jinja
index 748fd8b7..b6279ef0 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html.jinja
@@ -4,20 +4,20 @@
{% macro t(key) %}{{ {
"ATTRIBUTE": "属性",
"Attributes:": "属性:",
- "Classes:": "",
- "CLASS": "",
+ "Classes:": "クラス:",
+ "CLASS": "クラス",
"DEFAULT:": "デフォルト:",
"Default": "デフォルト",
"default:": "デフォルト:",
"DESCRIPTION": "デスクリプション",
"Description": "デスクリプション",
"Examples:": "例:",
- "Functions:": "",
- "FUNCTION": "",
- "Methods:": "",
- "METHOD": "",
- "Modules:": "",
- "MODULE": "",
+ "Functions:": "関数:",
+ "FUNCTION": "関数",
+ "Methods:": "メソッド:",
+ "METHOD": "メソッド",
+ "Modules:": "モジュール:",
+ "MODULE": "モジュール",
"Name": "名前",
"Other Parameters:": "他の引数:",
"PARAMETER": "引数",
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html
index 0b281195..b58b0479 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html.jinja
index 772e33cd..f25ff721 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html.jinja
@@ -4,20 +4,20 @@
{% macro t(key) %}{{ {
"ATTRIBUTE": "属性",
"Attributes:": "属性:",
- "Classes:": "",
- "CLASS": "",
+ "Classes:": "类:",
+ "CLASS": "类",
"DEFAULT:": "默认:",
"Default": "默认",
"default:": "默认:",
"DESCRIPTION": "描述",
"Description": "描述",
"Examples:": "示例:",
- "Functions:": "",
- "FUNCTION": "",
- "Methods:": "",
- "METHOD": "",
- "Modules:": "",
- "MODULE": "",
+ "Functions:": "函数:",
+ "FUNCTION": "函数",
+ "Methods:": "方法:",
+ "METHOD": "方法",
+ "Modules:": "模块:",
+ "MODULE": "模块",
"Name": "名称",
"Other Parameters:": "其他参数:",
"PARAMETER": "参数",
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
index 4ac364b0..6a67cafb 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html
index 7c50379b..a7024661 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html
index 70c557fb..fb49b54d 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html
index f8c3cf03..1365fc5e 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html
index 004ff00e..9521ee68 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html
index 979ce9ef..93413ed8 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html
index bb06cc85..95523fde 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html
index 717ef5d4..58bccc7b 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/language.html b/src/mkdocstrings_handlers/python/templates/readthedocs/language.html
index b905cff4..6da4f8df 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/language.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/language.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html
index 931967c1..bcc4121e 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html
index 17070edf..87827f60 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html
index e4ea3116..37c36ff0 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
diff --git a/tests/conftest.py b/tests/conftest.py
index f7b28105..926c4b83 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -2,24 +2,29 @@
from __future__ import annotations
-from collections import ChainMap
-from typing import TYPE_CHECKING, Any, Iterator
+from collections.abc import Iterator
+from typing import TYPE_CHECKING
import pytest
-from markdown.core import Markdown
-from mkdocs.config.defaults import MkDocsConfig
+
+from tests import helpers
if TYPE_CHECKING:
+ from collections.abc import Iterator
from pathlib import Path
- from mkdocs import config
- from mkdocstrings.plugin import MkdocstringsPlugin
+ from markdown.core import Markdown
+ from mkdocs.config.defaults import MkDocsConfig
+ from mkdocstrings import MkdocstringsPlugin
- from mkdocstrings_handlers.python.handler import PythonHandler
+ from mkdocstrings_handlers.python import PythonHandler
+# --------------------------------------------
+# Function-scoped fixtures.
+# --------------------------------------------
@pytest.fixture(name="mkdocs_conf")
-def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[config.Config]:
+def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[MkDocsConfig]:
"""Yield a MkDocs configuration object.
Parameters:
@@ -29,34 +34,12 @@ def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Itera
Yields:
MkDocs config.
"""
- conf = MkDocsConfig()
- while hasattr(request, "_parent_request") and hasattr(request._parent_request, "_parent_request"):
- request = request._parent_request
-
- conf_dict = {
- "site_name": "foo",
- "site_url": "https://example.org/",
- "site_dir": str(tmp_path),
- "plugins": [{"mkdocstrings": {"default_handler": "python"}}],
- **getattr(request, "param", {}),
- }
- # Re-create it manually as a workaround for https://github.com/mkdocs/mkdocs/issues/2289
- mdx_configs: dict[str, Any] = dict(ChainMap(*conf_dict.get("markdown_extensions", [])))
-
- conf.load_dict(conf_dict)
- assert conf.validate() == ([], [])
-
- conf["mdx_configs"] = mdx_configs
- conf["markdown_extensions"].insert(0, "toc") # Guaranteed to be added by MkDocs.
-
- conf = conf["plugins"]["mkdocstrings"].on_config(conf)
- conf = conf["plugins"]["autorefs"].on_config(conf)
- yield conf
- conf["plugins"]["mkdocstrings"].on_post_build(conf)
+ with helpers.mkdocs_conf(request, tmp_path) as mkdocs_conf:
+ yield mkdocs_conf
@pytest.fixture(name="plugin")
-def fixture_plugin(mkdocs_conf: config.Config) -> MkdocstringsPlugin:
+def fixture_plugin(mkdocs_conf: MkDocsConfig) -> MkdocstringsPlugin:
"""Return a plugin instance.
Parameters:
@@ -65,11 +48,11 @@ def fixture_plugin(mkdocs_conf: config.Config) -> MkdocstringsPlugin:
Returns:
mkdocstrings plugin instance.
"""
- return mkdocs_conf["plugins"]["mkdocstrings"]
+ return helpers.plugin(mkdocs_conf)
@pytest.fixture(name="ext_markdown")
-def fixture_ext_markdown(mkdocs_conf: config.Config) -> Markdown:
+def fixture_ext_markdown(mkdocs_conf: MkDocsConfig) -> Markdown:
"""Return a Markdown instance with MkdocstringsExtension.
Parameters:
@@ -78,7 +61,7 @@ def fixture_ext_markdown(mkdocs_conf: config.Config) -> Markdown:
Returns:
A Markdown instance.
"""
- return Markdown(extensions=mkdocs_conf["markdown_extensions"], extension_configs=mkdocs_conf["mdx_configs"])
+ return helpers.ext_markdown(mkdocs_conf)
@pytest.fixture(name="handler")
@@ -91,6 +74,64 @@ def fixture_handler(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> Pytho
Returns:
A handler instance.
"""
- handler = plugin.handlers.get_handler("python")
- handler._update_env(ext_markdown, plugin.handlers._config)
- return handler # type: ignore[return-value]
+ return helpers.handler(plugin, ext_markdown)
+
+
+# --------------------------------------------
+# Session-scoped fixtures.
+# --------------------------------------------
+@pytest.fixture(name="session_mkdocs_conf", scope="session")
+def fixture_session_mkdocs_conf(
+ request: pytest.FixtureRequest,
+ tmp_path_factory: pytest.TempPathFactory,
+) -> Iterator[MkDocsConfig]:
+ """Yield a MkDocs configuration object.
+
+ Parameters:
+ request: Pytest fixture.
+ tmp_path: Pytest fixture.
+
+ Yields:
+ MkDocs config.
+ """
+ with helpers.mkdocs_conf(request, tmp_path_factory.mktemp("project")) as mkdocs_conf:
+ yield mkdocs_conf
+
+
+@pytest.fixture(name="session_plugin", scope="session")
+def fixture_session_plugin(session_mkdocs_conf: MkDocsConfig) -> MkdocstringsPlugin:
+ """Return a plugin instance.
+
+ Parameters:
+ mkdocs_conf: Pytest fixture (see conftest.py).
+
+ Returns:
+ mkdocstrings plugin instance.
+ """
+ return helpers.plugin(session_mkdocs_conf)
+
+
+@pytest.fixture(name="session_ext_markdown", scope="session")
+def fixture_session_ext_markdown(session_mkdocs_conf: MkDocsConfig) -> Markdown:
+ """Return a Markdown instance with MkdocstringsExtension.
+
+ Parameters:
+ mkdocs_conf: Pytest fixture (see conftest.py).
+
+ Returns:
+ A Markdown instance.
+ """
+ return helpers.ext_markdown(session_mkdocs_conf)
+
+
+@pytest.fixture(name="session_handler", scope="session")
+def fixture_session_handler(session_plugin: MkdocstringsPlugin, session_ext_markdown: Markdown) -> PythonHandler:
+ """Return a handler instance.
+
+ Parameters:
+ plugin: Pytest fixture (see conftest.py).
+
+ Returns:
+ A handler instance.
+ """
+ return helpers.handler(session_plugin, session_ext_markdown)
diff --git a/tests/helpers.py b/tests/helpers.py
new file mode 100644
index 00000000..d7fb7e1d
--- /dev/null
+++ b/tests/helpers.py
@@ -0,0 +1,97 @@
+"""Configuration for the pytest test suite."""
+
+from __future__ import annotations
+
+from collections import ChainMap
+from contextlib import contextmanager
+from typing import TYPE_CHECKING, Any
+
+from markdown.core import Markdown
+from mkdocs.config.defaults import MkDocsConfig
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+ from pathlib import Path
+
+ import pytest
+ from mkdocstrings import MkdocstringsPlugin
+
+ from mkdocstrings_handlers.python import PythonHandler
+
+
+@contextmanager
+def mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[MkDocsConfig]:
+ """Yield a MkDocs configuration object.
+
+ Parameters:
+ request: Pytest request fixture.
+ tmp_path: Temporary path.
+
+ Yields:
+ MkDocs config.
+ """
+ while hasattr(request, "_parent_request") and hasattr(request._parent_request, "_parent_request"):
+ request = request._parent_request
+
+ params = getattr(request, "param", {})
+ plugins = params.pop("plugins", [{"mkdocstrings": {}}])
+
+ conf = MkDocsConfig()
+ conf_dict = {
+ "site_name": "foo",
+ "site_url": "https://example.org/",
+ "site_dir": str(tmp_path),
+ "plugins": plugins,
+ **getattr(request, "param", {}),
+ }
+ # Re-create it manually as a workaround for https://github.com/mkdocs/mkdocs/issues/2289
+ mdx_configs: dict[str, Any] = dict(ChainMap(*conf_dict.get("markdown_extensions", [])))
+
+ conf.load_dict(conf_dict)
+ assert conf.validate() == ([], [])
+
+ conf["mdx_configs"] = mdx_configs
+ conf["markdown_extensions"].insert(0, "toc") # Guaranteed to be added by MkDocs.
+
+ conf = conf["plugins"]["mkdocstrings"].on_config(conf)
+ conf = conf["plugins"]["autorefs"].on_config(conf)
+ yield conf
+ conf["plugins"]["mkdocstrings"].on_post_build(conf)
+
+
+def plugin(mkdocs_conf: MkDocsConfig) -> MkdocstringsPlugin:
+ """Return a plugin instance.
+
+ Parameters:
+ mkdocs_conf: MkDocs configuration.
+
+ Returns:
+ mkdocstrings plugin instance.
+ """
+ return mkdocs_conf["plugins"]["mkdocstrings"]
+
+
+def ext_markdown(mkdocs_conf: MkDocsConfig) -> Markdown:
+ """Return a Markdown instance with MkdocstringsExtension.
+
+ Parameters:
+ mkdocs_conf: MkDocs configuration.
+
+ Returns:
+ A Markdown instance.
+ """
+ return Markdown(extensions=mkdocs_conf["markdown_extensions"], extension_configs=mkdocs_conf["mdx_configs"])
+
+
+def handler(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> PythonHandler:
+ """Return a handler instance.
+
+ Parameters:
+ plugin: Plugin instance.
+
+ Returns:
+ A handler instance.
+ """
+ handler = plugin.handlers.get_handler("python")
+ handler._update_env(ext_markdown)
+ return handler # type: ignore[return-value]
diff --git a/tests/snapshots/__init__.py b/tests/snapshots/__init__.py
new file mode 100644
index 00000000..36eb97b7
--- /dev/null
+++ b/tests/snapshots/__init__.py
@@ -0,0 +1,405 @@
+"""Snaphots for the inline-snapshot pytest plugin."""
+
+from inline_snapshot import external, snapshot
+
+snapshots_signatures = snapshot(
+ {
+ (
+ ("separate_signature", True),
+ ("show_signature_annotations", False),
+ ("signature_crossrefs", False),
+ ): external("d03d16d1919a*.html"),
+ (
+ ("separate_signature", True),
+ ("show_signature_annotations", True),
+ ("signature_crossrefs", True),
+ ): external("e412376be64f*.html"),
+ (
+ ("separate_signature", False),
+ ("show_signature_annotations", True),
+ ("signature_crossrefs", True),
+ ): external("735fc6ffdb82*.html"),
+ (
+ ("separate_signature", False),
+ ("show_signature_annotations", False),
+ ("signature_crossrefs", True),
+ ): external("6a02b544c12c*.html"),
+ (
+ ("separate_signature", False),
+ ("show_signature_annotations", False),
+ ("signature_crossrefs", False),
+ ): external("b060b701543e*.html"),
+ (
+ ("separate_signature", True),
+ ("show_signature_annotations", True),
+ ("signature_crossrefs", False),
+ ): external("74ee37cd1e94*.html"),
+ (
+ ("separate_signature", True),
+ ("show_signature_annotations", False),
+ ("signature_crossrefs", True),
+ ): external("4041a38e355f*.html"),
+ (
+ ("separate_signature", False),
+ ("show_signature_annotations", True),
+ ("signature_crossrefs", False),
+ ): external("d1216ebf8e30*.html"),
+ },
+)
+
+snapshots_members = snapshot(
+ {
+ (
+ ("filters", ()),
+ ("inherited_members", ("method1",)),
+ ("members", False),
+ ): external("ab0ddac637b5*.html"),
+ (("filters", None), ("inherited_members", True), ("members", True)): external("c0f102dbd7d4*.html"),
+ (("filters", ()), ("inherited_members", False), ("members", True)): external("fca72854c849*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ()),
+ ("members", ("module_attribute",)),
+ ): external("6d12192d6b4d*.html"),
+ (("filters", ()), ("inherited_members", ()), ("members", False)): external("366b0537fe06*.html"),
+ (
+ ("filters", ()),
+ ("inherited_members", ("method1",)),
+ ("members", ("module_attribute",)),
+ ): external("e90c3e0c85dd*.html"),
+ (("filters", ()), ("inherited_members", True), ("members", True)): external("722165bce3ad*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", ()),
+ ): external("f8f32ea6a0c8*.html"),
+ (
+ ("filters", ()),
+ ("inherited_members", ("method1",)),
+ ("members", True),
+ ): external("cd51e40cc0dd*.html"),
+ (("filters", ()), ("inherited_members", False), ("members", False)): external("5cf0130e3b4f*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", True),
+ ("members", True),
+ ): external("34b16654e7ba*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", False),
+ ("members", ()),
+ ): external("fb5ebb7546d8*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", ("method1",)),
+ ("members", ("module_attribute",)),
+ ): external("afd5c166367d*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", ("module_attribute",)),
+ ): external("26bc66c2ba29*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", False),
+ ("members", ("module_attribute",)),
+ ): external("247a6063b698*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", False),
+ ("members", ("module_attribute",)),
+ ): external("5a9c10410801*.html"),
+ (("filters", ()), ("inherited_members", False), ("members", ())): external("fba0d78ae23e*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", None),
+ ): external("cfcd41685591*.html"),
+ (("filters", ()), ("inherited_members", False), ("members", None)): external("eac5bee59a9e*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ()),
+ ("members", False),
+ ): external("76ee8e01e1c0*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", ()),
+ ): external("42c053a5e567*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", ("method1",)),
+ ("members", ()),
+ ): external("4f60da13e2d4*.html"),
+ (("filters", ()), ("inherited_members", True), ("members", ())): external("c915eb92fd5d*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ()),
+ ("members", None),
+ ): external("c9a15552eed3*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", None),
+ ): external("fe1cd23642d4*.html"),
+ (("filters", None), ("inherited_members", False), ("members", False)): external("9bd282a6f2fe*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", ()),
+ ("members", ("module_attribute",)),
+ ): external("166b8dfab738*.html"),
+ (("filters", None), ("inherited_members", ()), ("members", False)): external("44e42f27bfe3*.html"),
+ (("filters", None), ("inherited_members", False), ("members", None)): external("0f046dea611f*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", True),
+ ("members", ()),
+ ): external("28d8862dd086*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", True),
+ ("members", False),
+ ): external("f3f3acb6b51b*.html"),
+ (("filters", None), ("inherited_members", ()), ("members", True)): external("dcf34c2f7269*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", True),
+ ("members", None),
+ ): external("8733f7fb7b6d*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", False),
+ ("members", False),
+ ): external("eee65d3705a6*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", False),
+ ("members", ("module_attribute",)),
+ ): external("a200913d9a7d*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", True),
+ ("members", ("module_attribute",)),
+ ): external("bd6594ae3b51*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", True),
+ ("members", ("module_attribute",)),
+ ): external("8d4e1f9af997*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", False),
+ ("members", ()),
+ ): external("d5a6bf59c663*.html"),
+ (("filters", None), ("inherited_members", ()), ("members", None)): external("fd291f98ca28*.html"),
+ (("filters", ()), ("inherited_members", True), ("members", None)): external("14bca0e5703b*.html"),
+ (
+ ("filters", ()),
+ ("inherited_members", False),
+ ("members", ("module_attribute",)),
+ ): external("09d96d69d9dc*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", ("method1",)),
+ ("members", None),
+ ): external("43d819f94dc7*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", True),
+ ("members", ()),
+ ): external("95f8e480937f*.html"),
+ (("filters", None), ("inherited_members", False), ("members", True)): external("f4150843096a*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", True),
+ ("members", True),
+ ): external("3c21330afd65*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", False),
+ ("members", None),
+ ): external("d55652702606*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", False),
+ ): external("f0014d9505ec*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", True),
+ ("members", ("module_attribute",)),
+ ): external("96cf94f4822a*.html"),
+ (("filters", None), ("inherited_members", True), ("members", ())): external("ce06da7f07b3*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ()),
+ ("members", False),
+ ): external("74bfab19cbd4*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", ("method1",)),
+ ("members", True),
+ ): external("75b69b702f3b*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", True),
+ ("members", False),
+ ): external("d726cb8367d9*.html"),
+ (("filters", None), ("inherited_members", False), ("members", ())): external("fb770e6537bc*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", True),
+ ("members", None),
+ ): external("2bf34b4dd82e*.html"),
+ (
+ ("filters", ()),
+ ("inherited_members", ("method1",)),
+ ("members", ()),
+ ): external("4892e0fe1920*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ()),
+ ("members", True),
+ ): external("13334b5b4fcf*.html"),
+ (
+ ("filters", ()),
+ ("inherited_members", ()),
+ ("members", ("module_attribute",)),
+ ): external("388a13d71284*.html"),
+ (("filters", None), ("inherited_members", True), ("members", False)): external("3f5d794823a4*.html"),
+ (
+ ("filters", ()),
+ ("inherited_members", True),
+ ("members", ("module_attribute",)),
+ ): external("9d03089a46fa*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", ("module_attribute",)),
+ ): external("8b097c69ac2f*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", False),
+ ("members", True),
+ ): external("cd3e45851714*.html"),
+ (
+ ("filters", None),
+ ("inherited_members", ("method1",)),
+ ("members", False),
+ ): external("e3defc3620e5*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ()),
+ ("members", True),
+ ): external("84193b3c9f5d*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", False),
+ ): external("c6e7ef9564cd*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", False),
+ ("members", None),
+ ): external("62e18d3e5777*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ()),
+ ("members", None),
+ ): external("3935bcf6d71b*.html"),
+ (("filters", None), ("inherited_members", ()), ("members", ())): external("f77f1c850398*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", False),
+ ("members", True),
+ ): external("fe25ab760039*.html"),
+ (("filters", None), ("inherited_members", True), ("members", None)): external("ea914f1afa9d*.html"),
+ (("filters", ()), ("inherited_members", ()), ("members", None)): external("19f98a747c01*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ()),
+ ("members", ()),
+ ): external("c260e7f4ef3b*.html"),
+ (
+ ("filters", ("!module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", True),
+ ): external("9720526cf5e4*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ()),
+ ("members", ("module_attribute",)),
+ ): external("f6e292b8358a*.html"),
+ (("filters", ()), ("inherited_members", True), ("members", False)): external("b0a9b08f1f72*.html"),
+ (("filters", ()), ("inherited_members", ()), ("members", True)): external("027ef7afeffc*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", False),
+ ("members", False),
+ ): external("710706687213*.html"),
+ (("filters", ()), ("inherited_members", ()), ("members", ())): external("11598fec2d07*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ("method1",)),
+ ("members", True),
+ ): external("e8608b0de174*.html"),
+ (
+ ("filters", ()),
+ ("inherited_members", ("method1",)),
+ ("members", None),
+ ): external("e5dc372374af*.html"),
+ (
+ ("filters", ("module_attribute",)),
+ ("inherited_members", ()),
+ ("members", ()),
+ ): external("a185e216dc7b*.html"),
+ (("filters", "public"), ("inherited_members", ("method1",)), ("members", None)): external("6af55596d9c4*.html"),
+ (("filters", "public"), ("inherited_members", ("method1",)), ("members", False)): external(
+ "6abf5ddd819b*.html",
+ ),
+ (("filters", "public"), ("inherited_members", ()), ("members", None)): external("6d72c524b827*.html"),
+ (("filters", "public"), ("inherited_members", False), ("members", False)): external("9dab67183389*.html"),
+ (("filters", "public"), ("inherited_members", ("method1",)), ("members", True)): external("6c0b7207df03*.html"),
+ (("filters", "public"), ("inherited_members", True), ("members", ())): external("f48d651b3f1a*.html"),
+ (("filters", "public"), ("inherited_members", ("method1",)), ("members", ("module_attribute",))): external(
+ "408244423577*.html",
+ ),
+ (("filters", "public"), ("inherited_members", True), ("members", None)): external("16295fa51a2c*.html"),
+ (("filters", "public"), ("inherited_members", True), ("members", True)): external("37232379c426*.html"),
+ (("filters", "public"), ("inherited_members", ()), ("members", ())): external("2e866eca9a45*.html"),
+ (("filters", "public"), ("inherited_members", True), ("members", False)): external("ed5d07bcdbaa*.html"),
+ (("filters", "public"), ("inherited_members", False), ("members", ())): external("135f57223e00*.html"),
+ (("filters", "public"), ("inherited_members", False), ("members", None)): external("b4e20d5cd52e*.html"),
+ (("filters", "public"), ("inherited_members", ()), ("members", False)): external("46daa7e60b98*.html"),
+ (("filters", "public"), ("inherited_members", False), ("members", True)): external("a255ee80bf7a*.html"),
+ (("filters", "public"), ("inherited_members", ()), ("members", True)): external("74e2496015e1*.html"),
+ (("filters", "public"), ("inherited_members", True), ("members", ("module_attribute",))): external(
+ "e254ae60f9af*.html",
+ ),
+ (("filters", "public"), ("inherited_members", ("method1",)), ("members", ())): external("51d73351dc55*.html"),
+ (("filters", "public"), ("inherited_members", ()), ("members", ("module_attribute",))): external(
+ "d56d3aeae22b*.html",
+ ),
+ (("filters", "public"), ("inherited_members", False), ("members", ("module_attribute",))): external(
+ "80399c502938*.html",
+ ),
+ (("heading", ""), ("members", False), ("separate_signature", False), ("show_if_no_docstring", True)): external(
+ "d1dd339f9260*.html",
+ ),
+ (
+ ("heading", "Some heading"),
+ ("members", False),
+ ("separate_signature", True),
+ ("show_if_no_docstring", True),
+ ): external("480324b25439*.html"),
+ (("heading", ""), ("members", False), ("separate_signature", True), ("show_if_no_docstring", True)): external(
+ "2eef87791b97*.html",
+ ),
+ (
+ ("heading", "Some heading"),
+ ("members", False),
+ ("separate_signature", False),
+ ("show_if_no_docstring", True),
+ ): external("51deee0f00f3*.html"),
+ },
+)
diff --git a/tests/snapshots/external/.gitignore b/tests/snapshots/external/.gitignore
new file mode 100644
index 00000000..45bef68b
--- /dev/null
+++ b/tests/snapshots/external/.gitignore
@@ -0,0 +1,2 @@
+# ignore all snapshots which are not refered in the source
+*-new.*
diff --git a/tests/snapshots/external/027ef7afeffc56219a09298c7db30f473c4dfdda12d99a171e9c76098c316067.html b/tests/snapshots/external/027ef7afeffc56219a09298c7db30f473c4dfdda12d99a171e9c76098c316067.html
new file mode 100644
index 00000000..ccfa8d64
--- /dev/null
+++ b/tests/snapshots/external/027ef7afeffc56219a09298c7db30f473c4dfdda12d99a171e9c76098c316067.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/09d96d69d9dcbc54c8189fb885e8e06269c51be673389f29fa8b2d90cff54eb2.html b/tests/snapshots/external/09d96d69d9dcbc54c8189fb885e8e06269c51be673389f29fa8b2d90cff54eb2.html
new file mode 100644
index 00000000..f2597daf
--- /dev/null
+++ b/tests/snapshots/external/09d96d69d9dcbc54c8189fb885e8e06269c51be673389f29fa8b2d90cff54eb2.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/0f046dea611f6c9e90b8eaed720f22af372394971808e2a5d1b3a12286f1ec76.html b/tests/snapshots/external/0f046dea611f6c9e90b8eaed720f22af372394971808e2a5d1b3a12286f1ec76.html
new file mode 100644
index 00000000..332a5c53
--- /dev/null
+++ b/tests/snapshots/external/0f046dea611f6c9e90b8eaed720f22af372394971808e2a5d1b3a12286f1ec76.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/11598fec2d07bb675dfa8a57e49136f18a94eedec6bc5a036dcecc005e70dc80.html b/tests/snapshots/external/11598fec2d07bb675dfa8a57e49136f18a94eedec6bc5a036dcecc005e70dc80.html
new file mode 100644
index 00000000..46cd4aee
--- /dev/null
+++ b/tests/snapshots/external/11598fec2d07bb675dfa8a57e49136f18a94eedec6bc5a036dcecc005e70dc80.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/13334b5b4fcf7267539b9eb99ca2ab79c66766ec6f35383f4bfcb6a8d9e2a116.html b/tests/snapshots/external/13334b5b4fcf7267539b9eb99ca2ab79c66766ec6f35383f4bfcb6a8d9e2a116.html
new file mode 100644
index 00000000..a7eb7dce
--- /dev/null
+++ b/tests/snapshots/external/13334b5b4fcf7267539b9eb99ca2ab79c66766ec6f35383f4bfcb6a8d9e2a116.html
@@ -0,0 +1,132 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/135f57223e006849dcdd1463367127e4c5ee4aba5f12bde17ab3e494dbeed490.html b/tests/snapshots/external/135f57223e006849dcdd1463367127e4c5ee4aba5f12bde17ab3e494dbeed490.html
new file mode 100644
index 00000000..e8d65a7e
--- /dev/null
+++ b/tests/snapshots/external/135f57223e006849dcdd1463367127e4c5ee4aba5f12bde17ab3e494dbeed490.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/14bca0e5703be9cab876200d88cccd1d728d1bdfef7cbfac751af212e00a8663.html b/tests/snapshots/external/14bca0e5703be9cab876200d88cccd1d728d1bdfef7cbfac751af212e00a8663.html
new file mode 100644
index 00000000..b2490df7
--- /dev/null
+++ b/tests/snapshots/external/14bca0e5703be9cab876200d88cccd1d728d1bdfef7cbfac751af212e00a8663.html
@@ -0,0 +1,506 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/16295fa51a2c3a60d1461a9a14093603333f836326a007d8eb061f78ab38a712.html b/tests/snapshots/external/16295fa51a2c3a60d1461a9a14093603333f836326a007d8eb061f78ab38a712.html
new file mode 100644
index 00000000..40c14a7b
--- /dev/null
+++ b/tests/snapshots/external/16295fa51a2c3a60d1461a9a14093603333f836326a007d8eb061f78ab38a712.html
@@ -0,0 +1,506 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/166b8dfab738b90f2ff0df84a048df96539455d9cad42b09b248ab65b5c742e2.html b/tests/snapshots/external/166b8dfab738b90f2ff0df84a048df96539455d9cad42b09b248ab65b5c742e2.html
new file mode 100644
index 00000000..b194ddc9
--- /dev/null
+++ b/tests/snapshots/external/166b8dfab738b90f2ff0df84a048df96539455d9cad42b09b248ab65b5c742e2.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/19f98a747c015a074f3d3362d03ed72f9da9db3aefe969a0d78c4052e7594372.html b/tests/snapshots/external/19f98a747c015a074f3d3362d03ed72f9da9db3aefe969a0d78c4052e7594372.html
new file mode 100644
index 00000000..9058ed13
--- /dev/null
+++ b/tests/snapshots/external/19f98a747c015a074f3d3362d03ed72f9da9db3aefe969a0d78c4052e7594372.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/247a6063b698c285bfef7addfd972ddf797f6a90dfd5a3e649e6e4c127b86562.html b/tests/snapshots/external/247a6063b698c285bfef7addfd972ddf797f6a90dfd5a3e649e6e4c127b86562.html
new file mode 100644
index 00000000..c27a4c82
--- /dev/null
+++ b/tests/snapshots/external/247a6063b698c285bfef7addfd972ddf797f6a90dfd5a3e649e6e4c127b86562.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/26bc66c2ba29feddfbd06c2490eca42ec5a8f62db8d650231b0748ddce8c85f1.html b/tests/snapshots/external/26bc66c2ba29feddfbd06c2490eca42ec5a8f62db8d650231b0748ddce8c85f1.html
new file mode 100644
index 00000000..271501b7
--- /dev/null
+++ b/tests/snapshots/external/26bc66c2ba29feddfbd06c2490eca42ec5a8f62db8d650231b0748ddce8c85f1.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/28d8862dd086c7d523516dd4091b57e5babd34165edccf619b62a06fc1936cd5.html b/tests/snapshots/external/28d8862dd086c7d523516dd4091b57e5babd34165edccf619b62a06fc1936cd5.html
new file mode 100644
index 00000000..06640b9d
--- /dev/null
+++ b/tests/snapshots/external/28d8862dd086c7d523516dd4091b57e5babd34165edccf619b62a06fc1936cd5.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/2bf34b4dd82e753b21200ec980cb197c530710fe8c150c4dd3fbbfb7d38928cc.html b/tests/snapshots/external/2bf34b4dd82e753b21200ec980cb197c530710fe8c150c4dd3fbbfb7d38928cc.html
new file mode 100644
index 00000000..eddcbb25
--- /dev/null
+++ b/tests/snapshots/external/2bf34b4dd82e753b21200ec980cb197c530710fe8c150c4dd3fbbfb7d38928cc.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/2e866eca9a45f82cd1e16bb55bbc2a03bb19548457598bca83141cb375fb1aa3.html b/tests/snapshots/external/2e866eca9a45f82cd1e16bb55bbc2a03bb19548457598bca83141cb375fb1aa3.html
new file mode 100644
index 00000000..ac0222f5
--- /dev/null
+++ b/tests/snapshots/external/2e866eca9a45f82cd1e16bb55bbc2a03bb19548457598bca83141cb375fb1aa3.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/2eef87791b974c724d2cd98e40bb25994087bc836868f63da18557a6094a00ee.html b/tests/snapshots/external/2eef87791b974c724d2cd98e40bb25994087bc836868f63da18557a6094a00ee.html
new file mode 100644
index 00000000..f0242792
--- /dev/null
+++ b/tests/snapshots/external/2eef87791b974c724d2cd98e40bb25994087bc836868f63da18557a6094a00ee.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ headings_package
+
+
+
+
+
+
+
diff --git a/tests/snapshots/external/34b16654e7baa8e16315cef2919f2eafa51ba39ec28c4c970fe7ea8e2c79f9d2.html b/tests/snapshots/external/34b16654e7baa8e16315cef2919f2eafa51ba39ec28c4c970fe7ea8e2c79f9d2.html
new file mode 100644
index 00000000..8357168e
--- /dev/null
+++ b/tests/snapshots/external/34b16654e7baa8e16315cef2919f2eafa51ba39ec28c4c970fe7ea8e2c79f9d2.html
@@ -0,0 +1,508 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/366b0537fe0625a10d55203a3532de5c360e49fb403078a82ec408d829afcb72.html b/tests/snapshots/external/366b0537fe0625a10d55203a3532de5c360e49fb403078a82ec408d829afcb72.html
new file mode 100644
index 00000000..b6a621d2
--- /dev/null
+++ b/tests/snapshots/external/366b0537fe0625a10d55203a3532de5c360e49fb403078a82ec408d829afcb72.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/37232379c426474cc962db72ded419e39c3e416c30e367c8745f3be4e86557a4.html b/tests/snapshots/external/37232379c426474cc962db72ded419e39c3e416c30e367c8745f3be4e86557a4.html
new file mode 100644
index 00000000..13b2239c
--- /dev/null
+++ b/tests/snapshots/external/37232379c426474cc962db72ded419e39c3e416c30e367c8745f3be4e86557a4.html
@@ -0,0 +1,506 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/388a13d71284b1a4b0c457e9c8d1ec60dfefb8871c69ceb1d7a035bd3bdadab8.html b/tests/snapshots/external/388a13d71284b1a4b0c457e9c8d1ec60dfefb8871c69ceb1d7a035bd3bdadab8.html
new file mode 100644
index 00000000..1232ad5e
--- /dev/null
+++ b/tests/snapshots/external/388a13d71284b1a4b0c457e9c8d1ec60dfefb8871c69ceb1d7a035bd3bdadab8.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/3935bcf6d71b58daa0e4512cbf3f53e19516885fb65d0bd760c12aadd021507f.html b/tests/snapshots/external/3935bcf6d71b58daa0e4512cbf3f53e19516885fb65d0bd760c12aadd021507f.html
new file mode 100644
index 00000000..793f43a4
--- /dev/null
+++ b/tests/snapshots/external/3935bcf6d71b58daa0e4512cbf3f53e19516885fb65d0bd760c12aadd021507f.html
@@ -0,0 +1,289 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/3c21330afd6529769164afe388e9385a9fddb3ae628124965e0c7b81932a0c63.html b/tests/snapshots/external/3c21330afd6529769164afe388e9385a9fddb3ae628124965e0c7b81932a0c63.html
new file mode 100644
index 00000000..26cb9e39
--- /dev/null
+++ b/tests/snapshots/external/3c21330afd6529769164afe388e9385a9fddb3ae628124965e0c7b81932a0c63.html
@@ -0,0 +1,132 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/3f5d794823a451ec9d4ed8c7e16d1354d39b74380402b255ee60741e97c9960c.html b/tests/snapshots/external/3f5d794823a451ec9d4ed8c7e16d1354d39b74380402b255ee60741e97c9960c.html
new file mode 100644
index 00000000..8b4491f3
--- /dev/null
+++ b/tests/snapshots/external/3f5d794823a451ec9d4ed8c7e16d1354d39b74380402b255ee60741e97c9960c.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/4041a38e355f6585a7e1265509d7c5b499fe3776aeeeb298db7589bb385ca019.html b/tests/snapshots/external/4041a38e355f6585a7e1265509d7c5b499fe3776aeeeb298db7589bb385ca019.html
new file mode 100644
index 00000000..8454da6d
--- /dev/null
+++ b/tests/snapshots/external/4041a38e355f6585a7e1265509d7c5b499fe3776aeeeb298db7589bb385ca019.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ __init__
+
+
+
+ __init__(a, b)
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+ method1
+
+
+
+ method1(a, b)
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+
+ module_function(a, b)
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/408244423577f9b2598b319118c5f4a0a495116b06ebb2877a0964d526ec18e0.html b/tests/snapshots/external/408244423577f9b2598b319118c5f4a0a495116b06ebb2877a0964d526ec18e0.html
new file mode 100644
index 00000000..befa0078
--- /dev/null
+++ b/tests/snapshots/external/408244423577f9b2598b319118c5f4a0a495116b06ebb2877a0964d526ec18e0.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/42c053a5e567a777dfde62cd0d061112dc8098f90e71f71d5aceba8be188fcf7.html b/tests/snapshots/external/42c053a5e567a777dfde62cd0d061112dc8098f90e71f71d5aceba8be188fcf7.html
new file mode 100644
index 00000000..52ada349
--- /dev/null
+++ b/tests/snapshots/external/42c053a5e567a777dfde62cd0d061112dc8098f90e71f71d5aceba8be188fcf7.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/43d819f94dc7cafe9ed60ce604bab9a938f42a115dc534cb72d12e15e998e96d.html b/tests/snapshots/external/43d819f94dc7cafe9ed60ce604bab9a938f42a115dc534cb72d12e15e998e96d.html
new file mode 100644
index 00000000..ddce47f6
--- /dev/null
+++ b/tests/snapshots/external/43d819f94dc7cafe9ed60ce604bab9a938f42a115dc534cb72d12e15e998e96d.html
@@ -0,0 +1,353 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/44e42f27bfe3d3b5ec14700c247c83195b1c6eea319d1a0679b2baa797d9859c.html b/tests/snapshots/external/44e42f27bfe3d3b5ec14700c247c83195b1c6eea319d1a0679b2baa797d9859c.html
new file mode 100644
index 00000000..2bfbdbf4
--- /dev/null
+++ b/tests/snapshots/external/44e42f27bfe3d3b5ec14700c247c83195b1c6eea319d1a0679b2baa797d9859c.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/46daa7e60b98815685904dd397f0de19cf1a94397d2165418a4f9fec02c7b560.html b/tests/snapshots/external/46daa7e60b98815685904dd397f0de19cf1a94397d2165418a4f9fec02c7b560.html
new file mode 100644
index 00000000..6f76b142
--- /dev/null
+++ b/tests/snapshots/external/46daa7e60b98815685904dd397f0de19cf1a94397d2165418a4f9fec02c7b560.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/480324b25439ea41507fdda100045132d578af0e1df1219c08bc9ea0bea1f39c.html b/tests/snapshots/external/480324b25439ea41507fdda100045132d578af0e1df1219c08bc9ea0bea1f39c.html
new file mode 100644
index 00000000..fd1f953b
--- /dev/null
+++ b/tests/snapshots/external/480324b25439ea41507fdda100045132d578af0e1df1219c08bc9ea0bea1f39c.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Some heading
+
+
+
+
+
+
diff --git a/tests/snapshots/external/4892e0fe1920c0bb22fa4787b6e76cccaa968163b35641d705f288c04fe4937e.html b/tests/snapshots/external/4892e0fe1920c0bb22fa4787b6e76cccaa968163b35641d705f288c04fe4937e.html
new file mode 100644
index 00000000..3b41766d
--- /dev/null
+++ b/tests/snapshots/external/4892e0fe1920c0bb22fa4787b6e76cccaa968163b35641d705f288c04fe4937e.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/4f60da13e2d45e803f73ed41746d8b3570f0dac7e132efb1bf0cdbf77e9e2c59.html b/tests/snapshots/external/4f60da13e2d45e803f73ed41746d8b3570f0dac7e132efb1bf0cdbf77e9e2c59.html
new file mode 100644
index 00000000..7d734fba
--- /dev/null
+++ b/tests/snapshots/external/4f60da13e2d45e803f73ed41746d8b3570f0dac7e132efb1bf0cdbf77e9e2c59.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/51d73351dc5546cefc8087b8409ebb7841c879fb48c875ff4cba6fbadee64014.html b/tests/snapshots/external/51d73351dc5546cefc8087b8409ebb7841c879fb48c875ff4cba6fbadee64014.html
new file mode 100644
index 00000000..f7385cf9
--- /dev/null
+++ b/tests/snapshots/external/51d73351dc5546cefc8087b8409ebb7841c879fb48c875ff4cba6fbadee64014.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/51deee0f00f35b0902f82fb96a36d547a80dfbb41a311dabd94b96fd968b83bc.html b/tests/snapshots/external/51deee0f00f35b0902f82fb96a36d547a80dfbb41a311dabd94b96fd968b83bc.html
new file mode 100644
index 00000000..8601ee01
--- /dev/null
+++ b/tests/snapshots/external/51deee0f00f35b0902f82fb96a36d547a80dfbb41a311dabd94b96fd968b83bc.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Some heading
+
+
+
+
+
+
diff --git a/tests/snapshots/external/5a9c10410801aa75b33878971b939da701df9a7ce8006dc7781c148d27a89756.html b/tests/snapshots/external/5a9c10410801aa75b33878971b939da701df9a7ce8006dc7781c148d27a89756.html
new file mode 100644
index 00000000..8fd78409
--- /dev/null
+++ b/tests/snapshots/external/5a9c10410801aa75b33878971b939da701df9a7ce8006dc7781c148d27a89756.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/5cf0130e3b4fdd536b1c99ee66c66ec4245e286bf75b989cf50979ce187e1a16.html b/tests/snapshots/external/5cf0130e3b4fdd536b1c99ee66c66ec4245e286bf75b989cf50979ce187e1a16.html
new file mode 100644
index 00000000..eb15c707
--- /dev/null
+++ b/tests/snapshots/external/5cf0130e3b4fdd536b1c99ee66c66ec4245e286bf75b989cf50979ce187e1a16.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/62e18d3e57777d911c7fdee1fcc032a9c23ffe82913060e3b66f29bf81a6a585.html b/tests/snapshots/external/62e18d3e57777d911c7fdee1fcc032a9c23ffe82913060e3b66f29bf81a6a585.html
new file mode 100644
index 00000000..1a8842f9
--- /dev/null
+++ b/tests/snapshots/external/62e18d3e57777d911c7fdee1fcc032a9c23ffe82913060e3b66f29bf81a6a585.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/6a02b544c12c68b75d9bf3b85b1800830fd980daabff9df8c3760eb6edea7915.html b/tests/snapshots/external/6a02b544c12c68b75d9bf3b85b1800830fd980daabff9df8c3760eb6edea7915.html
new file mode 100644
index 00000000..70567c97
--- /dev/null
+++ b/tests/snapshots/external/6a02b544c12c68b75d9bf3b85b1800830fd980daabff9df8c3760eb6edea7915.html
@@ -0,0 +1,136 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/6abf5ddd819b832a1593ece448c90e63e13faa4376cca76b4fddc4d52a47f8b0.html b/tests/snapshots/external/6abf5ddd819b832a1593ece448c90e63e13faa4376cca76b4fddc4d52a47f8b0.html
new file mode 100644
index 00000000..e649c2e7
--- /dev/null
+++ b/tests/snapshots/external/6abf5ddd819b832a1593ece448c90e63e13faa4376cca76b4fddc4d52a47f8b0.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/6af55596d9c42d2634baadf77df6060caba2bd9c2d634576378cc18131c0efba.html b/tests/snapshots/external/6af55596d9c42d2634baadf77df6060caba2bd9c2d634576378cc18131c0efba.html
new file mode 100644
index 00000000..5ca6f9fe
--- /dev/null
+++ b/tests/snapshots/external/6af55596d9c42d2634baadf77df6060caba2bd9c2d634576378cc18131c0efba.html
@@ -0,0 +1,353 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/6c0b7207df0351e1d5232859a5c13b72533fb8c87e5dc0e971b185f8dfe38c84.html b/tests/snapshots/external/6c0b7207df0351e1d5232859a5c13b72533fb8c87e5dc0e971b185f8dfe38c84.html
new file mode 100644
index 00000000..a191cb33
--- /dev/null
+++ b/tests/snapshots/external/6c0b7207df0351e1d5232859a5c13b72533fb8c87e5dc0e971b185f8dfe38c84.html
@@ -0,0 +1,353 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/6d12192d6b4dc0633bad697a683a3cdf3b2b9ceeb839044c72c63b469914f0a1.html b/tests/snapshots/external/6d12192d6b4dc0633bad697a683a3cdf3b2b9ceeb839044c72c63b469914f0a1.html
new file mode 100644
index 00000000..93503606
--- /dev/null
+++ b/tests/snapshots/external/6d12192d6b4dc0633bad697a683a3cdf3b2b9ceeb839044c72c63b469914f0a1.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/6d72c524b827a2e4fd84a17b2aecfffca0d05bfa3fc38815f89836607e5a6c92.html b/tests/snapshots/external/6d72c524b827a2e4fd84a17b2aecfffca0d05bfa3fc38815f89836607e5a6c92.html
new file mode 100644
index 00000000..5540be65
--- /dev/null
+++ b/tests/snapshots/external/6d72c524b827a2e4fd84a17b2aecfffca0d05bfa3fc38815f89836607e5a6c92.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/7107066872137b807b3f9d897e75eff78f5783b14d3c88e71c6477eaa8493113.html b/tests/snapshots/external/7107066872137b807b3f9d897e75eff78f5783b14d3c88e71c6477eaa8493113.html
new file mode 100644
index 00000000..27fcc6c1
--- /dev/null
+++ b/tests/snapshots/external/7107066872137b807b3f9d897e75eff78f5783b14d3c88e71c6477eaa8493113.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/722165bce3ada19df43b169ea982ab4908d94cd1bf19b777e1e6bc22e8aa02a5.html b/tests/snapshots/external/722165bce3ada19df43b169ea982ab4908d94cd1bf19b777e1e6bc22e8aa02a5.html
new file mode 100644
index 00000000..7c65c72b
--- /dev/null
+++ b/tests/snapshots/external/722165bce3ada19df43b169ea982ab4908d94cd1bf19b777e1e6bc22e8aa02a5.html
@@ -0,0 +1,506 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/735fc6ffdb82ce35cdab2aed2389a630e4d2c7ad95308bc5c7a56a8a8930b37f.html b/tests/snapshots/external/735fc6ffdb82ce35cdab2aed2389a630e4d2c7ad95308bc5c7a56a8a8930b37f.html
new file mode 100644
index 00000000..44516fe5
--- /dev/null
+++ b/tests/snapshots/external/735fc6ffdb82ce35cdab2aed2389a630e4d2c7ad95308bc5c7a56a8a8930b37f.html
@@ -0,0 +1,190 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ :
+
+
+ int
+
+
+ ,
+
+
+ b
+
+
+ :
+
+
+ str
+
+
+ )
+
+
+ ->
+
+
+ None
+
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ :
+
+
+ int
+
+
+ ,
+
+
+ b
+
+
+ :
+
+
+ str
+
+
+ )
+
+
+ ->
+
+
+ None
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ :
+
+
+ int
+
+
+ ,
+
+
+ b
+
+
+ :
+
+
+ str
+
+
+ )
+
+
+ ->
+
+
+ None
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/74bfab19cbd4ba02673f6b9ee736a3b6727936de92f73f299ba238491f619937.html b/tests/snapshots/external/74bfab19cbd4ba02673f6b9ee736a3b6727936de92f73f299ba238491f619937.html
new file mode 100644
index 00000000..3ae3af4d
--- /dev/null
+++ b/tests/snapshots/external/74bfab19cbd4ba02673f6b9ee736a3b6727936de92f73f299ba238491f619937.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/74e2496015e194b88a30c9d0a4d9309bf74c122d1d24aecaa4d9c9c392057d1a.html b/tests/snapshots/external/74e2496015e194b88a30c9d0a4d9309bf74c122d1d24aecaa4d9c9c392057d1a.html
new file mode 100644
index 00000000..7d596388
--- /dev/null
+++ b/tests/snapshots/external/74e2496015e194b88a30c9d0a4d9309bf74c122d1d24aecaa4d9c9c392057d1a.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/74ee37cd1e94250baa33050af088e7341495708d879ab45ee9e8ab1dcac26f2a.html b/tests/snapshots/external/74ee37cd1e94250baa33050af088e7341495708d879ab45ee9e8ab1dcac26f2a.html
new file mode 100644
index 00000000..9edcf4c5
--- /dev/null
+++ b/tests/snapshots/external/74ee37cd1e94250baa33050af088e7341495708d879ab45ee9e8ab1dcac26f2a.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ __init__
+
+
+
+ __init__(a: int, b: str) -> None
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+ method1
+
+
+
+ method1(a: int, b: str) -> None
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+
+ module_function(a: int, b: str) -> None
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/75b69b702f3b5fa3bc0d30091297b0a09a8915eb7f0e1f7be1ce99f5d59d9514.html b/tests/snapshots/external/75b69b702f3b5fa3bc0d30091297b0a09a8915eb7f0e1f7be1ce99f5d59d9514.html
new file mode 100644
index 00000000..fa970eca
--- /dev/null
+++ b/tests/snapshots/external/75b69b702f3b5fa3bc0d30091297b0a09a8915eb7f0e1f7be1ce99f5d59d9514.html
@@ -0,0 +1,353 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/76ee8e01e1c0b94de84d79da8443bc24f601f89cab70eae1b2af5ee21cfb1f3a.html b/tests/snapshots/external/76ee8e01e1c0b94de84d79da8443bc24f601f89cab70eae1b2af5ee21cfb1f3a.html
new file mode 100644
index 00000000..bed00768
--- /dev/null
+++ b/tests/snapshots/external/76ee8e01e1c0b94de84d79da8443bc24f601f89cab70eae1b2af5ee21cfb1f3a.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/80399c502938940d34e928b35648146970dc524534fe2e7f7127ccb32e3067d0.html b/tests/snapshots/external/80399c502938940d34e928b35648146970dc524534fe2e7f7127ccb32e3067d0.html
new file mode 100644
index 00000000..e40923d9
--- /dev/null
+++ b/tests/snapshots/external/80399c502938940d34e928b35648146970dc524534fe2e7f7127ccb32e3067d0.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/84193b3c9f5d84fef33daa61fb61aa9a3e66171d312de8d7f836c69f0bc069b0.html b/tests/snapshots/external/84193b3c9f5d84fef33daa61fb61aa9a3e66171d312de8d7f836c69f0bc069b0.html
new file mode 100644
index 00000000..07120341
--- /dev/null
+++ b/tests/snapshots/external/84193b3c9f5d84fef33daa61fb61aa9a3e66171d312de8d7f836c69f0bc069b0.html
@@ -0,0 +1,320 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/8733f7fb7b6d28b15bbe736f29c7fd030467c0ccfa2cbc6a68616e06c6dc6a9b.html b/tests/snapshots/external/8733f7fb7b6d28b15bbe736f29c7fd030467c0ccfa2cbc6a68616e06c6dc6a9b.html
new file mode 100644
index 00000000..cb43eee6
--- /dev/null
+++ b/tests/snapshots/external/8733f7fb7b6d28b15bbe736f29c7fd030467c0ccfa2cbc6a68616e06c6dc6a9b.html
@@ -0,0 +1,477 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/8b097c69ac2fd52857f33e1b008f4d99a53ed21894c51517b3d79da445b0a705.html b/tests/snapshots/external/8b097c69ac2fd52857f33e1b008f4d99a53ed21894c51517b3d79da445b0a705.html
new file mode 100644
index 00000000..e908da32
--- /dev/null
+++ b/tests/snapshots/external/8b097c69ac2fd52857f33e1b008f4d99a53ed21894c51517b3d79da445b0a705.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/8d4e1f9af9971bd21234c7c45dfbd59a1aee444bfa0cd3b9cfb6d052d378a041.html b/tests/snapshots/external/8d4e1f9af9971bd21234c7c45dfbd59a1aee444bfa0cd3b9cfb6d052d378a041.html
new file mode 100644
index 00000000..eb755e52
--- /dev/null
+++ b/tests/snapshots/external/8d4e1f9af9971bd21234c7c45dfbd59a1aee444bfa0cd3b9cfb6d052d378a041.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/95f8e480937f7a2b956392ed4d8058052d9748874cdd911feacdd31d1abe5d97.html b/tests/snapshots/external/95f8e480937f7a2b956392ed4d8058052d9748874cdd911feacdd31d1abe5d97.html
new file mode 100644
index 00000000..f827f125
--- /dev/null
+++ b/tests/snapshots/external/95f8e480937f7a2b956392ed4d8058052d9748874cdd911feacdd31d1abe5d97.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/96cf94f4822a5cf5d72407eab5a5dddda972f16623f7710f738ffe2bcf9130d9.html b/tests/snapshots/external/96cf94f4822a5cf5d72407eab5a5dddda972f16623f7710f738ffe2bcf9130d9.html
new file mode 100644
index 00000000..9aa9c3c1
--- /dev/null
+++ b/tests/snapshots/external/96cf94f4822a5cf5d72407eab5a5dddda972f16623f7710f738ffe2bcf9130d9.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/9720526cf5e4c44f27695c59764bb1e05e428834744442f43527ebf2b8acfb35.html b/tests/snapshots/external/9720526cf5e4c44f27695c59764bb1e05e428834744442f43527ebf2b8acfb35.html
new file mode 100644
index 00000000..6d460dd2
--- /dev/null
+++ b/tests/snapshots/external/9720526cf5e4c44f27695c59764bb1e05e428834744442f43527ebf2b8acfb35.html
@@ -0,0 +1,355 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/9bd282a6f2fe82f3ffe66b175bf90ab3e808e3a67f3c15a9f9e3e143d7956e49.html b/tests/snapshots/external/9bd282a6f2fe82f3ffe66b175bf90ab3e808e3a67f3c15a9f9e3e143d7956e49.html
new file mode 100644
index 00000000..ce4ee8a7
--- /dev/null
+++ b/tests/snapshots/external/9bd282a6f2fe82f3ffe66b175bf90ab3e808e3a67f3c15a9f9e3e143d7956e49.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/9d03089a46fab9a86b0836444cabb6225798eaf25be6fd4171bd73b7354509b6.html b/tests/snapshots/external/9d03089a46fab9a86b0836444cabb6225798eaf25be6fd4171bd73b7354509b6.html
new file mode 100644
index 00000000..0ee900fb
--- /dev/null
+++ b/tests/snapshots/external/9d03089a46fab9a86b0836444cabb6225798eaf25be6fd4171bd73b7354509b6.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/9dab67183389335dadba724875c80c49909904aa135e65c6c411c3a903d458da.html b/tests/snapshots/external/9dab67183389335dadba724875c80c49909904aa135e65c6c411c3a903d458da.html
new file mode 100644
index 00000000..12da79f0
--- /dev/null
+++ b/tests/snapshots/external/9dab67183389335dadba724875c80c49909904aa135e65c6c411c3a903d458da.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/a185e216dc7b7ebb31b46ea0e7ed446cf9da94eee8db306f08bae1ca0db0ca1d.html b/tests/snapshots/external/a185e216dc7b7ebb31b46ea0e7ed446cf9da94eee8db306f08bae1ca0db0ca1d.html
new file mode 100644
index 00000000..a0685468
--- /dev/null
+++ b/tests/snapshots/external/a185e216dc7b7ebb31b46ea0e7ed446cf9da94eee8db306f08bae1ca0db0ca1d.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/a200913d9a7d51c52ab58f6fc4e9ea7be278d7890c46cf28ecc3cfd35a36fb46.html b/tests/snapshots/external/a200913d9a7d51c52ab58f6fc4e9ea7be278d7890c46cf28ecc3cfd35a36fb46.html
new file mode 100644
index 00000000..96cff9d7
--- /dev/null
+++ b/tests/snapshots/external/a200913d9a7d51c52ab58f6fc4e9ea7be278d7890c46cf28ecc3cfd35a36fb46.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/a255ee80bf7a569ab3aa55ea94af24ce6671dace3d6075df5d14a3ff428ceb8b.html b/tests/snapshots/external/a255ee80bf7a569ab3aa55ea94af24ce6671dace3d6075df5d14a3ff428ceb8b.html
new file mode 100644
index 00000000..1973e99b
--- /dev/null
+++ b/tests/snapshots/external/a255ee80bf7a569ab3aa55ea94af24ce6671dace3d6075df5d14a3ff428ceb8b.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/ab0ddac637b536c06014746a4a8f8e0921b074015ae19680abf5df995c233ba1.html b/tests/snapshots/external/ab0ddac637b536c06014746a4a8f8e0921b074015ae19680abf5df995c233ba1.html
new file mode 100644
index 00000000..3933bd9d
--- /dev/null
+++ b/tests/snapshots/external/ab0ddac637b536c06014746a4a8f8e0921b074015ae19680abf5df995c233ba1.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/afd5c166367dd47e4f9843d906b3a1ad12398888fdad84bfbda3de8b19072611.html b/tests/snapshots/external/afd5c166367dd47e4f9843d906b3a1ad12398888fdad84bfbda3de8b19072611.html
new file mode 100644
index 00000000..8501bce2
--- /dev/null
+++ b/tests/snapshots/external/afd5c166367dd47e4f9843d906b3a1ad12398888fdad84bfbda3de8b19072611.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/b060b701543e5503dc848538a164e80480ab25f8885aa83b97776e6b0cc6b570.html b/tests/snapshots/external/b060b701543e5503dc848538a164e80480ab25f8885aa83b97776e6b0cc6b570.html
new file mode 100644
index 00000000..599197fe
--- /dev/null
+++ b/tests/snapshots/external/b060b701543e5503dc848538a164e80480ab25f8885aa83b97776e6b0cc6b570.html
@@ -0,0 +1,136 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/b0a9b08f1f721721c4dd110cb8f85ffda5caf1f1479851275bc227857fb01400.html b/tests/snapshots/external/b0a9b08f1f721721c4dd110cb8f85ffda5caf1f1479851275bc227857fb01400.html
new file mode 100644
index 00000000..bbd48b9e
--- /dev/null
+++ b/tests/snapshots/external/b0a9b08f1f721721c4dd110cb8f85ffda5caf1f1479851275bc227857fb01400.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/b4e20d5cd52e746cc7473537a2318a9ad886c5d8d8654c8d4f85fe209b04d86b.html b/tests/snapshots/external/b4e20d5cd52e746cc7473537a2318a9ad886c5d8d8654c8d4f85fe209b04d86b.html
new file mode 100644
index 00000000..39cf1b20
--- /dev/null
+++ b/tests/snapshots/external/b4e20d5cd52e746cc7473537a2318a9ad886c5d8d8654c8d4f85fe209b04d86b.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/bd6594ae3b516bf84cd0b0e6605087f430f62d787c32225ac8b4039c92e20b76.html b/tests/snapshots/external/bd6594ae3b516bf84cd0b0e6605087f430f62d787c32225ac8b4039c92e20b76.html
new file mode 100644
index 00000000..aa4ebf15
--- /dev/null
+++ b/tests/snapshots/external/bd6594ae3b516bf84cd0b0e6605087f430f62d787c32225ac8b4039c92e20b76.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/c0f102dbd7d4de76de40c06a8205a642465f5fde9a37b4b969aa01f161ef25a4.html b/tests/snapshots/external/c0f102dbd7d4de76de40c06a8205a642465f5fde9a37b4b969aa01f161ef25a4.html
new file mode 100644
index 00000000..e9f375b2
--- /dev/null
+++ b/tests/snapshots/external/c0f102dbd7d4de76de40c06a8205a642465f5fde9a37b4b969aa01f161ef25a4.html
@@ -0,0 +1,506 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/c260e7f4ef3b8b228bb25879d3adcf6610f1c2c971c9c46b5665d276716b8821.html b/tests/snapshots/external/c260e7f4ef3b8b228bb25879d3adcf6610f1c2c971c9c46b5665d276716b8821.html
new file mode 100644
index 00000000..fb55bdd1
--- /dev/null
+++ b/tests/snapshots/external/c260e7f4ef3b8b228bb25879d3adcf6610f1c2c971c9c46b5665d276716b8821.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/c6e7ef9564cdc8449a98c0ef790d652dee02c47b1339f858fc1d7a54aae9ed46.html b/tests/snapshots/external/c6e7ef9564cdc8449a98c0ef790d652dee02c47b1339f858fc1d7a54aae9ed46.html
new file mode 100644
index 00000000..e96d72c3
--- /dev/null
+++ b/tests/snapshots/external/c6e7ef9564cdc8449a98c0ef790d652dee02c47b1339f858fc1d7a54aae9ed46.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/c915eb92fd5dcc4e2c9da41ca72c726e65fcd85804942be0c67b4f05f452a549.html b/tests/snapshots/external/c915eb92fd5dcc4e2c9da41ca72c726e65fcd85804942be0c67b4f05f452a549.html
new file mode 100644
index 00000000..26f0f5ef
--- /dev/null
+++ b/tests/snapshots/external/c915eb92fd5dcc4e2c9da41ca72c726e65fcd85804942be0c67b4f05f452a549.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/c9a15552eed32a233795c2086a7c766ad95e05197d30d881540fbe52cdc07ff8.html b/tests/snapshots/external/c9a15552eed32a233795c2086a7c766ad95e05197d30d881540fbe52cdc07ff8.html
new file mode 100644
index 00000000..79a5ff40
--- /dev/null
+++ b/tests/snapshots/external/c9a15552eed32a233795c2086a7c766ad95e05197d30d881540fbe52cdc07ff8.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/cd3e458517147c43c360525140aa1b9a81682634aaf2674ffd4cceb7fc44aba6.html b/tests/snapshots/external/cd3e458517147c43c360525140aa1b9a81682634aaf2674ffd4cceb7fc44aba6.html
new file mode 100644
index 00000000..e196b599
--- /dev/null
+++ b/tests/snapshots/external/cd3e458517147c43c360525140aa1b9a81682634aaf2674ffd4cceb7fc44aba6.html
@@ -0,0 +1,132 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/cd51e40cc0ddf1d42b7c6bf7560ead2501370ee9d67499b74afc83e258caff8e.html b/tests/snapshots/external/cd51e40cc0ddf1d42b7c6bf7560ead2501370ee9d67499b74afc83e258caff8e.html
new file mode 100644
index 00000000..a52964c3
--- /dev/null
+++ b/tests/snapshots/external/cd51e40cc0ddf1d42b7c6bf7560ead2501370ee9d67499b74afc83e258caff8e.html
@@ -0,0 +1,353 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/ce06da7f07b34e4f9071c5c001a8626f2d5fd8eed9a3ba81abebd76f8afc6861.html b/tests/snapshots/external/ce06da7f07b34e4f9071c5c001a8626f2d5fd8eed9a3ba81abebd76f8afc6861.html
new file mode 100644
index 00000000..898bab70
--- /dev/null
+++ b/tests/snapshots/external/ce06da7f07b34e4f9071c5c001a8626f2d5fd8eed9a3ba81abebd76f8afc6861.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/cfcd41685591bcc497f9d1e9fd20006fc3acd857f068e78e6d1c2461bbd4063f.html b/tests/snapshots/external/cfcd41685591bcc497f9d1e9fd20006fc3acd857f068e78e6d1c2461bbd4063f.html
new file mode 100644
index 00000000..d543f794
--- /dev/null
+++ b/tests/snapshots/external/cfcd41685591bcc497f9d1e9fd20006fc3acd857f068e78e6d1c2461bbd4063f.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/d03d16d1919af01db9b8d4e5bf36b007810eb3730a7283624a4d68c6fe2ce652.html b/tests/snapshots/external/d03d16d1919af01db9b8d4e5bf36b007810eb3730a7283624a4d68c6fe2ce652.html
new file mode 100644
index 00000000..03d9e14d
--- /dev/null
+++ b/tests/snapshots/external/d03d16d1919af01db9b8d4e5bf36b007810eb3730a7283624a4d68c6fe2ce652.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ __init__
+
+
+
+ __init__(a, b)
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+ method1
+
+
+
+ method1(a, b)
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+
+ module_function(a, b)
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/d1216ebf8e30ec559861678318efb45bef54a847517e5d90e130818c2a06b163.html b/tests/snapshots/external/d1216ebf8e30ec559861678318efb45bef54a847517e5d90e130818c2a06b163.html
new file mode 100644
index 00000000..65e87e01
--- /dev/null
+++ b/tests/snapshots/external/d1216ebf8e30ec559861678318efb45bef54a847517e5d90e130818c2a06b163.html
@@ -0,0 +1,190 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ :
+
+
+ int
+
+
+ ,
+
+
+ b
+
+
+ :
+
+
+ str
+
+
+ )
+
+
+ ->
+
+
+ None
+
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ :
+
+
+ int
+
+
+ ,
+
+
+ b
+
+
+ :
+
+
+ str
+
+
+ )
+
+
+ ->
+
+
+ None
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ :
+
+
+ int
+
+
+ ,
+
+
+ b
+
+
+ :
+
+
+ str
+
+
+ )
+
+
+ ->
+
+
+ None
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/d1dd339f926026210ea46cc75922a8236f43cade477f95e4ce4c9a60248f0a10.html b/tests/snapshots/external/d1dd339f926026210ea46cc75922a8236f43cade477f95e4ce4c9a60248f0a10.html
new file mode 100644
index 00000000..a9dd1e61
--- /dev/null
+++ b/tests/snapshots/external/d1dd339f926026210ea46cc75922a8236f43cade477f95e4ce4c9a60248f0a10.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ headings_package
+
+
+
+
+
+
+
diff --git a/tests/snapshots/external/d556527026068280df9b77db277472320842cb1ae6099ac3cf558031afda6d2e.html b/tests/snapshots/external/d556527026068280df9b77db277472320842cb1ae6099ac3cf558031afda6d2e.html
new file mode 100644
index 00000000..5a87832a
--- /dev/null
+++ b/tests/snapshots/external/d556527026068280df9b77db277472320842cb1ae6099ac3cf558031afda6d2e.html
@@ -0,0 +1,289 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/d56d3aeae22be9b2494a085b812f0a3a5fabdbef184198de0462a0b944393891.html b/tests/snapshots/external/d56d3aeae22be9b2494a085b812f0a3a5fabdbef184198de0462a0b944393891.html
new file mode 100644
index 00000000..c8211de8
--- /dev/null
+++ b/tests/snapshots/external/d56d3aeae22be9b2494a085b812f0a3a5fabdbef184198de0462a0b944393891.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/d5a6bf59c663338bef9fdc2391f482aee444228e86e23357c11881498e711bb2.html b/tests/snapshots/external/d5a6bf59c663338bef9fdc2391f482aee444228e86e23357c11881498e711bb2.html
new file mode 100644
index 00000000..23e66fd7
--- /dev/null
+++ b/tests/snapshots/external/d5a6bf59c663338bef9fdc2391f482aee444228e86e23357c11881498e711bb2.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/d726cb8367d95b67ce78e718e88ee528d3abc2fbd04413d1c11916a243d7567a.html b/tests/snapshots/external/d726cb8367d95b67ce78e718e88ee528d3abc2fbd04413d1c11916a243d7567a.html
new file mode 100644
index 00000000..1f45fb80
--- /dev/null
+++ b/tests/snapshots/external/d726cb8367d95b67ce78e718e88ee528d3abc2fbd04413d1c11916a243d7567a.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/dcf34c2f72697f7a4700e4a1f048d601f374eab35eea68c9beb8bab8fc269aed.html b/tests/snapshots/external/dcf34c2f72697f7a4700e4a1f048d601f374eab35eea68c9beb8bab8fc269aed.html
new file mode 100644
index 00000000..2d79edd5
--- /dev/null
+++ b/tests/snapshots/external/dcf34c2f72697f7a4700e4a1f048d601f374eab35eea68c9beb8bab8fc269aed.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/e254ae60f9af14754001bc63b74a3c473f5198cf2a58f4d30ad6d5a4c196e67c.html b/tests/snapshots/external/e254ae60f9af14754001bc63b74a3c473f5198cf2a58f4d30ad6d5a4c196e67c.html
new file mode 100644
index 00000000..7b0e60a5
--- /dev/null
+++ b/tests/snapshots/external/e254ae60f9af14754001bc63b74a3c473f5198cf2a58f4d30ad6d5a4c196e67c.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/e3defc3620e5fee20f9400c33b7b541fde66297f257d9baf1b0f94b3ea49e6e0.html b/tests/snapshots/external/e3defc3620e5fee20f9400c33b7b541fde66297f257d9baf1b0f94b3ea49e6e0.html
new file mode 100644
index 00000000..8c035cc8
--- /dev/null
+++ b/tests/snapshots/external/e3defc3620e5fee20f9400c33b7b541fde66297f257d9baf1b0f94b3ea49e6e0.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/e412376be64f25f3f5d2264400a83a1e693c146feec7c359855c676c4a586392.html b/tests/snapshots/external/e412376be64f25f3f5d2264400a83a1e693c146feec7c359855c676c4a586392.html
new file mode 100644
index 00000000..e9ac18ce
--- /dev/null
+++ b/tests/snapshots/external/e412376be64f25f3f5d2264400a83a1e693c146feec7c359855c676c4a586392.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+ signature_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ __init__
+
+
+
+ __init__(a: int , b: str ) -> None
+
+
+
+
+ Docstring for `Class.
+
+ init
+
+ .
+
+
+
+
+
+
+ method1
+
+
+
+ method1(a: int , b: str ) -> None
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+
+ module_function(a: int , b: str ) -> None
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/e5dc372374af6f90a5d456d8683aacdf81104137ce91bd6d4121827f8d989d96.html b/tests/snapshots/external/e5dc372374af6f90a5d456d8683aacdf81104137ce91bd6d4121827f8d989d96.html
new file mode 100644
index 00000000..d9ae307d
--- /dev/null
+++ b/tests/snapshots/external/e5dc372374af6f90a5d456d8683aacdf81104137ce91bd6d4121827f8d989d96.html
@@ -0,0 +1,353 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/e8608b0de174402ca18f88ed58849312158c22f5bfdc845d2da02055fe14853c.html b/tests/snapshots/external/e8608b0de174402ca18f88ed58849312158c22f5bfdc845d2da02055fe14853c.html
new file mode 100644
index 00000000..795378be
--- /dev/null
+++ b/tests/snapshots/external/e8608b0de174402ca18f88ed58849312158c22f5bfdc845d2da02055fe14853c.html
@@ -0,0 +1,167 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/e90c3e0c85ddaa068f3d063c6a1ef718bb3ae2092760b707e838fb73164b3720.html b/tests/snapshots/external/e90c3e0c85ddaa068f3d063c6a1ef718bb3ae2092760b707e838fb73164b3720.html
new file mode 100644
index 00000000..a6ee2831
--- /dev/null
+++ b/tests/snapshots/external/e90c3e0c85ddaa068f3d063c6a1ef718bb3ae2092760b707e838fb73164b3720.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/ea914f1afa9de4b5eddc9792c2b6a5d8de367274278976092bb824e99e523ca5.html b/tests/snapshots/external/ea914f1afa9de4b5eddc9792c2b6a5d8de367274278976092bb824e99e523ca5.html
new file mode 100644
index 00000000..68c7d720
--- /dev/null
+++ b/tests/snapshots/external/ea914f1afa9de4b5eddc9792c2b6a5d8de367274278976092bb824e99e523ca5.html
@@ -0,0 +1,506 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/eac5bee59a9ee0a64602fd6bb8f4f54cb5f3543aa321169921326288a61f556c.html b/tests/snapshots/external/eac5bee59a9ee0a64602fd6bb8f4f54cb5f3543aa321169921326288a61f556c.html
new file mode 100644
index 00000000..7c90168c
--- /dev/null
+++ b/tests/snapshots/external/eac5bee59a9ee0a64602fd6bb8f4f54cb5f3543aa321169921326288a61f556c.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/ed5d07bcdbaa3f295c0cb1544d54b196728ed6c70f4d6c902991baca6f16193c.html b/tests/snapshots/external/ed5d07bcdbaa3f295c0cb1544d54b196728ed6c70f4d6c902991baca6f16193c.html
new file mode 100644
index 00000000..85cb268c
--- /dev/null
+++ b/tests/snapshots/external/ed5d07bcdbaa3f295c0cb1544d54b196728ed6c70f4d6c902991baca6f16193c.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/eee65d3705a655eec6512c4aa09d55f5d2e7c62dd245fed4b3f002a5e9a4d646.html b/tests/snapshots/external/eee65d3705a655eec6512c4aa09d55f5d2e7c62dd245fed4b3f002a5e9a4d646.html
new file mode 100644
index 00000000..53b5e455
--- /dev/null
+++ b/tests/snapshots/external/eee65d3705a655eec6512c4aa09d55f5d2e7c62dd245fed4b3f002a5e9a4d646.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/f0014d9505eceb38ba1e36c380a97ebe4d43669929ec1cdedba4d418899aecc7.html b/tests/snapshots/external/f0014d9505eceb38ba1e36c380a97ebe4d43669929ec1cdedba4d418899aecc7.html
new file mode 100644
index 00000000..5fbd6650
--- /dev/null
+++ b/tests/snapshots/external/f0014d9505eceb38ba1e36c380a97ebe4d43669929ec1cdedba4d418899aecc7.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/f3f3acb6b51ba98f5a06e7c62e85b791b6521504f19a8d7496592dee59c7f199.html b/tests/snapshots/external/f3f3acb6b51ba98f5a06e7c62e85b791b6521504f19a8d7496592dee59c7f199.html
new file mode 100644
index 00000000..48c42b3d
--- /dev/null
+++ b/tests/snapshots/external/f3f3acb6b51ba98f5a06e7c62e85b791b6521504f19a8d7496592dee59c7f199.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/f4150843096a1371b097478f8d67062e3d45ab9f6a8f97e79ae62d32abc5e22a.html b/tests/snapshots/external/f4150843096a1371b097478f8d67062e3d45ab9f6a8f97e79ae62d32abc5e22a.html
new file mode 100644
index 00000000..cce2be49
--- /dev/null
+++ b/tests/snapshots/external/f4150843096a1371b097478f8d67062e3d45ab9f6a8f97e79ae62d32abc5e22a.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/f48d651b3f1a2ce91910e05f4c3f7a7ec95e7d0e88d4503f101610d74029ce23.html b/tests/snapshots/external/f48d651b3f1a2ce91910e05f4c3f7a7ec95e7d0e88d4503f101610d74029ce23.html
new file mode 100644
index 00000000..e8f0258e
--- /dev/null
+++ b/tests/snapshots/external/f48d651b3f1a2ce91910e05f4c3f7a7ec95e7d0e88d4503f101610d74029ce23.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/f6e292b8358a04e3471ba11c8820307076be3cf83b0a9ec2fb5c949324b7e172.html b/tests/snapshots/external/f6e292b8358a04e3471ba11c8820307076be3cf83b0a9ec2fb5c949324b7e172.html
new file mode 100644
index 00000000..79900273
--- /dev/null
+++ b/tests/snapshots/external/f6e292b8358a04e3471ba11c8820307076be3cf83b0a9ec2fb5c949324b7e172.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/f77f1c850398f972a7ae2229f918ba497874115be6c5e9431838b4bb6931b2f4.html b/tests/snapshots/external/f77f1c850398f972a7ae2229f918ba497874115be6c5e9431838b4bb6931b2f4.html
new file mode 100644
index 00000000..4be85a18
--- /dev/null
+++ b/tests/snapshots/external/f77f1c850398f972a7ae2229f918ba497874115be6c5e9431838b4bb6931b2f4.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/f8f32ea6a0c80a63854f8c8d78b3706797feb3042ac88c8fcf0a6da277eddb9d.html b/tests/snapshots/external/f8f32ea6a0c80a63854f8c8d78b3706797feb3042ac88c8fcf0a6da277eddb9d.html
new file mode 100644
index 00000000..d1e4f8bd
--- /dev/null
+++ b/tests/snapshots/external/f8f32ea6a0c80a63854f8c8d78b3706797feb3042ac88c8fcf0a6da277eddb9d.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/fb5ebb7546d8d63744d7e6713ab5317b8c3d00d1108d28d7ef2949994b41dcbd.html b/tests/snapshots/external/fb5ebb7546d8d63744d7e6713ab5317b8c3d00d1108d28d7ef2949994b41dcbd.html
new file mode 100644
index 00000000..ec61d8e3
--- /dev/null
+++ b/tests/snapshots/external/fb5ebb7546d8d63744d7e6713ab5317b8c3d00d1108d28d7ef2949994b41dcbd.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/fb770e6537bc1b98c0de03db7810404967562a2ffd1700ca35c9788949ca55c0.html b/tests/snapshots/external/fb770e6537bc1b98c0de03db7810404967562a2ffd1700ca35c9788949ca55c0.html
new file mode 100644
index 00000000..0ed1d57b
--- /dev/null
+++ b/tests/snapshots/external/fb770e6537bc1b98c0de03db7810404967562a2ffd1700ca35c9788949ca55c0.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/fba0d78ae23e4f52b5e6f0fe003ea3edf681a937f647b11925e9932006648a11.html b/tests/snapshots/external/fba0d78ae23e4f52b5e6f0fe003ea3edf681a937f647b11925e9932006648a11.html
new file mode 100644
index 00000000..ff8087d4
--- /dev/null
+++ b/tests/snapshots/external/fba0d78ae23e4f52b5e6f0fe003ea3edf681a937f647b11925e9932006648a11.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/external/fca72854c849dc68c3ad072a41c32f926f95c6e88775f3e2eeaa63138d99837c.html b/tests/snapshots/external/fca72854c849dc68c3ad072a41c32f926f95c6e88775f3e2eeaa63138d99837c.html
new file mode 100644
index 00000000..d6c51063
--- /dev/null
+++ b/tests/snapshots/external/fca72854c849dc68c3ad072a41c32f926f95c6e88775f3e2eeaa63138d99837c.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/fd291f98ca28b8f15b5a8ed6a2608bacf5b5322599bcbf0544ef8e9c0a27870b.html b/tests/snapshots/external/fd291f98ca28b8f15b5a8ed6a2608bacf5b5322599bcbf0544ef8e9c0a27870b.html
new file mode 100644
index 00000000..91614cf0
--- /dev/null
+++ b/tests/snapshots/external/fd291f98ca28b8f15b5a8ed6a2608bacf5b5322599bcbf0544ef8e9c0a27870b.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/fe1cd23642d405d0b2a4d29ec4a2125f55b54f90c2440ee2d856540415e77745.html b/tests/snapshots/external/fe1cd23642d405d0b2a4d29ec4a2125f55b54f90c2440ee2d856540415e77745.html
new file mode 100644
index 00000000..dce4e148
--- /dev/null
+++ b/tests/snapshots/external/fe1cd23642d405d0b2a4d29ec4a2125f55b54f90c2440ee2d856540415e77745.html
@@ -0,0 +1,324 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/external/fe25ab7600392b4fd3a1438fb54337041719faac884123527bab9a92e3a51be5.html b/tests/snapshots/external/fe25ab7600392b4fd3a1438fb54337041719faac884123527bab9a92e3a51be5.html
new file mode 100644
index 00000000..40ebfa36
--- /dev/null
+++ b/tests/snapshots/external/fe25ab7600392b4fd3a1438fb54337041719faac884123527bab9a92e3a51be5.html
@@ -0,0 +1,320 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
+
+ module_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ module-attribute
+
+
+
+
+
+
+ Docstring for
+
+ module_attribute
+
+ .
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ class_attribute
+
+
+ =
+
+
+ 42
+
+
+
+
+
+ class-attribute
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.class_attribute
+
+ .
+
+
+
+
+
+
+
+ instance_attribute
+
+
+ =
+
+
+ a
+
+
+ +
+
+
+ b
+
+
+
+
+
+ instance-attribute
+
+
+
+
+
+
+ Docstring for
+
+ Class.instance_attribute
+
+ .
+
+
+
+
+
+
+ NestedClass
+
+
+
+
+ Docstring for
+
+ NestedClass
+
+ .
+
+
+
+
+
+
+
+ __init__
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.__init__
+
+ .
+
+
+
+
+
+
+
+ method1
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method1
+
+ .
+
+
+
+
+
+
+
+ method2
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.method2
+
+ .
+
+
+
+
+
+
+
+
+
+ Subclass
+
+
+
+
+ Bases:
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Subclass
+
+ .
+
+
+
+
+
+
+
+
+
+ module_function
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ module_function
+
+ .
+
+
+
+
+
+
diff --git a/tests/test_api.py b/tests/test_api.py
new file mode 100644
index 00000000..6d0b8738
--- /dev/null
+++ b/tests/test_api.py
@@ -0,0 +1,190 @@
+"""Tests for our own API exposition."""
+
+from __future__ import annotations
+
+from collections import defaultdict
+from pathlib import Path
+from typing import TYPE_CHECKING
+
+import griffe
+import pytest
+from mkdocstrings import Inventory
+
+from mkdocstrings_handlers import python
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+
+
+@pytest.fixture(name="loader", scope="module")
+def _fixture_loader() -> griffe.GriffeLoader:
+ loader = griffe.GriffeLoader()
+ loader.load("mkdocstrings")
+ loader.load("mkdocstrings_handlers.python")
+ loader.resolve_aliases()
+ return loader
+
+
+@pytest.fixture(name="internal_api", scope="module")
+def _fixture_internal_api(loader: griffe.GriffeLoader) -> griffe.Module:
+ return loader.modules_collection["mkdocstrings_handlers.python._internal"]
+
+
+@pytest.fixture(name="public_api", scope="module")
+def _fixture_public_api(loader: griffe.GriffeLoader) -> griffe.Module:
+ return loader.modules_collection["mkdocstrings_handlers.python"]
+
+
+def _yield_public_objects(
+ obj: griffe.Module | griffe.Class,
+ *,
+ modules: bool = False,
+ modulelevel: bool = True,
+ inherited: bool = False,
+ special: bool = False,
+) -> Iterator[griffe.Object | griffe.Alias]:
+ for member in obj.all_members.values() if inherited else obj.members.values():
+ try:
+ if member.is_module:
+ if member.is_alias or not member.is_public:
+ continue
+ if modules:
+ yield member
+ yield from _yield_public_objects(
+ member, # type: ignore[arg-type]
+ modules=modules,
+ modulelevel=modulelevel,
+ inherited=inherited,
+ special=special,
+ )
+ elif member.is_public and (special or not member.is_special):
+ yield member
+ else:
+ continue
+ if member.is_class and not modulelevel:
+ yield from _yield_public_objects(
+ member, # type: ignore[arg-type]
+ modules=modules,
+ modulelevel=False,
+ inherited=inherited,
+ special=special,
+ )
+ except (griffe.AliasResolutionError, griffe.CyclicAliasError):
+ continue
+
+
+@pytest.fixture(name="modulelevel_internal_objects", scope="module")
+def _fixture_modulelevel_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]:
+ return list(_yield_public_objects(internal_api, modulelevel=True))
+
+
+@pytest.fixture(name="internal_objects", scope="module")
+def _fixture_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]:
+ return list(_yield_public_objects(internal_api, modulelevel=False, special=True))
+
+
+@pytest.fixture(name="public_objects", scope="module")
+def _fixture_public_objects(public_api: griffe.Module) -> list[griffe.Object | griffe.Alias]:
+ return list(_yield_public_objects(public_api, modulelevel=False, inherited=True, special=True))
+
+
+@pytest.fixture(name="inventory", scope="module")
+def _fixture_inventory() -> Inventory:
+ inventory_file = Path(__file__).parent.parent / "site" / "objects.inv"
+ if not inventory_file.exists():
+ raise pytest.skip("The objects inventory is not available.")
+ with inventory_file.open("rb") as file:
+ return Inventory.parse_sphinx(file)
+
+
+def test_exposed_objects(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None:
+ """All public objects in the internal API are exposed under `mkdocstrings_handlers.python`."""
+ not_exposed = [
+ obj.path
+ for obj in modulelevel_internal_objects
+ if obj.name not in python.__all__ or not hasattr(python, obj.name)
+ ]
+ assert not not_exposed, "Objects not exposed:\n" + "\n".join(sorted(not_exposed))
+
+
+def test_unique_names(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None:
+ """All internal objects have unique names."""
+ names_to_paths = defaultdict(list)
+ for obj in modulelevel_internal_objects:
+ names_to_paths[obj.name].append(obj.path)
+ non_unique = [paths for paths in names_to_paths.values() if len(paths) > 1]
+ assert not non_unique, "Non-unique names:\n" + "\n".join(str(paths) for paths in non_unique)
+
+
+def test_single_locations(public_api: griffe.Module) -> None:
+ """All objects have a single public location."""
+
+ def _public_path(obj: griffe.Object | griffe.Alias) -> bool:
+ return obj.is_public and (obj.parent is None or _public_path(obj.parent))
+
+ multiple_locations = {}
+ for obj_name in python.__all__:
+ obj = public_api[obj_name]
+ if obj.aliases and (
+ public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)]
+ ):
+ multiple_locations[obj.path] = public_aliases
+ assert not multiple_locations, "Multiple public locations:\n" + "\n".join(
+ f"{path}: {aliases}" for path, aliases in multiple_locations.items()
+ )
+
+
+def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe.Object | griffe.Alias]) -> None:
+ """All public objects are added to the inventory."""
+ ignore_names = {"__getattr__", "__init__", "__repr__", "__str__", "__post_init__"}
+ not_in_inventory = [
+ obj.path for obj in public_objects if obj.name not in ignore_names and obj.path not in inventory
+ ]
+ msg = "Objects not in the inventory (try running `make run mkdocs build`):\n{paths}"
+ assert not not_in_inventory, msg.format(paths="\n".join(sorted(not_in_inventory)))
+
+
+def _module_or_child(parent: str, name: str) -> bool:
+ parents = [parent[:i] for i, char in enumerate(parent) if char == "."]
+ parents.append(parent)
+ return name in parents or name.startswith(parent + ".")
+
+
+def test_inventory_matches_api(
+ inventory: Inventory,
+ public_objects: list[griffe.Object | griffe.Alias],
+ loader: griffe.GriffeLoader,
+) -> None:
+ """The inventory doesn't contain any additional Python object."""
+ not_in_api = []
+ public_api_paths = {obj.path for obj in public_objects}
+ public_api_paths.add("mkdocstrings_handlers")
+ public_api_paths.add("mkdocstrings_handlers.python")
+ # YORE: Bump 2: Remove block.
+ public_api_paths.add("mkdocstrings_handlers.python.config")
+ public_api_paths.add("mkdocstrings_handlers.python.handler")
+ public_api_paths.add("mkdocstrings_handlers.python.rendering")
+
+ for item in inventory.values():
+ if item.domain == "py" and "(" not in item.name and _module_or_child("mkdocstrings_handlers.python", item.name):
+ obj = loader.modules_collection[item.name]
+ if obj.path not in public_api_paths and not any(path in public_api_paths for path in obj.aliases):
+ not_in_api.append(item.name)
+ msg = "Inventory objects not in public API (try running `make run mkdocs build`):\n{paths}"
+ assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api)))
+
+
+def test_no_module_docstrings_in_internal_api(internal_api: griffe.Module) -> None:
+ """No module docstrings should be written in our internal API.
+
+ The reasoning is that docstrings are addressed to users of the public API,
+ but internal modules are not exposed to users, so they should not have docstrings.
+ """
+
+ def _modules(obj: griffe.Module) -> Iterator[griffe.Module]:
+ for member in obj.modules.values():
+ yield member
+ yield from _modules(member)
+
+ for obj in _modules(internal_api):
+ assert not obj.docstring
diff --git a/tests/test_end_to_end.py b/tests/test_end_to_end.py
new file mode 100644
index 00000000..3a96f803
--- /dev/null
+++ b/tests/test_end_to_end.py
@@ -0,0 +1,220 @@
+"""End-to-end tests for every combination of options."""
+
+from __future__ import annotations
+
+import json
+import re
+from typing import TYPE_CHECKING, Any
+
+import bs4
+import pytest
+from griffe import LinesCollection, ModulesCollection, TmpPackage, temporary_pypackage
+from inline_snapshot import outsource
+
+from tests.snapshots import snapshots_members, snapshots_signatures
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+
+ from mkdocstrings_handlers.python import PythonHandler
+
+
+def _normalize_html(html: str) -> str:
+ soup = bs4.BeautifulSoup(html, features="html.parser")
+ 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)
+ html = re.sub(r'(?<=id="cell-id=)\w+(?=")', r"...", html)
+ return html # noqa: RET504
+
+
+def _render(handler: PythonHandler, package: TmpPackage, final_options: dict[str, Any]) -> str:
+ final_options.pop("handler", None)
+ final_options.pop("session_handler", None)
+ handler_options = final_options.copy()
+
+ # Some default options to make snapshots easier to review.
+ handler_options.setdefault("heading_level", 1)
+ handler_options.setdefault("show_root_heading", True)
+ handler_options.setdefault("show_source", False)
+
+ options = handler.get_options(handler_options)
+
+ handler._paths = [str(package.tmpdir)]
+ try:
+ data = handler.collect(package.name, options)
+ finally:
+ # We're using a session handler, so we need to reset its state after each call.
+ # This is not thread-safe, but pytest-xdist uses subprocesses, so it's fine.
+ handler._modules_collection = ModulesCollection()
+ handler._lines_collection = LinesCollection()
+ handler._paths = []
+
+ html = handler.render(data, options)
+ return _normalize_html(html)
+
+
+def _render_options(options: dict[str, Any]) -> str:
+ return f"\n\n"
+
+
+# Signature tests.
+@pytest.fixture(name="signature_package", scope="session")
+def _signature_package() -> Iterator[TmpPackage]:
+ code = """
+ def module_function(a: int, b: str) -> None:
+ '''Docstring for `module_function`.'''
+
+ def _private_function(a: int, b: str) -> None:
+ '''Docstring for `_private_function`.'''
+
+ class Class:
+ '''Docstring for `Class`.'''
+
+ def __init__(self, a: int, b: str) -> None:
+ '''Docstring for `Class.__init__.'''
+
+ def method1(self, a: int, b: str) -> None:
+ '''Docstring for `Class.method1`.'''
+ """
+ with temporary_pypackage("signature_package", {"__init__.py": code}) as tmppkg:
+ yield tmppkg
+
+
+@pytest.mark.parametrize("show_signature_annotations", [True, False])
+@pytest.mark.parametrize("signature_crossrefs", [True, False])
+@pytest.mark.parametrize("separate_signature", [True, False])
+def test_end_to_end_for_signatures(
+ session_handler: PythonHandler,
+ signature_package: TmpPackage,
+ show_signature_annotations: bool,
+ signature_crossrefs: bool,
+ separate_signature: bool,
+) -> None:
+ """Test rendering of a given theme's templates.
+
+ Parameters:
+ identifier: Parametrized identifier.
+ session_handler: Python handler (fixture).
+ """
+ final_options = {
+ "show_signature_annotations": show_signature_annotations,
+ "signature_crossrefs": signature_crossrefs,
+ "separate_signature": separate_signature,
+ }
+ html = _render_options(final_options) + _render(session_handler, signature_package, final_options)
+ snapshot_key = tuple(sorted(final_options.items()))
+ assert outsource(html, suffix=".html") == snapshots_signatures[snapshot_key]
+
+
+# Member tests.
+@pytest.fixture(name="members_package", scope="session")
+def _members_package() -> Iterator[TmpPackage]:
+ code = """
+ '''Docstring for the package.'''
+
+ def module_function(a: int, b: str) -> None:
+ '''Docstring for `module_function`.'''
+
+ class Class:
+ '''Docstring for `Class`.'''
+
+ class NestedClass:
+ '''Docstring for `NestedClass`.'''
+
+ class_attribute: int = 42
+ '''Docstring for `Class.class_attribute`.'''
+
+ def __init__(self, a: int, b: str) -> None:
+ '''Docstring for `Class.__init__`.'''
+ self.instance_attribute = a + b
+ '''Docstring for `Class.instance_attribute`.'''
+
+ def method1(self, a: int, b: str) -> None:
+ '''Docstring for `Class.method1`.'''
+
+ def method2(self, a: int, b: str) -> None:
+ '''Docstring for `Class.method2`.'''
+
+ module_attribute: int = 42
+ '''Docstring for `module_attribute`.'''
+
+ class Subclass(Class):
+ '''Docstring for `Subclass`.'''
+ """
+ with temporary_pypackage("members_package", {"__init__.py": code}) as tmppkg:
+ yield tmppkg
+
+
+@pytest.mark.parametrize("inherited_members", [(), ("method1",), True, False])
+@pytest.mark.parametrize("members", [(), ("module_attribute",), True, False, None])
+@pytest.mark.parametrize("filters", [(), ("!module_attribute",), ("module_attribute",), "public", None])
+def test_end_to_end_for_members(
+ session_handler: PythonHandler,
+ members_package: TmpPackage,
+ inherited_members: list[str] | bool | None,
+ members: list[str] | bool | None,
+ filters: list[str] | None,
+) -> None:
+ """Test rendering of a given theme's templates.
+
+ Parameters:
+ identifier: Parametrized identifier.
+ session_handler: Python handler (fixture).
+ """
+ final_options = {
+ "inherited_members": inherited_members,
+ "members": members,
+ "filters": filters,
+ }
+ html = _render_options(final_options) + _render(session_handler, members_package, final_options)
+ snapshot_key = tuple(sorted(final_options.items()))
+ assert outsource(html, suffix=".html") == snapshots_members[snapshot_key]
+
+
+# Heading tests.
+@pytest.fixture(name="headings_package", scope="session")
+def _headings_package() -> Iterator[TmpPackage]:
+ code = """
+ def module_function(a: int, b: str) -> None:
+ pass
+
+ class Class:
+ class_attribute: int = 42
+
+ def __init__(self, a: int, b: str) -> None:
+ self.instance_attribute = a + b
+
+ def method1(self, a: int, b: str) -> None:
+ pass
+
+ module_attribute: int = 42
+ """
+ with temporary_pypackage("headings_package", {"__init__.py": code}) as tmppkg:
+ yield tmppkg
+
+
+@pytest.mark.parametrize("separate_signature", [True, False])
+@pytest.mark.parametrize("heading", ["", "Some heading"])
+def test_end_to_end_for_headings(
+ session_handler: PythonHandler,
+ headings_package: TmpPackage,
+ separate_signature: bool,
+ heading: str,
+) -> None:
+ """Test rendering of a given theme's templates.
+
+ Parameters:
+ identifier: Parametrized identifier.
+ session_handler: Python handler (fixture).
+ """
+ final_options = {
+ "separate_signature": separate_signature,
+ "heading": heading,
+ "show_if_no_docstring": True,
+ "members": False,
+ }
+ html = _render_options(final_options) + _render(session_handler, headings_package, final_options)
+ snapshot_key = tuple(sorted(final_options.items()))
+ assert outsource(html, suffix=".html") == snapshots_members[snapshot_key]
diff --git a/tests/test_handler.py b/tests/test_handler.py
index 0717dc48..f98ce545 100644
--- a/tests/test_handler.py
+++ b/tests/test_handler.py
@@ -3,43 +3,52 @@
from __future__ import annotations
import os
+import sys
+from dataclasses import replace
from glob import glob
+from io import BytesIO
+from pathlib import Path
from textwrap import dedent
from typing import TYPE_CHECKING
+import mkdocstrings
import pytest
-from griffe import DocstringSectionExamples, DocstringSectionKind, temporary_visited_module
+from griffe import (
+ Docstring,
+ DocstringSectionExamples,
+ DocstringSectionKind,
+ Module,
+ temporary_inspected_module,
+ temporary_visited_module,
+)
+from mkdocstrings import CollectionError
-from mkdocstrings_handlers.python.handler import CollectionError, PythonHandler, get_handler
+from mkdocstrings_handlers.python import Inventory, PythonConfig, PythonHandler, PythonOptions
if TYPE_CHECKING:
- from pathlib import Path
+ from mkdocstrings import MkdocstringsPlugin
-def test_collect_missing_module() -> None:
+def test_collect_missing_module(handler: PythonHandler) -> None:
"""Assert error is raised for missing modules."""
- handler = get_handler(theme="material")
with pytest.raises(CollectionError):
- handler.collect("aaaaaaaa", {})
+ handler.collect("aaaaaaaa", PythonOptions())
-def test_collect_missing_module_item() -> None:
+def test_collect_missing_module_item(handler: PythonHandler) -> None:
"""Assert error is raised for missing items within existing modules."""
- handler = get_handler(theme="material")
with pytest.raises(CollectionError):
- handler.collect("mkdocstrings.aaaaaaaa", {})
+ handler.collect("mkdocstrings.aaaaaaaa", PythonOptions())
-def test_collect_module() -> None:
+def test_collect_module(handler: PythonHandler) -> None:
"""Assert existing module can be collected."""
- handler = get_handler(theme="material")
- assert handler.collect("mkdocstrings", {})
+ assert handler.collect("mkdocstrings", PythonOptions())
-def test_collect_with_null_parser() -> None:
+def test_collect_with_null_parser(handler: PythonHandler) -> None:
"""Assert we can pass `None` as parser when collecting."""
- handler = get_handler(theme="material")
- assert handler.collect("mkdocstrings", {"docstring_style": None})
+ assert handler.collect("mkdocstrings", PythonOptions(docstring_style=None))
@pytest.mark.parametrize(
@@ -71,7 +80,7 @@ def test_render_docstring_examples_section(handler: PythonHandler) -> None:
assert "Hello" in rendered
-def test_expand_globs(tmp_path: Path) -> None:
+def test_expand_globs(tmp_path: Path, plugin: MkdocstringsPlugin) -> None:
"""Assert globs are correctly expanded.
Parameters:
@@ -86,24 +95,16 @@ def test_expand_globs(tmp_path: Path) -> None:
globbed_paths = [tmp_path.joinpath(globbed_name) for globbed_name in globbed_names]
for path in globbed_paths:
path.touch()
- handler = PythonHandler(
- handler="python",
- theme="material",
- config_file_path=str(tmp_path.joinpath("mkdocs.yml")),
- paths=["*exp*"],
- )
+ plugin.handlers._tool_config.config_file_path = str(tmp_path.joinpath("mkdocs.yml"))
+ handler: PythonHandler = plugin.handlers.get_handler("python", {"paths": ["*exp*"]}) # type: ignore[assignment]
for path in globbed_paths:
assert str(path) in handler._paths
-def test_expand_globs_without_changing_directory() -> None:
+def test_expand_globs_without_changing_directory(plugin: MkdocstringsPlugin) -> None:
"""Assert globs are correctly expanded when we are already in the right directory."""
- handler = PythonHandler(
- handler="python",
- theme="material",
- config_file_path="mkdocs.yml",
- paths=["*.md"],
- )
+ plugin.handlers._tool_config.config_file_path = "mkdocs.yml"
+ handler: PythonHandler = plugin.handlers.get_handler("python", {"paths": ["*.md"]}) # type: ignore[assignment]
for path in list(glob(os.path.abspath(".") + "/*.md")):
assert path in handler._paths
@@ -119,22 +120,26 @@ def test_expand_globs_without_changing_directory() -> None:
(True, {"extension.py:SomeExtension": {"option": "value"}}),
(True, {"path/to/extension.py": {"option": "value"}}),
(True, {"path/to/extension.py:SomeExtension": {"option": "value"}}),
- (False, "/absolute/path/to/extension.py"),
- (False, "/absolute/path/to/extension.py:SomeExtension"),
- (False, {"/absolute/path/to/extension.py": {"option": "value"}}),
- (False, {"/absolute/path/to/extension.py:SomeExtension": {"option": "value"}}),
+ # True because OS path normalization.
+ (True, "/absolute/path/to/extension.py"),
+ (True, "/absolute/path/to/extension.py:SomeExtension"),
+ (True, {"/absolute/path/to/extension.py": {"option": "value"}}),
+ (True, {"/absolute/path/to/extension.py:SomeExtension": {"option": "value"}}),
(False, "dot.notation.path.to.extension"),
(False, "dot.notation.path.to.pyextension"),
(False, {"dot.notation.path.to.extension": {"option": "value"}}),
(False, {"dot.notation.path.to.pyextension": {"option": "value"}}),
],
)
-def test_extension_paths(tmp_path: Path, expect_change: bool, extension: str | dict) -> None:
+def test_extension_paths(
+ tmp_path: Path,
+ expect_change: bool,
+ extension: str | dict,
+ plugin: MkdocstringsPlugin,
+) -> None:
"""Assert extension paths are resolved relative to config file."""
- handler = get_handler(
- theme="material",
- config_file_path=str(tmp_path.joinpath("mkdocs.yml")),
- )
+ plugin.handlers._tool_config.config_file_path = str(tmp_path.joinpath("mkdocs.yml"))
+ handler: PythonHandler = plugin.handlers.get_handler("python") # type: ignore[assignment]
normalized = handler.normalize_extension_paths([extension])[0]
if expect_change:
if isinstance(normalized, str) and isinstance(extension, str):
@@ -165,10 +170,164 @@ def function(self):
""",
)
with temporary_visited_module(code) as module:
- # TODO: Remove once Griffe does that automatically.
- module.lines_collection[module.filepath] = code.splitlines() # type: ignore[index]
-
module["Class"].lineno = None
module["Class.function"].lineno = None
module["attribute"].lineno = None
- assert handler.render(module, {"show_source": True})
+ assert handler.render(module, PythonOptions(show_source=True))
+
+
+def test_give_precedence_to_user_paths() -> None:
+ """Assert user paths take precedence over default paths."""
+ last_sys_path = sys.path[-1]
+ handler = PythonHandler(
+ base_dir=Path("."),
+ config=PythonConfig.from_data(paths=[last_sys_path]),
+ mdx=[],
+ mdx_config={},
+ )
+ assert handler._paths[0] == last_sys_path
+
+
+@pytest.mark.parametrize(
+ ("section", "code"),
+ [
+ (
+ "Attributes",
+ """
+ class A:
+ '''Summary.
+
+ Attributes:
+ x: X.
+ y: Y.
+ '''
+ x: int = 0
+ '''X.'''
+ y: int = 0
+ '''Y.'''
+ """,
+ ),
+ (
+ "Methods",
+ """
+ class A:
+ '''Summary.
+
+ Methods:
+ x: X.
+ y: Y.
+ '''
+ def x(self): ...
+ '''X.'''
+ def y(self): ...
+ '''Y.'''
+ """,
+ ),
+ (
+ "Functions",
+ """
+ '''Summary.
+
+ Functions:
+ x: X.
+ y: Y.
+ '''
+ def x(): ...
+ '''X.'''
+ def y(): ...
+ '''Y.'''
+ """,
+ ),
+ (
+ "Classes",
+ """
+ '''Summary.
+
+ Classes:
+ A: A.
+ B: B.
+ '''
+ class A: ...
+ '''A.'''
+ class B: ...
+ '''B.'''
+ """,
+ ),
+ (
+ "Modules",
+ """
+ '''Summary.
+
+ Modules:
+ a: A.
+ b: B.
+ '''
+ """,
+ ),
+ ],
+)
+def test_deduplicate_summary_sections(handler: PythonHandler, section: str, code: str) -> None:
+ """Assert summary sections are deduplicated."""
+ summary_section = section.lower()
+ summary_section = "functions" if summary_section == "methods" else summary_section
+ with temporary_visited_module(code, docstring_parser="google") as module:
+ if summary_section == "modules":
+ module.set_member("a", Module("A", docstring=Docstring("A.")))
+ module.set_member("b", Module("B", docstring=Docstring("B.")))
+ html = handler.render(
+ module,
+ handler.get_options(
+ {
+ "summary": {summary_section: True},
+ "show_source": False,
+ "show_submodules": True,
+ },
+ ),
+ )
+ assert html.count(f"{section}:") == 1
+
+
+def test_inheriting_self_from_parent_class(handler: PythonHandler) -> None:
+ """Inspect self only once when inheriting it from parent class."""
+ with temporary_inspected_module(
+ """
+ class A: ...
+ class B(A): ...
+ A.B = B
+ """,
+ ) as module:
+ # Assert no recusrion error.
+ handler.render(
+ module,
+ handler.get_options({"inherited_members": True}),
+ )
+
+
+def test_specifying_inventory_base_url(handler: PythonHandler) -> None:
+ """Assert that the handler renders inventory URLs using the specified base_url."""
+ # Update handler config to include an inventory with a base URL
+ base_url = "https://docs.com/my_library"
+ inventory = Inventory(url="https://example.com/objects.inv", base_url=base_url)
+ handler.config = replace(handler.config, inventories=[inventory])
+
+ # Mock inventory bytes
+ item_name = "my_library.my_module.MyClass"
+ mocked_inventory = mkdocstrings.Inventory()
+ mocked_inventory.register(
+ name=item_name,
+ domain="py",
+ role="class",
+ uri=f"api-reference/#{item_name}",
+ dispname=item_name,
+ )
+ mocked_bytes = BytesIO(mocked_inventory.format_sphinx())
+
+ # Get inventory URL and config
+ url, config = handler.get_inventory_urls()[0]
+
+ # Load the mocked inventory
+ _, item_url = next(handler.load_inventory(mocked_bytes, url, **config))
+
+ # Assert the URL is based on the provided base URL
+ msg = "Expected inventory URL to start with base_url"
+ assert item_url.startswith(base_url), msg
diff --git a/tests/test_rendering.py b/tests/test_rendering.py
index 1bab29d7..2616610f 100644
--- a/tests/test_rendering.py
+++ b/tests/test_rendering.py
@@ -4,12 +4,12 @@
import re
from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any
+from typing import TYPE_CHECKING, Any, Callable
import pytest
from griffe import ModulesCollection, temporary_visited_module
-from mkdocstrings_handlers.python import rendering
+from mkdocstrings_handlers.python._internal import rendering
if TYPE_CHECKING:
from markupsafe import Markup
@@ -22,14 +22,22 @@
"aaaaa(bbbbb, ccccc=1) + ddddd.eeeee[ffff] or {ggggg: hhhhh, iiiii: jjjjj}",
],
)
-def test_format_code(code: str) -> None:
- """Assert code can be Black-formatted.
+@pytest.mark.parametrize(
+ "formatter",
+ [
+ rendering._get_black_formatter(),
+ rendering._get_ruff_formatter(),
+ rendering._get_formatter(),
+ ],
+)
+def test_format_code(code: str, formatter: Callable[[str, int], str]) -> None:
+ """Assert code can be formatted.
Parameters:
code: Code to format.
"""
for length in (5, 100):
- assert rendering.do_format_code(code, length)
+ assert formatter(code, length)
@pytest.mark.parametrize(
@@ -37,7 +45,7 @@ def test_format_code(code: str) -> None:
[("Class.method", "(param: str = 'hello') -> 'OtherClass'")],
)
def test_format_signature(name: Markup, signature: str) -> None:
- """Assert signatures can be Black-formatted.
+ """Assert signatures can be formatted.
Parameters:
signature: Signature to format.
@@ -50,6 +58,8 @@ def test_format_signature(name: Markup, signature: str) -> None:
class _FakeObject:
name: str
inherited: bool = False
+ parent: None = None
+ is_alias: bool = False
@pytest.mark.parametrize(
@@ -135,14 +145,14 @@ def main(self): ...
@pytest.mark.parametrize(
("order", "members_list", "expected_names"),
[
- (rendering.Order.alphabetical, None, ["a", "b", "c"]),
- (rendering.Order.source, None, ["c", "b", "a"]),
- (rendering.Order.alphabetical, ["c", "b"], ["c", "b"]),
- (rendering.Order.source, ["a", "c"], ["a", "c"]),
- (rendering.Order.alphabetical, [], ["a", "b", "c"]),
- (rendering.Order.source, [], ["c", "b", "a"]),
- (rendering.Order.alphabetical, True, ["a", "b", "c"]),
- (rendering.Order.source, False, ["c", "b", "a"]),
+ ("alphabetical", None, ["a", "b", "c"]),
+ ("source", None, ["c", "b", "a"]),
+ ("alphabetical", ["c", "b"], ["c", "b"]),
+ ("source", ["a", "c"], ["a", "c"]),
+ ("alphabetical", [], ["a", "b", "c"]),
+ ("source", [], ["c", "b", "a"]),
+ ("alphabetical", True, ["a", "b", "c"]),
+ ("source", False, ["c", "b", "a"]),
],
)
def test_ordering_members(order: rendering.Order, members_list: list[str | None], expected_names: list[str]) -> None:
diff --git a/tests/test_themes.py b/tests/test_themes.py
index a4ad0d59..bf7401d6 100644
--- a/tests/test_themes.py
+++ b/tests/test_themes.py
@@ -7,8 +7,7 @@
import pytest
if TYPE_CHECKING:
- from markdown import Markdown
- from mkdocstrings.plugin import MkdocstringsPlugin
+ from mkdocstrings_handlers.python import PythonHandler
@pytest.mark.parametrize(
@@ -32,15 +31,13 @@
"mkdocstrings_handlers.python",
],
)
-def test_render_themes_templates_python(identifier: str, plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> None:
+def test_render_themes_templates_python(identifier: str, handler: PythonHandler) -> None:
"""Test rendering of a given theme's templates.
Parameters:
identifier: Parametrized identifier.
- plugin: Pytest fixture (see conftest.py).
- ext_markdown: Pytest fixture (see conftest.py).
+ handler: Python handler (fixture).
"""
- handler = plugin.handlers.get_handler("python")
- handler._update_env(ext_markdown, plugin.handlers._config)
- data = handler.collect(identifier, {})
- handler.render(data, {})
+ options = handler.get_options({})
+ data = handler.collect(identifier, options)
+ handler.render(data, options)