From 1fc513a98c3264d7ab6eb19dc950c3ea99f90d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sun, 4 Jun 2023 18:22:45 +0200 Subject: [PATCH 01/13] chore: Template upgrade --- .copier-answers.yml | 2 +- scripts/gen_ref_nav.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index 35c682de..5d4b2178 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 0.15.8 +_commit: 0.15.9 _src_path: gh:pawamoy/copier-pdm author_email: pawamoy@pm.me author_fullname: Timothée Mazzucotelli diff --git a/scripts/gen_ref_nav.py b/scripts/gen_ref_nav.py index 69f6e3b9..4fcce9f1 100644 --- a/scripts/gen_ref_nav.py +++ b/scripts/gen_ref_nav.py @@ -5,7 +5,7 @@ import mkdocs_gen_files nav = mkdocs_gen_files.Nav() -mod_symbol = 'mod' +mod_symbol = 'mod' for path in sorted(Path("src").rglob("*.py")): module_path = path.relative_to("src").with_suffix("") From 22e83debb1084472a60e912f86d1ae2d60d4624e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 9 Jun 2023 00:26:31 +0200 Subject: [PATCH 02/13] chore: Template upgrade --- .copier-answers.yml | 2 +- docs/css/insiders.css | 23 +++++++++++++++++++++++ docs/insiders/index.md | 22 +++++++++++++++++++++- docs/license.md | 2 ++ scripts/gen_credits.py | 2 ++ scripts/gen_ref_nav.py | 2 +- 6 files changed, 50 insertions(+), 3 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index 5d4b2178..c93fb522 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 0.15.9 +_commit: 0.15.11 _src_path: gh:pawamoy/copier-pdm author_email: pawamoy@pm.me author_fullname: Timothée Mazzucotelli diff --git a/docs/css/insiders.css b/docs/css/insiders.css index 81dbd756..ef43f6fd 100644 --- a/docs/css/insiders.css +++ b/docs/css/insiders.css @@ -95,4 +95,27 @@ a.insiders { transition: all .25s; vertical-align: bottom !important; width: 1.2rem; +} + +.premium-sponsors { + text-align: center; +} + +.premium-sponsors .silver img { + height: 140px; +} + +.premium-sponsors .bronze img { + height: 140px; +} + +.premium-sponsors .bronze p { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.premium-sponsors .bronze a { + display: block; + flex-shrink: 0; } \ No newline at end of file diff --git a/docs/insiders/index.md b/docs/insiders/index.md index a8773879..bb780c56 100644 --- a/docs/insiders/index.md +++ b/docs/insiders/index.md @@ -119,13 +119,33 @@ You can cancel your sponsorship anytime.[^5] print_join_sponsors_button() ``` +
+
+ +
+ Bronze sponsors +

+ + + Material for MkDocs + + + Pydantic + + +

+
+
+ +

```python exec="1" session="insiders" print_sponsors() ``` -

+
+
If you sponsor publicly, you're automatically added here with a link to diff --git a/docs/license.md b/docs/license.md index cdacdfef..a873d2b5 100644 --- a/docs/license.md +++ b/docs/license.md @@ -1,3 +1,5 @@ +# License + ``` --8<-- "LICENSE" ``` diff --git a/scripts/gen_credits.py b/scripts/gen_credits.py index 85ac9041..bc01c0bd 100644 --- a/scripts/gen_credits.py +++ b/scripts/gen_credits.py @@ -89,6 +89,8 @@ def _render_credits() -> str: } template_text = dedent( """ + # Credits + These projects were used to build *{{ project_name }}*. **Thank you!** [`python`](https://www.python.org/) | diff --git a/scripts/gen_ref_nav.py b/scripts/gen_ref_nav.py index 4fcce9f1..713522be 100644 --- a/scripts/gen_ref_nav.py +++ b/scripts/gen_ref_nav.py @@ -5,7 +5,7 @@ import mkdocs_gen_files nav = mkdocs_gen_files.Nav() -mod_symbol = 'mod' +mod_symbol = '' for path in sorted(Path("src").rglob("*.py")): module_path = path.relative_to("src").with_suffix("") From 02619a85ee4aab25f3241d983bdfff0534dd3f81 Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Thu, 8 Jun 2023 16:51:02 +0200 Subject: [PATCH 03/13] fix: Show labels in deterministic order These labels are `set`s which have no defined order. Define *some* order, so they don't flip-flop depending on the environment. --- .../python/templates/material/_base/labels.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html index 4f2f72d9..0c84067a 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html @@ -1,7 +1,7 @@ {% if labels %} {{ log.debug("Rendering labels") }} - {% for label in labels %} + {% for label in labels|sort %} {{ label }} {% endfor %} From 04335879b92fdd87a5c87ad218abdeafee9c7890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sun, 2 Jul 2023 18:22:26 +0200 Subject: [PATCH 04/13] chore: Template upgrade --- .copier-answers.yml | 2 +- .github/workflows/ci.yml | 14 ++++++--- .gitpod.dockerfile | 1 - CONTRIBUTING.md | 13 ++++---- Makefile | 1 + docs/css/insiders.css | 12 ++++--- docs/insiders/goals.yml | 2 +- docs/insiders/index.md | 45 +++++++-------------------- docs/js/insiders.js | 67 ++++++++++++++++++++++++++++++++++++++++ duties.py | 2 +- mkdocs.yml | 15 +++++++-- scripts/insiders.py | 32 +++---------------- scripts/setup.sh | 6 ++-- 13 files changed, 123 insertions(+), 89 deletions(-) create mode 100644 docs/js/insiders.js diff --git a/.copier-answers.yml b/.copier-answers.yml index c93fb522..38ac3370 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 0.15.11 +_commit: 0.15.23 _src_path: gh:pawamoy/copier-pdm author_email: pawamoy@pm.me author_fullname: Timothée Mazzucotelli diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3e0afb6..daa2b927 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push: pull_request: branches: - - master + - main defaults: run: @@ -25,6 +25,9 @@ jobs: - name: Checkout uses: actions/checkout@v3 + - name: Fetch all tags + run: git fetch --depth=1 --tags + - name: Set up PDM uses: pdm-project/setup-pdm@v3 with: @@ -62,10 +65,10 @@ jobs: echo 'jobs=[ {"os": "macos-latest"}, {"os": "windows-latest"}, - {"python-version": "3.8"}, {"python-version": "3.9"}, {"python-version": "3.10"}, - {"python-version": "3.11"} + {"python-version": "3.11"}, + {"python-version": "3.12"} ]' | tr -d '[:space:]' >> $GITHUB_OUTPUT else echo 'jobs=[]' >> $GITHUB_OUTPUT @@ -82,14 +85,14 @@ jobs: - macos-latest - windows-latest python-version: - - "3.7" - "3.8" - "3.9" - "3.10" - "3.11" + - "3.12" exclude: ${{ fromJSON(needs.exclude-test-jobs.outputs.jobs) }} - runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.python-version == '3.12' }} steps: - name: Checkout @@ -99,6 +102,7 @@ jobs: uses: pdm-project/setup-pdm@v3 with: python-version: ${{ matrix.python-version }} + allow-python-prereleases: true - name: Resolving dependencies run: pdm lock -v --no-cross-platform -G ci-tests diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile index 33f285c2..0e6d9d35 100644 --- a/.gitpod.dockerfile +++ b/.gitpod.dockerfile @@ -1,7 +1,6 @@ FROM gitpod/workspace-full USER gitpod ENV PIP_USER=no -ENV PYTHON_VERSIONS= RUN pip3 install pipx; \ pipx install pdm; \ pipx ensurepath diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ec1ca91f..0dafa847 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,20 +39,19 @@ Run `make help` to see all the available actions! This project uses [duty](https://github.com/pawamoy/duty) to run tasks. A Makefile is also provided. The Makefile will try to run certain tasks on multiple Python versions. If for some reason you don't want to run the task -on multiple Python versions, you can do one of the following: - -1. `export PYTHON_VERSIONS= `: this will run the task - with only the current Python version -2. run the task directly with `pdm run duty TASK` +on multiple Python versions, you run the task directly with `pdm run duty TASK`. The Makefile detects if a virtual environment is activated, so `make` will work the same with the virtualenv activated or not. +If you work in VSCode, +[see examples of tasks and run configurations](https://pawamoy.github.io/copier-pdm/work/#vscode-setup). + ## Development As usual: -1. create a new branch: `git checkout -b feature-or-bugfix-name` +1. create a new branch: `git switch -c feature-or-bugfix-name` 1. edit the code and/or the documentation **Before committing:** @@ -138,7 +137,7 @@ git commit --fixup=SHA Once all the changes are approved, you can squash your commits: ```bash -git rebase -i --autosquash master +git rebase -i --autosquash main ``` And force-push: diff --git a/Makefile b/Makefile index cf75dae1..686de675 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ .DEFAULT_GOAL := help SHELL := bash DUTY := $(if $(VIRTUAL_ENV),,pdm run) duty +export PDM_MULTIRUN_VERSIONS ?= 3.8 3.9 3.10 3.11 args = $(foreach a,$($(subst -,_,$1)_args),$(if $(value $a),$a="$($a)")) check_quality_args = files diff --git a/docs/css/insiders.css b/docs/css/insiders.css index ef43f6fd..b5547bd1 100644 --- a/docs/css/insiders.css +++ b/docs/css/insiders.css @@ -101,21 +101,25 @@ a.insiders { text-align: center; } -.premium-sponsors .silver img { +#silver-sponsors img { height: 140px; } -.premium-sponsors .bronze img { +#bronze-sponsors img { height: 140px; } -.premium-sponsors .bronze p { +#bronze-sponsors p { display: flex; flex-wrap: wrap; justify-content: center; } -.premium-sponsors .bronze a { +#bronze-sponsors a { display: block; flex-shrink: 0; +} + +.sponsors-total { + font-weight: bold; } \ No newline at end of file diff --git a/docs/insiders/goals.yml b/docs/insiders/goals.yml index 896b9240..a96ac51b 100644 --- a/docs/insiders/goals.yml +++ b/docs/insiders/goals.yml @@ -1 +1 @@ -goals: {} +goals: {} \ No newline at end of file diff --git a/docs/insiders/index.md b/docs/insiders/index.md index bb780c56..71c06b92 100644 --- a/docs/insiders/index.md +++ b/docs/insiders/index.md @@ -65,10 +65,10 @@ data_source = "docs/insiders/goals.yml" @@ -115,34 +115,17 @@ You can cancel your sponsorship anytime.[^5] regarding your payment, and GitHub doesn't offer refunds, sponsorships are non-refundable. -```python exec="1" session="insiders" -print_join_sponsors_button() -``` +[:octicons-heart-fill-24:{ .pulse }   Join our awesome sponsors](https://github.com/sponsors/pawamoy){ .md-button .md-button--primary }
-
- Bronze sponsors -

- - - Material for MkDocs - - - Pydantic - - -

-
+

-
-```python exec="1" session="insiders" -print_sponsors() -``` +


@@ -155,18 +138,9 @@ print_sponsors() afterwards.
-## Funding - -```python exec="1" session="insiders" -print(f""" -Current funding is at **$ {human_readable_amount(current_funding)} a month**. -We do not have any funding goals yet. -Stay updated by following **@pawamoy** -on :material-mastodon:{{ .mastodon }} [Fosstodon](https://fosstodon.org/@pawamoy). -""") -``` +## Funding - +``` ## Frequently asked questions @@ -248,3 +222,6 @@ by the [ISC License][license]. However, we kindly ask you to respect our [billing cycle]: https://docs.github.com/en/github/setting-up-and-managing-billing-and-payments-on-github/changing-the-duration-of-your-billing-cycle [license]: ../license/ [private forks]: https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/removing-a-collaborator-from-a-personal-repository + + + diff --git a/docs/js/insiders.js b/docs/js/insiders.js new file mode 100644 index 00000000..03bcb404 --- /dev/null +++ b/docs/js/insiders.js @@ -0,0 +1,67 @@ +function humanReadableAmount(amount) { + const strAmount = String(amount); + if (strAmount.length >= 4) { + return `${strAmount.slice(0, strAmount.length - 3)},${strAmount.slice(-3)}`; + } + return strAmount; +} + +function getJSON(url, callback) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'json'; + xhr.onload = function () { + var status = xhr.status; + if (status === 200) { + callback(null, xhr.response); + } else { + callback(status, xhr.response); + } + }; + xhr.send(); +} + +function updateInsidersPage(author_username) { + const sponsorURL = `https://github.com/sponsors/${author_username}` + const dataURL = `https://raw.githubusercontent.com/${author_username}/sponsors/main`; + getJSON(dataURL + '/numbers.json', function (err, numbers) { + document.getElementById('sponsors-count').innerHTML = numbers.count; + Array.from(document.getElementsByClassName('sponsors-total')).forEach(function (element) { + element.innerHTML = '$ ' + humanReadableAmount(numbers.total); + }); + getJSON(dataURL + '/sponsors.json', function (err, sponsors) { + const sponsorsElem = document.getElementById('sponsors'); + const privateSponsors = numbers.count - sponsors.length; + sponsors.forEach(function (sponsor) { + sponsorsElem.innerHTML += ` + + + + `; + }); + if (privateSponsors > 0) { + sponsorsElem.innerHTML += ` + + +${privateSponsors} + + `; + } + }); + }); + getJSON(dataURL + '/sponsorsBronze.json', function (err, sponsors) { + const bronzeSponsors = document.getElementById("bronze-sponsors"); + if (sponsors) { + let html = ''; + html += 'Bronze sponsors

' + sponsors.forEach(function (sponsor) { + html += ` + + ${sponsor.name} + + ` + }); + html += '

' + bronzeSponsors.innerHTML = html; + } + }); +} diff --git a/duties.py b/duties.py index a49b49cb..06a1048d 100644 --- a/duties.py +++ b/duties.py @@ -299,6 +299,6 @@ def test(ctx: Context, match: str = "") -> None: py_version = f"{sys.version_info.major}{sys.version_info.minor}" os.environ["COVERAGE_FILE"] = f".coverage.{py_version}" ctx.run( - pytest.run("-n", "auto", "tests", config_file="config/pytest.ini", select=match), + pytest.run("-n", "auto", "tests", config_file="config/pytest.ini", select=match, color="yes"), title=pyprefix("Running tests"), ) diff --git a/mkdocs.yml b/mkdocs.yml index 85fd7ef7..058f69cc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -29,7 +29,8 @@ nav: - Customization: usage/customization.md - Extensions: usage/extensions.md # defer to gen-files + literate-nav -- Code Reference: reference/ +- API reference: + - mkdocstrings-python: reference/ - Development: - Contributing: contributing.md - Code of Conduct: code_of_conduct.md @@ -138,10 +139,18 @@ plugins: - https://mkdocstrings.github.io/objects.inv - https://mkdocstrings.github.io/griffe/objects.inv options: - separate_signature: true - merge_init_into_class: true docstring_options: ignore_init_summary: true + docstring_section_style: list + heading_level: 1 + merge_init_into_class: true + separate_signature: true + show_root_heading: true + show_root_full_path: false + show_signature_annotations: true + show_symbol_type_heading: true + show_symbol_type_toc: true + signature_crossrefs: true - git-committers: enabled: !ENV [DEPLOY, false] repository: mkdocstrings/python diff --git a/scripts/insiders.py b/scripts/insiders.py index 0d23a45a..6f8d0d84 100644 --- a/scripts/insiders.py +++ b/scripts/insiders.py @@ -9,7 +9,6 @@ from datetime import date, datetime, timedelta from itertools import chain from pathlib import Path -from textwrap import dedent from typing import Iterable, cast from urllib.error import HTTPError from urllib.parse import urljoin @@ -101,7 +100,7 @@ def load_goals(data: str, funding: int = 0, project: Project | None = None) -> d Feature( name=feature_data["name"], ref=feature_data["ref"], - since=feature_data["since"] + since=feature_data.get("since") and datetime.strptime(feature_data["since"], "%Y/%m/%d").date(), # noqa: DTZ007 project=project, ) @@ -185,32 +184,9 @@ def load_json(url: str) -> str | list | dict: # noqa: D103 current_funding = numbers["total"] sponsors_count = numbers["count"] goals = funding_goals(data_source, funding=current_funding) -all_features = feature_list(goals.values()) -completed_features = sorted( - (ft for ft in all_features if ft.since), +ongoing_goals = [goal for goal in goals.values() if not goal.complete] +unreleased_features = sorted( + (ft for ft in feature_list(ongoing_goals) if ft.since), key=lambda ft: cast(date, ft.since), reverse=True, ) - - -def print_join_sponsors_button() -> None: # noqa: D103 - btn_classes = "{ .md-button .md-button--primary }" - print( - dedent( - f""" - [:octicons-heart-fill-24:{{ .pulse }} -   Join our {sponsors_count} awesome sponsors]({sponsor_url}){btn_classes} - """, - ), - ) - - -def print_sponsors() -> None: # noqa: D103 - private_sponsors_count = sponsors_count - len(sponsors) - for sponsor in sponsors: - print( - f"""""" - f"""""", - ) - if private_sponsors_count: - print(f"""+{private_sponsors_count}""") diff --git a/scripts/setup.sh b/scripts/setup.sh index a0f87210..bbf0d11d 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash set -e -PYTHON_VERSIONS="${PYTHON_VERSIONS-3.7 3.8 3.9 3.10 3.11}" - if ! command -v pdm &>/dev/null; then if ! command -v pipx &>/dev/null; then python3 -m pip install --user pipx @@ -13,8 +11,8 @@ if ! pdm self list 2>/dev/null | grep -q pdm-multirun; then pdm install --plugins fi -if [ -n "${PYTHON_VERSIONS}" ]; then - pdm multirun -vi ${PYTHON_VERSIONS// /,} pdm install -G:all +if [ -n "${PDM_MULTIRUN_VERSIONS}" ]; then + pdm multirun -v pdm install -G:all else pdm install -G:all fi From 93ccaaa01e57d6c0711386a54ad92776f978d9b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sun, 2 Jul 2023 18:26:10 +0200 Subject: [PATCH 05/13] ci: Quality --- src/mkdocstrings_handlers/python/handler.py | 6 +++--- src/mkdocstrings_handlers/python/rendering.py | 3 +-- tests/conftest.py | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index c5a06d0c..8aeedbc1 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -10,7 +10,7 @@ import sys from collections import ChainMap from contextlib import suppress -from typing import TYPE_CHECKING, Any, BinaryIO, Iterator, Mapping +from typing import TYPE_CHECKING, Any, BinaryIO, ClassVar, Iterator, Mapping from griffe.collections import LinesCollection, ModulesCollection from griffe.docstrings.parsers import Parser @@ -71,8 +71,8 @@ class PythonHandler(BaseHandler): domain: str = "py" # to match Sphinx's default domain enable_inventory: bool = True fallback_theme = "material" - fallback_config: dict = {"fallback": True} - default_config: dict = { + fallback_config: ClassVar[dict] = {"fallback": True} # type: ignore[misc] + default_config: ClassVar[dict] = { "docstring_style": "google", "docstring_options": {}, "show_root_heading": False, diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py index 5c8b0f19..40d6a2c1 100644 --- a/src/mkdocstrings_handlers/python/rendering.py +++ b/src/mkdocstrings_handlers/python/rendering.py @@ -103,8 +103,7 @@ def do_format_signature( template = env.get_template("signature.html") signature = template.render(context.parent, function=function) signature = _format_signature(callable_path, signature, line_length) - signature = str(env.filters["highlight"](signature, language="python", inline=False)) - return signature + return str(env.filters["highlight"](signature, language="python", inline=False)) def do_order_members( diff --git a/tests/conftest.py b/tests/conftest.py index 5a34bd77..b93200ba 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -41,7 +41,7 @@ def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Itera **getattr(request, "param", {}), } # Re-create it manually as a workaround for https://github.com/mkdocs/mkdocs/issues/2289 - mdx_configs: dict[str, Any] = dict(ChainMap(*conf_dict.get("markdown_extensions", []))) # type: ignore[arg-type] + mdx_configs: dict[str, Any] = dict(ChainMap(*conf_dict.get("markdown_extensions", []))) conf.load_dict(conf_dict) assert conf.validate() == ([], []) From 8eb459f8be924d908492971a56d7ac2edaa5232d Mon Sep 17 00:00:00 2001 From: Eugene Mayer Date: Mon, 10 Jul 2023 13:58:51 +0300 Subject: [PATCH 06/13] docs: Fix a typo in `show_docstring_attributes` example --- docs/usage/configuration/docstrings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/configuration/docstrings.md b/docs/usage/configuration/docstrings.md index 97446d97..4e56b745 100644 --- a/docs/usage/configuration/docstrings.md +++ b/docs/usage/configuration/docstrings.md @@ -416,7 +416,7 @@ plugins: ```md title="or in docs/some_page.md (local configuration)" ::: path.to.module options: - show_if_no_docstring: false + show_docstring_attributes: false ``` ```python From ae4235689155a4b4f0c1e74b0014a466c6b1181f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 3 Jul 2023 18:46:50 +0200 Subject: [PATCH 07/13] feat: Support inheritance Issue mkdocstrings#157: https://github.com/mkdocstrings/mkdocstrings/issues/157 Discussion mkdocstrings#536: https://github.com/mkdocstrings/mkdocstrings/discussions/536 --- docs/usage/configuration/members.md | 163 ++++++++++++++++++ mkdocs.yml | 2 + pyproject.toml | 2 +- src/mkdocstrings_handlers/python/handler.py | 9 +- src/mkdocstrings_handlers/python/rendering.py | 43 +++-- .../templates/material/_base/children.html | 82 ++++++--- tests/conftest.py | 3 + tests/test_rendering.py | 62 +++++++ 8 files changed, 325 insertions(+), 41 deletions(-) diff --git a/docs/usage/configuration/members.md b/docs/usage/configuration/members.md index 412fdf45..17ef9527 100644 --- a/docs/usage/configuration/members.md +++ b/docs/usage/configuration/members.md @@ -89,6 +89,169 @@ this_attribute = 0 INFO: **The default behavior (with unspecified `members` or `members: null`) is to use [`filters`][].** +## `inherited_members` + +- **:octicons-package-24: Type list[str] | + bool :material-equal: `False`{ title="default value" }** + + +An explicit list of inherited members (for classes) to render. + +Inherited members are always fetched from classes that are in the same package +as the currently rendered class. To fetch members inherited from base classes, +themselves coming from external packages, use the [`preload_modules`][preload_modules] option. +For example, if your class inherits from Pydantic's `BaseModel`, and you want to render +`BaseModel`'s methods in your class, use `preload_modules: [pydantic]`. +The `pydantic` package must be available in the current environment. + +Passing a falsy value (`no`, `false` in YAML) or an empty list (`[]`) +will tell the Python handler not to render any inherited member. +Passing a truthy value (`yes`, `true` in YAML) +will tell the Python handler to render every inherited member. + +When all inherited members are selected with `inherited_members: true`, +it is possible to specify both members and inherited members in the `members` list: + +```yaml +inherited_members: true +members: +- inherited_member_a +- inherited_member_b +- member_x +- member_y +``` + +The alternative is not supported: + +```yaml +inherited_members: +- inherited_member_a +- inherited_member_b +members: +- member_x +- member_y +``` + +...because it would make members ordering ambiguous/unspecified. + +You can render inherited members *only* by setting `inherited_members: true` +(or a list of inherited members) and setting `members: false`: + +```yaml +inherited_members: true +members: false +``` + +```yaml +inherited_members: +- inherited_member_a +- inherited_member_b +members: false +``` + +You can render *all declared members* and all or specific inherited members +by leaving `members` as null (default): + +```yaml +inherited_members: +- inherited_member_a +- inherited_member_b +# members: null # (1) +``` + +1. In this case, only declared members will be subject +to further filtering with [`filters`][filters] and [`docstrings`][show_if_no_docstring]. + +```yaml +inherited_members: true # (1) +# members: null +``` + +1. In this case, both declared and inherited members will be subject +to further filtering with [`filters`][filters] and [`docstrings`][show_if_no_docstring]. + +You can render *all declared members* and all or specific inherited members, +avoiding further filtering with [`filters`][filters] and [`docstrings`][show_if_no_docstring] +by setting `members: true`: + +```yaml +inherited_members: true +members: true +``` + +```yaml +inherited_members: +- inherited_member_a +- inherited_member_b +members: true +``` + +The general rule is that declared or inherited members specified in lists +are never filtered out. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + inherited_members: false +``` + +```md title="or in docs/some_page.md (local configuration)" +::: package.module + options: + inherited_members: true +``` + +```python title="package/module.py" +"""Module docstring.""" + +class Base: + """Base class.""" + + def base(self): + """Base method.""" + + +class Main(Base): + """Main class.""" + + def main(self): + """Main method.""" +``` + +/// admonition | Preview + type: preview + +//// tab | With inherited members +

Module docstring.

+

Base

+

Base class.

+

base

+

Base method.

+

Main

+

Main class.

+

base

+

Base method.

+

main

+

Main method.

+//// + +//// tab | Without inherited members +

Module docstring.

+

Base

+

Base class.

+

base

+

Base method.

+

Main

+

Main class.

+

main

+

Main method.

+//// + +/// + ## `members_order` - **:octicons-package-24: Type [`str`][] :material-equal: `"alphabetical"`{ title="default value" }** diff --git a/mkdocs.yml b/mkdocs.yml index 058f69cc..c7bc867b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -143,7 +143,9 @@ plugins: ignore_init_summary: true docstring_section_style: list heading_level: 1 + inherited_members: true merge_init_into_class: true + preload_modules: [mkdocstrings] separate_signature: true show_root_heading: true show_root_full_path: false diff --git a/pyproject.toml b/pyproject.toml index 511dbcd2..f18cae03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ classifiers = [ ] dependencies = [ "mkdocstrings>=0.20", - "griffe>=0.24", + "griffe>=0.30", ] [project.urls] diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 8aeedbc1..be293591 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -106,6 +106,7 @@ class PythonHandler(BaseHandler): "members_order": rendering.Order.alphabetical.value, "docstring_section_style": "table", "members": None, + "inherited_members": False, "filters": ["!^_[^_]"], "annotations_path": "brief", "preload_modules": None, @@ -138,7 +139,13 @@ class PythonHandler(BaseHandler): show_category_heading (bool): When grouped by categories, show a heading for each category. Default: `False`. Attributes: Members options: - members (list[str] | False | None): An explicit list of members to render. Default: `None`. + inherited_members (list[str] | bool | None): A boolean, or an explicit list of inherited members to render. + If true, select all inherited members, which can then be filtered with `members`. + If false or empty list, do not select any inherited member. Default: `False`. + members (list[str] | bool | None): A boolean, or an explicit list of members to render. + If true, select all members without further filtering. + If false or empty list, do not render members. + If none, select all members and apply further filtering with filters and docstrings. Default: `None`. members_order (str): The members ordering to use. Options: `alphabetical` - order by the members names, `source` - order members as they appear in the source file. Default: `"alphabetical"`. filters (list[str] | None): A list of filters applied to filter objects based on their name. diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py index 40d6a2c1..81538212 100644 --- a/src/mkdocstrings_handlers/python/rendering.py +++ b/src/mkdocstrings_handlers/python/rendering.py @@ -194,7 +194,8 @@ def do_filter_objects( objects_dictionary: dict[str, Object | Alias], *, filters: Sequence[tuple[Pattern, bool]] | None = None, - members_list: list[str] | 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. @@ -207,31 +208,49 @@ def do_filter_objects( 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. """ - # no members - if members_list is False or members_list == []: - return [] - - objects = list(objects_dictionary.values()) + 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) + ] - # all members if members_list is True: + # Return all pre-selected members. return objects - # list of members + 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 [obj for obj in objects if obj.name in set(members_list)] + # 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) + ] - # none, use filters and docstrings + # Use filters and docstrings. if filters: - objects = [obj for obj in objects if _keep_object(obj.name, 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] + + return [obj for obj in objects if obj.has_docstrings or (inherited_members_specified and obj.inherited)] @lru_cache(maxsize=1) diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/children.html b/src/mkdocstrings_handlers/python/templates/material/_base/children.html index dda1c5ff..2c5d4087 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/children.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/children.html @@ -19,14 +19,19 @@ {% set extra_level = 0 %} {% endif %} - {% with attributes = obj.attributes|filter_objects(filters=config.filters, members_list=members_list, keep_no_docstrings=config.show_if_no_docstring) %} + {% with attributes = obj.attributes|filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) %} {% if attributes %} {% if config.show_category_heading %} {% filter heading(heading_level, id=html_id ~ "-attributes") %}Attributes{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for attribute in attributes|order_members(config.members_order, members_list) %} - {% if not attribute.is_alias or attribute.is_explicitely_exported %} + {% if not attribute.is_alias or attribute.is_explicitely_exported or attribute.inherited %} {% include attribute|get_template with context %} {% endif %} {% endfor %} @@ -34,14 +39,19 @@ {% endif %} {% endwith %} - {% with classes = obj.classes|filter_objects(filters=config.filters, members_list=members_list, keep_no_docstrings=config.show_if_no_docstring) %} + {% with classes = obj.classes|filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) %} {% if classes %} {% if config.show_category_heading %} {% filter heading(heading_level, id=html_id ~ "-classes") %}Classes{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for class in classes|order_members(config.members_order, members_list) %} - {% if not class.is_alias or class.is_explicitely_exported %} + {% if not class.is_alias or class.is_explicitely_exported or class.inherited %} {% include class|get_template with context %} {% endif %} {% endfor %} @@ -49,7 +59,12 @@ {% endif %} {% endwith %} - {% with functions = obj.functions|filter_objects(filters=config.filters, members_list=members_list, keep_no_docstrings=config.show_if_no_docstring) %} + {% with functions = obj.functions|filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) %} {% if functions %} {% if config.show_category_heading %} {% filter heading(heading_level, id=html_id ~ "-functions") %}Functions{% endfilter %} @@ -57,7 +72,7 @@ {% with heading_level = heading_level + extra_level %} {% for function in functions|order_members(config.members_order, members_list) %} {% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %} - {% if not function.is_alias or function.is_explicitely_exported %} + {% if not function.is_alias or function.is_explicitely_exported or function.inherited %} {% include function|get_template with context %} {% endif %} {% endif %} @@ -67,14 +82,19 @@ {% endwith %} {% if config.show_submodules %} - {% with modules = obj.modules|filter_objects(filters=config.filters, members_list=members_list, keep_no_docstrings=config.show_if_no_docstring) %} + {% with modules = obj.modules|filter_objects( + filters=config.filters, + members_list=members_list, + inherited_members=config.inherited_members, + keep_no_docstrings=config.show_if_no_docstring, + ) %} {% if modules %} {% if config.show_category_heading %} {% filter heading(heading_level, id=html_id ~ "-modules") %}Modules{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for module in modules|order_members(config.members_order, members_list) %} - {% if not module.is_alias or module.is_explicitely_exported %} + {% if not module.is_alias or module.is_explicitely_exported or module.inherited %} {% include module|get_template with context %} {% endif %} {% endfor %} @@ -87,32 +107,40 @@ {% else %} - {% for child in obj.members| - filter_objects(filters=config.filters, members_list=members_list, keep_no_docstrings=config.show_if_no_docstring)| - order_members(config.members_order, members_list) %} + {% for child in obj.all_members + |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) + %} {% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %} - {% if child.is_attribute %} - {% with attribute = child %} - {% include attribute|get_template with context %} - {% endwith %} + {% if not child.is_alias or child.is_explicitely_exported or child.inherited %} + {% if child.is_attribute %} + {% with attribute = child %} + {% include attribute|get_template with context %} + {% endwith %} - {% elif child.is_class %} - {% with class = child %} - {% include class|get_template with context %} - {% endwith %} + {% elif child.is_class %} + {% with class = child %} + {% include class|get_template with context %} + {% endwith %} - {% elif child.is_function %} - {% with function = child %} - {% include function|get_template with context %} - {% endwith %} + {% elif child.is_function %} + {% with function = child %} + {% include function|get_template with context %} + {% endwith %} - {% elif child.is_module and config.show_submodules %} - {% with module = child %} - {% include module|get_template with context %} - {% endwith %} + {% elif child.is_module and config.show_submodules %} + {% with module = child %} + {% include module|get_template with context %} + {% endwith %} + {% endif %} {% endif %} {% endif %} diff --git a/tests/conftest.py b/tests/conftest.py index b93200ba..b4f3e42e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,6 +18,9 @@ from mkdocstrings_handlers.python.handler import PythonHandler +pytest_plugins = ["griffe.tests"] + + @pytest.fixture(name="mkdocs_conf") def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[config.Config]: """Yield a MkDocs configuration object. diff --git a/tests/test_rendering.py b/tests/test_rendering.py index c504d4d0..5d35c121 100644 --- a/tests/test_rendering.py +++ b/tests/test_rendering.py @@ -7,6 +7,8 @@ from typing import TYPE_CHECKING, Any import pytest +from griffe.collections import ModulesCollection +from griffe.tests import temporary_visited_module from mkdocstrings_handlers.python import rendering @@ -48,6 +50,7 @@ def test_format_signature(name: Markup, signature: str) -> None: @dataclass class _FakeObject: name: str + inherited: bool = False @pytest.mark.parametrize( @@ -69,3 +72,62 @@ def test_filter_objects(names: list[str], filter_params: dict[str, Any], expecte filtered = rendering.do_filter_objects(objects, **filter_params) # type: ignore[arg-type] filtered_names = {obj.name for obj in filtered} assert set(filtered_names) == set(expected_names) + + +@pytest.mark.parametrize( + ("members", "inherited_members", "expected_names"), + [ + (True, True, {"base", "main"}), + (True, False, {"main"}), + (True, ["base"], {"base", "main"}), + (True, [], {"main"}), + (False, True, {"base"}), + (False, False, set()), + (False, ["base"], {"base"}), + (False, [], set()), + ([], True, {"base"}), + ([], False, set()), + ([], ["base"], {"base"}), + ([], [], set()), + (None, True, {"base", "main"}), + (None, False, {"main"}), + (None, ["base"], {"base", "main"}), + (None, [], {"main"}), + (["base"], True, {"base"}), + (["base"], False, set()), + (["base"], ["base"], {"base"}), + (["base"], [], set()), + (["main"], True, {"main"}), + (["main"], False, {"main"}), + (["main"], ["base"], {"base", "main"}), + (["main"], [], {"main"}), + ], +) +def test_filter_inherited_members( + members: bool | list[str] | None, + inherited_members: bool | list[str], + expected_names: list[str], +) -> None: + """Test inherited members filtering. + + Parameters: + members: Members option (parametrized). + inherited_members: Inherited members option (parametrized). + expected_names: The expected result as a list of member names. + """ + collection = ModulesCollection() + with temporary_visited_module( + """ + class Base: + def base(self): ... + + class Main(Base): + def main(self): ... + """, + modules_collection=collection, + ) as module: + collection["module"] = module + objects = module["Main"].all_members + filtered = rendering.do_filter_objects(objects, members_list=members, inherited_members=inherited_members) + names = {obj.name for obj in filtered} + assert names == expected_names From 5e1b854dbbd0eda79fdbf919f0a4c7798abaa27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Thu, 13 Jul 2023 20:27:58 +0200 Subject: [PATCH 08/13] chore: Template upgrade --- .copier-answers.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/dists.yml | 32 --------------- .github/workflows/release.yml | 45 +++++++++++++++++++++ config/ruff.toml | 2 +- duties.py | 19 +++++++-- pyproject.toml | 3 +- src/mkdocstrings_handlers/python/handler.py | 7 +--- 8 files changed, 66 insertions(+), 46 deletions(-) delete mode 100644 .github/workflows/dists.yml create mode 100644 .github/workflows/release.yml diff --git a/.copier-answers.yml b/.copier-answers.yml index 38ac3370..52bd8acf 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 0.15.23 +_commit: 0.16.2 _src_path: gh:pawamoy/copier-pdm author_email: pawamoy@pm.me author_fullname: Timothée Mazzucotelli diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index daa2b927..a1d63df6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push: pull_request: branches: - - main + - main defaults: run: diff --git a/.github/workflows/dists.yml b/.github/workflows/dists.yml deleted file mode 100644 index 99758277..00000000 --- a/.github/workflows/dists.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: dists - -on: push -permissions: - contents: write - -jobs: - build: - name: Build dists - runs-on: ubuntu-latest - if: github.repository_owner == 'pawamoy-insiders' - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup Python - uses: actions/setup-python@v3 - - name: Install build - run: python -m pip install build - - name: Build dists - run: python -m build - - name: Upload dists artifact - uses: actions/upload-artifact@v3 - with: - name: python-insiders - path: ./dist/* - - name: Create release and upload assets - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: ./dist/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..3dcc3fe4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,45 @@ +name: release + +on: push +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Fetch all tags + run: git fetch --depth=1 --tags + - name: Setup Python + uses: actions/setup-python@v4 + - name: Install build + if: github.repository_owner == 'pawamoy-insiders' + run: python -m pip install build + - name: Build dists + if: github.repository_owner == 'pawamoy-insiders' + run: python -m build + - name: Upload dists artifact + uses: actions/upload-artifact@v3 + if: github.repository_owner == 'pawamoy-insiders' + with: + name: python-insiders + path: ./dist/* + - name: Install git-changelog + if: github.repository_owner != 'pawamoy-insiders' + run: pip install git-changelog + - name: Prepare release notes + if: github.repository_owner != 'pawamoy-insiders' + run: git-changelog --release-notes > release-notes.md + - name: Create release with assets + uses: softprops/action-gh-release@v1 + if: github.repository_owner == 'pawamoy-insiders' + with: + files: ./dist/* + - name: Create release + uses: softprops/action-gh-release@v1 + if: github.repository_owner != 'pawamoy-insiders' + with: + body_path: release-notes.md diff --git a/config/ruff.toml b/config/ruff.toml index 56ad1c02..9925518c 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -1,4 +1,4 @@ -target-version = "py37" +target-version = "py38" line-length = 132 exclude = [ "fixtures", diff --git a/duties.py b/duties.py index 06a1048d..c8e616a4 100644 --- a/duties.py +++ b/duties.py @@ -109,6 +109,7 @@ def check_quality(ctx: Context) -> None: ctx.run( ruff.check(*PY_SRC_LIST, config="config/ruff.toml"), title=pyprefix("Checking code quality"), + command=f"ruff check --config config/ruff.toml {PY_SRC}", ) @@ -126,7 +127,11 @@ def check_dependencies(ctx: Context) -> None: allow_overrides=False, ) - ctx.run(safety.check(requirements), title="Checking dependencies") + ctx.run( + safety.check(requirements), + title="Checking dependencies", + command="pdm export -f requirements --without-hashes | safety check --stdin", + ) @duty @@ -138,7 +143,12 @@ def check_docs(ctx: Context) -> None: """ Path("htmlcov").mkdir(parents=True, exist_ok=True) Path("htmlcov/index.html").touch(exist_ok=True) - ctx.run(mkdocs.build(strict=True, config_file=mkdocs_config()), title=pyprefix("Building documentation")) + config = mkdocs_config() + ctx.run( + mkdocs.build(strict=True, config_file=config, verbose=True), + title=pyprefix("Building documentation"), + command=f"mkdocs build -vsf {config}", + ) @duty @@ -152,6 +162,7 @@ def check_types(ctx: Context) -> None: ctx.run( mypy.run(*PY_SRC_LIST, config_file="config/mypy.ini"), title=pyprefix("Type-checking"), + command=f"mypy --config-file config/mypy.ini {PY_SRC}", ) @@ -166,8 +177,9 @@ def check_api(ctx: Context) -> None: griffe_check = lazy(g_check, name="griffe.check") ctx.run( - griffe_check("mkdocstrings_handlers", search_paths=["src"]), + griffe_check("mkdocstrings_handlers", search_paths=["src"], color=True), title="Checking for API breaking changes", + command="griffe check -ssrc mkdocstrings_handlers", nofail=True, ) @@ -301,4 +313,5 @@ def test(ctx: Context, match: str = "") -> None: ctx.run( pytest.run("-n", "auto", "tests", config_file="config/pytest.ini", select=match, color="yes"), title=pyprefix("Running tests"), + command=f"pytest -c config/pytest.ini -n auto -k{match!r} --color=yes tests", ) diff --git a/pyproject.toml b/pyproject.toml index f18cae03..ab51fb01 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ description = "A Python handler for mkdocstrings." authors = [{name = "Timothée Mazzucotelli", email = "pawamoy@pm.me"}] license = {text = "ISC"} readme = "README.md" -requires-python = ">=3.7" +requires-python = ">=3.8" keywords = [] dynamic = ["version"] classifiers = [ @@ -17,7 +17,6 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index be293591..a0a86c8b 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -15,6 +15,7 @@ from griffe.collections import LinesCollection, ModulesCollection from griffe.docstrings.parsers import Parser from griffe.exceptions import AliasResolutionError +from griffe.extensions import load_extensions from griffe.loader import GriffeLoader from griffe.logger import patch_loggers from mkdocstrings.extension import PluginError @@ -24,12 +25,6 @@ from mkdocstrings_handlers.python import rendering -try: - from griffe.extensions import load_extensions -except ImportError: - # TODO: remove once support for Griffe 0.25 is dropped - from griffe.agents.extensions import load_extensions # type: ignore[no-redef] - if TYPE_CHECKING: from markdown import Markdown From b053b2900ef5c0069b68ad19bda9aaa98141a525 Mon Sep 17 00:00:00 2001 From: Nyuan Zhang Date: Fri, 14 Jul 2023 02:32:39 +0800 Subject: [PATCH 09/13] feat: Setup infrastructure for I18N, add translations for simplified chinese and japanese PR #77: https://github.com/mkdocstrings/python/pull/77 --- src/mkdocstrings_handlers/python/handler.py | 15 +++++++++- .../material/_base/docstring/attributes.html | 17 ++++++----- .../material/_base/docstring/examples.html | 5 +++- .../_base/docstring/other_parameters.html | 19 +++++++------ .../material/_base/docstring/parameters.html | 25 +++++++++-------- .../material/_base/docstring/raises.html | 15 ++++++---- .../material/_base/docstring/receives.html | 19 +++++++------ .../material/_base/docstring/returns.html | 19 +++++++------ .../material/_base/docstring/warns.html | 15 ++++++---- .../material/_base/docstring/yields.html | 19 +++++++------ .../templates/material/_base/function.html | 4 ++- .../material/_base/languages/en.html | 28 +++++++++++++++++++ .../material/_base/languages/ja.html | 28 +++++++++++++++++++ .../material/_base/languages/zh.html | 28 +++++++++++++++++++ .../python/templates/material/language.html | 10 +++++++ .../templates/material/languages/en.html | 1 + .../templates/material/languages/ja.html | 1 + .../templates/material/languages/zh.html | 1 + .../readthedocs/docstring/attributes.html | 5 +++- .../docstring/other_parameters.html | 5 +++- .../readthedocs/docstring/parameters.html | 5 +++- .../readthedocs/docstring/raises.html | 5 +++- .../readthedocs/docstring/receives.html | 5 +++- .../readthedocs/docstring/returns.html | 5 +++- .../readthedocs/docstring/warns.html | 5 +++- .../readthedocs/docstring/yields.html | 5 +++- .../templates/readthedocs/language.html | 10 +++++++ .../templates/readthedocs/languages/en.html | 11 ++++++++ .../templates/readthedocs/languages/ja.html | 11 ++++++++ .../templates/readthedocs/languages/zh.html | 11 ++++++++ tests/test_handler.py | 3 +- 31 files changed, 281 insertions(+), 74 deletions(-) create mode 100644 src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html create mode 100644 src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html create mode 100644 src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html create mode 100644 src/mkdocstrings_handlers/python/templates/material/language.html create mode 100644 src/mkdocstrings_handlers/python/templates/material/languages/en.html create mode 100644 src/mkdocstrings_handlers/python/templates/material/languages/ja.html create mode 100644 src/mkdocstrings_handlers/python/templates/material/languages/zh.html create mode 100644 src/mkdocstrings_handlers/python/templates/readthedocs/language.html create mode 100644 src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html create mode 100644 src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html create mode 100644 src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index be293591..ed44bf3c 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -187,6 +187,7 @@ def __init__( *args: Any, config_file_path: str | None = None, paths: list[str] | None = None, + locale: str = "en", **kwargs: Any, ) -> None: """Initialize the handler. @@ -195,6 +196,7 @@ def __init__( *args: Handler name, theme and custom templates. config_file_path: The MkDocs configuration file path. paths: A list of paths to use as Griffe search paths. + locale: The locale to use when rendering content. **kwargs: Same thing, but with keyword arguments. """ super().__init__(*args, **kwargs) @@ -215,6 +217,7 @@ def __init__( self._paths = search_paths self._modules_collection: ModulesCollection = ModulesCollection() self._lines_collection: LinesCollection = LinesCollection() + self._locale = locale @classmethod def load_inventory( @@ -328,7 +331,13 @@ def render(self, data: CollectorItem, config: Mapping[str, Any]) -> str: # noqa final_config["signature_crossrefs"] = False return template.render( - **{"config": final_config, data.kind.value: data, "heading_level": heading_level, "root": True}, + **{ + "config": final_config, + data.kind.value: data, + "heading_level": heading_level, + "root": True, + "locale": self._locale, + }, ) def update_env(self, md: Markdown, config: dict) -> None: # noqa: D102 (ignore missing docstring) @@ -344,6 +353,7 @@ def update_env(self, md: Markdown, config: dict) -> None: # noqa: D102 (ignore self.env.filters["filter_objects"] = rendering.do_filter_objects self.env.filters["stash_crossref"] = lambda ref, length: ref self.env.filters["get_template"] = rendering.do_get_template + self.env.tests["existing_template"] = lambda template_name: template_name in self.env.list_templates() def get_anchors(self, data: CollectorItem) -> set[str]: # noqa: D102 (ignore missing docstring) try: @@ -357,6 +367,7 @@ def get_handler( custom_templates: str | None = None, config_file_path: str | None = None, paths: list[str] | None = None, + locale: str = "en", **config: Any, # noqa: ARG001 ) -> PythonHandler: """Simply return an instance of `PythonHandler`. @@ -366,6 +377,7 @@ def get_handler( custom_templates: Directory containing custom templates. config_file_path: The MkDocs configuration file path. paths: A list of paths to use as Griffe search paths. + locale: The locale to use when rendering content. **config: Configuration passed to the handler. Returns: @@ -377,4 +389,5 @@ def get_handler( custom_templates=custom_templates, config_file_path=config_file_path, paths=paths, + locale=locale, ) 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 20487f20..296f1557 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html @@ -1,13 +1,16 @@ {{ log.debug("Rendering attributes section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} -

{{ section.title or "Attributes:" }}

+

{{ section.title or lang.t("Attributes:") }}

- - - + + + @@ -33,7 +36,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Attributes:" }}

+

{{ section.title or lang.t("Attributes:") }}

    {% for attribute in section.value %}
  • @@ -56,8 +59,8 @@
NameTypeDescription{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}
- - + + 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 54bbfa5d..bbec5e22 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/examples.html @@ -1,5 +1,8 @@ {{ log.debug("Rendering examples section") }} -

{{ section.title or "Examples:" }}

+ +{% import "language.html" as lang with context %} + +

{{ section.title or lang.t("Examples:") }}

{% for section_type, sub_section in section.value %} {% if section_type.value == "text" %} {{ sub_section|convert_markdown(heading_level, html_id) }} 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 82fc493c..a8ccbd9a 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,13 +1,16 @@ {{ log.debug("Rendering other parameters section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} -

{{ section.title or "Other Parameters:" }}

+

{{ section.title or lang.t("Other Parameters:") }}

{{ (section.title or "ATTRIBUTE").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("ATTRIBUTE")).rstrip(":").upper() }}{{ lang.t("DESCRIPTION") }}
- - - + + + @@ -33,7 +36,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Other Parameters:" }}

+

{{ section.title or lang.t("Other Parameters:") }}

    {% for parameter in section.value %}
  • @@ -56,8 +59,8 @@
NameTypeDescription{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}
- - + + @@ -71,7 +74,7 @@

{% if parameter.annotation %} - TYPE: + {{ lang.t("TYPE:") }} {% with expression = parameter.annotation %} {% include "expression.html" 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 b2b57509..515be812 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html @@ -1,14 +1,17 @@ {{ log.debug("Rendering parameters section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} -

{{ section.title or "Parameters:" }}

+

{{ section.title or lang.t("Parameters:") }}

{{ (section.title or "PARAMETER").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("PARAMETER")).rstrip(":").upper() }}{{ lang.t("DESCRIPTION") }}
- - - - + + + + @@ -33,7 +36,7 @@ {% include "expression.html" with context %} {% endwith %} {% else %} - required + {{ lang.t("required") }} {% endif %} @@ -43,7 +46,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Parameters:" }}

+

{{ section.title or lang.t("Parameters:") }}

    {% for parameter in section.value %}
  • @@ -66,8 +69,8 @@
NameTypeDescriptionDefault{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}{{ lang.t("Default") }}
- - + + @@ -81,7 +84,7 @@

{% if parameter.annotation %} - TYPE: + {{ lang.t("TYPE:") }} {% with expression = parameter.annotation %} {% include "expression.html" with context %} {% endwith %} @@ -89,7 +92,7 @@ {% endif %} {% if parameter.default %} - DEFAULT: + {{ lang.t("DEFAULT:") }} {% with expression = parameter.default %} {% include "expression.html" 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 45832d1c..e4edc66a 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html @@ -1,12 +1,15 @@ {{ log.debug("Rendering raises section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} -

{{ section.title or "Raises:" }}

+

{{ section.title or lang.t("Raises:") }}

{{ (section.title or "PARAMETER").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("PARAMETER")).rstrip(":").upper() }} {{ lang.t("DESCRIPTION") }}
- - + + @@ -31,7 +34,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Raises:" }}

+

{{ lang.t(section.title) or lang.t("Raises:") }}

    {% for raises in section.value %}
  • @@ -53,8 +56,8 @@
TypeDescription{{ lang.t("Type") }}{{ lang.t("Description") }}
- - + + 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 03b241cb..09b8caed 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html @@ -1,14 +1,17 @@ {{ log.debug("Rendering receives section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} {% set name_column = section.value|selectattr("name")|any %} -

{{ section.title or "Receives:" }}

+

{{ section.title or lang.t("Receives:") }}

{{ (section.title or "RAISES").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("RAISES")).rstrip(":").upper() }}{{ lang.t("DESCRIPTION") }}
- {% if name_column %}{% endif %} - - + {% if name_column %}{% endif %} + + @@ -34,7 +37,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Receives:" }}

+

{{ section.title or lang.t("Receives:") }}

    {% for receives in section.value %}
  • @@ -59,8 +62,8 @@
NameTypeDescription{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}
- - + + @@ -84,7 +87,7 @@ {% if receives.name and receives.annotation %}

- TYPE: + {{ lang.t("TYPE:") }} {% with expression = receives.annotation %} {% include "expression.html" 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 ad63db83..374f8de4 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html @@ -1,14 +1,17 @@ {{ log.debug("Rendering returns section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} {% set name_column = section.value|selectattr("name")|any %} -

{{ section.title or "Returns:" }}

+

{{ section.title or lang.t("Returns:") }}

{{ (section.title or "RECEIVES").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("RECEIVES")).rstrip(":").upper()) }}{{ lang.t("DESCRIPTION") }}
- {% if name_column %}{% endif %} - - + {% if name_column %}{% endif %} + + @@ -34,7 +37,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Returns:" }}

+

{{ section.title or lang.t("Returns:") }}

    {% for returns in section.value %}
  • @@ -59,8 +62,8 @@
NameTypeDescription{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}
- - + + @@ -84,7 +87,7 @@ {% if returns.name and returns.annotation %}

- TYPE: + {{ lang.t("TYPE:") }} {% with expression = returns.annotation %} {% include "expression.html" 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 49ae4380..cf1cc4a6 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html @@ -1,12 +1,15 @@ {{ log.debug("Rendering warns section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} -

{{ section.title or "Warns:" }}

+

{{ section.title or lang.t("Warns:") }}

{{ (section.title or "RETURNS").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("RETURNS")).rstrip(":").upper() }}{{ lang.t("DESCRIPTION").upper() }}
- - + + @@ -31,7 +34,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Warns:" }}

+

{{ section.title or lang.t("Warns:") }}

    {% for warns in section.value %}
  • @@ -53,8 +56,8 @@
TypeDescription{{ lang.t("Type") }}{{ lang.t("Description") }}
- - + + 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 93b3cfd2..9a0db29c 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html @@ -1,14 +1,17 @@ {{ log.debug("Rendering yields section") }} + +{% import "language.html" as lang with context %} + {% if config.docstring_section_style == "table" %} {% block table_style %} {% set name_column = section.value|selectattr("name")|any %} -

{{ section.title or "Yields:" }}

+

{{ section.title or lang.t("Yields:") }}

{{ (section.title or "WARNS").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("WARNS")).rstrip(":").upper() }}{{ lang.t("DESCRIPTION") }}
- {% if name_column %}{% endif %} - - + {% if name_column %}{% endif %} + + @@ -34,7 +37,7 @@ {% endblock table_style %} {% elif config.docstring_section_style == "list" %} {% block list_style %} -

{{ section.title or "Yields:" }}

+

{{ section.title or lang.t("Yields:") }}

    {% for yields in section.value %}
  • @@ -59,8 +62,8 @@
NameTypeDescription{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}
- - + + @@ -84,7 +87,7 @@ {% if yields.name and yields.annotation %}

- TYPE: + {{ lang.t("TYPE:") }}: {% with expression = yields.annotation %} {% include "expression.html" with context %} {% endwith %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html b/src/mkdocstrings_handlers/python/templates/material/_base/function.html index 70c26892..4ae53337 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html @@ -1,5 +1,7 @@ {{ log.debug("Rendering " + function.path) }} +{% import "language.html" as lang with context %} +

{% with html_id = function.path %} @@ -61,7 +63,7 @@ {% if config.show_source and function.source %}
- Source code in {{ function.relative_filepath }} + {{ lang.t("Source code in") }} {{ function.relative_filepath }} {{ function.source|highlight(language="python", linestart=function.lineno, linenums=True) }}
{% 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 new file mode 100644 index 00000000..5836cccf --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/en.html @@ -0,0 +1,28 @@ + +{% macro t(key) %}{{ { + "ATTRIBUTE": "ATTRIBUTE", + "Attributes:": "Attributes:", + "DEFAULT:": "DEFAULT:", + "Default": "Default", + "DESCRIPTION": "DESCRIPTION", + "Description": "Description", + "Examples:": "Examples:", + "Name": "Name", + "Other Parameters:": "Other Parameters:", + "PARAMETER": "PARAMETER", + "Parameters:": "Parameters:", + "RAISES": "RAISES", + "Raises:" : "Raises:", + "RECEIVES": "RECEIVES", + "Receives:": "Receives:", + "required": "required", + "RETURNS": "RETURNS", + "Returns:": "Returns:", + "Source code in": "Source code in", + "TYPE:": "TYPE:", + "Type": "Type", + "WARNS": "WARNS", + "Warns:": "Warns:", + "YIELDS": "YIELDS", + "Yields:": "Yields:", + }[key] }}{% endmacro %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html new file mode 100644 index 00000000..6b52ebcd --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/ja.html @@ -0,0 +1,28 @@ + +{% macro t(key) %}{{ { + "ATTRIBUTE": "属性", + "Attributes:": "属性:", + "DEFAULT:": "デフォルト:", + "Default": "デフォルト", + "DESCRIPTION": "デスクリプション", + "Description": "デスクリプション", + "Examples:": "例:", + "Name": "名前", + "Other Parameters:": "他の引数:", + "PARAMETER": "引数", + "Parameters:": "引数:", + "RAISES": "発生", + "Raises:" : "発生:", + "RECEIVES": "取得", + "Receives:": "取得:", + "required": "必須", + "RETURNS": "戻り値", + "Returns:": "戻り値:", + "Source code in": "ソースコード位置:", + "TYPE:": "タイプ:", + "Type": "タイプ", + "WARNS": "警告", + "Warns:": "警告:", + "YIELDS": "返す", + "Yields:": "返す:", +}[key] }}{% endmacro %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html new file mode 100644 index 00000000..a1516f15 --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/material/_base/languages/zh.html @@ -0,0 +1,28 @@ + +{% macro t(key) %}{{ { + "ATTRIBUTE": "属性", + "Attributes:": "属性:", + "DEFAULT:": "默认:", + "Default": "默认", + "DESCRIPTION": "描述", + "Description": "描述", + "Examples:": "示例:", + "Name": "名称", + "Other Parameters:": "其他参数:", + "PARAMETER": "参数", + "Parameters:": "参数:", + "RAISES": "引发", + "Raises:" : "引发:", + "Receives:": "接收:", + "RECEIVES": "接收", + "required": "必需", + "RETURNS": "返回", + "Returns:": "返回:", + "Source code in": "源代码位于:", + "TYPE:": "类型:", + "Type": "类型", + "Warns:": "警告:", + "WARNS": "警告", + "YIELDS": "产生", + "Yields:": "产生:", + }[key] }}{% endmacro %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/material/language.html b/src/mkdocstrings_handlers/python/templates/material/language.html new file mode 100644 index 00000000..26647ff3 --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/material/language.html @@ -0,0 +1,10 @@ + +{% set lang_pth = "languages/" ~ locale ~ ".html" %} +{% if lang_pth is existing_template %} + {% import lang_pth as lang %} + {% import "languages/en.html" as fallback %} + {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %} +{% else %} + {% import "languages/en.html" as lang %} + {% macro t(key) %}{{ lang.t(key) }}{% endmacro %} +{% endif %} diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/en.html b/src/mkdocstrings_handlers/python/templates/material/languages/en.html new file mode 100644 index 00000000..eab0a3f3 --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/material/languages/en.html @@ -0,0 +1 @@ +{% extends "_base/languages/en.html" %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/ja.html b/src/mkdocstrings_handlers/python/templates/material/languages/ja.html new file mode 100644 index 00000000..0463322d --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/material/languages/ja.html @@ -0,0 +1 @@ +{% extends "_base/languages/ja.html" %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/material/languages/zh.html b/src/mkdocstrings_handlers/python/templates/material/languages/zh.html new file mode 100644 index 00000000..90aeae6f --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/material/languages/zh.html @@ -0,0 +1 @@ +{% extends "_base/languages/zh.html" %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html index 3ed566d5..6f597cd1 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/attributes.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} +
{{ (section.title or "YIELDS").rstrip(":").upper() }}DESCRIPTION{{ (section.title or lang.t("YIELDS")).rstrip(":").upper() }}{{ lang.t("DESCRIPTION") }}
@@ -6,7 +9,7 @@ - +
{{ section.title or "Attributes:" }}{{ section.title or lang.t("Attributes:") }}
    {% for attribute in section.value %} 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 c5b4b039..d37bc8cb 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/other_parameters.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} + @@ -6,7 +9,7 @@ - +
    {{ section.title or "Other parameters:" }}{{ section.title or lang.t("Other parameters:") }}
      {% for parameter in section.value %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html index b05733a7..461fe2a1 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/parameters.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} + @@ -6,7 +9,7 @@ - +
      {{ section.title or "Parameters:" }}{{ section.title or lang.t("Parameters:") }}
        {% for parameter in section.value %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html index b744df22..f82437dd 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/raises.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} + @@ -6,7 +9,7 @@ - +
        {{ section.title or "Raises:" }}{{ section.title or lang.t("Raises:") }}
          {% for raises in section.value %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html index 127bcd3c..f112351d 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/receives.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} + @@ -6,7 +9,7 @@ - +
          {{ section.title or "Receives:" }}{{ section.title or lang.t("Receives:") }}
            {% for receives in section.value %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html index 92f29e31..28b83774 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/returns.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} + @@ -6,7 +9,7 @@ - +
            {{ section.title or "Returns:" }}{{ section.title or lang.t("Returns:") }}
              {% for returns in section.value %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html index 12631784..35aff0b1 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/warns.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} + @@ -6,7 +9,7 @@ - +
              {{ section.title or "Warns:" }}{{ section.title or lang.t("Warns:") }}
                {% for warns in section.value %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html index 86e8ff7b..7838a66a 100644 --- a/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/docstring/yields.html @@ -1,4 +1,7 @@ {{ log.debug() }} + +{% import "language.html" as lang with context %} + @@ -6,7 +9,7 @@ - +
                {{ section.title or "Yields:" }}{{ section.title or lang.t("Yields:") }}
                  {% for yields in section.value %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/language.html b/src/mkdocstrings_handlers/python/templates/readthedocs/language.html new file mode 100644 index 00000000..26647ff3 --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/language.html @@ -0,0 +1,10 @@ + +{% set lang_pth = "languages/" ~ locale ~ ".html" %} +{% if lang_pth is existing_template %} + {% import lang_pth as lang %} + {% import "languages/en.html" as fallback %} + {% macro t(key) %}{{ lang.t(key) or fallback.t(key) }}{% endmacro %} +{% else %} + {% import "languages/en.html" as lang %} + {% macro t(key) %}{{ lang.t(key) }}{% endmacro %} +{% endif %} diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html new file mode 100644 index 00000000..acc6d5a7 --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/en.html @@ -0,0 +1,11 @@ + +{% macro t(key) %}{{ { + "Attributes:": "Attributes:", + "Other parameters:": "Other parameters:", + "Parameters:": "Parameters:", + "Raises:" : "Raises:", + "Receives:": "Receives:", + "Returns:": "Returns:", + "Warns:": "Warns:", + "Yields:": "Yields:", + }[key] }}{% endmacro %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html new file mode 100644 index 00000000..9ae4a568 --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/ja.html @@ -0,0 +1,11 @@ + +{% macro t(key) %}{{ { + "Attributes:": "属性:", + "Other Parameters:": "他の引数:", + "Parameters:": "引数:", + "Raises:" : "発生:", + "Receives:": "取得:", + "Returns:": "戻り値:", + "Warns:": "警告:", + "Yields:": "返す:", + }[key] }}{% endmacro %} \ No newline at end of file diff --git a/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html new file mode 100644 index 00000000..42184f9c --- /dev/null +++ b/src/mkdocstrings_handlers/python/templates/readthedocs/languages/zh.html @@ -0,0 +1,11 @@ + +{% macro t(key) %}{{ { + "Attributes:": "属性:", + "Other Parameters:": "其他参数:", + "Parameters:": "参数:", + "Raises:" : "引发:", + "Receives:": "接收:", + "Returns:": "返回:", + "Warns:": "警告:", + "Yields:": "产生:", + }[key] }}{% endmacro %} \ No newline at end of file diff --git a/tests/test_handler.py b/tests/test_handler.py index fc31942c..4971e132 100644 --- a/tests/test_handler.py +++ b/tests/test_handler.py @@ -63,7 +63,8 @@ def test_render_docstring_examples_section(handler: PythonHandler) -> None: ], ) template = handler.env.get_template("docstring/examples.html") - rendered = template.render(section=section) + rendered = template.render(section=section, locale="en") + template.render(section=section, locale="not_existing") assert "

                  This is an example.

                  " in rendered assert "print" in rendered assert "Hello" in rendered From 7d5b6650ea159a51272eaa022b29d5972a594630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Thu, 13 Jul 2023 20:33:04 +0200 Subject: [PATCH 10/13] docs: Fix usage index --- docs/usage/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/usage/index.md b/docs/usage/index.md index 6fb703e6..670f6e57 100644 --- a/docs/usage/index.md +++ b/docs/usage/index.md @@ -200,6 +200,7 @@ in the following pages: ::: mkdocstrings_handlers.python.handler.PythonHandler.default_config options: + show_root_heading: false show_root_toc_entry: false ## Finding modules From 3d8724ed1f4d040d7a3d9d02784cf0d1f80445b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Thu, 13 Jul 2023 20:37:53 +0200 Subject: [PATCH 11/13] fix: Don't show `None` as return annotation of class signatures Issue #85: https://github.com/mkdocstrings/python/issues/85 --- .../python/templates/material/_base/signature.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html index ea642f51..3ea0f91e 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/signature.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/signature.html @@ -55,7 +55,10 @@ {%- endif -%} {%- endfor -%} ) - {%- if config.show_signature_annotations and function.annotation %} -> {% if config.separate_signature and config.signature_crossrefs -%} + {%- if config.show_signature_annotations + and function.annotation + and not (config.merge_init_into_class and function.name == "__init__" ) + %} -> {% if config.separate_signature and config.signature_crossrefs -%} {%- with expression = function.annotation %}{% include "expression.html" with context %}{%- endwith -%} {%- else -%} {{ function.annotation|safe }} From 299fe483cc03ba76df29b843f88467f89db6dc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 14 Jul 2023 19:31:55 +0200 Subject: [PATCH 12/13] feat: Add Jinja blocks to module, class, function and attribute templates --- docs/usage/customization.md | 96 ++++++++++--- .../templates/material/_base/attribute.html | 56 +++++--- .../templates/material/_base/class.html | 131 ++++++++++-------- .../templates/material/_base/function.html | 62 +++++---- .../templates/material/_base/module.html | 50 ++++--- 5 files changed, 253 insertions(+), 142 deletions(-) diff --git a/docs/usage/customization.md b/docs/usage/customization.md index 7fb0cae5..0dd5397f 100644 --- a/docs/usage/customization.md +++ b/docs/usage/customization.md @@ -69,33 +69,97 @@ for filepath in sorted(path for path in Path(basedir).rglob("*") if "_base" not See them [in the repository](https://github.com/mkdocstrings/python/tree/master/src/mkdocstrings_handlers/python/templates/). See the general *mkdocstrings* documentation to learn how to override them: https://mkdocstrings.github.io/theming/#templates. -In preparation for Jinja2 blocks, which will improve customization, -each one of these templates extends a base version in `theme/_base`. Example: +Each one of these templates extends a base version in `theme/_base`. Example: -```html+jinja title="theme/docstring/admonition.html" -{% extends "_base/docstring/admonition.html" %} +```html+jinja title="theme/class.html" +{% extends "_base/class.html" %} ``` -```html+jinja title="theme/_base/docstring/admonition.html" -{{ log.debug() }} -
                  - {{ section.title|convert_markdown(heading_level, html_id, strip_paragraph=True) }} - {{ section.value.contents|convert_markdown(heading_level, html_id) }} -
                  -``` - -It means you will be able to customize only *parts* of a template +Some of these templates define [Jinja blocks](https://jinja.palletsprojects.com/en/3.0.x/templates/#template-inheritance). +allowing to customize only *parts* of a template without having to fully copy-paste it into your project: -```jinja title="templates/theme/docstring.html" -{% extends "_base/docstring.html" %} +```jinja title="templates/theme/class.html" +{% extends "_base/class.html" %} {% block contents %} {{ block.super }} Additional contents {% endblock contents %} ``` -WARNING: **Block-level customization is not ready yet. We welcome [suggestions](https://github.com/mkdocstrings/python/issues/new).** +### Available blocks + +Only the templates for the **Material for MkDocs** provide Jinja blocks. +The following tables show the block names, description, +and the Jinja context available in their scope. + +#### `module.html` + +- `heading`: The module heading. +- `labels`: The module labels. +- `contents`: The module contents: docstring and children blocks. +- `docstring`: The module docstring. +- `children`: The module children. + +Available context: + +- `config`: The handler configuration (dictionary). +- `module`: The [Module][griffe.dataclasses.Module] instance. + +#### `class.html` + +- `heading`: The class heading. +- `labels`: The class labels. +- `signature`: The class signature. +- `contents`: The class contents: bases, docstring, source and children blocks. +- `bases`: The class bases. +- `docstring`: The class docstring. +- `source`: The class source code. +- `children`: The class children. + +Available context: + +- `config`: The handler configuration (dictionary). +- `class`: The [Class][griffe.dataclasses.Class] instance. + +#### `function.html` + +- `heading`: The function heading. +- `labels`: The function labels. +- `signature`: The function signature. +- `contents`: The function contents: docstring and source blocks. +- `docstring`: The function docstring. +- `source`: The function source code. + +Available context: + +- `config`: The handler configuration (dictionary). +- `function`: The [Function][griffe.dataclasses.Function] instance. + +#### `attribute.html` + +- `heading`: The attribute heading. +- `labels`: The attribute labels. +- `signature`: The attribute signature. +- `contents`: The attribute contents: docstring block. +- `docstring`: The attribute docstring. + +Available context: + +- `config`: The handler configuration (dictionary). +- `function`: The [Attribute][griffe.dataclasses.Attribute] instance. + +#### Docstring sections + +In `docstring/attributes.html`, `docstring/other_parameters.html`, `docstring/parameters.html`, `docstring/raises.html`, `docstring/receives.html`, `docstring/returns.html`, `docstring/warns.html`, and `docstring/yields.html`: + +- `table_style`: The section as a table. +- `list_style`: The section as a list. +- `spacy_style`: The section as a Spacy table. + +Available context: + +- `section`: The [DocstringSection][griffe.docstrings.dataclasses.DocstringSection] instance (see `DocstringSection*` subclasses). ## Style recommendations diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html index 019e7fae..42fd4824 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/attribute.html @@ -21,31 +21,37 @@ class="doc doc-heading", toc_label=attribute.name) %} - {% if config.separate_signature %} - {% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %} - {% else %} - {% filter highlight(language="python", inline=True) %} - {% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %} - {% if attribute.annotation %}: {{ attribute.annotation }}{% endif %} - {% if attribute.value %} = {{ attribute.value }}{% endif %} - {% endfilter %} - {% endif %} + {% block heading scoped %} + {% if config.separate_signature %} + {% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %} + {% else %} + {% filter highlight(language="python", inline=True) %} + {% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %} + {% if attribute.annotation %}: {{ attribute.annotation }}{% endif %} + {% if attribute.value %} = {{ attribute.value }}{% endif %} + {% endfilter %} + {% endif %} + {% endblock heading %} - {% with labels = attribute.labels %} - {% include "labels.html" with context %} - {% endwith %} + {% block labels scoped %} + {% with labels = attribute.labels %} + {% include "labels.html" with context %} + {% endwith %} + {% endblock labels %} {% endfilter %} - {% if config.separate_signature %} - {% filter highlight(language="python", inline=False) %} - {% filter format_code(config.line_length) %} - {% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %} - {% if attribute.annotation %}: {{ attribute.annotation|safe }}{% endif %} - {% if attribute.value %} = {{ attribute.value|safe }}{% endif %} + {% block signature scoped %} + {% if config.separate_signature %} + {% filter highlight(language="python", inline=False) %} + {% filter format_code(config.line_length) %} + {% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %} + {% if attribute.annotation %}: {{ attribute.annotation|safe }}{% endif %} + {% if attribute.value %} = {{ attribute.value|safe }}{% endif %} + {% endfilter %} {% endfilter %} - {% endfilter %} - {% endif %} + {% endif %} + {% endblock signature %} {% else %} {% if config.show_root_toc_entry %} @@ -60,9 +66,13 @@ {% endif %}
                  - {% with docstring_sections = attribute.docstring.parsed %} - {% include "docstring.html" with context %} - {% endwith %} + {% block contents scoped %} + {% block docstring scoped %} + {% with docstring_sections = attribute.docstring.parsed %} + {% include "docstring.html" with context %} + {% endwith %} + {% endblock docstring %} + {% endblock contents %}
                  {% endwith %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html b/src/mkdocstrings_handlers/python/templates/material/_base/class.html index 3f6248fb..e035d1f5 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html @@ -21,34 +21,40 @@ class="doc doc-heading", toc_label=class.name) %} - {% if config.separate_signature %} - {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} - {% elif config.merge_init_into_class and "__init__" in class.members -%} - {%- with function = class.members["__init__"] -%} - {%- filter highlight(language="python", inline=True) -%} - {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} - {%- include "signature.html" with context -%} - {%- endfilter -%} - {%- endwith -%} - {% else %} - {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} - {% endif %} + {% block heading scoped %} + {% if config.separate_signature %} + {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} + {% elif config.merge_init_into_class and "__init__" in class.members -%} + {%- with function = class.members["__init__"] -%} + {%- filter highlight(language="python", inline=True) -%} + {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} + {%- include "signature.html" with context -%} + {%- endfilter -%} + {%- endwith -%} + {% else %} + {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} + {% endif %} + {% endblock heading %} - {% with labels = class.labels %} - {% include "labels.html" with context %} - {% endwith %} + {% block labels scoped %} + {% with labels = class.labels %} + {% include "labels.html" with context %} + {% endwith %} + {% endblock labels %} {% endfilter %} - {% if config.separate_signature and config.merge_init_into_class %} - {% if "__init__" in class.members %} - {% with function = class.members["__init__"] %} - {% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %} - {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} - {% endfilter %} - {% endwith %} + {% block signature scoped %} + {% if config.separate_signature and config.merge_init_into_class %} + {% if "__init__" in class.members %} + {% with function = class.members["__init__"] %} + {% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %} + {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} + {% endfilter %} + {% endwith %} + {% endif %} {% endif %} - {% endif %} + {% endblock signature %} {% else %} {% if config.show_root_toc_entry %} @@ -63,47 +69,56 @@ {% endif %}
                  - {% if config.show_bases and class.bases %} -

                  - Bases: {% for expression in class.bases -%} - {% include "expression.html" with context %}{% if not loop.last %}, {% endif %} - {% endfor -%} -

                  - {% endif %} - - {% with docstring_sections = class.docstring.parsed %} - {% include "docstring.html" with context %} - {% endwith %} + {% block contents scoped %} + {% block bases scoped %} + {% if config.show_bases and class.bases %} +

                  + Bases: {% for expression in class.bases -%} + {% include "expression.html" with context %}{% if not loop.last %}, {% endif %} + {% endfor -%} +

                  + {% endif %} + {% endblock bases %} - {% if config.merge_init_into_class %} - {% if "__init__" in class.members and class.members["__init__"].has_docstring %} - {% with docstring_sections = class.members["__init__"].docstring.parsed %} + {% block docstring scoped %} + {% with docstring_sections = class.docstring.parsed %} {% include "docstring.html" with context %} {% endwith %} - {% endif %} - {% endif %} + {% if config.merge_init_into_class %} + {% if "__init__" in class.members and class.members["__init__"].has_docstring %} + {% with docstring_sections = class.members["__init__"].docstring.parsed %} + {% include "docstring.html" with context %} + {% endwith %} + {% endif %} + {% endif %} + {% endblock docstring %} - {% if config.show_source %} - {% if config.merge_init_into_class %} - {% if "__init__" in class.members and class.members["__init__"].source %} -
                  - Source code in {{ class.relative_filepath }} - {{ class.members["__init__"].source|highlight(language="python", linestart=class.members["__init__"].lineno, linenums=True) }} -
                  + {% block source scoped %} + {% if config.show_source %} + {% if config.merge_init_into_class %} + {% if "__init__" in class.members and class.members["__init__"].source %} +
                  + Source code in {{ class.relative_filepath }} + {{ class.members["__init__"].source|highlight(language="python", linestart=class.members["__init__"].lineno, linenums=True) }} +
                  + {% endif %} + {% elif class.source %} +
                  + Source code in {{ class.relative_filepath }} + {{ class.source|highlight(language="python", linestart=class.lineno, linenums=True) }} +
                  + {% endif %} {% endif %} - {% elif class.source %} -
                  - Source code in {{ class.relative_filepath }} - {{ class.source|highlight(language="python", linestart=class.lineno, linenums=True) }} -
                  - {% endif %} - {% endif %} + {% endblock source %} - {% with obj = class %} - {% set root = False %} - {% set heading_level = heading_level + 1 %} - {% include "children.html" with context %} - {% endwith %} + {% block children scoped %} + {% with obj = class %} + {% set root = False %} + {% set heading_level = heading_level + 1 %} + {% include "children.html" with context %} + {% endwith %} + {% endblock children %} + {% endblock contents %}
                  {% endwith %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/function.html b/src/mkdocstrings_handlers/python/templates/material/_base/function.html index 4ae53337..4290b115 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/function.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/function.html @@ -23,26 +23,32 @@ class="doc doc-heading", toc_label=function.name ~ "()") %} - {% if config.separate_signature %} - {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %} - {% else %} - {% filter highlight(language="python", inline=True) %} - {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %} - {% include "signature.html" with context %} - {% endfilter %} - {% endif %} + {% block heading scoped %} + {% if config.separate_signature %} + {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %} + {% else %} + {% filter highlight(language="python", inline=True) %} + {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %} + {% include "signature.html" with context %} + {% endfilter %} + {% endif %} + {% endblock heading %} - {% with labels = function.labels %} - {% include "labels.html" with context %} - {% endwith %} + {% block labels scoped %} + {% with labels = function.labels %} + {% include "labels.html" with context %} + {% endwith %} + {% endblock labels %} {% endfilter %} - {% if config.separate_signature %} - {% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %} - {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %} - {% endfilter %} - {% endif %} + {% block signature scoped %} + {% if config.separate_signature %} + {% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %} + {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %} + {% endfilter %} + {% endif %} + {% endblock signature %} {% else %} {% if config.show_root_toc_entry %} @@ -57,16 +63,22 @@ {% endif %}
                  - {% with docstring_sections = function.docstring.parsed %} - {% include "docstring.html" with context %} - {% endwith %} + {% block contents scoped %} + {% block docstring scoped %} + {% with docstring_sections = function.docstring.parsed %} + {% include "docstring.html" with context %} + {% endwith %} + {% endblock docstring %} - {% if config.show_source and function.source %} -
                  - {{ lang.t("Source code in") }} {{ function.relative_filepath }} - {{ function.source|highlight(language="python", linestart=function.lineno, linenums=True) }} -
                  - {% endif %} + {% block source scoped %} + {% if config.show_source and function.source %} +
                  + {{ lang.t("Source code in") }} {{ function.relative_filepath }} + {{ function.source|highlight(language="python", linestart=function.lineno, linenums=True) }} +
                  + {% endif %} + {% endblock source %} + {% endblock contents %}
                  {% endwith %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/module.html b/src/mkdocstrings_handlers/python/templates/material/_base/module.html index 8e14d354..299b4941 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/module.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/module.html @@ -21,17 +21,21 @@ class="doc doc-heading", toc_label=module.name) %} - {% with module_name = module.path if show_full_path else module.name %} - {% if config.separate_signature %} - {{ module_name }} - {% else %} - {{ module_name }} - {% endif %} - {% endwith %} - - {% with labels = module.labels %} - {% include "labels.html" with context %} - {% endwith %} + {% block heading scoped %} + {% with module_name = module.path if show_full_path else module.name %} + {% if config.separate_signature %} + {{ module_name }} + {% else %} + {{ module_name }} + {% endif %} + {% endwith %} + {% endblock heading %} + + {% block labels scoped %} + {% with labels = module.labels %} + {% include "labels.html" with context %} + {% endwith %} + {% endblock labels %} {% endfilter %} @@ -48,15 +52,21 @@ {% endif %}
                  - {% with docstring_sections = module.docstring.parsed %} - {% include "docstring.html" with context %} - {% endwith %} - - {% with obj = module %} - {% set root = False %} - {% set heading_level = heading_level + 1 %} - {% include "children.html" with context %} - {% endwith %} + {% block contents scoped %} + {% block docstring scoped %} + {% with docstring_sections = module.docstring.parsed %} + {% include "docstring.html" with context %} + {% endwith %} + {% endblock docstring %} + + {% block children scoped %} + {% with obj = module %} + {% set root = False %} + {% set heading_level = heading_level + 1 %} + {% include "children.html" with context %} + {% endwith %} + {% endblock children %} + {% endblock contents %}
                  {% endwith %} From b0123719ae90cb2d47e9b923166ac69fdce86632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 14 Jul 2023 19:33:35 +0200 Subject: [PATCH 13/13] chore: Prepare release 1.2.0 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cf8df1d..d8a46c10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ 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.2.0](https://github.com/mkdocstrings/python/releases/tag/1.2.0) - 2023-07-14 + +[Compare with 1.1.2](https://github.com/mkdocstrings/python/compare/1.1.2...1.2.0) + +### Features + +- Add Jinja blocks to module, class, function and attribute templates ([299fe48](https://github.com/mkdocstrings/python/commit/299fe483cc03ba76df29b843f88467f89db6dc72) by Timothée Mazzucotelli). +- Setup infrastructure for I18N, add translations for simplified chinese and japanese ([b053b29](https://github.com/mkdocstrings/python/commit/b053b2900ef5c0069b68ad19bda9aaa98141a525) by Nyuan Zhang). [PR #77](https://github.com/mkdocstrings/python/pull/77) +- Support inheritance ([ae42356](https://github.com/mkdocstrings/python/commit/ae4235689155a4b4f0c1e74b0014a466c6b1181f) by Timothée Mazzucotelli). [Issue mkdocstrings#157](https://github.com/mkdocstrings/mkdocstrings/issues/157), [Discussion mkdocstrings#536](https://github.com/mkdocstrings/mkdocstrings/discussions/536) + +### Bug Fixes + +- Don't show `None` as return annotation of class signatures ([3d8724e](https://github.com/mkdocstrings/python/commit/3d8724ed1f4d040d7a3d9d02784cf0d1f80445b2) by Timothée Mazzucotelli). [Issue #85](https://github.com/mkdocstrings/python/issues/85) +- Show labels in deterministic order ([02619a8](https://github.com/mkdocstrings/python/commit/02619a85ee4aab25f3241d983bdfff0534dd3f81) by Oleh Prypin). + ## [1.1.2](https://github.com/mkdocstrings/python/releases/tag/1.1.2) - 2023-06-04 [Compare with 1.1.1](https://github.com/mkdocstrings/python/compare/1.1.1...1.1.2)