From ad959b848482108c68e800091be1ccf84a88a700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 8 Oct 2021 11:46:38 +0200 Subject: [PATCH 01/12] docs: Clean up README --- README.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/README.md b/README.md index cb207ff0..e6ede3ef 100644 --- a/README.md +++ b/README.md @@ -91,10 +91,6 @@ Automatic documentation from sources, for [MkDocs](https://mkdocs.org/). - **Source code display:** *mkdocstrings* can add a collapsible div containing the highlighted source code of the Python object. -## Roadmap - -See the [Feature Roadmap issue](https://github.com/mkdocstrings/mkdocstrings/issues/183) on the bugtracker. - ## Requirements *mkdocstrings* requires Python 3.6 or above. @@ -119,13 +115,6 @@ pyenv global system 3.6.12 ``` -This project currently only works with the Material theme of MkDocs. -Therefore, it is required that you have it installed. - -``` -pip install mkdocs-material -``` - ## Installation With `pip`: From 1353e4d793e5d0f57f0ae0e9ac3bae17bd6b373b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Fri, 8 Oct 2021 11:47:51 +0200 Subject: [PATCH 02/12] chore: Match pytkdocs `requires-python` --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5e3fa81c..41fe7140 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ description = "Automatic documentation from sources, for MkDocs." authors = [{name = "Timothée Mazzucotelli", email = "pawamoy@pm.me"}] license = {file = "LICENSE"} readme = "README.md" -requires-python = ">=3.6" +requires-python = ">=3.6.1" keywords = ["mkdocs", "mkdocs-plugin", "docstrings", "autodoc", "documentation"] dynamic = ["version", "classifiers"] classifiers = [ From f6cf570255df17db1088b6e6cd94bcc823b3b17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sun, 10 Oct 2021 13:07:30 +0200 Subject: [PATCH 03/12] fix: Do minimum work when falling back to re-collecting an object to get its anchor This change introduces a new attribute on collectors: `fallback_config`. It is used by the `Handlers.get_anchor` method when collecting an object to find its anchor. It allows to pass specific options to the collector to avoid collecting the object members or, for example, parsing Python docstrings, as it is not useful, since we only care about the anchor. Issue #329: https://github.com/mkdocstrings/mkdocstrings/issues/329 PR #330: https://github.com/mkdocstrings/mkdocstrings/issues/330 --- pyproject.toml | 2 +- src/mkdocstrings/handlers/base.py | 3 ++- src/mkdocstrings/handlers/python.py | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 41fe7140..ecd9540e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ dependencies = [ "mkdocs~=1.2", "mkdocs-autorefs>=0.1,<0.4", "pymdown-extensions>=6.3,<10.0", - "pytkdocs>=0.2.0,<0.13.0", + "pytkdocs~=0.14.0", ] [project.urls] diff --git a/src/mkdocstrings/handlers/base.py b/src/mkdocstrings/handlers/base.py index f496e7ed..2b199c15 100644 --- a/src/mkdocstrings/handlers/base.py +++ b/src/mkdocstrings/handlers/base.py @@ -339,8 +339,9 @@ def get_anchor(self, identifier: str) -> Optional[str]: A string - anchor without '#', or None if there isn't any identifier familiar with it. """ for handler in self._handlers.values(): + fallback_config = getattr(handler.collector, "fallback_config", {}) try: - anchor = handler.renderer.get_anchor(handler.collector.collect(identifier, {})) + anchor = handler.renderer.get_anchor(handler.collector.collect(identifier, fallback_config)) except CollectionError: continue if anchor is not None: diff --git a/src/mkdocstrings/handlers/python.py b/src/mkdocstrings/handlers/python.py index 0aab09ac..a9fab089 100644 --- a/src/mkdocstrings/handlers/python.py +++ b/src/mkdocstrings/handlers/python.py @@ -141,6 +141,21 @@ class PythonCollector(BaseCollector): Obviously one could use a single filter instead: `"!^_[^_]"`, which is the default. """ + fallback_config = {"docstring_style": "markdown", "filters": ["!.*"]} + """The configuration used when falling back to re-collecting an object to get its anchor. + + This configuration is used in [`Handlers.get_anchor`][mkdocstrings.handlers.base.Handlers.get_anchor]. + + When trying to fix (optional) cross-references, the autorefs plugin will try to collect + an object with every configured handler until one succeeds. It will then try to get + an anchor for it. It's because objects can have multiple identifiers (aliases), + for example their definition path and multiple import paths in Python. + + When re-collecting the object, we have no use for its members, or for its docstring being parsed. + This is why the fallback configuration filters every member out, and uses the Markdown style, + which we know will not generate any warnings. + """ + def __init__(self, setup_commands: Optional[List[str]] = None) -> None: """Initialize the object. From 40c3e5fd094acbd9ac6397b58f5f60b95689f7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20K=C3=B6ch?= Date: Sun, 31 Oct 2021 13:05:19 +0000 Subject: [PATCH 04/12] docs: Fix admonitions link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6ede3ef..c489bb62 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Automatic documentation from sources, for [MkDocs](https://mkdocs.org/). Numpy-style requires an extra dependency from `pytkdocs`: `pytkdocs[numpy-style]`.* - **Admonition support in docstrings:** blocks like `Note:` or `Warning:` will be transformed - to their [admonition](https://squidfunk.github.io/mkdocs-material/extensions/admonition/) equivalent. + to their [admonition](https://squidfunk.github.io/mkdocs-material/reference/admonitions/) equivalent. *We do not support nested admonitions in docstrings!* - **Every object has a TOC entry:** we render a heading for each object, meaning *MkDocs* picks them into the Table From 78c498c4a6cfc33cc6ceab9829426bd64e518d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 14 Dec 2021 18:52:06 +0100 Subject: [PATCH 05/12] refactor: Return multiple identifiers from fallback method Since an object can have aliases (different identifiers leading to it), and since users sometimes want to render an object using one of its aliases instead of its canonical identifier, we make sure to register every identifier associated to an object so that autorefs can find it when fixing cross-references. Issue mkdocstrings/autorefs#11: https://github.com/mkdocstrings/autorefs/issues/11 PR #350: https://github.com/mkdocstrings/mkdocstrings/pull/350 --- pyproject.toml | 4 ++-- src/mkdocstrings/extension.py | 26 +++++++++++++++++--------- src/mkdocstrings/handlers/base.py | 28 +++++++++++++++------------- src/mkdocstrings/handlers/python.py | 11 +++++++---- src/mkdocstrings/plugin.py | 2 +- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ecd9540e..df75e5ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,14 +4,13 @@ build-backend = "pdm.pep517.api" [project] name = "mkdocstrings" -version = {use_scm = true} description = "Automatic documentation from sources, for MkDocs." authors = [{name = "Timothée Mazzucotelli", email = "pawamoy@pm.me"}] license = {file = "LICENSE"} readme = "README.md" requires-python = ">=3.6.1" keywords = ["mkdocs", "mkdocs-plugin", "docstrings", "autodoc", "documentation"] -dynamic = ["version", "classifiers"] +dynamic = ["version"] classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: ISC License (ISCL)", @@ -45,6 +44,7 @@ mkdocstrings = "mkdocstrings.plugin:MkdocstringsPlugin" [tool.pdm] package-dir = "src" includes = ["src/mkdocstrings"] +version = {use_scm = true} [tool.pdm.dev-dependencies] duty = ["duty~=0.6"] diff --git a/src/mkdocstrings/extension.py b/src/mkdocstrings/extension.py index afe59708..7f40a193 100644 --- a/src/mkdocstrings/extension.py +++ b/src/mkdocstrings/extension.py @@ -117,7 +117,7 @@ def run(self, parent: Element, blocks: MutableSequence[str]) -> None: heading_level = match["heading"].count("#") log.debug(f"Matched '::: {identifier}'") - html, handler = self._process_block(identifier, block, heading_level) + html, handler, data = self._process_block(identifier, block, heading_level) el = Element("div", {"class": "mkdocstrings"}) # The final HTML is inserted as opaque to subsequent processing, and only revealed at the end. el.text = self.md.htmlStash.store(html) @@ -125,17 +125,20 @@ def run(self, parent: Element, blocks: MutableSequence[str]) -> None: headings = handler.renderer.get_headings() el.extend(headings) - for heading in headings: - page = self._autorefs.current_page - anchor = heading.attrib["id"] + page = self._autorefs.current_page + for anchor in handler.renderer.get_anchors(data): self._autorefs.register_anchor(page, anchor) + for heading in headings: + anchor = heading.attrib["id"] # noqa: WPS440 + self._autorefs.register_anchor(page, anchor) # noqa: WPS441 + if "data-role" in heading.attrib: self._handlers.inventory.register( - name=anchor, + name=anchor, # noqa: WPS441 domain=handler.domain, role=heading.attrib["data-role"], - uri=f"{page}#{anchor}", + uri=f"{page}#{anchor}", # noqa: WPS441 ) parent.append(el) @@ -146,7 +149,12 @@ def run(self, parent: Element, blocks: MutableSequence[str]) -> None: # list for future processing. blocks.insert(0, the_rest) - def _process_block(self, identifier: str, yaml_block: str, heading_level: int = 0) -> Tuple[str, BaseHandler]: + def _process_block( + self, + identifier: str, + yaml_block: str, + heading_level: int = 0, + ) -> Tuple[str, BaseHandler, CollectorItem]: """Process an autodoc block. Arguments: @@ -159,7 +167,7 @@ def _process_block(self, identifier: str, yaml_block: str, heading_level: int = TemplateNotFound: When a template used for rendering could not be found. Returns: - Rendered HTML and the handler that was used. + Rendered HTML, the handler that was used, and the collected item. """ config = yaml.safe_load(yaml_block) or {} handler_name = self._handlers.get_handler_name(config) @@ -196,7 +204,7 @@ def _process_block(self, identifier: str, yaml_block: str, heading_level: int = ) raise - return (rendered, handler) + return rendered, handler, data def get_item_configs(handler_config: dict, config: dict) -> Tuple[Mapping, Mapping]: diff --git a/src/mkdocstrings/handlers/base.py b/src/mkdocstrings/handlers/base.py index 2b199c15..1a3a5781 100644 --- a/src/mkdocstrings/handlers/base.py +++ b/src/mkdocstrings/handlers/base.py @@ -125,18 +125,20 @@ def render(self, data: CollectorItem, config: dict) -> str: The rendered template as HTML. """ # noqa: DAR202 (excess return section) - def get_anchor(self, data: CollectorItem) -> Optional[str]: - """Return the canonical identifier (HTML anchor) for a collected item. - - This must match what the renderer would've actually rendered, - e.g. if rendering the item contains `

...` then the return value should be "foo". + def get_anchors(self, data: CollectorItem) -> Sequence[str]: + """Return the possible identifiers (HTML anchors) for a collected item. Arguments: data: The collected data. Returns: - The HTML anchor (without '#') as a string, or None if this item doesn't have an anchor. - """ # noqa: DAR202 (excess return section) + The HTML anchors (without '#'), or an empty tuple if this item doesn't have an anchor. + """ + # TODO: remove this at some point + try: + return (self.get_anchor(data),) # type: ignore + except AttributeError: + return () def do_convert_markdown(self, text: str, heading_level: int, html_id: str = "") -> Markup: """Render Markdown text; for use inside templates. @@ -329,24 +331,24 @@ def __init__(self, config: dict) -> None: self._handlers: Dict[str, BaseHandler] = {} self.inventory: Inventory = Inventory(project=self._config["site_name"]) - def get_anchor(self, identifier: str) -> Optional[str]: + def get_anchors(self, identifier: str) -> Sequence[str]: """Return the canonical HTML anchor for the identifier, if any of the seen handlers can collect it. Arguments: identifier: The identifier (one that [collect][mkdocstrings.handlers.base.BaseCollector.collect] can accept). Returns: - A string - anchor without '#', or None if there isn't any identifier familiar with it. + A tuple of strings - anchors without '#', or an empty tuple if there isn't any identifier familiar with it. """ for handler in self._handlers.values(): fallback_config = getattr(handler.collector, "fallback_config", {}) try: - anchor = handler.renderer.get_anchor(handler.collector.collect(identifier, fallback_config)) + anchors = handler.renderer.get_anchors(handler.collector.collect(identifier, fallback_config)) except CollectionError: continue - if anchor is not None: - return anchor - return None + if anchors: + return anchors + return () def get_handler_name(self, config: dict) -> str: """Return the handler name defined in an "autodoc" instruction YAML configuration, or the global default handler. diff --git a/src/mkdocstrings/handlers/python.py b/src/mkdocstrings/handlers/python.py index a9fab089..efab7d34 100644 --- a/src/mkdocstrings/handlers/python.py +++ b/src/mkdocstrings/handlers/python.py @@ -10,7 +10,7 @@ import traceback from collections import ChainMap from subprocess import PIPE, Popen # noqa: S404 (what other option, more secure that PIPE do we have? sockets?) -from typing import Any, BinaryIO, Callable, Iterator, List, Optional, Tuple +from typing import Any, BinaryIO, Callable, Iterator, List, Optional, Sequence, Tuple from markdown import Markdown from markupsafe import Markup @@ -95,8 +95,11 @@ def render(self, data: CollectorItem, config: dict) -> str: # noqa: D102 (ignor **{"config": final_config, data["category"]: data, "heading_level": heading_level, "root": True}, ) - def get_anchor(self, data: CollectorItem) -> str: # noqa: D102 (ignore missing docstring) - return data.get("path") + def get_anchors(self, data: CollectorItem) -> Sequence[str]: # noqa: D102 (ignore missing docstring) + try: + return (data["path"],) + except KeyError: + return () def update_env(self, md: Markdown, config: dict) -> None: # noqa: D102 (ignore missing docstring) super().update_env(md, config) @@ -144,7 +147,7 @@ class PythonCollector(BaseCollector): fallback_config = {"docstring_style": "markdown", "filters": ["!.*"]} """The configuration used when falling back to re-collecting an object to get its anchor. - This configuration is used in [`Handlers.get_anchor`][mkdocstrings.handlers.base.Handlers.get_anchor]. + This configuration is used in [`Handlers.get_anchors`][mkdocstrings.handlers.base.Handlers.get_anchors]. When trying to fix (optional) cross-references, the autorefs plugin will try to collect an object with every configured handler until one succeeds. It will then try to get diff --git a/src/mkdocstrings/plugin.py b/src/mkdocstrings/plugin.py index 4e693473..242d5931 100644 --- a/src/mkdocstrings/plugin.py +++ b/src/mkdocstrings/plugin.py @@ -183,7 +183,7 @@ def on_config(self, config: Config, **kwargs) -> Config: # noqa: W0613 (unused config["plugins"]["autorefs"] = autorefs log.debug(f"Added a subdued autorefs instance {autorefs!r}") # Add collector-based fallback in either case. - autorefs.get_fallback_anchor = self.handlers.get_anchor + autorefs.get_fallback_anchor = self.handlers.get_anchors mkdocstrings_extension = MkdocstringsExtension(extension_config, self.handlers, autorefs) config["markdown_extensions"].append(mkdocstrings_extension) From 12864271b7f997af7b421a834919b1e686793905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 15 Dec 2021 20:31:02 +0100 Subject: [PATCH 06/12] feat: Support Keyword Args and Yields sections Issue #205: https://github.com/mkdocstrings/mkdocstrings/issues/205 Issue #324: https://github.com/mkdocstrings/mkdocstrings/issues/324 PR #331: https://github.com/mkdocstrings/mkdocstrings/pull/331 --- .../templates/python/material/docstring.html | 8 ++++++++ .../python/material/keyword_args.html | 20 +++++++++++++++++++ .../templates/python/material/yield.html | 16 +++++++++++++++ .../templates/python/mkdocs/keyword_args.html | 7 +++++++ .../templates/python/mkdocs/yield.html | 5 +++++ .../python/readthedocs/keyword_args.html | 19 ++++++++++++++++++ .../templates/python/readthedocs/yield.html | 17 ++++++++++++++++ 7 files changed, 92 insertions(+) create mode 100644 src/mkdocstrings/templates/python/material/keyword_args.html create mode 100644 src/mkdocstrings/templates/python/material/yield.html create mode 100644 src/mkdocstrings/templates/python/mkdocs/keyword_args.html create mode 100644 src/mkdocstrings/templates/python/mkdocs/yield.html create mode 100644 src/mkdocstrings/templates/python/readthedocs/keyword_args.html create mode 100644 src/mkdocstrings/templates/python/readthedocs/yield.html diff --git a/src/mkdocstrings/templates/python/material/docstring.html b/src/mkdocstrings/templates/python/material/docstring.html index 0c32c01d..f1f179b3 100644 --- a/src/mkdocstrings/templates/python/material/docstring.html +++ b/src/mkdocstrings/templates/python/material/docstring.html @@ -11,10 +11,18 @@ {% with parameters = section.value %} {% include "parameters.html" with context %} {% endwith %} + {% elif section.type == "keyword_args" %} + {% with kwargs = section.value %} + {% include "keyword_args.html" with context %} + {% endwith %} {% elif section.type == "exceptions" %} {% with exceptions = section.value %} {% include "exceptions.html" with context %} {% endwith %} + {% elif section.type == "yield" %} + {% with yield = section.value %} + {% include "yield.html" with context %} + {% endwith %} {% elif section.type == "return" %} {% with return = section.value %} {% include "return.html" with context %} diff --git a/src/mkdocstrings/templates/python/material/keyword_args.html b/src/mkdocstrings/templates/python/material/keyword_args.html new file mode 100644 index 00000000..3396ffa5 --- /dev/null +++ b/src/mkdocstrings/templates/python/material/keyword_args.html @@ -0,0 +1,20 @@ +{{ log.debug() }} +

Keyword arguments:

+ + + + + + + + + + {% for kwarg in kwargs %} + + + + + + {% endfor %} + +
NameTypeDescription
{{ kwarg.name }}{% if kwarg.annotation %}{{ kwarg.annotation }}{% endif %}{{ kwarg.description|convert_markdown(heading_level, html_id) }}
diff --git a/src/mkdocstrings/templates/python/material/yield.html b/src/mkdocstrings/templates/python/material/yield.html new file mode 100644 index 00000000..d8a450ca --- /dev/null +++ b/src/mkdocstrings/templates/python/material/yield.html @@ -0,0 +1,16 @@ +{{ log.debug() }} +

Yields:

+ + + + + + + + + + + + + +
TypeDescription
{% if yield.annotation %}{{ yield.annotation }}{% endif %}{{ yield.description|convert_markdown(heading_level, html_id) }}
diff --git a/src/mkdocstrings/templates/python/mkdocs/keyword_args.html b/src/mkdocstrings/templates/python/mkdocs/keyword_args.html new file mode 100644 index 00000000..16af0ea0 --- /dev/null +++ b/src/mkdocstrings/templates/python/mkdocs/keyword_args.html @@ -0,0 +1,7 @@ +{{ log.debug() }} +
+
Keyword arguments:
+ {% for kwarg in kwargs %} +
{{ ("**" + kwarg.name + ":** " + ("`" + kwarg.annotation + "` – " if kwarg.annotation else "") + kwarg.description)|convert_markdown(heading_level, html_id) }}
+ {% endfor %} +
diff --git a/src/mkdocstrings/templates/python/mkdocs/yield.html b/src/mkdocstrings/templates/python/mkdocs/yield.html new file mode 100644 index 00000000..dad0f0e9 --- /dev/null +++ b/src/mkdocstrings/templates/python/mkdocs/yield.html @@ -0,0 +1,5 @@ +{{ log.debug() }} +
+
Yields:
+
{{ (("`" + yield.annotation + "` – " if yield.annotation else "") + yield.description)|convert_markdown(heading_level, html_id) }}
+
diff --git a/src/mkdocstrings/templates/python/readthedocs/keyword_args.html b/src/mkdocstrings/templates/python/readthedocs/keyword_args.html new file mode 100644 index 00000000..3c15308e --- /dev/null +++ b/src/mkdocstrings/templates/python/readthedocs/keyword_args.html @@ -0,0 +1,19 @@ +{{ log.debug() }} + + + + + + + + + + + +
Keyword arguments: +
    + {% for kwarg in kwargs %} +
  • {{ ("**" + kwarg.name + "**" + (" (`" + kwarg.annotation + "`)" if kwarg.annotation else "") + " – " + kwarg.description)|convert_markdown(heading_level, html_id) }}
  • + {% endfor %} +
+
diff --git a/src/mkdocstrings/templates/python/readthedocs/yield.html b/src/mkdocstrings/templates/python/readthedocs/yield.html new file mode 100644 index 00000000..7591f62c --- /dev/null +++ b/src/mkdocstrings/templates/python/readthedocs/yield.html @@ -0,0 +1,17 @@ +{{ log.debug() }} + + + + + + + + + + + +
Yields: +
    +
  • {{ ((("`" + yield.annotation + "` – ") if yield.annotation else "") + yield.description)|convert_markdown(heading_level, html_id) }}
  • +
+
From 75a608634a11835407cc7021fe9176e54a003ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Thu, 16 Dec 2021 21:20:08 +0100 Subject: [PATCH 07/12] chore: Template upgrade --- .copier-answers.yml | 2 +- .github/workflows/ci.yml | 25 ++++++---- .gitpod.dockerfile | 7 +++ .gitpod.yml | 13 +++++ Makefile | 16 ++++-- README.md | 1 + config/flake8.ini | 4 ++ config/mypy.ini | 14 +----- duties.py | 101 ++++++++++++++++++++++++++++++-------- pyproject.toml | 103 +++++++++++++++++++++++---------------- scripts/multirun.sh | 6 +-- scripts/setup.sh | 8 +-- 12 files changed, 204 insertions(+), 96 deletions(-) create mode 100644 .gitpod.dockerfile create mode 100644 .gitpod.yml diff --git a/.copier-answers.yml b/.copier-answers.yml index f844b711..7ad1c140 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 0.4.3 +_commit: 0.7.1 _src_path: gh:pawamoy/copier-pdm.git author_email: pawamoy@pm.me author_fullname: "Timoth\xE9e Mazzucotelli" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5750cd7..019502b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,9 @@ jobs: uses: actions/checkout@v2 - name: Set up PDM - uses: pdm-project/setup-pdm@v2 + uses: pdm-project/setup-pdm@v2.5 with: - python-version: 3.8 + python-version: "3.8" - name: Set cache variables id: set_variables @@ -49,15 +49,13 @@ jobs: run: pdm lock - name: Install dependencies - run: | - pdm install -G duty -G docs -G quality -G typing - pip install safety + run: pdm install -G duty -G docs -G quality -G typing -G security - name: Check if the documentation builds correctly run: pdm run duty check-docs - name: Check the code quality - run: pdm run duty check-code-quality + run: pdm run duty check-quality - name: Check if the code is correctly typed run: pdm run duty check-types @@ -69,8 +67,17 @@ jobs: strategy: matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - python-version: [3.6, 3.7, 3.8, 3.9] + os: + - ubuntu-latest + - macos-latest + - windows-latest + python-version: + - "3.6" + - "3.7" + - "3.8" + - "3.9" + - "3.10" + - "3.11-dev" runs-on: ${{ matrix.os }} @@ -79,7 +86,7 @@ jobs: uses: actions/checkout@v2 - name: Set up PDM - uses: pdm-project/setup-pdm@v2 + uses: pdm-project/setup-pdm@v2.5 with: python-version: ${{ matrix.python-version }} diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile new file mode 100644 index 00000000..33f285c2 --- /dev/null +++ b/.gitpod.dockerfile @@ -0,0 +1,7 @@ +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/.gitpod.yml b/.gitpod.yml new file mode 100644 index 00000000..23a3c2b7 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,13 @@ +vscode: + extensions: + - ms-python.python + +image: + file: .gitpod.dockerfile + +ports: +- port: 8000 + onOpen: notify + +tasks: +- init: make setup diff --git a/Makefile b/Makefile index 97aa6931..58291575 100644 --- a/Makefile +++ b/Makefile @@ -4,13 +4,14 @@ SHELL := bash DUTY = $(shell [ -n "${VIRTUAL_ENV}" ] || echo pdm run) duty args = $(foreach a,$($(subst -,_,$1)_args),$(if $(value $a),$a="$($a)")) -check_code_quality_args = files +check_quality_args = files docs_serve_args = host port release_args = version test_args = match BASIC_DUTIES = \ changelog \ + check-dependencies \ clean \ coverage \ docs \ @@ -21,9 +22,7 @@ BASIC_DUTIES = \ release QUALITY_DUTIES = \ - check \ - check-code-quality \ - check-dependencies \ + check-quality \ check-docs \ check-types \ test @@ -32,10 +31,19 @@ QUALITY_DUTIES = \ help: @$(DUTY) --list +.PHONY: lock +lock: + @pdm lock + .PHONY: setup setup: @bash scripts/setup.sh +.PHONY: check +check: + @bash scripts/multirun.sh duty check-quality check-types check-docs + @$(DUTY) check-dependencies + .PHONY: $(BASIC_DUTIES) $(BASIC_DUTIES): @$(DUTY) $@ $(call args,$@) diff --git a/README.md b/README.md index c489bb62..d914dc4f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![documentation](https://img.shields.io/badge/docs-mkdocs%20material-blue.svg?style=flat)](https://mkdocstrings.github.io/) [![pypi version](https://img.shields.io/pypi/v/mkdocstrings.svg)](https://pypi.org/project/mkdocstrings/) [![conda version](https://img.shields.io/conda/vn/conda-forge/mkdocstrings)](https://anaconda.org/conda-forge/mkdocstrings) +[![gitpod](https://img.shields.io/badge/gitpod-workspace-blue.svg?style=flat)](https://gitpod.io/#https://github.com/mkdocstrings/mkdocstrings) [![gitter](https://badges.gitter.im/join%20chat.svg)](https://gitter.im/mkdocstrings/community) Automatic documentation from sources, for [MkDocs](https://mkdocs.org/). diff --git a/config/flake8.ini b/config/flake8.ini index 2b50d854..e0a4cfbd 100644 --- a/config/flake8.ini +++ b/config/flake8.ini @@ -9,6 +9,10 @@ ignore = A001 # missing docstring in magic method D105 + # multi-line docstring summary should start at the first line + D212 + # does not support Parameters sections + D417 # whitespace before ':' (incompatible with Black) E203 # redundant with E0602 (undefined variable) diff --git a/config/mypy.ini b/config/mypy.ini index e88e9042..814e2ac8 100644 --- a/config/mypy.ini +++ b/config/mypy.ini @@ -1,15 +1,5 @@ [mypy] ignore_missing_imports = true exclude = tests/fixtures/ - -[mypy-docutils.*] -ignore_missing_imports = true - -[mypy-markdown.*] -ignore_missing_imports = true - -[mypy-toml.*] -ignore_missing_imports = true - -[mypy-yaml.*] -ignore_missing_imports = true +warn_unused_ignores = true +show_error_codes = true diff --git a/duties.py b/duties.py index 2dcc706c..3fdb1342 100644 --- a/duties.py +++ b/duties.py @@ -1,11 +1,14 @@ """Development tasks.""" +import importlib import os import re import sys +import tempfile +from contextlib import suppress from functools import wraps +from io import StringIO from pathlib import Path -from shutil import which from typing import List, Optional, Pattern from urllib.request import urlopen @@ -103,7 +106,7 @@ def changelog(ctx): ) -@duty(pre=["check_code_quality", "check_types", "check_docs", "check_dependencies"]) +@duty(pre=["check_quality", "check_types", "check_docs", "check_dependencies"]) def check(ctx): """Check it all! @@ -113,7 +116,7 @@ def check(ctx): @duty -def check_code_quality(ctx, files=PY_SRC): +def check_quality(ctx, files=PY_SRC): """Check the code quality. Arguments: @@ -131,22 +134,36 @@ def check_dependencies(ctx): Arguments: ctx: The context instance (passed automatically). """ - nofail = False - safety = which("safety") - if not safety: - pipx = which("pipx") - if pipx: - safety = f"{pipx} run safety" - else: - safety = "safety" - nofail = True - ctx.run( - f"pdm export -f requirements --without-hashes | {safety} check --stdin --full-report", - title="Checking dependencies", - pty=PTY, - nofail=nofail, + # undo possible patching + # see https://github.com/pyupio/safety/issues/348 + for module in sys.modules: # noqa: WPS528 + if module.startswith("safety.") or module == "safety": + del sys.modules[module] # noqa: WPS420 + + importlib.invalidate_caches() + + # reload original, unpatched safety + from safety.formatter import report + from safety.safety import check as safety_check + from safety.util import read_requirements + + # retrieve the list of dependencies + requirements = ctx.run( + ["pdm", "export", "-f", "requirements", "--without-hashes"], + title="Exporting dependencies as requirements", + allow_overrides=False, ) + # check using safety as a library + def safety(): # noqa: WPS430 + packages = list(read_requirements(StringIO(requirements))) + vulns = safety_check(packages=packages, ignore_ids="", key="", db_mirror="", cached=False, proxy={}) + output_report = report(vulns=vulns, full=True, checked_packages=len(packages)) + if vulns: + print(output_report) + + ctx.run(safety, title="Checking dependencies") + def no_docs_py36(nofail=True): """Decorate a duty that builds docs to warn that it's not possible on Python 3.6. @@ -184,14 +201,56 @@ def check_docs(ctx): ctx.run("mkdocs build -s", title="Building documentation", pty=PTY) -@duty -def check_types(ctx): +@duty # noqa: WPS231 +def check_types(ctx): # noqa: WPS231 """Check that the code is correctly typed. Arguments: ctx: The context instance (passed automatically). """ - ctx.run(f"mypy --config-file config/mypy.ini {PY_SRC}", title="Type-checking", pty=PTY, progress=True) + # NOTE: the following code works around this issue: + # https://github.com/python/mypy/issues/10633 + + # compute packages directory path + py = f"{sys.version_info.major}.{sys.version_info.minor}" + pkgs_dir = Path("__pypackages__", py, "lib").resolve() + + # build the list of available packages + packages = {} + for package in pkgs_dir.glob("*"): + if package.suffix not in {".dist-info", ".pth"} and package.name != "__pycache__": + packages[package.name] = package + + # handle .pth files + for pth in pkgs_dir.glob("*.pth"): + with suppress(OSError): + for package in Path(pth.read_text().splitlines()[0]).glob("*"): # noqa: WPS440 + if package.suffix != ".dist-info": + packages[package.name] = package + + # create a temporary directory to assign to MYPYPATH + with tempfile.TemporaryDirectory() as tmpdir: + + # symlink the stubs + ignore = set() + for stubs in (path for name, path in packages.items() if name.endswith("-stubs")): # noqa: WPS335 + Path(tmpdir, stubs.name).symlink_to(stubs, target_is_directory=True) + # try to symlink the corresponding package + # see https://www.python.org/dev/peps/pep-0561/#stub-only-packages + pkg_name = stubs.name.replace("-stubs", "") + if pkg_name in packages: + ignore.add(pkg_name) + Path(tmpdir, pkg_name).symlink_to(packages[pkg_name], target_is_directory=True) + + # create temporary mypy config to ignore stubbed packages + newconfig = Path("config", "mypy.ini").read_text() + newconfig += "\n" + "\n\n".join(f"[mypy-{pkg}.*]\nignore_errors=true" for pkg in ignore) + tmpconfig = Path(tmpdir, "mypy.ini") + tmpconfig.write_text(newconfig) + + # set MYPYPATH and run mypy + os.environ["MYPYPATH"] = tmpdir + ctx.run(f"mypy --config-file {tmpconfig} {PY_SRC}", title="Type-checking", pty=PTY) @duty(silent=True) @@ -282,7 +341,7 @@ def release(ctx, version): ctx.run("git push --tags", title="Pushing tags", pty=False) ctx.run("pdm build", title="Building dist/wheel", pty=PTY) ctx.run("twine upload --skip-existing dist/*", title="Publishing version", pty=PTY) - docs_deploy.run() # type: ignore + docs_deploy.run() @duty(silent=True) diff --git a/pyproject.toml b/pyproject.toml index df75e5ac..99348f53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,22 +8,36 @@ description = "Automatic documentation from sources, for MkDocs." authors = [{name = "Timothée Mazzucotelli", email = "pawamoy@pm.me"}] license = {file = "LICENSE"} readme = "README.md" -requires-python = ">=3.6.1" +requires-python = ">=3.6.2" keywords = ["mkdocs", "mkdocs-plugin", "docstrings", "autodoc", "documentation"] dynamic = ["version"] classifiers = [ "Development Status :: 4 - Beta", + "Intended Audience :: Developers", "License :: OSI Approved :: ISC License (ISCL)", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Topic :: Documentation", + "Topic :: Software Development", + "Topic :: Software Development :: Documentation", + "Topic :: Utilities", "Typing :: Typed", ] dependencies = [ - "Jinja2>=2.11.1,<4.0", - "Markdown~=3.3", - "MarkupSafe>=1.1,<3.0", - "mkdocs~=1.2", - "mkdocs-autorefs>=0.1,<0.4", - "pymdown-extensions>=6.3,<10.0", - "pytkdocs~=0.14.0", + "Jinja2>=2.11.1", + "Markdown>=3.3", + "MarkupSafe>=1.1", + "mkdocs>=1.2", + "mkdocs-autorefs>=0.1", + "pymdown-extensions>=6.3", + "pytkdocs>=0.14.0", ] [project.urls] @@ -39,57 +53,62 @@ Funding = "https://github.com/sponsors/mkdocstrings" [project.entry-points."mkdocs.plugins"] mkdocstrings = "mkdocstrings.plugin:MkdocstringsPlugin" - -[project.optional-dependencies] [tool.pdm] package-dir = "src" includes = ["src/mkdocstrings"] version = {use_scm = true} [tool.pdm.dev-dependencies] -duty = ["duty~=0.6"] +duty = ["duty>=0.7"] docs = [ - "mkdocs-coverage~=0.2; python_version >= '3.7'", - "mkdocs-gen-files~=0.3; python_version >= '3.7'", - "mkdocs-literate-nav~=0.4; python_version >= '3.7'", - "mkdocs-material~=7.1; python_version >= '3.7'", - "mkdocs-section-index~=0.3; python_version >= '3.7'", - "toml~=0.10; python_version >= '3.7'", + "mkdocs-coverage>=0.2; python_version >= '3.7'", + "mkdocs-gen-files>=0.3; python_version >= '3.7'", + "mkdocs-literate-nav>=0.4; python_version >= '3.7'", + "mkdocs-material>=7.3; python_version >= '3.7'", + "mkdocs-section-index>=0.3; python_version >= '3.7'", + "toml>=0.10; python_version >= '3.7'", ] format = [ - "autoflake~=1.4", - "black~=20.8b1", - "isort~=5.8", + "autoflake>=1.4", + "black>=21.10b0", + "isort>=5.10", ] maintain = [ # TODO: remove this section when git-changelog is more powerful - "git-changelog~=0.4", + "git-changelog>=0.4", ] quality = [ - "darglint~=1.7", - "flake8-bandit~=2.1", - "flake8-black~=0.2", - "flake8-bugbear~=21.3", - "flake8-builtins~=1.5", - "flake8-comprehensions~=3.4", - "flake8-docstrings~=1.6", - "flake8-pytest-style~=1.4", - "flake8-string-format~=0.3", - "flake8-tidy-imports~=4.2", - "flake8-variables-names~=0.0", - "pep8-naming~=0.11", - "wps-light~=0.15", - "curlylint~=0.13", + "darglint>=1.8", + "flake8-bandit>=2.1", + "flake8-black>=0.2", + "flake8-bugbear>=21.9", + "flake8-builtins>=1.5", + "flake8-comprehensions>=3.7", + "flake8-docstrings>=1.6", + "flake8-pytest-style>=1.5", + "flake8-string-format>=0.3", + "flake8-tidy-imports>=4.5", + "flake8-variables-names>=0.0", + "pep8-naming>=0.12", + "wps-light>=0.15", + "curlylint>=0.13", ] tests = [ - "pygments~=2.10", # python 3.6 - "pytest~=6.2", - "pytest-cov~=2.11", - "pytest-randomly~=3.6", - "pytest-sugar~=0.9", - "pytest-xdist~=2.2", + "pygments>=2.10", # python 3.6 + "pytest>=6.2", + "pytest-cov>=3.0", + "pytest-randomly>=3.10", + "pytest-sugar>=0.9", + "pytest-xdist>=2.4", +] +typing = [ + "mypy>=0.910", + "types-docutils", + "types-markdown>=3.3", + "types-pyyaml", + "types-toml>=0.10", ] -typing = ["mypy~=0.812"] +security = ["safety>=1.10"] [tool.black] line-length = 120 diff --git a/scripts/multirun.sh b/scripts/multirun.sh index 4ca6e2ce..7b5d9cf2 100755 --- a/scripts/multirun.sh +++ b/scripts/multirun.sh @@ -1,15 +1,15 @@ #!/usr/bin/env bash set -e -PYTHON_VERSIONS="${PYTHON_VERSIONS-3.6 3.7 3.8 3.9}" +PYTHON_VERSIONS="${PYTHON_VERSIONS-3.6 3.7 3.8 3.9 3.10 3.11}" if [ -n "${PYTHON_VERSIONS}" ]; then for python_version in ${PYTHON_VERSIONS}; do - if pdm use -f "${python_version}" &>/dev/null; then + if pdm use -f "python${python_version}" &>/dev/null; then echo "> pdm run $@ (Python ${python_version})" pdm run "$@" else - echo "> pdm use -f ${python_version}: Python version not available?" >&2 + echo "> pdm use -f python${python_version}: Python interpreter not available?" >&2 fi done else diff --git a/scripts/setup.sh b/scripts/setup.sh index cfddbac7..c5df7b4c 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -PYTHON_VERSIONS="${PYTHON_VERSIONS-3.6 3.7 3.8 3.9}" +PYTHON_VERSIONS="${PYTHON_VERSIONS-3.6 3.7 3.8 3.9 3.10 3.11}" install_with_pipx() { if ! command -v "$1" &>/dev/null; then @@ -16,11 +16,11 @@ install_with_pipx pdm if [ -n "${PYTHON_VERSIONS}" ]; then for python_version in ${PYTHON_VERSIONS}; do - if pdm use -f "${python_version}" &>/dev/null; then - echo "> Using Python ${python_version} environment" + if pdm use -f "python${python_version}" &>/dev/null; then + echo "> Using Python ${python_version} interpreter" pdm install else - echo "> pdm use -f ${python_version}: Python version not available?" >&2 + echo "> pdm use -f python${python_version}: Python interpreter not available?" >&2 fi done else From 46cea793471d49b984ea6d7d251e67910afdf413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Thu, 16 Dec 2021 21:38:44 +0100 Subject: [PATCH 08/12] tests: Depend on Sphinx and Docutils for tests --- duties.py | 10 ---------- pyproject.toml | 2 ++ 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/duties.py b/duties.py index 3fdb1342..879445e2 100644 --- a/duties.py +++ b/duties.py @@ -364,16 +364,6 @@ def test(ctx, match: str = ""): ctx: The context instance (passed automatically). match: A pytest expression to filter selected tests. """ - try: # noqa: WPS229 - import sphinx # isort:skip # noqa: F401 - import docutils # isort:skip # noqa: F401 - except ImportError: - py = f"{sys.version_info.major}.{sys.version_info.minor}" - ctx.run( - f"pip install sphinx docutils --no-deps -t __pypackages__/{py}/lib", - title="Installing additional test dependencies", - ) - py_version = f"{sys.version_info.major}{sys.version_info.minor}" os.environ["COVERAGE_FILE"] = f".coverage.{py_version}" ctx.run( diff --git a/pyproject.toml b/pyproject.toml index 99348f53..ac0bd9de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -94,12 +94,14 @@ quality = [ "curlylint>=0.13", ] tests = [ + "docutils", "pygments>=2.10", # python 3.6 "pytest>=6.2", "pytest-cov>=3.0", "pytest-randomly>=3.10", "pytest-sugar>=0.9", "pytest-xdist>=2.4", + "sphinx", ] typing = [ "mypy>=0.910", From b19fee3defd74db3dc09581bad67735d04767213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Thu, 16 Dec 2021 21:39:02 +0100 Subject: [PATCH 09/12] ci: Remove unused type ignore comments --- src/mkdocstrings/extension.py | 4 ++-- src/mkdocstrings/handlers/base.py | 6 +++--- src/mkdocstrings/handlers/rendering.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mkdocstrings/extension.py b/src/mkdocstrings/extension.py index 7f40a193..ab550268 100644 --- a/src/mkdocstrings/extension.py +++ b/src/mkdocstrings/extension.py @@ -79,7 +79,7 @@ def __init__( self._autorefs = autorefs self._updated_env = False - def test(self, parent: Element, block: str) -> bool: # type: ignore + def test(self, parent: Element, block: str) -> bool: """Match our autodoc instructions. Arguments: @@ -108,7 +108,7 @@ def run(self, parent: Element, blocks: MutableSequence[str]) -> None: if match.start() > 0: self.parser.parseBlocks(parent, [block[: match.start()]]) # removes the first line - block = block[match.end() :] # type: ignore + block = block[match.end() :] block, the_rest = self.detab(block) diff --git a/src/mkdocstrings/handlers/base.py b/src/mkdocstrings/handlers/base.py index 1a3a5781..c5c49c20 100644 --- a/src/mkdocstrings/handlers/base.py +++ b/src/mkdocstrings/handlers/base.py @@ -104,9 +104,9 @@ def __init__(self, directory: str, theme: str, custom_templates: Optional[str] = self.env = Environment( autoescape=True, - loader=FileSystemLoader(paths), # type: ignore + loader=FileSystemLoader(paths), auto_reload=False, # Editing a template in the middle of a build is not useful. - ) # type: ignore + ) self.env.filters["any"] = do_any self.env.globals["log"] = get_template_logger() @@ -402,7 +402,7 @@ def get_handler(self, name: str, handler_config: Optional[dict] = None) -> BaseH self._config["theme_name"], self._config["mkdocstrings"]["custom_templates"], **handler_config, - ) # type: ignore + ) return self._handlers[name] @property diff --git a/src/mkdocstrings/handlers/rendering.py b/src/mkdocstrings/handlers/rendering.py index e7ff9802..c28beb00 100644 --- a/src/mkdocstrings/handlers/rendering.py +++ b/src/mkdocstrings/handlers/rendering.py @@ -63,7 +63,7 @@ def __init__(self, md: Markdown): md: The Markdown instance to read configs from. """ config: Dict[str, Any] = {} - for ext in md.registeredExtensions: # type: ignore + for ext in md.registeredExtensions: if isinstance(ext, HighlightExtension) and (ext.enabled or not config): config = ext.getConfigs() break # This one takes priority, no need to continue looking From 024ee826bb6f0aa297ba857bc18075d6f4162cad Mon Sep 17 00:00:00 2001 From: Will Da Silva Date: Sun, 19 Dec 2021 09:21:06 -0500 Subject: [PATCH 10/12] feat: Add `show_signature` rendering option Issue #341: https://github.com/mkdocstrings/mkdocstrings/issues/341 PR #342: https://github.com/mkdocstrings/mkdocstrings/pull/342 --- src/mkdocstrings/handlers/python.py | 4 +++- src/mkdocstrings/templates/python/material/signature.html | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mkdocstrings/handlers/python.py b/src/mkdocstrings/handlers/python.py index efab7d34..0f85a6de 100644 --- a/src/mkdocstrings/handlers/python.py +++ b/src/mkdocstrings/handlers/python.py @@ -45,6 +45,7 @@ class PythonRenderer(BaseRenderer): "show_object_full_path": False, "show_category_heading": False, "show_if_no_docstring": False, + "show_signature": True, "show_signature_annotations": False, "show_source": True, "show_bases": True, @@ -63,7 +64,8 @@ class PythonRenderer(BaseRenderer): **`show_root_members_full_path`** | `bool` | Show the full Python path of objects that are children of the root object (for example, classes in a module). When False, `show_object_full_path` overrides. | `False` **`show_category_heading`** | `bool` | When grouped by categories, show a heading for each category. | `False` **`show_if_no_docstring`** | `bool` | Show the object heading even if it has no docstring or children with docstrings. | `False` - **`show_signature_annotations`** | `bool` | Show the type annotations in methods and functions signatures. | `False` + **`show_signature`** | `bool` | Show method and function signatures. | `True` + **`show_signature_annotations`** | `bool` | Show the type annotations in method and function signatures. | `False` **`show_source`** | `bool` | Show the source code of this object. | `True` **`show_bases`** | `bool` | Show the base classes of a class. | `True` **`group_by_category`** | `bool` | Group the object's children by categories: attributes, classes, functions, methods, and modules. | `True` diff --git a/src/mkdocstrings/templates/python/material/signature.html b/src/mkdocstrings/templates/python/material/signature.html index e1f815da..90cc4180 100644 --- a/src/mkdocstrings/templates/python/material/signature.html +++ b/src/mkdocstrings/templates/python/material/signature.html @@ -1,5 +1,5 @@ {{ log.debug() }} -{%- if signature -%} +{%- if signature and config.show_signature -%} {%- with -%} {%- set ns = namespace(render_pos_only_separator=True, render_kw_only_separator=True, equal="=") -%} From 57ed0c6ee27879594dca921e8a399a67ad4b0930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 27 Dec 2021 18:54:03 +0100 Subject: [PATCH 11/12] ci: Fix mypy warnings --- src/mkdocstrings/extension.py | 4 ++-- src/mkdocstrings/handlers/base.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mkdocstrings/extension.py b/src/mkdocstrings/extension.py index ab550268..d8aae2e5 100644 --- a/src/mkdocstrings/extension.py +++ b/src/mkdocstrings/extension.py @@ -23,7 +23,7 @@ """ import re from collections import ChainMap -from typing import Mapping, MutableSequence, Tuple +from typing import Mapping, MutableMapping, MutableSequence, Tuple from xml.etree.ElementTree import Element import yaml @@ -207,7 +207,7 @@ def _process_block( return rendered, handler, data -def get_item_configs(handler_config: dict, config: dict) -> Tuple[Mapping, Mapping]: +def get_item_configs(handler_config: dict, config: dict) -> Tuple[Mapping, MutableMapping]: """Get the selection and rendering configuration merged into the global configuration of the given handler. Arguments: diff --git a/src/mkdocstrings/handlers/base.py b/src/mkdocstrings/handlers/base.py index c5c49c20..32da5a20 100644 --- a/src/mkdocstrings/handlers/base.py +++ b/src/mkdocstrings/handlers/base.py @@ -398,7 +398,7 @@ def get_handler(self, name: str, handler_config: Optional[dict] = None) -> BaseH if handler_config is None: handler_config = self.get_handler_config(name) module = importlib.import_module(f"mkdocstrings.handlers.{name}") - self._handlers[name] = module.get_handler( # type: ignore + self._handlers[name] = module.get_handler( self._config["theme_name"], self._config["mkdocstrings"]["custom_templates"], **handler_config, From 8ea5f768713627b1e7e9e8f61a2d9bd32edd6353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 27 Dec 2021 18:59:33 +0100 Subject: [PATCH 12/12] chore: Prepare release 0.17.0 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f1c2b98..c5593cd0 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). +## [0.17.0](https://github.com/mkdocstrings/mkdocstrings/releases/tag/0.17.0) - 2021-12-27 + +[Compare with 0.16.2](https://github.com/mkdocstrings/mkdocstrings/compare/0.16.2...0.17.0) + +### Features +- Add `show_signature` rendering option ([024ee82](https://github.com/mkdocstrings/mkdocstrings/commit/024ee826bb6f0aa297ba857bc18075d6f4162cad) by Will Da Silva). [Issue #341](https://github.com/mkdocstrings/mkdocstrings/issues/341), [PR #342](https://github.com/mkdocstrings/mkdocstrings/pull/342) +- Support Keyword Args and Yields sections ([1286427](https://github.com/mkdocstrings/mkdocstrings/commit/12864271b7f997af7b421a834919b1e686793905) by Timothée Mazzucotelli). [Issue #205](https://github.com/mkdocstrings/mkdocstrings/issues/205) and [#324](https://github.com/mkdocstrings/mkdocstrings/issues/324), [PR #331](https://github.com/mkdocstrings/mkdocstrings/pull/331) + +### Bug Fixes +- Do minimum work when falling back to re-collecting an object to get its anchor ([f6cf570](https://github.com/mkdocstrings/mkdocstrings/commit/f6cf570255df17db1088b6e6cd94bcc823b3b17f) by Timothée Mazzucotelli). [Issue #329](https://github.com/mkdocstrings/mkdocstrings/issues/329), [PR #330](https://github.com/mkdocstrings/mkdocstrings/pull/330) + +### Code Refactoring +- Return multiple identifiers from fallback method ([78c498c](https://github.com/mkdocstrings/mkdocstrings/commit/78c498c4a6cfc33cc6ceab9829426bd64e518d44) by Timothée Mazzucotelli). [Issue mkdocstrings/autorefs#11](https://github.com/mkdocstrings/autorefs/issues/11), [PR #350](https://github.com/mkdocstrings/mkdocstrings/pull/350) + + ## [0.16.2](https://github.com/mkdocstrings/mkdocstrings/releases/tag/0.16.2) - 2021-10-04 [Compare with 0.16.1](https://github.com/mkdocstrings/mkdocstrings/compare/0.16.1...0.16.2)