From 26b7013054b683f40d17aa5b5e9d7dff57f7b271 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 01:51:05 -0700 Subject: [PATCH 01/10] Update coconut requirement from <2.3.0,>=1.4.3 to >=1.4.3,<3.1.0 (#517) Updates the requirements on [coconut](https://github.com/evhub/coconut) to permit the latest version. - [Release notes](https://github.com/evhub/coconut/releases) - [Commits](https://github.com/evhub/coconut/compare/v1.4.3...v3.0.0) --- updated-dependencies: - dependency-name: coconut dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1d759b32..f0cafba4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ rtd = [ "alabaster", "altair", "bokeh", - "coconut>=1.4.3,<2.3.0", + "coconut>=1.4.3,<3.1.0", "ipykernel~=5.5", "ipywidgets", "jupytext>=1.11.2,<1.15.0", From 5d972446636b631dd5777f286420cce3e906cfce Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 01:51:15 -0700 Subject: [PATCH 02/10] [pre-commit.ci] pre-commit autoupdate (#518) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.3.2 → v3.7.0](https://github.com/asottile/pyupgrade/compare/v3.3.2...v3.7.0) - [github.com/pre-commit/mirrors-mypy: v1.2.0 → v1.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.2.0...v1.3.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7896a9fc..a10c3699 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade - rev: v3.3.2 + rev: v3.7.0 hooks: - id: pyupgrade args: [--py37-plus] @@ -42,7 +42,7 @@ repos: additional_dependencies: [flake8-bugbear] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.2.0 + rev: v1.3.0 hooks: - id: mypy args: [--config-file=pyproject.toml] From 46c58de6bf58235a6007b51ebd019896bc08cfc1 Mon Sep 17 00:00:00 2001 From: Angus Hollands Date: Fri, 23 Jun 2023 13:21:53 +0100 Subject: [PATCH 03/10] Feat: allow any value for expr (#429) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- myst_nb/core/config.py | 8 ++++++++ myst_nb/core/execute/base.py | 4 ---- myst_nb/core/execute/inline.py | 5 +++-- myst_nb/ext/eval/__init__.py | 6 ++++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/myst_nb/core/config.py b/myst_nb/core/config.py index 1d69465a..8f7b117f 100644 --- a/myst_nb/core/config.py +++ b/myst_nb/core/config.py @@ -188,6 +188,14 @@ def __post_init__(self): "sections": (Section.global_lvl, Section.execute), }, ) + eval_name_regex: str = dc.field( + default=r"^[a-zA-Z_][a-zA-Z0-9_]*$", + metadata={ + "validator": instance_of(str), + "help": "Regex that matches permitted values of eval expressions", + "sections": (Section.global_lvl, Section.file_lvl, Section.execute), + }, + ) execution_mode: Literal["off", "force", "auto", "cache", "inline"] = dc.field( default="auto", metadata={ diff --git a/myst_nb/core/execute/base.py b/myst_nb/core/execute/base.py index edcfd03d..befb6d29 100644 --- a/myst_nb/core/execute/base.py +++ b/myst_nb/core/execute/base.py @@ -2,7 +2,6 @@ from __future__ import annotations from pathlib import Path -import re from typing import Any from nbformat import NotebookNode @@ -39,9 +38,6 @@ class EvalNameError(Exception): """An exception for if an evaluation variable name is invalid.""" -EVAL_NAME_REGEX = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$") - - class NotebookClientBase: """A base client for interacting with Jupyter notebooks. diff --git a/myst_nb/core/execute/inline.py b/myst_nb/core/execute/inline.py index 06b53b07..13d20786 100644 --- a/myst_nb/core/execute/inline.py +++ b/myst_nb/core/execute/inline.py @@ -3,6 +3,7 @@ import asyncio from datetime import datetime +import re import shutil from tempfile import mkdtemp import time @@ -22,7 +23,7 @@ from myst_nb.ext.glue import extract_glue_data_cell -from .base import EVAL_NAME_REGEX, EvalNameError, ExecutionError, NotebookClientBase +from .base import EvalNameError, ExecutionError, NotebookClientBase class NotebookClientInline(NotebookClientBase): @@ -148,7 +149,7 @@ def code_cell_outputs( return cell.get("execution_count", None), cell.get("outputs", []) def eval_variable(self, name: str) -> list[NotebookNode]: - if not EVAL_NAME_REGEX.match(name): + if not re.match(self.nb_config.eval_name_regex, name): raise EvalNameError(name) return self._client.eval_expression(name) diff --git a/myst_nb/ext/eval/__init__.py b/myst_nb/ext/eval/__init__.py index 3b565c74..52c04cd2 100644 --- a/myst_nb/ext/eval/__init__.py +++ b/myst_nb/ext/eval/__init__.py @@ -43,11 +43,13 @@ def retrieve_eval_data(document: nodes.document, key: str) -> list[VariableOutpu except NotImplementedError: raise RetrievalError("This document does not have a running kernel") except EvalNameError: - raise RetrievalError(f"The variable {key!r} is not a valid name") + raise RetrievalError( + f"The expression {key!r} is not valid according to the configured pattern" + ) except Exception as exc: raise RetrievalError(f"variable evaluation error: {exc}") if not outputs: - raise RetrievalError(f"variable {key!r} does not return any outputs") + raise RetrievalError(f"expression {key!r} does not return any outputs") # the returned outputs could be one of the following: # https://nbformat.readthedocs.io/en/latest/format_description.html#code-cell-outputs From 48c45c6a8c4501005766c2d821b5e9ddfbedd5fa Mon Sep 17 00:00:00 2001 From: Alvaro Leiva geisse Date: Fri, 30 Jun 2023 01:10:50 -0700 Subject: [PATCH 04/10] UPGRADE: myst-parser 1.0 (#479) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Chris Holdgraf Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Angus Hollands Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Holdgraf Co-authored-by: Josh Mitchell Co-authored-by: Michael Aye Co-authored-by: Jan-Hendrik Müller <44469195+kolibril13@users.noreply.github.com> Co-authored-by: Oriol Abril-Pla Co-authored-by: mmcky Co-authored-by: mmcky --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 4 +- docs/authoring/custom-formats.Rmd | 2 +- docs/authoring/jupyter-notebooks.md | 16 ++-- docs/index.md | 2 +- myst_nb/__init__.py | 2 +- myst_nb/core/config.py | 32 +++++--- myst_nb/core/read.py | 25 +++--- myst_nb/core/render.py | 38 ++++----- myst_nb/docutils_.py | 36 ++++----- myst_nb/ext/glue/directives.py | 1 - myst_nb/sphinx_.py | 10 ++- myst_nb/warnings_.py | 103 ++++++++++++++++++++++++ pyproject.toml | 6 +- tests/nb_fixtures/reporter_warnings.txt | 9 +-- 15 files changed, 191 insertions(+), 97 deletions(-) create mode 100644 myst_nb/warnings_.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a10c3699..a84a065e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: args: [--config-file=pyproject.toml] additional_dependencies: - importlib_metadata - - myst-parser~=0.18.0 + - myst-parser~=1.0.0 - "sphinx~=5.0" - nbclient - types-PyYAML diff --git a/CHANGELOG.md b/CHANGELOG.md index d0191248..0699e778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,7 +92,7 @@ WARNING: 'jupyter_execute_notebooks' is deprecated for 'nb_execution_mode' [myst `nb_render_priority` has been removed and replaced by `nb_mime_priority_overrides`, which has a different format and is more flexible. See [Outputs MIME priority](docs/render/format_code_cells.md) for more information. -As per the changes in [`myst_parser`](myst:develop/_changelog), the `dollarmath` syntax extension is no longer included by default. +As per the changes in [`myst_parser`](inv:myst#develop/_changelog), the `dollarmath` syntax extension is no longer included by default. To re-add this extension, ensure that it is specified in your `conf.py`: `myst_enable_extensions = ["dollarmath"]`. For cell-level configuration the top-level key `render` has now been deprecated for `mystnb`. @@ -168,7 +168,7 @@ See [Embedding outputs as variables](docs/render/glue.md) for more details. - `nbconvert` - Updated: - `Python`: `3.6+ -> 3.7+` - - `myst_parser`: [`0.15 -> 0.17`](myst:develop/_changelog) + - `myst_parser`: [`0.15 -> 0.17`](inv:myst#develop/_changelog) - `jupyter-cache`: [`0.4 -> 0.5`](https://github.com/executablebooks/jupyter-cache/blob/master/CHANGELOG.md) - `sphinx-togglebutton`: [`0.1 -> 0.3`](https://sphinx-togglebutton.readthedocs.io/en/latest/changelog.html) diff --git a/docs/authoring/custom-formats.Rmd b/docs/authoring/custom-formats.Rmd index c682702c..7575d250 100644 --- a/docs/authoring/custom-formats.Rmd +++ b/docs/authoring/custom-formats.Rmd @@ -21,7 +21,7 @@ nb_custom_formats = { ``` - The string should be a Python function that will be loaded by `import mylibrary.converter_function` -- The function should take a file's contents (as a `str`) and return an [nbformat.NotebookNode](nbformat:api) +- The function should take a file's contents (as a `str`) and return an [nbformat.NotebookNode](inv:nbformat#api) If the function takes additional keyword arguments, then you can specify these as dictionary in a second argument. For example this is what the default conversion would look like: diff --git a/docs/authoring/jupyter-notebooks.md b/docs/authoring/jupyter-notebooks.md index 945ab336..58b1f71a 100644 --- a/docs/authoring/jupyter-notebooks.md +++ b/docs/authoring/jupyter-notebooks.md @@ -16,13 +16,13 @@ Sphinx using the MyST parser.[^download] :::{seealso} For more information about what you can write with MyST Markdown, see the -[MyST Parser documentation](myst:intro/get-started). +[MyST Parser documentation](inv:myst#intro/get-started). ::: ### Configuration -The MyST-NB parser derives from [the base MyST-Parser](myst:intro/get-started), and so all the same configuration options are available. -See the [MyST configuration options](myst:sphinx/config-options) for the full set of options, and [MyST syntax guide](myst:syntax/core) for all the syntax options. +The MyST-NB parser derives from [the base MyST-Parser](inv:myst#intro/get-started), and so all the same configuration options are available. +See the [MyST configuration options](inv:myst#sphinx/config-options) for the full set of options, and [MyST syntax guide](inv:myst#syntax/core) for all the syntax options. To build documentation from this notebook, the following options are set: @@ -38,7 +38,7 @@ myst_url_schemes = ("http", "https", "mailto") ``` :::{note} -Loading the `myst_nb` extension also activates the [`myst_parser`](myst:index) extension, for enabling the MyST flavour of Markdown. +Loading the `myst_nb` extension also activates the [`myst_parser`](inv:myst#index) extension, for enabling the MyST flavour of Markdown. It is not required to add this explicitly in the list of `extensions`. ::: @@ -53,7 +53,7 @@ For example, here's the MyST-NB logo: ![myst-nb logo](../_static/logo-wide.svg) -By adding `"html_image"` to the `myst_enable_extensions` list in the sphinx configuration ([see here](myst:syntax/images)), you can even add HTML `img` tags with attributes: +By adding `"html_image"` to the `myst_enable_extensions` list in the sphinx configuration ([see here](inv:myst#syntax/images)), you can even add HTML `img` tags with attributes: ```html logo @@ -66,7 +66,7 @@ For example, here's a note admonition block: :::::{note} **Wow**, a note! -It was generated with this code ([as explained here](myst:syntax/admonitions)): +It was generated with this code ([as explained here](inv:myst:std:label#syntax/admonitions)): ````md :::{note} @@ -77,7 +77,7 @@ It was generated with this code ([as explained here](myst:syntax/admonitions)): ::::: If you wish to use "bare" LaTeX equations, then you should add `"amsmath"` to the `myst_enable_extensions` list in the sphinx configuration. -This is [explained here](myst:syntax/amsmath), and works as such: +This is [explained here](inv:myst:std:label#syntax/amsmath), and works as such: ```latex \begin{equation} @@ -110,7 +110,7 @@ $$e^{i\pi} + 1 = 0$$ (euler) Euler's identity, equation {math:numref}`euler`, was elected one of the most beautiful mathematical formulas. -You can see the syntax used for this example [here in the MyST documentation](myst:syntax/math). +You can see the syntax used for this example [here in the MyST documentation](inv:myst:std:label#syntax/math). ## Code cells and outputs diff --git a/docs/index.md b/docs/index.md index 06fef4a1..d75b9260 100644 --- a/docs/index.md +++ b/docs/index.md @@ -86,7 +86,7 @@ Build single or collections of documents into multiple formats (HTML, PDF, ...). MyST-NB is a module within the [Executable Books Project](https://executablebooks.org), an international collaboration to build open source tools that facilitate publishing computational narratives using the Jupyter ecosystem. -It is also a core component of [Jupyter Book](jb:intro). +It is also a core component of [Jupyter Book](inv:jb#intro). Check out the [Gallery of Jupyter Books](https://executablebooks.org/en/latest/gallery), for inspiration from across the community. diff --git a/myst_nb/__init__.py b/myst_nb/__init__.py index 7fd25d88..8b156d3a 100644 --- a/myst_nb/__init__.py +++ b/myst_nb/__init__.py @@ -1,5 +1,5 @@ """A docutils/sphinx parser for Jupyter Notebooks.""" -__version__ = "0.17.2" +__version__ = "0.18.0" def setup(app): diff --git a/myst_nb/core/config.py b/myst_nb/core/config.py index 8f7b117f..3bf97e83 100644 --- a/myst_nb/core/config.py +++ b/myst_nb/core/config.py @@ -1,6 +1,7 @@ """Configuration for myst-nb.""" import dataclasses as dc from enum import Enum +import sys from typing import Any, Callable, Dict, Iterable, Optional, Sequence, Tuple from myst_parser.config.dc_validators import ( @@ -12,7 +13,13 @@ optional, validate_fields, ) -from typing_extensions import Literal + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal # noqa: F401 + +from myst_nb.warnings_ import MystNBWarnings def custom_formats_converter(value: dict) -> Dict[str, Tuple[str, dict, bool]]: @@ -130,7 +137,7 @@ def __post_init__(self): default_factory=dict, metadata={ "help": "Custom formats for reading notebook; suffix -> reader", - "docutils_exclude": True, + "omit": ["docutils"], "sections": (Section.global_lvl, Section.read), }, ) @@ -184,7 +191,7 @@ def __post_init__(self): "validator": deep_mapping(instance_of(str), instance_of(str)), "help": "Mapping of kernel name regex to replacement kernel name" "(applied before execution)", - "docutils_exclude": True, + "omit": ["docutils"], "sections": (Section.global_lvl, Section.execute), }, ) @@ -228,7 +235,7 @@ def __post_init__(self): "validator": deep_iterable(instance_of(str)), "help": "Exclude (POSIX) glob patterns for notebooks", "legacy_name": "execution_excludepatterns", - "docutils_exclude": True, + "omit": ["docutils"], "sections": (Section.global_lvl, Section.execute), }, ) @@ -395,7 +402,7 @@ def __post_init__(self): "help": "Overrides for the base render priority of mime types: " "list of (builder name, mime type, priority)", # TODO how to allow this in docutils? - "docutils_exclude": True, + "omit": ["docutils"], "sections": (Section.global_lvl, Section.file_lvl, Section.render), }, repr=False, @@ -462,7 +469,7 @@ def __post_init__(self): metadata={ "validator": deep_mapping(instance_of(str), instance_of((str, int))), "help": "Options for image outputs (class|alt|height|width|scale|align)", - "docutils_exclude": True, + "omit": ["docutils"], # TODO backward-compatible change to "image_options"? "cell_key": "image", "sections": ( @@ -479,7 +486,7 @@ def __post_init__(self): metadata={ "validator": deep_mapping(instance_of(str), instance_of((str, int))), "help": "Options for figure outputs (classes|name|caption|caption_before)", - "docutils_exclude": True, + "omit": ["docutils"], "cell_key": "figure", "sections": ( Section.global_lvl, @@ -513,7 +520,7 @@ def __post_init__(self): instance_of(str), deep_mapping(instance_of(str), instance_of(str)) ), "help": "Javascript to be loaded on pages containing ipywidgets", - "docutils_exclude": True, + "omit": ["docutils"], "sections": (Section.global_lvl, Section.render), }, repr=False, @@ -575,7 +582,7 @@ def get_cell_level_config( self, field_name: str, cell_metadata: Dict[str, Any], - warning_callback: Callable[[str, str], Any], + warning_callback: Callable[[str, MystNBWarnings], Any], ) -> Any: """Get a configuration value at the cell level. @@ -601,7 +608,7 @@ def get_cell_level_config( warning_callback( f"Deprecated `cell_metadata_key` 'render' " f"found, replace with {self.cell_metadata_key!r}", - "cell_metadata_key", + MystNBWarnings.CELL_METADATA_KEY, ) cell_meta = cell_metadata["render"] else: @@ -619,7 +626,10 @@ def get_cell_level_config( field.metadata["validator"](self, field, value) return value except Exception as exc: - warning_callback(f"Cell metadata invalid: {exc}", "cell_config") + warning_callback( + f"Cell metadata invalid: {exc}", + MystNBWarnings.CELL_CONFIG, + ) # default/global/file level should have already been merged return getattr(self, field.name) diff --git a/myst_nb/core/read.py b/myst_nb/core/read.py index ad011049..2b3dae4b 100644 --- a/myst_nb/core/read.py +++ b/myst_nb/core/read.py @@ -312,25 +312,22 @@ class _MockDirective: def _read_fenced_cell(token, cell_index, cell_type): - from myst_parser.parsers.directives import ( - DirectiveParsingError, - parse_directive_text, - ) + from myst_parser.parsers.directives import parse_directive_text - try: - _, options, body_lines, _ = parse_directive_text( - directive_class=_MockDirective, - first_line="", - content=token.content, - validate_options=False, - ) - except DirectiveParsingError as err: + result = parse_directive_text( + directive_class=_MockDirective, + first_line="", + content=token.content, + validate_options=False, + ) + if result.warnings: raise MystMetadataParsingError( "{} cell {} at line {} could not be read: {}".format( - cell_type, cell_index, token.map[0] + 1, err + cell_type, cell_index, token.map[0] + 1, result.warnings[0] ) ) - return options, body_lines + + return result.options, result.body def _read_cell_metadata(token, cell_index): diff --git a/myst_nb/core/render.py b/myst_nb/core/render.py index e28b856b..54f1762d 100644 --- a/myst_nb/core/render.py +++ b/myst_nb/core/render.py @@ -28,8 +28,9 @@ from myst_nb.core.config import NbParserConfig from myst_nb.core.execute import NotebookClientBase -from myst_nb.core.loggers import DEFAULT_LOG_TYPE, LoggerType +from myst_nb.core.loggers import LoggerType # DEFAULT_LOG_TYPE, from myst_nb.core.utils import coalesce_streams +from myst_nb.warnings_ import MystNBWarnings, create_warning if TYPE_CHECKING: from markdown_it.tree import SyntaxTreeNode @@ -57,7 +58,6 @@ class MditRenderMixin: # required by mypy md_options: dict[str, Any] document: nodes.document - create_warning: Any render_children: Any add_line_and_source_path: Any add_line_and_source_path_r: Any @@ -95,8 +95,8 @@ def get_cell_level_config( :param cell_metadata: the metadata for the cell """ - def _callback(msg: str, subtype: str): - self.create_warning(msg, line=line, subtype=subtype) + def _callback(msg: str, subtype: MystNBWarnings): + create_warning(self.document, msg, line=line, subtype=subtype) return self.nb_config.get_cell_level_config(field, cell_metadata, _callback) @@ -222,10 +222,11 @@ def _get_nb_source_code_lexer( # TODO this will create a warning for every cell, but perhaps # it should only be a single warning for the notebook (as previously) # TODO allow user to set default lexer? - self.create_warning( + create_warning( + self.document, f"No source code lexer found for notebook cell {cell_index + 1}", - wtype=DEFAULT_LOG_TYPE, - subtype="lexer", + # wtype=DEFAULT_LOG_TYPE, + subtype=MystNBWarnings.LEXER, line=line, append_to=self.current_node, ) @@ -310,11 +311,6 @@ class MimeData: """Index of the output in the cell""" line: int | None = None """Source line of the cell""" - md_headings: bool = False - """Whether to render headings in text/markdown blocks.""" - # we can only do this if know the content will be rendered into the main body - # of the document, e.g. not inside a container node - # (otherwise it will break the structure of the AST) @property def string(self) -> str: @@ -598,9 +594,7 @@ def render_markdown(self, data: MimeData) -> list[nodes.Element]: fmt = self.renderer.get_cell_level_config( "render_markdown_format", data.cell_metadata, line=data.line ) - return self._render_markdown_base( - data, fmt=fmt, inline=False, allow_headings=data.md_headings - ) + return self._render_markdown_base(data, fmt=fmt, inline=False) def render_text_plain(self, data: MimeData) -> list[nodes.Element]: """Render a notebook text/plain mime data output.""" @@ -753,9 +747,7 @@ def render_markdown_inline(self, data: MimeData) -> list[nodes.Element]: fmt = self.renderer.get_cell_level_config( "render_markdown_format", data.cell_metadata, line=data.line ) - return self._render_markdown_base( - data, fmt=fmt, inline=True, allow_headings=data.md_headings - ) + return self._render_markdown_base(data, fmt=fmt, inline=True) def render_text_plain_inline(self, data: MimeData) -> list[nodes.Element]: """Render a notebook text/plain mime data output.""" @@ -796,7 +788,7 @@ def render_widget_view_inline(self, data: MimeData) -> list[nodes.Element]: return self.render_widget_view(data) def _render_markdown_base( - self, data: MimeData, *, fmt: str, inline: bool, allow_headings: bool + self, data: MimeData, *, fmt: str, inline: bool ) -> list[nodes.Element]: """Base render for a notebook markdown mime output (block or inline).""" psuedo_element = nodes.Element() # element to hold the parsed markdown @@ -832,7 +824,6 @@ def _render_markdown_base( data.string, data.line or 0, inline=inline, - allow_headings=allow_headings, ) finally: # restore the parser @@ -986,11 +977,12 @@ def create_figure_context( caption.source = self.document["source"] caption.line = line elif not (isinstance(first_node, nodes.comment) and len(first_node) == 0): - self.create_warning( + create_warning( + self.document, "Figure caption must be a paragraph or empty comment.", line=line, - wtype=DEFAULT_LOG_TYPE, - subtype="fig_caption", + # wtype=DEFAULT_LOG_TYPE, + subtype=MystNBWarnings.FIG_CAPTION, ) self.current_node.append(figure_node) diff --git a/myst_nb/docutils_.py b/myst_nb/docutils_.py index 9738a0f0..7da9c6db 100644 --- a/myst_nb/docutils_.py +++ b/myst_nb/docutils_.py @@ -14,14 +14,7 @@ from markdown_it.token import Token from markdown_it.tree import SyntaxTreeNode from myst_parser.config.main import MdParserConfig, merge_file_level -from myst_parser.mdit_to_docutils.base import ( - DocutilsRenderer, - create_warning, - token_line, -) -from myst_parser.parsers.docutils_ import ( - DOCUTILS_EXCLUDED_ARGS as DOCUTILS_EXCLUDED_ARGS_MYST, -) +from myst_parser.mdit_to_docutils.base import DocutilsRenderer, token_line from myst_parser.parsers.docutils_ import Parser as MystParser from myst_parser.parsers.docutils_ import create_myst_config, create_myst_settings_spec from myst_parser.parsers.mdit import create_md_parser @@ -32,7 +25,7 @@ from myst_nb import static from myst_nb.core.config import NbParserConfig from myst_nb.core.execute import create_client -from myst_nb.core.loggers import DEFAULT_LOG_TYPE, DocutilsDocLogger +from myst_nb.core.loggers import DocutilsDocLogger # DEFAULT_LOG_TYPE, from myst_nb.core.nb_to_tokens import nb_node_to_dict, notebook_to_tokens from myst_nb.core.read import ( NbReader, @@ -50,6 +43,7 @@ ) from myst_nb.ext.eval import load_eval_docutils from myst_nb.ext.glue import load_glue_docutils +from myst_nb.warnings_ import MystNBWarnings, create_warning DOCUTILS_EXCLUDED_ARGS = list( {f.name for f in NbParserConfig.get_fields() if f.metadata.get("docutils_exclude")} @@ -81,7 +75,7 @@ class Parser(MystParser): settings_spec = ( "MyST-NB options", None, - create_myst_settings_spec(DOCUTILS_EXCLUDED_ARGS, NbParserConfig, "nb_"), + create_myst_settings_spec(NbParserConfig, "nb_"), *MystParser.settings_spec, ) """Runtime settings specification.""" @@ -116,18 +110,14 @@ def _parse(self, inputstring: str, document: nodes.document) -> None: # get markdown parsing configuration try: - md_config = create_myst_config( - document.settings, DOCUTILS_EXCLUDED_ARGS_MYST - ) + md_config = create_myst_config(document.settings) except (TypeError, ValueError) as error: logger.error(f"myst configuration invalid: {error.args[0]}") md_config = MdParserConfig() # get notebook rendering configuration try: - nb_config = create_myst_config( - document.settings, DOCUTILS_EXCLUDED_ARGS, NbParserConfig, "nb_" - ) + nb_config = create_myst_config(document.settings, NbParserConfig, "nb_") except (TypeError, ValueError) as error: logger.error(f"myst-nb configuration invalid: {error.args[0]}") nb_config = NbParserConfig() @@ -310,13 +300,14 @@ def _render_nb_cell_code_outputs( mime_type = next(x for x in mime_priority if x in output["data"]) except StopIteration: if output["data"]: - self.create_warning( + create_warning( + self.document, "No output mime type found from render_priority " f"(cell<{cell_index}>.output<{output_index}>", line=line, append_to=self.current_node, - wtype=DEFAULT_LOG_TYPE, - subtype="mime_type", + # wtype=DEFAULT_LOG_TYPE, + subtype=MystNBWarnings.MIME_TYPE, ) else: figure_options = ( @@ -341,12 +332,13 @@ def _render_nb_cell_code_outputs( self.current_node.extend(_nodes) self.add_line_and_source_path_r(_nodes, token) else: - self.create_warning( + create_warning( + self.document, f"Unsupported output type: {output.output_type}", line=line, append_to=self.current_node, - wtype=DEFAULT_LOG_TYPE, - subtype="output_type", + # wtype=DEFAULT_LOG_TYPE, + subtype=MystNBWarnings.OUTPUT_TYPE, ) diff --git a/myst_nb/ext/glue/directives.py b/myst_nb/ext/glue/directives.py index fc63376c..4d42c15a 100644 --- a/myst_nb/ext/glue/directives.py +++ b/myst_nb/ext/glue/directives.py @@ -106,7 +106,6 @@ def run(self) -> List[nodes.Node]: }, output_metadata=result.metadata, line=self.line, - md_headings=True, ) _nodes = result.nb_renderer.render_markdown(mime) self.set_source_info(_nodes) diff --git a/myst_nb/sphinx_.py b/myst_nb/sphinx_.py index 62bd9a7c..dba36531 100644 --- a/myst_nb/sphinx_.py +++ b/myst_nb/sphinx_.py @@ -13,7 +13,7 @@ from markdown_it.tree import SyntaxTreeNode from myst_parser.config.main import MdParserConfig, merge_file_level from myst_parser.mdit_to_docutils.base import token_line -from myst_parser.mdit_to_docutils.sphinx_ import SphinxRenderer, create_warning +from myst_parser.mdit_to_docutils.sphinx_ import SphinxRenderer from myst_parser.parsers.mdit import create_md_parser from myst_parser.parsers.sphinx_ import MystParser import nbformat @@ -38,6 +38,7 @@ get_mime_priority, load_renderer, ) +from myst_nb.warnings_ import MystNBWarnings, create_warning SPHINX_LOGGER = sphinx_logging.getLogger(__name__) @@ -301,12 +302,13 @@ def _render_nb_cell_code_outputs( self.add_line_and_source_path_r([mime_bundle], token) self.current_node.append(mime_bundle) else: - self.create_warning( + create_warning( + self.document, f"Unsupported output type: {output.output_type}", line=line, append_to=self.current_node, - wtype=DEFAULT_LOG_TYPE, - subtype="output_type", + # wtype=DEFAULT_LOG_TYPE, + subtype=MystNBWarnings.OUTPUT_TYPE, ) diff --git a/myst_nb/warnings_.py b/myst_nb/warnings_.py new file mode 100644 index 00000000..de8e66ce --- /dev/null +++ b/myst_nb/warnings_.py @@ -0,0 +1,103 @@ +"""Central handling of warnings for the myst-nb extension.""" +from __future__ import annotations + +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", + "create_warning", +] + + +class MystNBWarnings(Enum): + """MySTNB warning types.""" + + LEXER = "lexer" + """Issue resolving lexer""" + + FIG_CAPTION = "fig_caption" + """Issue resoliving figure caption""" + + MIME_TYPE = "mime_type" + """Issue resolving MIME type""" + OUTPUT_TYPE = "output_type" + """Issue resolving Output type""" + + CELL_METADATA_KEY = "cell_metadata_key" + """Issue with a key in a cell's `metadata` dictionary.""" + CELL_CONFIG = "cell_config" + """Issue with a cell's configuration or metadata.""" + + +def _is_suppressed_warning( + type: str, subtype: str, suppress_warnings: Sequence[str] +) -> bool: + """Check whether the warning is suppressed or not. + + Mirrors: + https://github.com/sphinx-doc/sphinx/blob/47d9035bca9e83d6db30a0726a02dc9265bd66b1/sphinx/util/logging.py + """ + if type is None: + return False + + subtarget: str | None + + for warning_type in suppress_warnings: + if "." in warning_type: + target, subtarget = warning_type.split(".", 1) + else: + target, subtarget = warning_type, None + + if target == type and subtarget in (None, subtype, "*"): + return True + + return False + + +def create_warning( + document: nodes.document, + message: str, + subtype: MystNBWarnings | MystWarnings, + *, + line: int | None = None, + append_to: nodes.Element | None = None, +) -> nodes.system_message | None: + """Generate a warning, logging if it is necessary. + + If the warning type is listed in the ``suppress_warnings`` configuration, + then ``None`` will be returned and no warning logged. + """ + # Pass off Myst Parser warnings to that package + if isinstance(subtype, MystWarnings): + myst_parser_create_warnings( + document=document, + message=message, + subtype=subtype, + line=line, + append_to=append_to, + ) + + wtype = "myst-nb" + # figure out whether to suppress the warning, if sphinx is available, + # it will have been set up by the Sphinx environment, + # otherwise we will use the configuration set by docutils + suppress_warnings: Sequence[str] = [] + try: + suppress_warnings = document.settings.env.app.config.suppress_warnings + except AttributeError: + suppress_warnings = document.settings.myst_suppress_warnings or [] + if _is_suppressed_warning(wtype, subtype.value, suppress_warnings): + return None + + kwargs = {"line": line} if line is not None else {} + message = f"{message} [{wtype}.{subtype.value}]" + msg_node = document.reporter.warning(message, **kwargs) + if append_to is not None: + append_to.append(msg_node) + return msg_node diff --git a/pyproject.toml b/pyproject.toml index f0cafba4..290d31c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ dependencies = [ "ipython", "jupyter-cache>=0.5,<0.7", "nbclient", # nbclient version pinned by jupyter-client - "myst-parser~=0.18.0", + "myst-parser~=1.0.0", "nbformat~=5.0", "pyyaml", "sphinx>=4,<6", @@ -71,7 +71,7 @@ rtd = [ "alabaster", "altair", "bokeh", - "coconut>=1.4.3,<3.1.0", + "coconut>=1.4.3,<2.3.0", "ipykernel~=5.5", "ipywidgets", "jupytext>=1.11.2,<1.15.0", @@ -79,7 +79,7 @@ rtd = [ "numpy", "pandas", "plotly", - "sphinx-book-theme>=0.3,<1.1", + "sphinx-book-theme~=1.0.0", "sphinx-copybutton", "sphinx-design~=0.4.0", "sphinxcontrib-bibtex", diff --git a/tests/nb_fixtures/reporter_warnings.txt b/tests/nb_fixtures/reporter_warnings.txt index 813d082c..1e226162 100644 --- a/tests/nb_fixtures/reporter_warnings.txt +++ b/tests/nb_fixtures/reporter_warnings.txt @@ -10,10 +10,9 @@ cells: source: | {unknown}`a` . -:20002: (ERROR/3) Unknown interpreted text role "unknown". +:20002: (WARNING/2) Unknown interpreted text role "unknown". [myst.role_unknown] . - Unknown directive: . cells: @@ -24,7 +23,7 @@ cells: ```{xyz} ``` . -:10003: (ERROR/3) Unknown directive type "xyz". +:10003: (WARNING/2) Unknown directive type: 'xyz' [myst.directive_unknown] . Directive parsing error: @@ -66,5 +65,5 @@ cells: [a]: c . -:20004: (WARNING/2) Duplicate reference definition: A [myst.ref] -. \ No newline at end of file +:20004: (WARNING/2) Duplicate reference definition: A [myst.duplicate_def] +. From 95b54f5fa30ac8fcb8d48d40598dcf5dac004dd6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 01:13:56 -0700 Subject: [PATCH 05/10] [pre-commit.ci] pre-commit autoupdate (#526) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a84a065e..fc8cabfb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,7 +42,7 @@ repos: additional_dependencies: [flake8-bugbear] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.4.1 hooks: - id: mypy args: [--config-file=pyproject.toml] From 22a0393eb85969cd48976a10af4af598c0b4a5d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 01:16:58 -0700 Subject: [PATCH 06/10] build(deps-dev): update coconut requirement from <2.3.0,>=1.4.3 to >=1.4.3,<3.1.0 (#527) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 290d31c6..cd624d8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ rtd = [ "alabaster", "altair", "bokeh", - "coconut>=1.4.3,<2.3.0", + "coconut>=1.4.3,<3.1.0", "ipykernel~=5.5", "ipywidgets", "jupytext>=1.11.2,<1.15.0", From 3dc6b522ba4c06e62dcbeaa58233b49bb62769dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 02:10:09 -0700 Subject: [PATCH 07/10] Update ipython requirement from !=8.1.0,<8.5 to !=8.1.0,<8.15 (#521) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Holdgraf --- docs/requirements.txt | 2 +- pyproject.toml | 2 +- tests/test_execute/test_allow_errors_auto.ipynb | 4 ++-- tests/test_execute/test_allow_errors_auto.xml | 2 +- tests/test_execute/test_allow_errors_cache.ipynb | 4 ++-- tests/test_execute/test_allow_errors_cache.xml | 2 +- tests/test_execute/test_basic_failing_auto.ipynb | 4 ++-- tests/test_execute/test_basic_failing_auto.xml | 2 +- tests/test_execute/test_basic_failing_cache.ipynb | 4 ++-- tests/test_execute/test_basic_failing_cache.xml | 2 +- tests/test_execute/test_basic_failing_inline.ipynb | 4 ++-- tests/test_execute/test_basic_failing_inline.xml | 2 +- tox.ini | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 822d882b..013a5bc0 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,2 @@ # this is only required by coconut kernel -ipython<=7.11.0 +ipython<=8.14.0 diff --git a/pyproject.toml b/pyproject.toml index cd624d8b..cf333e5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,7 +92,7 @@ testing = [ # for issue with 8.1.0 see https://github.com/ipython/ipython/issues/13554 # TODO ipython 8.5 subtly changes output of test regressions # see https://ipython.readthedocs.io/en/stable/whatsnew/version8.html#restore-line-numbers-for-input - "ipython!=8.1.0,<8.5", + "ipython!=8.1.0,<8.15", "ipywidgets>=8", "jupytext>=1.11.2,<1.15.0", "matplotlib>=3.5.3,<3.6", # TODO mpl 3.6 subtly changes output of test regressions diff --git a/tests/test_execute/test_allow_errors_auto.ipynb b/tests/test_execute/test_allow_errors_auto.ipynb index 70acbc69..3606ee95 100644 --- a/tests/test_execute/test_allow_errors_auto.ipynb +++ b/tests/test_execute/test_allow_errors_auto.ipynb @@ -21,7 +21,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "Cell \u001b[0;32mIn[1], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[0;31mException\u001b[0m: oopsie!" ] } @@ -47,7 +47,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.9.7" }, "test_name": "notebook1" }, diff --git a/tests/test_execute/test_allow_errors_auto.xml b/tests/test_execute/test_allow_errors_auto.xml index f06308ac..c8d1d104 100644 --- a/tests/test_execute/test_allow_errors_auto.xml +++ b/tests/test_execute/test_allow_errors_auto.xml @@ -12,7 +12,7 @@ --------------------------------------------------------------------------- Exception Traceback (most recent call last) - Input In [1], in () + Cell In[1], line 1 ----> 1 raise Exception('oopsie!') Exception: oopsie! diff --git a/tests/test_execute/test_allow_errors_cache.ipynb b/tests/test_execute/test_allow_errors_cache.ipynb index 70acbc69..3606ee95 100644 --- a/tests/test_execute/test_allow_errors_cache.ipynb +++ b/tests/test_execute/test_allow_errors_cache.ipynb @@ -21,7 +21,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "Cell \u001b[0;32mIn[1], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[0;31mException\u001b[0m: oopsie!" ] } @@ -47,7 +47,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.9.7" }, "test_name": "notebook1" }, diff --git a/tests/test_execute/test_allow_errors_cache.xml b/tests/test_execute/test_allow_errors_cache.xml index f06308ac..c8d1d104 100644 --- a/tests/test_execute/test_allow_errors_cache.xml +++ b/tests/test_execute/test_allow_errors_cache.xml @@ -12,7 +12,7 @@ --------------------------------------------------------------------------- Exception Traceback (most recent call last) - Input In [1], in () + Cell In[1], line 1 ----> 1 raise Exception('oopsie!') Exception: oopsie! diff --git a/tests/test_execute/test_basic_failing_auto.ipynb b/tests/test_execute/test_basic_failing_auto.ipynb index 70acbc69..3606ee95 100644 --- a/tests/test_execute/test_basic_failing_auto.ipynb +++ b/tests/test_execute/test_basic_failing_auto.ipynb @@ -21,7 +21,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "Cell \u001b[0;32mIn[1], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[0;31mException\u001b[0m: oopsie!" ] } @@ -47,7 +47,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.9.7" }, "test_name": "notebook1" }, diff --git a/tests/test_execute/test_basic_failing_auto.xml b/tests/test_execute/test_basic_failing_auto.xml index f06308ac..c8d1d104 100644 --- a/tests/test_execute/test_basic_failing_auto.xml +++ b/tests/test_execute/test_basic_failing_auto.xml @@ -12,7 +12,7 @@ --------------------------------------------------------------------------- Exception Traceback (most recent call last) - Input In [1], in () + Cell In[1], line 1 ----> 1 raise Exception('oopsie!') Exception: oopsie! diff --git a/tests/test_execute/test_basic_failing_cache.ipynb b/tests/test_execute/test_basic_failing_cache.ipynb index 70acbc69..3606ee95 100644 --- a/tests/test_execute/test_basic_failing_cache.ipynb +++ b/tests/test_execute/test_basic_failing_cache.ipynb @@ -21,7 +21,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "Cell \u001b[0;32mIn[1], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[0;31mException\u001b[0m: oopsie!" ] } @@ -47,7 +47,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.9.7" }, "test_name": "notebook1" }, diff --git a/tests/test_execute/test_basic_failing_cache.xml b/tests/test_execute/test_basic_failing_cache.xml index f06308ac..c8d1d104 100644 --- a/tests/test_execute/test_basic_failing_cache.xml +++ b/tests/test_execute/test_basic_failing_cache.xml @@ -12,7 +12,7 @@ --------------------------------------------------------------------------- Exception Traceback (most recent call last) - Input In [1], in () + Cell In[1], line 1 ----> 1 raise Exception('oopsie!') Exception: oopsie! diff --git a/tests/test_execute/test_basic_failing_inline.ipynb b/tests/test_execute/test_basic_failing_inline.ipynb index 70acbc69..3606ee95 100644 --- a/tests/test_execute/test_basic_failing_inline.ipynb +++ b/tests/test_execute/test_basic_failing_inline.ipynb @@ -21,7 +21,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "Cell \u001b[0;32mIn[1], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[0;31mException\u001b[0m: oopsie!" ] } @@ -47,7 +47,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.9.7" }, "test_name": "notebook1" }, diff --git a/tests/test_execute/test_basic_failing_inline.xml b/tests/test_execute/test_basic_failing_inline.xml index f06308ac..c8d1d104 100644 --- a/tests/test_execute/test_basic_failing_inline.xml +++ b/tests/test_execute/test_basic_failing_inline.xml @@ -12,7 +12,7 @@ --------------------------------------------------------------------------- Exception Traceback (most recent call last) - Input In [1], in () + Cell In[1], line 1 ----> 1 raise Exception('oopsie!') Exception: oopsie! diff --git a/tox.ini b/tox.ini index 5cc43a9a..3bfcea70 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ # then then deleting compiled files has been found to fix it: `find . -name \*.pyc -delete` [tox] -envlist = py38-sphinx5 +envlist = py39-sphinx5 [testenv] usedevelop = true From e35d5d90c58e956e0a49b5f5ad92de392bf48c04 Mon Sep 17 00:00:00 2001 From: Cristian Le Date: Sun, 18 Jun 2023 00:08:36 +0200 Subject: [PATCH 08/10] Allow to build sphinx 7 --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cf333e5e..fc27f2c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,10 +38,10 @@ dependencies = [ "ipython", "jupyter-cache>=0.5,<0.7", "nbclient", # nbclient version pinned by jupyter-client - "myst-parser~=1.0.0", + "myst-parser>=0.18.0", "nbformat~=5.0", "pyyaml", - "sphinx>=4,<6", + "sphinx>=4", "typing-extensions", # ipykernel is not a requirement of the library, # but is a common requirement for users (registers the python3 kernel) @@ -79,7 +79,7 @@ rtd = [ "numpy", "pandas", "plotly", - "sphinx-book-theme~=1.0.0", + "sphinx-book-theme>=0.3", "sphinx-copybutton", "sphinx-design~=0.4.0", "sphinxcontrib-bibtex", From c27422da9502714be3a844007d7a5080ee51a65d Mon Sep 17 00:00:00 2001 From: Cristian Le Date: Sun, 18 Jun 2023 00:09:44 +0200 Subject: [PATCH 09/10] Fix CI to test more sphinx versions --- .github/workflows/tests.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b5174d5e..5ff1c884 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,15 +26,15 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python-version: ["3.8", "3.9", "3.10"] - sphinx: [">=5,<6"] + python-version: ["3.8", "3.9", "3.10", "3.11"] + sphinx: ["~=5.0","~=6.0","~=7.0"] include: - os: windows-latest python-version: 3.9 - sphinx: ">=5,<6" + sphinx: "~=5.0" - os: macos-latest python-version: 3.9 - sphinx: ">=5,<6" + sphinx: "~=5.0" runs-on: ${{ matrix.os }} @@ -44,11 +44,11 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + cache: pip - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install "sphinx${{ matrix.sphinx }}" - pip install -e .[testing] + pip install --upgrade pip + pip install --upgrade "Sphinx${{ matrix.sphinx }}" -e .[testing] - name: Run pytest run: pytest --durations=10 --cov=myst_nb --cov-report=xml --cov-report=term-missing From c534408b665dfbc0078f2425b4cda00385b6de15 Mon Sep 17 00:00:00 2001 From: Cristian Le Date: Sun, 18 Jun 2023 02:23:28 +0200 Subject: [PATCH 10/10] Separate coverage action --- .github/workflows/tests.yml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5ff1c884..dafab884 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -45,11 +45,30 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: pip - - name: Install dependencies + - name: Install myst-nb with Sphinx ${{ matrix.sphinx }} run: | pip install --upgrade pip pip install --upgrade "Sphinx${{ matrix.sphinx }}" -e .[testing] + - name: Run pytest + run: pytest --durations=10 + + coverage: + needs: [tests] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: 3.11 + cache: pip + - name: Install dependencies + run: | + pip install --upgrade pip + pip install -e .[testing] + - name: Run pytest run: pytest --durations=10 --cov=myst_nb --cov-report=xml --cov-report=term-missing @@ -59,13 +78,11 @@ jobs: # this is why we run `coverage xml` afterwards (required by codecov) - name: Upload to Codecov - if: github.repository == 'executablebooks/MyST-NB' && matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest' uses: codecov/codecov-action@v3 with: name: myst-nb-pytests flags: pytests files: ./coverage.xml - fail_ci_if_error: true publish: