|
11 | 11 | # serve to show the default.
|
12 | 12 |
|
13 | 13 | import datetime
|
14 |
| -import importlib.metadata |
| 14 | +import os |
| 15 | +import re |
| 16 | +from pathlib import Path |
15 | 17 |
|
16 |
| -import jinja2.filters |
17 | 18 | import numpy as np
|
18 | 19 |
|
19 | 20 | import pywt
|
|
25 | 26 | except TypeError:
|
26 | 27 | pass
|
27 | 28 |
|
| 29 | +from sphinx.application import Sphinx |
| 30 | + |
| 31 | +HERE = Path(__file__).parent |
| 32 | + |
| 33 | + |
| 34 | +def preprocess_notebooks(app: Sphinx, *args, **kwargs): |
| 35 | + """Preprocess Markdown notebooks to convert them to IPyNB format.""" |
| 36 | + |
| 37 | + import jupytext |
| 38 | + import nbformat |
| 39 | + |
| 40 | + print("Converting Markdown files to IPyNB...") |
| 41 | + for path in (HERE / "regression").glob("*.md"): |
| 42 | + if any(path.match(pattern) for pattern in exclude_patterns): |
| 43 | + continue |
| 44 | + nb = jupytext.read(str(path)) |
| 45 | + |
| 46 | + # In .md to .ipynb conversion, do not include any cells that have the |
| 47 | + # jupyterlite_sphinx_strip tag |
| 48 | + nb.cells = [ |
| 49 | + cell for cell in nb.cells if "jupyterlite_sphinx_strip" not in cell.metadata.get("tags", []) |
| 50 | + ] |
| 51 | + |
| 52 | + ipynb_path = path.with_suffix(".ipynb") |
| 53 | + with open(ipynb_path, "w") as f: |
| 54 | + nbformat.write(nb, f) |
| 55 | + print(f"Converted {path} to {ipynb_path}") |
| 56 | + |
| 57 | + |
| 58 | +# Should match {{ parent_docname }} or {{parent_docname}} |
| 59 | +parent_docname_substitution_re = re.compile(r"{{\s*parent_docname\s*}}") |
| 60 | + |
| 61 | +def sub_parent_docname_in_header( |
| 62 | + app: Sphinx, relative_path: Path, parent_docname: str, content: list[str] |
| 63 | +): |
| 64 | + """Fill in the name of the document in the header. |
| 65 | +
|
| 66 | + When regression/header.md is read via the include directive, replace |
| 67 | + {{ parent_docname }} with the name of the parent document that included |
| 68 | + header.md. |
| 69 | +
|
| 70 | + Note: parent_docname does not include the file extension. |
| 71 | +
|
| 72 | + Here is a simplified example of how this works. |
| 73 | +
|
| 74 | + Contents of header.md: |
| 75 | +
|
| 76 | + {download}`Download {{ parent_docname }}.md <{{ parent_docname }}.md>` |
| 77 | +
|
| 78 | + Contents of foobar.md: |
| 79 | +
|
| 80 | + ```{include} header.md |
| 81 | + ``` |
| 82 | +
|
| 83 | + After this function and others are run... |
| 84 | +
|
| 85 | + Contents of foobar.md: |
| 86 | +
|
| 87 | + {download}`Download foobar.md <foobar.md>` |
| 88 | + """ |
| 89 | + if not relative_path.match("regression/header.md"): |
| 90 | + return |
| 91 | + |
| 92 | + for i, value in enumerate(content): |
| 93 | + content[i] = re.sub(parent_docname_substitution_re, parent_docname, value) |
| 94 | + |
| 95 | + |
| 96 | +def setup(app): |
| 97 | + app.connect("config-inited", preprocess_notebooks) |
| 98 | + app.connect("include-read", sub_parent_docname_in_header) |
28 | 99 |
|
29 | 100 | # If extensions (or modules to document with autodoc) are in another directory,
|
30 | 101 | # add these directories to sys.path here. If the directory is relative to the
|
|
38 | 109 | extensions = [
|
39 | 110 | 'jupyterlite_sphinx',
|
40 | 111 | 'matplotlib.sphinxext.plot_directive',
|
| 112 | + 'myst_nb', |
41 | 113 | 'numpydoc',
|
42 | 114 | 'sphinx.ext.autodoc',
|
43 | 115 | 'sphinx.ext.autosummary',
|
|
47 | 119 | 'sphinx.ext.mathjax',
|
48 | 120 | 'sphinx.ext.todo',
|
49 | 121 | 'sphinx_copybutton',
|
| 122 | + 'sphinx_design', |
50 | 123 | 'sphinx_togglebutton',
|
51 |
| - |
52 | 124 | ]
|
53 | 125 |
|
54 | 126 | # Add any paths that contain templates here, relative to this directory.
|
55 | 127 | templates_path = ['_templates']
|
56 | 128 |
|
57 | 129 | # The suffix of source filenames.
|
58 |
| -source_suffix = '.rst' |
| 130 | +source_suffix = { |
| 131 | + '.rst': 'restructuredtext', |
| 132 | + '.md': 'myst-nb', |
| 133 | + 'ipynb': None, # do not parse IPyNB files |
| 134 | +} |
59 | 135 |
|
60 | 136 | # The encoding of source files.
|
61 | 137 | source_encoding = 'utf-8'
|
|
141 | 217 | "show_prev_next": True,
|
142 | 218 | "footer_start": ["copyright", "sphinx-version"],
|
143 | 219 | "footer_end": ["theme-version"],
|
144 |
| -"pygment_light_style": "a11y-high-contrast-light", |
145 |
| -"pygment_dark_style": "a11y-high-contrast-dark", |
| 220 | +"pygments_light_style": "a11y-high-contrast-light", |
| 221 | +"pygments_dark_style": "a11y-high-contrast-dark", |
146 | 222 | "icon_links": [
|
147 | 223 | {
|
148 | 224 | "name": "Discussion group on Google Groups",
|
|
200 | 276 | # _static directory.
|
201 | 277 | html_css_files = [
|
202 | 278 | "pywavelets.css",
|
| 279 | + "myst-nb.css" |
203 | 280 | ]
|
204 | 281 |
|
205 | 282 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
|
278 | 355 |
|
279 | 356 | # List of patterns, relative to source directory, that match files and
|
280 | 357 | # directories to ignore when looking for source files.
|
281 |
| -exclude_patterns = ['substitutions.rst', ] |
| 358 | +exclude_patterns = [ |
| 359 | + 'substitutions.rst', |
| 360 | + 'regression/header.md', |
| 361 | + 'regression/README.md', |
| 362 | + 'regression/*.ipynb' # exclude IPyNB files from the build |
| 363 | +] |
282 | 364 |
|
283 | 365 | # numpydoc_show_class_members = False
|
284 | 366 | numpydoc_class_members_toctree = False
|
|
310 | 392 | Shall you encounter any issues, please feel free to report them on the
|
311 | 393 | [PyWavelets issue tracker](https://github.com/PyWavelets/pywt/issues)."""
|
312 | 394 | )
|
| 395 | + |
| 396 | +jupyterlite_silence = True |
| 397 | +strip_tagged_cells = True |
| 398 | + |
| 399 | +# -- Options for MyST-NB and Markdown-based content -------------------------- |
| 400 | + |
| 401 | +os.environ["PYDEVD_DISABLE_FILE_VALIDATION"] = "1" |
| 402 | + |
| 403 | +# https://myst-nb.readthedocs.io/en/latest/configuration.html |
| 404 | +nb_execution_mode = 'auto' |
| 405 | +nb_execution_timeout = 60 |
| 406 | +nb_execution_allow_errors = False |
| 407 | +nb_execution_raise_on_error = True |
| 408 | +nb_render_markdown_format = "myst" |
| 409 | +nb_remove_code_source = False |
| 410 | +nb_remove_code_outputs = False |
| 411 | + |
| 412 | +myst_enable_extensions = [ |
| 413 | + 'amsmath', |
| 414 | + 'colon_fence', |
| 415 | + 'dollarmath', |
| 416 | +] |
0 commit comments