diff --git a/myst_nb/core/config.py b/myst_nb/core/config.py index d90e85ab..d3b11080 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