`
- sponsors.forEach(function (sponsor) {
- html += `
-
-
-
- `
- });
- html += '
list[int \| float] | `gravity_forces` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | *required*
-VacuumType \| Literal["regular"] | `vacuum_type` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | `VacuumType.PLASMA`
+list [int \| float ] | `gravity_forces` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | *required*
+VacuumType \| Literal ["regular"] | `vacuum_type` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | `VacuumType.PLASMA`
////
//// tab | List
@@ -222,8 +228,8 @@ Lists work well whatever the length of names, type annotations, descriptions, et
**Other Parameters:**
-- `gravity_forces` (list[int \| float]) — Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-- `vacuum_type` (VacuumType \| Literal["regular"]) — Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+- `gravity_forces` (list [int \| float ]) — Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+- `vacuum_type` (VacuumType \| Literal ["regular"]) — Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
////
//// tab | Spacy
@@ -241,11 +247,12 @@ by reserving more horizontal space on the second column.
**Name** | **Description**
----------- | ---------------
-`gravity_forces` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.list[int \| float] DEFAULT: required
-`vacuum_type` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.VacuumType \| Literal["regular"] DEFAULT: VacuumType.PLASMA
+`gravity_forces` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.list [int \| float ] DEFAULT: required
+`vacuum_type` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.VacuumType \| Literal ["regular"] DEFAULT: VacuumType.PLASMA
////
///
+[](){#option-merge_init_into_class}
## `merge_init_into_class`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -317,6 +324,224 @@ class Thing:
////
///
+[](){#option-relative_crossrefs}
+## `relative_crossrefs`
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
+
+
+Whether to enable the relative-crossref syntax.
+
+The relative-crossref syntax lets you reference the current object or its parent by prefixing a crossref identifier with dots. For example, to cross-reference the current object's `name` member, you can write `[link to name attribute][.name]`. The "current object" is the object containing the docstring being rendered.
+
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ relative_crossrefs: false
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ relative_crossrefs: true
+```
+
+/// admonition | Examples
+ type: preview
+
+```python title="pkg/module.py"
+"""Summary.
+
+- Link to [`module`][.].
+- Link to [`module_attribute`][.module_attribute].
+- Link to [`Class`][.Class].
+- Link to [`class_attribute`][.Class.class_attribute].
+- Link to [`instance_attribute`][.Class.instance_attribute].
+- Link to [`method`][.Class.method].
+"""
+
+module_attribute = 0
+"""Summary.
+
+- Link to [`module`][..].
+- Link to [`module_attribute`][.].
+- Link to [`Class`][..Class].
+- Link to [`class_attribute`][..Class.class_attribute].
+- Link to [`instance_attribute`][..Class.instance_attribute].
+- Link to [`method`][..Class.method].
+"""
+
+class Class:
+ """Summary.
+
+ - Link to [`module`][..].
+ - Link to [`module_attribute`][..module_attribute].
+ - Link to [`Class`][.].
+ - Link to [`class_attribute`][.class_attribute].
+ - Link to [`instance_attribute`][.instance_attribute].
+ - Link to [`method`][.method].
+ """
+
+ class_attribute = 0
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][.].
+ - Link to [`instance_attribute`][..instance_attribute].
+ - Link to [`method`][..method].
+ """
+
+ def __init__(self):
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][..class_attribute].
+ - Link to [`instance_attribute`][..instance_attribute].
+ - Link to [`method`][..method].
+ """
+ self.instance_attribute = 0
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][..class_attribute].
+ - Link to [`instance_attribute`][.].
+ - Link to [`method`][..method].
+ """
+
+ def method(self):
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][..class_attribute].
+ - Link to [`instance_attribute`][..instance_attribute].
+ - Link to [`method`][.].
+ """
+```
+
+///
+
+INFO: **There is an alternative, third-party Python handler that handles relative references: [mkdocstrings-python-xref](https://github.com/analog-garage/mkdocstrings-python-xref).**
+
+[](){#option-scoped_crossrefs}
+## `scoped_crossrefs`
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
+
+
+Whether to enable scoped cross-references.
+
+With scoped cross-references, you can write identifiers as if you wanted to access them from the current object's scope. The scoping rules do not exactly match Python's: you can reference members and siblings too, without prefixing with `self.` or `cls.`.
+
+The following order is applied when resolving a name in a given scope:
+
+1. member of the current object
+2. parent class
+3. repeat 1-2 within parent's scope
+
+In practice, it means that the name is first looked up in members, then it is compared against the parent name (only if it's a class), then it is looked up in siblings. It continues climbing up the object tree until there's no parent, in which case it raises a name resolution error.
+
+Cross-referencing an imported object will directly link to this object if the objects inventory of the project it comes from was [loaded][inventories]. You won't be able to cross-reference it within your own documentation with scoped references, if you happen to be rendering this external object too. In that case, you can use an absolute reference or a [relative][relative_crossrefs] one instead.
+
+Another limitation is that you won't be able to reference an external package if its name can be resolved in the current object's scope.
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ scoped_crossrefs: false
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ scoped_crossrefs: true
+```
+
+/// admonition | Examples
+ type: preview
+
+```python title="pkg/module.py"
+"""Summary.
+
+- Link to [`module_attribute`][module_attribute].
+- Link to [`Class`][Class].
+- Link to [`class_attribute`][Class.class_attribute].
+- Link to [`instance_attribute`][Class.instance_attribute].
+- Link to [`method`][Class.method].
+"""
+
+module_attribute = 0
+"""Summary.
+
+- Link to [`Class`][Class].
+- Link to [`class_attribute`][Class.class_attribute].
+- Link to [`instance_attribute`][Class.instance_attribute].
+- Link to [`method`][Class.method].
+"""
+
+class Class:
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`instance_attribute`][instance_attribute].
+ - Link to [`method`][method].
+ """
+
+ class_attribute = 0
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`instance_attribute`][instance_attribute].
+ - Link to [`method`][method].
+ """
+
+ def __init__(self):
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`instance_attribute`][instance_attribute].
+ - Link to [`method`][method].
+ """
+ self.instance_attribute = 0
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`method`][method].
+ """
+
+ def method(self):
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`instance_attribute`][instance_attribute].
+ """
+```
+
+///
+
+[](){#option-show_if_no_docstring}
## `show_if_no_docstring`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -386,12 +611,13 @@ class ClassWithoutDocstring:
////
///
+[](){#option-show_docstring_attributes}
## `show_docstring_attributes`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
-Whether to render the "Attributes" sections of docstrings.
+Whether to render the "Attributes" section of docstrings.
```yaml title="in mkdocs.yml (global configuration)"
plugins:
@@ -438,12 +664,13 @@ class Class:
////
///
+[](){#option-show_docstring_functions}
## `show_docstring_functions`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
-Whether to render the "Functions" or "Methods" sections of docstrings.
+Whether to render the "Functions" or "Methods" section of docstrings.
```yaml title="in mkdocs.yml (global configuration)"
plugins:
@@ -512,13 +739,13 @@ class Class:
////
///
-
+[](){#option-show_docstring_classes}
## `show_docstring_classes`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
-Whether to render the "Classes" sections of docstrings.
+Whether to render the "Classes" section of docstrings.
```yaml title="in mkdocs.yml (global configuration)"
plugins:
@@ -571,12 +798,71 @@ class Class:
////
///
+[](){#option-show_docstring_type_aliases}
+## `show_docstring_type_aliases`
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
+
+Whether to render the "Type Aliases" section of docstrings.
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ show_docstring_type_aliases: true
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ show_docstring_type_aliases: false
+```
+
+```python
+"""Summary.
+
+Type Aliases:
+ TypeAlias: Some type alias.
+"""
+
+
+type TypeAlias = int
+"""Summary."""
+```
+
+/// admonition | Preview
+ type: preview
+
+//// tab | With type_aliases
+Summary.
+Type Aliases:
+ +**Name** | **Description** +------------ | ---------------- +`TypeAlias` | Some type alias. + +TypeAliasSummary.
+//// + +//// tab | Without classes +Summary.
+TypeAliasSummary.
+//// +/// + +[](){#option-show_docstring_modules} ## `show_docstring_modules` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** -Whether to render the "Modules" sections of docstrings. +Whether to render the "Modules" section of docstrings. ```yaml title="in mkdocs.yml (global configuration)" plugins: @@ -627,6 +913,7 @@ Modules: //// /// +[](){#option-show_docstring_description} ## `show_docstring_description` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -690,6 +977,7 @@ class Class: //// /// +[](){#option-show_docstring_examples} ## `show_docstring_examples` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -743,6 +1031,7 @@ hello //// /// +[](){#option-show_docstring_other_parameters} ## `show_docstring_other_parameters` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -793,6 +1082,7 @@ def do_something(**kwargs): //// /// +[](){#option-show_docstring_parameters} ## `show_docstring_parameters` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -843,6 +1133,7 @@ def do_something(whatever: int = 0): //// /// +[](){#option-show_docstring_raises} ## `show_docstring_raises` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -894,6 +1185,7 @@ def raise_runtime_error(): //// /// +[](){#option-show_docstring_receives} ## `show_docstring_receives` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -953,6 +1245,7 @@ def iter_skip( //// /// +[](){#option-show_docstring_returns} ## `show_docstring_returns` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -1004,6 +1297,58 @@ def rand() -> int: //// /// +[](){#option-show_docstring_type_parameters} +## `show_docstring_type_parameters` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** + + +Whether to render the "Type Parameters" section of docstrings. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + show_docstring_type_parameters: true +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.module + options: + show_docstring_type_parameters: false +``` + +```python +class AClass[X: (int, str) = str]: + """Represents something. + + Type Parameters: + X: Something. + """ +``` + +/// admonition | Preview + type: preview + +//// tab | With parameters +AClassRepresents something.
+Type Parameters:
+ +**Name** | **Bound or Constraints** | **Description** | **Default** +---------- | ------------------------ | --------------- | ----------- +`whatever` | `(int, str)` | Something. | `str` +//// + +//// tab | Without parameters +AClassRepresents something.
+//// +/// + +[](){#option-show_docstring_warns} ## `show_docstring_warns` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -1055,6 +1400,7 @@ def warn(): //// /// +[](){#option-show_docstring_yields} ## `show_docstring_yields` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** diff --git a/docs/usage/configuration/general.md b/docs/usage/configuration/general.md index e4ddaec1..921f3b27 100644 --- a/docs/usage/configuration/general.md +++ b/docs/usage/configuration/general.md @@ -1,5 +1,6 @@ # General options +[](){#option-allow_inspection} ## `allow_inspection` - **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** @@ -18,6 +19,10 @@ and sometimes the collected data is inaccurate (depending on the tool that was used to compile the module) or too low-level/technical for API documentation. +See also [`force_inspection`](#force_inspection). + +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 `allow_inspection` 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: @@ -55,12 +60,60 @@ plugins: //// /// -## `show_bases` +[](){#option-backlinks} +## `backlinks` -- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** +- **:octicons-package-24: TypeLiteral ["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:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ backlinks: tree
+```
+
+/// admonition | Preview
+ type: preview
+
+//// tab | Flat
+
+////
+
+//// tab | Tree
+
+////
+///
+
+[](){#option-extensions}
+## `extensions`
+
+- **:octicons-package-24: Type list [str | dict [str , dict [str , Any ]]] :material-equal: `[]`{ title="default value" }**
-Show the base classes of a class.
+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:
@@ -68,36 +121,133 @@ plugins:
handlers:
python:
options:
- show_bases: 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_bases: false
+ extensions:
+ - griffe_typingdoc
+```
+
+[](){#option-extra}
+## `extra`
+
+- **:octicons-package-24: Type [`dict`][] :material-equal: `{}`{ title="default value" }**
+
+
+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].
+
+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):
+ """
+ SomeClass()Bases: SomeBaseClass
Docstring of the class.
+//// tab | With find_stubs_package +your_funcFunction docstring
//// -//// tab | Without bases -SomeClass()Docstring of the class.
+//// tab | Without find_stubs_package +your_funcsome_function()Docstring of the function.
-///// details | Source code in `package/module.py` - type: quote +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.""" +``` -```python linenums="1" -def some_function(): - ... +//// tab | `TD` (or `TB`) + +```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 ``` -///// + //// -//// tab | Without source -some_function()Docstring of the function.
+//// tab | `BT` + +```mermaid +flowchart BT +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 +``` + +//// + +//// tab | `RL` + +```mermaid +flowchart RL +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 +``` + +//// + +//// tab | `LR` + +```mermaid +flowchart LR +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 +``` + //// /// +[](){#option-preload_modules} ## `preload_modules` -- **:octicons-package-24: Typelist[str] | None :material-equal: `None`{ title="default value" }**
+- **:octicons-package-24: Type list [str ] | None :material-equal: `None`{ title="default value" }**
Pre-load modules that are not specified directly in [autodoc instructions][autodoc syntax] (`::: identifier`).
@@ -165,7 +432,7 @@ plugins:
::: your_package.your_module
options:
preload_modules:
- - their_package
+ - their_package
```
```python title="your_package/your_module.py"
@@ -192,14 +459,65 @@ __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-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 +525,163 @@ 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): - """ -some_function()Docstring of the function.
+ +///// details | Source code in `package/module.py` + type: quote + +```python linenums="1" +def some_function(): ... +``` +///// +//// -# rest of your code +//// tab | Without source +some_function()Docstring of the function.
+//// +/// + +[](){#option-skip_local_inventory} +## `skip_local_inventory` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +Whether to skip registering symbols in the objects inventory. + +With this option enabled, re-rendering docstrings for objects from external inventories is possible with their cross-references pointing to the original external inventory, not local. Similarly, it becomes possible to render the same symbol several times in the same documentation, with only one canonical location being used for cross-references (preventing confusion in mkdocs-autorefs). + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + skip_local_inventory: false +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.module + options: + skip_local_inventory: true ``` /// admonition | Preview type: preview -//// tab | With find_stubs_package -your_funcFunction docstring
+ +//// tab | Without `skip_local_inventory` + +```md exec="on" +::: bisect.bisect_left + options: + heading_level: 3 + skip_local_inventory: false + show_docstring_description: false +``` + +Notice how [`bisect.bisect_left`][] now points to the section above. + //// -//// tab | Without find_stubs_package -your_func 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 +259,7 @@ plugins:
////
///
+[](){#option-show_root_toc_entry}
## `show_root_toc_entry`
- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
@@ -164,19 +304,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 +363,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 +412,7 @@ plugins:
////
///
+[](){#option-show_object_full_path}
## `show_object_full_path`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -278,7 +421,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 +466,7 @@ plugins:
////
///
+[](){#option-show_category_heading}
## `show_category_heading`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -332,7 +476,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,10 +532,9 @@ plugins:
////
///
+[](){#option-show_symbol_type_heading}
## `show_symbol_type_heading`
-[:octicons-tag-24: Insiders 1.1.0](../../insiders/changelog.md#1.1.0)
-
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -452,10 +595,9 @@ plugins:
////
///
+[](){#option-show_symbol_type_toc}
## `show_symbol_type_toc`
-[:octicons-tag-24: Insiders 1.1.0](../../insiders/changelog.md#1.1.0)
-
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -515,3 +657,154 @@ 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"
+```
+
+[](){#option-type_parameter_headings}
+## `type_parameter_headings`
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
+
+Whether to render headings for generic class, function/method and type alias
+type parameters.
+
+With this option enabled, each type parameter of a generic object (including
+type 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.
+
+
+
+Enabling this option along with [`signature_crossrefs`][] will automatically
+render cross-references to type parameters in class/function/method/type alias
+signatures.
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ type_parameter_headings: false
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ type_parameter_headings: true
+```
+
+/// admonition | Preview: Cross-references
+ type: preview
+
+```md exec="on"
+::: package.generics
+ options:
+ show_root_heading: false
+ heading_level: 3
+ docstring_section_style: list
+ show_bases: true
+ summary: false
+ separate_signature: true
+ show_signature_type_parameters: true
+ show_inheritance_diagram: false
+ type_parameter_headings: true
+```
+
+///
+
+/// admonition | Preview: Type parameter sections
+ type: preview
+
+//// tab | Table style
+```md exec="on"
+::: package.generics.MagicBag
+ options:
+ members: false
+ heading_level: 3
+ show_root_heading: false
+ show_root_toc_entry: false
+ parameter_headings: true
+ docstring_section_style: table
+ show_docstring_description: false
+ show_docstring_parameters: false
+ show_docstring_returns: false
+ show_inheritance_diagram: false
+```
+////
+
+//// tab | List style
+```md exec="on"
+::: package.generics.MagicBag
+ options:
+ members: false
+ heading_level: 3
+ show_root_heading: false
+ show_root_toc_entry: false
+ parameter_headings: true
+ docstring_section_style: list
+ show_docstring_description: false
+ show_docstring_parameters: false
+ show_docstring_returns: false
+ show_inheritance_diagram: false
+```
+////
+
+//// tab | Spacy style
+```md exec="on"
+::: package.generics.MagicBag
+ options:
+ members: false
+ heading_level: 3
+ show_root_heading: false
+ show_root_toc_entry: false
+ parameter_headings: true
+ docstring_section_style: spacy
+ show_docstring_description: false
+ show_docstring_parameters: false
+ show_docstring_returns: false
+ show_inheritance_diagram: false
+```
+////
+///
+
+/// admonition | Preview: Table of contents (with symbol types)
+ type: preview
+
+ mutate U
+
+To customize symbols, see [Customizing symbol types](../customization.md/#symbol-types).
+
+///
diff --git a/docs/usage/configuration/members.md b/docs/usage/configuration/members.md
index 1e5ff771..53d955fa 100644
--- a/docs/usage/configuration/members.md
+++ b/docs/usage/configuration/members.md
@@ -1,9 +1,10 @@
# Members options
+[](){#option-members}
## `members`
-- **:octicons-package-24: Type list[str] |
- bool | None :material-equal: `None`{ title="default value" }**
+- **:octicons-package-24: Type list [str ] |
+ bool | None :material-equal: `None`{ title="default value" }**
An explicit list of members to render.
@@ -95,10 +96,11 @@ 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] |
- bool :material-equal: `False`{ title="default value" }**
+- **:octicons-package-24: Type list [str ] |
+ bool :material-equal: `False`{ title="default value" }**
An explicit list of inherited members (for classes) to render.
@@ -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__`: 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,21 @@ 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}
+
+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 +394,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 +446,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 +516,7 @@ def function_d():
////
///
+[](){#option-show_submodules}
## `show_submodules`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
@@ -550,18 +571,16 @@ 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" }**
+- **:octicons-package-24: Type bool | dict [str , bool ] :material-equal: `False`{ title="default value" }**
Whether to render summaries of modules, classes, functions (methods) and attributes.
This option accepts a boolean (`yes`, `true`, `no`, `false` in YAML)
-or a dictionary with one or more of the following keys: `attributes`, `functions`, `classes`, `modules`,
+or a dictionary with one or more of the following keys: `attributes`, `functions`, `classes`, `modules`, `type_aliases`,
with booleans as values. Class methods summary is (de)activated with the `functions` key.
By default, `summary` is false, and by extension all values are false.
@@ -644,6 +663,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..109362e3 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,139 @@ plugins:
////
///
+[](){#option-modernize_annotations}
+## `modernize_annotations`
+
+- **: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-overloads_only}
+## `overloads_only`
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
+
+Whether to hide the implementation signature if the overloads are shown with [`show_overloads`][].
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ overloads_only: false
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ overloads_only: true
+```
+
+/// admonition | Preview
+ type: preview
+//// tab | With overloads only
+Function docstring.
+//// + +//// tab | Without signature type parameters +Function docstring.
+//// +/// + +[](){#option-separate_signature} ## `separate_signature` - **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** @@ -293,10 +490,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,9 +534,102 @@ function(param1, param2=None) //// /// -## `signature_crossrefs` +[](){#option-show_attribute_values} +## `show_attribute_values` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** + + +Show initial values of attributes in classes. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + show_attribute_values: true +``` + +```md title="or in docs/some_page.md (local configuration)" +::: path.to.object + options: + show_attribute_values: true +``` + +```python title="package/module.py" +class SomeClass: + def __init__(self): + self.some_attr = 1 +``` + +/// admonition | Preview + type: preview + +//// tab | With attribute values visible +SomeClasssome_attr = 1
+//// + +//// tab | With attribute values hidden +SomeClasssome_attr
+//// +/// + +[](){#option-show_overloads} +## `show_overloads` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** + +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 +
Try cycling through the themes to see the colors for each theme:
+
@@ -189,6 +221,14 @@ 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-type_parameter::after {
+ content: "P";
+}
+
.doc-symbol-attribute::after {
content: "A";
}
@@ -205,6 +245,10 @@ For example, to use single letters instead of truncated types:
content: "C";
}
+.doc-symbol-type_alias::after {
+ content: "T";
+}
+
.doc-symbol-module::after {
content: "M";
}
@@ -215,6 +259,14 @@ For example, to use single letters instead of truncated types:
'
-
-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..3c425a73
--- /dev/null
+++ b/scripts/get_version.py
@@ -0,0 +1,31 @@
+# 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 ( # ty: ignore[unresolved-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..5a4447ca
--- /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]
+ 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
deleted file mode 100644
index 15212486..00000000
--- a/scripts/insiders.py
+++ /dev/null
@@ -1,203 +0,0 @@
-"""Functions related to Insiders funding goals."""
-
-from __future__ import annotations
-
-import json
-import logging
-import os
-import posixpath
-from dataclasses import dataclass
-from datetime import date, datetime, timedelta
-from itertools import chain
-from pathlib import Path
-from typing import Iterable, cast
-from urllib.error import HTTPError
-from urllib.parse import urljoin
-from urllib.request import urlopen
-
-import yaml
-
-logger = logging.getLogger(f"mkdocs.logs.{__name__}")
-
-
-def human_readable_amount(amount: int) -> str: # noqa: D103
- str_amount = str(amount)
- if len(str_amount) >= 4: # noqa: PLR2004
- return f"{str_amount[:len(str_amount)-3]},{str_amount[-3:]}"
- return 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
- project: Project | None
-
- def url(self, rel_base: str = "..") -> str | None: # noqa: D102
- if not self.ref:
- return None
- if self.project:
- rel_base = self.project.url
- return posixpath.join(rel_base, self.ref.lstrip("/"))
-
- def render(self, rel_base: str = "..", *, badge: bool = False) -> None: # noqa: D102
- new = ""
- if badge:
- recent = self.since and date.today() - self.since <= timedelta(days=60) # noqa: DTZ011
- if recent:
- ft_date = self.since.strftime("%B %d, %Y") # type: ignore[union-attr]
- new = f' :material-alert-decagram:{{ .new-feature .vibrate title="Added on {ft_date}" }}'
- project = f"[{self.project.name}]({self.project.url}) — " if self.project else ""
- feature = f"[{self.name}]({self.url(rel_base)})" if self.ref else self.name
- print(f"- [{'x' if self.since else ' '}] {project}{feature}{new}")
-
-
-@dataclass
-class Goal:
- """Class representing an Insiders goal."""
-
- name: str
- amount: int
- features: list[Feature]
- complete: bool = False
-
- @property
- def human_readable_amount(self) -> str: # noqa: D102
- return human_readable_amount(self.amount)
-
- def render(self, rel_base: str = "..") -> None: # noqa: D102
- print(f"#### $ {self.human_readable_amount} — {self.name}\n")
- if self.features:
- for feature in self.features:
- feature.render(rel_base)
- print("")
- else:
- print("There are no features in this goal for this project. ")
- print(
- "[See the features in this goal **for all Insiders projects.**]"
- f"(https://pawamoy.github.io/insiders/#{self.amount}-{self.name.lower().replace(' ', '-')})",
- )
-
-
-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(
- name=goal_data["name"],
- amount=amount,
- complete=funding >= amount,
- features=[
- Feature(
- name=feature_data["name"],
- ref=feature_data.get("ref"),
- since=feature_data.get("since") and datetime.strptime(feature_data["since"], "%Y/%m/%d").date(), # noqa: DTZ007
- project=project,
- )
- for feature_data in goal_data["features"]
- ],
- )
- for amount, goal_data in goals_data.items()
- }
-
-
-def _load_goals_from_disk(path: str, funding: int = 0) -> dict[int, Goal]:
- project_dir = os.getenv("MKDOCS_CONFIG_DIR", ".")
- try:
- data = Path(project_dir, path).read_text()
- except OSError as error:
- raise RuntimeError(f"Could not load data from disk: {path}") from error
- return load_goals(data, funding)
-
-
-def _load_goals_from_url(source_data: tuple[str, str, str], funding: int = 0) -> dict[int, Goal]:
- project_name, project_url, data_fragment = source_data
- data_url = urljoin(project_url, data_fragment)
- try:
- with urlopen(data_url) as response: # noqa: S310
- data = response.read()
- except HTTPError as error:
- raise RuntimeError(f"Could not load data from network: {data_url}") from error
- return load_goals(data, funding, project=Project(name=project_name, url=project_url))
-
-
-def _load_goals(source: str | tuple[str, str, str], funding: int = 0) -> dict[int, Goal]:
- if isinstance(source, str):
- return _load_goals_from_disk(source, funding)
- return _load_goals_from_url(source, funding)
-
-
-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 = {}
- for src in source:
- source_goals = _load_goals(src, funding)
- for amount, goal in source_goals.items():
- if amount not in goals:
- goals[amount] = goal
- else:
- goals[amount].features.extend(goal.features)
- return {amount: goals[amount] for amount in sorted(goals)}
-
-
-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
- with urlopen(url) as response: # noqa: S310
- return json.loads(response.read().decode())
-
-
-data_source = globals()["data_source"]
-sponsor_url = "https://github.com/sponsors/pawamoy"
-data_url = "https://raw.githubusercontent.com/pawamoy/sponsors/main"
-numbers: dict[str, int] = load_json(f"{data_url}/numbers.json") # type: ignore[assignment]
-sponsors: list[dict] = load_json(f"{data_url}/sponsors.json") # type: ignore[assignment]
-current_funding = numbers["total"]
-sponsors_count = numbers["count"]
-goals = funding_goals(data_source, funding=current_funding)
-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),
- reverse=True,
-)
diff --git a/scripts/make b/scripts/make
deleted file mode 100755
index c097985e..00000000
--- a/scripts/make
+++ /dev/null
@@ -1,203 +0,0 @@
-#!/usr/bin/env python3
-"""Management commands."""
-
-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) -> None:
- """Run a shell command."""
- subprocess.run(cmd, shell=True, check=True) # noqa: S602
-
-
-@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')}"
- cmd = f"uv pip compile {uv_opts} pyproject.toml devdeps.txt | uv pip install -r -"
- shell(cmd)
- 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 Exception: # noqa: BLE001
- sys.exit(1)
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..b741a366
--- /dev/null
+++ b/scripts/make.py
@@ -0,0 +1,224 @@
+#!/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.10 3.11 3.12 3.13 3.14 3.15").split()
+PYTHON_DEV = "3.15"
+
+
+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)
+
+
+class _RunError(subprocess.CalledProcessError):
+ def __init__(self, *args: Any, python_version: str, **kwargs: Any):
+ super().__init__(*args, **kwargs)
+ self.python_version = python_version
+
+
+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"]
+ try:
+ 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
+ except subprocess.CalledProcessError as process:
+ raise _RunError(
+ returncode=process.returncode,
+ python_version=version,
+ cmd=process.cmd,
+ output=process.output,
+ stderr=process.stderr,
+ ) from process
+
+
+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":
+ if not args:
+ print("make: run: missing command", file=sys.stderr)
+ return 1
+ run("default", *args) # ty: ignore[missing-argument]
+ return 0
+
+ if cmd == "multirun":
+ if not args:
+ print("make: run: missing command", file=sys.stderr)
+ return 1
+ multirun(*args) # ty: ignore[missing-argument]
+ return 0
+
+ if cmd == "allrun":
+ if not args:
+ print("make: run: missing command", file=sys.stderr)
+ return 1
+ allrun(*args) # ty: ignore[missing-argument]
+ return 0
+
+ if cmd.startswith("3."):
+ if not args:
+ print("make: run: missing command", file=sys.stderr)
+ return 1
+ run(cmd, *args) # ty: ignore[missing-argument]
+ 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 _RunError as process:
+ if process.output:
+ print(process.output, file=sys.stderr)
+ if (code := process.returncode) == 139: # noqa: PLR2004
+ print(
+ f"✗ (python{process.python_version}) '{' '.join(process.cmd)}' failed with return code {code} (segfault)",
+ file=sys.stderr,
+ )
+ if process.python_version == PYTHON_DEV:
+ code = 0
+ sys.exit(code)
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..dbad0355 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_as_type_aliases_section,
+ do_backlink_tree,
+ do_filter_objects,
+ do_format_attribute,
+ do_format_code,
+ do_format_signature,
+ do_format_type_alias,
+ do_get_template,
+ 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_as_type_aliases_section",
+ "do_backlink_tree",
+ "do_filter_objects",
+ "do_format_attribute",
+ "do_format_code",
+ "do_format_signature",
+ "do_format_type_alias",
+ "do_get_template",
+ "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..f9f8963b
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/config.py
@@ -0,0 +1,1166 @@
+# 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
+
+ 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
+
+
+@dataclass(frozen=True, kw_only=True)
+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
+
+ warn_missing_types: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Warn about missing type/annotation for parameters, return values, etc.",
+ ),
+ ] = True
+
+ warnings: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Generally enable/disable warnings when parsing docstrings.",
+ ),
+ ] = True
+
+
+@dataclass(frozen=True, kw_only=True)
+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
+
+ warn_missing_types: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Warn about missing type/annotation for parameters, return values, etc.",
+ ),
+ ] = True
+
+ warnings: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Generally enable/disable warnings when parsing docstrings.",
+ ),
+ ] = True
+
+
+@dataclass(frozen=True, kw_only=True)
+class SphinxStyleOptions:
+ """Sphinx style docstring options."""
+
+ warn_unknown_params: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Warn about documented parameters not appearing in the signature.",
+ ),
+ ] = True
+
+ warn_missing_types: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Warn about missing type/annotation for return values.",
+ ),
+ ] = True
+
+ warnings: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Generally enable/disable warnings when parsing docstrings.",
+ ),
+ ] = True
+
+
+@dataclass(frozen=True, kw_only=True)
+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)
+
+
+@dataclass(frozen=True, kw_only=True)
+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)
+
+
+@dataclass(frozen=True, kw_only=True)
+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
+
+ type_aliases: Annotated[
+ bool,
+ _Field(
+ group="members",
+ parent="summary",
+ description="Whether to render summaries of type aliases.",
+ ),
+ ] = False
+
+
+@dataclass(frozen=True, kw_only=True)
+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**
+
+ 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=_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
+
+ inheritance_diagram_direction: Annotated[
+ Literal["TB", "TD", "BT", "RL", "LR"],
+ _Field(
+ group="docstrings",
+ description="The direction of the Mermaid chart presenting the inheritance diagram of a class.",
+ ),
+ ] = "TD"
+
+ 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
+
+ overloads_only: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Whether to hide the implementation signature if the overloads are shown.",
+ ),
+ ] = 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_attribute_values: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Show initial values of attributes in classes.",
+ ),
+ ] = True
+
+ 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_type_aliases: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Type Aliases' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_type_parameters: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Type Parameters' 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_type_parameters: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Show the type parameters in generic classes, methods, functions and type aliases 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
+
+ skip_local_inventory: Annotated[
+ bool,
+ _Field(
+ group="general",
+ description="Whether to prevent objects from being registered in the local objects inventory.",
+ ),
+ ] = 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.",
+ ),
+ ] = ""
+
+ type_parameter_headings: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="Whether to render headings for type parameters (therefore showing type parameters in the ToC).",
+ ),
+ ] = False
+
+ 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, type_aliases=True)
+ elif summary is False:
+ summary = SummaryOption(
+ attributes=False,
+ functions=False,
+ classes=False,
+ modules=False,
+ type_aliases=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))
+
+
+@dataclass(frozen=True, kw_only=True)
+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), attributes and type aliases."""
+
+ @classmethod
+ def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
+ """Create an instance from a dictionary."""
+ if "filters" in data and not isinstance(data["filters"], str):
+ # 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)
+
+
+@dataclass(frozen=True, kw_only=True)
+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}
+
+
+@dataclass(frozen=True, kw_only=True)
+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="Deprecated. Use mkdocstrings' own `locale` setting instead. 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))
+
+
+@dataclass(frozen=True, kw_only=True)
+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..a3c99d75 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))], # ty: ignore[invalid-argument-type]
+ 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..b84cd8ba
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/handler.py
@@ -0,0 +1,406 @@
+# 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 griffe import (
+ AliasResolutionError,
+ GriffeLoader,
+ LinesCollection,
+ ModulesCollection,
+ Parser,
+ load_extensions,
+ patch_loggers,
+)
+from mkdocs.exceptions import PluginError
+from mkdocs_autorefs import BacklinkCrumb
+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 Iterable, Iterator, Mapping, MutableMapping, Sequence
+
+ from mkdocs.config.defaults import MkDocsConfig
+ from mkdocs_autorefs import Backlink
+
+
+# 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)
+
+
+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."""
+
+ 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.BaseHandler.load_inventory`][]).
+
+ 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.
+ """
+ extra = {**self.global_options.get("extra", {}), **local_options.get("extra", {})}
+ options = {**self.global_options, **local_options, "extra": extra}
+ try:
+ return PythonOptions.from_data(**options)
+ except Exception as error:
+ raise PluginError(f"Invalid options: {error}") from error
+
+ 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,
+ 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, locale: str | None = None) -> str:
+ """Render the collected data.
+
+ Parameters:
+ data: The collected data.
+ options: The options to use for rendering.
+ locale: The locale to use for rendering (default is "en").
+
+ Returns:
+ The rendered data (HTML).
+ """
+ template_name = rendering.do_get_template(data)
+ template = self.env.get_template(template_name)
+
+ return template.render(
+ **{
+ "config": options,
+ data.kind.value.replace(" ", "_"): 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": locale or "en",
+ },
+ )
+
+ def render_backlinks(self, backlinks: Mapping[str, Iterable[Backlink]], *, locale: str | None = None) -> str: # noqa: ARG002
+ """Render the backlinks.
+
+ Parameters:
+ backlinks: The backlinks to render.
+
+ Returns:
+ The rendered backlinks (HTML).
+ """
+ template = self.env.get_template("backlinks.html.jinja")
+ verbose_type = {key: key.capitalize().replace("-by", " by") for key in backlinks.keys()} # noqa: SIM118
+ return template.render(
+ backlinks=backlinks,
+ config=self.get_options({}),
+ verbose_type=verbose_type,
+ default_crumb=BacklinkCrumb(title="", url=""),
+ )
+
+ 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["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["format_type_alias"] = rendering.do_format_type_alias
+ 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_type_aliases_section"] = rendering.do_as_type_aliases_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 = 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.
+ **kwargs: Additional arguments to pass to the handler.
+
+ Returns:
+ An instance of `PythonHandler`.
+ """
+ # In rare cases, Griffe hits the recursion limit because of deeply-nested ASTs.
+ # We therefore increase the limit here, once, before Griffe is used to collect or render stuff.
+ sys.setrecursionlimit(max(sys.getrecursionlimit(), 2000))
+
+ base_dir = Path(getattr(tool_config, "config_file_path", None) or "./mkdocs.yml").parent
+ 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..a906b465
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/rendering.py
@@ -0,0 +1,868 @@
+# This module implements rendering utilities.
+
+from __future__ import annotations
+
+import random
+import re
+import string
+import subprocess
+import sys
+from collections import defaultdict
+from contextlib import suppress
+from dataclasses import replace
+from functools import lru_cache
+from re import 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,
+ DocstringSectionTypeAliases,
+ DocstringTypeAlias,
+ Object,
+ TypeAlias,
+)
+from jinja2 import pass_context
+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.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:
+ if item.parent.exports is not None:
+ try:
+ return item.parent.exports.index(item.name)
+ except ValueError:
+ # If the item is not in `__all__`, it will go to the end of the list.
+ return float("inf")
+ # No exports declared, refuse to sort (try other methods or return members as they are).
+ raise ValueError(f"Parent object {item.parent.path} doesn't declare exports")
+
+
+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
+ type_params_template = env.get_template("type_parameters.html.jinja")
+ signature_template = env.get_template("signature.html.jinja")
+
+ 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 = type_params_template.render(context.parent, obj=function, signature=True)
+ signature += 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
+ show_value: bool = True,
+) -> 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
+ template = env.get_template("expression.html.jinja")
+ 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 show_value and 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
+
+
+@pass_context
+def do_format_type_alias(
+ context: Context,
+ type_alias_path: Markup,
+ type_alias: TypeAlias,
+ line_length: int,
+ *,
+ crossrefs: bool = False, # noqa: ARG001
+) -> str:
+ """Format a type alias.
+
+ Parameters:
+ context: Jinja context, passed automatically.
+ type_alias_path: The path of the type alias we render the signature of.
+ type_alias: The type alias 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
+ type_params_template = env.get_template("type_parameters.html.jinja")
+ expr_template = env.get_template("expression.html.jinja")
+
+ signature = str(type_alias_path).strip()
+ signature += type_params_template.render(context.parent, obj=type_alias, signature=True)
+ value = expr_template.render(context.parent, expression=type_alias.value, signature=True)
+ 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,
+ ),
+ )
+
+ # Since we highlight the signature without `type`,
+ # Pygments sees only an assignment, not a type alias definition
+ # (at the moment it does not understand type alias definitions anyway).
+ # The result is that the type alias name is not parsed as such,
+ # but instead as a regular name: `n` CSS class instead of `nc`.
+ # To fix it, we replace the first occurrence of an `n` CSS class
+ # with an `nc` one, unless we found `nc` already.
+ 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
+
+
+def do_order_members(
+ members: Sequence[Object | Alias],
+ order: Order | list[Order],
+ members_list: bool | list[str] | None, # noqa: FBT001
+) -> 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
+
+
+_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
+ parents = {obj.path, parent.path}
+ if parent.is_alias:
+ parents.add(parent.final_target.path)
+ while parent.parent:
+ parent = parent.parent
+ parents.add(parent.path)
+ if parent.is_alias:
+ parents.add(parent.final_target.path)
+ 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):
+ 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 # noqa: PLC0415
+ 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 # noqa: PLC0415
+ 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
+
+
+def do_get_template(obj: Object | Alias) -> str:
+ """Get the template name used to render an object.
+
+ Parameters:
+ obj: A Griffe object.
+
+ Returns:
+ A template name.
+ """
+ extra_data = getattr(obj, "extra", {}).get("mkdocstrings", {})
+ if name := extra_data.get("template", ""):
+ return name
+ name = obj.kind.value.replace(" ", "_")
+ return f"{name}.html.jinja"
+
+
+@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,
+ )
+ 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
+ ],
+ )
+
+
+@pass_context
+def do_as_type_aliases_section(
+ context: Context, # noqa: ARG001
+ type_aliases: Sequence[TypeAlias],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionTypeAliases:
+ """Build a type aliases section from a list of type aliases.
+
+ Parameters:
+ type_aliases: The type aliases to build the section from.
+ check_public: Whether to check if the type_alias is public.
+
+ Returns:
+ A type aliases docstring section.
+ """
+ return DocstringSectionTypeAliases(
+ [
+ DocstringTypeAlias(
+ name=type_alias.name,
+ description=type_alias.docstring.value.split("\n", 1)[0] if type_alias.docstring else "",
+ )
+ for type_alias in type_aliases
+ if not check_public or type_alias.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.
+ """
+ # Handle leading dots in the identifier:
+ # - `.name` is a reference to the current object's `name` member.
+ # - `..name` is a reference to the parent object's `name` member.
+ # - etc.
+ # TODO: We should update the protocol to allow modifying the title too.
+ # In this case it would likely be better to strip dots from the title,
+ # when it's not explicitly specified.
+ if self.config.relative_crossrefs and identifier.startswith("."): # type: ignore[attr-defined]
+ identifier = identifier[1:]
+ obj = self.current_object
+ while identifier and identifier[0] == ".":
+ identifier = identifier[1:]
+ obj = obj.parent
+ identifier = f"{obj.path}.{identifier}" if identifier else obj.path
+
+ # We resolve the identifier to its full path.
+ # For this we take out the first name, resolve it, and then append the rest.
+ if self.config.scoped_crossrefs: # type: ignore[attr-defined]
+ if "." in identifier:
+ identifier, remaining = identifier.split(".", 1)
+ else:
+ remaining = ""
+ with suppress(Exception):
+ identifier = self.current_object.resolve(identifier)
+ if remaining:
+ identifier = f"{identifier}.{remaining}"
+
+ 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
+ lineno = self.current_object.docstring.lineno or 0
+ 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/handler.py b/src/mkdocstrings_handlers/python/handler.py
deleted file mode 100644
index 9cc60f31..00000000
--- a/src/mkdocstrings_handlers/python/handler.py
+++ /dev/null
@@ -1,502 +0,0 @@
-"""This module implements a handler for the Python language."""
-
-from __future__ import annotations
-
-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
-
-from griffe.collections import LinesCollection, ModulesCollection
-from griffe.docstrings.parsers import Parser
-from griffe.exceptions import AliasResolutionError
-from griffe.extensions import load_extensions
-from griffe.loader import GriffeLoader
-from griffe.logger import 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 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 parsers under [`griffe.docstrings`][].
- 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.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,
- )
diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py
deleted file mode 100644
index face49fe..00000000
--- a/src/mkdocstrings_handlers/python/rendering.py
+++ /dev/null
@@ -1,571 +0,0 @@
-"""This module implements rendering utilities."""
-
-from __future__ import annotations
-
-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 griffe.dataclasses import Alias, Object
-from griffe.docstrings.dataclasses import (
- DocstringSectionAttributes,
- DocstringSectionClasses,
- DocstringSectionFunctions,
- DocstringSectionModules,
-)
-from jinja2 import TemplateNotFound, pass_context, pass_environment
-from markupsafe import Markup
-from mkdocstrings.loggers import get_logger
-
-if TYPE_CHECKING:
- from griffe.dataclasses 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:
- warnings.warn(
- "The `crossref` filter is deprecated and will be removed in a future version",
- DeprecationWarning,
- stacklevel=1,
- )
-
-
-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:
- if rules == {False}:
- # only included stuff, no match = reject
- return False
- # only excluded stuff, or included and excluded stuff, no match = keep
- return True
- 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([])
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
deleted file mode 100644
index 7effc590..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 11bc4e77..65054689 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja
@@ -4,7 +4,7 @@ This template renders a Python attribute (or variable).
This can be a module attribute or a class attribute.
Context:
- attribute (griffe.dataclasses.Attribute): The attribute to render.
+ attribute (griffe.Attribute): The attribute to render.
root (bool): Whether this is the root object, injected with `:::` in a Markdown page.
heading_level (int): The HTML heading level to use.
config (dict): The configuration options.
@@ -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,32 +39,35 @@ 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),
+ skip_inventory=config.skip_local_inventory,
) %}
{% 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 %}
- {% if attribute.value %} = {{ attribute.value }}{% endif %}
+ {{ attribute_name }}{% if attribute.annotation and config.show_signature_annotations %}: {{ attribute.annotation }}{% endif %}
+ {% if config.show_attribute_values and attribute.value %} = {{ attribute.value }}{% endif %}
{% endfilter %}
{% endif %}
{% endblock heading %}
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the attribute.
-#}
{% with labels = attribute.labels %}
- {% include "labels"|get_template with context %}
+ {% include "labels.html.jinja" with context %}
{% endwith %}
{% endblock labels %}
@@ -72,11 +75,11 @@ Context:
{% block signature scoped %}
{#- Signature block.
-
+
This block renders the signature for the attribute.
-#}
{% if config.separate_signature %}
- {% filter format_attribute(attribute, config.line_length, crossrefs=config.signature_crossrefs) %}
+ {% filter format_attribute(attribute, config.line_length, crossrefs=config.signature_crossrefs, show_value=config.show_attribute_values) %}
{{ attribute.name }}
{% endfilter %}
{% endif %}
@@ -88,8 +91,9 @@ 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,
+ skip_inventory=config.skip_local_inventory,
) %}
{% endfilter %}
{% endif %}
@@ -99,20 +103,24 @@ Context:
'|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),
+ skip_inventory=config.skip_local_inventory,
) %}
{% 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__"] %}
+ {% elif config.merge_init_into_class and "__init__" in all_members %}
+ {% with function = all_members["__init__"] %}
{%+ filter highlight(language="python", inline=True) %}
- {{ class_name }}{% include "signature"|get_template with context %}
+ {{ class_name -}}
+ {%- with obj = function -%}
+ {%- include "type_parameters.html.jinja" with context -%}
+ {%- endwith -%}
+ {%- include "signature.html.jinja" with context -%}
{% endfilter %}
{% endwith %}
{% else %}
+ {# TODO: Maybe render type parameters here. #}
{{ class_name }}
{% endif %}
{% endblock heading %}
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the class.
-#}
{% with labels = class.labels %}
- {% include "labels"|get_template with context %}
+ {% include "labels.html.jinja" with context %}
{% endwith %}
{% endblock labels %}
@@ -74,17 +85,34 @@ 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 the class is generic, but the `__init__` method isn't or `merge_init_into_class` is disabled,
+ the class signature is rendered if `separate_signature` and `show_signature_type_parameters` are enabled.
+
+ If the `__init__` method or any overloads are generic, they are rendered as methods if
+ `merge_init_into_class`, `separate_signature` and `show_signature_type_parameters` are enabled.
-#}
- {% if config.separate_signature and config.merge_init_into_class %}
- {% if "__init__" in class.all_members %}
- {% with function = class.all_members["__init__"] %}
+ {% if config.merge_init_into_class and "__init__" in all_members %}
+ {% with function = all_members["__init__"] %}
+ {% if function.overloads and config.show_overloads %}
+ '|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,
+ skip_inventory=config.skip_local_inventory,
) %}
{% endfilter %}
{% endif %}
@@ -104,53 +133,123 @@ Context:
Bases: {% for expression in class.bases -%}
- {% include "expression"|get_template with context %}{% if not loop.last %}, {% endif %}
+
+ {%- with backlink_type = "subclassed-by" -%}
+ {%- include "expression.html.jinja" with context -%}
+ {%- endwith -%}
+ {% if not loop.last %}, {% endif %}
{% endfor -%}
+ flowchart {{ config.inheritance_diagram_direction }}
+ {{ class.path }}[{{ class.name }}]
+ {% for base in class.mro() %}
+ {{ base.path }}[{{ base.name }}]
+ {% endfor %}
+
+ {{ edges(class) | safe }}
+
+ click {{ class.path }} href "" "{{ class.path }}"
+ {% for base in class.mro() %}
+ click {{ base.path }} href "" "{{ base.path }}"
+ {% endfor %}
+
+
+ {% endif %}
+ {% endblock inheritance_diagram %}
+
{% block docstring scoped %}
{#- Docstring block.
-
+
This block renders the docstring for the class.
-#}
{% with docstring_sections = class.docstring.parsed %}
- {% include "docstring"|get_template with context %}
+ {% include "docstring.html.jinja" 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 %}
+ {% include "docstring.html.jinja" with context %}
+ {% endwith %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
{% endif %}
{% endblock docstring %}
+ {% if config.backlinks %}
+
+ {% if "__init__" in all_members and all_members["__init__"].source %}
+ {% with init = all_members["__init__"] %}
+
+ {{ lang.t("Source code in") }}
{%- if init.relative_filepath.is_absolute() -%}
{{ init.relative_package_filepath }}
{%- else -%}
@@ -162,8 +261,8 @@ Context:
{% endwith %}
{% endif %}
{% elif class.source %}
-
- Source code in
+
+ {{ lang.t("Source code in") }}
{%- if class.relative_filepath.is_absolute() -%}
{{ class.relative_package_filepath }}
{%- else -%}
@@ -178,12 +277,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 %}
- {% include "children"|get_template with context %}
+ {% include "children.html.jinja" with context %}
{% endblock children %}
{% endblock contents %}
{{ attribute.name }}{{ attribute.name }} {% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ attribute.name }}
+ {{ attribute.name }}
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
- ({% include "expression"|get_template with context %})
+ ({% include "expression.html.jinja" with context %})
{% endwith %}
{% endif %}
–
{{ attribute.name }}{{ attribute.name }}
{% if attribute.annotation %}
- TYPE:
+ {{ lang.t("TYPE:") }}
{% with expression = attribute.annotation %}
- {% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
deleted file mode 100644
index 78b47e2d..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 1aee5fd2..b139a761 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
@@ -4,18 +4,18 @@ This template renders a list of documented classes in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% 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 %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
{% if config.docstring_section_style == "table" %}
@@ -32,10 +32,10 @@ Context:
{{ class.name }}{{ class.name }} {{ class.name }}
+ {{ class.name }}
–
{{ class.name }}{{ class.name }} {{ section.title or lang.t("Examples:") }}
{% for section_type, sub_section in section.value %} {% if section_type.value == "text" %} - {{ sub_section|convert_markdown(heading_level, html_id) }} + {{ sub_section|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }} {% elif section_type.value == "examples" %} - {{ sub_section|highlight(language="pycon", linenums=False) }} + {{ 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 deleted file mode 100644 index a61c48fb..00000000 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html +++ /dev/null @@ -1,11 +0,0 @@ -{% 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.", - 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 53bda233..afec8f60 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 @@ -4,18 +4,18 @@ This template renders a list of documented functions in the format specified with the [`docstring_section_style`][] configuration option. Context: - section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render. + section (griffe.DocstringSectionAttributes): The section to render. -#} {% 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 %} -{% import "language"|get_template as lang with context %} +{% import "language.html.jinja" as lang with context %} {#- Language module providing the `t` translation method. -#} {% if config.docstring_section_style == "table" %} @@ -33,10 +33,10 @@ Context: {% for function in section.value %} {% if not function.name == "__init__" or not config.merge_init_into_class %}{{ function.name }}{{ function.name }} {{ function.name }}
+ {{ function.name }}
–
{{ function.name }}{{ function.name }} {{ module.name }}{{ module.name }} {{ module.name }}
+ {{ module.name }}
–
{{ module.name }}{{ module.name }} {{ parameter.name }}{% include "expression"|get_template with context %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ parameter.name }}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
- ({% include "expression"|get_template with context %})
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ ({% include "expression.html.jinja" with context %})
{% endwith %}
{% endif %}
–
{{ parameter.name }}
{% if parameter.annotation %}
{{ lang.t("TYPE:") }}
- {% with expression = parameter.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
deleted file mode 100644
index f5745464..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 3de6f4a9..a67113fa 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
@@ -4,18 +4,18 @@ This template renders a list of documented parameters in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% 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 %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
{% if config.docstring_section_style == "table" %}
@@ -34,23 +34,38 @@ Context:
{{ parameter.name }} '|safe if config.show_symbol_type_toc else '') + parameter.name,
+ skip_inventory=config.skip_local_inventory,
+ ) %}
+ {{ parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ parameter.name }}
+ {% endif %}
+ {% include "expression"|get_template with context %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{% include "expression"|get_template with context %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% else %}
{{ lang.t("required") }}
@@ -68,20 +83,33 @@ Context:
{{ 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,
+ skip_inventory=config.skip_local_inventory,
+ ) %}
+ {{ parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ parameter.name }}
+ {% endif %}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
- ({% include "expression"|get_template with context %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ ({% include "expression.html.jinja" with context %}
{%- if parameter.default %}, {{ lang.t("default:") }}
- {% with expression = parameter.default %}
- {% include "expression"|get_template with context %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %})
{% endwith %}
{% endif %}
–
{{ parameter.name }} '|safe if config.show_symbol_type_toc else '') + parameter.name,
+ skip_inventory=config.skip_local_inventory,
+ ) %}
+ {{ parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ parameter.name }}
+ {% endif %}
+
{% if parameter.annotation %}
{{ lang.t("TYPE:") }}
- {% with expression = parameter.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{% if parameter.default %}
{{ lang.t("DEFAULT:") }}
- {% with expression = parameter.default %}
- {% include "expression"|get_template with context %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
deleted file mode 100644
index 361b9732..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 79024057..7d548035 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
@@ -4,18 +4,18 @@ This template renders a list of documented exceptions in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% 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 %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
{% if config.docstring_section_style == "table" %}
@@ -34,14 +34,14 @@ Context:
{% include "expression"|get_template with context %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{% include "expression"|get_template with context %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
–
{% endif %}
{% include "expression"|get_template with context %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{{ receives.name }}{% endif %}{% include "expression"|get_template with context %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ receives.name }}{% endif %}
{% if receives.annotation %}
- {% with expression = receives.annotation %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
{% if receives.name %} ({% endif %}
- {% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% if receives.name %}){% endif %}
{% endwith %}
{% endif %}
–
{{ receives.name }}
{% elif receives.annotation %}
- {% with expression = receives.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ lang.t("TYPE:") }}
- {% with expression = receives.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = receives.annotation, backlink_type = "received-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{{ returns.name }}{% endif %}{% include "expression"|get_template with context %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ returns.name }}{% endif %}
{% if returns.annotation %}
- {% with expression = returns.annotation %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
{% if returns.name %} ({% endif %}
- {% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% if returns.name %}){% endif %}
{% endwith %}
{% endif %}
–
{{ returns.name }}
{% elif returns.annotation %}
- {% with expression = returns.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ lang.t("TYPE:") }}
- {% with expression = returns.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{{ section.title or lang.t("Type Aliases:") }}
+| {{ lang.t("Name") }} | +{{ lang.t("Description") }} | +
|---|---|
|
+
+
+ {{ type_alias.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
+
+ |
+
{{ section.title or lang.t("Type Aliases:") }}
+{{ type_alias.name }}
+ –
+ | {{ (section.title or lang.t("TYPE ALIAS")).rstrip(":").upper() }} | +{{ lang.t("DESCRIPTION") }} | +
|---|---|
|
+
+
+ {{ type_alias.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
+
+ |
+
+ + {{ section.title or lang.t(("Class " if obj.is_class else "Init " if obj.is_init_method else "") ~ "Type Parameters:") }} + +
+| {{ lang.t("Name") }} | +{{ lang.t("Bound or Constraints") }} | +{{ lang.t("Description") }} | +{{ lang.t("Default") }} | +
|---|---|---|---|
+ {% if config.type_parameter_headings %}
+ {% filter heading(
+ heading_level + 1,
+ role="typeparam",
+ id=obj.path ~ "[" ~ type_parameter.name ~ "]",
+ class="doc doc-heading doc-heading-type_parameter",
+ toc_label=(' '|safe if config.show_symbol_type_toc else '') + type_parameter.name,
+ ) %}
+ {{ type_parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ type_parameter.name }}
+ {% endif %}
+ |
+
+ {% if type_parameter.annotation %}
+ {% with expression = type_parameter.annotation %}
+ {% include "expression.html.jinja" with context %}
+ {% endwith %}
+ {% endif %}
+ |
+
+
+ {{ type_parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
+
+ |
+
+ {% if type_parameter.default %}
+ {% with expression = type_parameter.default %}
+ {% include "expression.html.jinja" with context %}
+ {% endwith %}
+ {% else %}
+ {{ lang.t("required") }}
+ {% endif %}
+ |
+
+ + {{ section.title or lang.t(("Class " if obj.is_class else "Init " if obj.is_init_method else "") ~ "Type Parameters:") }} + +
+ '|safe if config.show_symbol_type_toc else '') + type_parameter.name,
+ ) %}
+ {{ type_parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ type_parameter.name }}
+ {% endif %}
+ {%- if type_parameter.bound or type_parameter.constraints or type_parameter.default -%}
+ (
+ {%- endif -%}
+ {%- if type_parameter.bound -%}
+ {%- with expression = type_parameter.bound -%}
+ {% include "expression.html.jinja" with context %}
+ {%- endwith -%}
+ {%- if type_parameter.default %}, {% endif -%}
+ {%- elif type_parameter.constraints -%}
+ {%- for expression in type_parameter.constraints -%}
+ {% include "expression.html.jinja" with context %}
+ {%- if not loop.last %}, {% endif -%}
+ {%- endfor -%}
+ {%- if type_parameter.default %}, {% endif -%}
+ {%- endif -%}
+ {%- if type_parameter.default -%}
+ {{ lang.t("default:") }}
+ {% with expression = type_parameter.default %}
+ {% include "expression.html.jinja" with context %}
+ {%- endwith -%}
+ {%- endif -%}
+ {%- if type_parameter.constraints or type_parameter.default -%}
+ )
+ {% endif -%}
+ –
+ | + + {{ (section.title or lang.t(("CLASS " if obj.is_class else "INIT " if obj.is_init_method else "") ~ "TYPE PARAMETER")).rstrip(":").upper() }} + + | +{{ lang.t("DESCRIPTION") }} | +
|---|---|
+ {% if config.type_parameter_headings %}
+ {% filter heading(
+ heading_level + 1,
+ role="typeparam",
+ id=obj.path ~ "[" ~ type_parameter.name ~ "]",
+ class="doc doc-heading doc-heading-type_parameter",
+ toc_label=(' '|safe if config.show_symbol_type_toc else '') + type_parameter.name,
+ ) %}
+ {{ type_parameter.name }}
+ {% endfilter %}
+ {% else %}
+ {{ type_parameter.name }}
+ {% endif %}
+ |
+
+
+ {{ type_parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
+
+
+ {% if type_parameter.constraints %}
+
+ {{ lang.t("CONSTRAINTS:") }}
+ {% for constraint in type_parameter.constraints -%}
+ {%- with expression = constraint -%}
+ |
+
{% include "expression"|get_template with context %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{% include "expression"|get_template with context %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
–
{% endif %}
{% include "expression"|get_template with context %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{{ yields.name }}{% endif %}{% include "expression"|get_template with context %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ yields.name }}{% endif %}
{% if yields.annotation %}
- {% with expression = yields.annotation %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
{% if yields.name %} ({% endif %}
- {% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% if yields.name %}){% endif %}
{% endwith %}
{% endif %}
–
{{ yields.name }}
{% elif yields.annotation %}
- {% with expression = yields.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
{{ lang.t("TYPE:") }}:
- {% with expression = yields.annotation %}
- {% include "expression"|get_template with context %}
+ {% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
')|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),
+ skip_inventory=config.skip_local_inventory,
) %}
{% 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) %}
- {{ function_name }}{% include "signature"|get_template with context %}
- {% endfilter %}
+ {%+ filter highlight(language="python", inline=True) -%}
+ {{ function_name }}
+ {%- include "type_parameters.html.jinja" with context -%}
+ {%- include "signature.html.jinja" with context -%}
+ {%- endfilter %}
{% endif %}
{% endblock heading %}
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the function.
-#}
{% with labels = function.labels %}
- {% include "labels"|get_template with context %}
+ {% include "labels.html.jinja" with context %}
{% endwith %}
{% endblock labels %}
@@ -76,10 +81,20 @@ 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 config.separate_signature %}
+ {% if function.overloads and config.show_overloads %}
+ ')|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,
+ skip_inventory=config.skip_local_inventory,
) %}
{% endfilter %}
{% endif %}
@@ -104,28 +120,32 @@ Context:
{%- if function.relative_filepath.is_absolute() -%}
{{ function.relative_package_filepath }}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
deleted file mode 100644
index 784150c4..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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
deleted file mode 100644
index c97d0c31..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/language.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..31ecfdd6 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,17 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
-{% set lang_pth = "languages/" ~ locale | get_template %}
+{% set lang_pth = "languages/" ~ locale ~ ".html.jinja" %}
{% 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 %}
+ {% import "languages/en.html.jinja" 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 %}
+ {% import "languages/en.html.jinja" 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
deleted file mode 100644
index eab87415..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..d2bbba03 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,26 +2,37 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
{% macro t(key) %}{{ {
"ATTRIBUTE": "ATTRIBUTE",
+ "Attributes": "Attributes",
"Attributes:": "Attributes:",
+ "BOUND:": "BOUND:",
+ "Bound or Constraints": "Bound or Constraints",
+ "Classes": "Classes",
"Classes:": "Classes:",
+ "Class Type Parameters:": "Class Type Parameters:",
+ "CLASS TYPE PARAMETER": "CLASS TYPE PARAMETER",
"CLASS": "CLASS",
+ "CONSTRAINTS:": "CONSTRAINTS:",
"DEFAULT:": "DEFAULT:",
"Default": "Default",
"default:": "default:",
"DESCRIPTION": "DESCRIPTION",
"Description": "Description",
"Examples:": "Examples:",
+ "Functions": "Functions",
"Functions:": "Functions:",
"FUNCTION": "FUNCTION",
+ "Init Type Parameters:": "Init Type Parameters:",
+ "INIT TYPE PARAMETER": "INIT TYPE PARAMETER",
"Methods:": "Methods:",
"METHOD": "METHOD",
+ "Modules": "Modules",
"Modules:": "Modules:",
"MODULE": "MODULE",
"Name": "Name",
@@ -38,6 +49,11 @@
"Source code in": "Source code in",
"TYPE:": "TYPE:",
"Type": "Type",
+ "Type Aliases": "Type Aliases",
+ "Type Aliases:": "Type Aliases:",
+ "TYPE ALIAS": "TYPE ALIAS",
+ "Type Parameters:": "Type Parameters:",
+ "TYPE PARAMETER": "TYPE PARAMETER",
"WARNS": "WARNS",
"Warns:": "Warns:",
"YIELDS": "YIELDS",
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
deleted file mode 100644
index 14319499..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..840da89c 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,28 +2,39 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
{% macro t(key) %}{{ {
"ATTRIBUTE": "属性",
+ "Attributes": "属性",
"Attributes:": "属性:",
- "Classes:": "",
- "CLASS": "",
+ "BOUND:": "境界:",
+ "Bound or Constraints": "境界や制約",
+ "Classes": "クラス",
+ "Classes:": "クラス:",
+ "Class Type Parameters:": "Class Type Parameters:",
+ "CLASS TYPE PARAMETER": "CLASS TYPE PARAMETER",
+ "CLASS": "クラス",
+ "CONSTRAINTS:": "制約:",
"DEFAULT:": "デフォルト:",
"Default": "デフォルト",
"default:": "デフォルト:",
"DESCRIPTION": "デスクリプション",
"Description": "デスクリプション",
"Examples:": "例:",
- "Functions:": "",
- "FUNCTION": "",
- "Methods:": "",
- "METHOD": "",
- "Modules:": "",
- "MODULE": "",
+ "Functions": "関数",
+ "Functions:": "関数:",
+ "FUNCTION": "関数",
+ "Init Type Parameters:": "Init Type Parameters:",
+ "INIT TYPE PARAMETER": "INIT TYPE PARAMETER",
+ "Methods:": "メソッド:",
+ "METHOD": "メソッド",
+ "Modules": "モジュール",
+ "Modules:": "モジュール:",
+ "MODULE": "モジュール",
"Name": "名前",
"Other Parameters:": "他の引数:",
"PARAMETER": "引数",
@@ -38,6 +49,11 @@
"Source code in": "ソースコード位置:",
"TYPE:": "タイプ:",
"Type": "タイプ",
+ "Type Aliases": "型エイリアス",
+ "Type Aliases:": "型エイリアス:",
+ "TYPE ALIAS": "型エイリアス",
+ "Type Parameters:": "型パラメータ:",
+ "TYPE PARAMETER": "型パラメータ",
"WARNS": "警告",
"Warns:": "警告:",
"YIELDS": "返す",
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
deleted file mode 100644
index 0b281195..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..53888779 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,28 +2,39 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
{% macro t(key) %}{{ {
"ATTRIBUTE": "属性",
+ "Attributes": "属性",
"Attributes:": "属性:",
- "Classes:": "",
- "CLASS": "",
+ "BOUND:": "边界:",
+ "Bound or Constraints": "边界或约束",
+ "Classes": "类",
+ "Classes:": "类:",
+ "Class Type Parameters:": "Class Type Parameters:",
+ "CLASS TYPE PARAMETER": "CLASS TYPE PARAMETER",
+ "CLASS": "类",
+ "CONSTRAINTS:": "约束:",
"DEFAULT:": "默认:",
"Default": "默认",
"default:": "默认:",
"DESCRIPTION": "描述",
"Description": "描述",
"Examples:": "示例:",
- "Functions:": "",
- "FUNCTION": "",
- "Methods:": "",
- "METHOD": "",
- "Modules:": "",
- "MODULE": "",
+ "Functions": "函数",
+ "Functions:": "函数:",
+ "FUNCTION": "函数",
+ "Init Type Parameters:": "Init Type Parameters:",
+ "INIT TYPE PARAMETER": "INIT TYPE PARAMETER",
+ "Methods:": "方法:",
+ "METHOD": "方法",
+ "Modules": "模块",
+ "Modules:": "模块:",
+ "MODULE": "模块",
"Name": "名称",
"Other Parameters:": "其他参数:",
"PARAMETER": "参数",
@@ -38,6 +49,11 @@
"Source code in": "源代码位于:",
"TYPE:": "类型:",
"Type": "类型",
+ "Type Aliases": "类型别名",
+ "Type Aliases:": "类型别名:",
+ "TYPE ALIAS": "类型别名",
+ "Type Parameters:": "类型形参:",
+ "TYPE PARAMETER": "类型形参",
"Warns:": "警告:",
"WARNS": "警告",
"YIELDS": "产生",
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/module.html b/src/mkdocstrings_handlers/python/templates/material/_base/module.html
deleted file mode 100644
index 918ab6d0..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 06870b98..c0f4a7cb 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja
@@ -3,7 +3,7 @@
This template renders a Python module.
Context:
- module (griffe.dataclasses.Module): The module to render.
+ module (griffe.Module): The module to render.
root (bool): Whether this is the root object, injected with `:::` in a Markdown page.
heading_level (int): The HTML heading level to use.
config (dict): The configuration options.
@@ -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,19 @@ 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),
+ skip_inventory=config.skip_local_inventory,
) %}
{% 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,11 +59,11 @@ Context:
{% block labels scoped %}
{#- Labels block.
-
+
This block renders the labels for the module.
-#}
{% with labels = module.labels %}
- {% include "labels"|get_template with context %}
+ {% include "labels.html.jinja" with context %}
{% endwith %}
{% endblock labels %}
@@ -71,8 +74,9 @@ 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,
+ skip_inventory=config.skip_local_inventory,
) %}
{% endfilter %}
{% endif %}
@@ -82,29 +86,41 @@ 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 %}
- {% include "docstring"|get_template with context %}
+ {% include "docstring.html.jinja" with context %}
{% endwith %}
{% endblock docstring %}
+ {% if config.backlinks %}
+
+ {% endif %}
+
+ {% block summary scoped %}
+ {#- Summary block.
+
+ This block renders auto-summaries for classes, methods, and attributes.
+ -#}
+ {% include "summary.html.jinja" 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 %}
- {% include "children"|get_template with context %}
+ {% include "children.html.jinja" 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
deleted file mode 100644
index 623879db..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 2d87986c..7167f1d7 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja
@@ -5,14 +5,14 @@ It iterates over the parameters of the function to rebuild the signature.
The signature is the list of parameters of a function or method, including their names, default values, and annotations.
Context:
- function (griffe.dataclasses.Function): The function or method to render.
+ function (griffe.Function): The function or method to render.
config (dict): The configuration options.
-#}
{%- 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,11 @@ 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" -%}
+ {%- include "expression.html.jinja" with context -%}
+ {%- endwith -%}{%- endset -%}
{%- endwith -%}
{%- else -%}
{%- set ns.annotation = ": " + parameter.annotation|safe -%}
@@ -60,7 +63,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 +73,45 @@ 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" -%}
+ {%- include "expression.html.jinja" with context -%}
+ {%- endwith -%}
+ {%- else -%}
+ {{ parameter.default|safe }}
+ {%- endif -%}
+ {%- endif -%}
+
{%- if not loop.last %}, {% endif -%}
{%- endif -%}
@@ -82,7 +123,9 @@ 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" -%}
+ {%- include "expression.html.jinja" 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
deleted file mode 100644
index aa33dc9c..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..852af437 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 %}
+ {% include "summary/modules.html.jinja" with context %}
+ {% endif %}
+
+ {% if config.summary.type_aliases %}
+ {% include "summary/type_aliases.html.jinja" with context %}
+ {% endif %}
+
+ {% if config.summary.classes %}
+ {% include "summary/classes.html.jinja" with context %}
+ {% endif %}
+
+ {% if config.summary.functions %}
+ {% include "summary/functions.html.jinja" with context %}
+ {% endif %}
+
+ {% if config.summary.attributes %}
+ {% include "summary/attributes.html.jinja" 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
deleted file mode 100644
index f2643791..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..be42ed0f 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,22 @@
{% 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)
+ %}
+ {% if section %}{% include "docstring/attributes.html.jinja" 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
deleted file mode 100644
index 5c6275b4..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..3c0406dd 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,22 @@
{% 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)
+ %}
+ {% if section %}{% include "docstring/classes.html.jinja" 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
deleted file mode 100644
index 31887e0a..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..9fc6ea87 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,22 @@
{% 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)
+ %}
+ {% if section %}{% include "docstring/functions.html.jinja" 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
deleted file mode 100644
index 31dcb5f0..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..6206c6d1 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,22 @@
{% 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)
+ %}
+ {% if section %}{% include "docstring/modules.html.jinja" with context %}{% endif %}
+ {% endwith %}
+{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/type_aliases.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/type_aliases.html.jinja
new file mode 100644
index 00000000..ed0d2ef5
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/type_aliases.html.jinja
@@ -0,0 +1,23 @@
+{#- Summary of type aliases. -#}
+
+{% 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", "type aliases") | list %}
+ {% with section = obj.type_aliases
+ |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_type_aliases_section(check_public=not members_list)
+ %}
+ {% if section %}{% include "docstring/type_aliases.html.jinja" with context %}{% endif %}
+ {% endwith %}
+{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/type_alias.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/type_alias.html.jinja
new file mode 100644
index 00000000..ff1e8464
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/type_alias.html.jinja
@@ -0,0 +1,117 @@
+{#- Template for Python type aliases.
+
+This template renders a Python type alias.
+
+Context:
+ type_alias (griffe.TypeAlias): The type alias to render.
+ root (bool): Whether this is the root object, injected with `:::` in a Markdown page.
+ heading_level (int): The HTML heading level to use.
+ config (dict): The configuration options.
+-#}
+
+{% block logs scoped %}
+ {#- Logging block.
+
+ This block can be used to log debug messages, deprecation messages, warnings, etc.
+ -#}
+ {{ log.debug("Rendering " + type_alias.path) }}
+{% endblock logs %}
+
+
+ {% with obj = type_alias, html_id = type_alias.path %}
+
+ {% if root %}
+ {% set show_full_path = config.show_root_full_path %}
+ {% set root_members = True %}
+ {% elif root_members %}
+ {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %}
+ {% set root_members = False %}
+ {% else %}
+ {% set show_full_path = config.show_object_full_path %}
+ {% endif %}
+
+ {% set type_alias_name = type_alias.path if show_full_path else type_alias.name %}
+
+ {% if not root or config.show_root_heading %}
+ {% filter heading(
+ heading_level,
+ role="typealias",
+ id=html_id,
+ class="doc doc-heading",
+ toc_label=(' '|safe if config.show_symbol_type_toc else '') + type_alias.name,
+ ) %}
+
+ {% block heading scoped %}
+ {#- Heading block.
+
+ This block renders the heading for the type alias.
+ -#}
+ {% if config.show_symbol_type_heading %}{% endif %}
+ {% if config.separate_signature %}
+ {{ type_alias_name }}
+ {% else %}
+ {%+ filter highlight(language="python", inline=True) %}
+ {{ type_alias_name }}{% include "type_parameters.html.jinja" with context %} = {{ type_alias.value }}
+ {% endfilter %}
+ {% endif %}
+ {% endblock heading %}
+
+ {% block labels scoped %}
+ {#- Labels block.
+
+ This block renders the labels for the type alias.
+ -#}
+ {% with labels = type_alias.labels %}
+ {% include "labels.html.jinja" with context %}
+ {% endwith %}
+ {% endblock labels %}
+
+ {% endfilter %}
+
+ {% block signature scoped %}
+ {#- Signature block.
+
+ This block renders the signature for the type alias.
+ -#}
+ {% if config.separate_signature %}
+ {% filter format_type_alias(type_alias, config.line_length, crossrefs=config.signature_crossrefs) %}
+ {{ type_alias.name }}
+ {% endfilter %}
+ {% endif %}
+ {% endblock signature %}
+
+ {% else %}
+ {% if config.show_root_toc_entry %}
+ {% filter heading(heading_level,
+ role="typealias",
+ id=html_id,
+ toc_label=(' '|safe if config.show_symbol_type_toc else '') + type_alias.name,
+ hidden=True,
+ ) %}
+ {% endfilter %}
+ {% endif %}
+ {% set heading_level = heading_level - 1 %}
+ {% endif %}
+
+
+ {% block contents scoped %}
+ {#- Contents block.
+
+ This block renders the contents of the type alias.
+ 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 type alias.
+ -#}
+ {% with docstring_sections = type_alias.docstring.parsed %}
+ {% include "docstring.html.jinja" with context %}
+ {% endwith %}
+ {% endblock docstring %}
+ {% endblock contents %}
+
+
+ {% endwith %}
+
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/type_parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/type_parameters.html.jinja
new file mode 100644
index 00000000..47100924
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/type_parameters.html.jinja
@@ -0,0 +1,87 @@
+{#- Template for type parameters.
+
+This template renders the type parameters of a generic obj.
+It iterates over the type parameters of the object to rebuild the signature.
+The signature is the list of type parameters of a generic object, including their names, default values, and bound or constraints.
+
+Context:
+ obj (griffe.Object): The object to render.
+ config (dict): The configuration options.
+-#}
+
+{%- if config.show_signature_type_parameters -%}
+ {%- block logs scoped -%}
+ {#- Logging block.
+
+ This block can be used to log debug messages, deprecation messages, warnings, etc.
+ -#}
+ {{ log.debug("Rendering type parameters") }}
+ {%- endblock logs -%}
+
+ {%- with ns = namespace(annotation="", equal="=", default=False) -%}
+ {%- if obj.is_generic -%}
+ [
+ {%- for type_parameter in obj.type_parameters -%}
+ {#- Prepare type bound or constraints. -#}
+ {%- if config.show_signature_annotations and type_parameter.annotation is not none -%}
+ {%- set ns.equal = " = " -%}
+ {%- if config.separate_signature and config.signature_crossrefs -%}
+ {%- with expression = type_parameter.annotation -%}
+ {%- set ns.annotation -%}: {% include "expression.html.jinja" with context %}{%- endset -%}
+ {%- endwith -%}
+ {%- else -%}
+ {%- set ns.annotation = ": " + type_parameter.annotation|safe -%}
+ {%- endif -%}
+ {%- else -%}
+ {%- set ns.equal = "=" -%}
+ {%- set ns.annotation = "" -%}
+ {%- endif -%}
+
+ {#- Prepare default value. -#}
+ {%- if type_parameter.default is not none -%}
+ {%- set ns.default = True -%}
+ {%- else -%}
+ {%- set ns.default = False -%}
+ {%- endif -%}
+
+ {#- Prepare name. -#}
+ {%- set type_param_prefix -%}
+ {%- if type_parameter.kind == "type-var-tuple" -%}
+ *
+ {%- elif type_parameter.kind == "param-spec" -%}
+ **
+ {%- endif -%}
+ {%- endset -%}
+
+ {#- Render type parameter name with optional cross-reference to its heading. -#}
+ {{ type_param_prefix }}
+ {%- if config.separate_signature and config.type_parameter_headings and config.signature_crossrefs -%}
+ {%- filter stash_crossref(length=type_parameter.name|length) -%}
+ {{ type_parameter.name }}
+ {%- endfilter -%}
+ {%- else -%}
+ {{ type_parameter.name }}
+ {%- endif -%}
+
+ {#- Render type parameter bound or constraints. -#}
+ {{ ns.annotation }}
+
+ {#- Render type parameter default value. -#}
+ {%- if ns.default -%}
+ {{ ns.equal }}
+ {%- if config.signature_crossrefs and config.separate_signature -%}
+ {%- with expression = type_parameter.default -%}
+ {%- include "expression.html.jinja" with context -%}
+ {%- endwith -%}
+ {%- else -%}
+ {{ type_parameter.default|safe }}
+ {%- endif -%}
+ {%- endif -%}
+
+ {%- if not loop.last %}, {% endif -%}
+ {%- endfor -%}
+ ]
+ {%- endif -%}
+
+ {%- endwith -%}
+{%- endif -%}
diff --git a/src/mkdocstrings_handlers/python/templates/material/attribute.html b/src/mkdocstrings_handlers/python/templates/material/attribute.html
deleted file mode 100644
index a3c27503..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/attribute.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 2c2a73ab..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/children.html
+++ /dev/null
@@ -1 +0,0 @@
-{% extends "_base/children.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring.html b/src/mkdocstrings_handlers/python/templates/material/docstring.html
deleted file mode 100644
index a7ccd66c..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index e9da5e9a..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 4ac364b0..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 035b3102..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 34e9c4ba..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index f3eaed78..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 8ea02a33..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 7c50379b..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 70c557fb..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index f8c3cf03..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 004ff00e..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 979ce9ef..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html
+++ /dev/null
@@ -1 +0,0 @@
-{% extends "_base/docstring/returns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/type_aliases.html b/src/mkdocstrings_handlers/python/templates/material/docstring/type_aliases.html
new file mode 100644
index 00000000..78bd497a
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/type_aliases.html
@@ -0,0 +1 @@
+{% extends "_base/docstring/type_aliases.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/type_aliases.html.jinja b/src/mkdocstrings_handlers/python/templates/material/docstring/type_aliases.html.jinja
new file mode 100644
index 00000000..78bd497a
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/type_aliases.html.jinja
@@ -0,0 +1 @@
+{% extends "_base/docstring/type_aliases.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/type_parameters.html b/src/mkdocstrings_handlers/python/templates/material/docstring/type_parameters.html
new file mode 100644
index 00000000..223fbb04
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/type_parameters.html
@@ -0,0 +1 @@
+{% extends "_base/docstring/type_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/type_parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/material/docstring/type_parameters.html.jinja
new file mode 100644
index 00000000..223fbb04
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/type_parameters.html.jinja
@@ -0,0 +1 @@
+{% extends "_base/docstring/type_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
deleted file mode 100644
index bb06cc85..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 717ef5d4..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 60c64d79..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/expression.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 54bba061..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/function.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 51cb29d6..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/labels.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index b905cff4..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/language.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 931967c1..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/languages/en.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 17070edf..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/languages/ja.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index e4ea3116..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/languages/zh.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 9d8efea5..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/module.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 33b266c8..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/signature.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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..7bb97041 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 {
@@ -21,42 +26,95 @@
}
/* Defaults in Spacy table style. */
-.doc-param-default {
+.doc-param-default,
+.doc-type_param-default {
float: right;
}
+/* Parameter headings must be inline, not blocks. */
+.doc-heading-parameter,
+.doc-heading-type_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,
+.doc-heading-type_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-type_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-type_alias-fg-color: #0550ae;
--doc-symbol-module-fg-color: #5cad0f;
+ --doc-symbol-parameter-bg-color: #df50af1a;
+ --doc-symbol-type_parameter-bg-color: #df50af1a;
--doc-symbol-attribute-bg-color: #9538001a;
--doc-symbol-function-bg-color: #8250df1a;
--doc-symbol-method-bg-color: #8250df1a;
--doc-symbol-class-bg-color: #0550ae1a;
+ --doc-symbol-type_alias-bg-color: #0550ae1a;
--doc-symbol-module-bg-color: #5cad0f1a;
}
[data-md-color-scheme="slate"] {
+ --doc-symbol-parameter-fg-color: #ffa8cc;
+ --doc-symbol-type_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-type_alias-fg-color: #79c0ff;
--doc-symbol-module-fg-color: #baff79;
+ --doc-symbol-parameter-bg-color: #ffa8cc1a;
+ --doc-symbol-type_parameter-bg-color: #ffa8cc1a;
--doc-symbol-attribute-bg-color: #ffa6571a;
--doc-symbol-function-bg-color: #d2a8ff1a;
--doc-symbol-method-bg-color: #d2a8ff1a;
--doc-symbol-class-bg-color: #79c0ff1a;
+ --doc-symbol-type_alias-bg-color: #79c0ff1a;
--doc-symbol-module-bg-color: #baff791a;
}
@@ -67,7 +125,28 @@ 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-type_parameter,
+a code.doc-symbol-type_parameter {
+ color: var(--doc-symbol-type_parameter-fg-color);
+ background-color: var(--doc-symbol-type_parameter-bg-color);
+}
+
+code.doc-symbol-type_parameter::after {
+ content: "type-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 +155,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 +165,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 +175,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 +185,19 @@ code.doc-symbol-class::after {
content: "class";
}
-code.doc-symbol-module {
+
+code.doc-symbol-type_alias,
+a code.doc-symbol-type_alias {
+ color: var(--doc-symbol-type_alias-fg-color);
+ background-color: var(--doc-symbol-type_alias-bg-color);
+}
+
+code.doc-symbol-type_alias::after {
+ content: "type";
+}
+
+code.doc-symbol-module,
+a code.doc-symbol-module {
color: var(--doc-symbol-module-fg-color);
background-color: var(--doc-symbol-module-bg-color);
}
@@ -116,3 +210,27 @@ code.doc-symbol-module::after {
color: inherit;
border-bottom: 1px dotted currentcolor;
}
+
+/* Source code blocks (admonitions). */
+:root {
+ --md-admonition-icon--mkdocstrings-source: url('data:image/svg+xml;charset=utf-8,')
+}
+.md-typeset .admonition.mkdocstrings-source,
+.md-typeset details.mkdocstrings-source {
+ border: none;
+ padding: 0;
+}
+.md-typeset .admonition.mkdocstrings-source:focus-within,
+.md-typeset details.mkdocstrings-source:focus-within {
+ box-shadow: none;
+}
+.md-typeset .mkdocstrings-source > .admonition-title,
+.md-typeset .mkdocstrings-source > summary {
+ background-color: inherit;
+}
+.md-typeset .mkdocstrings-source > .admonition-title::before,
+.md-typeset .mkdocstrings-source > summary::before {
+ background-color: var(--md-default-fg-color);
+ -webkit-mask-image: var(--md-admonition-icon--mkdocstrings-source);
+ mask-image: var(--md-admonition-icon--mkdocstrings-source);
+}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary.html b/src/mkdocstrings_handlers/python/templates/material/summary.html
deleted file mode 100644
index 59eddea0..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/summary.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index c69755c6..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 825eb1bb..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/summary/classes.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index fc609bda..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/summary/functions.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 46db0023..00000000
--- a/src/mkdocstrings_handlers/python/templates/material/summary/modules.html
+++ /dev/null
@@ -1 +0,0 @@
-{% extends "_base/summary/modules.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/type_aliases.html b/src/mkdocstrings_handlers/python/templates/material/summary/type_aliases.html
new file mode 100644
index 00000000..ca10bc88
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/type_aliases.html
@@ -0,0 +1 @@
+{% extends "_base/summary/type_aliases.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/type_aliases.html.jinja b/src/mkdocstrings_handlers/python/templates/material/summary/type_aliases.html.jinja
new file mode 100644
index 00000000..ca10bc88
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/type_aliases.html.jinja
@@ -0,0 +1 @@
+{% extends "_base/summary/type_aliases.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/type_alias.html b/src/mkdocstrings_handlers/python/templates/material/type_alias.html
new file mode 100644
index 00000000..5139a2db
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/type_alias.html
@@ -0,0 +1 @@
+{% extends "_base/type_alias.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/type_alias.html.jinja b/src/mkdocstrings_handlers/python/templates/material/type_alias.html.jinja
new file mode 100644
index 00000000..5139a2db
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/type_alias.html.jinja
@@ -0,0 +1 @@
+{% extends "_base/type_alias.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/type_parameters.html b/src/mkdocstrings_handlers/python/templates/material/type_parameters.html
new file mode 100644
index 00000000..c39ca528
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/type_parameters.html
@@ -0,0 +1 @@
+{% extends "_base/type_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/type_parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/material/type_parameters.html.jinja
new file mode 100644
index 00000000..c39ca528
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/material/type_parameters.html.jinja
@@ -0,0 +1 @@
+{% extends "_base/type_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/class.html
similarity index 100%
rename from src/mkdocstrings_handlers/python/templates/material/_base/class.html
rename to src/mkdocstrings_handlers/python/templates/readthedocs/_base/class.html
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/class.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/class.html.jinja
new file mode 100644
index 00000000..64b41ea6
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/class.html.jinja
@@ -0,0 +1,251 @@
+{#- Template for Python classes.
+
+This template renders a Python class.
+
+Context:
+ class (griffe.Class): The class to render.
+ root (bool): Whether this is the root object, injected with `:::` in a Markdown page.
+ heading_level (int): The HTML heading level to use.
+ config (dict): The configuration options.
+-#}
+
+{% 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 %}
+
+ {% if root %}
+ {% set show_full_path = config.show_root_full_path %}
+ {% set root_members = True %}
+ {% elif root_members %}
+ {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %}
+ {% set root_members = False %}
+ {% else %}
+ {% set show_full_path = config.show_object_full_path %}
+ {% endif %}
+
+ {% set class_name = class.path if show_full_path else class.name %}
+
+ {% if not root or config.show_root_heading %}
+ {% filter heading(
+ heading_level,
+ role="class",
+ id=html_id,
+ class="doc doc-heading",
+ toc_label=(' '|safe if config.show_symbol_type_toc 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 %}
+ {{ 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) %}
+ {{ class_name }}{% include "signature.html.jinja" with context %}
+ {% endfilter %}
+ {% endwith %}
+ {% else %}
+ {{ class_name }}
+ {% endif %}
+ {% endblock heading %}
+
+ {% block labels scoped %}
+ {#- Labels block.
+
+ This block renders the labels for the class.
+ -#}
+ {% with labels = class.labels %}
+ {% include "labels.html.jinja" with context %}
+ {% endwith %}
+ {% endblock labels %}
+
+ {% endfilter %}
+
+ {% block signature scoped %}
+ {#- Signature block.
+
+ This block renders the signature for the class.
+ -#}
+ {% 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 %}
+ {% endwith %}
+ {% endif %}
+ {% endif %}
+ {% endblock signature %}
+
+ {% else %}
+ {% if config.show_root_toc_entry %}
+ {% filter heading(heading_level,
+ role="class",
+ id=html_id,
+ toc_label=(' '|safe if config.show_symbol_type_toc else '') + class.name,
+ hidden=True,
+ ) %}
+ {% endfilter %}
+ {% endif %}
+ {% set heading_level = heading_level - 1 %}
+ {% endif %}
+
+
+ {% 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.html.jinja" with context %}{% if not loop.last %}, {% endif %}
+ {% endfor -%}
+
+ {% endif %}
+ {% endblock bases %}
+
+ {% block inheritance_diagram scoped %}
+ {#- Inheritance diagram block.
+
+ This block renders the inheritance diagram for the class,
+ using Mermaid syntax and a bit of JavaScript to make the nodes clickable,
+ linking to the corresponding class documentation.
+ -#}
+ {% if config.show_inheritance_diagram and class.bases %}
+ {% macro edges(class) %}
+ {% for base in class.resolved_bases %}
+ {{ base.path }} --> {{ class.path }}
+ {{ edges(base) }}
+ {% endfor %}
+ {% endmacro %}
+
+
+ flowchart {{ config.inheritance_diagram_direction }}
+ {{ class.path }}[{{ class.name }}]
+ {% for base in class.mro() %}
+ {{ base.path }}[{{ base.name }}]
+ {% endfor %}
+
+ {{ edges(class) | safe }}
+
+ click {{ class.path }} href "" "{{ class.path }}"
+ {% for base in class.mro() %}
+ click {{ base.path }} href "" "{{ base.path }}"
+ {% endfor %}
+
+
+ {% endif %}
+ {% endblock inheritance_diagram %}
+
+ {% block docstring scoped %}
+ {#- Docstring block.
+
+ This block renders the docstring for the class.
+ -#}
+ {% with docstring_sections = class.docstring.parsed %}
+ {% include "docstring.html.jinja" with context %}
+ {% endwith %}
+ {% if config.merge_init_into_class %}
+ {% if "__init__" in class.all_members and class.all_members["__init__"].has_docstring %}
+ {% with function = class.all_members["__init__"] %}
+ {% with obj = function, docstring_sections = function.docstring.parsed %}
+ {% include "docstring.html.jinja" with context %}
+ {% endwith %}
+ {% endwith %}
+ {% endif %}
+ {% endif %}
+ {% endblock docstring %}
+
+ {% block summary scoped %}
+ {#- Summary block.
+
+ This block renders auto-summaries for classes, methods, and attributes.
+ -#}
+ {% include "summary.html.jinja" 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__"] %}
+
+ Source code in
+ {%- if init.relative_filepath.is_absolute() -%}
+ {{ init.relative_package_filepath }}
+ {%- else -%}
+ {{ init.relative_filepath }}
+ {%- endif -%}
+
+ {{ init.source|highlight(language="python", linestart=init.lineno or 0, linenums=True) }}
+
+ {% endwith %}
+ {% endif %}
+ {% elif class.source %}
+
+ Source code in
+ {%- if class.relative_filepath.is_absolute() -%}
+ {{ class.relative_package_filepath }}
+ {%- else -%}
+ {{ class.relative_filepath }}
+ {%- endif -%}
+
+ {{ class.source|highlight(language="python", linestart=class.lineno or 0, linenums=True) }}
+
+ {% endif %}
+ {% endif %}
+ {% endblock source %}
+
+ {% block children scoped %}
+ {#- Children block.
+
+ This block renders the children (members) of the class.
+ -#}
+ {% set root = False %}
+ {% set heading_level = heading_level + 1 %}
+ {% include "children.html.jinja" with context %}
+ {% endblock children %}
+ {% endblock contents %}
+
+
+ {% endwith %}
+
+
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
deleted file mode 100644
index cd4b05be..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 8df20e1c..a3817449 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
@@ -4,18 +4,18 @@ This template renders a list of documented attributes in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -33,12 +33,12 @@ Context:
{{ attribute.name }}
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
- ({% include "expression"|get_template with context %})
+ ({% include "expression.html.jinja" with context %})
{% endwith %}
{% endif %}
–
- {{ attribute.description|convert_markdown(heading_level, html_id) }}
+ {{ attribute.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
deleted file mode 100644
index eae60aa7..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 4b416b65..f7af2121 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
@@ -4,18 +4,18 @@ This template renders a list of documented other parameters in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,13 +32,13 @@ Context:
-
{{ parameter.name }}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
- ({% include "expression"|get_template with context %})
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ ({% include "expression.html.jinja" with context %})
{% endwith %}
{% endif %}
–
- {{ parameter.description|convert_markdown(heading_level, html_id) }}
+ {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
deleted file mode 100644
index f5745464..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 10bbd7ba..95c480fa 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
@@ -4,18 +4,18 @@ This template renders a list of documented parameters in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,18 +32,18 @@ Context:
-
{{ parameter.name }}
{% if parameter.annotation %}
- {% with expression = parameter.annotation %}
- ({% include "expression"|get_template with context %}
+ {% with expression = parameter.annotation, backlink_type = "used-by" %}
+ ({% include "expression.html.jinja" with context %}
{%- if parameter.default %}, {{ lang.t("default:") }}
- {% with expression = parameter.default %}
- {% include "expression"|get_template with context %}
+ {% with expression = parameter.default, backlink_type = "used-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %})
{% endwith %}
{% endif %}
–
- {{ parameter.description|convert_markdown(heading_level, html_id) }}
+ {{ parameter.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
deleted file mode 100644
index 361b9732..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 f350bc97..71beb34c 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
@@ -4,18 +4,18 @@ This template renders a list of documented exceptions in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -31,13 +31,13 @@ Context:
{% for raises in section.value %}
-
{% if raises.annotation %}
- {% with expression = raises.annotation %}
-
{% include "expression"|get_template with context %}
+ {% with expression = raises.annotation, backlink_type = "raised-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
–
- {{ raises.description|convert_markdown(heading_level, html_id) }}
+ {{ raises.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
deleted file mode 100644
index e5a115c1..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 804a04a0..8ad9cae3 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
@@ -4,18 +4,18 @@ This template renders a list of documented received values (generators) in the f
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,15 +32,15 @@ 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 %}
- {% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% if receives.name %}){% endif %}
{% endwith %}
{% endif %}
–
- {{ receives.description|convert_markdown(heading_level, html_id) }}
+ {{ receives.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
deleted file mode 100644
index 0e7807ac..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 0074327a..2201f545 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
@@ -4,18 +4,18 @@ This template renders a list of documented returned values in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,15 +32,15 @@ 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 %}
- {% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% if returns.name %}){% endif %}
{% endwith %}
{% endif %}
–
- {{ returns.description|convert_markdown(heading_level, html_id) }}
+ {{ returns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
deleted file mode 100644
index b7b937a9..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 88308b68..97cbc1de 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
@@ -4,18 +4,18 @@ This template renders a list of documented warnings in the format
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -31,13 +31,13 @@ Context:
{% for warns in section.value %}
-
{% if warns.annotation %}
- {% with expression = warns.annotation %}
-
{% include "expression"|get_template with context %}
+ {% with expression = warns.annotation, backlink_type = "emitted-by" %}
+ {% include "expression.html.jinja" with context %}
{% endwith %}
{% endif %}
–
- {{ warns.description|convert_markdown(heading_level, html_id) }}
+ {{ warns.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
deleted file mode 100644
index ecd6f513..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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 bd43955d..8298421f 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
@@ -4,18 +4,18 @@ This template renders a list of documented yielded values (generators) in the fo
specified with the [`docstring_section_style`][] configuration option.
Context:
- section (griffe.docstrings.dataclasses.DocstringSectionAttributes): The section to render.
+ section (griffe.DocstringSectionAttributes): The section to render.
-#}
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{{ log.debug() }}
{% endblock %}
-{% import "language"|get_template as lang with context %}
+{% import "language.html.jinja" as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,15 +32,15 @@ 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 %}
-
{% include "expression"|get_template with context %}
+ {% include "expression.html.jinja" with context %}
{% if yields.name %}){% endif %}
{% endwith %}
{% endif %}
–
- {{ yields.description|convert_markdown(heading_level, html_id) }}
+ {{ yields.description|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
deleted file mode 100644
index c97d0c31..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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..31ecfdd6 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,17 @@
{% block logs scoped %}
{#- Logging block.
-
+
This block can be used to log debug messages, deprecation messages, warnings, etc.
-#}
{% endblock logs %}
-{% set lang_pth = "languages/" ~ locale | get_template %}
+{% set lang_pth = "languages/" ~ locale ~ ".html.jinja" %}
{% 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 %}
+ {% import "languages/en.html.jinja" 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 %}
+ {% import "languages/en.html.jinja" 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
deleted file mode 100644
index eab87415..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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
deleted file mode 100644
index 14319499..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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
deleted file mode 100644
index 0b281195..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% 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.",
- 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/material/class.html b/src/mkdocstrings_handlers/python/templates/readthedocs/class.html
similarity index 100%
rename from src/mkdocstrings_handlers/python/templates/material/class.html
rename to src/mkdocstrings_handlers/python/templates/readthedocs/class.html
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/class.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/class.html.jinja
new file mode 100644
index 00000000..5e7329df
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/class.html.jinja
@@ -0,0 +1 @@
+{% extends "_base/class.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
deleted file mode 100644
index 4ac364b0..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 7c50379b..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 70c557fb..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index f8c3cf03..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 004ff00e..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 979ce9ef..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index bb06cc85..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 717ef5d4..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index b905cff4..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/language.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 931967c1..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index 17070edf..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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
deleted file mode 100644
index e4ea3116..00000000
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html
+++ /dev/null
@@ -1 +0,0 @@
-{% 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/headings/heading=,separate_signature=False.html b/tests/snapshots/headings/heading=,separate_signature=False.html
new file mode 100644
index 00000000..2be154b9
--- /dev/null
+++ b/tests/snapshots/headings/heading=,separate_signature=False.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+ headings_package
+
+
+
+
+
+
+
diff --git a/tests/snapshots/headings/heading=,separate_signature=True.html b/tests/snapshots/headings/heading=,separate_signature=True.html
new file mode 100644
index 00000000..c73f0184
--- /dev/null
+++ b/tests/snapshots/headings/heading=,separate_signature=True.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+ headings_package
+
+
+
+
+
+
+
diff --git a/tests/snapshots/headings/heading=Some heading,separate_signature=False.html b/tests/snapshots/headings/heading=Some heading,separate_signature=False.html
new file mode 100644
index 00000000..b000bf14
--- /dev/null
+++ b/tests/snapshots/headings/heading=Some heading,separate_signature=False.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Some heading
+
+
+
+
+
+
diff --git a/tests/snapshots/headings/heading=Some heading,separate_signature=True.html b/tests/snapshots/headings/heading=Some heading,separate_signature=True.html
new file mode 100644
index 00000000..852b7487
--- /dev/null
+++ b/tests/snapshots/headings/heading=Some heading,separate_signature=True.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Some heading
+
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=('module_attribute',).html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=('module_attribute',).html
new file mode 100644
index 00000000..271501b7
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=('module_attribute',).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/members/filters=('!module_attribute',),inherited_members=('method1',),members=().html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=().html
new file mode 100644
index 00000000..52ada349
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=().html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=False.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=False.html
new file mode 100644
index 00000000..e96d72c3
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=False.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=None.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=None.html
new file mode 100644
index 00000000..dce4e148
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=None.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/members/filters=('!module_attribute',),inherited_members=('method1',),members=True.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=True.html
new file mode 100644
index 00000000..6d460dd2
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=('method1',),members=True.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/members/filters=('!module_attribute',),inherited_members=(),members=('module_attribute',).html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=('module_attribute',).html
new file mode 100644
index 00000000..93503606
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=('module_attribute',).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/members/filters=('!module_attribute',),inherited_members=(),members=().html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=().html
new file mode 100644
index 00000000..fb55bdd1
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=False.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=False.html
new file mode 100644
index 00000000..3ae3af4d
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=None.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=None.html
new file mode 100644
index 00000000..793f43a4
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=None.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/members/filters=('!module_attribute',),inherited_members=(),members=True.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=True.html
new file mode 100644
index 00000000..07120341
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=(),members=True.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/members/filters=('!module_attribute',),inherited_members=False,members=('module_attribute',).html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=('module_attribute',).html
new file mode 100644
index 00000000..c27a4c82
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=('module_attribute',).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/members/filters=('!module_attribute',),inherited_members=False,members=().html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=().html
new file mode 100644
index 00000000..ec61d8e3
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=False.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=False.html
new file mode 100644
index 00000000..53b5e455
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=None.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=None.html
new file mode 100644
index 00000000..5a87832a
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=None.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/members/filters=('!module_attribute',),inherited_members=False,members=True.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=True.html
new file mode 100644
index 00000000..40ebfa36
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=False,members=True.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/members/filters=('!module_attribute',),inherited_members=True,members=('module_attribute',).html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=('module_attribute',).html
new file mode 100644
index 00000000..9aa9c3c1
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=('module_attribute',).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/members/filters=('!module_attribute',),inherited_members=True,members=().html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=().html
new file mode 100644
index 00000000..06640b9d
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=False.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=False.html
new file mode 100644
index 00000000..1f45fb80
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=None.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=None.html
new file mode 100644
index 00000000..cb43eee6
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=None.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/members/filters=('!module_attribute',),inherited_members=True,members=True.html b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=True.html
new file mode 100644
index 00000000..8357168e
--- /dev/null
+++ b/tests/snapshots/members/filters=('!module_attribute',),inherited_members=True,members=True.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/members/filters=('module_attribute',),inherited_members=('method1',),members=('module_attribute',).html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=('module_attribute',).html
new file mode 100644
index 00000000..e908da32
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=('module_attribute',).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/members/filters=('module_attribute',),inherited_members=('method1',),members=().html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=().html
new file mode 100644
index 00000000..d1e4f8bd
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=().html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=False.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=False.html
new file mode 100644
index 00000000..5fbd6650
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=False.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=None.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=None.html
new file mode 100644
index 00000000..d543f794
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=None.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/members/filters=('module_attribute',),inherited_members=('method1',),members=True.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=True.html
new file mode 100644
index 00000000..795378be
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=('method1',),members=True.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/members/filters=('module_attribute',),inherited_members=(),members=('module_attribute',).html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=('module_attribute',).html
new file mode 100644
index 00000000..79900273
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=('module_attribute',).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/members/filters=('module_attribute',),inherited_members=(),members=().html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=().html
new file mode 100644
index 00000000..a0685468
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=False.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=False.html
new file mode 100644
index 00000000..bed00768
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=None.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=None.html
new file mode 100644
index 00000000..79a5ff40
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=None.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/members/filters=('module_attribute',),inherited_members=(),members=True.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=True.html
new file mode 100644
index 00000000..a7eb7dce
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=(),members=True.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/members/filters=('module_attribute',),inherited_members=False,members=('module_attribute',).html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=('module_attribute',).html
new file mode 100644
index 00000000..8fd78409
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=('module_attribute',).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/members/filters=('module_attribute',),inherited_members=False,members=().html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=().html
new file mode 100644
index 00000000..23e66fd7
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=False.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=False.html
new file mode 100644
index 00000000..27fcc6c1
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=None.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=None.html
new file mode 100644
index 00000000..1a8842f9
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=None.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/members/filters=('module_attribute',),inherited_members=False,members=True.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=True.html
new file mode 100644
index 00000000..e196b599
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=False,members=True.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/members/filters=('module_attribute',),inherited_members=True,members=('module_attribute',).html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=('module_attribute',).html
new file mode 100644
index 00000000..eb755e52
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=('module_attribute',).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/members/filters=('module_attribute',),inherited_members=True,members=().html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=().html
new file mode 100644
index 00000000..f827f125
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=False.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=False.html
new file mode 100644
index 00000000..48c42b3d
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=None.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=None.html
new file mode 100644
index 00000000..eddcbb25
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=None.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/members/filters=('module_attribute',),inherited_members=True,members=True.html b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=True.html
new file mode 100644
index 00000000..26cb9e39
--- /dev/null
+++ b/tests/snapshots/members/filters=('module_attribute',),inherited_members=True,members=True.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/members/filters=(),inherited_members=('method1',),members=('module_attribute',).html b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=('module_attribute',).html
new file mode 100644
index 00000000..a6ee2831
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=('module_attribute',).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/members/filters=(),inherited_members=('method1',),members=().html b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=().html
new file mode 100644
index 00000000..3b41766d
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=('method1',),members=False.html b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=False.html
new file mode 100644
index 00000000..3933bd9d
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=('method1',),members=None.html b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=None.html
new file mode 100644
index 00000000..d9ae307d
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=None.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/members/filters=(),inherited_members=('method1',),members=True.html b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=True.html
new file mode 100644
index 00000000..a52964c3
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=('method1',),members=True.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/members/filters=(),inherited_members=(),members=('module_attribute',).html b/tests/snapshots/members/filters=(),inherited_members=(),members=('module_attribute',).html
new file mode 100644
index 00000000..1232ad5e
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=(),members=('module_attribute',).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/members/filters=(),inherited_members=(),members=().html b/tests/snapshots/members/filters=(),inherited_members=(),members=().html
new file mode 100644
index 00000000..46cd4aee
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=(),members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=(),members=False.html b/tests/snapshots/members/filters=(),inherited_members=(),members=False.html
new file mode 100644
index 00000000..b6a621d2
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=(),members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=(),members=None.html b/tests/snapshots/members/filters=(),inherited_members=(),members=None.html
new file mode 100644
index 00000000..9058ed13
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=(),members=None.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/members/filters=(),inherited_members=(),members=True.html b/tests/snapshots/members/filters=(),inherited_members=(),members=True.html
new file mode 100644
index 00000000..ccfa8d64
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=(),members=True.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/members/filters=(),inherited_members=False,members=('module_attribute',).html b/tests/snapshots/members/filters=(),inherited_members=False,members=('module_attribute',).html
new file mode 100644
index 00000000..f2597daf
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=False,members=('module_attribute',).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/members/filters=(),inherited_members=False,members=().html b/tests/snapshots/members/filters=(),inherited_members=False,members=().html
new file mode 100644
index 00000000..ff8087d4
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=False,members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=False,members=False.html b/tests/snapshots/members/filters=(),inherited_members=False,members=False.html
new file mode 100644
index 00000000..eb15c707
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=False,members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=False,members=None.html b/tests/snapshots/members/filters=(),inherited_members=False,members=None.html
new file mode 100644
index 00000000..7c90168c
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=False,members=None.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/members/filters=(),inherited_members=False,members=True.html b/tests/snapshots/members/filters=(),inherited_members=False,members=True.html
new file mode 100644
index 00000000..d6c51063
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=False,members=True.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/members/filters=(),inherited_members=True,members=('module_attribute',).html b/tests/snapshots/members/filters=(),inherited_members=True,members=('module_attribute',).html
new file mode 100644
index 00000000..0ee900fb
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=True,members=('module_attribute',).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/members/filters=(),inherited_members=True,members=().html b/tests/snapshots/members/filters=(),inherited_members=True,members=().html
new file mode 100644
index 00000000..26f0f5ef
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=True,members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=True,members=False.html b/tests/snapshots/members/filters=(),inherited_members=True,members=False.html
new file mode 100644
index 00000000..bbd48b9e
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=True,members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=(),inherited_members=True,members=None.html b/tests/snapshots/members/filters=(),inherited_members=True,members=None.html
new file mode 100644
index 00000000..b2490df7
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=True,members=None.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/members/filters=(),inherited_members=True,members=True.html b/tests/snapshots/members/filters=(),inherited_members=True,members=True.html
new file mode 100644
index 00000000..7c65c72b
--- /dev/null
+++ b/tests/snapshots/members/filters=(),inherited_members=True,members=True.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/members/filters=None,inherited_members=('method1',),members=('module_attribute',).html b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=('module_attribute',).html
new file mode 100644
index 00000000..8501bce2
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=('module_attribute',).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/members/filters=None,inherited_members=('method1',),members=().html b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=().html
new file mode 100644
index 00000000..7d734fba
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=('method1',),members=False.html b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=False.html
new file mode 100644
index 00000000..8c035cc8
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=('method1',),members=None.html b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=None.html
new file mode 100644
index 00000000..ddce47f6
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=None.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/members/filters=None,inherited_members=('method1',),members=True.html b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=True.html
new file mode 100644
index 00000000..fa970eca
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=('method1',),members=True.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/members/filters=None,inherited_members=(),members=('module_attribute',).html b/tests/snapshots/members/filters=None,inherited_members=(),members=('module_attribute',).html
new file mode 100644
index 00000000..b194ddc9
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=(),members=('module_attribute',).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/members/filters=None,inherited_members=(),members=().html b/tests/snapshots/members/filters=None,inherited_members=(),members=().html
new file mode 100644
index 00000000..4be85a18
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=(),members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=(),members=False.html b/tests/snapshots/members/filters=None,inherited_members=(),members=False.html
new file mode 100644
index 00000000..2bfbdbf4
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=(),members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=(),members=None.html b/tests/snapshots/members/filters=None,inherited_members=(),members=None.html
new file mode 100644
index 00000000..91614cf0
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=(),members=None.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/members/filters=None,inherited_members=(),members=True.html b/tests/snapshots/members/filters=None,inherited_members=(),members=True.html
new file mode 100644
index 00000000..2d79edd5
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=(),members=True.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/members/filters=None,inherited_members=False,members=('module_attribute',).html b/tests/snapshots/members/filters=None,inherited_members=False,members=('module_attribute',).html
new file mode 100644
index 00000000..96cff9d7
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=False,members=('module_attribute',).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/members/filters=None,inherited_members=False,members=().html b/tests/snapshots/members/filters=None,inherited_members=False,members=().html
new file mode 100644
index 00000000..0ed1d57b
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=False,members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=False,members=False.html b/tests/snapshots/members/filters=None,inherited_members=False,members=False.html
new file mode 100644
index 00000000..ce4ee8a7
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=False,members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=False,members=None.html b/tests/snapshots/members/filters=None,inherited_members=False,members=None.html
new file mode 100644
index 00000000..332a5c53
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=False,members=None.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/members/filters=None,inherited_members=False,members=True.html b/tests/snapshots/members/filters=None,inherited_members=False,members=True.html
new file mode 100644
index 00000000..cce2be49
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=False,members=True.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/members/filters=None,inherited_members=True,members=('module_attribute',).html b/tests/snapshots/members/filters=None,inherited_members=True,members=('module_attribute',).html
new file mode 100644
index 00000000..aa4ebf15
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=True,members=('module_attribute',).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/members/filters=None,inherited_members=True,members=().html b/tests/snapshots/members/filters=None,inherited_members=True,members=().html
new file mode 100644
index 00000000..898bab70
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=True,members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=True,members=False.html b/tests/snapshots/members/filters=None,inherited_members=True,members=False.html
new file mode 100644
index 00000000..8b4491f3
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=True,members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=None,inherited_members=True,members=None.html b/tests/snapshots/members/filters=None,inherited_members=True,members=None.html
new file mode 100644
index 00000000..68c7d720
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=True,members=None.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/members/filters=None,inherited_members=True,members=True.html b/tests/snapshots/members/filters=None,inherited_members=True,members=True.html
new file mode 100644
index 00000000..e9f375b2
--- /dev/null
+++ b/tests/snapshots/members/filters=None,inherited_members=True,members=True.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/members/filters=public,inherited_members=('method1',),members=('module_attribute',).html b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=('module_attribute',).html
new file mode 100644
index 00000000..befa0078
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=('module_attribute',).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/members/filters=public,inherited_members=('method1',),members=().html b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=().html
new file mode 100644
index 00000000..f7385cf9
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=().html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=('method1',),members=False.html b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=False.html
new file mode 100644
index 00000000..e649c2e7
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=False.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=('method1',),members=None.html b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=None.html
new file mode 100644
index 00000000..5ca6f9fe
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=None.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/members/filters=public,inherited_members=('method1',),members=True.html b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=True.html
new file mode 100644
index 00000000..a191cb33
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=('method1',),members=True.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/members/filters=public,inherited_members=(),members=('module_attribute',).html b/tests/snapshots/members/filters=public,inherited_members=(),members=('module_attribute',).html
new file mode 100644
index 00000000..c8211de8
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=(),members=('module_attribute',).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/members/filters=public,inherited_members=(),members=().html b/tests/snapshots/members/filters=public,inherited_members=(),members=().html
new file mode 100644
index 00000000..ac0222f5
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=(),members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=(),members=False.html b/tests/snapshots/members/filters=public,inherited_members=(),members=False.html
new file mode 100644
index 00000000..6f76b142
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=(),members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=(),members=None.html b/tests/snapshots/members/filters=public,inherited_members=(),members=None.html
new file mode 100644
index 00000000..5540be65
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=(),members=None.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/members/filters=public,inherited_members=(),members=True.html b/tests/snapshots/members/filters=public,inherited_members=(),members=True.html
new file mode 100644
index 00000000..7d596388
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=(),members=True.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/members/filters=public,inherited_members=False,members=('module_attribute',).html b/tests/snapshots/members/filters=public,inherited_members=False,members=('module_attribute',).html
new file mode 100644
index 00000000..e40923d9
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=False,members=('module_attribute',).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/members/filters=public,inherited_members=False,members=().html b/tests/snapshots/members/filters=public,inherited_members=False,members=().html
new file mode 100644
index 00000000..e8d65a7e
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=False,members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=False,members=False.html b/tests/snapshots/members/filters=public,inherited_members=False,members=False.html
new file mode 100644
index 00000000..12da79f0
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=False,members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=False,members=None.html b/tests/snapshots/members/filters=public,inherited_members=False,members=None.html
new file mode 100644
index 00000000..39cf1b20
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=False,members=None.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/members/filters=public,inherited_members=False,members=True.html b/tests/snapshots/members/filters=public,inherited_members=False,members=True.html
new file mode 100644
index 00000000..1973e99b
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=False,members=True.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/members/filters=public,inherited_members=True,members=('module_attribute',).html b/tests/snapshots/members/filters=public,inherited_members=True,members=('module_attribute',).html
new file mode 100644
index 00000000..7b0e60a5
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=True,members=('module_attribute',).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/members/filters=public,inherited_members=True,members=().html b/tests/snapshots/members/filters=public,inherited_members=True,members=().html
new file mode 100644
index 00000000..e8f0258e
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=True,members=().html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=True,members=False.html b/tests/snapshots/members/filters=public,inherited_members=True,members=False.html
new file mode 100644
index 00000000..85cb268c
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=True,members=False.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ members_package
+
+
+
+
+ Docstring for the package.
+
+
+
+
+
diff --git a/tests/snapshots/members/filters=public,inherited_members=True,members=None.html b/tests/snapshots/members/filters=public,inherited_members=True,members=None.html
new file mode 100644
index 00000000..40c14a7b
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=True,members=None.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/members/filters=public,inherited_members=True,members=True.html b/tests/snapshots/members/filters=public,inherited_members=True,members=True.html
new file mode 100644
index 00000000..13b2239c
--- /dev/null
+++ b/tests/snapshots/members/filters=public,inherited_members=True,members=True.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/overloads/overloads_only=False,separate_signature=False,show_overloads=False.html b/tests/snapshots/overloads/overloads_only=False,separate_signature=False,show_overloads=False.html
new file mode 100644
index 00000000..76234631
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=False,separate_signature=False,show_overloads=False.html
@@ -0,0 +1,169 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/overloads/overloads_only=False,separate_signature=False,show_overloads=True.html b/tests/snapshots/overloads/overloads_only=False,separate_signature=False,show_overloads=True.html
new file mode 100644
index 00000000..afa94fae
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=False,separate_signature=False,show_overloads=True.html
@@ -0,0 +1,189 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/overloads/overloads_only=False,separate_signature=True,show_overloads=False.html b/tests/snapshots/overloads/overloads_only=False,separate_signature=True,show_overloads=False.html
new file mode 100644
index 00000000..96629ba3
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=False,separate_signature=True,show_overloads=False.html
@@ -0,0 +1,117 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+ foo(a, b)
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+ foo(a, b)
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/overloads/overloads_only=False,separate_signature=True,show_overloads=True.html b/tests/snapshots/overloads/overloads_only=False,separate_signature=True,show_overloads=True.html
new file mode 100644
index 00000000..3f231581
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=False,separate_signature=True,show_overloads=True.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+ foo(a, b)
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+ foo(a, b)
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/overloads/overloads_only=True,separate_signature=False,show_overloads=False.html b/tests/snapshots/overloads/overloads_only=True,separate_signature=False,show_overloads=False.html
new file mode 100644
index 00000000..23a1a9c5
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=True,separate_signature=False,show_overloads=False.html
@@ -0,0 +1,169 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/overloads/overloads_only=True,separate_signature=False,show_overloads=True.html b/tests/snapshots/overloads/overloads_only=True,separate_signature=False,show_overloads=True.html
new file mode 100644
index 00000000..79b078af
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=True,separate_signature=False,show_overloads=True.html
@@ -0,0 +1,189 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+
+ bar
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+
+ foo
+
+
+ (
+
+
+ a
+
+
+ ,
+
+
+ b
+
+
+ )
+
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/overloads/overloads_only=True,separate_signature=True,show_overloads=False.html b/tests/snapshots/overloads/overloads_only=True,separate_signature=True,show_overloads=False.html
new file mode 100644
index 00000000..1f1c5822
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=True,separate_signature=True,show_overloads=False.html
@@ -0,0 +1,117 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+ foo(a, b)
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+ foo(a, b)
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/overloads/overloads_only=True,separate_signature=True,show_overloads=True.html b/tests/snapshots/overloads/overloads_only=True,separate_signature=True,show_overloads=True.html
new file mode 100644
index 00000000..7d4b3416
--- /dev/null
+++ b/tests/snapshots/overloads/overloads_only=True,separate_signature=True,show_overloads=True.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+ overloads_package
+
+
+
+
+
+
+
+ Class
+
+
+
+
+ Docstring for
+
+ Class
+
+ .
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ Class.bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+
+ Docstring for
+
+ Class.foo
+
+ .
+
+
+
+
+
+
+
+
+
+ bar
+
+
+
+ bar(a, b)
+
+
+
+
+ Docstring for
+
+ bar
+
+ .
+
+
+
+
+
+
+ foo
+
+
+
+
+ foo(a: int, b: str) -> float
+
+
+
+ foo(a: str, b: int) -> None
+
+
+
+
+
+ Docstring for
+
+ foo
+
+ .
+
+
+
+
+
+
diff --git a/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=False,signature_crossrefs=False.html b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=False,signature_crossrefs=False.html
new file mode 100644
index 00000000..599197fe
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=False,signature_crossrefs=False.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/signatures/separate_signature=False,show_signature_annotations=False,signature_crossrefs=True.html b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=False,signature_crossrefs=True.html
new file mode 100644
index 00000000..70567c97
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=False,signature_crossrefs=True.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/signatures/separate_signature=False,show_signature_annotations=True,signature_crossrefs=False.html b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=True,signature_crossrefs=False.html
new file mode 100644
index 00000000..65e87e01
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=True,signature_crossrefs=False.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/signatures/separate_signature=False,show_signature_annotations=True,signature_crossrefs=True.html b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=True,signature_crossrefs=True.html
new file mode 100644
index 00000000..44516fe5
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=False,show_signature_annotations=True,signature_crossrefs=True.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/signatures/separate_signature=True,show_signature_annotations=False,signature_crossrefs=False.html b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=False,signature_crossrefs=False.html
new file mode 100644
index 00000000..03d9e14d
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=False,signature_crossrefs=False.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/signatures/separate_signature=True,show_signature_annotations=False,signature_crossrefs=True.html b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=False,signature_crossrefs=True.html
new file mode 100644
index 00000000..8454da6d
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=False,signature_crossrefs=True.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/signatures/separate_signature=True,show_signature_annotations=True,signature_crossrefs=False.html b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=True,signature_crossrefs=False.html
new file mode 100644
index 00000000..9edcf4c5
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=True,signature_crossrefs=False.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/signatures/separate_signature=True,show_signature_annotations=True,signature_crossrefs=True.html b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=True,signature_crossrefs=True.html
new file mode 100644
index 00000000..e9ac18ce
--- /dev/null
+++ b/tests/snapshots/signatures/separate_signature=True,show_signature_annotations=True,signature_crossrefs=True.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/test_api.py b/tests/test_api.py
new file mode 100644
index 00000000..85432b54
--- /dev/null
+++ b/tests/test_api.py
@@ -0,0 +1,188 @@
+"""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,
+ 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,
+ 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():
+ pytest.skip("The objects inventory is not available.") # ty: ignore[call-non-callable]
+ 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 = [
+ f"{obj.relative_filepath}:{obj.lineno}: {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")
+
+ 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..3363ebd6
--- /dev/null
+++ b/tests/test_end_to_end.py
@@ -0,0 +1,283 @@
+"""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 external_file, register_format_alias
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+
+ from mkdocstrings_handlers.python import PythonHandler
+
+
+register_format_alias(".html", ".txt")
+
+
+def _normalize_html(html: str) -> str:
+ soup = bs4.BeautifulSoup(html, features="html.parser")
+ html = soup.prettify()
+ 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"
+
+
+def _snapshot_file(group: str, options: dict[str, Any]) -> str:
+ return f"snapshots/{group}/" + ",".join(f"{k}={v}" for k, v in sorted(options.items())) + ".html"
+
+
+# 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).
+ """
+ options = {
+ "show_signature_annotations": show_signature_annotations,
+ "signature_crossrefs": signature_crossrefs,
+ "separate_signature": separate_signature,
+ }
+ html = _render_options(options) + _render(session_handler, signature_package, options)
+ assert html == external_file(_snapshot_file("signatures", options), format=".txt")
+
+
+# Signature overloads tests.
+@pytest.fixture(name="overloads_package", scope="session")
+def _overloads_package() -> Iterator[TmpPackage]:
+ code = """
+ from typing_extensions import overload
+
+ @overload
+ def foo(a: int, b: str) -> float: ...
+
+ @overload
+ def foo(a: str, b: int) -> None: ...
+
+ def foo(a: str | int, b: int | str) -> float | None:
+ '''Docstring for `foo`.'''
+
+ def bar(a: str, b: int | str) -> float | None:
+ '''Docstring for `bar`.'''
+
+ class Class:
+ '''Docstring for `Class`.'''
+
+ @overload
+ def foo(self, a: int, b: str) -> float: ...
+
+ @overload
+ def foo(self, a: str, b: int) -> None: ...
+
+ def foo(self, a: str | int, b: int | str) -> float | None:
+ '''Docstring for `Class.foo`.'''
+
+ def bar(self, a: str, b: int | str) -> float | None:
+ '''Docstring for `Class.bar`.'''
+ """
+ with temporary_pypackage("overloads_package", {"__init__.py": code}) as tmppkg:
+ yield tmppkg
+
+
+@pytest.mark.parametrize("separate_signature", [True, False])
+@pytest.mark.parametrize("show_overloads", [True, False])
+@pytest.mark.parametrize("overloads_only", [True, False])
+def test_end_to_end_for_overloads(
+ session_handler: PythonHandler,
+ overloads_package: TmpPackage,
+ separate_signature: bool,
+ show_overloads: bool,
+ overloads_only: bool,
+) -> None:
+ """Test rendering of a given theme's templates.
+
+ Parameters:
+ identifier: Parametrized identifier.
+ session_handler: Python handler (fixture).
+ """
+ options = {
+ "separate_signature": separate_signature,
+ "show_overloads": show_overloads,
+ "overloads_only": overloads_only,
+ }
+ html = _render_options(options) + _render(session_handler, overloads_package, options)
+ assert html == external_file(_snapshot_file("overloads", options), format=".txt")
+
+
+# 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).
+ """
+ options = {
+ "inherited_members": inherited_members,
+ "members": members,
+ "filters": filters,
+ }
+ html = _render_options(options) + _render(session_handler, members_package, options)
+ assert html == external_file(_snapshot_file("members", options), format=".txt")
+
+
+# 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).
+ """
+ options = {
+ "separate_signature": separate_signature,
+ "heading": heading,
+ }
+ extra = {"show_if_no_docstring": True, "members": False}
+ html = _render_options(options) + _render(session_handler, headings_package, {**options, **extra})
+ assert html == external_file(_snapshot_file("headings", options), format=".txt")
diff --git a/tests/test_handler.py b/tests/test_handler.py
index 4ec7ee28..1cccd6c6 100644
--- a/tests/test_handler.py
+++ b/tests/test_handler.py
@@ -3,44 +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.docstrings.dataclasses import DocstringSectionExamples, DocstringSectionKind
-from griffe.tests import 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(
@@ -72,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:
@@ -87,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
@@ -120,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):
@@ -166,10 +170,166 @@ 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(
+ theme="material",
+ custom_templates=None,
+ 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 38d81dbb..91f945a8 100644
--- a/tests/test_rendering.py
+++ b/tests/test_rendering.py
@@ -4,13 +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.collections import ModulesCollection
-from griffe.tests import temporary_visited_module
+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
@@ -23,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(
@@ -38,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.
@@ -51,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(
@@ -69,7 +78,7 @@ def test_filter_objects(names: list[str], filter_params: dict[str, Any], expecte
expected_names: Names expected to be kept.
"""
objects = {name: _FakeObject(name) for name in names}
- filtered = rendering.do_filter_objects(objects, **filter_params) # type: ignore[arg-type]
+ filtered = rendering.do_filter_objects(objects, **filter_params)
filtered_names = {obj.name for obj in filtered}
assert set(filtered_names) == set(expected_names)
@@ -136,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..5a7e9038 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(
@@ -23,24 +22,18 @@
@pytest.mark.parametrize(
"identifier",
[
- "mkdocstrings.extension",
- "mkdocstrings.inventory",
- "mkdocstrings.loggers",
- "mkdocstrings.plugin",
- "mkdocstrings.handlers.base",
- "mkdocstrings.handlers.rendering",
- "mkdocstrings_handlers.python",
+ "mkdocstrings_handlers.python._internal.config",
+ "mkdocstrings_handlers.python._internal.handler",
+ "mkdocstrings_handlers.python._internal.rendering",
],
)
-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)