From ba98661b50e2cde19d8696d6c8ceecdbb49ce83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 14 Mar 2025 14:39:54 +0100 Subject: [PATCH 1/8] deps: Remove unused typing-extensions dependency --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c3087f61..1e104425 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,6 @@ dependencies = [ "mkdocs-autorefs>=1.4", "pymdown-extensions>=6.3", "importlib-metadata>=4.6; python_version < '3.10'", - "typing-extensions>=4.1; python_version < '3.10'", ] [project.optional-dependencies] From 94645796ecbb48a4a4c654d219df2e588d59f7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 14 Mar 2025 14:40:23 +0100 Subject: [PATCH 2/8] tests: Remove old skip conditions --- tests/test_extension.py | 1 - tests/test_inventory.py | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/test_extension.py b/tests/test_extension.py index b7c1c742..aed0a1f1 100644 --- a/tests/test_extension.py +++ b/tests/test_extension.py @@ -60,7 +60,6 @@ def test_reference_inside_autodoc(ext_markdown: Markdown) -> None: assert re.search(r"Link to <.*something\.Else.*>something\.Else<.*>\.", output) -@pytest.mark.skipif(sys.version_info < (3, 8), reason="typing.Literal requires Python 3.8") def test_quote_inside_annotation(ext_markdown: Markdown) -> None: """Assert that inline highlighting doesn't double-escape HTML.""" output = ext_markdown.convert("::: tests.fixtures.string_annotation.Foo") diff --git a/tests/test_inventory.py b/tests/test_inventory.py index eb008661..9589d528 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -36,7 +36,6 @@ def test_sphinx_load_inventory_file(our_inv: Inventory) -> None: assert item.name in sphinx_inv[f"{item.domain}:{item.role}"] -@pytest.mark.skipif(sys.version_info < (3, 7), reason="using plugins that require Python 3.7") def test_sphinx_load_mkdocstrings_inventory_file() -> None: """Perform the 'live' inventory load test on mkdocstrings own inventory.""" mkdocs_config = load_config() From 983b3cd8c4e1de249ef3ebec2678e295e6c6b966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 14 Mar 2025 14:40:45 +0100 Subject: [PATCH 3/8] chore: Mark legacy stuff with Yore comments --- pyproject.toml | 2 ++ src/mkdocstrings/_internal/handlers/base.py | 3 ++- src/mkdocstrings/_internal/loggers.py | 3 ++- src/mkdocstrings/extension.py | 2 ++ src/mkdocstrings/handlers/__init__.py | 2 ++ src/mkdocstrings/handlers/base.py | 2 ++ src/mkdocstrings/handlers/rendering.py | 2 ++ src/mkdocstrings/inventory.py | 2 ++ src/mkdocstrings/loggers.py | 2 ++ src/mkdocstrings/plugin.py | 2 ++ 10 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1e104425..29aff0d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,12 +31,14 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ + # YORE: Bump 1: Replace `2.11.1` with `3.1` within line. "Jinja2>=2.11.1", "Markdown>=3.6", "MarkupSafe>=1.1", "mkdocs>=1.6", "mkdocs-autorefs>=1.4", "pymdown-extensions>=6.3", + # YORE: EOL 3.9: Remove line. "importlib-metadata>=4.6; python_version < '3.10'", ] diff --git a/src/mkdocstrings/_internal/handlers/base.py b/src/mkdocstrings/_internal/handlers/base.py index 7784f007..f19d9094 100644 --- a/src/mkdocstrings/_internal/handlers/base.py +++ b/src/mkdocstrings/_internal/handlers/base.py @@ -33,7 +33,8 @@ from mkdocstrings._internal.inventory import Inventory from mkdocstrings._internal.loggers import get_logger, get_template_logger -# TODO: remove once support for Python 3.9 is dropped + +# YORE: EOL 3.9: Replace block with line 4. if sys.version_info < (3, 10): from importlib_metadata import entry_points else: diff --git a/src/mkdocstrings/_internal/loggers.py b/src/mkdocstrings/_internal/loggers.py index d56d09c3..6c6304c3 100644 --- a/src/mkdocstrings/_internal/loggers.py +++ b/src/mkdocstrings/_internal/loggers.py @@ -7,9 +7,10 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Callable +# YORE: Bump 1: Replace block with line 2. try: from jinja2 import pass_context -except ImportError: # TODO: remove once Jinja2 < 3.1 is dropped +except ImportError: from jinja2 import contextfunction as pass_context # type: ignore[attr-defined,no-redef] if TYPE_CHECKING: diff --git a/src/mkdocstrings/extension.py b/src/mkdocstrings/extension.py index 15a84cc8..c7943652 100644 --- a/src/mkdocstrings/extension.py +++ b/src/mkdocstrings/extension.py @@ -1,5 +1,7 @@ """Deprecated. Import from `mkdocstrings` directly.""" +# YORE: Bump 1: Remove file. + import warnings from typing import Any diff --git a/src/mkdocstrings/handlers/__init__.py b/src/mkdocstrings/handlers/__init__.py index af032e98..b684324a 100644 --- a/src/mkdocstrings/handlers/__init__.py +++ b/src/mkdocstrings/handlers/__init__.py @@ -1 +1,3 @@ """Deprecated. Import from `mkdocstrings` directly.""" + +# YORE: Bump 1: Remove file. diff --git a/src/mkdocstrings/handlers/base.py b/src/mkdocstrings/handlers/base.py index 82ee3edb..c55a50ba 100644 --- a/src/mkdocstrings/handlers/base.py +++ b/src/mkdocstrings/handlers/base.py @@ -1,5 +1,7 @@ """Deprecated. Import from `mkdocstrings` directly.""" +# YORE: Bump 1: Remove file. + import warnings from typing import Any diff --git a/src/mkdocstrings/handlers/rendering.py b/src/mkdocstrings/handlers/rendering.py index 940f3a9c..f3f04eea 100644 --- a/src/mkdocstrings/handlers/rendering.py +++ b/src/mkdocstrings/handlers/rendering.py @@ -1,5 +1,7 @@ """Deprecated. Import from `mkdocstrings` directly.""" +# YORE: Bump 1: Remove file. + import warnings from typing import Any diff --git a/src/mkdocstrings/inventory.py b/src/mkdocstrings/inventory.py index b5c8adea..7192acff 100644 --- a/src/mkdocstrings/inventory.py +++ b/src/mkdocstrings/inventory.py @@ -1,5 +1,7 @@ """Deprecated. Import from `mkdocstrings` directly.""" +# YORE: Bump 1: Remove file. + import warnings from typing import Any diff --git a/src/mkdocstrings/loggers.py b/src/mkdocstrings/loggers.py index ce805362..25545ca5 100644 --- a/src/mkdocstrings/loggers.py +++ b/src/mkdocstrings/loggers.py @@ -1,5 +1,7 @@ """Deprecated. Import from `mkdocstrings` directly.""" +# YORE: Bump 1: Remove file. + import warnings from typing import Any diff --git a/src/mkdocstrings/plugin.py b/src/mkdocstrings/plugin.py index b4edf945..dbb6abf9 100644 --- a/src/mkdocstrings/plugin.py +++ b/src/mkdocstrings/plugin.py @@ -1,5 +1,7 @@ """Deprecated. Import from `mkdocstrings` directly.""" +# YORE: Bump 1: Remove file. + import warnings from typing import Any From ccf65c1166103cf705f30b27b8c913863a372da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 28 Mar 2025 16:06:34 +0100 Subject: [PATCH 4/8] docs: Remove 'sponsors only' labels --- docs/usage/handlers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage/handlers.md b/docs/usage/handlers.md index b9a01f68..0d375a95 100644 --- a/docs/usage/handlers.md +++ b/docs/usage/handlers.md @@ -4,12 +4,12 @@ A handler is what makes it possible to collect and render documentation for a pa ## Available handlers -- [C](https://mkdocstrings.github.io/c/){ .external } [:octicons-heart-fill-24:{ .heart .pulse title="Sponsors only" }](../insiders/index.md) +- [C](https://mkdocstrings.github.io/c/){ .external } - [Crystal](https://mkdocstrings.github.io/crystal/){ .external } - [Python](https://mkdocstrings.github.io/python/){ .external } - [Python (Legacy)](https://mkdocstrings.github.io/python-legacy/){ .external } - [Shell](https://mkdocstrings.github.io/shell/){ .external } -- [TypeScript](https://mkdocstrings.github.io/typescript/){ .external } [:octicons-heart-fill-24:{ .heart .pulse title="Sponsors only" }](../insiders/index.md) +- [TypeScript](https://mkdocstrings.github.io/typescript/){ .external } - [VBA](https://pypi.org/project/mkdocstrings-vba/){ .external } ## About the Python handlers From 0bc4799b0e38bf7378d0e57428d52fdd1e7ac1ab Mon Sep 17 00:00:00 2001 From: Josh Mitchell Date: Thu, 27 Mar 2025 17:27:17 +1100 Subject: [PATCH 5/8] style: Format and configure for Ruff >= 0.10.0 Ruff 0.10.0 introduces the S704 lint, which triggers when a non- literal string is passed to `markupsafe.Markup()`. This triggered 5 times in the codebase. Only one of these errors was trivially fixable, and the fix caused tests to fail because the "fix" introduced escapes to already correct markup. This commit therefore configures Ruff to ignore this lint and does not fix any code that triggers it. Other changes are due to other formatting and linting changes from recent releases of Ruff. Ruff 0.10.0: https://github.com/astral-sh/ruff/releases/tag/0.10.0 Lint S704: https://docs.astral.sh/ruff/rules/unsafe-markup-use/ --- config/ruff.toml | 1 + scripts/insiders.py | 2 +- src/mkdocstrings/_internal/handlers/base.py | 5 ++--- tests/test_extension.py | 1 - tests/test_inventory.py | 1 - 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/config/ruff.toml b/config/ruff.toml index 655a158c..65416253 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -43,6 +43,7 @@ ignore = [ "PLR0913", # Too many arguments to function call "PLR0915", # Too many statements "SLF001", # Private member accessed + "S704", # Unsafe use of `markupsafe.Markup` "TRY003", # Avoid specifying long messages outside the exception class ] diff --git a/scripts/insiders.py b/scripts/insiders.py index 6535a31e..4cd438d4 100644 --- a/scripts/insiders.py +++ b/scripts/insiders.py @@ -168,6 +168,6 @@ def load_json(url: str) -> str | list | dict: 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/src/mkdocstrings/_internal/handlers/base.py b/src/mkdocstrings/_internal/handlers/base.py index f19d9094..cb1fffb3 100644 --- a/src/mkdocstrings/_internal/handlers/base.py +++ b/src/mkdocstrings/_internal/handlers/base.py @@ -17,7 +17,6 @@ from jinja2 import Environment, FileSystemLoader from markdown import Markdown -from markdown.extensions.toc import TocTreeprocessor from markupsafe import Markup from mkdocs.utils.cache import download_and_cache_url from mkdocs_autorefs import AutorefsInlineProcessor, BacklinksTreeProcessor @@ -33,7 +32,6 @@ from mkdocstrings._internal.inventory import Inventory from mkdocstrings._internal.loggers import get_logger, get_template_logger - # YORE: EOL 3.9: Replace block with line 4. if sys.version_info < (3, 10): from importlib_metadata import entry_points @@ -44,6 +42,7 @@ from collections.abc import Iterable, Iterator, Mapping, Sequence from markdown import Extension + from markdown.extensions.toc import TocTreeprocessor from mkdocs_autorefs import AutorefsHookInterface, Backlink _logger = get_logger(__name__) @@ -494,7 +493,7 @@ def do_heading( el = Element(f"h{heading_level}", attributes) el.append(Element("mkdocstrings-placeholder")) # Tell the inner 'toc' extension to make its additions if configured so. - toc = cast(TocTreeprocessor, self.md.treeprocessors["toc"]) + toc = cast("TocTreeprocessor", self.md.treeprocessors["toc"]) if toc.use_anchors: toc.add_anchor(el, attributes["id"]) if toc.use_permalinks: diff --git a/tests/test_extension.py b/tests/test_extension.py index aed0a1f1..dd3d7028 100644 --- a/tests/test_extension.py +++ b/tests/test_extension.py @@ -3,7 +3,6 @@ from __future__ import annotations import re -import sys from textwrap import dedent from typing import TYPE_CHECKING diff --git a/tests/test_inventory.py b/tests/test_inventory.py index 9589d528..8c2333d3 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -2,7 +2,6 @@ from __future__ import annotations -import sys from io import BytesIO from os.path import join From 81caff5ff76f1a6606da9d2980e81ae9d2e02246 Mon Sep 17 00:00:00 2001 From: Josh Mitchell Date: Thu, 27 Mar 2025 17:38:04 +1100 Subject: [PATCH 6/8] fix: Ignore invalid inventory lines Previously, inventory items whose `dispname` value contains multiple lines would prevent mkdocstrings from loading the whole inventory file. This change makes mkdocstrings ignore invalid lines in inventories so that the rest of the inventory can still be loaded. This continuation line behavior can be seen in the wild in the OpenEye toolkits inventory file and a few Open Force Field inventory files. These projects' inventories cannot be used with mkdocstrings because of the raised error. Note that in Sphinx too, these inventory files are read succesfully, and the continuation lines are discarded, truncating the display name. In theory, a continuation line that by chance did parse correctly would be interpreted by both packages as a new inventory item. OpenEye Toolkits inventory file: https://docs.eyesopen.com/toolkits/python/objects.inv Open Force Field Toolkit inventory file: https://docs.openforcefield.org/projects/toolkit/en/stable/objects.inv BespokeFit inventory file: https://docs.openforcefield.org/projects/bespokefit/en/stable/objects.inv --- src/mkdocstrings/_internal/inventory.py | 18 +++++++++++--- tests/test_inventory.py | 33 +++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/mkdocstrings/_internal/inventory.py b/src/mkdocstrings/_internal/inventory.py index 471e3633..241bbb12 100644 --- a/src/mkdocstrings/_internal/inventory.py +++ b/src/mkdocstrings/_internal/inventory.py @@ -8,7 +8,7 @@ import re import zlib from textwrap import dedent -from typing import TYPE_CHECKING, BinaryIO +from typing import TYPE_CHECKING, BinaryIO, Literal, overload if TYPE_CHECKING: from collections.abc import Collection @@ -66,11 +66,21 @@ def format_sphinx(self) -> str: sphinx_item_regex = re.compile(r"^(.+?)\s+(\S+):(\S+)\s+(-?\d+)\s+(\S+)\s*(.*)$") """Regex to parse a Sphinx v2 inventory line.""" + @overload @classmethod - def parse_sphinx(cls, line: str) -> InventoryItem: + def parse_sphinx(cls, line: str, *, return_none: Literal[False]) -> InventoryItem: ... + + @overload + @classmethod + def parse_sphinx(cls, line: str, *, return_none: Literal[True]) -> InventoryItem | None: ... + + @classmethod + def parse_sphinx(cls, line: str, *, return_none: bool = False) -> InventoryItem | None: """Parse a line from a Sphinx v2 inventory file and return an `InventoryItem` from it.""" match = cls.sphinx_item_regex.search(line) if not match: + if return_none: + return None raise ValueError(line) name, domain, role, priority, uri, dispname = match.groups() if uri.endswith("$"): @@ -167,7 +177,9 @@ def parse_sphinx(cls, in_file: BinaryIO, *, domain_filter: Collection[str] = ()) for _ in range(4): in_file.readline() lines = zlib.decompress(in_file.read()).splitlines() - items = [InventoryItem.parse_sphinx(line.decode("utf8")) for line in lines] + items: list[InventoryItem] = [ + item for line in lines if (item := InventoryItem.parse_sphinx(line.decode("utf8"), return_none=True)) + ] if domain_filter: items = [item for item in items if item.domain in domain_filter] return cls(items) diff --git a/tests/test_inventory.py b/tests/test_inventory.py index 8c2333d3..ab61e599 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -11,8 +11,6 @@ from mkdocstrings import Inventory, InventoryItem -sphinx = pytest.importorskip("sphinx.util.inventory", reason="Sphinx is not installed") - @pytest.mark.parametrize( "our_inv", @@ -21,10 +19,13 @@ Inventory([InventoryItem(name="object_path", domain="py", role="obj", uri="page_url")]), Inventory([InventoryItem(name="object_path", domain="py", role="obj", uri="page_url#object_path")]), Inventory([InventoryItem(name="object_path", domain="py", role="obj", uri="page_url#other_anchor")]), + Inventory([InventoryItem(name="o", domain="py", role="obj", uri="u#o", dispname="first line\nsecond line")]), ], ) def test_sphinx_load_inventory_file(our_inv: Inventory) -> None: """Perform the 'live' inventory load test.""" + sphinx = pytest.importorskip("sphinx.util.inventory", reason="Sphinx is not installed") + buffer = BytesIO(our_inv.format_sphinx()) sphinx_inv = sphinx.InventoryFile.load(buffer, "", join) @@ -37,6 +38,8 @@ def test_sphinx_load_inventory_file(our_inv: Inventory) -> None: def test_sphinx_load_mkdocstrings_inventory_file() -> None: """Perform the 'live' inventory load test on mkdocstrings own inventory.""" + sphinx = pytest.importorskip("sphinx.util.inventory", reason="Sphinx is not installed") + mkdocs_config = load_config() mkdocs_config["plugins"].run_event("startup", command="build", dirty=False) try: @@ -53,3 +56,29 @@ def test_sphinx_load_mkdocstrings_inventory_file() -> None: for item in own_inv.values(): assert item.name in sphinx_inv[f"{item.domain}:{item.role}"] + + +@pytest.mark.parametrize( + "our_inv", + [ + Inventory(), + Inventory([InventoryItem(name="object_path", domain="py", role="obj", uri="page_url")]), + Inventory([InventoryItem(name="object_path", domain="py", role="obj", uri="page_url#object_path")]), + Inventory([InventoryItem(name="object_path", domain="py", role="obj", uri="page_url#other_anchor")]), + Inventory([InventoryItem(name="o", domain="py", role="obj", uri="u#o", dispname="first line\nsecond line")]), + ], +) +def test_mkdocstrings_roundtrip_inventory_file(our_inv: Inventory) -> None: + """Save some inventory files, then load them in again.""" + buffer = BytesIO(our_inv.format_sphinx()) + round_tripped = Inventory.parse_sphinx(buffer) + + assert our_inv.keys() == round_tripped.keys() + for key, value in our_inv.items(): + round_tripped_item = round_tripped[key] + assert round_tripped_item.name == value.name + assert round_tripped_item.domain == value.domain + assert round_tripped_item.role == value.role + assert round_tripped_item.uri == value.uri + assert round_tripped_item.priority == value.priority + assert round_tripped_item.dispname == value.dispname.splitlines()[0] From 1a980402c39728ce265d8998b396c34bf76a113d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 31 Mar 2025 10:30:52 +0200 Subject: [PATCH 7/8] refactor: Rename loggers to "mkdocstrings" --- src/mkdocstrings/_internal/download.py | 2 +- src/mkdocstrings/_internal/extension.py | 2 +- src/mkdocstrings/_internal/handlers/base.py | 2 +- src/mkdocstrings/_internal/plugin.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mkdocstrings/_internal/download.py b/src/mkdocstrings/_internal/download.py index 2beb053a..ffe25e6b 100644 --- a/src/mkdocstrings/_internal/download.py +++ b/src/mkdocstrings/_internal/download.py @@ -9,7 +9,7 @@ from mkdocstrings._internal.loggers import get_logger -_logger = get_logger(__name__) +_logger = get_logger("mkdocstrings") # Regex pattern for an environment variable in the form ${ENV_VAR}. _ENV_VAR_PATTERN = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}") diff --git a/src/mkdocstrings/_internal/extension.py b/src/mkdocstrings/_internal/extension.py index 182fc563..83421ff8 100644 --- a/src/mkdocstrings/_internal/extension.py +++ b/src/mkdocstrings/_internal/extension.py @@ -44,7 +44,7 @@ from mkdocs_autorefs import AutorefsPlugin -_logger = get_logger(__name__) +_logger = get_logger("mkdocstrings") class AutoDocProcessor(BlockProcessor): diff --git a/src/mkdocstrings/_internal/handlers/base.py b/src/mkdocstrings/_internal/handlers/base.py index cb1fffb3..3d5852c5 100644 --- a/src/mkdocstrings/_internal/handlers/base.py +++ b/src/mkdocstrings/_internal/handlers/base.py @@ -45,7 +45,7 @@ from markdown.extensions.toc import TocTreeprocessor from mkdocs_autorefs import AutorefsHookInterface, Backlink -_logger = get_logger(__name__) +_logger = get_logger("mkdocstrings") CollectorItem = Any """The type of the item returned by the `collect` method of a handler.""" diff --git a/src/mkdocstrings/_internal/plugin.py b/src/mkdocstrings/_internal/plugin.py index d7adf1c6..afc94490 100644 --- a/src/mkdocstrings/_internal/plugin.py +++ b/src/mkdocstrings/_internal/plugin.py @@ -35,7 +35,7 @@ from mkdocs.structure.files import Files -_logger = get_logger(__name__) +_logger = get_logger("mkdocstrings") class PluginConfig(Config): From df4e7c81bd5b2a8931c676adf2d916d06531a987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 31 Mar 2025 10:32:52 +0200 Subject: [PATCH 8/8] chore: Prepare release 0.29.1 --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 826873b0..ed973133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.29.1](https://github.com/mkdocstrings/mkdocstrings/releases/tag/0.29.1) - 2025-03-31 + +[Compare with 0.29.0](https://github.com/mkdocstrings/mkdocstrings/compare/0.29.0...0.29.1) + +### Dependencies + +- Remove unused typing-extensions dependency ([ba98661](https://github.com/mkdocstrings/mkdocstrings/commit/ba98661b50e2cde19d8696d6c8ceecdbb49ce83f) by Timothée Mazzucotelli). + +### Bug Fixes + +- Ignore invalid inventory lines ([81caff5](https://github.com/mkdocstrings/mkdocstrings/commit/81caff5ff76f1a6606da9d2980e81ae9d2e02246) by Josh Mitchell). [PR-748](https://github.com/mkdocstrings/mkdocstrings/pull/748) + +### Code Refactoring + +- Rename loggers to "mkdocstrings" ([1a98040](https://github.com/mkdocstrings/mkdocstrings/commit/1a980402c39728ce265d8998b396c34bf76a113d) by Timothée Mazzucotelli). + ## [0.29.0](https://github.com/mkdocstrings/mkdocstrings/releases/tag/0.29.0) - 2025-03-10 [Compare with 0.28.3](https://github.com/mkdocstrings/mkdocstrings/compare/0.28.3...0.29.0)