From 1ee13304a1b841650a28d6d1ad7c5f219eb82819 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 16:39:27 +0000 Subject: [PATCH 1/2] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.20 → v0.16.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.20...v0.16.1) - [github.com/pre-commit/mirrors-mypy: v2.1.0 → v2.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v2.1.0...v2.3.0) - [github.com/codespell-project/codespell: v2.4.2 → v2.4.3](https://github.com/codespell-project/codespell/compare/v2.4.2...v2.4.3) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 93e1203f..a555b8f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,14 +29,14 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.20 + rev: v0.16.1 hooks: - id: ruff args: ["--fix", "--show-fixes"] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v2.1.0 + rev: v2.3.0 hooks: - id: mypy args: [--config-file=pyproject.toml] @@ -52,7 +52,7 @@ repos: )$ - repo: https://github.com/codespell-project/codespell - rev: v2.4.2 + rev: v2.4.3 hooks: - id: codespell args: ["-S", "*.ipynb"] From 0bfa09da320e2bb830724aa546a78713c39aa43d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 16:39:58 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/render/orphaned_nb.ipynb | 2 +- myst_nb/core/config.py | 25 +++++++++++++------------ myst_nb/core/execute/__init__.py | 2 +- myst_nb/core/execute/base.py | 2 +- myst_nb/core/read.py | 14 ++++---------- myst_nb/core/render.py | 5 +++-- myst_nb/docutils_.py | 4 ++-- myst_nb/ext/execution_tables.py | 8 +++++--- myst_nb/ext/glue/crossref.py | 5 +++-- myst_nb/ext/glue/directives.py | 16 ++++++++-------- myst_nb/sphinx_.py | 8 ++++---- myst_nb/sphinx_ext.py | 3 ++- myst_nb/warnings_.py | 4 ++-- tests/conftest.py | 4 ++-- tests/test_execute_kernel_manager.py | 4 ++-- tests/test_render_outputs.py | 2 +- 16 files changed, 54 insertions(+), 54 deletions(-) diff --git a/docs/render/orphaned_nb.ipynb b/docs/render/orphaned_nb.ipynb index 685f11ba..e552bbb5 100644 --- a/docs/render/orphaned_nb.ipynb +++ b/docs/render/orphaned_nb.ipynb @@ -89,8 +89,8 @@ } ], "source": [ - "import numpy as np\n", "import matplotlib.pyplot as plt\n", + "import numpy as np\n", "\n", "data = np.random.rand(3, 100) * 100\n", "\n", diff --git a/myst_nb/core/config.py b/myst_nb/core/config.py index 2451f181..8c769d89 100644 --- a/myst_nb/core/config.py +++ b/myst_nb/core/config.py @@ -1,8 +1,9 @@ """Configuration for myst-nb.""" +from collections.abc import Callable, Iterable, Sequence import dataclasses as dc from enum import Enum -from typing import Any, Callable, Dict, Iterable, Literal, Optional, Sequence, Tuple +from typing import Any, Literal from myst_parser.config.dc_validators import ( ValidatorType, @@ -17,11 +18,11 @@ from myst_nb.warnings_ import MystNBWarnings -def custom_formats_converter(value: dict) -> Dict[str, Tuple[str, dict, bool]]: +def custom_formats_converter(value: dict) -> dict[str, tuple[str, dict, bool]]: """Convert the custom format dict.""" if not isinstance(value, dict): raise TypeError(f"`nb_custom_formats` must be a dict: {value}") - output: Dict[str, Tuple[str, dict, bool]] = {} + output: dict[str, tuple[str, dict, bool]] = {} for suffix, reader in value.items(): if not isinstance(suffix, str): raise TypeError(f"`nb_custom_formats` keys must be a string: {suffix}") @@ -56,7 +57,7 @@ def custom_formats_converter(value: dict) -> Dict[str, Tuple[str, dict, bool]]: return output -def ipywidgets_js_factory() -> Dict[str, Dict[str, str]]: +def ipywidgets_js_factory() -> dict[str, dict[str, str]]: """Create a default ipywidgets js dict.""" # see: https://ipywidgets.readthedocs.io/en/7.6.5/embedding.html return { @@ -128,7 +129,7 @@ def __post_init__(self): # file read options - custom_formats: Dict[str, Tuple[str, dict, bool]] = dc.field( + custom_formats: dict[str, tuple[str, dict, bool]] = dc.field( default_factory=dict, metadata={ "help": "Custom formats for reading notebook; suffix -> reader", @@ -180,7 +181,7 @@ def __post_init__(self): # notebook execution options - kernel_rgx_aliases: Dict[str, str] = dc.field( + kernel_rgx_aliases: dict[str, str] = dc.field( default_factory=dict, metadata={ "validator": deep_mapping(instance_of(str), instance_of(str)), @@ -400,7 +401,7 @@ def __post_init__(self): }, repr=False, ) - mime_priority_overrides: Sequence[Tuple[str, str, Optional[int]]] = dc.field( + mime_priority_overrides: Sequence[tuple[str, str, int | None]] = dc.field( default=(), metadata={ "validator": deep_iterable( @@ -472,7 +473,7 @@ def __post_init__(self): ), }, ) - render_image_options: Dict[str, str] = dc.field( + render_image_options: dict[str, str] = dc.field( default_factory=dict, # see https://docutils.sourceforge.io/docs/ref/rst/directives.html#image metadata={ @@ -489,7 +490,7 @@ def __post_init__(self): ), }, ) - render_figure_options: Dict[str, str] = dc.field( + render_figure_options: dict[str, str] = dc.field( default_factory=dict, # see https://docutils.sourceforge.io/docs/ref/rst/directives.html#figure metadata={ @@ -522,7 +523,7 @@ def __post_init__(self): # TODO jupyter_sphinx_require_url and jupyter_sphinx_embed_url (undocumented), # are no longer used by this package, replaced by ipywidgets_js # do we add any deprecation warnings? - ipywidgets_js: Dict[str, Dict[str, str]] = dc.field( + ipywidgets_js: dict[str, dict[str, str]] = dc.field( default_factory=ipywidgets_js_factory, metadata={ "validator": deep_mapping( @@ -562,13 +563,13 @@ def __post_init__(self): ) @classmethod - def get_fields(cls) -> Tuple[dc.Field, ...]: + def get_fields(cls) -> tuple[dc.Field, ...]: return dc.fields(cls) def as_dict(self, dict_factory=dict) -> dict: return dc.asdict(self, dict_factory=dict_factory) - def as_triple(self) -> Iterable[Tuple[str, Any, dc.Field]]: + def as_triple(self) -> Iterable[tuple[str, Any, dc.Field]]: """Yield triples of (name, value, field).""" fields = {f.name: f for f in dc.fields(self.__class__)} for name, value in dc.asdict(self).items(): diff --git a/myst_nb/core/execute/__init__.py b/myst_nb/core/execute/__init__.py index 8a633929..cb1552b1 100644 --- a/myst_nb/core/execute/__init__.py +++ b/myst_nb/core/execute/__init__.py @@ -9,8 +9,8 @@ from .inline import NotebookClientInline if TYPE_CHECKING: - from nbformat import NotebookNode from jupyter_client import KernelManager + from nbformat import NotebookNode from myst_nb.core.config import NbParserConfig from myst_nb.core.loggers import LoggerType diff --git a/myst_nb/core/execute/base.py b/myst_nb/core/execute/base.py index 8b6bd0b8..4bfd89aa 100644 --- a/myst_nb/core/execute/base.py +++ b/myst_nb/core/execute/base.py @@ -3,7 +3,7 @@ from __future__ import annotations from pathlib import Path -from typing import Any, TYPE_CHECKING +from typing import TYPE_CHECKING, Any from nbformat import NotebookNode from typing_extensions import TypedDict, final diff --git a/myst_nb/core/read.py b/myst_nb/core/read.py index 84a6b35b..d113316c 100644 --- a/myst_nb/core/read.py +++ b/myst_nb/core/read.py @@ -2,11 +2,11 @@ from __future__ import annotations +from collections.abc import Callable, Iterator import dataclasses as dc from functools import partial import json from pathlib import Path -from typing import Callable, Iterator from docutils.parsers.rst import Directive from markdown_it.renderer import RendererHTML @@ -326,9 +326,7 @@ def _read_fenced_cell(token, cell_index, cell_type): ) if result.warnings: raise MystMetadataParsingError( - "{} cell {} at line {} could not be read: {}".format( - cell_type, cell_index, token.map[0] + 1, result.warnings[0] - ) + f"{cell_type} cell {cell_index} at line {token.map[0] + 1} could not be read: {result.warnings[0]}" ) return result.options, result.body @@ -341,15 +339,11 @@ def _read_cell_metadata(token, cell_index): metadata = json.loads(token.content.strip()) except Exception as err: raise MystMetadataParsingError( - "Markdown cell {} at line {} could not be read: {}".format( - cell_index, token.map[0] + 1, err - ) + f"Markdown cell {cell_index} at line {token.map[0] + 1} could not be read: {err}" ) if not isinstance(metadata, dict): raise MystMetadataParsingError( - "Markdown cell {} at line {} is not a dict".format( - cell_index, token.map[0] + 1 - ) + f"Markdown cell {cell_index} at line {token.map[0] + 1} is not a dict" ) return metadata diff --git a/myst_nb/core/render.py b/myst_nb/core/render.py index 2b738e77..18ace6f6 100644 --- a/myst_nb/core/render.py +++ b/myst_nb/core/render.py @@ -7,6 +7,7 @@ from __future__ import annotations from binascii import a2b_base64 +from collections.abc import Iterator, Sequence from contextlib import contextmanager import dataclasses as dc from functools import lru_cache @@ -16,7 +17,7 @@ import os from pathlib import Path import re -from typing import TYPE_CHECKING, Any, ClassVar, Iterator, Sequence, Union +from typing import TYPE_CHECKING, Any, ClassVar, Union from docutils import nodes from docutils.parsers.rst import directives as options_spec @@ -935,7 +936,7 @@ def strip_latex_delimiters(source): https://github.com/jupyter/jupyter-sphinx/issues/90 for discussion. """ source = source.strip() - delimiter_pairs = (pair.split() for pair in r"\( \),\[ \],$$ $$,$ $".split(",")) + delimiter_pairs = (pair.split() for pair in [r"\( \)", r"\[ \]", r"$$ $$", r"$ $"]) for start, end in delimiter_pairs: if source.startswith(start) and source.endswith(end): return source[len(start) : -len(end)] diff --git a/myst_nb/docutils_.py b/myst_nb/docutils_.py index 3abece41..5dcad172 100644 --- a/myst_nb/docutils_.py +++ b/myst_nb/docutils_.py @@ -6,7 +6,7 @@ from functools import lru_cache, partial from importlib import resources as import_resources import os -from typing import Any, TYPE_CHECKING +from typing import TYPE_CHECKING, Any from docutils import nodes from docutils.core import default_description, publish_cmdline @@ -153,7 +153,7 @@ def _parse(self, inputstring: str, document: nodes.document) -> None: notebook = nb_reader.read(inputstring) # update the global markdown config with the file-level config - warning = lambda wtype, msg: create_warning( # noqa: E731 + warning = lambda wtype, msg: create_warning( document, msg, line=1, append_to=document, subtype=wtype ) nb_reader.md_config = merge_file_level( diff --git a/myst_nb/ext/execution_tables.py b/myst_nb/ext/execution_tables.py index 7beaacc9..28f47104 100644 --- a/myst_nb/ext/execution_tables.py +++ b/myst_nb/ext/execution_tables.py @@ -7,9 +7,11 @@ from __future__ import annotations +from collections import defaultdict +from collections.abc import Callable from datetime import datetime import posixpath -from typing import Any, Callable, DefaultDict +from typing import Any from docutils import nodes from sphinx.addnodes import pending_xref @@ -104,7 +106,7 @@ def run(self, **kwargs) -> None: def make_stat_table( - parent_docname: str, metadata: DefaultDict[str, dict] + parent_docname: str, metadata: defaultdict[str, dict] ) -> nodes.table: """Create a table of statistics on executed notebooks.""" @@ -158,7 +160,7 @@ def make_stat_table( row.append(nodes.entry("", paragraph)) # other rows - for name in _key2header.keys(): + for name in _key2header: paragraph = nodes.paragraph() if name == "succeeded" and data[name] is False: paragraph += nodes.abbreviation( diff --git a/myst_nb/ext/glue/crossref.py b/myst_nb/ext/glue/crossref.py index e7817bab..0c1c35db 100644 --- a/myst_nb/ext/glue/crossref.py +++ b/myst_nb/ext/glue/crossref.py @@ -7,13 +7,14 @@ from __future__ import annotations from binascii import a2b_base64 +from collections.abc import Sequence from functools import lru_cache import hashlib import json from mimetypes import guess_extension -from pathlib import Path -from typing import Any, Sequence import os +from pathlib import Path +from typing import Any from docutils import nodes from sphinx.builders import Builder diff --git a/myst_nb/ext/glue/directives.py b/myst_nb/ext/glue/directives.py index faf2ba76..2efbe0be 100644 --- a/myst_nb/ext/glue/directives.py +++ b/myst_nb/ext/glue/directives.py @@ -4,7 +4,7 @@ in order to allow docutils-only use without sphinx installed. """ -from typing import TYPE_CHECKING, Any, Dict, List +from typing import TYPE_CHECKING, Any from docutils import nodes from docutils.parsers.rst import directives as spec @@ -36,7 +36,7 @@ class PasteAnyDirective(DirectiveBase): option_spec = {"doc": spec.unchanged} - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" key = self.arguments[0] if "doc" in self.options: @@ -81,7 +81,7 @@ class PasteMarkdownDirective(DirectiveBase): "format": md_fmt, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" key = self.arguments[0] try: @@ -149,7 +149,7 @@ def run(self): data = retrieve_glue_data(self.document, self.arguments[0]) except RetrievalError as exc: return [glue_warning(str(exc), self.document, self.line)] - render: Dict[str, Any] = {} + render: dict[str, Any] = {} for key in ("alt", "height", "width", "scale", "class"): if key in self.options: render.setdefault("image", {})[key.replace("classes", "class")] = ( @@ -217,7 +217,7 @@ class PasteMathDirective(DirectiveBase): "name": spec.unchanged, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" key = self.arguments[0] try: @@ -249,10 +249,10 @@ def run(self) -> List[nodes.Node]: return self.add_target(node) return [node] - def add_target(self, node: nodes.math_block) -> List[nodes.Node]: + def add_target(self, node: nodes.math_block) -> list[nodes.Node]: """Add target to the node.""" # adapted from sphinx.directives.patches.MathDirective - env: "BuildEnvironment" = self.document.settings.env + env: BuildEnvironment = self.document.settings.env node["docname"] = env.docname @@ -266,7 +266,7 @@ def add_target(self, node: nodes.math_block) -> List[nodes.Node]: return [node] # register label to domain - domain: "MathDomain" = env.get_domain("math") # type: ignore + domain: MathDomain = env.get_domain("math") # type: ignore domain.note_equation(env.docname, node["label"], location=node) node["number"] = domain.get_equation_number_for(node["label"]) diff --git a/myst_nb/sphinx_.py b/myst_nb/sphinx_.py index c6c03d3f..9ce3fab4 100644 --- a/myst_nb/sphinx_.py +++ b/myst_nb/sphinx_.py @@ -7,7 +7,7 @@ import json from pathlib import Path import re -from typing import Any, DefaultDict, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, cast from docutils import nodes from markdown_it.token import Token @@ -53,7 +53,7 @@ class SphinxEnvType(BuildEnvironment): myst_config: MdParserConfig mystnb_config: NbParserConfig - nb_metadata: DefaultDict[str, dict] + nb_metadata: defaultdict[str, dict] nb_new_exec_data: bool @@ -106,7 +106,7 @@ def parse(self, inputstring: str, document: nodes.document) -> None: notebook = nb_reader.read(inputstring) # update the global markdown config with the file-level config - warning = lambda wtype, msg: create_warning( # noqa: E731 + warning = lambda wtype, msg: create_warning( document, msg, line=1, append_to=document, subtype=wtype ) nb_reader.md_config = merge_file_level( @@ -392,7 +392,7 @@ def set_doc_data(env: SphinxEnvType, docname: str, key: str, value: Any) -> None env.nb_metadata.setdefault(docname, {})[key] = value @staticmethod - def get_doc_data(env: SphinxEnvType) -> DefaultDict[str, dict]: + def get_doc_data(env: SphinxEnvType) -> defaultdict[str, dict]: """Get myst-nb docname -> metadata dict.""" if not hasattr(env, "nb_metadata"): env.nb_metadata = defaultdict(dict) diff --git a/myst_nb/sphinx_ext.py b/myst_nb/sphinx_ext.py index 9a7b7996..e7119ce7 100644 --- a/myst_nb/sphinx_ext.py +++ b/myst_nb/sphinx_ext.py @@ -2,13 +2,14 @@ from __future__ import annotations +from collections.abc import Iterator import contextlib import hashlib from importlib import resources as import_resources import os from pathlib import Path from types import ModuleType -from typing import Any, Iterator, cast +from typing import Any, cast from myst_parser.sphinx_ext.main import setup_sphinx as setup_myst_parser from sphinx.application import Sphinx diff --git a/myst_nb/warnings_.py b/myst_nb/warnings_.py index 4284f2d6..cddc4b9a 100644 --- a/myst_nb/warnings_.py +++ b/myst_nb/warnings_.py @@ -2,16 +2,16 @@ from __future__ import annotations +from collections.abc import Sequence from enum import Enum -from typing import Sequence from docutils import nodes from myst_parser.warnings_ import MystWarnings from myst_parser.warnings_ import create_warning as myst_parser_create_warnings __all__ = [ - "MystWarnings", "MystNBWarnings", + "MystWarnings", "create_warning", ] diff --git a/tests/conftest.py b/tests/conftest.py index f2bdb3b7..2d547028 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,10 +2,11 @@ import os from pathlib import Path import re -import uuid import shutil +import uuid import bs4 +import docutils from docutils.nodes import image as image_node from nbconvert.filters import strip_ansi from nbdime.diffing.notebooks import ( @@ -16,7 +17,6 @@ from nbdime.prettyprint import pretty_print_diff import nbformat as nbf import pytest -import docutils import sphinx from sphinx import version_info as sphinx_version_info from sphinx.util.console import nocolor diff --git a/tests/test_execute_kernel_manager.py b/tests/test_execute_kernel_manager.py index c8a0c8e3..a4dc1a2b 100644 --- a/tests/test_execute_kernel_manager.py +++ b/tests/test_execute_kernel_manager.py @@ -1,12 +1,12 @@ from __future__ import annotations import gc -import warnings from typing import TYPE_CHECKING +import warnings +from jupyter_client import AsyncKernelManager import nbformat import pytest -from jupyter_client import AsyncKernelManager from myst_nb.core.config import NbParserConfig from myst_nb.core.execute import create_client diff --git a/tests/test_render_outputs.py b/tests/test_render_outputs.py index bfd29e51..115daae2 100644 --- a/tests/test_render_outputs.py +++ b/tests/test_render_outputs.py @@ -1,9 +1,9 @@ """Tests for rendering code cell outputs.""" import pytest +from sphinx.util.fileutil import copy_asset_file from myst_nb.core.render import EntryPointError, load_renderer -from sphinx.util.fileutil import copy_asset_file def test_load_renderer_not_found():