sphinx-examples-as-code 0.6.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sphinx_examples_as_code-0.7.0/.github/dependabot.yml +22 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/.github/workflows/ci.yml +22 -6
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/PKG-INFO +65 -31
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/README.md +60 -30
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/pyproject.toml +5 -1
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/sphinx_examples_as_code/__init__.py +185 -51
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/sphinx_examples_as_code/_version.py +3 -3
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/sphinx_examples_as_code.egg-info/PKG-INFO +65 -31
- sphinx_examples_as_code-0.7.0/sphinx_examples_as_code.egg-info/requires.txt +7 -0
- sphinx_examples_as_code-0.7.0/sphinx_examples_as_code.egg-info/scm_version.json +8 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/test_gallery_downloads.py +84 -11
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/test_heading_level_reuse.py +7 -7
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/test_single_function_page.py +5 -5
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/test_sphinx_examples_as_code.py +289 -127
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/test_tinypages.py +79 -67
- sphinx_examples_as_code-0.6.0/.github/dependabot.yml +0 -16
- sphinx_examples_as_code-0.6.0/sphinx_examples_as_code.egg-info/requires.txt +0 -1
- sphinx_examples_as_code-0.6.0/sphinx_examples_as_code.egg-info/scm_version.json +0 -8
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/.github/release.yml +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/.gitignore +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/.pre-commit-config.yaml +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/LICENSE +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/setup.cfg +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/sphinx_examples_as_code.egg-info/SOURCES.txt +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/sphinx_examples_as_code.egg-info/dependency_links.txt +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/sphinx_examples_as_code.egg-info/scm_file_list.json +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/sphinx_examples_as_code.egg-info/top_level.txt +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/gallery_fixture/conf.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/gallery_fixture/examples/GALLERY_HEADER.rst +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/gallery_fixture/examples/plot_minimal.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/gallery_fixture/index.rst +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/heading_level_fixture/conf.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/heading_level_fixture/examples/GALLERY_HEADER.rst +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/heading_level_fixture/examples/plot_reused_level.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/heading_level_fixture/examples/plot_three_levels.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/heading_level_fixture/index.rst +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/single_function_fixture/conf.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/single_function_fixture/index.rst +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/single_function_fixture/mymodule.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/tinypages/conf.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/tinypages/docstring_cases.py +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/tinypages/docstring_cases.rst +0 -0
- {sphinx_examples_as_code-0.6.0 → sphinx_examples_as_code-0.7.0}/tests/tinypages/index.rst +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
multi-ecosystem-groups:
|
|
3
|
+
maintenance:
|
|
4
|
+
schedule:
|
|
5
|
+
interval: quarterly
|
|
6
|
+
labels: [maintenance, dependencies]
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: pip
|
|
9
|
+
directory: /
|
|
10
|
+
schedule:
|
|
11
|
+
interval: weekly
|
|
12
|
+
labels: [maintenance, dependencies]
|
|
13
|
+
allow:
|
|
14
|
+
- dependency-name: pyvista
|
|
15
|
+
- dependency-name: sphinx-gallery
|
|
16
|
+
groups:
|
|
17
|
+
project:
|
|
18
|
+
patterns: ['*']
|
|
19
|
+
- package-ecosystem: github-actions
|
|
20
|
+
directory: /
|
|
21
|
+
patterns: ['*']
|
|
22
|
+
multi-ecosystem-group: maintenance
|
|
@@ -22,10 +22,10 @@ jobs:
|
|
|
22
22
|
with:
|
|
23
23
|
persist-credentials: false
|
|
24
24
|
fetch-depth: 0
|
|
25
|
-
- uses: astral-sh/setup-uv@
|
|
25
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
26
26
|
with:
|
|
27
27
|
enable-cache: false
|
|
28
|
-
- run: uv sync --group dev
|
|
28
|
+
- run: uv sync --group dev --extra gallery
|
|
29
29
|
- run: uv run pre-commit run --all-files --show-diff-on-failure
|
|
30
30
|
env:
|
|
31
31
|
# This hook exists to stop *local* commits straight to main; it
|
|
@@ -43,15 +43,15 @@ jobs:
|
|
|
43
43
|
with:
|
|
44
44
|
persist-credentials: false
|
|
45
45
|
fetch-depth: 0
|
|
46
|
-
- uses: astral-sh/setup-uv@
|
|
46
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
47
47
|
with:
|
|
48
48
|
enable-cache: false
|
|
49
49
|
- uses: pyvista/setup-headless-display-action@c103a2ff45650d38cb71684b5dc6cdfeb9442c79 # v5.1.0
|
|
50
50
|
with:
|
|
51
51
|
pyvista: true
|
|
52
|
-
- run: uv sync --group dev --python ${{ matrix.python-version }}
|
|
52
|
+
- run: uv sync --group dev --extra gallery --python ${{ matrix.python-version }}
|
|
53
53
|
- run: uv run pytest tests/ --cov --cov-report=xml
|
|
54
|
-
- uses: codecov/codecov-action@
|
|
54
|
+
- uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
|
55
55
|
with:
|
|
56
56
|
files: ./coverage.xml
|
|
57
57
|
env:
|
|
@@ -65,7 +65,7 @@ jobs:
|
|
|
65
65
|
with:
|
|
66
66
|
persist-credentials: false
|
|
67
67
|
fetch-depth: 0
|
|
68
|
-
- uses: astral-sh/setup-uv@
|
|
68
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
69
69
|
with:
|
|
70
70
|
enable-cache: false
|
|
71
71
|
- run: uv build
|
|
@@ -87,3 +87,19 @@ jobs:
|
|
|
87
87
|
name: dist
|
|
88
88
|
path: dist/
|
|
89
89
|
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
90
|
+
|
|
91
|
+
release:
|
|
92
|
+
needs: publish
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
permissions:
|
|
95
|
+
contents: write
|
|
96
|
+
steps:
|
|
97
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
98
|
+
with:
|
|
99
|
+
name: dist
|
|
100
|
+
path: dist/
|
|
101
|
+
# Notes come from the merged pull requests, shaped by .github/release.yml.
|
|
102
|
+
- env:
|
|
103
|
+
GH_TOKEN: ${{ github.token }}
|
|
104
|
+
TAG: ${{ github.ref_name }}
|
|
105
|
+
run: gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --title "$TAG" --generate-notes --verify-tag dist/*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sphinx-examples-as-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Sphinx extension for converting docstring examples into downloadable code.
|
|
5
5
|
Author-email: The PyVista Developers <info@pyvista.org>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -23,12 +23,17 @@ Requires-Python: >=3.10
|
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: pyvista>=0.48
|
|
26
|
+
Provides-Extra: gallery
|
|
27
|
+
Requires-Dist: sphinx-gallery<0.23,>=0.22; extra == "gallery"
|
|
28
|
+
Provides-Extra: marimo
|
|
29
|
+
Requires-Dist: marimo>=0.14; extra == "marimo"
|
|
26
30
|
Dynamic: license-file
|
|
27
31
|
|
|
28
32
|
# sphinx-examples-as-code
|
|
29
33
|
|
|
30
34
|
A Sphinx extension that turns docstring/page "Examples" sections into downloadable,
|
|
31
|
-
runnable
|
|
35
|
+
runnable Python scripts, Jupyter notebooks and/or [marimo](https://marimo.io) notebooks,
|
|
36
|
+
with a download link inserted into the section.
|
|
32
37
|
|
|
33
38
|
Pages or docstrings without an Examples section are left completely untouched. Adding
|
|
34
39
|
`sphinx_examples_as_code` to `conf.py`'s `extensions` is the only on/off switch.
|
|
@@ -39,6 +44,19 @@ Pages or docstrings without an Examples section are left completely untouched. A
|
|
|
39
44
|
pip install sphinx-examples-as-code
|
|
40
45
|
```
|
|
41
46
|
|
|
47
|
+
Sphinx-Gallery integration is opt-in and needs a compatible sphinx-gallery, which the
|
|
48
|
+
`gallery` extra pins:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install 'sphinx-examples-as-code[gallery]'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
marimo notebook downloads need marimo 0.14 or newer, which the `marimo` extra installs:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install 'sphinx-examples-as-code[marimo]'
|
|
58
|
+
```
|
|
59
|
+
|
|
42
60
|
Add it to your Sphinx `conf.py`:
|
|
43
61
|
|
|
44
62
|
```python
|
|
@@ -56,23 +74,29 @@ the keys you want to change from their default:
|
|
|
56
74
|
```python
|
|
57
75
|
sphinx_examples_as_code_conf = {
|
|
58
76
|
'link_position': 'top',
|
|
59
|
-
'formats': ['
|
|
77
|
+
'formats': ['python', 'jupyter', 'marimo'],
|
|
60
78
|
'gallery_downloads': False,
|
|
61
79
|
'footer': (
|
|
62
80
|
'Generated by `sphinx-examples-as-code '
|
|
63
81
|
'<https://github.com/pyvista/sphinx-examples-as-code>`_'
|
|
64
82
|
),
|
|
65
83
|
'link_labels': {
|
|
66
|
-
'
|
|
67
|
-
'
|
|
84
|
+
'python': 'Download Python script',
|
|
85
|
+
'jupyter': 'Download Jupyter notebook',
|
|
86
|
+
'marimo': 'Download marimo notebook',
|
|
68
87
|
},
|
|
69
88
|
}
|
|
70
89
|
```
|
|
71
90
|
|
|
72
91
|
- `link_position`: where the download link(s) land within the Examples section. `'top'`
|
|
73
92
|
(default) or `'bottom'`.
|
|
74
|
-
- `formats`: which downloads to generate. A list containing `'
|
|
75
|
-
|
|
93
|
+
- `formats`: which downloads to generate. A list containing any of `'python'` (a plain
|
|
94
|
+
Python script, `<name>.py`), `'jupyter'` (a Jupyter notebook, `<name>.ipynb`) and
|
|
95
|
+
`'marimo'` (a marimo notebook, `<name>.marimo.py`); defaults to all three. Always
|
|
96
|
+
offered in that order regardless of how the list is written. Without marimo 0.14 or
|
|
97
|
+
newer installed, the default skips the marimo download, and a `formats` that names
|
|
98
|
+
`'marimo'` (in `conf.py` or through `-D`) stops the build with a configuration error. An unknown format raises a configuration error too;
|
|
99
|
+
the old `'py'` and `'ipynb'` names say what replaced them.
|
|
76
100
|
- `link_labels`: the text of the download link(s) themselves, per format. Set only the
|
|
77
101
|
format(s) you want to change; any left unset keep reading their own default shown above.
|
|
78
102
|
- `gallery_downloads`: opt-in takeover of
|
|
@@ -82,11 +106,11 @@ sphinx_examples_as_code_conf = {
|
|
|
82
106
|
- `footer`: a string appended to the end of every generated file. Defaults to a one-line
|
|
83
107
|
"generated file" credit linking back to this project; set to `None` to omit it
|
|
84
108
|
entirely. Preceded by a blank line and a `-`-only divider line, which also renders as a
|
|
85
|
-
real horizontal rule in
|
|
109
|
+
real horizontal rule in notebooks; the footer always gets its own dedicated cell there.
|
|
86
110
|
Parsed as RST: a hyperlink written as `` `text <url>`_ `` becomes a real clickable
|
|
87
|
-
Markdown link in
|
|
88
|
-
markup at all becomes one comment line per line of text, and
|
|
89
|
-
paragraphs stay separated.
|
|
111
|
+
Markdown link in notebooks, and renders inline as `text url` in Python scripts. Plain
|
|
112
|
+
text with no markup at all becomes one comment line per line of text, and
|
|
113
|
+
blank-line-separated paragraphs stay separated.
|
|
90
114
|
|
|
91
115
|
An unrecognized key raises a configuration error at build start.
|
|
92
116
|
|
|
@@ -107,39 +131,43 @@ What happens to the content of an Examples section:
|
|
|
107
131
|
- `.. code-block:: python` (or `py`) blocks are kept as-is; other languages become
|
|
108
132
|
comments, set off with blank lines on both sides like any other directive.
|
|
109
133
|
- Admonitions (`.. note::`, `.. warning::`, ...) become a `# LABEL:` comment followed by
|
|
110
|
-
their content as comments, indented one level under the label in
|
|
134
|
+
their content as comments, indented one level under the label in Python scripts only.
|
|
111
135
|
- A bullet/numbered list becomes a `-`/`N.`-marked line per item, set off with a blank
|
|
112
136
|
line on both sides in either format — a bare `#` instead of a real blank line when
|
|
113
|
-
that falls inside an admonition or a definition's own body in
|
|
114
|
-
thing still reads as one unbroken comment block. A definition list's term stays
|
|
115
|
-
the surrounding indent; its definition (the body nested under it) is indented one
|
|
116
|
-
level further in
|
|
137
|
+
that falls inside an admonition or a definition's own body in a Python script, so the
|
|
138
|
+
whole thing still reads as one unbroken comment block. A definition list's term stays
|
|
139
|
+
at the surrounding indent; its definition (the body nested under it) is indented one
|
|
140
|
+
level further in Python scripts, same as an admonition's own content.
|
|
117
141
|
- Cross-references and inline code (`:class:`, `:meth:`, `:func:`, `:attr:`,
|
|
118
142
|
double-backtick literals, ...) keep their display text, wrapped in backticks (e.g.
|
|
119
143
|
``:class:`pyvista.Plotter` `` -> `` `pyvista.Plotter` ``). If `html_baseurl` is set and
|
|
120
|
-
the reference resolves,
|
|
121
|
-
link, only the display text.
|
|
144
|
+
the reference resolves, notebooks turn it into a clickable link; Python scripts never
|
|
145
|
+
write the link, only the display text.
|
|
122
146
|
- Plain prose-style references (`:ref:`, `:doc:`) are treated the same way, minus the
|
|
123
147
|
backticks.
|
|
124
148
|
- Everything else text-bearing (prose, captions, other non-Python code) becomes a plain
|
|
125
149
|
`#` comment.
|
|
126
150
|
- A table becomes an aligned text table, its caption on the line above: an RST simple
|
|
127
|
-
table in
|
|
128
|
-
line, and a column left entirely empty -- one holding only images, say -- is
|
|
129
|
-
along with its heading.
|
|
151
|
+
table in Python scripts, a Markdown pipe table in notebooks. Each cell is flattened to a
|
|
152
|
+
single line, and a column left entirely empty -- one holding only images, say -- is
|
|
153
|
+
dropped along with its heading.
|
|
130
154
|
- Figures/images, raw HTML, sphinx-design dropdowns/tab-sets, and sphinx-tags' `.. tags::`
|
|
131
155
|
line are dropped entirely.
|
|
132
156
|
- "See Also" content is always dropped.
|
|
133
157
|
|
|
134
|
-
Generated
|
|
158
|
+
Generated Python scripts start with a `# Examples from <qualified name>` title header
|
|
135
159
|
(gallery mode uses the page's own title instead -- see below), with a few whitespace
|
|
136
160
|
conventions: prose directly above a code block stays attached to it, a code block is
|
|
137
161
|
always followed by a blank line, and a directive (header, `# NOTE:`-style block) gets
|
|
138
162
|
blank lines on both sides.
|
|
139
163
|
|
|
140
|
-
Generated
|
|
164
|
+
Generated Jupyter notebooks use the same content, split into alternating code/markdown
|
|
141
165
|
cells instead.
|
|
142
166
|
|
|
167
|
+
Generated marimo notebooks are that same Jupyter notebook converted by marimo's own
|
|
168
|
+
converter, the one behind `marimo convert`. `from __future__` imports are dropped first,
|
|
169
|
+
so the notebook also runs as a plain script (`python <name>.marimo.py`).
|
|
170
|
+
|
|
143
171
|
A download link is only added if the resulting code contains at least one real
|
|
144
172
|
executable statement.
|
|
145
173
|
|
|
@@ -148,7 +176,7 @@ executable statement.
|
|
|
148
176
|
With `sphinx_examples_as_code_conf['gallery_downloads'] = True`, this extension takes
|
|
149
177
|
over the downloads on every page generated by
|
|
150
178
|
[sphinx-gallery](https://sphinx-gallery.github.io): the "Go to the end to download the
|
|
151
|
-
full example code" note and the `.py`/`.
|
|
179
|
+
full example code" note and the `.py`/`.zip` download footer are removed from
|
|
152
180
|
the page, replaced with download link(s) built by this extension instead — same
|
|
153
181
|
conversion rules as above, applied to the whole page rather than one Examples section.
|
|
154
182
|
The generated file's header uses the page's own title (e.g. `# Create Circular Arcs`)
|
|
@@ -163,7 +191,7 @@ is left completely untouched. Gallery pages and ordinary docstring/prose pages (
|
|
|
163
191
|
the Examples-section behavior above) can coexist on the same site.
|
|
164
192
|
|
|
165
193
|
A `# %%` cell with its own RST heading gets the same header treatment as the file's own
|
|
166
|
-
title, and renders as a real Markdown heading in
|
|
194
|
+
title, and renders as a real Markdown heading in notebooks. Level is relative to actual
|
|
167
195
|
RST section nesting, not always one below the file's own header: a cell heading nested
|
|
168
196
|
under the page's own title (the common case) is one level below it; one that reuses the
|
|
169
197
|
page title's own underline character is level 1, the same as the file's own header; a
|
|
@@ -172,24 +200,30 @@ cell heading nested under *that* is level 2 relative to it, and so on.
|
|
|
172
200
|
Each format uses one heading style consistently across every level, rather than mixing
|
|
173
201
|
styles:
|
|
174
202
|
|
|
175
|
-
-
|
|
203
|
+
- Python scripts use an RST-style title + underline, one character per level -- the same
|
|
176
204
|
sequence Sphinx's own documentation uses for sections through sub-paragraphs: `=`, `-`,
|
|
177
205
|
`~`, `^`, `"`, `'` for levels 1 through 6.
|
|
178
|
-
-
|
|
206
|
+
- Notebooks always use ATX syntax (`#`, `##`, `###`, ...) at every level.
|
|
179
207
|
|
|
180
208
|
Two things worth knowing before turning this on:
|
|
181
209
|
|
|
182
210
|
- It's built against sphinx-gallery's own doctree output — the `sphx-glr-*` CSS classes
|
|
183
211
|
its own theming depends on, and the private node type holding a highlighted code
|
|
184
212
|
block — not a documented extension API. A future sphinx-gallery release could shift
|
|
185
|
-
that structure without warning.
|
|
186
|
-
|
|
187
|
-
|
|
213
|
+
that structure without warning. Only sphinx-gallery 0.22.x is tested, so the `gallery`
|
|
214
|
+
extra caps there rather than letting the next release quietly produce no downloads.
|
|
215
|
+
- sphinx-gallery's own `.py`/`.zip` downloads still end up copied into `_downloads/`,
|
|
216
|
+
even though nothing on the page links to them anymore. Its `.ipynb` is never written:
|
|
217
|
+
with `gallery_downloads` on, this extension sets `sphinx_gallery_conf['pypandoc']` to
|
|
218
|
+
`False` and `sphinx_gallery_conf['notebook_extensions']` to an empty set before
|
|
219
|
+
sphinx-gallery reads them, so pandoc is not needed. Setting `pypandoc`,
|
|
220
|
+
`notebook_extensions`, `first_notebook_cell`, `last_notebook_cell` or `notebook_images`
|
|
221
|
+
yourself has no effect and is reported as a warning.
|
|
188
222
|
|
|
189
223
|
## Development
|
|
190
224
|
|
|
191
225
|
```bash
|
|
192
|
-
uv sync --group dev
|
|
226
|
+
uv sync --group dev --extra gallery
|
|
193
227
|
uv run pytest
|
|
194
228
|
uv run pre-commit run --all-files
|
|
195
229
|
```
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# sphinx-examples-as-code
|
|
2
2
|
|
|
3
3
|
A Sphinx extension that turns docstring/page "Examples" sections into downloadable,
|
|
4
|
-
runnable
|
|
4
|
+
runnable Python scripts, Jupyter notebooks and/or [marimo](https://marimo.io) notebooks,
|
|
5
|
+
with a download link inserted into the section.
|
|
5
6
|
|
|
6
7
|
Pages or docstrings without an Examples section are left completely untouched. Adding
|
|
7
8
|
`sphinx_examples_as_code` to `conf.py`'s `extensions` is the only on/off switch.
|
|
@@ -12,6 +13,19 @@ Pages or docstrings without an Examples section are left completely untouched. A
|
|
|
12
13
|
pip install sphinx-examples-as-code
|
|
13
14
|
```
|
|
14
15
|
|
|
16
|
+
Sphinx-Gallery integration is opt-in and needs a compatible sphinx-gallery, which the
|
|
17
|
+
`gallery` extra pins:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install 'sphinx-examples-as-code[gallery]'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
marimo notebook downloads need marimo 0.14 or newer, which the `marimo` extra installs:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install 'sphinx-examples-as-code[marimo]'
|
|
27
|
+
```
|
|
28
|
+
|
|
15
29
|
Add it to your Sphinx `conf.py`:
|
|
16
30
|
|
|
17
31
|
```python
|
|
@@ -29,23 +43,29 @@ the keys you want to change from their default:
|
|
|
29
43
|
```python
|
|
30
44
|
sphinx_examples_as_code_conf = {
|
|
31
45
|
'link_position': 'top',
|
|
32
|
-
'formats': ['
|
|
46
|
+
'formats': ['python', 'jupyter', 'marimo'],
|
|
33
47
|
'gallery_downloads': False,
|
|
34
48
|
'footer': (
|
|
35
49
|
'Generated by `sphinx-examples-as-code '
|
|
36
50
|
'<https://github.com/pyvista/sphinx-examples-as-code>`_'
|
|
37
51
|
),
|
|
38
52
|
'link_labels': {
|
|
39
|
-
'
|
|
40
|
-
'
|
|
53
|
+
'python': 'Download Python script',
|
|
54
|
+
'jupyter': 'Download Jupyter notebook',
|
|
55
|
+
'marimo': 'Download marimo notebook',
|
|
41
56
|
},
|
|
42
57
|
}
|
|
43
58
|
```
|
|
44
59
|
|
|
45
60
|
- `link_position`: where the download link(s) land within the Examples section. `'top'`
|
|
46
61
|
(default) or `'bottom'`.
|
|
47
|
-
- `formats`: which downloads to generate. A list containing `'
|
|
48
|
-
|
|
62
|
+
- `formats`: which downloads to generate. A list containing any of `'python'` (a plain
|
|
63
|
+
Python script, `<name>.py`), `'jupyter'` (a Jupyter notebook, `<name>.ipynb`) and
|
|
64
|
+
`'marimo'` (a marimo notebook, `<name>.marimo.py`); defaults to all three. Always
|
|
65
|
+
offered in that order regardless of how the list is written. Without marimo 0.14 or
|
|
66
|
+
newer installed, the default skips the marimo download, and a `formats` that names
|
|
67
|
+
`'marimo'` (in `conf.py` or through `-D`) stops the build with a configuration error. An unknown format raises a configuration error too;
|
|
68
|
+
the old `'py'` and `'ipynb'` names say what replaced them.
|
|
49
69
|
- `link_labels`: the text of the download link(s) themselves, per format. Set only the
|
|
50
70
|
format(s) you want to change; any left unset keep reading their own default shown above.
|
|
51
71
|
- `gallery_downloads`: opt-in takeover of
|
|
@@ -55,11 +75,11 @@ sphinx_examples_as_code_conf = {
|
|
|
55
75
|
- `footer`: a string appended to the end of every generated file. Defaults to a one-line
|
|
56
76
|
"generated file" credit linking back to this project; set to `None` to omit it
|
|
57
77
|
entirely. Preceded by a blank line and a `-`-only divider line, which also renders as a
|
|
58
|
-
real horizontal rule in
|
|
78
|
+
real horizontal rule in notebooks; the footer always gets its own dedicated cell there.
|
|
59
79
|
Parsed as RST: a hyperlink written as `` `text <url>`_ `` becomes a real clickable
|
|
60
|
-
Markdown link in
|
|
61
|
-
markup at all becomes one comment line per line of text, and
|
|
62
|
-
paragraphs stay separated.
|
|
80
|
+
Markdown link in notebooks, and renders inline as `text url` in Python scripts. Plain
|
|
81
|
+
text with no markup at all becomes one comment line per line of text, and
|
|
82
|
+
blank-line-separated paragraphs stay separated.
|
|
63
83
|
|
|
64
84
|
An unrecognized key raises a configuration error at build start.
|
|
65
85
|
|
|
@@ -80,39 +100,43 @@ What happens to the content of an Examples section:
|
|
|
80
100
|
- `.. code-block:: python` (or `py`) blocks are kept as-is; other languages become
|
|
81
101
|
comments, set off with blank lines on both sides like any other directive.
|
|
82
102
|
- Admonitions (`.. note::`, `.. warning::`, ...) become a `# LABEL:` comment followed by
|
|
83
|
-
their content as comments, indented one level under the label in
|
|
103
|
+
their content as comments, indented one level under the label in Python scripts only.
|
|
84
104
|
- A bullet/numbered list becomes a `-`/`N.`-marked line per item, set off with a blank
|
|
85
105
|
line on both sides in either format — a bare `#` instead of a real blank line when
|
|
86
|
-
that falls inside an admonition or a definition's own body in
|
|
87
|
-
thing still reads as one unbroken comment block. A definition list's term stays
|
|
88
|
-
the surrounding indent; its definition (the body nested under it) is indented one
|
|
89
|
-
level further in
|
|
106
|
+
that falls inside an admonition or a definition's own body in a Python script, so the
|
|
107
|
+
whole thing still reads as one unbroken comment block. A definition list's term stays
|
|
108
|
+
at the surrounding indent; its definition (the body nested under it) is indented one
|
|
109
|
+
level further in Python scripts, same as an admonition's own content.
|
|
90
110
|
- Cross-references and inline code (`:class:`, `:meth:`, `:func:`, `:attr:`,
|
|
91
111
|
double-backtick literals, ...) keep their display text, wrapped in backticks (e.g.
|
|
92
112
|
``:class:`pyvista.Plotter` `` -> `` `pyvista.Plotter` ``). If `html_baseurl` is set and
|
|
93
|
-
the reference resolves,
|
|
94
|
-
link, only the display text.
|
|
113
|
+
the reference resolves, notebooks turn it into a clickable link; Python scripts never
|
|
114
|
+
write the link, only the display text.
|
|
95
115
|
- Plain prose-style references (`:ref:`, `:doc:`) are treated the same way, minus the
|
|
96
116
|
backticks.
|
|
97
117
|
- Everything else text-bearing (prose, captions, other non-Python code) becomes a plain
|
|
98
118
|
`#` comment.
|
|
99
119
|
- A table becomes an aligned text table, its caption on the line above: an RST simple
|
|
100
|
-
table in
|
|
101
|
-
line, and a column left entirely empty -- one holding only images, say -- is
|
|
102
|
-
along with its heading.
|
|
120
|
+
table in Python scripts, a Markdown pipe table in notebooks. Each cell is flattened to a
|
|
121
|
+
single line, and a column left entirely empty -- one holding only images, say -- is
|
|
122
|
+
dropped along with its heading.
|
|
103
123
|
- Figures/images, raw HTML, sphinx-design dropdowns/tab-sets, and sphinx-tags' `.. tags::`
|
|
104
124
|
line are dropped entirely.
|
|
105
125
|
- "See Also" content is always dropped.
|
|
106
126
|
|
|
107
|
-
Generated
|
|
127
|
+
Generated Python scripts start with a `# Examples from <qualified name>` title header
|
|
108
128
|
(gallery mode uses the page's own title instead -- see below), with a few whitespace
|
|
109
129
|
conventions: prose directly above a code block stays attached to it, a code block is
|
|
110
130
|
always followed by a blank line, and a directive (header, `# NOTE:`-style block) gets
|
|
111
131
|
blank lines on both sides.
|
|
112
132
|
|
|
113
|
-
Generated
|
|
133
|
+
Generated Jupyter notebooks use the same content, split into alternating code/markdown
|
|
114
134
|
cells instead.
|
|
115
135
|
|
|
136
|
+
Generated marimo notebooks are that same Jupyter notebook converted by marimo's own
|
|
137
|
+
converter, the one behind `marimo convert`. `from __future__` imports are dropped first,
|
|
138
|
+
so the notebook also runs as a plain script (`python <name>.marimo.py`).
|
|
139
|
+
|
|
116
140
|
A download link is only added if the resulting code contains at least one real
|
|
117
141
|
executable statement.
|
|
118
142
|
|
|
@@ -121,7 +145,7 @@ executable statement.
|
|
|
121
145
|
With `sphinx_examples_as_code_conf['gallery_downloads'] = True`, this extension takes
|
|
122
146
|
over the downloads on every page generated by
|
|
123
147
|
[sphinx-gallery](https://sphinx-gallery.github.io): the "Go to the end to download the
|
|
124
|
-
full example code" note and the `.py`/`.
|
|
148
|
+
full example code" note and the `.py`/`.zip` download footer are removed from
|
|
125
149
|
the page, replaced with download link(s) built by this extension instead — same
|
|
126
150
|
conversion rules as above, applied to the whole page rather than one Examples section.
|
|
127
151
|
The generated file's header uses the page's own title (e.g. `# Create Circular Arcs`)
|
|
@@ -136,7 +160,7 @@ is left completely untouched. Gallery pages and ordinary docstring/prose pages (
|
|
|
136
160
|
the Examples-section behavior above) can coexist on the same site.
|
|
137
161
|
|
|
138
162
|
A `# %%` cell with its own RST heading gets the same header treatment as the file's own
|
|
139
|
-
title, and renders as a real Markdown heading in
|
|
163
|
+
title, and renders as a real Markdown heading in notebooks. Level is relative to actual
|
|
140
164
|
RST section nesting, not always one below the file's own header: a cell heading nested
|
|
141
165
|
under the page's own title (the common case) is one level below it; one that reuses the
|
|
142
166
|
page title's own underline character is level 1, the same as the file's own header; a
|
|
@@ -145,24 +169,30 @@ cell heading nested under *that* is level 2 relative to it, and so on.
|
|
|
145
169
|
Each format uses one heading style consistently across every level, rather than mixing
|
|
146
170
|
styles:
|
|
147
171
|
|
|
148
|
-
-
|
|
172
|
+
- Python scripts use an RST-style title + underline, one character per level -- the same
|
|
149
173
|
sequence Sphinx's own documentation uses for sections through sub-paragraphs: `=`, `-`,
|
|
150
174
|
`~`, `^`, `"`, `'` for levels 1 through 6.
|
|
151
|
-
-
|
|
175
|
+
- Notebooks always use ATX syntax (`#`, `##`, `###`, ...) at every level.
|
|
152
176
|
|
|
153
177
|
Two things worth knowing before turning this on:
|
|
154
178
|
|
|
155
179
|
- It's built against sphinx-gallery's own doctree output — the `sphx-glr-*` CSS classes
|
|
156
180
|
its own theming depends on, and the private node type holding a highlighted code
|
|
157
181
|
block — not a documented extension API. A future sphinx-gallery release could shift
|
|
158
|
-
that structure without warning.
|
|
159
|
-
|
|
160
|
-
|
|
182
|
+
that structure without warning. Only sphinx-gallery 0.22.x is tested, so the `gallery`
|
|
183
|
+
extra caps there rather than letting the next release quietly produce no downloads.
|
|
184
|
+
- sphinx-gallery's own `.py`/`.zip` downloads still end up copied into `_downloads/`,
|
|
185
|
+
even though nothing on the page links to them anymore. Its `.ipynb` is never written:
|
|
186
|
+
with `gallery_downloads` on, this extension sets `sphinx_gallery_conf['pypandoc']` to
|
|
187
|
+
`False` and `sphinx_gallery_conf['notebook_extensions']` to an empty set before
|
|
188
|
+
sphinx-gallery reads them, so pandoc is not needed. Setting `pypandoc`,
|
|
189
|
+
`notebook_extensions`, `first_notebook_cell`, `last_notebook_cell` or `notebook_images`
|
|
190
|
+
yourself has no effect and is reported as a warning.
|
|
161
191
|
|
|
162
192
|
## Development
|
|
163
193
|
|
|
164
194
|
```bash
|
|
165
|
-
uv sync --group dev
|
|
195
|
+
uv sync --group dev --extra gallery
|
|
166
196
|
uv run pytest
|
|
167
197
|
uv run pre-commit run --all-files
|
|
168
198
|
```
|
|
@@ -4,6 +4,7 @@ requires = ['setuptools>=64', 'setuptools_scm>=8']
|
|
|
4
4
|
|
|
5
5
|
[dependency-groups]
|
|
6
6
|
dev = [
|
|
7
|
+
'marimo>=0.14',
|
|
7
8
|
'nbformat',
|
|
8
9
|
'numpydoc',
|
|
9
10
|
'pre-commit',
|
|
@@ -11,7 +12,6 @@ dev = [
|
|
|
11
12
|
'pytest-cov',
|
|
12
13
|
'sphinx',
|
|
13
14
|
'sphinx-design',
|
|
14
|
-
'sphinx-gallery>=0.22',
|
|
15
15
|
'trame-pyvista',
|
|
16
16
|
]
|
|
17
17
|
|
|
@@ -41,6 +41,10 @@ name = 'sphinx-examples-as-code'
|
|
|
41
41
|
readme = 'README.md'
|
|
42
42
|
requires-python = '>=3.10'
|
|
43
43
|
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
gallery = ['sphinx-gallery>=0.22,<0.23']
|
|
46
|
+
marimo = ['marimo>=0.14']
|
|
47
|
+
|
|
44
48
|
[project.urls]
|
|
45
49
|
Homepage = 'https://github.com/pyvista/sphinx-examples-as-code'
|
|
46
50
|
|