diff --git a/.vscode/settings.json b/.vscode/settings.json index dc840b3d0..f46e33649 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -49,6 +49,7 @@ } ], "livePreview.defaultPreviewPath": "docs/_build/html", + "multiDiffEditor.experimental.enabled": true, "mypy-type-checker.args": ["--config-file=${workspaceFolder}/pyproject.toml"], "mypy-type-checker.importStrategy": "fromEnvironment", "notebook.gotoSymbols.showAllSymbols": true, diff --git a/docs/_extend_docstrings.py b/docs/_extend_docstrings.py index bb5370aa4..f3cb5ecb5 100644 --- a/docs/_extend_docstrings.py +++ b/docs/_extend_docstrings.py @@ -6,9 +6,13 @@ # pyright: reportMissingImports=false from __future__ import annotations +import hashlib import inspect import logging +import pickle +import sys import textwrap +from pathlib import Path from typing import TYPE_CHECKING, Callable import attrs @@ -23,7 +27,13 @@ from ampform.kinematics import FourMomentumSymbol, _ArraySize from ampform.sympy._array_expressions import ArrayMultiplication +if sys.version_info < (3, 8): + from importlib_metadata import version as get_package_version +else: + from importlib.metadata import version as get_package_version if TYPE_CHECKING: + from qrules.transition import ReactionInfo + from ampform.sympy import NumPyPrintable logging.getLogger().setLevel(logging.ERROR) @@ -518,7 +528,7 @@ def extend_formulate_wigner_d() -> None: def __get_graphviz_state_transition_example( formalism: str, transition_number: int = 0 ) -> str: - reaction = qrules.generate_transitions( + reaction = __generate_transitions_cached( initial_state=[("J/psi(1S)", [+1])], final_state=[("gamma", [-1]), "f(0)(980)"], formalism=formalism, @@ -699,6 +709,30 @@ def _append_to_docstring(class_type: Callable | type, appended_text: str) -> Non class_type.__doc__ += appended_text +def __generate_transitions_cached( + initial_state: list[tuple[str, list[float | int]] | str], + final_state: list[tuple[str, list[float | int]] | str], + formalism: str, +) -> ReactionInfo: + version = get_package_version("qrules") + obj = (initial_state, final_state, formalism) + h = hashlib.sha256(pickle.dumps(obj)).hexdigest() + docs_dir = Path(__file__).parent + file_name = docs_dir / ".cache" / f"reaction-qrules-v{version}-{h}.pickle" + file_name.parent.mkdir(exist_ok=True) + if file_name.exists(): + with open(file_name, "rb") as f: + return pickle.load(f) # noqa: S301 + reaction = qrules.generate_transitions( + initial_state, + final_state, + formalism=formalism, + ) + with open(file_name, "wb") as f: + pickle.dump(reaction, f) + return reaction + + def __print_imports(printer: NumPyPrinter) -> str: code = "" for module, items in printer.module_imports.items(): diff --git a/tox.ini b/tox.ini index a092cc77c..c7b0d91ad 100644 --- a/tox.ini +++ b/tox.ini @@ -97,6 +97,40 @@ setenv = FORCE_COLOR = yes PYTHONHASHSEED = 0 +[testenv:docnblive] +allowlist_externals = + sphinx-autobuild +commands = + sphinx-autobuild \ + --open-browser \ + --re-ignore .*/.ipynb_checkpoints/.* \ + --re-ignore .*/__pycache__/.* \ + --re-ignore .*\.gitignore \ + --re-ignore .*\.tmp \ + --re-ignore docs/.*\.csv \ + --re-ignore docs/.*\.gif \ + --re-ignore docs/.*\.gv \ + --re-ignore docs/.*\.inv \ + --re-ignore docs/.*\.json \ + --re-ignore docs/.*\.pickle \ + --re-ignore docs/.*\.png \ + --re-ignore docs/.*\.svg \ + --re-ignore docs/.*\.yaml \ + --re-ignore docs/.*\.yml \ + --re-ignore docs/_build/.* \ + --re-ignore docs/_images/.* \ + --re-ignore docs/api/.* \ + --watch docs \ + --watch src \ + docs/ docs/_build/html +description = + Set up a server to directly preview changes to the HTML pages +passenv = * +setenv = + EXECUTE_NB = yes + FORCE_COLOR = yes + PYTHONHASHSEED = 0 + [testenv:docnb-force] allowlist_externals = sphinx-build