diff --git a/CHANGELOG.md b/CHANGELOG.md index 66bb2047..1cd4ce23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,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). +## [1.16.3](https://github.com/mkdocstrings/python/releases/tag/1.16.3) - 2025-03-08 + +[Compare with 1.16.2](https://github.com/mkdocstrings/python/compare/1.16.2...1.16.3) + +### Build + +- Depend on mkdocstrings 0.28.3 ([9fa4f16](https://github.com/mkdocstrings/python/commit/9fa4f1636af240bb695661b7172f052cb11e0ec9) by Timothée Mazzucotelli). + +### Bug Fixes + +- De-duplicate summary sections ([a657d07](https://github.com/mkdocstrings/python/commit/a657d07499eb82d22337c169aa86b1cdd85543fa) by Timothée Mazzucotelli). [Issue-134](https://github.com/mkdocstrings/python/issues/134) + +### Code Refactoring + +- Import from top-level `mkdocstrings` module ([da2ba13](https://github.com/mkdocstrings/python/commit/da2ba13b1367ce107416d08f382fb9f2384c015c) by Timothée Mazzucotelli). + ## [1.16.2](https://github.com/mkdocstrings/python/releases/tag/1.16.2) - 2025-02-24 [Compare with 1.16.1](https://github.com/mkdocstrings/python/compare/1.16.1...1.16.2) diff --git a/pyproject.toml b/pyproject.toml index e69145f9..cb429367 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "mkdocstrings>=0.28.2", + "mkdocstrings>=0.28.3", "mkdocs-autorefs>=1.4", "griffe>=0.49", "typing-extensions>=4.0; python_version < '3.11'", diff --git a/scripts/make.py b/scripts/make.py index 3d427296..a3b9e751 100755 --- a/scripts/make.py +++ b/scripts/make.py @@ -16,7 +16,7 @@ from collections.abc import Iterator -PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13 3.14").split() +PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13").split() def shell(cmd: str, *, capture_output: bool = False, **kwargs: Any) -> str | None: diff --git a/src/mkdocstrings_handlers/python/config.py b/src/mkdocstrings_handlers/python/config.py index 6607d01c..a1ecdcd8 100644 --- a/src/mkdocstrings_handlers/python/config.py +++ b/src/mkdocstrings_handlers/python/config.py @@ -7,7 +7,7 @@ from dataclasses import field, fields from typing import TYPE_CHECKING, Annotated, Any, Literal -from mkdocstrings.loggers import get_logger +from mkdocstrings import get_logger # YORE: EOL 3.10: Replace block with line 2. if sys.version_info >= (3, 11): diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 0051be0f..d9db6669 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -22,9 +22,7 @@ patch_loggers, ) from mkdocs.exceptions import PluginError -from mkdocstrings.handlers.base import BaseHandler, CollectionError, CollectorItem, HandlerOptions -from mkdocstrings.inventory import Inventory -from mkdocstrings.loggers import get_logger +from mkdocstrings import BaseHandler, CollectionError, CollectorItem, HandlerOptions, Inventory, get_logger from mkdocstrings_handlers.python import rendering from mkdocstrings_handlers.python.config import PythonConfig, PythonOptions diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py index d284567a..4b8a8ee4 100644 --- a/src/mkdocstrings_handlers/python/rendering.py +++ b/src/mkdocstrings_handlers/python/rendering.py @@ -29,7 +29,7 @@ from jinja2 import TemplateNotFound, pass_context, pass_environment from markupsafe import Markup from mkdocs_autorefs import AutorefsHookInterface -from mkdocstrings.loggers import get_logger +from mkdocstrings import get_logger if TYPE_CHECKING: from collections.abc import Iterator, Sequence @@ -37,7 +37,7 @@ from griffe import Attribute, Class, Function, Module from jinja2 import Environment, Template from jinja2.runtime import Context - from mkdocstrings.handlers.base import CollectorItem + from mkdocstrings import CollectorItem logger = get_logger(__name__) 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 8bc8cb60..3675eda7 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 @@ -7,15 +7,17 @@ -#} {% endblock logs %} -{% with section = obj.attributes - |filter_objects( - filters=config.filters, - members_list=members_list, - inherited_members=config.inherited_members, - keep_no_docstrings=config.show_if_no_docstring, - ) - |order_members(config.members_order, members_list) - |as_attributes_section(check_public=not members_list) - %} - {% if section %}{% include "docstring/attributes"|get_template with context %}{% endif %} -{% endwith %} +{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "attributes") %} + {% with section = obj.attributes + |filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) + |order_members(config.members_order, members_list) + |as_attributes_section(check_public=not members_list) + %} + {% if section %}{% include "docstring/attributes"|get_template with context %}{% endif %} + {% endwith %} +{% endif %} 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 1b1ef8f3..3db63f3b 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 @@ -7,15 +7,17 @@ -#} {% endblock logs %} -{% with section = obj.classes - |filter_objects( - filters=config.filters, - members_list=members_list, - inherited_members=config.inherited_members, - keep_no_docstrings=config.show_if_no_docstring, - ) - |order_members(config.members_order, members_list) - |as_classes_section(check_public=not members_list) - %} - {% if section %}{% include "docstring/classes"|get_template with context %}{% endif %} -{% endwith %} +{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "classes") %} + {% with section = obj.classes + |filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) + |order_members(config.members_order, members_list) + |as_classes_section(check_public=not members_list) + %} + {% if section %}{% include "docstring/classes"|get_template with context %}{% endif %} + {% endwith %} +{% endif %} 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 f03dfba2..60369401 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 @@ -7,15 +7,17 @@ -#} {% endblock logs %} -{% with section = obj.functions - |filter_objects( - filters=config.filters, - members_list=members_list, - inherited_members=config.inherited_members, - keep_no_docstrings=config.show_if_no_docstring, - ) - |order_members(config.members_order, members_list) - |as_functions_section(check_public=not members_list) - %} - {% if section %}{% include "docstring/functions"|get_template with context %}{% endif %} -{% endwith %} +{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "functions") %} + {% with section = obj.functions + |filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) + |order_members(config.members_order, members_list) + |as_functions_section(check_public=not members_list) + %} + {% if section %}{% include "docstring/functions"|get_template with context %}{% endif %} + {% endwith %} +{% endif %} 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 606711c5..dd14ee9f 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 @@ -7,15 +7,17 @@ -#} {% endblock logs %} -{% with section = obj.modules - |filter_objects( - filters=config.filters, - members_list=members_list, - inherited_members=config.inherited_members, - keep_no_docstrings=config.show_if_no_docstring, - ) - |order_members("alphabetical", members_list) - |as_modules_section(check_public=not members_list) - %} - {% if section %}{% include "docstring/modules"|get_template with context %}{% endif %} -{% endwith %} +{% if not obj.docstring.parsed | selectattr("kind.value", "eq", "modules") %} + {% with section = obj.modules + |filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) + |order_members("alphabetical", members_list) + |as_modules_section(check_public=not members_list) + %} + {% if section %}{% include "docstring/modules"|get_template with context %}{% endif %} + {% endwith %} +{% endif %} diff --git a/tests/conftest.py b/tests/conftest.py index 1c53cba4..5b2dd33f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,7 +15,7 @@ from markdown.core import Markdown from mkdocs.config.defaults import MkDocsConfig - from mkdocstrings.plugin import MkdocstringsPlugin + from mkdocstrings import MkdocstringsPlugin from mkdocstrings_handlers.python.handler import PythonHandler diff --git a/tests/helpers.py b/tests/helpers.py index 37c127e4..b0dc6ad7 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -14,7 +14,7 @@ from pathlib import Path import pytest - from mkdocstrings.plugin import MkdocstringsPlugin + from mkdocstrings import MkdocstringsPlugin from mkdocstrings_handlers.python.handler import PythonHandler diff --git a/tests/test_handler.py b/tests/test_handler.py index 7cf8dc54..4d8b4f3d 100644 --- a/tests/test_handler.py +++ b/tests/test_handler.py @@ -10,13 +10,13 @@ from typing import TYPE_CHECKING import pytest -from griffe import DocstringSectionExamples, DocstringSectionKind, temporary_visited_module +from griffe import Docstring, DocstringSectionExamples, DocstringSectionKind, Module, temporary_visited_module from mkdocstrings_handlers.python.config import PythonConfig, PythonOptions from mkdocstrings_handlers.python.handler import CollectionError, PythonHandler if TYPE_CHECKING: - from mkdocstrings.plugin import MkdocstringsPlugin + from mkdocstrings import MkdocstringsPlugin def test_collect_missing_module(handler: PythonHandler) -> None: @@ -179,3 +179,102 @@ def test_give_precedence_to_user_paths() -> None: mdx_config={}, ) assert handler._paths[0] == last_sys_path + + +@pytest.mark.parametrize( + ("section", "code"), + [ + ( + "Attributes", + """ + class A: + '''Summary. + + Attributes: + x: X. + y: Y. + ''' + x: int = 0 + '''X.''' + y: int = 0 + '''Y.''' + """, + ), + ( + "Methods", + """ + class A: + '''Summary. + + Methods: + x: X. + y: Y. + ''' + def x(self): ... + '''X.''' + def y(self): ... + '''Y.''' + """, + ), + ( + "Functions", + """ + '''Summary. + + Functions: + x: X. + y: Y. + ''' + def x(): ... + '''X.''' + def y(): ... + '''Y.''' + """, + ), + ( + "Classes", + """ + '''Summary. + + Classes: + A: A. + B: B. + ''' + class A: ... + '''A.''' + class B: ... + '''B.''' + """, + ), + ( + "Modules", + """ + '''Summary. + + Modules: + a: A. + b: B. + ''' + """, + ), + ], +) +def test_deduplicate_summary_sections(handler: PythonHandler, section: str, code: str) -> None: + """Assert summary sections are deduplicated.""" + summary_section = section.lower() + summary_section = "functions" if summary_section == "methods" else summary_section + with temporary_visited_module(code, docstring_parser="google") as module: # type: ignore[arg-type] + if summary_section == "modules": + module.set_member("a", Module("A", docstring=Docstring("A."))) + module.set_member("b", Module("B", docstring=Docstring("B."))) + html = handler.render( + module, + handler.get_options( + { + "summary": {summary_section: True}, + "show_source": False, + "show_submodules": True, + }, + ), + ) + assert html.count(f"{section}:") == 1 diff --git a/tests/test_themes.py b/tests/test_themes.py index a7b44795..ca7125d3 100644 --- a/tests/test_themes.py +++ b/tests/test_themes.py @@ -7,7 +7,7 @@ import pytest if TYPE_CHECKING: - from mkdocstrings.handlers.python import PythonHandler + from mkdocstrings_handlers.python.handler import PythonHandler @pytest.mark.parametrize(