From 4fe186f1002395d398cb386bb6914fdb497d7c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 8 Jan 2024 17:47:05 +0100 Subject: [PATCH 01/13] chore: Template upgrade --- .copier-answers.yml | 2 +- Makefile | 1 + scripts/insiders.py | 2 +- scripts/setup.sh | 7 +++++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index 58ab94af..d8a0fef0 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 1.1.3 +_commit: 1.2.0 _src_path: gh:pawamoy/copier-pdm author_email: pawamoy@pm.me author_fullname: Timothée Mazzucotelli diff --git a/Makefile b/Makefile index 437880eb..8ad5209e 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ SHELL := bash DUTY := $(if $(VIRTUAL_ENV),,pdm run) duty export PDM_MULTIRUN_VERSIONS ?= 3.8 3.9 3.10 3.11 3.12 +export PDM_MULTIRUN_USE_VENVS ?= $(if $(shell pdm config python.use_venv | grep True),1,0) args = $(foreach a,$($(subst -,_,$1)_args),$(if $(value $a),$a="$($a)")) check_quality_args = files diff --git a/scripts/insiders.py b/scripts/insiders.py index 8f5e215e..85ecbd0e 100644 --- a/scripts/insiders.py +++ b/scripts/insiders.py @@ -155,7 +155,7 @@ def funding_goals(source: str | list[str | tuple[str, str, str]], funding: int = return _load_goals_from_disk(source, funding) goals = {} for src in source: - source_goals = _load_goals(src) + source_goals = _load_goals(src, funding) for amount, goal in source_goals.items(): if amount not in goals: goals[amount] = goal diff --git a/scripts/setup.sh b/scripts/setup.sh index bbf0d11d..eef38433 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -12,6 +12,13 @@ if ! pdm self list 2>/dev/null | grep -q pdm-multirun; then fi if [ -n "${PDM_MULTIRUN_VERSIONS}" ]; then + if [ "${PDM_MULTIRUN_USE_VENVS}" -eq "1" ]; then + for version in ${PDM_MULTIRUN_VERSIONS}; do + if ! pdm venv --path "${version}" &>/dev/null; then + pdm venv create --name "${version}" "${version}" + fi + done + fi pdm multirun -v pdm install -G:all else pdm install -G:all From 03e53e3964908d77068ed7d8538a046222b56d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 9 Jan 2024 15:56:45 +0100 Subject: [PATCH 02/13] docs: Tell that members are still grouped by category when specifying members or members order options Issue #119: https://github.com/mkdocstrings/python/issues/119 --- docs/usage/configuration/members.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/usage/configuration/members.md b/docs/usage/configuration/members.md index 0b6d27e5..f558040f 100644 --- a/docs/usage/configuration/members.md +++ b/docs/usage/configuration/members.md @@ -14,6 +14,8 @@ even if [`show_if_no_docstring`][] is set to false. The members will be rendered in the specified order, regardless of the value of [`members_order`][]. +**Note that members will still be grouped by category, +according to the [`group_by_category`][] option.** Passing a falsy value (`no`, `false` in YAML) or an empty list (`[]`) will tell the Python handler not to render any member. @@ -269,6 +271,8 @@ The members ordering to use. Possible values: The order applies for all members, recursively. The order will be ignored for members that are explicitely sorted using the [`members`][] option. +**Note that members will still be grouped by category, +according to the [`group_by_category`][] option.** ```yaml title="in mkdocs.yml (global configuration)" plugins: From d70cd9d6e592e545b2c4e1d6964a927df0fcb7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 31 Jan 2024 12:32:16 +0100 Subject: [PATCH 03/13] docs: Fix typo --- docs/usage/customization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/customization.md b/docs/usage/customization.md index 9dedbf20..14721092 100644 --- a/docs/usage/customization.md +++ b/docs/usage/customization.md @@ -324,7 +324,7 @@ Available context: Available context: - `config`: The handler configuration (dictionary). -- `function`: The [Attribute][griffe.dataclasses.Attribute] instance. +- `attribute`: The [Attribute][griffe.dataclasses.Attribute] instance. #### Docstring sections From 548bdaddd66ffc99b3b9a5a62228a2ff4ff0dd00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 31 Jan 2024 12:32:37 +0100 Subject: [PATCH 04/13] refactor: Mark all Jinja blocks as scoped --- .../templates/material/_base/docstring/attributes.html | 6 +++--- .../python/templates/material/_base/docstring/classes.html | 6 +++--- .../templates/material/_base/docstring/functions.html | 6 +++--- .../python/templates/material/_base/docstring/modules.html | 6 +++--- .../material/_base/docstring/other_parameters.html | 6 +++--- .../templates/material/_base/docstring/parameters.html | 6 +++--- .../python/templates/material/_base/docstring/raises.html | 6 +++--- .../python/templates/material/_base/docstring/receives.html | 6 +++--- .../python/templates/material/_base/docstring/returns.html | 6 +++--- .../python/templates/material/_base/docstring/warns.html | 6 +++--- .../python/templates/material/_base/docstring/yields.html | 6 +++--- 11 files changed, 33 insertions(+), 33 deletions(-) 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 0b291574..88c5990d 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/attributes.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

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

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

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

    {% for attribute in section.value %} @@ -55,7 +55,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html index 42531649..b8ad2e0f 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/classes.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

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

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

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

    {% for class in section.value %} @@ -42,7 +42,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html index f93a2e4b..ab1939f5 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/functions.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

{{ section.title or lang.t("Methods:") if obj.is_class else lang.t("Functions:") }}

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

{{ section.title or lang.t("Methods:") if obj.is_class else lang.t("Functions:") }}

    {% for function in section.value %} @@ -46,7 +46,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html index 3bae2a83..f771f20b 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/modules.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

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

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

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

    {% for module in section.value %} @@ -42,7 +42,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} 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 8315381d..7ede6715 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 @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

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

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

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

    {% for parameter in section.value %} @@ -55,7 +55,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} 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 9483e8af..7b4788ca 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/parameters.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

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

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

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

    {% for parameter in section.value %} @@ -70,7 +70,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} 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 e4edc66a..396ccc73 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/raises.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

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

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

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

    {% for raises in section.value %} @@ -52,7 +52,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} 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 d58fb684..77d83c0b 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/receives.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %} {% set name_column = section.value|selectattr("name")|any %}

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

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

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

    {% for receives in section.value %} @@ -58,7 +58,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} 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 a8e3b776..b19917a3 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/returns.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %} {% set name_column = section.value|selectattr("name")|any %}

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

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

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

    {% for returns in section.value %} @@ -58,7 +58,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} 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 cf1cc4a6..8377669f 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/warns.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %}

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

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

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

    {% for warns in section.value %} @@ -52,7 +52,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} 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 63824c0c..c69135ea 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/docstring/yields.html @@ -3,7 +3,7 @@ {% import "language.html" as lang with context %} {% if config.docstring_section_style == "table" %} - {% block table_style %} + {% block table_style scoped %} {% set name_column = section.value|selectattr("name")|any %}

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

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

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

    {% for yields in section.value %} @@ -58,7 +58,7 @@
{% endblock list_style %} {% elif config.docstring_section_style == "spacy" %} - {% block spacy_style %} + {% block spacy_style scoped %} From 0c6aa323c9e57b8348765a5daa11c79d0c5edb07 Mon Sep 17 00:00:00 2001 From: Romain Date: Sat, 3 Feb 2024 05:40:36 -0800 Subject: [PATCH 05/13] feat: Add option to search for stubs packages This allows using the feature in Griffe that searches for stubs packages. PR #128: https://github.com/mkdocstrings/python/pull/128 PR griffe#221: : https://github.com/mkdocstrings/griffe/pull/221 --- docs/usage/configuration/general.md | 57 +++++++++++++++++++++ src/mkdocstrings_handlers/python/handler.py | 6 ++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/docs/usage/configuration/general.md b/docs/usage/configuration/general.md index 320d0074..e4ddaec1 100644 --- a/docs/usage/configuration/general.md +++ b/docs/usage/configuration/general.md @@ -191,3 +191,60 @@ __all__ = ["their_object"]

Docstring of your module.

//// /// + +## `find_stubs_package` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }** + + +When looking for documentation specified in [autodoc instructions][autodoc syntax] (`::: identifier`), also look for +the stubs package as defined in [PEP 561](https://peps.python.org/pep-0561/) if it exists. This is useful when +most of your documentation is separately provided by such a package and not inline in your main package. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + find_stubs_package: true +``` + +```md title="or in docs/some_page.md (local configuration)" +::: your_package.your_module.your_func + options: + find_stubs_package: true +``` + +```python title="your_package/your_module.py" + +def your_func(a, b): + # Function code + ... + +# rest of your code +``` + +```python title="your_package-stubs/your_module.pyi" + +def your_func(a: int, b: str): + """ + + """ + ... + +# rest of your code +``` + +/// admonition | Preview + type: preview + +//// tab | With find_stubs_package +

your_func

+

Function docstring

+//// + +//// tab | Without find_stubs_package +

your_func

+//// +/// diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 9f6cae4b..7b33e30c 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -61,6 +61,7 @@ class PythonHandler(BaseHandler): fallback_config: ClassVar[dict] = {"fallback": True} """The configuration used to collect item during autorefs fallback.""" default_config: ClassVar[dict] = { + "find_stubs_package": False, "docstring_style": "google", "docstring_options": {}, "show_symbol_type_heading": False, @@ -110,6 +111,7 @@ class PythonHandler(BaseHandler): """Default handler configuration. Attributes: General options: + find_stubs_package (bool): Whether to load stubs package (package-stubs) when extracting docstrings. allow_inspection (bool): Whether to allow inspecting modules when visiting them is not possible. Default: `True`. show_bases (bool): Show the base classes of a class. Default: `True`. show_source (bool): Show the source code of this object. Default: `True`. @@ -279,8 +281,8 @@ def collect(self, identifier: str, config: Mapping[str, Any]) -> CollectorItem: try: for pre_loaded_module in final_config.get("preload_modules") or []: if pre_loaded_module not in self._modules_collection: - loader.load(pre_loaded_module) - loader.load(module_name) + loader.load(pre_loaded_module, find_stubs_package=final_config["find_stubs_package"]) + loader.load(module_name, find_stubs_package=final_config["find_stubs_package"]) except ImportError as error: raise CollectionError(str(error)) from error unresolved, iterations = loader.resolve_aliases( From 8e867785574536cf085496ef32647b5ad2b1b517 Mon Sep 17 00:00:00 2001 From: Romain Date: Sun, 4 Feb 2024 02:35:40 -0800 Subject: [PATCH 06/13] docs: Add default value for `find_stubs_package` docs --- src/mkdocstrings_handlers/python/handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 7b33e30c..7ffdaf6b 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -111,7 +111,7 @@ class PythonHandler(BaseHandler): """Default handler configuration. Attributes: General options: - find_stubs_package (bool): Whether to load stubs package (package-stubs) when extracting docstrings. + find_stubs_package (bool): Whether to load stubs package (package-stubs) when extracting docstrings. Default `False`. allow_inspection (bool): Whether to allow inspecting modules when visiting them is not possible. Default: `True`. show_bases (bool): Show the base classes of a class. Default: `True`. show_source (bool): Show the source code of this object. Default: `True`. From eaf9b8240069f7369f401fe048892043c8b173d3 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Mon, 5 Feb 2024 13:47:05 +0100 Subject: [PATCH 07/13] feat: Add `show_labels` option to show/hide labels Issue #120: https://github.com/mkdocstrings/python/issues/120 PR #130: https://github.com/mkdocstrings/python/pull/130 --- docs/usage/configuration/members.md | 46 +++++++++++++++++++ src/mkdocstrings_handlers/python/handler.py | 2 + .../templates/material/_base/labels.html | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/docs/usage/configuration/members.md b/docs/usage/configuration/members.md index f558040f..1e5ff771 100644 --- a/docs/usage/configuration/members.md +++ b/docs/usage/configuration/members.md @@ -643,3 +643,49 @@ plugins: //// /// + +## `show_labels` + +- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }** + + +Whether to show labels of the members. + +```yaml title="in mkdocs.yml (global configuration)" +plugins: +- mkdocstrings: + handlers: + python: + options: + show_labels: true +``` + +```md title="or in docs/some_page.md (local configuration)" +::: package.module + options: + show_labels: false +``` + +```python title="package/module.py" +class SomeClass: + some_attr: int +``` + +/// admonition | Preview + type: preview + +//// tab | With labels + + some_attr: + int + +instance-attribute +//// + +//// tab | Without labels + + some_attr: + int + +//// +/// diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 7ffdaf6b..c5217e98 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -106,6 +106,7 @@ class PythonHandler(BaseHandler): "preload_modules": None, "allow_inspection": True, "summary": False, + "show_labels": True, "unwrap_annotated": False, } """Default handler configuration. @@ -154,6 +155,7 @@ class PythonHandler(BaseHandler): group_by_category (bool): Group the object's children by categories: attributes, classes, functions, and modules. Default: `True`. show_submodules (bool): When rendering a module, show its submodules recursively. Default: `False`. summary (bool | dict[str, bool]): Whether to render summaries of modules, classes, functions (methods) and attributes. + show_labels (bool): Whether to show labels of the members. Default: `True`. Attributes: Docstrings options: docstring_style (str): The docstring style to use: `google`, `numpy`, `sphinx`, or `None`. Default: `"google"`. diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html index 0c84067a..a35bffbb 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/labels.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/labels.html @@ -1,4 +1,4 @@ -{% if labels %} +{% if config.show_labels and labels %} {{ log.debug("Rendering labels") }} {% for label in labels|sort %} From 6364fbcd4012d2026aa9efe4501b697f08b8c6ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 13 Mar 2024 19:34:04 +0100 Subject: [PATCH 08/13] chore: Template upgrade --- .copier-answers.yml | 7 +++--- .github/workflows/ci.yml | 8 +++---- .github/workflows/release.yml | 4 ++-- .gitignore | 1 + CODE_OF_CONDUCT.md | 2 +- config/ruff.toml | 6 ++++- config/vscode/launch.json | 4 ++-- docs/insiders/index.md | 44 +++++++++++++++++++++++------------ docs/insiders/installation.md | 4 ++-- docs/js/insiders.js | 39 ++++++++++++++++++------------- duties.py | 4 ++-- pyproject.toml | 2 +- scripts/gen_ref_nav.py | 5 ++-- 13 files changed, 79 insertions(+), 51 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index d8a0fef0..dd37bf57 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,14 +1,15 @@ # Changes here will be overwritten by Copier -_commit: 1.2.0 +_commit: 1.2.6 _src_path: gh:pawamoy/copier-pdm -author_email: pawamoy@pm.me +author_email: dev@pawamoy.fr author_fullname: Timothée Mazzucotelli author_username: pawamoy copyright_date: '2021' copyright_holder: Timothée Mazzucotelli -copyright_holder_email: pawamoy@pm.me +copyright_holder_email: dev@pawamoy.fr copyright_license: ISC License insiders: true +insiders_email: insiders@pawamoy.fr insiders_repository_name: mkdocstrings-python project_description: A Python handler for mkdocstrings. project_name: mkdocstrings-python diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1d63df6..be76a509 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,13 +23,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Fetch all tags run: git fetch --depth=1 --tags - name: Set up PDM - uses: pdm-project/setup-pdm@v3 + uses: pdm-project/setup-pdm@v4 with: python-version: "3.8" @@ -96,10 +96,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up PDM - uses: pdm-project/setup-pdm@v3 + uses: pdm-project/setup-pdm@v4 with: python-version: ${{ matrix.python-version }} allow-python-prereleases: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3dcc3fe4..d82736f7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Fetch all tags run: git fetch --depth=1 --tags - name: Setup Python @@ -22,7 +22,7 @@ jobs: if: github.repository_owner == 'pawamoy-insiders' run: python -m build - name: Upload dists artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: github.repository_owner == 'pawamoy-insiders' with: name: python-insiders diff --git a/.gitignore b/.gitignore index ae47b28b..588e34e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea/ +.vscode/ __pycache__/ *.py[cod] dist/ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index fe3eefbf..255e0eed 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -60,7 +60,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -pawamoy@pm.me. +dev@pawamoy.fr. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the diff --git a/config/ruff.toml b/config/ruff.toml index 99efa62b..a16c92b6 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -1,5 +1,5 @@ target-version = "py38" -line-length = 132 +line-length = 120 exclude = [ "fixtures", "site", @@ -102,3 +102,7 @@ known-first-party = ["mkdocstrings_handlers"] [pydocstyle] convention = "google" + +[format] +docstring-code-format = true +docstring-code-line-length = 80 diff --git a/config/vscode/launch.json b/config/vscode/launch.json index 2e0d651e..d056ccee 100644 --- a/config/vscode/launch.json +++ b/config/vscode/launch.json @@ -3,7 +3,7 @@ "configurations": [ { "name": "python (current file)", - "type": "python", + "type": "debugpy", "request": "launch", "program": "${file}", "console": "integratedTerminal", @@ -11,7 +11,7 @@ }, { "name": "test", - "type": "python", + "type": "debugpy", "request": "launch", "module": "pytest", "justMyCode": false, diff --git a/docs/insiders/index.md b/docs/insiders/index.md index ceb3c59c..a6642ede 100644 --- a/docs/insiders/index.md +++ b/docs/insiders/index.md @@ -65,17 +65,31 @@ data_source = [ ``` -```python exec="1" session="insiders" +```python exec="1" session="insiders" idprefix="" --8<-- "scripts/insiders.py" -print( - f"""The moment you become a sponsor, you'll get **immediate - access to {len(unreleased_features)} additional features** that you can start using right away, and - which are currently exclusively available to sponsors:\n""" -) - -for feature in unreleased_features: - feature.render(badge=True) +if unreleased_features: + print( + "The moment you [become a sponsor](#how-to-become-a-sponsor), you'll get **immediate " + f"access to {len(unreleased_features)} additional features** that you can start using right away, and " + "which are currently exclusively available to sponsors:\n" + ) + + for feature in unreleased_features: + feature.render(badge=True) + + print( + "\n\nThese are just the features related to this project. " + "[See the complete feature list on the author's main Insiders page](https://pawamoy.github.io/insiders/#whats-in-it-for-me)." + ) +else: + print( + "The moment you [become a sponsor](#how-to-become-a-sponsor), you'll get immediate " + "access to all released features that you can start using right away, and " + "which are exclusively available to sponsors. At this moment, there are no " + "Insiders features for this project, but checkout the [next funding goals](#goals) " + "to see what's coming, as well as **[the feature list for all Insiders projects](https://pawamoy.github.io/insiders/#whats-in-it-for-me).**" + ) ``` @@ -88,7 +102,7 @@ You can use your individual or organization GitHub account for sponsoring. **Important**: If you're sponsoring **[@pawamoy][github sponsor profile]** through a GitHub organization, please send a short email -to pawamoy@pm.me with the name of your +to insiders@pawamoy.fr with the name of your organization and the GitHub account of the individual that should be added as a collaborator.[^4] @@ -97,7 +111,7 @@ You can cancel your sponsorship anytime.[^5] [^4]: It's currently not possible to grant access to each member of an organization, as GitHub only allows for adding users. Thus, after - sponsoring, please send an email to pawamoy@pm.me, stating which + sponsoring, please send an email to insiders@pawamoy.fr, stating which account should become a collaborator of the Insiders repository. We're working on a solution which will make access to organizations much simpler. To ensure that access is not tied to a particular individual GitHub account, @@ -120,10 +134,10 @@ You can cancel your sponsorship anytime.[^5]
- -
+
+
+
-
@@ -188,7 +202,7 @@ yearly billing cycle][billing cycle]. If for some reason you cannot do that, you could also create a dedicated GitHub account with a yearly billing cycle, which you only use for sponsoring (some sponsors already do that). -If you have any problems or further questions, please reach out to pawamoy@pm.me. +If you have any problems or further questions, please reach out to insiders@pawamoy.fr. ### Terms diff --git a/docs/insiders/installation.md b/docs/insiders/installation.md index 3d9d75d8..3ebe5dfd 100644 --- a/docs/insiders/installation.md +++ b/docs/insiders/installation.md @@ -143,7 +143,7 @@ as it is against our [Terms of use](index.md#terms).** > ```bash > # clone the repository > git clone git@github.com:pawamoy-insiders/mkdocstrings-python -> cd python +> cd mkdocstrings-python > > # install build > pip install --user build @@ -184,7 +184,7 @@ git clone git@github.com:pawamoy-insiders/mkdocstrings-python When cloning from `git`, the package must be installed: ``` -pip install -e python +pip install -e mkdocstrings-python ``` ## Upgrading diff --git a/docs/js/insiders.js b/docs/js/insiders.js index 03bcb404..8bb68485 100644 --- a/docs/js/insiders.js +++ b/docs/js/insiders.js @@ -21,6 +21,26 @@ function getJSON(url, callback) { xhr.send(); } +function updatePremiumSponsors(dataURL, rank) { + let capRank = rank.charAt(0).toUpperCase() + rank.slice(1); + getJSON(dataURL + `/sponsors${capRank}.json`, function (err, sponsors) { + const sponsorsDiv = document.getElementById(`${rank}-sponsors`); + if (sponsors.length > 0) { + let html = ''; + html += `${capRank} sponsors

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

' + sponsorsDiv.innerHTML = html; + } + }); +} + function updateInsidersPage(author_username) { const sponsorURL = `https://github.com/sponsors/${author_username}` const dataURL = `https://raw.githubusercontent.com/${author_username}/sponsors/main`; @@ -48,20 +68,7 @@ function updateInsidersPage(author_username) { } }); }); - 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; - } - }); + updatePremiumSponsors(dataURL, "gold"); + updatePremiumSponsors(dataURL, "silver"); + updatePremiumSponsors(dataURL, "bronze"); } diff --git a/duties.py b/duties.py index 30fb2221..55fcf6a2 100644 --- a/duties.py +++ b/duties.py @@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Iterator from duty import duty -from duty.callables import black, coverage, lazy, mkdocs, mypy, pytest, ruff, safety +from duty.callables import coverage, lazy, mkdocs, mypy, pytest, ruff, safety if TYPE_CHECKING: from duty.context import Context @@ -225,7 +225,7 @@ def format(ctx: Context) -> None: ruff.check(*PY_SRC_LIST, config="config/ruff.toml", fix_only=True, exit_zero=True), title="Auto-fixing code", ) - ctx.run(black.run(*PY_SRC_LIST, config="config/black.toml"), title="Formatting code") + ctx.run(ruff.format(*PY_SRC_LIST, config="config/ruff.toml"), title="Formatting code") @duty(post=["docs-deploy"]) diff --git a/pyproject.toml b/pyproject.toml index 853cdf9e..75643e9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "pdm.backend" [project] name = "mkdocstrings-python" description = "A Python handler for mkdocstrings." -authors = [{name = "Timothée Mazzucotelli", email = "pawamoy@pm.me"}] +authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}] license = {text = "ISC"} readme = "README.md" requires-python = ">=3.8" diff --git a/scripts/gen_ref_nav.py b/scripts/gen_ref_nav.py index 7285ac1c..b369536c 100644 --- a/scripts/gen_ref_nav.py +++ b/scripts/gen_ref_nav.py @@ -7,7 +7,8 @@ nav = mkdocs_gen_files.Nav() mod_symbol = '' -src = Path(__file__).parent.parent / "src" +root = Path(__file__).parent.parent +src = root / "src" for path in sorted(src.rglob("*.py")): module_path = path.relative_to(src).with_suffix("") @@ -30,7 +31,7 @@ ident = ".".join(parts) fd.write(f"::: {ident}") - mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path) + mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path.relative_to(root)) with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file: nav_file.writelines(nav.build_literate_nav()) From 0dd0b7956bc2db2e492404cb5a445ad49f126a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 13 Mar 2024 19:35:36 +0100 Subject: [PATCH 09/13] chore: Use mkdocstrings' handler-template --- .copier-answers.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index dd37bf57..65d4018a 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,6 +1,6 @@ # Changes here will be overwritten by Copier -_commit: 1.2.6 -_src_path: gh:pawamoy/copier-pdm +_commit: 0.1.0 +_src_path: gh:mkdocstrings/handler-template author_email: dev@pawamoy.fr author_fullname: Timothée Mazzucotelli author_username: pawamoy @@ -20,4 +20,4 @@ python_package_import_name: mkdocstrings_handlers repository_name: python repository_namespace: mkdocstrings repository_provider: github.com - +language: Python \ No newline at end of file From 20623257d0b98d843b68f8bd168e551a8c98b10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 13 Mar 2024 19:49:01 +0100 Subject: [PATCH 10/13] chore: Template upgrade --- .copier-answers.yml | 8 +- .envrc | 1 + .github/workflows/ci.yml | 61 +++++-- .gitignore | 7 +- .gitpod.dockerfile | 2 +- CONTRIBUTING.md | 10 +- Makefile | 57 ++----- README.md | 22 +-- config/coverage.ini | 3 +- config/pytest.ini | 6 - config/ruff.toml | 64 +++----- config/vscode/launch.json | 11 ++ config/vscode/settings.json | 23 +-- config/vscode/tasks.json | 80 +++++---- devdeps.txt | 27 +++ docs/insiders/goals.yml | 8 +- docs/insiders/index.md | 7 +- duties.py | 21 ++- pyproject.toml | 44 ----- scripts/gen_credits.py | 150 +++++++++++------ scripts/insiders.py | 16 +- scripts/make | 155 ++++++++++++++++++ scripts/setup.sh | 25 --- src/mkdocstrings_handlers/python/__init__.py | 6 +- .../{ => python}/py.typed | 0 tests/conftest.py | 6 +- tests/test_themes.py | 13 +- 27 files changed, 483 insertions(+), 350 deletions(-) create mode 100644 .envrc create mode 100644 devdeps.txt create mode 100755 scripts/make delete mode 100755 scripts/setup.sh rename src/mkdocstrings_handlers/{ => python}/py.typed (100%) diff --git a/.copier-answers.yml b/.copier-answers.yml index 65d4018a..0e3a987e 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 0.1.0 +_commit: 0.3.1 _src_path: gh:mkdocstrings/handler-template author_email: dev@pawamoy.fr author_fullname: Timothée Mazzucotelli @@ -11,13 +11,13 @@ copyright_license: ISC License insiders: true insiders_email: insiders@pawamoy.fr insiders_repository_name: mkdocstrings-python +language: Python project_description: A Python handler for mkdocstrings. project_name: mkdocstrings-python public_release: true -python_package_command_line_name: '' python_package_distribution_name: mkdocstrings-python -python_package_import_name: mkdocstrings_handlers +python_package_import_name: python repository_name: python repository_namespace: mkdocstrings repository_provider: github.com -language: Python \ No newline at end of file + diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..f9d77ee3 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +PATH_add scripts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be76a509..f3b59817 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,7 @@ env: LANG: en_US.utf-8 LC_ALL: en_US.utf-8 PYTHONIOENCODING: UTF-8 + PYTHON_VERSIONS: "" jobs: @@ -28,28 +29,51 @@ jobs: - name: Fetch all tags run: git fetch --depth=1 --tags - - name: Set up PDM - uses: pdm-project/setup-pdm@v4 + - name: Set up Python + uses: actions/setup-python@v5 with: - python-version: "3.8" + python-version: "3.11" - - name: Resolving dependencies - run: pdm lock -v --no-cross-platform -G ci-quality + - name: Install uv + run: pip install uv - name: Install dependencies - run: pdm install -G ci-quality + run: make setup - name: Check if the documentation builds correctly - run: pdm run duty check-docs + run: make check-docs - name: Check the code quality - run: pdm run duty check-quality + run: make check-quality - name: Check if the code is correctly typed - run: pdm run duty check-types + run: make check-types - name: Check for vulnerabilities in dependencies - run: pdm run duty check-dependencies + run: make check-dependencies + + - name: Check for breaking changes in the API + run: make check-api + + exclude-test-jobs: + runs-on: ubuntu-latest + outputs: + jobs: ${{ steps.exclude-jobs.outputs.jobs }} + steps: + - id: exclude-jobs + run: | + if ${{ github.repository_owner == 'pawamoy-insiders' }}; then + echo 'jobs=[ + {"os": "macos-latest"}, + {"os": "windows-latest"}, + {"python-version": "3.9"}, + {"python-version": "3.10"}, + {"python-version": "3.11"}, + {"python-version": "3.12"} + ]' | tr -d '[:space:]' >> $GITHUB_OUTPUT + else + echo 'jobs=[]' >> $GITHUB_OUTPUT + fi - name: Check for breaking changes in the API run: pdm run duty check-api @@ -98,17 +122,20 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set up PDM - uses: pdm-project/setup-pdm@v4 + - name: Set up Python + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - allow-python-prereleases: true + allow-prereleases: true - - name: Resolving dependencies - run: pdm lock -v --no-cross-platform -G ci-tests + - name: Install uv + run: pip install uv - name: Install dependencies - run: pdm install --no-editable -G ci-tests + run: | + uv venv + uv pip install -r devdeps.txt + uv pip install "mkdocstrings-python @ ." - name: Run the test suite - run: pdm run duty test + run: make test diff --git a/.gitignore b/.gitignore index 588e34e0..246951cc 100644 --- a/.gitignore +++ b/.gitignore @@ -10,11 +10,8 @@ htmlcov/ pip-wheel-metadata/ .pytest_cache/ .mypy_cache/ +.ruff_cache/ site/ -pdm.lock -pdm.toml -.pdm-plugins/ -.pdm-python -__pypackages__/ .venv/ +.venvs/ .cache/ diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile index 0e6d9d35..1590b415 100644 --- a/.gitpod.dockerfile +++ b/.gitpod.dockerfile @@ -2,5 +2,5 @@ FROM gitpod/workspace-full USER gitpod ENV PIP_USER=no RUN pip3 install pipx; \ - pipx install pdm; \ + pipx install uv; \ pipx ensurepath diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dfe5a910..6af01962 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,18 +17,18 @@ make setup > NOTE: > If it fails for some reason, > you'll need to install -> [PDM](https://github.com/pdm-project/pdm) +> [uv](https://github.com/astral-sh/uv) > manually. > > You can install it with: > > ```bash > python3 -m pip install --user pipx -> pipx install pdm +> pipx install uv > ``` > > Now you can try running `make setup` again, -> or simply `pdm install`. +> or simply `uv install`. You now have the dependencies installed. @@ -39,13 +39,13 @@ 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 run the task directly with `pdm run duty TASK`. +on multiple Python versions, you run the task directly with `make 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, we provide -[an action to configure VSCode](https://pawamoy.github.io/copier-pdm/work/#vscode-setup) +[an action to configure VSCode](https://pawamoy.github.io/copier-uv/work/#vscode-setup) for the project. ## Development diff --git a/Makefile b/Makefile index 8ad5209e..771b333c 100644 --- a/Makefile +++ b/Makefile @@ -1,54 +1,27 @@ -.DEFAULT_GOAL := help -SHELL := bash -DUTY := $(if $(VIRTUAL_ENV),,pdm run) duty -export PDM_MULTIRUN_VERSIONS ?= 3.8 3.9 3.10 3.11 3.12 -export PDM_MULTIRUN_USE_VENVS ?= $(if $(shell pdm config python.use_venv | grep True),1,0) +# If you have `direnv` loaded in your shell, and allow it in the repository, +# the `make` command will point at the `scripts/make` shell script. +# This Makefile is just here to allow auto-completion in the terminal. -args = $(foreach a,$($(subst -,_,$1)_args),$(if $(value $a),$a="$($a)")) -check_quality_args = files -docs_args = host port -release_args = version -test_args = match - -BASIC_DUTIES = \ +actions = \ changelog \ + check \ check-api \ check-dependencies \ + check-docs \ + check-quality \ + check-types \ clean \ coverage \ docs \ docs-deploy \ format \ + help \ release \ + run \ + setup \ + test \ vscode -QUALITY_DUTIES = \ - check-quality \ - check-docs \ - check-types \ - test - -.PHONY: help -help: - @$(DUTY) --list - -.PHONY: lock -lock: - @pdm lock -G:all - -.PHONY: setup -setup: - @bash scripts/setup.sh - -.PHONY: check -check: - @pdm multirun duty check-quality check-types check-docs - @$(DUTY) check-dependencies check-api - -.PHONY: $(BASIC_DUTIES) -$(BASIC_DUTIES): - @$(DUTY) $@ $(call args,$@) - -.PHONY: $(QUALITY_DUTIES) -$(QUALITY_DUTIES): - @pdm multirun duty $@ $(call args,$@) +.PHONY: $(actions) +$(actions): + @bash scripts/make "$@" diff --git a/README.md b/README.md index 6b3afb5f..23b6e809 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,11 @@

A Python handler for mkdocstrings.

-

- - ci - - - documentation - - - pypi version - - - gitpod - - - gitter - -

+[![ci](https://github.com/mkdocstrings/python/workflows/ci/badge.svg)](https://github.com/mkdocstrings/python/actions?query=workflow%3Aci) +[![documentation](https://img.shields.io/badge/docs-mkdocs%20material-blue.svg?style=flat)](https://mkdocstrings.github.io/python/) +[![pypi version](https://img.shields.io/pypi/v/mkdocstrings-python.svg)](https://pypi.org/project/mkdocstrings-python/) +[![gitpod](https://img.shields.io/badge/gitpod-workspace-blue.svg?style=flat)](https://gitpod.io/#https://github.com/mkdocstrings/python) +[![gitter](https://badges.gitter.im/join%20chat.svg)](https://app.gitter.im/#/room/#python:gitter.im) --- diff --git a/config/coverage.ini b/config/coverage.ini index 19b34d9b..71d12074 100644 --- a/config/coverage.ini +++ b/config/coverage.ini @@ -8,7 +8,8 @@ source = [coverage:paths] equivalent = src/ - __pypackages__/ + .venv/lib/*/site-packages/ + .venvs/*/lib/*/site-packages/ [coverage:report] include_namespace_packages = true diff --git a/config/pytest.ini b/config/pytest.ini index 5a493959..ebdeb484 100644 --- a/config/pytest.ini +++ b/config/pytest.ini @@ -1,10 +1,4 @@ [pytest] -norecursedirs = - .git - .tox - .env - dist - build python_files = test_*.py *_test.py diff --git a/config/ruff.toml b/config/ruff.toml index a16c92b6..751bf595 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -1,53 +1,27 @@ target-version = "py38" line-length = 120 + +[lint] exclude = [ "fixtures", "site", ] select = [ - "A", - "ANN", - "ARG", - "B", - "BLE", - "C", - "C4", + "A", "ANN", "ARG", + "B", "BLE", + "C", "C4", "COM", - "D", - "DTZ", - "E", - "ERA", - "EXE", - "F", - "FBT", + "D", "DTZ", + "E", "ERA", "EXE", + "F", "FBT", "G", - "I", - "ICN", - "INP", - "ISC", + "I", "ICN", "INP", "ISC", "N", - "PGH", - "PIE", - "PL", - "PLC", - "PLE", - "PLR", - "PLW", - "PT", - "PYI", + "PGH", "PIE", "PL", "PLC", "PLE", "PLR", "PLW", "PT", "PYI", "Q", - "RUF", - "RSE", - "RET", - "S", - "SIM", - "SLF", - "T", - "T10", - "T20", - "TCH", - "TID", - "TRY", + "RUF", "RSE", "RET", + "S", "SIM", "SLF", + "T", "T10", "T20", "TCH", "TID", "TRY", "UP", "W", "YTT", @@ -73,7 +47,7 @@ ignore = [ "TRY003", # Avoid specifying long messages outside the exception class ] -[per-file-ignores] +[lint.per-file-ignores] "src/*/cli.py" = [ "T201", # Print statement ] @@ -91,16 +65,16 @@ ignore = [ "S101", # Use of assert detected ] -[flake8-quotes] +[lint.flake8-quotes] docstring-quotes = "double" -[flake8-tidy-imports] +[lint.flake8-tidy-imports] ban-relative-imports = "all" -[isort] -known-first-party = ["mkdocstrings_handlers"] +[lint.isort] +known-first-party = ["mkdocstrings_handlers.python"] -[pydocstyle] +[lint.pydocstyle] convention = "google" [format] diff --git a/config/vscode/launch.json b/config/vscode/launch.json index d056ccee..e3288388 100644 --- a/config/vscode/launch.json +++ b/config/vscode/launch.json @@ -9,6 +9,17 @@ "console": "integratedTerminal", "justMyCode": false }, + { + "name": "docs", + "type": "debugpy", + "request": "launch", + "module": "mkdocs", + "justMyCode": false, + "args": [ + "serve", + "-v" + ] + }, { "name": "test", "type": "debugpy", diff --git a/config/vscode/settings.json b/config/vscode/settings.json index 17beee4b..949856d1 100644 --- a/config/vscode/settings.json +++ b/config/vscode/settings.json @@ -1,29 +1,9 @@ { "files.watcherExclude": { - "**/__pypackages__/**": true, "**/.venv*/**": true, + "**/.venvs*/**": true, "**/venv*/**": true }, - "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter" - }, - "python.autoComplete.extraPaths": [ - "__pypackages__/3.8/lib", - "__pypackages__/3.9/lib", - "__pypackages__/3.10/lib", - "__pypackages__/3.11/lib", - "__pypackages__/3.12/lib" - ], - "python.analysis.extraPaths": [ - "__pypackages__/3.8/lib", - "__pypackages__/3.9/lib", - "__pypackages__/3.10/lib", - "__pypackages__/3.11/lib", - "__pypackages__/3.12/lib" - ], - "black-formatter.args": [ - "--config=config/black.toml" - ], "mypy-type-checker.args": [ "--config-file=config/mypy.ini" ], @@ -32,6 +12,7 @@ "python.testing.pytestArgs": [ "--config-file=config/pytest.ini" ], + "ruff.enable": true, "ruff.format.args": [ "--config=config/ruff.toml" ], diff --git a/config/vscode/tasks.json b/config/vscode/tasks.json index 80cd13d2..30008cf2 100644 --- a/config/vscode/tasks.json +++ b/config/vscode/tasks.json @@ -3,84 +3,94 @@ "tasks": [ { "label": "changelog", - "type": "shell", - "command": "pdm run duty changelog" + "type": "process", + "command": "scripts/make", + "args": ["changelog"] }, { "label": "check", - "type": "shell", - "command": "pdm run duty check" + "type": "process", + "command": "scripts/make", + "args": ["check"] }, { "label": "check-quality", - "type": "shell", - "command": "pdm run duty check-quality" + "type": "process", + "command": "scripts/make", + "args": ["check-quality"] }, { "label": "check-types", - "type": "shell", - "command": "pdm run duty check-types" + "type": "process", + "command": "scripts/make", + "args": ["check-types"] }, { "label": "check-docs", - "type": "shell", - "command": "pdm run duty check-docs" + "type": "process", + "command": "scripts/make", + "args": ["check-docs"] }, { "label": "check-dependencies", - "type": "shell", - "command": "pdm run duty check-dependencies" + "type": "process", + "command": "scripts/make", + "args": ["check-dependencies"] }, { "label": "check-api", - "type": "shell", - "command": "pdm run duty check-api" + "type": "process", + "command": "scripts/make", + "args": ["check-api"] }, { "label": "clean", - "type": "shell", - "command": "pdm run duty clean" + "type": "process", + "command": "scripts/make", + "args": ["clean"] }, { "label": "docs", - "type": "shell", - "command": "pdm run duty docs" + "type": "process", + "command": "scripts/make", + "args": ["docs"] }, { "label": "docs-deploy", - "type": "shell", - "command": "pdm run duty docs-deploy" + "type": "process", + "command": "scripts/make", + "args": ["docs-deploy"] }, { "label": "format", - "type": "shell", - "command": "pdm run duty format" - }, - { - "label": "lock", - "type": "shell", - "command": "pdm lock -G:all" + "type": "process", + "command": "scripts/make", + "args": ["format"] }, { "label": "release", - "type": "shell", - "command": "pdm run duty release ${input:version}" + "type": "process", + "command": "scripts/make", + "args": ["release", "${input:version}"] }, { "label": "setup", - "type": "shell", - "command": "bash scripts/setup.sh" + "type": "process", + "command": "scripts/make", + "args": ["setup"] }, { "label": "test", - "type": "shell", - "command": "pdm run duty test coverage", + "type": "process", + "command": "scripts/make", + "args": ["test", "coverage"], "group": "test" }, { "label": "vscode", - "type": "shell", - "command": "pdm run duty vscode" + "type": "process", + "command": "scripts/make", + "args": ["vscode"] } ], "inputs": [ diff --git a/devdeps.txt b/devdeps.txt new file mode 100644 index 00000000..4fe97996 --- /dev/null +++ b/devdeps.txt @@ -0,0 +1,27 @@ +build>=1.0 +duty>=0.10 +black>=23.9 +markdown-callouts>=0.3 +markdown-exec>=1.7 +mkdocs>=1.5 +mkdocs-coverage>=1.0 +mkdocs-gen-files>=0.5 +mkdocs-git-committers-plugin-2>=1.2 +mkdocs-literate-nav>=0.6 +mkdocs-material>=9.4 +mkdocs-minify-plugin>=0.7 +mkdocstrings[python]>=0.23 +tomli>=2.0; python_version < '3.11' +black>=23.9 +blacken-docs>=1.16 +git-changelog>=2.3 +ruff>=0.0 +pytest>=7.4 +pytest-cov>=4.1 +pytest-randomly>=3.15 +pytest-xdist>=3.3 +mypy>=1.5 +types-markdown>=3.5 +types-pyyaml>=6.0 +safety>=2.3 +twine>=5.0 diff --git a/docs/insiders/goals.yml b/docs/insiders/goals.yml index 8b6cb2b0..381e5029 100644 --- a/docs/insiders/goals.yml +++ b/docs/insiders/goals.yml @@ -9,10 +9,16 @@ goals: ref: /usage/configuration/headings/#show_symbol_type_toc since: 2023/06/04 1000: - name: GraviFridge User Manual + name: GraviFridge Fluid Renewal features: - name: Auto-summary of object members ref: /usage/configuration/members/#summary since: 2023/08/20 - name: Automatic rendering of function signature overloads since: 2023/09/05 + 1500: + name: HyperLamp Navigation Tips + features: [] + 2000: + name: FusionDrive Ejection Configuration + features: [] diff --git a/docs/insiders/index.md b/docs/insiders/index.md index a6642ede..9a0ae309 100644 --- a/docs/insiders/index.md +++ b/docs/insiders/index.md @@ -49,9 +49,8 @@ The biggest bottleneck in Open Source is time.[^3] If you're unsure if you should sponsor this project, check out the list of [completed funding goals][goals completed] to learn whether you're already using features that -were developed with the help of sponsorships. - +were developed with the help of sponsorships. You're most likely using at least +a handful of them, [thanks to our awesome sponsors][sponsors]! ## What's in it for me? @@ -173,7 +172,7 @@ This section lists all funding goals that were previously completed, which means that those features were part of Insiders, but are now generally available and can be used by all users. -```python exec="1" session="insiders" +```python exec="1" session="insiders" idprefix="" for goal in goals.values(): if goal.complete: goal.render() diff --git a/duties.py b/duties.py index 55fcf6a2..1c3f6b79 100644 --- a/duties.py +++ b/duties.py @@ -22,7 +22,7 @@ CI = os.environ.get("CI", "0") in {"1", "true", "yes", ""} WINDOWS = os.name == "nt" PTY = not WINDOWS and not CI -MULTIRUN = os.environ.get("PDM_MULTIRUN", "0") == "1" +MULTIRUN = os.environ.get("MULTIRUN", "0") == "1" def pyprefix(title: str) -> str: # noqa: D103 @@ -72,7 +72,6 @@ def check_quality(ctx: Context) -> None: Parameters: ctx: The context instance (passed automatically). """ - os.environ["MYPYPATH"] = "src" ctx.run( ruff.check(*PY_SRC_LIST, config="config/ruff.toml"), title=pyprefix("Checking code quality"), @@ -89,15 +88,15 @@ def check_dependencies(ctx: Context) -> None: """ # retrieve the list of dependencies requirements = ctx.run( - ["pdm", "export", "-f", "requirements", "--without-hashes"], - title="Exporting dependencies as requirements", + ["uv", "pip", "freeze"], + silent=True, allow_overrides=False, ) ctx.run( safety.check(requirements), title="Checking dependencies", - command="pdm export -f requirements --without-hashes | safety check --stdin", + command="uv pip freeze | safety check --stdin", ) @@ -144,9 +143,9 @@ def check_api(ctx: Context) -> None: griffe_check = lazy(g_check, name="griffe.check") ctx.run( - griffe_check("mkdocstrings_handlers", search_paths=["src"], color=True), + griffe_check("mkdocstrings_handlers.python", search_paths=["src"], color=True), title="Checking for API breaking changes", - command="griffe check -ssrc mkdocstrings_handlers", + command="griffe check -ssrc mkdocstrings_handlers.python", nofail=True, ) @@ -201,7 +200,11 @@ def docs_deploy(ctx: Context) -> None: ctx.run(lambda: False, title="Not deploying docs without Material for MkDocs Insiders!") origin = ctx.run("git config --get remote.origin.url", silent=True) if "pawamoy-insiders/mkdocstrings-python" in origin: - ctx.run("git remote add upstream git@github.com:mkdocstrings/python", silent=True, nofail=True) + ctx.run( + "git remote add upstream git@github.com:mkdocstrings/python", + silent=True, + nofail=True, + ) ctx.run( mkdocs.gh_deploy(remote_name="upstream", force=True), title="Deploying documentation", @@ -247,7 +250,7 @@ def release(ctx: Context, version: str) -> None: ctx.run(f"git tag {version}", title="Tagging commit", pty=PTY) ctx.run("git push", title="Pushing commits", pty=False) ctx.run("git push --tags", title="Pushing tags", pty=False) - ctx.run("pdm build", title="Building dist/wheel", pty=PTY) + ctx.run("pyproject-build", title="Building dist/wheel", pty=PTY) ctx.run("twine upload --skip-existing dist/*", title="Publishing version", pty=PTY) diff --git a/pyproject.toml b/pyproject.toml index 75643e9a..222a7400 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,6 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Topic :: Documentation", "Topic :: Software Development", - "Topic :: Software Development :: Documentation", "Topic :: Utilities", "Typing :: Typed", ] @@ -45,51 +44,8 @@ Funding = "https://github.com/sponsors/pawamoy" [tool.pdm] version = {source = "scm"} -plugins = [ - "pdm-multirun", -] [tool.pdm.build] package-dir = "src" includes = ["src/mkdocstrings_handlers"] editable-backend = "editables" - -[tool.pdm.dev-dependencies] -duty = ["duty>=0.10"] -ci-quality = ["mkdocstrings-python[duty,docs,quality,typing,security]"] -ci-tests = ["mkdocstrings-python[duty,docs,tests]"] -docs = [ - "black>=23.9", - "markdown-callouts>=0.3", - "markdown-exec>=1.7", - "mkdocs>=1.5", - "mkdocs-coverage>=1.0", - "mkdocs-gen-files>=0.5", - "mkdocs-git-committers-plugin-2>=1.2", - "mkdocs-literate-nav>=0.6", - "mkdocs-material>=9.4", - "mkdocs-minify-plugin>=0.7", - "tomli>=2.0; python_version < '3.11'", -] -maintain = [ - "black>=23.9", - "blacken-docs>=1.16", - "git-changelog>=2.3", -] -quality = [ - "ruff>=0.0", -] -tests = [ - "pytest>=7.4", - "pytest-cov>=4.1", - "pytest-randomly>=3.15", - "pytest-xdist>=3.3", -] -typing = [ - "mypy>=1.5", - "types-markdown>=3.5", - "types-pyyaml>=6.0", -] -security = [ - "safety>=2.3", -] diff --git a/scripts/gen_credits.py b/scripts/gen_credits.py index bf35f0da..a1115f55 100644 --- a/scripts/gen_credits.py +++ b/scripts/gen_credits.py @@ -3,16 +3,17 @@ from __future__ import annotations import os -import re import sys -from importlib.metadata import PackageNotFoundError, metadata +from collections import defaultdict +from importlib.metadata import distributions from itertools import chain from pathlib import Path from textwrap import dedent -from typing import Mapping, cast +from typing import Dict, Iterable, Union from jinja2 import StrictUndefined from jinja2.sandbox import SandboxedEnvironment +from packaging.requirements import Requirement # TODO: Remove once support for Python 3.10 is dropped. if sys.version_info >= (3, 11): @@ -24,71 +25,120 @@ with project_dir.joinpath("pyproject.toml").open("rb") as pyproject_file: pyproject = tomllib.load(pyproject_file) project = pyproject["project"] -pdm = pyproject["tool"]["pdm"] -with project_dir.joinpath("pdm.lock").open("rb") as lock_file: - lock_data = tomllib.load(lock_file) -lock_pkgs = {pkg["name"].lower(): pkg for pkg in lock_data["package"]} project_name = project["name"] -regex = re.compile(r"(?P[\w.-]+)(?P.*)$") +with open("devdeps.txt") as devdeps_file: + devdeps = [line.strip() for line in devdeps_file if not line.startswith("-e")] +PackageMetadata = Dict[str, Union[str, Iterable[str]]] +Metadata = Dict[str, PackageMetadata] -def _get_license(pkg_name: str) -> str: + +def _merge_fields(metadata: dict) -> PackageMetadata: + fields = defaultdict(list) + for header, value in metadata.items(): + fields[header.lower()].append(value.strip()) + return { + field: value if len(value) > 1 or field in ("classifier", "requires-dist") else value[0] + for field, value in fields.items() + } + + +def _norm_name(name: str) -> str: + return name.replace("_", "-").replace(".", "-").lower() + + +def _norm_spec(spec: str) -> set[str]: + clean_spec = spec.split("]", 1)[-1].split(";", 1)[0].replace("(", "").replace(")", "").replace(" ", "").strip() + if clean_spec: + return set(clean_spec.split(",")) + return set() + + +def _requirements(deps: list[str]) -> dict[str, Requirement]: + return {_norm_name((req := Requirement(dep)).name): req for dep in deps} + + +def _extra_marker(req: Requirement) -> str | None: + if not req.marker: + return None try: - data = metadata(pkg_name) - except PackageNotFoundError: - return "?" - license_name = cast(dict, data).get("License", "").strip() - multiple_lines = bool(license_name.count("\n")) - # TODO: Remove author logic once all my packages licenses are fixed. - author = "" - if multiple_lines or not license_name or license_name == "UNKNOWN": - for header, value in cast(dict, data).items(): - if header == "Classifier" and value.startswith("License ::"): - license_name = value.rsplit("::", 1)[1].strip() - elif header == "Author-email": - author = value - if license_name == "Other/Proprietary License" and "pawamoy" in author: - license_name = "ISC" - return license_name or "?" - - -def _get_deps(base_deps: Mapping[str, Mapping[str, str]]) -> dict[str, dict[str, str]]: + return next(marker[2].value for marker in req.marker._markers if getattr(marker[0], "value", None) == "extra") + except StopIteration: + return None + + +def _get_metadata() -> Metadata: + metadata = {} + for pkg in distributions(): + name = _norm_name(pkg.name) # type: ignore[attr-defined,unused-ignore] + metadata[name] = _merge_fields(pkg.metadata) # type: ignore[arg-type] + metadata[name]["spec"] = set() + metadata[name]["extras"] = set() + _set_license(metadata[name]) + return metadata + + +def _set_license(metadata: PackageMetadata) -> None: + license_field = metadata.get("license-expression", metadata.get("license", "")) + license_name = license_field if isinstance(license_field, str) else " + ".join(license_field) + check_classifiers = license_name in ("UNKNOWN", "Dual License", "") or license_name.count("\n") + if check_classifiers: + license_names = [] + for classifier in metadata["classifier"]: + if classifier.startswith("License ::"): + license_names.append(classifier.rsplit("::", 1)[1].strip()) + license_name = " + ".join(license_names) + metadata["license"] = license_name or "?" + + +def _get_deps(base_deps: dict[str, Requirement], metadata: Metadata) -> Metadata: deps = {} - for dep in base_deps: - parsed = regex.match(dep).groupdict() # type: ignore[union-attr] - dep_name = parsed["dist"].lower() - if dep_name not in lock_pkgs: + for dep_name, dep_req in base_deps.items(): + if dep_name not in metadata: continue - deps[dep_name] = {"license": _get_license(dep_name), **parsed, **lock_pkgs[dep_name]} + metadata[dep_name]["spec"] |= {str(spec) for spec in dep_req.specifier} # type: ignore[operator] + metadata[dep_name]["extras"] |= dep_req.extras # type: ignore[operator] + deps[dep_name] = metadata[dep_name] again = True while again: again = False - for pkg_name in lock_pkgs: + for pkg_name in metadata: if pkg_name in deps: - for pkg_dependency in lock_pkgs[pkg_name].get("dependencies", []): - parsed = regex.match(pkg_dependency).groupdict() # type: ignore[union-attr] - dep_name = parsed["dist"].lower() - if dep_name in lock_pkgs and dep_name not in deps and dep_name != project["name"]: - deps[dep_name] = {"license": _get_license(dep_name), **parsed, **lock_pkgs[dep_name]} + for pkg_dependency in metadata[pkg_name].get("requires-dist", []): + requirement = Requirement(pkg_dependency) + dep_name = _norm_name(requirement.name) + extra_marker = _extra_marker(requirement) + if ( + dep_name in metadata + and dep_name not in deps + and dep_name != project["name"] + and (not extra_marker or extra_marker in deps[pkg_name]["extras"]) + ): + metadata[dep_name]["spec"] |= {str(spec) for spec in requirement.specifier} # type: ignore[operator] + deps[dep_name] = metadata[dep_name] again = True return deps def _render_credits() -> str: - dev_dependencies = _get_deps(chain(*pdm.get("dev-dependencies", {}).values())) # type: ignore[arg-type] + metadata = _get_metadata() + dev_dependencies = _get_deps(_requirements(devdeps), metadata) prod_dependencies = _get_deps( - chain( # type: ignore[arg-type] - project.get("dependencies", []), - chain(*project.get("optional-dependencies", {}).values()), + _requirements( + chain( # type: ignore[arg-type] + project.get("dependencies", []), + chain(*project.get("optional-dependencies", {}).values()), + ), ), + metadata, ) template_data = { "project_name": project_name, - "prod_dependencies": sorted(prod_dependencies.values(), key=lambda dep: dep["name"]), - "dev_dependencies": sorted(dev_dependencies.values(), key=lambda dep: dep["name"]), + "prod_dependencies": sorted(prod_dependencies.values(), key=lambda dep: str(dep["name"])), + "dev_dependencies": sorted(dev_dependencies.values(), key=lambda dep: str(dep["name"])), "more_credits": "http://pawamoy.github.io/credits/", } template_text = dedent( @@ -98,13 +148,14 @@ def _render_credits() -> str: These projects were used to build *{{ project_name }}*. **Thank you!** [`python`](https://www.python.org/) | - [`pdm`](https://pdm.fming.dev/) | - [`copier-pdm`](https://github.com/pawamoy/copier-pdm) + [`uv`](https://github.com/astral-sh/uv) | + [`copier-uv`](https://github.com/pawamoy/copier-uv) {% macro dep_line(dep) -%} - [`{{ dep.name }}`](https://pypi.org/project/{{ dep.name }}/) | {{ dep.summary }} | {{ ("`" ~ dep.spec ~ "`") if dep.spec else "" }} | `{{ dep.version }}` | {{ dep.license }} + [`{{ dep.name }}`](https://pypi.org/project/{{ dep.name }}/) | {{ dep.summary }} | {{ ("`" ~ dep.spec|sort(reverse=True)|join(", ") ~ "`") if dep.spec else "" }} | `{{ dep.version }}` | {{ dep.license }} {%- endmacro %} + {% if prod_dependencies -%} ### Runtime dependencies Project | Summary | Version (accepted) | Version (last resolved) | License @@ -113,6 +164,8 @@ def _render_credits() -> str: {{ dep_line(dep) }} {% endfor %} + {% endif -%} + {% if dev_dependencies -%} ### Development dependencies Project | Summary | Version (accepted) | Version (last resolved) | License @@ -121,6 +174,7 @@ def _render_credits() -> str: {{ dep_line(dep) }} {% endfor %} + {% endif -%} {% if more_credits %}**[More credits from the author]({{ more_credits }})**{% endif %} """, ) diff --git a/scripts/insiders.py b/scripts/insiders.py index 85ecbd0e..15212486 100644 --- a/scripts/insiders.py +++ b/scripts/insiders.py @@ -78,9 +78,16 @@ def human_readable_amount(self) -> str: # noqa: D102 def render(self, rel_base: str = "..") -> None: # noqa: D102 print(f"#### $ {self.human_readable_amount} — {self.name}\n") - for feature in self.features: - feature.render(rel_base) - print("") + if self.features: + for feature in self.features: + feature.render(rel_base) + print("") + else: + print("There are no features in this goal for this project. ") + print( + "[See the features in this goal **for all Insiders projects.**]" + f"(https://pawamoy.github.io/insiders/#{self.amount}-{self.name.lower().replace(' ', '-')})", + ) def load_goals(data: str, funding: int = 0, project: Project | None = None) -> dict[int, Goal]: @@ -104,8 +111,7 @@ def load_goals(data: str, funding: int = 0, project: Project | None = None) -> d Feature( name=feature_data["name"], ref=feature_data.get("ref"), - since=feature_data.get("since") - and datetime.strptime(feature_data["since"], "%Y/%m/%d").date(), # noqa: DTZ007 + since=feature_data.get("since") and datetime.strptime(feature_data["since"], "%Y/%m/%d").date(), # noqa: DTZ007 project=project, ) for feature_data in goal_data["features"] diff --git a/scripts/make b/scripts/make new file mode 100755 index 00000000..4190622e --- /dev/null +++ b/scripts/make @@ -0,0 +1,155 @@ +#!/usr/bin/env bash + +set -e +export PYTHON_VERSIONS=${PYTHON_VERSIONS-3.8 3.9 3.10 3.11 3.12} + +exe="" +prefix="" + + +# Install runtime and development dependencies, +# as well as current project in editable mode. +uv_install() { + uv pip compile pyproject.toml devdeps.txt | uv pip install -r - + uv pip install -e . +} + + +# Setup the development environment by installing dependencies +# in multiple Python virtual environments with uv: +# one venv per Python version in `.venvs/$py`, +# and an additional default venv in `.venv`. +setup() { + if ! command -v uv &>/dev/null; then + echo "make: setup: uv must be installed, see https://github.com/astral-sh/uv" >&2 + return 1 + fi + + if [ -n "${PYTHON_VERSIONS}" ]; then + for version in ${PYTHON_VERSIONS}; do + if [ ! -d ".venvs/${version}" ]; then + uv venv --seed --python "${version}" ".venvs/${version}" + fi + VIRTUAL_ENV="${PWD}/.venvs/${version}" uv_install + done + fi + + if [ ! -d .venv ]; then uv venv --seed --python python; fi + uv_install +} + + +# Activate a Python virtual environments. +# The annoying operating system also requires +# that we set some global variables to help it find commands... +activate() { + local path + if [ -f "$1/bin/activate" ]; then + source "$1/bin/activate" + return 0 + fi + if [ -f "$1/Scripts/activate.bat" ]; then + "$1/Scripts/activate.bat" + exe=".exe" + prefix="$1/Scripts/" + return 0 + fi + echo "run: Cannot activate venv $1" >&2 + return 1 +} + + +# Run a command in all configured Python virtual environments. +# We handle the case when the `PYTHON_VERSIONS` environment variable +# is unset or empty, for robustness. +multirun() { + local cmd="$1" + shift + + if [ -n "${PYTHON_VERSIONS}" ]; then + for version in ${PYTHON_VERSIONS}; do + (activate ".venvs/${version}" && MULTIRUN=1 "${prefix}${cmd}${exe}" "$@") + done + else + (activate .venv && "${prefix}${cmd}${exe}" "$@") + fi +} + + +# Run a command in the default Python virtual environment. +# We rely on `multirun`'s handling of empty `PYTHON_VERSIONS`. +singlerun() { + PYTHON_VERSIONS= multirun "$@" +} + + +# Record options following a command name, +# until a non-option argument is met or there are no more arguments. +# Output each option on a new line, so the parent caller can store them in an array. +# Return the number of times the parent caller must shift arguments. +options() { + local shift_count=0 + for arg in "$@"; do + if [[ "${arg}" =~ ^- || "${arg}" =~ ^.+= ]]; then + echo "${arg}" + ((shift_count++)) + else + break + fi + done + return ${shift_count} +} + + +# Main function. +main() { + local cmd + while [ $# -ne 0 ]; do + cmd="$1" + shift + + # Handle `run` early to simplify `case` below. + if [ "${cmd}" = "run" ]; then + singlerun "$@" + exit $? + fi + + # Handle `multirun` early to simplify `case` below. + if [ "${cmd}" = "multirun" ]; then + multirun "$@" + exit $? + fi + + # All commands except `run` and `multirun` can be chained on a single line. + # Some of them accept options in two formats: `-f`, `--flag` and `param=value`. + # Some of them don't, and will print warnings/errors if options were given. + opts=($(options "$@")) || shift $? + + case "${cmd}" in + # The following commands require special handling. + help|"") + singlerun duty --list ;; + setup) + setup ;; + check) + multirun duty check-quality check-types check-docs + singlerun duty check-dependencies check-api + ;; + + # The following commands run in all venvs. + check-quality|\ + check-docs|\ + check-types|\ + test) + multirun duty "${cmd}" "${opts[@]}" ;; + + # The following commands run in the default venv only. + *) + singlerun duty "${cmd}" "${opts[@]}" ;; + esac + done +} + + +# Execute the main function. +main "$@" diff --git a/scripts/setup.sh b/scripts/setup.sh deleted file mode 100755 index eef38433..00000000 --- a/scripts/setup.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -e - -if ! command -v pdm &>/dev/null; then - if ! command -v pipx &>/dev/null; then - python3 -m pip install --user pipx - fi - pipx install pdm -fi -if ! pdm self list 2>/dev/null | grep -q pdm-multirun; then - pdm install --plugins -fi - -if [ -n "${PDM_MULTIRUN_VERSIONS}" ]; then - if [ "${PDM_MULTIRUN_USE_VENVS}" -eq "1" ]; then - for version in ${PDM_MULTIRUN_VERSIONS}; do - if ! pdm venv --path "${version}" &>/dev/null; then - pdm venv create --name "${version}" "${version}" - fi - done - fi - pdm multirun -v pdm install -G:all -else - pdm install -G:all -fi diff --git a/src/mkdocstrings_handlers/python/__init__.py b/src/mkdocstrings_handlers/python/__init__.py index f93ab20e..0432a90d 100644 --- a/src/mkdocstrings_handlers/python/__init__.py +++ b/src/mkdocstrings_handlers/python/__init__.py @@ -1,9 +1,5 @@ -"""This package implements a handler for the Python language.""" +"""Python handler for mkdocstrings.""" from mkdocstrings_handlers.python.handler import get_handler __all__ = ["get_handler"] - -# TODO: CSS classes everywhere in templates -# TODO: name normalization (filenames, Jinja2 variables, HTML tags, CSS classes) -# TODO: Jinja2 blocks everywhere in templates diff --git a/src/mkdocstrings_handlers/py.typed b/src/mkdocstrings_handlers/python/py.typed similarity index 100% rename from src/mkdocstrings_handlers/py.typed rename to src/mkdocstrings_handlers/python/py.typed diff --git a/tests/conftest.py b/tests/conftest.py index 1c1a1c54..f7b28105 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -60,7 +60,7 @@ def fixture_plugin(mkdocs_conf: config.Config) -> MkdocstringsPlugin: """Return a plugin instance. Parameters: - mkdocs_conf: Pytest fixture: [tests.conftest.fixture_mkdocs_conf][]. + mkdocs_conf: Pytest fixture (see conftest.py). Returns: mkdocstrings plugin instance. @@ -73,7 +73,7 @@ def fixture_ext_markdown(mkdocs_conf: config.Config) -> Markdown: """Return a Markdown instance with MkdocstringsExtension. Parameters: - mkdocs_conf: Pytest fixture: [tests.conftest.fixture_mkdocs_conf][]. + mkdocs_conf: Pytest fixture (see conftest.py). Returns: A Markdown instance. @@ -86,7 +86,7 @@ def fixture_handler(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> Pytho """Return a handler instance. Parameters: - plugin: Pytest fixture: [tests.conftest.fixture_plugin][]. + plugin: Pytest fixture (see conftest.py). Returns: A handler instance. diff --git a/tests/test_themes.py b/tests/test_themes.py index bedcc806..a4ad0d59 100644 --- a/tests/test_themes.py +++ b/tests/test_themes.py @@ -2,7 +2,6 @@ from __future__ import annotations -import sys from typing import TYPE_CHECKING import pytest @@ -22,7 +21,7 @@ indirect=["plugin"], ) @pytest.mark.parametrize( - "module", + "identifier", [ "mkdocstrings.extension", "mkdocstrings.inventory", @@ -33,15 +32,15 @@ "mkdocstrings_handlers.python", ], ) -@pytest.mark.skipif(sys.version_info < (3, 7), reason="material is not installed on Python 3.6") -def test_render_themes_templates_python(module: str, plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> None: +def test_render_themes_templates_python(identifier: str, plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> None: """Test rendering of a given theme's templates. Parameters: - module: Parametrized argument. - plugin: Pytest fixture: [tests.conftest.fixture_plugin][]. + identifier: Parametrized identifier. + plugin: Pytest fixture (see conftest.py). + ext_markdown: Pytest fixture (see conftest.py). """ handler = plugin.handlers.get_handler("python") handler._update_env(ext_markdown, plugin.handlers._config) - data = handler.collect(module, {}) + data = handler.collect(identifier, {}) handler.render(data, {}) From cd93ee31418a2752667d43bb5a05d22284522c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 13 Mar 2024 19:58:24 +0100 Subject: [PATCH 11/13] deps: Add upper bound on Python-Markdown 3.6 to temporarily prevent breaking changes --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 222a7400..05438338 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ + "markdown>=3.3,<3.6", "mkdocstrings>=0.20", "griffe>=0.37", ] From ddf32c6697f895287c9f5546e51656183e569cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 13 Mar 2024 20:02:25 +0100 Subject: [PATCH 12/13] docs: Enable inline syntax highlight --- mkdocs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index 3d21de72..9a739787 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -111,6 +111,10 @@ markdown_extensions: - pymdownx.emoji: emoji_index: !!python/name:material.extensions.emoji.twemoji emoji_generator: !!python/name:material.extensions.emoji.to_svg +- pymdownx.highlight: + pygments_lang_class: true +- pymdownx.inlinehilite: + style_plain_text: py3 - pymdownx.magiclink - pymdownx.snippets: auto_append: [docs/.glossary.md] From e639c8b1a07aed6ac25eb86c790d7cea1f1628c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 13 Mar 2024 20:04:48 +0100 Subject: [PATCH 13/13] chore: Prepare release 1.9.0 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c5647dd..4bc0d6a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,23 @@ 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.9.0](https://github.com/mkdocstrings/python/releases/tag/1.9.0) - 2024-03-13 + +[Compare with 1.8.0](https://github.com/mkdocstrings/python/compare/1.8.0...1.9.0) + +### Dependencies + +- Add upper bound on Python-Markdown 3.6 to temporarily prevent breaking changes ([cd93ee3](https://github.com/mkdocstrings/python/commit/cd93ee31418a2752667d43bb5a05d22284522c24) by Timothée Mazzucotelli). + +### Features + +- Add `show_labels` option to show/hide labels ([eaf9b82](https://github.com/mkdocstrings/python/commit/eaf9b8240069f7369f401fe048892043c8b173d3) by Viicos). [Issue #120](https://github.com/mkdocstrings/python/issues/120), [PR #130](https://github.com/mkdocstrings/python/pull/130) +- Add option to search for stubs packages ([0c6aa32](https://github.com/mkdocstrings/python/commit/0c6aa323c9e57b8348765a5daa11c79d0c5edb07) by Romain). [PR #128](https://github.com/mkdocstrings/python/pull/128), PR griffe#221: : https://github.com/mkdocstrings/griffe/pull/221 + +### Code Refactoring + +- Mark all Jinja blocks as scoped ([548bdad](https://github.com/mkdocstrings/python/commit/548bdaddd66ffc99b3b9a5a62228a2ff4ff0dd00) by Timothée Mazzucotelli). + ## [1.8.0](https://github.com/mkdocstrings/python/releases/tag/1.8.0) - 2024-01-08 [Compare with 1.7.5](https://github.com/mkdocstrings/python/compare/1.7.5...1.8.0)