'
-
-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
index f4a30a8c..6734e5b6 100644
--- a/scripts/get_version.py
+++ b/scripts/get_version.py
@@ -1,4 +1,4 @@
-"""Get current project version from Git tags or changelog."""
+# Get current project version from Git tags or changelog.
import re
from contextlib import suppress
@@ -13,7 +13,6 @@
def get_version() -> str:
- """Get current project version from Git tags or changelog."""
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
diff --git a/scripts/griffe_extensions.py b/scripts/griffe_extensions.py
index 7d283054..eb50f5f2 100644
--- a/scripts/griffe_extensions.py
+++ b/scripts/griffe_extensions.py
@@ -1,4 +1,4 @@
-"""Custom extensions for Griffe."""
+# Custom extensions for Griffe.
from __future__ import annotations
@@ -7,7 +7,7 @@
import griffe
-logger = griffe.get_logger("griffe_extensions")
+_logger = griffe.get_logger("griffe_extensions")
class CustomFields(griffe.Extension):
@@ -28,14 +28,14 @@ def on_attribute_instance(
except AttributeError:
return
- if field.canonical_path == "mkdocstrings_handlers.python.config.Field":
+ 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")
+ _logger.warning(f"Field description of {attr.path} is not a static string")
description = str(description)
attr.docstring = griffe.Docstring(
diff --git a/scripts/insiders.py b/scripts/insiders.py
index a7da99bc..4cd438d4 100644
--- a/scripts/insiders.py
+++ b/scripts/insiders.py
@@ -1,4 +1,4 @@
-"""Functions related to Insiders funding goals."""
+# Functions related to Insiders funding goals.
from __future__ import annotations
@@ -23,7 +23,7 @@
logger = logging.getLogger(f"mkdocs.logs.{__name__}")
-def human_readable_amount(amount: int) -> str: # noqa: D103
+def human_readable_amount(amount: int) -> str:
str_amount = str(amount)
if len(str_amount) >= 4: # noqa: PLR2004
return f"{str_amount[: len(str_amount) - 3]},{str_amount[-3:]}"
@@ -32,16 +32,12 @@ def human_readable_amount(amount: int) -> str: # noqa: D103
@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
@@ -68,8 +64,6 @@ def render(self, rel_base: str = "..", *, badge: bool = False) -> None: # noqa:
@dataclass
class Goal:
- """Class representing an Insiders goal."""
-
name: str
amount: int
features: list[Feature]
@@ -94,16 +88,6 @@ def render(self, rel_base: str = "..") -> None: # noqa: D102
def load_goals(data: str, funding: int = 0, project: Project | None = None) -> dict[int, Goal]:
- """Load goals from JSON data.
-
- Parameters:
- data: The JSON data.
- funding: The current total funding, per month.
- origin: The origin of the data (URL).
-
- Returns:
- A dictionaries of goals, keys being their target monthly amount.
- """
goals_data = yaml.safe_load(data)["goals"]
return {
amount: Goal(
@@ -151,15 +135,6 @@ def _load_goals(source: str | tuple[str, str, str], funding: int = 0) -> dict[in
def funding_goals(source: str | list[str | tuple[str, str, str]], funding: int = 0) -> dict[int, Goal]:
- """Load funding goals from a given data source.
-
- Parameters:
- source: The data source (local file path or URL).
- funding: The current total funding, per month.
-
- Returns:
- A dictionaries of goals, keys being their target monthly amount.
- """
if isinstance(source, str):
return _load_goals_from_disk(source, funding)
goals = {}
@@ -174,18 +149,10 @@ def funding_goals(source: str | list[str | tuple[str, str, str]], funding: int =
def feature_list(goals: Iterable[Goal]) -> list[Feature]:
- """Extract feature list from funding goals.
-
- Parameters:
- goals: A list of funding goals.
-
- Returns:
- A list of features.
- """
return list(chain.from_iterable(goal.features for goal in goals))
-def load_json(url: str) -> str | list | dict: # noqa: D103
+def load_json(url: str) -> str | list | dict:
with urlopen(url) as response: # noqa: S310
return json.loads(response.read().decode())
@@ -201,6 +168,6 @@ def load_json(url: str) -> str | list | dict: # noqa: D103
ongoing_goals = [goal for goal in goals.values() if not goal.complete]
unreleased_features = sorted(
(ft for ft in feature_list(ongoing_goals) if ft.since),
- key=lambda ft: cast(date, ft.since),
+ key=lambda ft: cast("date", ft.since),
reverse=True,
)
diff --git a/scripts/make.py b/scripts/make.py
index a3b9e751..5a7fb4c2 100755
--- a/scripts/make.py
+++ b/scripts/make.py
@@ -1,6 +1,4 @@
#!/usr/bin/env python3
-"""Management commands."""
-
from __future__ import annotations
import os
diff --git a/scripts/mkdocs_hooks.py b/scripts/mkdocs_hooks.py
index 805055e0..739f93b3 100644
--- a/scripts/mkdocs_hooks.py
+++ b/scripts/mkdocs_hooks.py
@@ -1,4 +1,4 @@
-"""Generate a JSON schema of the Python handler configuration."""
+# Generate a JSON schema of the Python handler configuration.
import json
from dataclasses import dataclass, fields
@@ -8,7 +8,7 @@
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.plugins import get_plugin_logger
-from mkdocstrings_handlers.python.config import PythonInputConfig, PythonInputOptions
+from mkdocstrings_handlers.python import PythonInputConfig, PythonInputOptions
# TODO: Update when Pydantic supports Python 3.14 (sources and duties as well).
try:
@@ -17,13 +17,13 @@
TypeAdapter = None # type: ignore[assignment,misc]
-logger = get_plugin_logger(__name__)
+_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")
+ _logger.info("Pydantic is not installed, skipping JSON schema generation")
return
@dataclass
@@ -35,12 +35,12 @@ class PythonHandlerSchema:
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")
+ _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")
+ _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")
+ _logger.warning(f"Configuration option `{field.name}` is not documented")
diff --git a/src/mkdocstrings_handlers/python/__init__.py b/src/mkdocstrings_handlers/python/__init__.py
index 0432a90d..faa9b9f4 100644
--- a/src/mkdocstrings_handlers/python/__init__.py
+++ b/src/mkdocstrings_handlers/python/__init__.py
@@ -1,5 +1,70 @@
"""Python handler for mkdocstrings."""
-from mkdocstrings_handlers.python.handler import get_handler
+from mkdocstrings_handlers.python._internal.config import (
+ AutoStyleOptions,
+ GoogleStyleOptions,
+ Inventory,
+ NumpyStyleOptions,
+ PerStyleOptions,
+ PythonConfig,
+ PythonInputConfig,
+ PythonInputOptions,
+ PythonOptions,
+ SphinxStyleOptions,
+ SummaryOption,
+)
+from mkdocstrings_handlers.python._internal.handler import PythonHandler, get_handler
+from mkdocstrings_handlers.python._internal.rendering import (
+ AutorefsHook,
+ Order,
+ Tree,
+ do_as_attributes_section,
+ do_as_classes_section,
+ do_as_functions_section,
+ do_as_modules_section,
+ do_backlink_tree,
+ do_crossref,
+ do_filter_objects,
+ do_format_attribute,
+ do_format_code,
+ do_format_signature,
+ do_get_template,
+ do_multi_crossref,
+ do_order_members,
+ do_split_path,
+ do_stash_crossref,
+)
-__all__ = ["get_handler"]
+__all__ = [
+ "AutoStyleOptions",
+ "AutorefsHook",
+ "GoogleStyleOptions",
+ "Inventory",
+ "NumpyStyleOptions",
+ "Order",
+ "PerStyleOptions",
+ "PythonConfig",
+ "PythonHandler",
+ "PythonInputConfig",
+ "PythonInputOptions",
+ "PythonOptions",
+ "SphinxStyleOptions",
+ "SummaryOption",
+ "Tree",
+ "do_as_attributes_section",
+ "do_as_classes_section",
+ "do_as_functions_section",
+ "do_as_modules_section",
+ "do_backlink_tree",
+ "do_crossref",
+ "do_filter_objects",
+ "do_format_attribute",
+ "do_format_code",
+ "do_format_signature",
+ "do_get_template",
+ "do_multi_crossref",
+ "do_order_members",
+ "do_split_path",
+ "do_stash_crossref",
+ "get_handler",
+]
diff --git a/src/mkdocstrings_handlers/python/_internal/__init__.py b/src/mkdocstrings_handlers/python/_internal/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/mkdocstrings_handlers/python/_internal/config.py b/src/mkdocstrings_handlers/python/_internal/config.py
new file mode 100644
index 00000000..a09f9fbe
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/config.py
@@ -0,0 +1,1036 @@
+# 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
+
+# YORE: EOL 3.10: Replace block with line 2.
+if sys.version_info >= (3, 11):
+ from typing import Self
+else:
+ from typing_extensions import Self
+
+
+_logger = get_logger(__name__)
+
+_DEFAULT_FILTERS = ["!^_[^_]"]
+
+try:
+ # When Pydantic is available, use it to validate options (done automatically).
+ # Users can therefore opt into validation by installing Pydantic in development/CI.
+ # When building the docs to deploy them, Pydantic is not required anymore.
+
+ # When building our own docs, Pydantic is always installed (see `docs` group in `pyproject.toml`)
+ # to allow automatic generation of a JSON Schema. The JSON Schema is then referenced by mkdocstrings,
+ # which is itself referenced by mkdocs-material's schema system. For example in VSCode:
+ #
+ # "yaml.schemas": {
+ # "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml"
+ # }
+ import pydantic
+
+ if getattr(pydantic, "__version__", "1.").startswith("1."):
+ raise ImportError # noqa: TRY301
+
+ # YORE: EOL 3.9: Remove block.
+ if sys.version_info < (3, 10):
+ try:
+ import eval_type_backport # noqa: F401
+ except ImportError:
+ _logger.debug(
+ "Pydantic needs the `eval-type-backport` package to be installed "
+ "for modern type syntax to work on Python 3.9. "
+ "Deactivating Pydantic validation for Python handler options.",
+ )
+ raise
+
+ from inspect import cleandoc
+
+ from pydantic import Field as BaseField
+ from pydantic.dataclasses import dataclass
+
+ _base_url = "https://mkdocstrings.github.io/python/usage"
+
+ def _Field( # noqa: N802
+ *args: Any,
+ description: str,
+ group: Literal["general", "headings", "members", "docstrings", "signatures"] | None = None,
+ parent: str | None = None,
+ **kwargs: Any,
+ ) -> None:
+ def _add_markdown_description(schema: dict[str, Any]) -> None:
+ url = f"{_base_url}/{f'configuration/{group}/' if group else ''}#{parent or schema['title']}"
+ schema["markdownDescription"] = f"[DOCUMENTATION]({url})\n\n{schema['description']}"
+
+ return BaseField(
+ *args,
+ description=cleandoc(description),
+ field_title_generator=lambda name, _: name,
+ json_schema_extra=_add_markdown_description,
+ **kwargs,
+ )
+except ImportError:
+ from dataclasses import dataclass # type: ignore[no-redef]
+
+ def _Field(*args: Any, **kwargs: Any) -> None: # type: ignore[misc] # noqa: N802
+ pass
+
+
+if TYPE_CHECKING:
+ from collections.abc import MutableMapping
+
+
+# YORE: EOL 3.9: Remove block.
+_dataclass_options = {"frozen": True}
+if sys.version_info >= (3, 10):
+ _dataclass_options["kw_only"] = True
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class GoogleStyleOptions:
+ """Google style docstring options."""
+
+ ignore_init_summary: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Whether to ignore the summary in `__init__` methods' docstrings.",
+ ),
+ ] = False
+
+ returns_multiple_items: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="""Whether to parse multiple items in `Yields` and `Returns` sections.
+
+ When true, each item's continuation lines must be indented.
+ When false (single item), no further indentation is required.
+ """,
+ ),
+ ] = True
+
+ returns_named_value: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="""Whether to parse `Yields` and `Returns` section items as name and description, rather than type and description.
+
+ When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`.
+ When false, parentheses are optional but the items cannot be named: `int: Description`.
+ """,
+ ),
+ ] = True
+
+ returns_type_in_property_summary: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Whether to parse the return type of properties at the beginning of their summary: `str: Summary of the property`.",
+ ),
+ ] = False
+
+ receives_multiple_items: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="""Whether to parse multiple items in `Receives` sections.
+
+ When true, each item's continuation lines must be indented.
+ When false (single item), no further indentation is required.
+ """,
+ ),
+ ] = True
+
+ receives_named_value: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="""Whether to parse `Receives` section items as name and description, rather than type and description.
+
+ When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`.
+ When false, parentheses are optional but the items cannot be named: `int: Description`.
+ """,
+ ),
+ ] = True
+
+ trim_doctest_flags: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Whether to remove doctest flags from Python example blocks.",
+ ),
+ ] = True
+
+ warn_unknown_params: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Warn about documented parameters not appearing in the signature.",
+ ),
+ ] = True
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class NumpyStyleOptions:
+ """Numpy style docstring options."""
+
+ ignore_init_summary: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Whether to ignore the summary in `__init__` methods' docstrings.",
+ ),
+ ] = False
+
+ trim_doctest_flags: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Whether to remove doctest flags from Python example blocks.",
+ ),
+ ] = True
+
+ warn_unknown_params: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Warn about documented parameters not appearing in the signature.",
+ ),
+ ] = True
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class SphinxStyleOptions:
+ """Sphinx style docstring options."""
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class PerStyleOptions:
+ """Per style options."""
+
+ google: Annotated[
+ GoogleStyleOptions,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Google-style options.",
+ ),
+ ] = field(default_factory=GoogleStyleOptions)
+
+ numpy: Annotated[
+ NumpyStyleOptions,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Numpydoc-style options.",
+ ),
+ ] = field(default_factory=NumpyStyleOptions)
+
+ sphinx: Annotated[
+ SphinxStyleOptions,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Sphinx-style options.",
+ ),
+ ] = field(default_factory=SphinxStyleOptions)
+
+ @classmethod
+ def from_data(cls, **data: Any) -> Self:
+ """Create an instance from a dictionary."""
+ if "google" in data:
+ data["google"] = GoogleStyleOptions(**data["google"])
+ if "numpy" in data:
+ data["numpy"] = NumpyStyleOptions(**data["numpy"])
+ if "sphinx" in data:
+ data["sphinx"] = SphinxStyleOptions(**data["sphinx"])
+ return cls(**data)
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class AutoStyleOptions:
+ """Auto style docstring options."""
+
+ method: Annotated[
+ Literal["heuristics", "max_sections"],
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="The method to use to determine the docstring style.",
+ ),
+ ] = "heuristics"
+
+ style_order: Annotated[
+ list[str],
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="The order of the docstring styles to try.",
+ ),
+ ] = field(default_factory=lambda: ["sphinx", "google", "numpy"])
+
+ default: Annotated[
+ str | None,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="The default docstring style to use if no other style is detected.",
+ ),
+ ] = None
+
+ per_style_options: Annotated[
+ PerStyleOptions,
+ _Field(
+ group="docstrings",
+ parent="docstring_options",
+ description="Per-style options.",
+ ),
+ ] = field(default_factory=PerStyleOptions)
+
+ @classmethod
+ def from_data(cls, **data: Any) -> Self:
+ """Create an instance from a dictionary."""
+ if "per_style_options" in data:
+ data["per_style_options"] = PerStyleOptions.from_data(**data["per_style_options"])
+ return cls(**data)
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class SummaryOption:
+ """Summary option."""
+
+ attributes: Annotated[
+ bool,
+ _Field(
+ group="members",
+ parent="summary",
+ description="Whether to render summaries of attributes.",
+ ),
+ ] = False
+
+ functions: Annotated[
+ bool,
+ _Field(
+ group="members",
+ parent="summary",
+ description="Whether to render summaries of functions (methods).",
+ ),
+ ] = False
+
+ classes: Annotated[
+ bool,
+ _Field(
+ group="members",
+ parent="summary",
+ description="Whether to render summaries of classes.",
+ ),
+ ] = False
+
+ modules: Annotated[
+ bool,
+ _Field(
+ group="members",
+ parent="summary",
+ description="Whether to render summaries of modules.",
+ ),
+ ] = False
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class PythonInputOptions:
+ """Accepted input options."""
+
+ allow_inspection: Annotated[
+ bool,
+ _Field(
+ group="general",
+ description="Whether to allow inspecting modules when visiting them is not possible.",
+ ),
+ ] = True
+
+ force_inspection: Annotated[
+ bool,
+ _Field(
+ group="general",
+ description="Whether to force using dynamic analysis when loading data.",
+ ),
+ ] = False
+
+ annotations_path: Annotated[
+ Literal["brief", "source", "full"],
+ _Field(
+ group="signatures",
+ description="The verbosity for annotations path: `brief` (recommended), `source` (as written in the source), or `full`.",
+ ),
+ ] = "brief"
+
+ backlinks: Annotated[
+ Literal["flat", "tree", False],
+ _Field(
+ group="general",
+ description="Whether to render backlinks, and how.",
+ ),
+ ] = False
+
+ docstring_options: Annotated[
+ GoogleStyleOptions | NumpyStyleOptions | SphinxStyleOptions | AutoStyleOptions | None,
+ _Field(
+ group="docstrings",
+ description="""The options for the docstring parser.
+
+ See [docstring parsers](https://mkdocstrings.github.io/griffe/reference/docstrings/) and their options in Griffe docs.
+ """,
+ ),
+ ] = None
+
+ docstring_section_style: Annotated[
+ Literal["table", "list", "spacy"],
+ _Field(
+ group="docstrings",
+ description="The style used to render docstring sections.",
+ ),
+ ] = "table"
+
+ docstring_style: Annotated[
+ Literal["auto", "google", "numpy", "sphinx"] | None,
+ _Field(
+ group="docstrings",
+ description="The docstring style to use: `auto`, `google`, `numpy`, `sphinx`, or `None`.",
+ ),
+ ] = "google"
+
+ extensions: Annotated[
+ list[str | dict[str, Any]],
+ _Field(
+ group="general",
+ description="A list of Griffe extensions to load.",
+ ),
+ ] = field(default_factory=list)
+
+ filters: Annotated[
+ list[str],
+ _Field(
+ group="members",
+ description="""A list of filters applied to filter objects based on their name.
+
+ A filter starting with `!` will exclude matching objects instead of including them.
+ The `members` option takes precedence over `filters` (filters will still be applied recursively
+ to lower members in the hierarchy).
+ """,
+ ),
+ ] = field(default_factory=lambda: _DEFAULT_FILTERS.copy())
+
+ find_stubs_package: Annotated[
+ bool,
+ _Field(
+ group="general",
+ description="Whether to load stubs package (package-stubs) when extracting docstrings.",
+ ),
+ ] = False
+
+ group_by_category: Annotated[
+ bool,
+ _Field(
+ group="members",
+ description="Group the object's children by categories: attributes, classes, functions, and modules.",
+ ),
+ ] = True
+
+ heading: Annotated[
+ str,
+ _Field(
+ group="headings",
+ description="A custom string to override the autogenerated heading of the root object.",
+ ),
+ ] = ""
+
+ heading_level: Annotated[
+ int,
+ _Field(
+ group="headings",
+ description="The initial heading level to use.",
+ ),
+ ] = 2
+
+ inherited_members: Annotated[
+ bool | list[str],
+ _Field(
+ group="members",
+ description="""A boolean, or an explicit list of inherited members to render.
+
+ If true, select all inherited members, which can then be filtered with `members`.
+ If false or empty list, do not select any inherited member.
+ """,
+ ),
+ ] = False
+
+ line_length: Annotated[
+ int,
+ _Field(
+ group="signatures",
+ description="Maximum line length when formatting code/signatures.",
+ ),
+ ] = 60
+
+ members: Annotated[
+ list[str] | bool | None,
+ _Field(
+ group="members",
+ description="""A boolean, or an explicit list of members to render.
+
+ If true, select all members without further filtering.
+ If false or empty list, do not render members.
+ If none, select all members and apply further filtering with filters and docstrings.
+ """,
+ ),
+ ] = None
+
+ members_order: Annotated[
+ Literal["alphabetical", "source"],
+ _Field(
+ group="members",
+ description="""The members ordering to use.
+
+ - `alphabetical`: order by the members names,
+ - `source`: order members as they appear in the source file.
+ """,
+ ),
+ ] = "alphabetical"
+
+ merge_init_into_class: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to merge the `__init__` method into the class' signature and docstring.",
+ ),
+ ] = False
+
+ modernize_annotations: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Whether to modernize annotations, for example `Optional[str]` into `str | None`.",
+ ),
+ ] = False
+
+ parameter_headings: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="Whether to render headings for parameters (therefore showing parameters in the ToC).",
+ ),
+ ] = False
+
+ preload_modules: Annotated[
+ list[str],
+ _Field(
+ group="general",
+ description="""Pre-load modules that are not specified directly in autodoc instructions (`::: identifier`).
+
+ It is useful when you want to render documentation for a particular member of an object,
+ and this member is imported from another package than its parent.
+
+ For an imported member to be rendered, you need to add it to the `__all__` attribute
+ of the importing module.
+
+ The modules must be listed as an array of strings.
+ """,
+ ),
+ ] = field(default_factory=list)
+
+ relative_crossrefs: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to enable the relative crossref syntax.",
+ ),
+ ] = False
+
+ scoped_crossrefs: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to enable the scoped crossref ability.",
+ ),
+ ] = False
+
+ show_overloads: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Show the overloads of a function or method.",
+ ),
+ ] = True
+
+ separate_signature: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="""Whether to put the whole signature in a code block below the heading.
+
+ If Black or Ruff are installed, the signature is also formatted using them.
+ """,
+ ),
+ ] = False
+
+ show_bases: Annotated[
+ bool,
+ _Field(
+ group="general",
+ description="Show the base classes of a class.",
+ ),
+ ] = True
+
+ show_category_heading: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="When grouped by categories, show a heading for each category.",
+ ),
+ ] = False
+
+ show_docstring_attributes: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Attributes' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_classes: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Classes' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_description: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the textual block (including admonitions) in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_examples: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Examples' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_functions: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Functions' or 'Methods' sections in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_modules: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Modules' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_other_parameters: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Other Parameters' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_parameters: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Parameters' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_raises: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Raises' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_receives: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Receives' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_returns: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Returns' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_warns: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Warns' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_docstring_yields: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to display the 'Yields' section in the object's docstring.",
+ ),
+ ] = True
+
+ show_if_no_docstring: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Show the object heading even if it has no docstring or children with docstrings.",
+ ),
+ ] = False
+
+ show_inheritance_diagram: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Show the inheritance diagram of a class using Mermaid.",
+ ),
+ ] = False
+
+ show_labels: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Whether to show labels of the members.",
+ ),
+ ] = True
+
+ show_object_full_path: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Show the full Python path of every object.",
+ ),
+ ] = False
+
+ show_root_full_path: Annotated[
+ bool,
+ _Field(
+ group="docstrings",
+ description="Show the full Python path for the root object heading.",
+ ),
+ ] = True
+
+ show_root_heading: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="""Show the heading of the object at the root of the documentation tree.
+
+ The root object is the object referenced by the identifier after `:::`.
+ """,
+ ),
+ ] = False
+
+ show_root_members_full_path: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="Show the full Python path of the root members.",
+ ),
+ ] = False
+
+ show_root_toc_entry: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="If the root heading is not shown, at least add a ToC entry for it.",
+ ),
+ ] = True
+
+ show_signature_annotations: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Show the type annotations in methods and functions signatures.",
+ ),
+ ] = False
+
+ show_signature: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Show methods and functions signatures.",
+ ),
+ ] = True
+
+ show_source: Annotated[
+ bool,
+ _Field(
+ group="general",
+ description="Show the source code of this object.",
+ ),
+ ] = True
+
+ show_submodules: Annotated[
+ bool,
+ _Field(
+ group="members",
+ description="When rendering a module, show its submodules recursively.",
+ ),
+ ] = False
+
+ show_symbol_type_heading: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="Show the symbol type in headings (e.g. mod, class, meth, func and attr).",
+ ),
+ ] = False
+
+ show_symbol_type_toc: Annotated[
+ bool,
+ _Field(
+ group="headings",
+ description="Show the symbol type in the Table of Contents (e.g. mod, class, methd, func and attr).",
+ ),
+ ] = False
+
+ signature_crossrefs: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Whether to render cross-references for type annotations in signatures.",
+ ),
+ ] = False
+
+ summary: Annotated[
+ bool | SummaryOption,
+ _Field(
+ group="members",
+ description="Whether to render summaries of modules, classes, functions (methods) and attributes.",
+ ),
+ ] = field(default_factory=SummaryOption)
+
+ toc_label: Annotated[
+ str,
+ _Field(
+ group="headings",
+ description="A custom string to override the autogenerated toc label of the root object.",
+ ),
+ ] = ""
+
+ unwrap_annotated: Annotated[
+ bool,
+ _Field(
+ group="signatures",
+ description="Whether to unwrap `Annotated` types to show only the type without the annotations.",
+ ),
+ ] = False
+
+ extra: Annotated[
+ dict[str, Any],
+ _Field(
+ group="general",
+ description="Extra options.",
+ ),
+ ] = field(default_factory=dict)
+
+ @classmethod
+ def _extract_extra(cls, data: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
+ field_names = {field.name for field in fields(cls)}
+ copy = data.copy()
+ return {name: copy.pop(name) for name in data if name not in field_names}, copy
+
+ @classmethod
+ def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
+ """Coerce data."""
+ if "docstring_options" in data:
+ docstring_style = data.get("docstring_style", "google")
+ docstring_options = data["docstring_options"]
+ if docstring_options is not None:
+ if docstring_style == "auto":
+ docstring_options = AutoStyleOptions.from_data(**docstring_options)
+ elif docstring_style == "google":
+ docstring_options = GoogleStyleOptions(**docstring_options)
+ elif docstring_style == "numpy":
+ docstring_options = NumpyStyleOptions(**docstring_options)
+ elif docstring_style == "sphinx":
+ docstring_options = SphinxStyleOptions(**docstring_options)
+ data["docstring_options"] = docstring_options
+ if "summary" in data:
+ summary = data["summary"]
+ if summary is True:
+ summary = SummaryOption(attributes=True, functions=True, classes=True, modules=True)
+ elif summary is False:
+ summary = SummaryOption(attributes=False, functions=False, classes=False, modules=False)
+ else:
+ summary = SummaryOption(**summary)
+ data["summary"] = summary
+ return data
+
+ @classmethod
+ def from_data(cls, **data: Any) -> Self:
+ """Create an instance from a dictionary."""
+ return cls(**cls.coerce(**data))
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class PythonOptions(PythonInputOptions): # type: ignore[override,unused-ignore]
+ """Final options passed as template context."""
+
+ filters: list[tuple[re.Pattern, bool]] = field( # type: ignore[assignment]
+ default_factory=lambda: [
+ (re.compile(filtr.removeprefix("!")), filtr.startswith("!")) for filtr in _DEFAULT_FILTERS
+ ],
+ )
+ """A list of filters applied to filter objects based on their name."""
+
+ summary: SummaryOption = field(default_factory=SummaryOption)
+ """Whether to render summaries of modules, classes, functions (methods) and attributes."""
+
+ @classmethod
+ def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
+ """Create an instance from a dictionary."""
+ if "filters" in data:
+ data["filters"] = [
+ (re.compile(filtr.removeprefix("!")), filtr.startswith("!")) for filtr in data["filters"] or ()
+ ]
+ return super().coerce(**data)
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class Inventory:
+ """An inventory."""
+
+ url: Annotated[
+ str,
+ _Field(
+ parent="inventories",
+ description="The URL of the inventory.",
+ ),
+ ]
+
+ base: Annotated[
+ str | None,
+ _Field(
+ parent="inventories",
+ description="The base URL of the inventory.",
+ ),
+ ] = None
+
+ domains: Annotated[
+ list[str],
+ _Field(
+ parent="inventories",
+ description="The domains to load from the inventory.",
+ ),
+ ] = field(default_factory=lambda: ["py"])
+
+ @property
+ def _config(self) -> dict[str, Any]:
+ return {"base": self.base, "domains": self.domains}
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class PythonInputConfig:
+ """Python handler configuration."""
+
+ inventories: Annotated[
+ list[str | Inventory],
+ _Field(description="The inventories to load."),
+ ] = field(default_factory=list)
+
+ paths: Annotated[
+ list[str],
+ _Field(description="The paths in which to search for Python packages."),
+ ] = field(default_factory=lambda: ["."])
+
+ load_external_modules: Annotated[
+ bool | None,
+ _Field(description="Whether to always load external modules/packages."),
+ ] = None
+
+ options: Annotated[
+ PythonInputOptions,
+ _Field(description="Configuration options for collecting and rendering objects."),
+ ] = field(default_factory=PythonInputOptions)
+
+ locale: Annotated[
+ str | None,
+ _Field(description="The locale to use when translating template strings."),
+ ] = None
+
+ @classmethod
+ def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
+ """Coerce data."""
+ return data
+
+ @classmethod
+ def from_data(cls, **data: Any) -> Self:
+ """Create an instance from a dictionary."""
+ return cls(**cls.coerce(**data))
+
+
+# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
+@dataclass(**_dataclass_options) # type: ignore[call-overload]
+class PythonConfig(PythonInputConfig): # type: ignore[override,unused-ignore]
+ """Python handler configuration."""
+
+ inventories: Annotated[
+ list[Inventory],
+ _Field(description="The object inventories to load."),
+ ] = field(default_factory=list) # type: ignore[assignment]
+
+ options: Annotated[
+ dict[str, Any],
+ _Field(description="Configuration options for collecting and rendering objects."),
+ ] = field(default_factory=dict) # type: ignore[assignment]
+
+ @classmethod
+ def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
+ """Coerce data."""
+ if "inventories" in data:
+ data["inventories"] = [
+ Inventory(url=inv) if isinstance(inv, str) else Inventory(**inv) for inv in data["inventories"]
+ ]
+ return data
diff --git a/src/mkdocstrings_handlers/python/debug.py b/src/mkdocstrings_handlers/python/_internal/debug.py
similarity index 80%
rename from src/mkdocstrings_handlers/python/debug.py
rename to src/mkdocstrings_handlers/python/_internal/debug.py
index e44f2be5..5fff669f 100644
--- a/src/mkdocstrings_handlers/python/debug.py
+++ b/src/mkdocstrings_handlers/python/_internal/debug.py
@@ -1,5 +1,3 @@
-"""Debugging utilities."""
-
from __future__ import annotations
import os
@@ -10,7 +8,7 @@
@dataclass
-class Variable:
+class _Variable:
"""Dataclass describing an environment variable."""
name: str
@@ -20,7 +18,7 @@ class Variable:
@dataclass
-class Package:
+class _Package:
"""Dataclass describing a Python package."""
name: str
@@ -30,7 +28,7 @@ class Package:
@dataclass
-class Environment:
+class _Environment:
"""Dataclass to store environment information."""
interpreter_name: str
@@ -41,9 +39,9 @@ class Environment:
"""Path to Python executable."""
platform: str
"""Operating System."""
- packages: list[Package]
+ packages: list[_Package]
"""Installed packages."""
- variables: list[Variable]
+ variables: list[_Variable]
"""Environment variables."""
@@ -58,7 +56,7 @@ def _interpreter_name_version() -> tuple[str, str]:
return "", "0.0.0"
-def get_version(dist: str = "mkdocstrings-python") -> str:
+def _get_version(dist: str = "mkdocstrings-python") -> str:
"""Get version of the given distribution.
Parameters:
@@ -73,28 +71,28 @@ def get_version(dist: str = "mkdocstrings-python") -> str:
return "0.0.0"
-def get_debug_info() -> Environment:
+def _get_debug_info() -> _Environment:
"""Get debug/environment information.
Returns:
Environment information.
"""
py_name, py_version = _interpreter_name_version()
- packages = ["mkdocs", "mkdocstrings", "mkdocstrings-python", "griffe"]
+ packages = ["mkdocstrings-python"]
variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("MKDOCSTRINGS_PYTHON")]]
- return Environment(
+ return _Environment(
interpreter_name=py_name,
interpreter_version=py_version,
interpreter_path=sys.executable,
platform=platform.platform(),
- variables=[Variable(var, val) for var in variables if (val := os.getenv(var))],
- packages=[Package(pkg, get_version(pkg)) for pkg in packages],
+ variables=[_Variable(var, val) for var in variables if (val := os.getenv(var))],
+ packages=[_Package(pkg, _get_version(pkg)) for pkg in packages],
)
-def print_debug_info() -> None:
+def _print_debug_info() -> None:
"""Print debug/environment information."""
- info = get_debug_info()
+ info = _get_debug_info()
print(f"- __System__: {info.platform}")
print(f"- __Python__: {info.interpreter_name} {info.interpreter_version} ({info.interpreter_path})")
print("- __Environment variables__:")
@@ -106,4 +104,4 @@ def print_debug_info() -> None:
if __name__ == "__main__":
- print_debug_info()
+ _print_debug_info()
diff --git a/src/mkdocstrings_handlers/python/_internal/handler.py b/src/mkdocstrings_handlers/python/_internal/handler.py
new file mode 100644
index 00000000..896a70e3
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/handler.py
@@ -0,0 +1,416 @@
+# This module implements a handler for the Python language.
+
+from __future__ import annotations
+
+import glob
+import os
+import posixpath
+import sys
+from contextlib import suppress
+from dataclasses import asdict
+from pathlib import Path
+from typing import TYPE_CHECKING, Any, BinaryIO, ClassVar
+from warnings import warn
+
+from griffe import (
+ AliasResolutionError,
+ GriffeLoader,
+ LinesCollection,
+ ModulesCollection,
+ Parser,
+ load_extensions,
+ patch_loggers,
+)
+from mkdocs.exceptions import PluginError
+from mkdocstrings import BaseHandler, CollectionError, CollectorItem, HandlerOptions, Inventory, get_logger
+
+from mkdocstrings_handlers.python._internal import rendering
+from mkdocstrings_handlers.python._internal.config import PythonConfig, PythonOptions
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator, Mapping, MutableMapping, Sequence
+
+ from mkdocs.config.defaults import MkDocsConfig
+
+
+# YORE: EOL 3.10: Replace block with line 2.
+if sys.version_info >= (3, 11):
+ from contextlib import chdir
+else:
+ from contextlib import contextmanager
+
+ @contextmanager
+ def chdir(path: str) -> Iterator[None]:
+ old_wd = os.getcwd()
+ os.chdir(path)
+ try:
+ yield
+ finally:
+ os.chdir(old_wd)
+
+
+_logger = get_logger(__name__)
+
+patch_loggers(get_logger)
+
+
+# YORE: Bump 2: Remove block.
+def _warn_extra_options(names: Sequence[str]) -> None:
+ warn(
+ "Passing extra options directly under `options` is deprecated. "
+ "Instead, pass them under `options.extra`, and update your templates. "
+ f"Current extra (unrecognized) options: {', '.join(sorted(names))}",
+ DeprecationWarning,
+ stacklevel=3,
+ )
+
+
+class PythonHandler(BaseHandler):
+ """The Python handler class."""
+
+ name: ClassVar[str] = "python"
+ """The handler's name."""
+
+ domain: ClassVar[str] = "py"
+ """The cross-documentation domain/language for this handler."""
+
+ enable_inventory: ClassVar[bool] = True
+ """Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file."""
+
+ fallback_theme: ClassVar[str] = "material"
+ """The fallback theme."""
+
+ def __init__(self, config: PythonConfig, base_dir: Path, **kwargs: Any) -> None:
+ """Initialize the handler.
+
+ Parameters:
+ config: The handler configuration.
+ base_dir: The base directory of the project.
+ **kwargs: Arguments passed to the parent constructor.
+ """
+ super().__init__(**kwargs)
+
+ self.config = config
+ """The handler configuration."""
+ self.base_dir = base_dir
+ """The base directory of the project."""
+
+ # YORE: Bump 2: Remove block.
+ global_extra, global_options = PythonOptions._extract_extra(config.options)
+ if global_extra:
+ _warn_extra_options(global_extra.keys()) # type: ignore[arg-type]
+ self._global_extra = global_extra
+ self.global_options = global_options
+ """The global configuration options (in `mkdocs.yml`)."""
+
+ # YORE: Bump 2: Replace `# ` with `` within block.
+ # self.global_options = config.options
+ # """The global configuration options (in `mkdocs.yml`)."""
+
+ # Warn if user overrides base templates.
+ if self.custom_templates:
+ for theme_dir in base_dir.joinpath(self.custom_templates, "python").iterdir():
+ if theme_dir.joinpath("_base").is_dir():
+ _logger.warning(
+ f"Overriding base template '{theme_dir.name}/_base/.html.jinja' is not supported, "
+ f"override '{theme_dir.name}/.html.jinja' instead",
+ )
+
+ paths = config.paths or []
+
+ # Expand paths with glob patterns.
+ with chdir(str(base_dir)):
+ resolved_globs = [glob.glob(path) for path in paths]
+ paths = [path for glob_list in resolved_globs for path in glob_list]
+
+ # By default, add the base directory to the search paths.
+ if not paths:
+ paths.append(str(base_dir))
+
+ # Initialize search paths from `sys.path`, eliminating empty paths.
+ search_paths = [path for path in sys.path if path]
+
+ for path in reversed(paths):
+ # If it's not absolute, make path relative to the config file path, then make it absolute.
+ if not os.path.isabs(path):
+ path = os.path.abspath(base_dir / path) # noqa: PLW2901
+ # Remove pre-listed paths.
+ if path in search_paths:
+ search_paths.remove(path)
+ # Give precedence to user-provided paths.
+ search_paths.insert(0, path)
+
+ self._paths = search_paths
+ self._modules_collection: ModulesCollection = ModulesCollection()
+ self._lines_collection: LinesCollection = LinesCollection()
+
+ def get_inventory_urls(self) -> list[tuple[str, dict[str, Any]]]:
+ """Return the URLs of the inventory files to download."""
+ return [(inv.url, inv._config) for inv in self.config.inventories]
+
+ @staticmethod
+ def load_inventory(
+ in_file: BinaryIO,
+ url: str,
+ base_url: str | None = None,
+ domains: list[str] | None = None,
+ **kwargs: Any, # noqa: ARG004
+ ) -> Iterator[tuple[str, str]]:
+ """Yield items and their URLs from an inventory file streamed from `in_file`.
+
+ This implements mkdocstrings' `load_inventory` "protocol" (see [`mkdocstrings.plugin`][]).
+
+ Arguments:
+ in_file: The binary file-like object to read the inventory from.
+ url: The URL that this file is being streamed from (used to guess `base_url`).
+ base_url: The URL that this inventory's sub-paths are relative to.
+ domains: A list of domain strings to filter the inventory by, when not passed, "py" will be used.
+ **kwargs: Ignore additional arguments passed from the config.
+
+ Yields:
+ Tuples of (item identifier, item URL).
+ """
+ domains = domains or ["py"]
+ if base_url is None:
+ base_url = posixpath.dirname(url)
+
+ for item in Inventory.parse_sphinx(in_file, domain_filter=domains).values():
+ yield item.name, posixpath.join(base_url, item.uri)
+
+ def get_options(self, local_options: Mapping[str, Any]) -> HandlerOptions:
+ """Get combined default, global and local options.
+
+ Arguments:
+ local_options: The local options.
+
+ Returns:
+ The combined options.
+ """
+ # YORE: Bump 2: Remove block.
+ local_extra, local_options = PythonOptions._extract_extra(local_options) # type: ignore[arg-type]
+ if local_extra:
+ _warn_extra_options(local_extra.keys()) # type: ignore[arg-type]
+ unknown_extra = self._global_extra | local_extra
+
+ extra = {**self.global_options.get("extra", {}), **local_options.get("extra", {})}
+ options = {**self.global_options, **local_options, "extra": extra}
+ try:
+ # YORE: Bump 2: Replace `opts =` with `return` within line.
+ opts = PythonOptions.from_data(**options)
+ except Exception as error:
+ raise PluginError(f"Invalid options: {error}") from error
+
+ # YORE: Bump 2: Remove block.
+ for key, value in unknown_extra.items():
+ object.__setattr__(opts, key, value)
+ return opts
+
+ def collect(self, identifier: str, options: PythonOptions) -> CollectorItem:
+ """Collect the documentation for the given identifier.
+
+ Parameters:
+ identifier: The identifier of the object to collect.
+ options: The options to use for the collection.
+
+ Returns:
+ The collected item.
+ """
+ module_name = identifier.split(".", 1)[0]
+ unknown_module = module_name not in self._modules_collection
+ reapply = True
+ if options == {}:
+ if unknown_module:
+ raise CollectionError("Not loading additional modules during fallback")
+ options = self.get_options({})
+ reapply = False
+
+ parser_name = options.docstring_style
+ parser = parser_name and Parser(parser_name)
+ parser_options = options.docstring_options and asdict(options.docstring_options)
+
+ if unknown_module:
+ extensions = self.normalize_extension_paths(options.extensions)
+ loader = GriffeLoader(
+ extensions=load_extensions(*extensions),
+ search_paths=self._paths,
+ docstring_parser=parser,
+ docstring_options=parser_options, # type: ignore[arg-type]
+ modules_collection=self._modules_collection,
+ lines_collection=self._lines_collection,
+ allow_inspection=options.allow_inspection,
+ force_inspection=options.force_inspection,
+ )
+ try:
+ for pre_loaded_module in options.preload_modules:
+ if pre_loaded_module not in self._modules_collection:
+ loader.load(
+ pre_loaded_module,
+ try_relative_path=False,
+ find_stubs_package=options.find_stubs_package,
+ )
+ loader.load(
+ module_name,
+ try_relative_path=False,
+ find_stubs_package=options.find_stubs_package,
+ )
+ except ImportError as error:
+ raise CollectionError(str(error)) from error
+ unresolved, iterations = loader.resolve_aliases(
+ implicit=False,
+ external=self.config.load_external_modules,
+ )
+ if unresolved:
+ _logger.debug(f"{len(unresolved)} aliases were still unresolved after {iterations} iterations")
+ _logger.debug(f"Unresolved aliases: {', '.join(sorted(unresolved))}")
+
+ try:
+ doc_object = self._modules_collection[identifier]
+ except KeyError as error:
+ raise CollectionError(f"{identifier} could not be found") from error
+ except AliasResolutionError as error:
+ raise CollectionError(str(error)) from error
+
+ if not unknown_module and reapply:
+ with suppress(AliasResolutionError):
+ if doc_object.docstring is not None:
+ doc_object.docstring.parser = parser
+ doc_object.docstring.parser_options = parser_options or {}
+
+ return doc_object
+
+ def render(self, data: CollectorItem, options: PythonOptions) -> str:
+ """Render the collected data.
+
+ Parameters:
+ data: The collected data.
+ options: The options to use for rendering.
+
+ Returns:
+ The rendered data (HTML).
+ """
+ template_name = rendering.do_get_template(self.env, data)
+ template = self.env.get_template(template_name)
+
+ return template.render(
+ **{
+ "config": options,
+ data.kind.value: data,
+ # Heading level is a "state" variable, that will change at each step
+ # of the rendering recursion. Therefore, it's easier to use it as a plain value
+ # than as an item in a dictionary.
+ "heading_level": options.heading_level,
+ "root": True,
+ "locale": self.config.locale,
+ },
+ )
+
+ def update_env(self, config: Any) -> None: # noqa: ARG002
+ """Update the Jinja environment with custom filters and tests.
+
+ Parameters:
+ config: The SSG configuration.
+ """
+ self.env.trim_blocks = True
+ self.env.lstrip_blocks = True
+ self.env.keep_trailing_newline = False
+ self.env.filters["split_path"] = rendering.do_split_path
+ self.env.filters["crossref"] = rendering.do_crossref
+ self.env.filters["multi_crossref"] = rendering.do_multi_crossref
+ self.env.filters["order_members"] = rendering.do_order_members
+ self.env.filters["format_code"] = rendering.do_format_code
+ self.env.filters["format_signature"] = rendering.do_format_signature
+ self.env.filters["format_attribute"] = rendering.do_format_attribute
+ self.env.filters["filter_objects"] = rendering.do_filter_objects
+ self.env.filters["stash_crossref"] = rendering.do_stash_crossref
+ self.env.filters["get_template"] = rendering.do_get_template
+ self.env.filters["as_attributes_section"] = rendering.do_as_attributes_section
+ self.env.filters["as_functions_section"] = rendering.do_as_functions_section
+ self.env.filters["as_classes_section"] = rendering.do_as_classes_section
+ self.env.filters["as_modules_section"] = rendering.do_as_modules_section
+ self.env.filters["backlink_tree"] = rendering.do_backlink_tree
+ self.env.globals["AutorefsHook"] = rendering.AutorefsHook
+ self.env.tests["existing_template"] = lambda template_name: template_name in self.env.list_templates()
+
+ def get_aliases(self, identifier: str) -> tuple[str, ...]:
+ """Get the aliases for the given identifier.
+
+ Parameters:
+ identifier: The identifier to get the aliases for.
+
+ Returns:
+ The aliases.
+ """
+ if "(" in identifier:
+ identifier, parameter = identifier.split("(", 1)
+ parameter.removesuffix(")")
+ else:
+ parameter = ""
+ try:
+ data = self._modules_collection[identifier]
+ except (KeyError, AliasResolutionError):
+ return ()
+ aliases = [data.path]
+ try:
+ for alias in [data.canonical_path, *data.aliases]:
+ if alias not in aliases:
+ aliases.append(alias)
+ except AliasResolutionError:
+ pass
+ if parameter:
+ return tuple(f"{alias}({parameter})" for alias in aliases)
+ return tuple(aliases)
+
+ def normalize_extension_paths(self, extensions: Sequence) -> Sequence:
+ """Resolve extension paths relative to config file.
+
+ Parameters:
+ extensions: The extensions (configuration) to normalize.
+
+ Returns:
+ The normalized extensions.
+ """
+ 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:
+ # This is a system path. Normalize it, make it absolute relative to config file path.
+ pth = os.path.abspath(self.base_dir / pth)
+
+ if options is not None:
+ normalized.append({pth: options})
+ else:
+ normalized.append(pth)
+
+ return normalized
+
+
+def get_handler(
+ handler_config: MutableMapping[str, Any],
+ tool_config: MkDocsConfig,
+ **kwargs: Any,
+) -> PythonHandler:
+ """Return an instance of `PythonHandler`.
+
+ Parameters:
+ handler_config: The handler configuration.
+ tool_config: The tool (SSG) configuration.
+
+ Returns:
+ An instance of `PythonHandler`.
+ """
+ base_dir = Path(tool_config.config_file_path or "./mkdocs.yml").parent
+ if "inventories" not in handler_config and "import" in handler_config:
+ warn("The 'import' key is renamed 'inventories' for the Python handler", FutureWarning, stacklevel=1)
+ handler_config["inventories"] = handler_config.pop("import", [])
+ return PythonHandler(
+ config=PythonConfig.from_data(**handler_config),
+ base_dir=base_dir,
+ **kwargs,
+ )
diff --git a/src/mkdocstrings_handlers/python/_internal/rendering.py b/src/mkdocstrings_handlers/python/_internal/rendering.py
new file mode 100644
index 00000000..313658bc
--- /dev/null
+++ b/src/mkdocstrings_handlers/python/_internal/rendering.py
@@ -0,0 +1,786 @@
+# This module implements rendering utilities.
+
+from __future__ import annotations
+
+import random
+import re
+import string
+import subprocess
+import sys
+import warnings
+from collections import defaultdict
+from dataclasses import replace
+from functools import lru_cache
+from pathlib import Path
+from re import Match, Pattern
+from typing import TYPE_CHECKING, Any, Callable, ClassVar, Literal, TypeVar
+
+from griffe import (
+ Alias,
+ DocstringAttribute,
+ DocstringClass,
+ DocstringFunction,
+ DocstringModule,
+ DocstringSectionAttributes,
+ DocstringSectionClasses,
+ DocstringSectionFunctions,
+ DocstringSectionModules,
+ Object,
+)
+from jinja2 import TemplateNotFound, pass_context, pass_environment
+from markupsafe import Markup
+from mkdocs_autorefs import AutorefsHookInterface, Backlink, BacklinkCrumb
+from mkdocstrings import get_logger
+
+if TYPE_CHECKING:
+ from collections.abc import Iterable, Iterator, Sequence
+
+ from griffe import Attribute, Class, Function, Module
+ from jinja2 import Environment
+ from jinja2.runtime import Context
+ from mkdocstrings import CollectorItem
+
+_logger = get_logger(__name__)
+
+
+def _sort_key_alphabetical(item: CollectorItem) -> 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 = Literal["alphabetical", "source"]
+"""Ordering methods."""
+
+_order_map = {
+ "alphabetical": _sort_key_alphabetical,
+ "source": _sort_key_source,
+}
+
+
+def do_format_code(code: str, line_length: int) -> str:
+ """Format code.
+
+ Parameters:
+ code: The code to format.
+ line_length: The line length.
+
+ Returns:
+ The same code, formatted.
+ """
+ code = code.strip()
+ if len(code) < line_length:
+ return code
+ formatter = _get_formatter()
+ return formatter(code, line_length)
+
+
+class _StashCrossRefFilter:
+ stash: ClassVar[dict[str, str]] = {}
+
+ @staticmethod
+ def _gen_key(length: int) -> str:
+ return "_" + "".join(random.choice(string.ascii_letters + string.digits) for _ in range(max(1, length - 1))) # noqa: S311
+
+ def _gen_stash_key(self, length: int) -> str:
+ key = self._gen_key(length)
+ while key in self.stash:
+ key = self._gen_key(length)
+ return key
+
+ def __call__(self, crossref: str, *, length: int) -> str:
+ key = self._gen_stash_key(length)
+ self.stash[key] = crossref
+ return key
+
+
+do_stash_crossref = _StashCrossRefFilter()
+"""Filter to stash cross-references (and restore them after formatting and highlighting)."""
+
+
+def _format_signature(name: Markup, signature: str, line_length: int) -> str:
+ name = str(name).strip() # type: ignore[assignment]
+ signature = signature.strip()
+ if len(name + signature) < line_length:
+ return name + signature
+
+ # Black cannot format names with dots, so we replace
+ # the whole name with a string of equal length
+ name_length = len(name)
+ formatter = _get_formatter()
+ formatable = f"def {'x' * name_length}{signature}: pass"
+ formatted = formatter(formatable, line_length)
+
+ # We put back the original name
+ # and remove starting `def ` and trailing `: pass`
+ return name + formatted[4:-5].strip()[name_length:-1]
+
+
+@pass_context
+def do_format_signature(
+ context: Context,
+ callable_path: Markup,
+ function: Function,
+ line_length: int,
+ *,
+ annotations: bool | None = None,
+ crossrefs: bool = False, # noqa: ARG001
+) -> str:
+ """Format a signature.
+
+ Parameters:
+ context: Jinja context, passed automatically.
+ callable_path: The path of the callable we render the signature of.
+ function: The function we render the signature of.
+ line_length: The line length.
+ annotations: Whether to show type annotations.
+ crossrefs: Whether to cross-reference types in the signature.
+
+ Returns:
+ The same code, formatted.
+ """
+ env = context.environment
+ # YORE: Bump 2: Replace `do_get_template(env, "signature")` with `"signature.html.jinja"`.
+ template = env.get_template(do_get_template(env, "signature"))
+
+ if annotations is None:
+ new_context = context.parent
+ else:
+ new_context = dict(context.parent)
+ new_context["config"] = replace(new_context["config"], show_signature_annotations=annotations)
+
+ signature = template.render(new_context, function=function, signature=True)
+ signature = _format_signature(callable_path, signature, line_length)
+ signature = str(
+ env.filters["highlight"](
+ Markup.escape(signature),
+ language="python",
+ inline=False,
+ classes=["doc-signature"],
+ linenums=False,
+ ),
+ )
+
+ # Since we highlight the signature without `def`,
+ # Pygments sees it as a function call and not a function definition.
+ # The result is that the function name is not parsed as such,
+ # but instead as a regular name: `n` CSS class instead of `nf`.
+ # 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 := env.filters["stash_crossref"].stash:
+ for key, value in stash.items():
+ signature = re.sub(rf"\b{key}\b", value, signature)
+ stash.clear()
+
+ return signature
+
+
+@pass_context
+def do_format_attribute(
+ context: Context,
+ attribute_path: Markup,
+ attribute: Attribute,
+ line_length: int,
+ *,
+ crossrefs: bool = False, # noqa: ARG001
+) -> str:
+ """Format an attribute.
+
+ Parameters:
+ context: Jinja context, passed automatically.
+ attribute_path: The path of the callable we render the signature of.
+ attribute: The attribute we render the signature of.
+ line_length: The line length.
+ crossrefs: Whether to cross-reference types in the signature.
+
+ Returns:
+ The same code, formatted.
+ """
+ env = context.environment
+ # YORE: Bump 2: Replace `do_get_template(env, "expression")` with `"expression.html.jinja"`.
+ template = env.get_template(do_get_template(env, "expression"))
+ annotations = context.parent["config"].show_signature_annotations
+
+ signature = str(attribute_path).strip()
+ if annotations and attribute.annotation:
+ annotation = template.render(
+ context.parent,
+ expression=attribute.annotation,
+ signature=True,
+ backlink_type="returned-by",
+ )
+ signature += f": {annotation}"
+ if attribute.value:
+ value = template.render(context.parent, expression=attribute.value, signature=True, backlink_type="used-by")
+ signature += f" = {value}"
+
+ signature = do_format_code(signature, line_length)
+ signature = str(
+ env.filters["highlight"](
+ Markup.escape(signature),
+ language="python",
+ inline=False,
+ classes=["doc-signature"],
+ linenums=False,
+ ),
+ )
+
+ if stash := env.filters["stash_crossref"].stash:
+ for key, value in stash.items():
+ signature = re.sub(rf"\b{key}\b", value, signature)
+ stash.clear()
+
+ return signature
+
+
+def do_order_members(
+ members: Sequence[Object | Alias],
+ order: Order,
+ 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])
+
+
+# YORE: Bump 2: Remove block.
+@lru_cache
+def _warn_crossref() -> None:
+ warnings.warn(
+ "The `crossref` filter is deprecated and will be removed in a future version",
+ DeprecationWarning,
+ stacklevel=1,
+ )
+
+
+# YORE: Bump 2: Remove block.
+def do_crossref(path: str, *, brief: bool = True) -> Markup:
+ """Deprecated. Filter to create cross-references.
+
+ Parameters:
+ path: The path to link to.
+ brief: Show only the last part of the path, add full path as hover.
+
+ Returns:
+ Markup text.
+ """
+ _warn_crossref()
+ full_path = path
+ if brief:
+ path = full_path.split(".")[-1]
+ return Markup("{text}
"
+ return Markup(text).format(**variables) # noqa: S704
+
+
+_split_path_re = re.compile(r"([.(]?)([\w]+)(\))?")
+_splitable_re = re.compile(r"[().]")
+
+
+def do_split_path(path: str, full_path: str) -> Iterator[tuple[str, str, str, str]]:
+ """Split object paths for building cross-references.
+
+ Parameters:
+ path: The path to split.
+ full_path: The full path, used to compute correct paths for each part of the path.
+
+ Yields:
+ 4-tuples: prefix, word, full path, suffix.
+ """
+ # Path is a single word, yield full path directly.
+ if not _splitable_re.search(path):
+ yield ("", path, full_path, "")
+ return
+
+ current_path = ""
+ if path == full_path:
+ # Split full path and yield directly without storing data in a dict.
+ for match in _split_path_re.finditer(full_path):
+ prefix, word, suffix = match.groups()
+ current_path = f"{current_path}{prefix}{word}{suffix or ''}" if current_path else word
+ yield prefix or "", word, current_path, suffix or ""
+ return
+
+ # Split full path first to store tuples in a dict.
+ elements = {}
+ for match in _split_path_re.finditer(full_path):
+ prefix, word, suffix = match.groups()
+ current_path = f"{current_path}{prefix}{word}{suffix or ''}" if current_path else word
+ elements[word] = (prefix or "", word, current_path, suffix or "")
+
+ # Then split path and pick tuples from the dict.
+ first = True
+ for match in _split_path_re.finditer(path):
+ prefix, word, current_path, suffix = elements[match.group(2)]
+ yield "" if first else prefix, word, current_path, suffix
+ first = False
+
+
+def _keep_object(name: str, filters: Sequence[tuple[Pattern, bool]]) -> bool:
+ keep = None
+ rules = set()
+ for regex, exclude in filters:
+ rules.add(exclude)
+ if regex.search(name):
+ keep = not exclude
+ if keep is None:
+ # When we only include stuff, no match = reject.
+ # When we only exclude stuff, or include and exclude stuff, no match = keep.
+ return rules != {False}
+ return keep
+
+
+def 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_formatter() -> Callable[[str, int], str]:
+ for formatter_function in [
+ _get_black_formatter,
+ _get_ruff_formatter,
+ ]:
+ if (formatter := formatter_function()) is not None:
+ return formatter
+
+ _logger.info("Formatting signatures requires either Black or Ruff to be installed.")
+ return lambda text, _: text
+
+
+def _get_ruff_formatter() -> Callable[[str, int], str] | None:
+ try:
+ from ruff.__main__ import find_ruff_bin
+ except ImportError:
+ return None
+
+ try:
+ ruff_bin = find_ruff_bin()
+ except FileNotFoundError:
+ ruff_bin = "ruff"
+
+ def formatter(code: str, line_length: int) -> str:
+ try:
+ completed_process = subprocess.run( # noqa: S603
+ [
+ ruff_bin,
+ "format",
+ "--config",
+ f"line-length={line_length}",
+ "--stdin-filename",
+ "file.py",
+ "-",
+ ],
+ check=True,
+ capture_output=True,
+ text=True,
+ input=code,
+ )
+ except subprocess.CalledProcessError:
+ return code
+ else:
+ return completed_process.stdout
+
+ return formatter
+
+
+def _get_black_formatter() -> Callable[[str, int], str] | None:
+ try:
+ from black import InvalidInput, Mode, format_str
+ except ModuleNotFoundError:
+ return None
+
+ def formatter(code: str, line_length: int) -> str:
+ mode = Mode(line_length=line_length)
+ try:
+ return format_str(code, mode=mode)
+ except InvalidInput:
+ return code
+
+ return formatter
+
+
+# YORE: Bump 2: Remove line.
+@pass_environment
+# YORE: Bump 2: Replace `env: Environment, ` with `` within line.
+# YORE: Bump 2: Replace `str | ` with `` within line.
+def do_get_template(env: Environment, obj: str | Object) -> str:
+ """Get the template name used to render an object.
+
+ Parameters:
+ env: The Jinja environment, passed automatically.
+ obj: A Griffe object, or a template name.
+
+ Returns:
+ A template name.
+ """
+ name = obj
+ if isinstance(obj, (Alias, Object)):
+ extra_data = getattr(obj, "extra", {}).get("mkdocstrings", {})
+ if name := extra_data.get("template", ""):
+ return name
+ name = obj.kind.value
+ # YORE: Bump 2: Replace block with `return f"{name}.html.jinja"`.
+ try:
+ template = env.get_template(f"{name}.html")
+ except TemplateNotFound:
+ return f"{name}.html.jinja"
+ our_template = Path(template.filename).is_relative_to(Path(__file__).parent.parent) # type: ignore[arg-type]
+ if our_template:
+ return f"{name}.html.jinja"
+ _logger.warning(
+ f"DeprecationWarning: Overriding '{name}.html' is deprecated, override '{name}.html.jinja' instead. ",
+ once=True,
+ )
+ return f"{name}.html"
+
+
+@pass_context
+def do_as_attributes_section(
+ context: Context, # noqa: ARG001
+ attributes: Sequence[Attribute],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionAttributes:
+ """Build an attributes section from a list of attributes.
+
+ Parameters:
+ attributes: The attributes to build the section from.
+ check_public: Whether to check if the attribute is public.
+
+ Returns:
+ An attributes docstring section.
+ """
+
+ def _parse_docstring_summary(attribute: Attribute) -> str:
+ if attribute.docstring is None:
+ return ""
+ line = attribute.docstring.value.split("\n", 1)[0]
+ if ":" in line and attribute.docstring.parser_options.get("returns_type_in_property_summary", False):
+ _, line = line.split(":", 1)
+ return line
+
+ return DocstringSectionAttributes(
+ [
+ DocstringAttribute(
+ name=attribute.name,
+ description=_parse_docstring_summary(attribute),
+ annotation=attribute.annotation,
+ value=attribute.value, # type: ignore[arg-type]
+ )
+ for attribute in attributes
+ if not check_public or attribute.is_public
+ ],
+ )
+
+
+@pass_context
+def do_as_functions_section(
+ context: Context,
+ functions: Sequence[Function],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionFunctions:
+ """Build a functions section from a list of functions.
+
+ Parameters:
+ functions: The functions to build the section from.
+ check_public: Whether to check if the function is public.
+
+ Returns:
+ A functions docstring section.
+ """
+ keep_init_method = not context.parent["config"].merge_init_into_class
+ return DocstringSectionFunctions(
+ [
+ DocstringFunction(
+ name=function.name,
+ description=function.docstring.value.split("\n", 1)[0] if function.docstring else "",
+ )
+ for function in functions
+ if (not check_public or function.is_public) and (function.name != "__init__" or keep_init_method)
+ ],
+ )
+
+
+@pass_context
+def do_as_classes_section(
+ context: Context, # noqa: ARG001
+ classes: Sequence[Class],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionClasses:
+ """Build a classes section from a list of classes.
+
+ Parameters:
+ classes: The classes to build the section from.
+ check_public: Whether to check if the class is public.
+
+ Returns:
+ A classes docstring section.
+ """
+ return DocstringSectionClasses(
+ [
+ DocstringClass(
+ name=cls.name,
+ description=cls.docstring.value.split("\n", 1)[0] if cls.docstring else "",
+ )
+ for cls in classes
+ if not check_public or cls.is_public
+ ],
+ )
+
+
+@pass_context
+def do_as_modules_section(
+ context: Context, # noqa: ARG001
+ modules: Sequence[Module],
+ *,
+ check_public: bool = True,
+) -> DocstringSectionModules:
+ """Build a modules section from a list of modules.
+
+ Parameters:
+ modules: The modules to build the section from.
+ check_public: Whether to check if the module is public.
+
+ Returns:
+ A modules docstring section.
+ """
+ return DocstringSectionModules(
+ [
+ DocstringModule(
+ name=module.name,
+ description=module.docstring.value.split("\n", 1)[0] if module.docstring else "",
+ )
+ for module in modules
+ if not check_public or module.is_public
+ ],
+ )
+
+
+class AutorefsHook(AutorefsHookInterface):
+ """Autorefs hook.
+
+ With this hook, we're able to add context to autorefs (cross-references),
+ such as originating file path and line number, to improve error reporting.
+ """
+
+ def __init__(self, current_object: Object | Alias, config: dict[str, Any]) -> None:
+ """Initialize the hook.
+
+ Parameters:
+ current_object: The object being rendered.
+ config: The configuration dictionary.
+ """
+ self.current_object = current_object
+ """The current object being rendered."""
+ self.config = config
+ """The configuration options."""
+
+ def expand_identifier(self, identifier: str) -> str:
+ """Expand an identifier.
+
+ Parameters:
+ identifier: The identifier to expand.
+
+ Returns:
+ The expanded identifier.
+ """
+ return identifier
+
+ def get_context(self) -> AutorefsHookInterface.Context:
+ """Get the context for the current object.
+
+ Returns:
+ The context.
+ """
+ role = {
+ "attribute": "data" if self.current_object.parent and self.current_object.parent.is_module else "attr",
+ "class": "class",
+ "function": "meth" if self.current_object.parent and self.current_object.parent.is_class else "func",
+ "module": "mod",
+ }.get(self.current_object.kind.value.lower(), "obj")
+ origin = self.current_object.path
+ try:
+ filepath = self.current_object.docstring.parent.filepath # type: ignore[union-attr]
+ lineno = self.current_object.docstring.lineno or 0 # type: ignore[union-attr]
+ except AttributeError:
+ filepath = self.current_object.filepath
+ lineno = 0
+
+ return AutorefsHookInterface.Context(
+ domain="py",
+ role=role,
+ origin=origin,
+ filepath=str(filepath),
+ lineno=lineno,
+ )
+
+
+_T = TypeVar("_T")
+_Tree = dict[_T, "_Tree"]
+_rtree = lambda: defaultdict(_rtree) # type: ignore[has-type,var-annotated] # noqa: E731
+
+Tree = dict[tuple[_T, ...], "Tree"]
+"""A tree type. Each node holds a tuple of items."""
+
+
+def _tree(data: Iterable[tuple[_T, ...]]) -> _Tree:
+ new_tree = _rtree()
+ for nav in data:
+ *path, leaf = nav
+ node = new_tree
+ for key in path:
+ node = node[key]
+ node[leaf] = _rtree()
+ return new_tree
+
+
+def _compact_tree(tree: _Tree) -> Tree:
+ new_tree = _rtree()
+ for key, value in tree.items():
+ child = _compact_tree(value)
+ if len(child) == 1:
+ child_key, child_value = next(iter(child.items()))
+ new_key = (key, *child_key)
+ new_tree[new_key] = child_value
+ else:
+ new_tree[(key,)] = child
+ return new_tree
+
+
+def do_backlink_tree(backlinks: list[Backlink]) -> Tree[BacklinkCrumb]:
+ """Build a tree of backlinks.
+
+ Parameters:
+ backlinks: The list of backlinks.
+
+ Returns:
+ A tree of backlinks.
+ """
+ return _compact_tree(_tree(backlink.crumbs for backlink in backlinks))
diff --git a/src/mkdocstrings_handlers/python/config.py b/src/mkdocstrings_handlers/python/config.py
index af2ac7f7..5edab089 100644
--- a/src/mkdocstrings_handlers/python/config.py
+++ b/src/mkdocstrings_handlers/python/config.py
@@ -1,1023 +1,17 @@
-"""Configuration and options dataclasses."""
+"""Deprecated. Import from `mkdocstrings_handlers.python` directly."""
-from __future__ import annotations
+# YORE: Bump 2: Remove file.
-import re
-import sys
-from dataclasses import field, fields
-from typing import TYPE_CHECKING, Annotated, Any, Literal
+import warnings
+from typing import Any
-from mkdocstrings import get_logger
+from mkdocstrings_handlers.python._internal import config
-# 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__)
-
-
-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
-
- if sys.version_info < (3, 10):
- try:
- import eval_type_backport # noqa: F401
- except ImportError:
- logger.debug(
- "Pydantic needs the `eval-type-backport` package to be installed "
- "for modern type syntax to work on Python 3.9. "
- "Deactivating Pydantic validation for Python handler options.",
- )
- raise
-
- from inspect import cleandoc
-
- from pydantic import Field as BaseField
- from pydantic.dataclasses import dataclass
-
- _base_url = "https://mkdocstrings.github.io/python/usage"
-
- def Field( # noqa: N802, D103
- *args: Any,
- description: str,
- group: Literal["general", "headings", "members", "docstrings", "signatures"] | None = None,
- parent: str | None = None,
- **kwargs: Any,
- ) -> None:
- def _add_markdown_description(schema: dict[str, Any]) -> None:
- url = f"{_base_url}/{f'configuration/{group}/' if group else ''}#{parent or schema['title']}"
- schema["markdownDescription"] = f"[DOCUMENTATION]({url})\n\n{schema['description']}"
-
- return BaseField(
- *args,
- description=cleandoc(description),
- field_title_generator=lambda name, _: name,
- json_schema_extra=_add_markdown_description,
- **kwargs,
- )
-except ImportError:
- from dataclasses import dataclass # type: ignore[no-redef]
-
- def Field(*args: Any, **kwargs: Any) -> None: # type: ignore[misc] # noqa: D103, N802
- pass
-
-
-if TYPE_CHECKING:
- from collections.abc import MutableMapping
-
-
-# YORE: EOL 3.9: Remove block.
-_dataclass_options = {"frozen": True}
-if sys.version_info >= (3, 10):
- _dataclass_options["kw_only"] = True
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class GoogleStyleOptions:
- """Google style docstring options."""
-
- ignore_init_summary: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Whether to ignore the summary in `__init__` methods' docstrings.",
- ),
- ] = False
-
- returns_multiple_items: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="""Whether to parse multiple items in `Yields` and `Returns` sections.
-
- When true, each item's continuation lines must be indented.
- When false (single item), no further indentation is required.
- """,
- ),
- ] = True
-
- returns_named_value: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="""Whether to parse `Yields` and `Returns` section items as name and description, rather than type and description.
-
- When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`.
- When false, parentheses are optional but the items cannot be named: `int: Description`.
- """,
- ),
- ] = True
-
- returns_type_in_property_summary: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Whether to parse the return type of properties at the beginning of their summary: `str: Summary of the property`.",
- ),
- ] = False
-
- receives_multiple_items: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="""Whether to parse multiple items in `Receives` sections.
-
- When true, each item's continuation lines must be indented.
- When false (single item), no further indentation is required.
- """,
- ),
- ] = True
-
- receives_named_value: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="""Whether to parse `Receives` section items as name and description, rather than type and description.
-
- When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`.
- When false, parentheses are optional but the items cannot be named: `int: Description`.
- """,
- ),
- ] = True
-
- trim_doctest_flags: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Whether to remove doctest flags from Python example blocks.",
- ),
- ] = True
-
- warn_unknown_params: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Warn about documented parameters not appearing in the signature.",
- ),
- ] = True
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class NumpyStyleOptions:
- """Numpy style docstring options."""
-
- ignore_init_summary: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Whether to ignore the summary in `__init__` methods' docstrings.",
- ),
- ] = False
-
- trim_doctest_flags: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Whether to remove doctest flags from Python example blocks.",
- ),
- ] = True
-
- warn_unknown_params: Annotated[
- bool,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Warn about documented parameters not appearing in the signature.",
- ),
- ] = True
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class SphinxStyleOptions:
- """Sphinx style docstring options."""
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class PerStyleOptions:
- """Per style options."""
-
- google: Annotated[
- GoogleStyleOptions,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Google-style options.",
- ),
- ] = field(default_factory=GoogleStyleOptions)
-
- numpy: Annotated[
- NumpyStyleOptions,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Numpydoc-style options.",
- ),
- ] = field(default_factory=NumpyStyleOptions)
-
- sphinx: Annotated[
- SphinxStyleOptions,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Sphinx-style options.",
- ),
- ] = field(default_factory=SphinxStyleOptions)
-
- @classmethod
- def from_data(cls, **data: Any) -> Self:
- """Create an instance from a dictionary."""
- if "google" in data:
- data["google"] = GoogleStyleOptions(**data["google"])
- if "numpy" in data:
- data["numpy"] = NumpyStyleOptions(**data["numpy"])
- if "sphinx" in data:
- data["sphinx"] = SphinxStyleOptions(**data["sphinx"])
- return cls(**data)
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class AutoStyleOptions:
- """Auto style docstring options."""
-
- method: Annotated[
- Literal["heuristics", "max_sections"],
- Field(
- group="docstrings",
- parent="docstring_options",
- description="The method to use to determine the docstring style.",
- ),
- ] = "heuristics"
-
- style_order: Annotated[
- list[str],
- Field(
- group="docstrings",
- parent="docstring_options",
- description="The order of the docstring styles to try.",
- ),
- ] = field(default_factory=lambda: ["sphinx", "google", "numpy"])
-
- default: Annotated[
- str | None,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="The default docstring style to use if no other style is detected.",
- ),
- ] = None
-
- per_style_options: Annotated[
- PerStyleOptions,
- Field(
- group="docstrings",
- parent="docstring_options",
- description="Per-style options.",
- ),
- ] = field(default_factory=PerStyleOptions)
-
- @classmethod
- def from_data(cls, **data: Any) -> Self:
- """Create an instance from a dictionary."""
- if "per_style_options" in data:
- data["per_style_options"] = PerStyleOptions.from_data(**data["per_style_options"])
- return cls(**data)
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class SummaryOption:
- """Summary option."""
-
- attributes: Annotated[
- bool,
- Field(
- group="members",
- parent="summary",
- description="Whether to render summaries of attributes.",
- ),
- ] = False
-
- functions: Annotated[
- bool,
- Field(
- group="members",
- parent="summary",
- description="Whether to render summaries of functions (methods).",
- ),
- ] = False
-
- classes: Annotated[
- bool,
- Field(
- group="members",
- parent="summary",
- description="Whether to render summaries of classes.",
- ),
- ] = False
-
- modules: Annotated[
- bool,
- Field(
- group="members",
- parent="summary",
- description="Whether to render summaries of modules.",
- ),
- ] = False
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class PythonInputOptions:
- """Accepted input options."""
-
- allow_inspection: Annotated[
- bool,
- Field(
- group="general",
- description="Whether to allow inspecting modules when visiting them is not possible.",
- ),
- ] = True
-
- force_inspection: Annotated[
- bool,
- Field(
- group="general",
- description="Whether to force using dynamic analysis when loading data.",
- ),
- ] = False
-
- annotations_path: Annotated[
- Literal["brief", "source", "full"],
- Field(
- group="signatures",
- description="The verbosity for annotations path: `brief` (recommended), `source` (as written in the source), or `full`.",
- ),
- ] = "brief"
-
- 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],
- Field(
- group="members",
- description="""A list of filters applied to filter objects based on their name.
-
- A filter starting with `!` will exclude matching objects instead of including them.
- The `members` option takes precedence over `filters` (filters will still be applied recursively
- to lower members in the hierarchy).
- """,
- ),
- ] = field(default_factory=lambda: ["!^_[^_]"])
-
- find_stubs_package: Annotated[
- bool,
- Field(
- group="general",
- description="Whether to load stubs package (package-stubs) when extracting docstrings.",
- ),
- ] = False
-
- group_by_category: Annotated[
- bool,
- Field(
- group="members",
- description="Group the object's children by categories: attributes, classes, functions, and modules.",
- ),
- ] = True
-
- heading: Annotated[
- str,
- Field(
- group="headings",
- description="A custom string to override the autogenerated heading of the root object.",
- ),
- ] = ""
-
- heading_level: Annotated[
- int,
- Field(
- group="headings",
- description="The initial heading level to use.",
- ),
- ] = 2
-
- inherited_members: Annotated[
- bool | list[str],
- Field(
- group="members",
- description="""A boolean, or an explicit list of inherited members to render.
-
- If true, select all inherited members, which can then be filtered with `members`.
- If false or empty list, do not select any inherited member.
- """,
- ),
- ] = False
-
- line_length: Annotated[
- int,
- Field(
- group="signatures",
- description="Maximum line length when formatting code/signatures.",
- ),
- ] = 60
-
- members: Annotated[
- list[str] | bool | None,
- Field(
- group="members",
- description="""A boolean, or an explicit list of members to render.
-
- If true, select all members without further filtering.
- If false or empty list, do not render members.
- If none, select all members and apply further filtering with filters and docstrings.
- """,
- ),
- ] = None
-
- members_order: Annotated[
- Literal["alphabetical", "source"],
- Field(
- group="members",
- description="""The members ordering to use.
-
- - `alphabetical`: order by the members names,
- - `source`: order members as they appear in the source file.
- """,
- ),
- ] = "alphabetical"
-
- merge_init_into_class: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to merge the `__init__` method into the class' signature and docstring.",
- ),
- ] = False
-
- modernize_annotations: Annotated[
- bool,
- Field(
- group="signatures",
- description="Whether to modernize annotations, for example `Optional[str]` into `str | None`.",
- ),
- ] = False
-
- parameter_headings: Annotated[
- bool,
- Field(
- group="headings",
- description="Whether to render headings for parameters (therefore showing parameters in the ToC).",
- ),
- ] = False
-
- preload_modules: Annotated[
- list[str],
- Field(
- group="general",
- description="""Pre-load modules that are not specified directly in autodoc instructions (`::: identifier`).
-
- It is useful when you want to render documentation for a particular member of an object,
- and this member is imported from another package than its parent.
-
- For an imported member to be rendered, you need to add it to the `__all__` attribute
- of the importing module.
-
- The modules must be listed as an array of strings.
- """,
- ),
- ] = field(default_factory=list)
-
- relative_crossrefs: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to enable the relative crossref syntax.",
- ),
- ] = False
-
- scoped_crossrefs: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to enable the scoped crossref ability.",
- ),
- ] = False
-
- show_overloads: Annotated[
- bool,
- Field(
- group="signatures",
- description="Show the overloads of a function or method.",
- ),
- ] = True
-
- separate_signature: Annotated[
- bool,
- Field(
- group="signatures",
- description="""Whether to put the whole signature in a code block below the heading.
-
- If Black or Ruff are installed, the signature is also formatted using them.
- """,
- ),
- ] = False
-
- show_bases: Annotated[
- bool,
- Field(
- group="general",
- description="Show the base classes of a class.",
- ),
- ] = True
-
- show_category_heading: Annotated[
- bool,
- Field(
- group="headings",
- description="When grouped by categories, show a heading for each category.",
- ),
- ] = False
-
- show_docstring_attributes: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Attributes' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_classes: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Classes' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_description: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the textual block (including admonitions) in the object's docstring.",
- ),
- ] = True
-
- show_docstring_examples: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Examples' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_functions: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Functions' or 'Methods' sections in the object's docstring.",
- ),
- ] = True
-
- show_docstring_modules: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Modules' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_other_parameters: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Other Parameters' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_parameters: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Parameters' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_raises: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Raises' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_receives: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Receives' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_returns: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Returns' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_warns: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Warns' section in the object's docstring.",
- ),
- ] = True
-
- show_docstring_yields: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to display the 'Yields' section in the object's docstring.",
- ),
- ] = True
-
- show_if_no_docstring: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Show the object heading even if it has no docstring or children with docstrings.",
- ),
- ] = False
-
- show_inheritance_diagram: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Show the inheritance diagram of a class using Mermaid.",
- ),
- ] = False
-
- show_labels: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Whether to show labels of the members.",
- ),
- ] = True
-
- show_object_full_path: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Show the full Python path of every object.",
- ),
- ] = False
-
- show_root_full_path: Annotated[
- bool,
- Field(
- group="docstrings",
- description="Show the full Python path for the root object heading.",
- ),
- ] = True
-
- show_root_heading: Annotated[
- bool,
- Field(
- group="headings",
- description="""Show the heading of the object at the root of the documentation tree.
-
- The root object is the object referenced by the identifier after `:::`.
- """,
- ),
- ] = False
-
- show_root_members_full_path: Annotated[
- bool,
- Field(
- group="headings",
- description="Show the full Python path of the root members.",
- ),
- ] = False
-
- show_root_toc_entry: Annotated[
- bool,
- Field(
- group="headings",
- description="If the root heading is not shown, at least add a ToC entry for it.",
- ),
- ] = True
-
- show_signature_annotations: Annotated[
- bool,
- Field(
- group="signatures",
- description="Show the type annotations in methods and functions signatures.",
- ),
- ] = False
-
- show_signature: Annotated[
- bool,
- Field(
- group="signatures",
- description="Show methods and functions signatures.",
- ),
- ] = True
-
- show_source: Annotated[
- bool,
- Field(
- group="general",
- description="Show the source code of this object.",
- ),
- ] = True
-
- show_submodules: Annotated[
- bool,
- Field(
- group="members",
- description="When rendering a module, show its submodules recursively.",
- ),
- ] = False
-
- show_symbol_type_heading: Annotated[
- bool,
- Field(
- group="headings",
- description="Show the symbol type in headings (e.g. mod, class, meth, func and attr).",
- ),
- ] = False
-
- show_symbol_type_toc: Annotated[
- bool,
- Field(
- group="headings",
- description="Show the symbol type in the Table of Contents (e.g. mod, class, methd, func and attr).",
- ),
- ] = False
-
- signature_crossrefs: Annotated[
- bool,
- Field(
- group="signatures",
- description="Whether to render cross-references for type annotations in signatures.",
- ),
- ] = False
-
- summary: Annotated[
- bool | SummaryOption,
- Field(
- group="members",
- description="Whether to render summaries of modules, classes, functions (methods) and attributes.",
- ),
- ] = field(default_factory=SummaryOption)
-
- toc_label: Annotated[
- str,
- Field(
- group="headings",
- description="A custom string to override the autogenerated toc label of the root object.",
- ),
- ] = ""
-
- unwrap_annotated: Annotated[
- bool,
- Field(
- group="signatures",
- description="Whether to unwrap `Annotated` types to show only the type without the annotations.",
- ),
- ] = False
-
- extra: Annotated[
- dict[str, Any],
- Field(
- group="general",
- description="Extra options.",
- ),
- ] = field(default_factory=dict)
-
- @classmethod
- def _extract_extra(cls, data: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
- field_names = {field.name for field in fields(cls)}
- copy = data.copy()
- return {name: copy.pop(name) for name in data if name not in field_names}, copy
-
- @classmethod
- def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
- """Coerce data."""
- if "docstring_options" in data:
- docstring_style = data.get("docstring_style", "google")
- docstring_options = data["docstring_options"]
- if docstring_options is not None:
- if docstring_style == "auto":
- docstring_options = AutoStyleOptions.from_data(**docstring_options)
- elif docstring_style == "google":
- docstring_options = GoogleStyleOptions(**docstring_options)
- elif docstring_style == "numpy":
- docstring_options = NumpyStyleOptions(**docstring_options)
- elif docstring_style == "sphinx":
- docstring_options = SphinxStyleOptions(**docstring_options)
- data["docstring_options"] = docstring_options
- if "summary" in data:
- summary = data["summary"]
- if summary is True:
- summary = SummaryOption(attributes=True, functions=True, classes=True, modules=True)
- elif summary is False:
- summary = SummaryOption(attributes=False, functions=False, classes=False, modules=False)
- else:
- summary = SummaryOption(**summary)
- data["summary"] = summary
- return data
-
- @classmethod
- def from_data(cls, **data: Any) -> Self:
- """Create an instance from a dictionary."""
- return cls(**cls.coerce(**data))
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class PythonOptions(PythonInputOptions): # type: ignore[override,unused-ignore]
- """Final options passed as template context."""
-
- filters: list[tuple[re.Pattern, bool]] = field(default_factory=list) # type: ignore[assignment]
- """A list of filters applied to filter objects based on their name."""
-
- summary: SummaryOption = field(default_factory=SummaryOption)
- """Whether to render summaries of modules, classes, functions (methods) and attributes."""
-
- @classmethod
- def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
- """Create an instance from a dictionary."""
- if "filters" in data:
- data["filters"] = [
- (re.compile(filtr.lstrip("!")), filtr.startswith("!")) for filtr in data["filters"] or ()
- ]
- return super().coerce(**data)
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class Inventory:
- """An inventory."""
-
- url: Annotated[
- str,
- Field(
- parent="inventories",
- description="The URL of the inventory.",
- ),
- ]
-
- base: Annotated[
- str | None,
- Field(
- parent="inventories",
- description="The base URL of the inventory.",
- ),
- ] = None
-
- domains: Annotated[
- list[str],
- Field(
- parent="inventories",
- description="The domains to load from the inventory.",
- ),
- ] = field(default_factory=lambda: ["py"])
-
- @property
- def _config(self) -> dict[str, Any]:
- return {"base": self.base, "domains": self.domains}
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class PythonInputConfig:
- """Python handler configuration."""
-
- inventories: Annotated[
- list[str | Inventory],
- Field(description="The inventories to load."),
- ] = field(default_factory=list)
-
- paths: Annotated[
- list[str],
- Field(description="The paths in which to search for Python packages."),
- ] = field(default_factory=lambda: ["."])
-
- load_external_modules: Annotated[
- bool | None,
- Field(description="Whether to always load external modules/packages."),
- ] = None
-
- options: Annotated[
- PythonInputOptions,
- Field(description="Configuration options for collecting and rendering objects."),
- ] = field(default_factory=PythonInputOptions)
-
- locale: Annotated[
- str | None,
- Field(description="The locale to use when translating template strings."),
- ] = None
-
- @classmethod
- def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
- """Coerce data."""
- return data
-
- @classmethod
- def from_data(cls, **data: Any) -> Self:
- """Create an instance from a dictionary."""
- return cls(**cls.coerce(**data))
-
-
-# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line.
-@dataclass(**_dataclass_options) # type: ignore[call-overload]
-class PythonConfig(PythonInputConfig): # type: ignore[override,unused-ignore]
- """Python handler configuration."""
-
- inventories: list[Inventory] = field(default_factory=list) # type: ignore[assignment]
- options: dict[str, Any] = field(default_factory=dict) # type: ignore[assignment]
-
- @classmethod
- def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
- """Coerce data."""
- if "inventories" in data:
- data["inventories"] = [
- Inventory(url=inv) if isinstance(inv, str) else Inventory(**inv) for inv in data["inventories"]
- ]
- return data
+def __getattr__(name: str) -> Any:
+ warnings.warn(
+ "Importing from `mkdocstrings_handlers.python.config` is deprecated. Import from `mkdocstrings_handlers.python` directly.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return getattr(config, name)
diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py
index 69f228f1..5b334860 100644
--- a/src/mkdocstrings_handlers/python/handler.py
+++ b/src/mkdocstrings_handlers/python/handler.py
@@ -1,375 +1,17 @@
-"""This module implements a handler for the Python language."""
+"""Deprecated. Import from `mkdocstrings_handlers.python` directly."""
-from __future__ import annotations
+# YORE: Bump 2: Remove file.
-import glob
-import os
-import posixpath
-import sys
-from contextlib import suppress
-from dataclasses import asdict
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, BinaryIO, ClassVar
-from warnings import warn
+import warnings
+from typing import Any
-from griffe import (
- AliasResolutionError,
- GriffeLoader,
- LinesCollection,
- ModulesCollection,
- Parser,
- load_extensions,
- patch_loggers,
-)
-from mkdocs.exceptions import PluginError
-from mkdocstrings import BaseHandler, CollectionError, CollectorItem, HandlerOptions, Inventory, get_logger
+from mkdocstrings_handlers.python._internal import handler
-from mkdocstrings_handlers.python import rendering
-from mkdocstrings_handlers.python.config import PythonConfig, PythonOptions
-if TYPE_CHECKING:
- from collections.abc import Iterator, Mapping, MutableMapping, Sequence
-
- from mkdocs.config.defaults import MkDocsConfig
-
-
-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)
-
-
-def _warn_extra_options(names: Sequence[str]) -> None:
- warn(
- "Passing extra options directly under `options` is deprecated. "
- "Instead, pass them under `options.extra`, and update your templates. "
- f"Current extra (unrecognized) options: {', '.join(sorted(names))}",
+def __getattr__(name: str) -> Any:
+ warnings.warn(
+ "Importing from `mkdocstrings_handlers.python.handler` is deprecated. Import from `mkdocstrings_handlers.python` directly.",
DeprecationWarning,
- stacklevel=3,
- )
-
-
-class PythonHandler(BaseHandler):
- """The Python handler class."""
-
- name: ClassVar[str] = "python"
- """The handler's name."""
-
- domain: ClassVar[str] = "py"
- """The cross-documentation domain/language for this handler."""
-
- enable_inventory: ClassVar[bool] = True
- """Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file."""
-
- fallback_theme: ClassVar[str] = "material"
- """The fallback theme."""
-
- def __init__(self, config: PythonConfig, base_dir: Path, **kwargs: Any) -> None:
- """Initialize the handler.
-
- Parameters:
- config: The handler configuration.
- base_dir: The base directory of the project.
- **kwargs: Arguments passed to the parent constructor.
- """
- super().__init__(**kwargs)
-
- self.config = config
- self.base_dir = base_dir
-
- # YORE: Bump 2: Replace block with `self.global_options = config.options`.
- global_extra, global_options = PythonOptions._extract_extra(config.options)
- if global_extra:
- _warn_extra_options(global_extra.keys()) # type: ignore[arg-type]
- self._global_extra = global_extra
- self.global_options = global_options
-
- # Warn if user overrides base templates.
- if self.custom_templates:
- for theme_dir in base_dir.joinpath(self.custom_templates, "python").iterdir():
- if theme_dir.joinpath("_base").is_dir():
- logger.warning(
- f"Overriding base template '{theme_dir.name}/_base/.html.jinja' is not supported, "
- f"override '{theme_dir.name}/.html.jinja' instead",
- )
-
- paths = config.paths or []
-
- # Expand paths with glob patterns.
- with chdir(str(base_dir)):
- resolved_globs = [glob.glob(path) for path in paths]
- paths = [path for glob_list in resolved_globs for path in glob_list]
-
- # By default, add the base directory to the search paths.
- if not paths:
- paths.append(str(base_dir))
-
- # Initialize search paths from `sys.path`, eliminating empty paths.
- search_paths = [path for path in sys.path if path]
-
- for path in reversed(paths):
- # If it's not absolute, make path relative to the config file path, then make it absolute.
- if not os.path.isabs(path):
- path = os.path.abspath(base_dir / path) # noqa: PLW2901
- # Remove pre-listed paths.
- if path in search_paths:
- search_paths.remove(path)
- # Give precedence to user-provided paths.
- search_paths.insert(0, path)
-
- self._paths = search_paths
- self._modules_collection: ModulesCollection = ModulesCollection()
- self._lines_collection: LinesCollection = LinesCollection()
-
- def get_inventory_urls(self) -> list[tuple[str, dict[str, Any]]]:
- """Return the URLs of the inventory files to download."""
- return [(inv.url, inv._config) for inv in self.config.inventories]
-
- @staticmethod
- def load_inventory(
- in_file: BinaryIO,
- url: str,
- base_url: str | None = None,
- domains: list[str] | None = None,
- **kwargs: Any, # noqa: ARG004
- ) -> Iterator[tuple[str, str]]:
- """Yield items and their URLs from an inventory file streamed from `in_file`.
-
- This implements mkdocstrings' `load_inventory` "protocol" (see [`mkdocstrings.plugin`][]).
-
- Arguments:
- in_file: The binary file-like object to read the inventory from.
- url: The URL that this file is being streamed from (used to guess `base_url`).
- base_url: The URL that this inventory's sub-paths are relative to.
- domains: A list of domain strings to filter the inventory by, when not passed, "py" will be used.
- **kwargs: Ignore additional arguments passed from the config.
-
- Yields:
- Tuples of (item identifier, item URL).
- """
- domains = domains or ["py"]
- if base_url is None:
- base_url = posixpath.dirname(url)
-
- for item in Inventory.parse_sphinx(in_file, domain_filter=domains).values():
- yield item.name, posixpath.join(base_url, item.uri)
-
- def get_options(self, local_options: Mapping[str, Any]) -> HandlerOptions:
- """Get combined default, global and local options.
-
- Arguments:
- local_options: The local options.
-
- Returns:
- The combined options.
- """
- # YORE: Bump 2: Remove block.
- local_extra, local_options = PythonOptions._extract_extra(local_options) # type: ignore[arg-type]
- if local_extra:
- _warn_extra_options(local_extra.keys()) # type: ignore[arg-type]
- unknown_extra = self._global_extra | local_extra
-
- extra = {**self.global_options.get("extra", {}), **local_options.get("extra", {})}
- options = {**self.global_options, **local_options, "extra": extra}
- try:
- # YORE: Bump 2: Replace `opts =` with `return` within line.
- opts = PythonOptions.from_data(**options)
- except Exception as error:
- raise PluginError(f"Invalid options: {error}") from error
-
- # YORE: Bump 2: Remove block.
- for key, value in unknown_extra.items():
- object.__setattr__(opts, key, value)
- return opts
-
- def collect(self, identifier: str, options: PythonOptions) -> CollectorItem: # noqa: D102
- module_name = identifier.split(".", 1)[0]
- unknown_module = module_name not in self._modules_collection
- reapply = True
- if options == {}:
- if unknown_module:
- raise CollectionError("Not loading additional modules during fallback")
- options = self.get_options({})
- reapply = False
-
- parser_name = options.docstring_style
- parser = parser_name and Parser(parser_name)
- parser_options = options.docstring_options and asdict(options.docstring_options)
-
- if unknown_module:
- extensions = self.normalize_extension_paths(options.extensions)
- loader = GriffeLoader(
- extensions=load_extensions(*extensions),
- search_paths=self._paths,
- docstring_parser=parser,
- docstring_options=parser_options, # type: ignore[arg-type]
- modules_collection=self._modules_collection,
- lines_collection=self._lines_collection,
- allow_inspection=options.allow_inspection,
- force_inspection=options.force_inspection,
- )
- try:
- for pre_loaded_module in options.preload_modules:
- if pre_loaded_module not in self._modules_collection:
- loader.load(
- pre_loaded_module,
- try_relative_path=False,
- find_stubs_package=options.find_stubs_package,
- )
- loader.load(
- module_name,
- try_relative_path=False,
- find_stubs_package=options.find_stubs_package,
- )
- except ImportError as error:
- raise CollectionError(str(error)) from error
- unresolved, iterations = loader.resolve_aliases(
- implicit=False,
- external=self.config.load_external_modules,
- )
- if unresolved:
- logger.debug(f"{len(unresolved)} aliases were still unresolved after {iterations} iterations")
- logger.debug(f"Unresolved aliases: {', '.join(sorted(unresolved))}")
-
- try:
- doc_object = self._modules_collection[identifier]
- except KeyError as error:
- raise CollectionError(f"{identifier} could not be found") from error
- except AliasResolutionError as error:
- raise CollectionError(str(error)) from error
-
- if not unknown_module and reapply:
- with suppress(AliasResolutionError):
- if doc_object.docstring is not None:
- doc_object.docstring.parser = parser
- doc_object.docstring.parser_options = parser_options or {}
-
- return doc_object
-
- def render(self, data: CollectorItem, options: PythonOptions) -> str: # noqa: D102 (ignore missing docstring)
- template_name = rendering.do_get_template(self.env, data)
- template = self.env.get_template(template_name)
-
- return template.render(
- **{
- "config": options,
- data.kind.value: data,
- # Heading level is a "state" variable, that will change at each step
- # of the rendering recursion. Therefore, it's easier to use it as a plain value
- # than as an item in a dictionary.
- "heading_level": options.heading_level,
- "root": True,
- "locale": self.config.locale,
- },
- )
-
- def update_env(self, config: Any) -> None: # noqa: ARG002
- """Update the Jinja environment with custom filters and tests.
-
- Parameters:
- config: The SSG configuration.
- """
- self.env.trim_blocks = True
- self.env.lstrip_blocks = True
- self.env.keep_trailing_newline = False
- self.env.filters["split_path"] = rendering.do_split_path
- self.env.filters["crossref"] = rendering.do_crossref
- self.env.filters["multi_crossref"] = rendering.do_multi_crossref
- self.env.filters["order_members"] = rendering.do_order_members
- self.env.filters["format_code"] = rendering.do_format_code
- self.env.filters["format_signature"] = rendering.do_format_signature
- self.env.filters["format_attribute"] = rendering.do_format_attribute
- self.env.filters["filter_objects"] = rendering.do_filter_objects
- self.env.filters["stash_crossref"] = rendering.do_stash_crossref
- self.env.filters["get_template"] = rendering.do_get_template
- self.env.filters["as_attributes_section"] = rendering.do_as_attributes_section
- self.env.filters["as_functions_section"] = rendering.do_as_functions_section
- self.env.filters["as_classes_section"] = rendering.do_as_classes_section
- self.env.filters["as_modules_section"] = rendering.do_as_modules_section
- self.env.filters["backlink_tree"] = rendering.do_backlink_tree
- self.env.globals["AutorefsHook"] = rendering.AutorefsHook
- self.env.tests["existing_template"] = lambda template_name: template_name in self.env.list_templates()
-
- def get_aliases(self, identifier: str) -> tuple[str, ...]: # noqa: D102 (ignore missing docstring)
- if "(" in identifier:
- identifier, parameter = identifier.split("(", 1)
- parameter.removesuffix(")")
- else:
- parameter = ""
- try:
- data = self._modules_collection[identifier]
- except (KeyError, AliasResolutionError):
- return ()
- aliases = [data.path]
- try:
- for alias in [data.canonical_path, *data.aliases]:
- if alias not in aliases:
- aliases.append(alias)
- except AliasResolutionError:
- pass
- if parameter:
- return tuple(f"{alias}({parameter})" for alias in aliases)
- return tuple(aliases)
-
- def normalize_extension_paths(self, extensions: Sequence) -> Sequence:
- """Resolve extension paths relative to config file."""
- 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:
- # 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:
- """Simply return an instance of `PythonHandler`.
-
- Arguments:
- handler_config: The handler configuration.
- tool_config: The tool (SSG) configuration.
-
- Returns:
- An instance of `PythonHandler`.
- """
- base_dir = Path(tool_config.config_file_path or "./mkdocs.yml").parent
- if "inventories" not in handler_config and "import" in handler_config:
- warn("The 'import' key is renamed 'inventories' for the Python handler", FutureWarning, stacklevel=1)
- handler_config["inventories"] = handler_config.pop("import", [])
- return PythonHandler(
- config=PythonConfig.from_data(**handler_config),
- base_dir=base_dir,
- **kwargs,
+ stacklevel=2,
)
+ return getattr(handler, name)
diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py
index 0a670b90..5cd4d200 100644
--- a/src/mkdocstrings_handlers/python/rendering.py
+++ b/src/mkdocstrings_handlers/python/rendering.py
@@ -1,775 +1,17 @@
-"""This module implements rendering utilities."""
+"""Deprecated. Import from `mkdocstrings_handlers.python` directly."""
-from __future__ import annotations
+# YORE: Bump 2: Remove file.
-import random
-import re
-import string
-import subprocess
-import sys
import warnings
-from collections import defaultdict
-from dataclasses import replace
-from functools import lru_cache
-from pathlib import Path
-from re import Match, Pattern
-from typing import TYPE_CHECKING, Any, Callable, ClassVar, Literal, TypeVar
+from typing import Any
-from griffe import (
- Alias,
- DocstringAttribute,
- DocstringClass,
- DocstringFunction,
- DocstringModule,
- DocstringSectionAttributes,
- DocstringSectionClasses,
- DocstringSectionFunctions,
- DocstringSectionModules,
- Object,
-)
-from jinja2 import TemplateNotFound, pass_context, pass_environment
-from markupsafe import Markup
-from mkdocs_autorefs import AutorefsHookInterface, Backlink, BacklinkCrumb
-from mkdocstrings import get_logger
+from mkdocstrings_handlers.python._internal import rendering
-if TYPE_CHECKING:
- from collections.abc import Iterable, Iterator, Sequence
- from griffe import Attribute, Class, Function, Module
- from jinja2 import Environment, Template
- from jinja2.runtime import Context
- from mkdocstrings import CollectorItem
-
-logger = get_logger(__name__)
-
-
-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 = Literal["alphabetical", "source"]
-order_map = {
- "alphabetical": _sort_key_alphabetical,
- "source": _sort_key_source,
-}
-
-
-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()
-
-
-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
- # TODO: Stop using `do_get_template` when `*.html` templates are removed.
- template = env.get_template(do_get_template(env, "signature"))
-
- if annotations is None:
- new_context = context.parent
- else:
- new_context = dict(context.parent)
- new_context["config"] = replace(new_context["config"], show_signature_annotations=annotations)
-
- signature = template.render(new_context, function=function, signature=True)
- signature = _format_signature(callable_path, signature, line_length)
- signature = str(
- env.filters["highlight"](
- Markup.escape(signature),
- language="python",
- inline=False,
- classes=["doc-signature"],
- linenums=False,
- ),
- )
-
- # Since we highlight the signature without `def`,
- # Pygments sees it as a function call and not a function definition.
- # The result is that the function name is not parsed as such,
- # but instead as a regular name: `n` CSS class instead of `nf`.
- # 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 := env.filters["stash_crossref"].stash:
- for key, value in stash.items():
- signature = re.sub(rf"\b{key}\b", value, signature)
- stash.clear()
-
- return signature
-
-
-@pass_context
-def do_format_attribute(
- context: Context,
- attribute_path: Markup,
- attribute: Attribute,
- line_length: int,
- *,
- crossrefs: bool = False, # noqa: ARG001
-) -> str:
- """Format an attribute.
-
- Parameters:
- context: Jinja context, passed automatically.
- attribute_path: The path of the callable we render the signature of.
- attribute: The attribute we render the signature of.
- line_length: The line length.
- crossrefs: Whether to cross-reference types in the signature.
-
- Returns:
- The same code, formatted.
- """
- env = context.environment
- # 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
-
- signature = str(attribute_path).strip()
- if annotations and attribute.annotation:
- annotation = template.render(
- context.parent,
- expression=attribute.annotation,
- signature=True,
- backlink_type="returned-by",
- )
- signature += f": {annotation}"
- if attribute.value:
- value = template.render(context.parent, expression=attribute.value, signature=True, backlink_type="used-by")
- signature += f" = {value}"
-
- signature = do_format_code(signature, line_length)
- signature = str(
- env.filters["highlight"](
- Markup.escape(signature),
- language="python",
- inline=False,
- classes=["doc-signature"],
- linenums=False,
- ),
- )
-
- if stash := env.filters["stash_crossref"].stash:
- for key, value in stash.items():
- signature = re.sub(rf"\b{key}\b", value, signature)
- stash.clear()
-
- return signature
-
-
-def do_order_members(
- members: Sequence[Object | Alias],
- order: Order,
- 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("{text}
"
- return Markup(text).format(**variables)
-
-
-_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 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_formatter() -> Callable[[str, int], str]:
- for formatter_function in [
- _get_black_formatter,
- _get_ruff_formatter,
- ]:
- if (formatter := formatter_function()) is not None:
- return formatter
-
- logger.info("Formatting signatures requires either Black or Ruff to be installed.")
- return lambda text, _: text
-
-
-def _get_ruff_formatter() -> Callable[[str, int], str] | None:
- try:
- from ruff.__main__ import find_ruff_bin
- except ImportError:
- return None
-
- try:
- ruff_bin = find_ruff_bin()
- except FileNotFoundError:
- ruff_bin = "ruff"
-
- def formatter(code: str, line_length: int) -> str:
- try:
- completed_process = subprocess.run( # noqa: S603
- [
- ruff_bin,
- "format",
- "--config",
- f"line-length={line_length}",
- "--stdin-filename",
- "file.py",
- "-",
- ],
- check=True,
- capture_output=True,
- text=True,
- input=code,
- )
- except subprocess.CalledProcessError:
- return code
- else:
- return completed_process.stdout
-
- return formatter
-
-
-def _get_black_formatter() -> Callable[[str, int], str] | None:
- try:
- from black import InvalidInput, Mode, format_str
- except ModuleNotFoundError:
- return None
-
- def formatter(code: str, line_length: int) -> str:
- mode = Mode(line_length=line_length)
- try:
- return format_str(code, mode=mode)
- except InvalidInput:
- return code
-
- return formatter
-
-
-@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"
- 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],
- *,
- check_public: bool = True,
-) -> DocstringSectionAttributes:
- """Build an attributes section from a list of attributes.
-
- Parameters:
- attributes: The attributes to build the section from.
- check_public: Whether to check if the attribute is public.
-
- Returns:
- An attributes docstring section.
- """
-
- def _parse_docstring_summary(attribute: Attribute) -> str:
- if attribute.docstring is None:
- return ""
- line = attribute.docstring.value.split("\n", 1)[0]
- if ":" in line and attribute.docstring.parser_options.get("returns_type_in_property_summary", False):
- _, line = line.split(":", 1)
- return line
-
- return DocstringSectionAttributes(
- [
- DocstringAttribute(
- name=attribute.name,
- description=_parse_docstring_summary(attribute),
- annotation=attribute.annotation,
- value=attribute.value, # type: ignore[arg-type]
- )
- for attribute in attributes
- if not check_public or attribute.is_public
- ],
- )
-
-
-@pass_context
-def do_as_functions_section(
- context: Context,
- functions: Sequence[Function],
- *,
- check_public: bool = True,
-) -> DocstringSectionFunctions:
- """Build a functions section from a list of functions.
-
- Parameters:
- functions: The functions to build the section from.
- check_public: Whether to check if the function is public.
-
- Returns:
- A functions docstring section.
- """
- keep_init_method = not context.parent["config"].merge_init_into_class
- return DocstringSectionFunctions(
- [
- DocstringFunction(
- name=function.name,
- description=function.docstring.value.split("\n", 1)[0] if function.docstring else "",
- )
- for function in functions
- if (not check_public or function.is_public) and (function.name != "__init__" or keep_init_method)
- ],
- )
-
-
-@pass_context
-def do_as_classes_section(
- context: Context, # noqa: ARG001
- classes: Sequence[Class],
- *,
- check_public: bool = True,
-) -> DocstringSectionClasses:
- """Build a classes section from a list of classes.
-
- Parameters:
- classes: The classes to build the section from.
- check_public: Whether to check if the class is public.
-
- Returns:
- A classes docstring section.
- """
- return DocstringSectionClasses(
- [
- DocstringClass(
- name=cls.name,
- description=cls.docstring.value.split("\n", 1)[0] if cls.docstring else "",
- )
- for cls in classes
- if not check_public or cls.is_public
- ],
- )
-
-
-@pass_context
-def do_as_modules_section(
- context: Context, # noqa: ARG001
- modules: Sequence[Module],
- *,
- check_public: bool = True,
-) -> DocstringSectionModules:
- """Build a modules section from a list of modules.
-
- Parameters:
- modules: The modules to build the section from.
- check_public: Whether to check if the module is public.
-
- Returns:
- A modules docstring section.
- """
- return DocstringSectionModules(
- [
- DocstringModule(
- name=module.name,
- description=module.docstring.value.split("\n", 1)[0] if module.docstring else "",
- )
- for module in modules
- if not check_public or module.is_public
- ],
- )
-
-
-class AutorefsHook(AutorefsHookInterface):
- """Autorefs hook.
-
- With this hook, we're able to add context to autorefs (cross-references),
- such as originating file path and line number, to improve error reporting.
- """
-
- def __init__(self, current_object: Object | Alias, config: dict[str, Any]) -> None:
- """Initialize the hook.
-
- Parameters:
- current_object: The object being rendered.
- config: The configuration dictionary.
- """
- self.current_object = current_object
- """The current object being rendered."""
- self.config = config
- """The configuration options."""
-
- def expand_identifier(self, identifier: str) -> str:
- """Expand an identifier.
-
- Parameters:
- identifier: The identifier to expand.
-
- Returns:
- The expanded identifier.
- """
- return identifier
-
- def get_context(self) -> AutorefsHookInterface.Context:
- """Get the context for the current object.
-
- Returns:
- The context.
- """
- role = {
- "attribute": "data" if self.current_object.parent and self.current_object.parent.is_module else "attr",
- "class": "class",
- "function": "meth" if self.current_object.parent and self.current_object.parent.is_class else "func",
- "module": "mod",
- }.get(self.current_object.kind.value.lower(), "obj")
- origin = self.current_object.path
- try:
- filepath = self.current_object.docstring.parent.filepath # type: ignore[union-attr]
- lineno = self.current_object.docstring.lineno or 0 # type: ignore[union-attr]
- except AttributeError:
- filepath = self.current_object.filepath
- lineno = 0
-
- return AutorefsHookInterface.Context(
- domain="py",
- role=role,
- origin=origin,
- filepath=str(filepath),
- lineno=lineno,
- )
-
-
-T = TypeVar("T")
-Tree = dict[T, "Tree"]
-CompactTree = dict[tuple[T, ...], "CompactTree"]
-_rtree = lambda: defaultdict(_rtree) # type: ignore[has-type,var-annotated] # noqa: E731
-
-
-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) -> CompactTree:
- 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]) -> CompactTree[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))
+ return getattr(rendering, name)
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
index 7effc590..37c8702c 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/attribute.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/attribute.html' is deprecated, extend '_base/attribute.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/attribute.html' is deprecated, extend '_base/attribute.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja
index 3217b4f6..e69b9b83 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html.jinja
@@ -64,6 +64,7 @@ Context:
This block renders the labels for the attribute.
-#}
{% with labels = attribute.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -110,6 +111,7 @@ Context:
This block renders the docstring for the attribute.
-#}
{% with docstring_sections = attribute.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% endblock docstring %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/children.html b/src/mkdocstrings_handlers/python/templates/material/_base/children.html
index 15fada5a..eada68e8 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/children.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/children.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/children.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/children.html' is deprecated, extend '_base/children.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/children.html' is deprecated, extend '_base/children.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html b/src/mkdocstrings_handlers/python/templates/material/_base/class.html
index ac3e421e..0fb87f5b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/class.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
index a07a36be..e0aab3ac 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
@@ -51,9 +51,10 @@ Context:
{{ config.heading if config.heading and root else class_name }}
{% elif config.merge_init_into_class and "__init__" in all_members %}
{% with function = all_members["__init__"] %}
- {%+ filter highlight(language="python", inline=True) %}
+ {%+ filter highlight(language="python", inline=True) -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{{ class_name }}{% include "signature"|get_template with context %}
- {% endfilter %}
+ {%- endfilter %}
{% endwith %}
{% else %}
{{ class_name }}
@@ -66,6 +67,7 @@ Context:
This block renders the labels for the class.
-#}
{% with labels = class.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -132,6 +134,7 @@ Context:
Bases: {% for expression in class.bases -%}
{%- with backlink_type = "subclassed-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{%- include "expression"|get_template with context -%}
{%- endwith -%}
{% if not loop.last %}, {% endif %}
@@ -146,6 +149,7 @@ Context:
This block renders the docstring for the class.
-#}
{% with docstring_sections = class.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% if config.merge_init_into_class %}
@@ -155,6 +159,7 @@ Context:
{% if "__init__" in check_members and check_members["__init__"].has_docstring %}
{% with function = check_members["__init__"] %}
{% with obj = function, docstring_sections = function.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% endwith %}
@@ -172,6 +177,7 @@ Context:
This block renders auto-summaries for classes, methods, and attributes.
-#}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "summary"|get_template with context %}
{% endblock summary %}
@@ -218,6 +224,7 @@ Context:
-#}
{% set root = False %}
{% set heading_level = heading_level + 1 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "children"|get_template with context %}
{% endblock children %}
{% endblock contents %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html
index 5ef9da3e..c487550b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring.html' is deprecated, extend '_base/docstring.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring.html' is deprecated, extend '_base/docstring.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja
index 6983b2e1..c560668e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring.html.jinja
@@ -24,30 +24,43 @@ Context:
{% if config.show_docstring_description and section.kind.value == "text" %}
{{ section.value|convert_markdown(heading_level, html_id, autoref_hook=autoref_hook) }}
{% elif config.show_docstring_attributes and section.kind.value == "attributes" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/attributes"|get_template with context %}
{% elif config.show_docstring_functions and section.kind.value == "functions" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/functions"|get_template with context %}
{% elif config.show_docstring_classes and section.kind.value == "classes" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/classes"|get_template with context %}
{% elif config.show_docstring_modules and section.kind.value == "modules" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/modules"|get_template with context %}
{% elif config.show_docstring_parameters and section.kind.value == "parameters" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/parameters"|get_template with context %}
{% elif config.show_docstring_other_parameters and section.kind.value == "other parameters" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/other_parameters"|get_template with context %}
{% elif config.show_docstring_raises and section.kind.value == "raises" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/raises"|get_template with context %}
{% elif config.show_docstring_warns and section.kind.value == "warns" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/warns"|get_template with context %}
{% elif config.show_docstring_yields and section.kind.value == "yields" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/yields"|get_template with context %}
{% elif config.show_docstring_receives and section.kind.value == "receives" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/receives"|get_template with context %}
{% elif config.show_docstring_returns and section.kind.value == "returns" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/returns"|get_template with context %}
{% elif config.show_docstring_examples and section.kind.value == "examples" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/examples"|get_template with context %}
{% elif config.show_docstring_description and section.kind.value == "admonition" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring/admonition"|get_template with context %}
{% endif %}
{% endfor %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html
index a8a75542..e94d6e61 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/admonition.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/admonition.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/admonition.html' is deprecated, extend '_base/docstring/admonition.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/admonition.html' is deprecated, extend '_base/docstring/admonition.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html
index cd4b05be..9f2abcd1 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja
index 13bd15b2..03104333 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering attributes section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -37,6 +38,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -61,6 +63,7 @@ Context:
{{ attribute.name }}
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
@@ -95,6 +98,7 @@ Context:
TYPE:
{% with expression = attribute.annotation %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
index 78b47e2d..9c04b145 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/classes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/classes.html' is deprecated, extend '_base/docstring/classes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/classes.html' is deprecated, extend '_base/docstring/classes.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja
index 73f39329..09a5b758 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering classes section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html
index 37674811..4f66600f 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/examples.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/examples.html' is deprecated, extend '_base/docstring/examples.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/examples.html' is deprecated, extend '_base/docstring/examples.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja
index 0caacc15..09293cfb 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering examples section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html
index a61c48fb..906658b4 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/functions.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/functions.html' is deprecated, extend '_base/docstring/functions.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/functions.html' is deprecated, extend '_base/docstring/functions.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja
index 28bb0cae..dd33984f 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering functions section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html
index d0b303b4..7b0dcc51 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/modules.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/modules.html' is deprecated, extend '_base/docstring/modules.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/modules.html' is deprecated, extend '_base/docstring/modules.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja
index d55f854e..106e6bf6 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering modules section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html
index eae60aa7..02261331 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja
index 8b64af1b..66940069 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/other_parameters.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering other parameters section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -37,6 +38,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -61,6 +63,7 @@ Context:
{{ parameter.name }}
{% if parameter.annotation %}
{% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
@@ -95,6 +98,7 @@ Context:
{{ lang.t("TYPE:") }}
{% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
index f5745464..f5292150 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja
index ae8fb7a3..1035ddf7 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering parameters section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -52,6 +53,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -64,6 +66,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% else %}
@@ -97,9 +100,11 @@ Context:
{% endif %}
{% if parameter.annotation %}
{% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
{%- if parameter.default %}, {{ lang.t("default:") }}
{% with expression = parameter.default, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %})
@@ -150,6 +155,7 @@ Context:
{{ lang.t("TYPE:") }}
{% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -158,6 +164,7 @@ Context:
{{ lang.t("DEFAULT:") }}
{% with expression = parameter.default, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
index 361b9732..38a21e89 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja
index 1e1d5006..cd034c0e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering raises section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -35,6 +36,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -58,6 +60,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
–
@@ -85,6 +88,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html
index e5a115c1..d9c404b6 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja
index a447b216..3ecc5b41 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering receives section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -38,6 +39,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -63,6 +65,7 @@ Context:
{% if receives.annotation %}
{% with expression = receives.annotation, backlink_type = "received-by" %}
{% if receives.name %} ({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if receives.name %}){% endif %}
{% endwith %}
@@ -94,6 +97,7 @@ Context:
{% elif receives.annotation %}
{% with expression = receives.annotation, backlink_type = "received-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -108,6 +112,7 @@ Context:
{{ lang.t("TYPE:") }}
{% with expression = receives.annotation, backlink_type = "received-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html
index 0e7807ac..b608af5f 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja
index 30540e66..bc8ee4ff 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering returns section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -38,6 +39,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -63,6 +65,7 @@ Context:
{% if returns.annotation %}
{% with expression = returns.annotation, backlink_type = "returned-by" %}
{% if returns.name %} ({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if returns.name %}){% endif %}
{% endwith %}
@@ -94,6 +97,7 @@ Context:
{% elif returns.annotation %}
{% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -108,6 +112,7 @@ Context:
{{ lang.t("TYPE:") }}
{% with expression = returns.annotation, backlink_type = "returned-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html
index b7b937a9..9eba72ab 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja
index 814e3020..d5a24262 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering warns section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -35,6 +36,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -58,6 +60,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
–
@@ -85,6 +88,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html
index ecd6f513..6ec31dd0 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja
index 01b8b9e5..154d0202 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug("Rendering yields section") }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -38,6 +39,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
@@ -63,6 +65,7 @@ Context:
{% if yields.annotation %}
{% with expression = yields.annotation, backlink_type = "yielded-by" %}
{% if yields.name %} ({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if yields.name %}){% endif %}
{% endwith %}
@@ -94,6 +97,7 @@ Context:
{% elif yields.annotation %}
{% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
@@ -108,6 +112,7 @@ Context:
{{ lang.t("TYPE:") }}:
{% with expression = yields.annotation, backlink_type = "yielded-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
index 556b3e2b..8c84928c 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/expression.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/expression.html' is deprecated, extend '_base/expression.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/expression.html' is deprecated, extend '_base/expression.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html b/src/mkdocstrings_handlers/python/templates/material/_base/function.html
index 07be5abb..4afd930b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/function.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/function.html' is deprecated, extend '_base/function.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/function.html' is deprecated, extend '_base/function.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja
index 4adcf3bd..50ed5840 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html.jinja
@@ -17,6 +17,7 @@ Context:
{{ log.debug("Rendering " + function.path) }}
{% endblock logs %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -56,9 +57,10 @@ Context:
{% if config.separate_signature %}
{{ config.heading if config.heading and root else function_name }}
{% else %}
- {%+ filter highlight(language="python", inline=True) %}
+ {%+ filter highlight(language="python", inline=True) -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{{ function_name }}{% include "signature"|get_template with context %}
- {% endfilter %}
+ {%- endfilter %}
{% endif %}
{% endblock heading %}
@@ -68,6 +70,7 @@ Context:
This block renders the labels for the function.
-#}
{% with labels = function.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -125,6 +128,7 @@ Context:
This block renders the docstring for the function.
-#}
{% with docstring_sections = function.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% endblock docstring %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
index 784150c4..cda79114 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/labels.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/labels.html' is deprecated, extend '_base/labels.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/labels.html' is deprecated, extend '_base/labels.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/language.html b/src/mkdocstrings_handlers/python/templates/material/_base/language.html
index c97d0c31..a5a86545 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/language.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/language.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja
index e3a614bb..5a4b773e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/language.html.jinja
@@ -7,12 +7,15 @@
-#}
{% endblock logs %}
+{# YORE: Bump 2: Replace `| get_template` with `~ ".html.jinja"` within line. #}
{% set lang_pth = "languages/" ~ locale | get_template %}
{% if lang_pth is existing_template %}
- {% import lang_pth as lang %}
- {% import "languages/en"|get_template as fallback %}
- {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %}
+ {% import lang_pth as lang %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% import "languages/en"|get_template as fallback %}
+ {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %}
{% else %}
- {% import "languages/en"|get_template as lang %}
- {% macro t(key) %}{{ lang.t(key) }}{% endmacro %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% import "languages/en"|get_template as lang %}
+ {% macro t(key) %}{{ lang.t(key) }}{% endmacro %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html
index eab87415..2f050a32 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
index 14319499..1f3095f4 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
index 0b281195..b58b0479 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/module.html b/src/mkdocstrings_handlers/python/templates/material/_base/module.html
index 918ab6d0..dcda15ea 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/module.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/module.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/module.html' is deprecated, extend '_base/module.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/module.html' is deprecated, extend '_base/module.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja
index d49dc76d..d2b5516d 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/module.html.jinja
@@ -60,6 +60,7 @@ Context:
This block renders the labels for the module.
-#}
{% with labels = module.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "labels"|get_template with context %}
{% endwith %}
{% endblock labels %}
@@ -93,6 +94,7 @@ Context:
This block renders the docstring for the module.
-#}
{% with docstring_sections = module.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "docstring"|get_template with context %}
{% endwith %}
{% endblock docstring %}
@@ -106,6 +108,7 @@ Context:
This block renders auto-summaries for classes, methods, and attributes.
-#}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "summary"|get_template with context %}
{% endblock summary %}
@@ -116,6 +119,7 @@ Context:
-#}
{% set root = False %}
{% set heading_level = heading_level + 1 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "children"|get_template with context %}
{% endblock children %}
{% endblock contents %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
index 623879db..6f05fed7 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/signature.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/signature.html' is deprecated, extend '_base/signature.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/signature.html' is deprecated, extend '_base/signature.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja
index e414fbe3..0e0678a1 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html.jinja
@@ -50,6 +50,7 @@ Context:
{%- if config.separate_signature -%}
{%- with expression = parameter.annotation -%}
{%- set ns.annotation -%}: {% with backlink_type = "used-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{%- include "expression"|get_template with context -%}
{%- endwith -%}{%- endset -%}
{%- endwith -%}
@@ -105,6 +106,7 @@ Context:
{{ ns.equal }}
{%- if config.signature_crossrefs and config.separate_signature -%}
{%- with expression = parameter.default, backlink_type = "used-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{%- include "expression"|get_template with context -%}
{%- endwith -%}
{%- else -%}
@@ -124,6 +126,7 @@ Context:
and not (config.merge_init_into_class and function.name == "__init__" )
%} -> {% if config.separate_signature and config.signature_crossrefs -%}
{%- with expression = function.annotation, backlink_type = "returned-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
{%- include "expression"|get_template with context -%}
{%- endwith -%}
{%- else -%}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html
index aa33dc9c..b970164d 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary.html' is deprecated, extend '_base/summary.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary.html' is deprecated, extend '_base/summary.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja
index 0a4ee071..78b0b9d7 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary.html.jinja
@@ -9,18 +9,22 @@
{% with members_list = config.members if root_members else None %}
{% if config.summary.modules %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "summary/modules"|get_template with context %}
{% endif %}
{% if config.summary.classes %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "summary/classes"|get_template with context %}
{% endif %}
{% if config.summary.functions %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "summary/functions"|get_template with context %}
{% endif %}
{% if config.summary.attributes %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "summary/attributes"|get_template with context %}
{% endif %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html
index f2643791..8e575a44 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/attributes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/attributes.html' is deprecated, extend '_base/summary/attributes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/attributes.html' is deprecated, extend '_base/summary/attributes.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja
index cabda067..52f9a43a 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/attributes.html.jinja
@@ -18,6 +18,7 @@
|order_members(config.members_order, members_list)
|as_attributes_section(check_public=not members_list)
%}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% if section %}{% include "docstring/attributes"|get_template with context %}{% endif %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html
index 5c6275b4..a74eff99 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/classes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/classes.html' is deprecated, extend '_base/summary/classes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/classes.html' is deprecated, extend '_base/summary/classes.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja
index 7527781b..628d4133 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/classes.html.jinja
@@ -18,6 +18,7 @@
|order_members(config.members_order, members_list)
|as_classes_section(check_public=not members_list)
%}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% if section %}{% include "docstring/classes"|get_template with context %}{% endif %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html
index 31887e0a..ff95f246 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/functions.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/functions.html' is deprecated, extend '_base/summary/functions.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/functions.html' is deprecated, extend '_base/summary/functions.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja
index cdf75973..a82f2f87 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/functions.html.jinja
@@ -18,6 +18,7 @@
|order_members(config.members_order, members_list)
|as_functions_section(check_public=not members_list)
%}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% if section %}{% include "docstring/functions"|get_template with context %}{% endif %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html
index 31dcb5f0..51e964c1 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/modules.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/summary/modules.html' is deprecated, extend '_base/summary/modules.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/summary/modules.html' is deprecated, extend '_base/summary/modules.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja
index b9654593..109b34a9 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/summary/modules.html.jinja
@@ -18,6 +18,7 @@
|order_members("alphabetical", members_list)
|as_modules_section(check_public=not members_list)
%}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% if section %}{% include "docstring/modules"|get_template with context %}{% endif %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/attribute.html b/src/mkdocstrings_handlers/python/templates/material/attribute.html
index a3c27503..aaf56880 100644
--- a/src/mkdocstrings_handlers/python/templates/material/attribute.html
+++ b/src/mkdocstrings_handlers/python/templates/material/attribute.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/attribute.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/children.html b/src/mkdocstrings_handlers/python/templates/material/children.html
index 2c2a73ab..312346ec 100644
--- a/src/mkdocstrings_handlers/python/templates/material/children.html
+++ b/src/mkdocstrings_handlers/python/templates/material/children.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/children.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/class.html b/src/mkdocstrings_handlers/python/templates/material/class.html
index 5e7329df..7ee0f690 100644
--- a/src/mkdocstrings_handlers/python/templates/material/class.html
+++ b/src/mkdocstrings_handlers/python/templates/material/class.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/class.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring.html b/src/mkdocstrings_handlers/python/templates/material/docstring.html
index a7ccd66c..cb91e77a 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html b/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html
index e9da5e9a..943c883f 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/admonition.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/admonition.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html
index 4ac364b0..6a67cafb 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/attributes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html b/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html
index 035b3102..fce82b60 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/classes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/classes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html b/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html
index 34e9c4ba..334796a6 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/examples.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/examples.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html b/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html
index f3eaed78..9f07107e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/functions.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/functions.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html b/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html
index 8ea02a33..23a9965e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/modules.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/modules.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html
index 7c50379b..a7024661 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/other_parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html
index 70c557fb..fb49b54d 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html
index f8c3cf03..1365fc5e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/raises.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html
index 004ff00e..9521ee68 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/receives.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html
index 979ce9ef..93413ed8 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/returns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
index bb06cc85..95523fde 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/warns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html
index 717ef5d4..58bccc7b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/material/docstring/yields.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/expression.html b/src/mkdocstrings_handlers/python/templates/material/expression.html
index 60c64d79..5edd5520 100644
--- a/src/mkdocstrings_handlers/python/templates/material/expression.html
+++ b/src/mkdocstrings_handlers/python/templates/material/expression.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/expression.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/function.html b/src/mkdocstrings_handlers/python/templates/material/function.html
index 54bba061..c90df9b5 100644
--- a/src/mkdocstrings_handlers/python/templates/material/function.html
+++ b/src/mkdocstrings_handlers/python/templates/material/function.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/function.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/labels.html b/src/mkdocstrings_handlers/python/templates/material/labels.html
index 51cb29d6..124caf19 100644
--- a/src/mkdocstrings_handlers/python/templates/material/labels.html
+++ b/src/mkdocstrings_handlers/python/templates/material/labels.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/labels.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/language.html b/src/mkdocstrings_handlers/python/templates/material/language.html
index b905cff4..6da4f8df 100644
--- a/src/mkdocstrings_handlers/python/templates/material/language.html
+++ b/src/mkdocstrings_handlers/python/templates/material/language.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/en.html b/src/mkdocstrings_handlers/python/templates/material/languages/en.html
index 931967c1..bcc4121e 100644
--- a/src/mkdocstrings_handlers/python/templates/material/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/material/languages/en.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/ja.html b/src/mkdocstrings_handlers/python/templates/material/languages/ja.html
index 17070edf..87827f60 100644
--- a/src/mkdocstrings_handlers/python/templates/material/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/material/languages/ja.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/zh.html b/src/mkdocstrings_handlers/python/templates/material/languages/zh.html
index e4ea3116..37c36ff0 100644
--- a/src/mkdocstrings_handlers/python/templates/material/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/material/languages/zh.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/module.html b/src/mkdocstrings_handlers/python/templates/material/module.html
index 9d8efea5..ea043657 100644
--- a/src/mkdocstrings_handlers/python/templates/material/module.html
+++ b/src/mkdocstrings_handlers/python/templates/material/module.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/module.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/signature.html b/src/mkdocstrings_handlers/python/templates/material/signature.html
index 33b266c8..e6573985 100644
--- a/src/mkdocstrings_handlers/python/templates/material/signature.html
+++ b/src/mkdocstrings_handlers/python/templates/material/signature.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/signature.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary.html b/src/mkdocstrings_handlers/python/templates/material/summary.html
index 59eddea0..604624e7 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html b/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html
index c69755c6..a0fdbb04 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/attributes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/attributes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/classes.html b/src/mkdocstrings_handlers/python/templates/material/summary/classes.html
index 825eb1bb..c01b2094 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/classes.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/classes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/classes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/functions.html b/src/mkdocstrings_handlers/python/templates/material/summary/functions.html
index fc609bda..90ca63e0 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/functions.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/functions.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/functions.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/material/summary/modules.html b/src/mkdocstrings_handlers/python/templates/material/summary/modules.html
index 46db0023..1f69b3dc 100644
--- a/src/mkdocstrings_handlers/python/templates/material/summary/modules.html
+++ b/src/mkdocstrings_handlers/python/templates/material/summary/modules.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/summary/modules.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
index cd4b05be..9f2abcd1 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/attributes.html' is deprecated, extend '_base/docstring/attributes.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja
index ad798971..e8804310 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/attributes.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -33,6 +34,7 @@ Context:
{{ attribute.name }}
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
index eae60aa7..02261331 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/other_parameters.html' is deprecated, extend '_base/docstring/other_parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja
index 657b21b4..6605e48d 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/other_parameters.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -33,6 +34,7 @@ Context:
{{ parameter.name }}
{% if parameter.annotation %}
{% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
)
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
index f5745464..f5292150 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/parameters.html' is deprecated, extend '_base/docstring/parameters.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja
index 6017a8cb..de01dcbe 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/parameters.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -33,9 +34,11 @@ Context:
{{ parameter.name }}
{% if parameter.annotation %}
{% with expression = parameter.annotation, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
({% include "expression"|get_template with context %}
{%- if parameter.default %}, {{ lang.t("default:") }}
{% with expression = parameter.default, backlink_type = "used-by" %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %})
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
index 361b9732..38a21e89 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/raises.html' is deprecated, extend '_base/docstring/raises.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja
index 11f695e8..cf7d0b01 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/raises.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,6 +33,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
index e5a115c1..d9c404b6 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/receives.html' is deprecated, extend '_base/docstring/receives.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja
index aec9a858..84d6c1bc 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/receives.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -34,6 +35,7 @@ Context:
{% if receives.annotation %}
{% with expression = receives.annotation, backlink_type = "received-by" %}
{% if receives.name %}({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if receives.name %}){% endif %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
index 0e7807ac..b608af5f 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/returns.html' is deprecated, extend '_base/docstring/returns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja
index 3f8bbba4..c1171c7e 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/returns.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -34,6 +35,7 @@ Context:
{% if returns.annotation %}
{% with expression = returns.annotation, backlink_type = "returned-by" %}
{% if returns.name %}({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if returns.name %}){% endif %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
index b7b937a9..9eba72ab 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/warns.html' is deprecated, extend '_base/docstring/warns.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja
index 1d465ec9..5570ca37 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/warns.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -32,6 +33,7 @@ Context:
{% include "expression"|get_template with context %}
{% endwith %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
index ecd6f513..6ec31dd0 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/docstring/yields.html' is deprecated, extend '_base/docstring/yields.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja
index 70c782b3..712776fe 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/docstring/yields.html.jinja
@@ -15,6 +15,7 @@ Context:
{{ log.debug() }}
{% endblock %}
+{# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "language"|get_template as lang with context %}
{#- Language module providing the `t` translation method. -#}
@@ -34,6 +35,7 @@ Context:
{% if yields.annotation %}
{% with expression = yields.annotation, backlink_type = "yielded-by" %}
{% if yields.name %}({% endif %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% include "expression"|get_template with context %}
{% if yields.name %}){% endif %}
{% endwith %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
index c97d0c31..a5a86545 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/language.html' is deprecated, extend '_base/language.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja
index 21163f47..5a4b773e 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/language.html.jinja
@@ -7,12 +7,15 @@
-#}
{% endblock logs %}
+{# YORE: Bump 2: Replace `| get_template` with `~ ".html.jinja"` within line. #}
{% set lang_pth = "languages/" ~ locale | get_template %}
{% if lang_pth is existing_template %}
{% import lang_pth as lang %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "languages/en"|get_template as fallback %}
{% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %}
{% else %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
{% import "languages/en"|get_template as lang %}
{% macro t(key) %}{{ lang.t(key) }}{% endmacro %}
{% endif %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html
index eab87415..2f050a32 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/en.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/en.html' is deprecated, extend '_base/languages/en.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html
index 14319499..1f3095f4 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/ja.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/ja.html' is deprecated, extend '_base/languages/ja.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html
index 0b281195..b58b0479 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/_base/languages/zh.html
@@ -1,11 +1,10 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
{% block logs scoped %}
{{ super() }}
- {# TODO: Switch to a warning after some time. #}
- {{ log.info(
- "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. " ~
- "After some time, this message will be logged as a warning, causing strict builds to fail.",
+ {{ log.warning(
+ "DeprecationWarning: Extending '_base/languages/zh.html' is deprecated, extend '_base/languages/zh.html.jinja' instead. ",
once=True,
) }}
{% endblock logs %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
index 4ac364b0..6a67cafb 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/attributes.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html
index 7c50379b..a7024661 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/other_parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html
index 70c557fb..fb49b54d 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/parameters.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html
index f8c3cf03..1365fc5e 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/raises.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html
index 004ff00e..9521ee68 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/receives.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html
index 979ce9ef..93413ed8 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/returns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html
index bb06cc85..95523fde 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/warns.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html
index 717ef5d4..58bccc7b 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/docstring/yields.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/language.html b/src/mkdocstrings_handlers/python/templates/readthedocs/language.html
index b905cff4..6da4f8df 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/language.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/language.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/language.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html
index 931967c1..bcc4121e 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/en.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html
index 17070edf..87827f60 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/ja.html.jinja" %}
diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html
index e4ea3116..37c36ff0 100644
--- a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html
+++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html
@@ -1 +1,2 @@
+{# YORE: Bump 2: Remove file. #}
{% extends "_base/languages/zh.html.jinja" %}
diff --git a/tests/conftest.py b/tests/conftest.py
index 5b2dd33f..926c4b83 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -17,7 +17,7 @@
from mkdocs.config.defaults import MkDocsConfig
from mkdocstrings import MkdocstringsPlugin
- from mkdocstrings_handlers.python.handler import PythonHandler
+ from mkdocstrings_handlers.python import PythonHandler
# --------------------------------------------
diff --git a/tests/helpers.py b/tests/helpers.py
index b0dc6ad7..d7fb7e1d 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -16,7 +16,7 @@
import pytest
from mkdocstrings import MkdocstringsPlugin
- from mkdocstrings_handlers.python.handler import PythonHandler
+ from mkdocstrings_handlers.python import PythonHandler
@contextmanager
diff --git a/tests/test_api.py b/tests/test_api.py
new file mode 100644
index 00000000..490bd82d
--- /dev/null
+++ b/tests/test_api.py
@@ -0,0 +1,190 @@
+"""Tests for our own API exposition."""
+
+from __future__ import annotations
+
+from collections import defaultdict
+from pathlib import Path
+from typing import TYPE_CHECKING
+
+import griffe
+import pytest
+from mkdocstrings import Inventory
+
+from mkdocstrings_handlers import python
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+
+
+@pytest.fixture(name="loader", scope="module")
+def _fixture_loader() -> griffe.GriffeLoader:
+ loader = griffe.GriffeLoader()
+ loader.load("mkdocstrings")
+ loader.load("mkdocstrings_handlers.python")
+ loader.resolve_aliases()
+ return loader
+
+
+@pytest.fixture(name="internal_api", scope="module")
+def _fixture_internal_api(loader: griffe.GriffeLoader) -> griffe.Module:
+ return loader.modules_collection["mkdocstrings_handlers.python._internal"]
+
+
+@pytest.fixture(name="public_api", scope="module")
+def _fixture_public_api(loader: griffe.GriffeLoader) -> griffe.Module:
+ return loader.modules_collection["mkdocstrings_handlers.python"]
+
+
+def _yield_public_objects(
+ obj: griffe.Module | griffe.Class,
+ *,
+ modules: bool = False,
+ modulelevel: bool = True,
+ inherited: bool = False,
+ special: bool = False,
+) -> Iterator[griffe.Object | griffe.Alias]:
+ for member in obj.all_members.values() if inherited else obj.members.values():
+ try:
+ if member.is_module:
+ if member.is_alias or not member.is_public:
+ continue
+ if modules:
+ yield member
+ yield from _yield_public_objects(
+ member, # type: ignore[arg-type]
+ modules=modules,
+ modulelevel=modulelevel,
+ inherited=inherited,
+ special=special,
+ )
+ elif member.is_public and (special or not member.is_special):
+ yield member
+ else:
+ continue
+ if member.is_class and not modulelevel:
+ yield from _yield_public_objects(
+ member, # type: ignore[arg-type]
+ modules=modules,
+ modulelevel=False,
+ inherited=inherited,
+ special=special,
+ )
+ except (griffe.AliasResolutionError, griffe.CyclicAliasError):
+ continue
+
+
+@pytest.fixture(name="modulelevel_internal_objects", scope="module")
+def _fixture_modulelevel_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]:
+ return list(_yield_public_objects(internal_api, modulelevel=True))
+
+
+@pytest.fixture(name="internal_objects", scope="module")
+def _fixture_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]:
+ return list(_yield_public_objects(internal_api, modulelevel=False, special=True))
+
+
+@pytest.fixture(name="public_objects", scope="module")
+def _fixture_public_objects(public_api: griffe.Module) -> list[griffe.Object | griffe.Alias]:
+ return list(_yield_public_objects(public_api, modulelevel=False, inherited=True, special=True))
+
+
+@pytest.fixture(name="inventory", scope="module")
+def _fixture_inventory() -> Inventory:
+ inventory_file = Path(__file__).parent.parent / "site" / "objects.inv"
+ if not inventory_file.exists():
+ raise pytest.skip("The objects inventory is not available.")
+ with inventory_file.open("rb") as file:
+ return Inventory.parse_sphinx(file)
+
+
+def test_exposed_objects(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None:
+ """All public objects in the internal API are exposed under `mkdocstrings_handlers.python`."""
+ not_exposed = [
+ obj.path
+ for obj in modulelevel_internal_objects
+ if obj.name not in python.__all__ or not hasattr(python, obj.name)
+ ]
+ assert not not_exposed, "Objects not exposed:\n" + "\n".join(sorted(not_exposed))
+
+
+def test_unique_names(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None:
+ """All internal objects have unique names."""
+ names_to_paths = defaultdict(list)
+ for obj in modulelevel_internal_objects:
+ names_to_paths[obj.name].append(obj.path)
+ non_unique = [paths for paths in names_to_paths.values() if len(paths) > 1]
+ assert not non_unique, "Non-unique names:\n" + "\n".join(str(paths) for paths in non_unique)
+
+
+def test_single_locations(public_api: griffe.Module) -> None:
+ """All objects have a single public location."""
+
+ def _public_path(obj: griffe.Object | griffe.Alias) -> bool:
+ return obj.is_public and (obj.parent is None or _public_path(obj.parent))
+
+ multiple_locations = {}
+ for obj_name in python.__all__:
+ obj = public_api[obj_name]
+ if obj.aliases and (
+ public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)]
+ ):
+ multiple_locations[obj.path] = public_aliases
+ assert not multiple_locations, "Multiple public locations:\n" + "\n".join(
+ f"{path}: {aliases}" for path, aliases in multiple_locations.items()
+ )
+
+
+def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe.Object | griffe.Alias]) -> None:
+ """All public objects are added to the inventory."""
+ ignore_names = {"__getattr__", "__init__", "__repr__", "__str__", "__post_init__"}
+ not_in_inventory = [
+ obj.path for obj in public_objects if obj.name not in ignore_names and obj.path not in inventory
+ ]
+ msg = "Objects not in the inventory (try running `make run mkdocs build`):\n{paths}"
+ assert not not_in_inventory, msg.format(paths="\n".join(sorted(not_in_inventory)))
+
+
+def _module_or_child(parent: str, name: str) -> bool:
+ parents = [parent[: i + 1] for i, char in enumerate(parent) if char == "."]
+ parents.append(parent)
+ return name in parents or name.startswith(parent + ".")
+
+
+def test_inventory_matches_api(
+ inventory: Inventory,
+ public_objects: list[griffe.Object | griffe.Alias],
+ loader: griffe.GriffeLoader,
+) -> None:
+ """The inventory doesn't contain any additional Python object."""
+ not_in_api = []
+ public_api_paths = {obj.path for obj in public_objects}
+ public_api_paths.add("mkdocstrings_handlers")
+ public_api_paths.add("mkdocstrings_handlers.python")
+ # YORE: Bump 2: Remove block.
+ public_api_paths.add("mkdocstrings_handlers.python.config")
+ public_api_paths.add("mkdocstrings_handlers.python.handler")
+ public_api_paths.add("mkdocstrings_handlers.python.rendering")
+
+ for item in inventory.values():
+ if item.domain == "py" and "(" not in item.name and _module_or_child("mkdocstrings_handlers.python", item.name):
+ obj = loader.modules_collection[item.name]
+ if obj.path not in public_api_paths and not any(path in public_api_paths for path in obj.aliases):
+ not_in_api.append(item.name)
+ msg = "Inventory objects not in public API (try running `make run mkdocs build`):\n{paths}"
+ assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api)))
+
+
+def test_no_module_docstrings_in_internal_api(internal_api: griffe.Module) -> None:
+ """No module docstrings should be written in our internal API.
+
+ The reasoning is that docstrings are addressed to users of the public API,
+ but internal modules are not exposed to users, so they should not have docstrings.
+ """
+
+ def _modules(obj: griffe.Module) -> Iterator[griffe.Module]:
+ for member in obj.modules.values():
+ yield member
+ yield from _modules(member)
+
+ for obj in _modules(internal_api):
+ assert not obj.docstring
diff --git a/tests/test_end_to_end.py b/tests/test_end_to_end.py
index 161dcdf2..6b6b6401 100644
--- a/tests/test_end_to_end.py
+++ b/tests/test_end_to_end.py
@@ -16,7 +16,7 @@
if TYPE_CHECKING:
from collections.abc import Iterator
- from mkdocstrings_handlers.python.handler import PythonHandler
+ from mkdocstrings_handlers.python import PythonHandler
def _normalize_html(html: str) -> str:
@@ -66,6 +66,9 @@ def _signature_package() -> Iterator[TmpPackage]:
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`.'''
diff --git a/tests/test_handler.py b/tests/test_handler.py
index 1a907469..a4e1d23a 100644
--- a/tests/test_handler.py
+++ b/tests/test_handler.py
@@ -11,9 +11,9 @@
import pytest
from griffe import Docstring, DocstringSectionExamples, DocstringSectionKind, Module, temporary_visited_module
+from mkdocstrings import CollectionError
-from mkdocstrings_handlers.python.config import PythonConfig, PythonOptions
-from mkdocstrings_handlers.python.handler import CollectionError, PythonHandler
+from mkdocstrings_handlers.python import PythonConfig, PythonHandler, PythonOptions
if TYPE_CHECKING:
from mkdocstrings import MkdocstringsPlugin
@@ -160,9 +160,6 @@ 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
diff --git a/tests/test_rendering.py b/tests/test_rendering.py
index 98da5d9c..31829e85 100644
--- a/tests/test_rendering.py
+++ b/tests/test_rendering.py
@@ -9,7 +9,7 @@
import pytest
from griffe import ModulesCollection, temporary_visited_module
-from mkdocstrings_handlers.python import rendering
+from mkdocstrings_handlers.python._internal import rendering
if TYPE_CHECKING:
from markupsafe import Markup
diff --git a/tests/test_themes.py b/tests/test_themes.py
index ca7125d3..bf7401d6 100644
--- a/tests/test_themes.py
+++ b/tests/test_themes.py
@@ -7,7 +7,7 @@
import pytest
if TYPE_CHECKING:
- from mkdocstrings_handlers.python.handler import PythonHandler
+ from mkdocstrings_handlers.python import PythonHandler
@pytest.mark.parametrize(