element into the root element and inherit its tag name (it's significant!) root[0].tag = root.tag return root[0] + return None class MkdocstringsInnerExtension(Extension): """Extension that should always be added to Markdown sub-documents that handlers request (and *only* them).""" - def __init__(self, headings: List[Element]): + def __init__(self, headings: list[Element]): """Initialize the object. Arguments: diff --git a/src/mkdocstrings/inventory.py b/src/mkdocstrings/inventory.py index 9108d91d..42e9b3db 100644 --- a/src/mkdocstrings/inventory.py +++ b/src/mkdocstrings/inventory.py @@ -3,17 +3,25 @@ # Credits to Brian Skinn and the sphobjinv project: # https://github.com/bskinn/sphobjinv +from __future__ import annotations + import re import zlib from textwrap import dedent -from typing import BinaryIO, Collection, List, Optional +from typing import BinaryIO, Collection class InventoryItem: """Inventory item.""" def __init__( - self, name: str, domain: str, role: str, uri: str, priority: str = "1", dispname: Optional[str] = None + self, + name: str, + domain: str, + role: str, + uri: str, + priority: str = "1", + dispname: str | None = None, ): """Initialize the object. @@ -49,7 +57,7 @@ def format_sphinx(self) -> str: sphinx_item_regex = re.compile(r"^(.+?)\s+(\S+):(\S+)\s+(-?\d+)\s+(\S+)\s*(.*)$") @classmethod - def parse_sphinx(cls, line: str) -> "InventoryItem": + def parse_sphinx(cls, line: str) -> InventoryItem: """Parse a line from a Sphinx v2 inventory file and return an `InventoryItem` from it.""" match = cls.sphinx_item_regex.search(line) if not match: @@ -65,7 +73,7 @@ def parse_sphinx(cls, line: str) -> "InventoryItem": class Inventory(dict): """Inventory of collected and rendered objects.""" - def __init__(self, items: Optional[List[InventoryItem]] = None, project: str = "project", version: str = "0.0.0"): + def __init__(self, items: list[InventoryItem] | None = None, project: str = "project", version: str = "0.0.0"): """Initialize the object. Arguments: @@ -80,7 +88,7 @@ def __init__(self, items: Optional[List[InventoryItem]] = None, project: str = " self.project = project self.version = version - def register(self, *args: str, **kwargs: str): + def register(self, *args: str, **kwargs: str) -> None: """Create and register an item. Arguments: @@ -103,7 +111,7 @@ def format_sphinx(self) -> bytes: # Project: {self.project} # Version: {self.version} # The remainder of this file is compressed using zlib. - """ + """, ) .lstrip() .encode("utf8") @@ -113,7 +121,7 @@ def format_sphinx(self) -> bytes: return header + zlib.compress(b"\n".join(lines) + b"\n", 9) @classmethod - def parse_sphinx(cls, in_file: BinaryIO, *, domain_filter: Collection[str] = ()) -> "Inventory": + def parse_sphinx(cls, in_file: BinaryIO, *, domain_filter: Collection[str] = ()) -> Inventory: """Parse a Sphinx v2 inventory file and return an `Inventory` from it. Arguments: diff --git a/src/mkdocstrings/loggers.py b/src/mkdocstrings/loggers.py index 24004f8f..5e3f42bb 100644 --- a/src/mkdocstrings/loggers.py +++ b/src/mkdocstrings/loggers.py @@ -1,24 +1,29 @@ """Logging functions.""" +from __future__ import annotations + import logging from contextlib import suppress from pathlib import Path -from typing import Any, Callable, MutableMapping, Optional, Sequence, Tuple +from typing import TYPE_CHECKING, Any, Callable, MutableMapping, Sequence -from jinja2.runtime import Context from mkdocs.utils import warning_filter try: from jinja2 import pass_context except ImportError: # TODO: remove once Jinja2 < 3.1 is dropped - from jinja2 import contextfunction as pass_context # type: ignore # noqa: WPS440 + from jinja2 import contextfunction as pass_context # type: ignore[attr-defined,no-redef] try: import mkdocstrings_handlers except ImportError: TEMPLATES_DIRS: Sequence[Path] = () else: - TEMPLATES_DIRS = tuple(mkdocstrings_handlers.__path__) # type: ignore[arg-type] # noqa: WPS609 + TEMPLATES_DIRS = tuple(mkdocstrings_handlers.__path__) # type: ignore[arg-type] + + +if TYPE_CHECKING: + from jinja2.runtime import Context class LoggerAdapter(logging.LoggerAdapter): @@ -34,7 +39,7 @@ def __init__(self, prefix: str, logger: logging.Logger): super().__init__(logger, {}) self.prefix = prefix - def process(self, msg: str, kwargs: MutableMapping[str, Any]) -> Tuple[str, Any]: + def process(self, msg: str, kwargs: MutableMapping[str, Any]) -> tuple[str, Any]: """Process the message. Arguments: @@ -82,7 +87,7 @@ def get_template_logger_function(logger_func: Callable) -> Callable: """ @pass_context - def wrapper(context: Context, msg: Optional[str] = None) -> str: + def wrapper(context: Context, msg: str | None = None) -> str: """Log a message. Arguments: diff --git a/src/mkdocstrings/plugin.py b/src/mkdocstrings/plugin.py index bbb5ee8a..a35309c8 100644 --- a/src/mkdocstrings/plugin.py +++ b/src/mkdocstrings/plugin.py @@ -12,17 +12,18 @@ during the [`on_serve` event hook](https://www.mkdocs.org/user-guide/plugins/#on_serve). """ +from __future__ import annotations + import collections import functools import gzip import os +import sys from concurrent import futures -from typing import Any, BinaryIO, Callable, Iterable, List, Mapping, Optional, Tuple +from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Iterable, List, Mapping, Tuple, TypeVar from urllib import request -from mkdocs.config import Config from mkdocs.config.config_options import Type as MkType -from mkdocs.livereload import LiveReloadServer from mkdocs.plugins import BasePlugin from mkdocs.utils import write_file from mkdocs_autorefs.plugin import AutorefsPlugin @@ -31,25 +32,38 @@ from mkdocstrings.handlers.base import BaseHandler, Handlers from mkdocstrings.loggers import get_logger +if TYPE_CHECKING: + from jinja2.environment import Environment + from mkdocs.config import Config + from mkdocs.livereload import LiveReloadServer + +if sys.version_info < (3, 10): + from typing_extensions import ParamSpec +else: + from typing import ParamSpec + log = get_logger(__name__) SELECTION_OPTS_KEY: str = "selection" -"""The name of the selection parameter in YAML configuration blocks.""" +"""Deprecated. The name of the selection parameter in YAML configuration blocks.""" RENDERING_OPTS_KEY: str = "rendering" -"""The name of the rendering parameter in YAML configuration blocks.""" +"""Deprecated. The name of the rendering parameter in YAML configuration blocks.""" InventoryImportType = List[Tuple[str, Mapping[str, Any]]] InventoryLoaderType = Callable[..., Iterable[Tuple[str, str]]] +P = ParamSpec("P") +R = TypeVar("R") -def list_to_tuple(function: Callable[..., Any]) -> Callable[..., Any]: + +def list_to_tuple(function: Callable[P, R]) -> Callable[P, R]: """Decorater to convert lists to tuples in the arguments.""" - def wrapper(*args: Any, **kwargs: Any): + def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: safe_args = [tuple(item) if isinstance(item, list) else item for item in args] if kwargs: - kwargs = {key: tuple(value) if isinstance(value, list) else value for key, value in kwargs.items()} - return function(*safe_args, **kwargs) + kwargs = {key: tuple(value) if isinstance(value, list) else value for key, value in kwargs.items()} # type: ignore[assignment] + return function(*safe_args, **kwargs) # type: ignore[arg-type] return wrapper @@ -68,8 +82,8 @@ class MkdocstringsPlugin(BasePlugin): for more information about its plugin system. """ - config_scheme: Tuple[Tuple[str, MkType]] = ( - ("watch", MkType(list, default=[])), # type: ignore + config_scheme: tuple[tuple[str, MkType]] = ( + ("watch", MkType(list, default=[])), # type: ignore[assignment] ("handlers", MkType(dict, default={})), ("default_handler", MkType(str, default="python")), ("custom_templates", MkType(str, default=None)), @@ -108,7 +122,7 @@ class MkdocstringsPlugin(BasePlugin): def __init__(self) -> None: """Initialize the object.""" super().__init__() - self._handlers: Optional[Handlers] = None + self._handlers: Handlers | None = None @property def handlers(self) -> Handlers: @@ -126,8 +140,13 @@ def handlers(self) -> Handlers: # TODO: remove once watch feature is removed def on_serve( - self, server: LiveReloadServer, config: Config, builder: Callable, *args: Any, **kwargs: Any - ) -> None: # noqa: W0613 (unused arguments) + self, + server: LiveReloadServer, + config: Config, # noqa: ARG002 + builder: Callable, + *args: Any, # noqa: ARG002 + **kwargs: Any, # noqa: ARG002 + ) -> None: """Watch directories. Hook for the [`on_serve` event](https://www.mkdocs.org/user-guide/plugins/#on_serve). @@ -149,7 +168,7 @@ def on_serve( log.debug(f"Adding directory '{element}' to watcher") server.watch(element, builder) - def on_config(self, config: Config, **kwargs: Any) -> Config: # noqa: W0613 (unused arguments) + def on_config(self, config: Config, **kwargs: Any) -> Config: # noqa: ARG002 """Instantiate our Markdown extension. Hook for the [`on_config` event](https://www.mkdocs.org/user-guide/plugins/#on_config). @@ -171,30 +190,25 @@ def on_config(self, config: Config, **kwargs: Any) -> Config: # noqa: W0613 (un return config log.debug("Adding extension to the list") - theme_name = None - if config["theme"].name is None: - theme_name = os.path.dirname(config["theme"].dirs[0]) - else: - theme_name = config["theme"].name + theme_name = config["theme"].name or os.path.dirname(config["theme"].dirs[0]) to_import: InventoryImportType = [] for handler_name, conf in self.config["handlers"].items(): for import_item in conf.pop("import", ()): if isinstance(import_item, str): - import_item = {"url": import_item} + import_item = {"url": import_item} # noqa: PLW2901 to_import.append((handler_name, import_item)) extension_config = { - "site_name": config["site_name"], - "config_file_path": config["config_file_path"], "theme_name": theme_name, "mdx": config["markdown_extensions"], "mdx_configs": config["mdx_configs"], "mkdocstrings": self.config, + "mkdocs": config, } self._handlers = Handlers(extension_config) - try: # noqa: WPS229 + try: # If autorefs plugin is explicitly enabled, just use it. autorefs = config["plugins"]["autorefs"] log.debug(f"Picked up existing autorefs instance {autorefs!r}") @@ -215,9 +229,11 @@ def on_config(self, config: Config, **kwargs: Any) -> Config: # noqa: W0613 (un self._inv_futures = [] if to_import: inv_loader = futures.ThreadPoolExecutor(4) - for handler_name, import_item in to_import: # noqa: WPS440 + for handler_name, import_item in to_import: future = inv_loader.submit( - self._load_inventory, self.get_handler(handler_name).load_inventory, **import_item + self._load_inventory, + self.get_handler(handler_name).load_inventory, + **import_item, ) self._inv_futures.append(future) inv_loader.shutdown(wait=False) @@ -248,7 +264,7 @@ def plugin_enabled(self) -> bool: """ return self.config["enabled"] - def on_env(self, env, config: Config, *args, **kwargs) -> None: + def on_env(self, env: Environment, config: Config, *args: Any, **kwargs: Any) -> None: # noqa: ARG002 """Extra actions that need to happen after all Markdown rendering and before HTML rendering. Hook for the [`on_env` event](https://www.mkdocs.org/user-guide/plugins/#on_env). @@ -275,8 +291,10 @@ def on_env(self, env, config: Config, *args, **kwargs) -> None: self._inv_futures = [] def on_post_build( - self, config: Config, **kwargs: Any - ) -> None: # noqa: W0613,R0201 (unused arguments, cannot be static) + self, + config: Config, # noqa: ARG002 + **kwargs: Any, # noqa: ARG002 + ) -> None: """Teardown the handlers. Hook for the [`on_post_build` event](https://www.mkdocs.org/user-guide/plugins/#on_post_build). @@ -312,9 +330,9 @@ def get_handler(self, handler_name: str) -> BaseHandler: return self.handlers.get_handler(handler_name) @classmethod + @functools.lru_cache(maxsize=None) # lru_cache does not allow mutable arguments such lists, but that is what we load from YAML config. @list_to_tuple - @functools.lru_cache(maxsize=None) def _load_inventory(cls, loader: InventoryLoaderType, url: str, **kwargs: Any) -> Mapping[str, str]: """Download and process inventory files using a handler. @@ -338,7 +356,7 @@ def _load_inventory(cls, loader: InventoryLoaderType, url: str, **kwargs: Any) - @classmethod @functools.lru_cache(maxsize=None) # Warn only once - def _warn_about_watch_option(cls): + def _warn_about_watch_option(cls) -> None: log.info( "DEPRECATION: mkdocstrings' watch feature is deprecated in favor of MkDocs' watch feature, " "see https://www.mkdocs.org/user-guide/configuration/#watch", diff --git a/tests/conftest.py b/tests/conftest.py index c79b04d0..a2ea6b26 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,19 +1,27 @@ """Configuration for the pytest test suite.""" +from __future__ import annotations + from collections import ChainMap +from typing import TYPE_CHECKING, Any, Iterator import pytest from markdown.core import Markdown from mkdocs import config from mkdocs.config.defaults import get_schema +if TYPE_CHECKING: + from pathlib import Path + + from mkdocstrings.plugin import MkdocstringsPlugin + @pytest.fixture(name="mkdocs_conf") -def fixture_mkdocs_conf(request, tmp_path): +def fixture_mkdocs_conf(request: pytest.FixtureRequest, tmp_path: Path) -> Iterator[config.Config]: """Yield a MkDocs configuration object.""" - conf = config.Config(schema=get_schema()) - while hasattr(request, "_parent_request") and hasattr(request._parent_request, "_parent_request"): # noqa: WPS437 - request = request._parent_request # noqa: WPS437 + conf = config.Config(schema=get_schema()) # type: ignore[call-arg] + while hasattr(request, "_parent_request") and hasattr(request._parent_request, "_parent_request"): + request = request._parent_request conf_dict = { "site_name": "foo", @@ -23,7 +31,7 @@ def fixture_mkdocs_conf(request, tmp_path): **getattr(request, "param", {}), } # Re-create it manually as a workaround for https://github.com/mkdocs/mkdocs/issues/2289 - mdx_configs = dict(ChainMap(*conf_dict.get("markdown_extensions", []))) + mdx_configs: dict[str, Any] = dict(ChainMap(*conf_dict.get("markdown_extensions", []))) # type: ignore[arg-type] conf.load_dict(conf_dict) assert conf.validate() == ([], []) @@ -38,14 +46,12 @@ def fixture_mkdocs_conf(request, tmp_path): @pytest.fixture(name="plugin") -def fixture_plugin(mkdocs_conf): +def fixture_plugin(mkdocs_conf: config.Config) -> MkdocstringsPlugin: """Return a plugin instance.""" - plugin = mkdocs_conf["plugins"]["mkdocstrings"] - plugin.md = Markdown(extensions=mkdocs_conf["markdown_extensions"], extension_configs=mkdocs_conf["mdx_configs"]) - return plugin + return mkdocs_conf["plugins"]["mkdocstrings"] @pytest.fixture(name="ext_markdown") -def fixture_ext_markdown(plugin): +def fixture_ext_markdown(mkdocs_conf: config.Config) -> Markdown: """Return a Markdown instance with MkdocstringsExtension.""" - return plugin.md + return Markdown(extensions=mkdocs_conf["markdown_extensions"], extension_configs=mkdocs_conf["mdx_configs"]) diff --git a/tests/test_extension.py b/tests/test_extension.py index 3c41932c..f7c3cecc 100644 --- a/tests/test_extension.py +++ b/tests/test_extension.py @@ -1,14 +1,23 @@ """Tests for the extension module.""" + +from __future__ import annotations + import logging import re import sys from textwrap import dedent +from typing import TYPE_CHECKING import pytest +if TYPE_CHECKING: + from markdown import Markdown + + from mkdocstrings.plugin import MkdocstringsPlugin + @pytest.mark.parametrize("ext_markdown", [{"markdown_extensions": [{"footnotes": {}}]}], indirect=["ext_markdown"]) -def test_multiple_footnotes(ext_markdown): +def test_multiple_footnotes(ext_markdown: Markdown) -> None: """Assert footnotes don't get added to subsequent docstrings.""" output = ext_markdown.convert( dedent( @@ -30,7 +39,7 @@ def test_multiple_footnotes(ext_markdown): assert output.count("Top footnote") == 1 -def test_markdown_heading_level(ext_markdown): +def test_markdown_heading_level(ext_markdown: Markdown) -> None: """Assert that Markdown headings' level doesn't exceed heading_level.""" output = ext_markdown.convert("::: tests.fixtures.headings\n options:\n show_root_heading: true") assert ">Foo" in output @@ -38,7 +47,7 @@ def test_markdown_heading_level(ext_markdown): assert ">Baz" in output -def test_keeps_preceding_text(ext_markdown): +def test_keeps_preceding_text(ext_markdown: Markdown) -> None: """Assert that autodoc is recognized in the middle of a block and preceding text is kept.""" output = ext_markdown.convert("**preceding**\n::: tests.fixtures.headings") assert "preceding" in output @@ -46,21 +55,21 @@ def test_keeps_preceding_text(ext_markdown): assert ":::" not in output -def test_reference_inside_autodoc(ext_markdown): +def test_reference_inside_autodoc(ext_markdown: Markdown) -> None: """Assert cross-reference Markdown extension works correctly.""" output = ext_markdown.convert("::: tests.fixtures.cross_reference") assert re.search(r"Link to <.*something\.Else.*>something\.Else<.*>\.", output) @pytest.mark.skipif(sys.version_info < (3, 8), reason="typing.Literal requires Python 3.8") -def test_quote_inside_annotation(ext_markdown): +def test_quote_inside_annotation(ext_markdown: Markdown) -> None: """Assert that inline highlighting doesn't double-escape HTML.""" output = ext_markdown.convert("::: tests.fixtures.string_annotation.Foo") assert ";hi&" in output assert "&" not in output -def test_html_inside_heading(ext_markdown): +def test_html_inside_heading(ext_markdown: Markdown) -> None: """Assert that headings don't double-escape HTML.""" output = ext_markdown.convert("::: tests.fixtures.html_tokens") assert "'<" in output @@ -76,7 +85,7 @@ def test_html_inside_heading(ext_markdown): ], indirect=["ext_markdown"], ) -def test_no_double_toc(ext_markdown, expect_permalink): +def test_no_double_toc(ext_markdown: Markdown, expect_permalink: str) -> None: """Assert that the 'toc' extension doesn't apply its modification twice.""" output = ext_markdown.convert( dedent( @@ -88,12 +97,12 @@ def test_no_double_toc(ext_markdown, expect_permalink): show_root_toc_entry: false # bb - """ - ) + """, + ), ) assert output.count(expect_permalink) == 5 assert 'id="tests.fixtures.headings--foo"' in output - assert ext_markdown.toc_tokens == [ # noqa: E1101 (the member gets populated only with 'toc' extension) + assert ext_markdown.toc_tokens == [ # type: ignore[attr-defined] # the member gets populated only with 'toc' extension { "level": 1, "id": "aa", @@ -109,43 +118,43 @@ def test_no_double_toc(ext_markdown, expect_permalink): "id": "tests.fixtures.headings--bar", "name": "Bar", "children": [ - {"level": 6, "id": "tests.fixtures.headings--baz", "name": "Baz", "children": []} + {"level": 6, "id": "tests.fixtures.headings--baz", "name": "Baz", "children": []}, ], - } + }, ], - } + }, ], }, {"level": 1, "id": "bb", "name": "bb", "children": []}, ] -def test_use_custom_handler(ext_markdown): +def test_use_custom_handler(ext_markdown: Markdown) -> None: """Assert that we use the custom handler declared in an individual autodoc instruction.""" with pytest.raises(ModuleNotFoundError): ext_markdown.convert("::: tests.fixtures.headings\n handler: not_here") -def test_dont_register_every_identifier_as_anchor(plugin): +def test_dont_register_every_identifier_as_anchor(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> None: """Assert that we don't preemptively register all identifiers of a rendered object.""" - handler = plugin._handlers.get_handler("python") # noqa: WPS437 + handler = plugin._handlers.get_handler("python") # type: ignore[union-attr] ids = {"id1", "id2", "id3"} - handler.get_anchors = lambda _: ids - plugin.md.convert("::: tests.fixtures.headings") - autorefs = plugin.md.parser.blockprocessors["mkdocstrings"]._autorefs # noqa: WPS219,WPS437 + handler.get_anchors = lambda _: ids # type: ignore[method-assign] + ext_markdown.convert("::: tests.fixtures.headings") + autorefs = ext_markdown.parser.blockprocessors["mkdocstrings"]._autorefs for identifier in ids: - assert identifier not in autorefs._url_map # noqa: WPS437 - assert identifier not in autorefs._abs_url_map # noqa: WPS437 + assert identifier not in autorefs._url_map + assert identifier not in autorefs._abs_url_map -def test_use_deprecated_yaml_keys(ext_markdown, caplog): +def test_use_deprecated_yaml_keys(ext_markdown: Markdown, caplog: pytest.LogCaptureFixture) -> None: """Check that using the deprecated 'selection' and 'rendering' YAML keys emits a deprecation warning.""" caplog.set_level(logging.INFO) assert "h1" not in ext_markdown.convert("::: tests.fixtures.headings\n rendering:\n heading_level: 2") assert "single 'options' YAML key" in caplog.text -def test_use_new_options_yaml_key(ext_markdown): +def test_use_new_options_yaml_key(ext_markdown: Markdown) -> None: """Check that using the new 'options' YAML key works as expected.""" assert "h1" in ext_markdown.convert("::: tests.fixtures.headings\n options:\n heading_level: 1") assert "h1" not in ext_markdown.convert("::: tests.fixtures.headings\n options:\n heading_level: 2") diff --git a/tests/test_handlers.py b/tests/test_handlers.py index cfe04cd8..a0b3be3e 100644 --- a/tests/test_handlers.py +++ b/tests/test_handlers.py @@ -1,5 +1,7 @@ """Tests for the handlers.base module.""" +from __future__ import annotations + import pytest from markdown import Markdown @@ -7,14 +9,14 @@ @pytest.mark.parametrize("extension_name", ["codehilite", "pymdownx.highlight"]) -def test_highlighter_without_pygments(extension_name): +def test_highlighter_without_pygments(extension_name: str) -> None: """Assert that it's possible to disable Pygments highlighting. Arguments: extension_name: The "user-chosen" Markdown extension for syntax highlighting. """ configs = {extension_name: {"use_pygments": False, "css_class": "hiiii"}} - md = Markdown(extensions=configs, extension_configs=configs) + md = Markdown(extensions=[extension_name], extension_configs=configs) hl = Highlighter(md) assert ( hl.highlight("import foo", language="python") @@ -28,17 +30,14 @@ def test_highlighter_without_pygments(extension_name): @pytest.mark.parametrize("extension_name", [None, "codehilite", "pymdownx.highlight"]) @pytest.mark.parametrize("inline", [False, True]) -def test_highlighter_basic(extension_name, inline): +def test_highlighter_basic(extension_name: str | None, inline: bool) -> None: """Assert that Pygments syntax highlighting works. Arguments: extension_name: The "user-chosen" Markdown extension for syntax highlighting. inline: Whether the highlighting was inline. """ - configs = {} - if extension_name: - configs[extension_name] = {} - md = Markdown(extensions=configs, extension_configs=configs) + md = Markdown(extensions=[extension_name], extension_configs={extension_name: {}}) if extension_name else Markdown() hl = Highlighter(md) actual = hl.highlight("import foo", language="python", inline=inline) diff --git a/tests/test_inventory.py b/tests/test_inventory.py index afbaa9fe..ecbb3cd2 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -1,5 +1,7 @@ """Tests for the inventory module.""" +from __future__ import annotations + import sys from io import BytesIO from os.path import join @@ -22,7 +24,7 @@ Inventory([InventoryItem(name="object_path", domain="py", role="obj", uri="page_url#other_anchor")]), ], ) -def test_sphinx_load_inventory_file(our_inv): +def test_sphinx_load_inventory_file(our_inv: Inventory) -> None: """Perform the 'live' inventory load test.""" buffer = BytesIO(our_inv.format_sphinx()) sphinx_inv = sphinx.InventoryFile.load(buffer, "", join) @@ -35,7 +37,7 @@ def test_sphinx_load_inventory_file(our_inv): @pytest.mark.skipif(sys.version_info < (3, 7), reason="using plugins that require Python 3.7") -def test_sphinx_load_mkdocstrings_inventory_file(): +def test_sphinx_load_mkdocstrings_inventory_file() -> None: """Perform the 'live' inventory load test on mkdocstrings own inventory.""" mkdocs_config = load_config() mkdocs_config["plugins"].run_event("startup", command="build", dirty=False) diff --git a/tests/test_plugin.py b/tests/test_plugin.py index c8649dc8..b8e8d2a5 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1,11 +1,17 @@ """Tests for the mkdocstrings plugin.""" +from __future__ import annotations + +from typing import TYPE_CHECKING from mkdocs.commands.build import build from mkdocs.config import load_config +if TYPE_CHECKING: + from pathlib import Path + -def test_disabling_plugin(tmp_path): +def test_disabling_plugin(tmp_path: Path) -> None: """Test disabling plugin.""" docs_dir = tmp_path / "docs" site_dir = tmp_path / "site"