markdown-exec 1.9.3__tar.gz → 1.10.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.
Files changed (105) hide show
  1. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/CHANGELOG.md +12 -0
  2. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/CONTRIBUTING.md +7 -10
  3. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/PKG-INFO +4 -7
  4. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/README.md +0 -3
  5. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/ruff.toml +1 -1
  6. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/.overrides/main.html +5 -3
  7. markdown_exec-1.10.0/docs/.overrides/partials/comments.html +57 -0
  8. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/gallery.md +14 -2
  9. markdown_exec-1.10.0/docs/index.md +6 -0
  10. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/insiders/index.md +4 -0
  11. markdown_exec-1.10.0/docs/js/feedback.js +14 -0
  12. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/license.md +5 -0
  13. markdown_exec-1.10.0/docs/snippets/gallery/expandable_filetree.py +41 -0
  14. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/matplotlib.py +4 -4
  15. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/usage/pyodide.md +12 -0
  16. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/usage/shell.md +1 -1
  17. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/duties.py +39 -14
  18. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/mkdocs.yml +19 -4
  19. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/pyproject.toml +49 -4
  20. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/scripts/gen_credits.py +6 -6
  21. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/scripts/insiders.py +4 -1
  22. markdown_exec-1.10.0/scripts/make +1 -0
  23. markdown_exec-1.10.0/scripts/make.py +193 -0
  24. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/_exec_python.py +2 -2
  25. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/base.py +3 -1
  26. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/bash.py +2 -2
  27. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/pyodide.py +3 -2
  28. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/python.py +1 -1
  29. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/sh.py +2 -2
  30. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/mkdocs_plugin.py +3 -1
  31. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/rendering.py +4 -3
  32. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/conftest.py +1 -1
  33. markdown_exec-1.9.3/devdeps.txt +0 -49
  34. markdown_exec-1.9.3/docs/index.md +0 -1
  35. markdown_exec-1.9.3/scripts/make +0 -203
  36. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/CODE_OF_CONDUCT.md +0 -0
  37. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/LICENSE +0 -0
  38. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/coverage.ini +0 -0
  39. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/git-changelog.toml +0 -0
  40. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/mypy.ini +0 -0
  41. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/pytest.ini +0 -0
  42. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/vscode/launch.json +0 -0
  43. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/vscode/settings.json +0 -0
  44. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/config/vscode/tasks.json +0 -0
  45. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/changelog.md +0 -0
  46. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/code_of_conduct.md +0 -0
  47. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/contributing.md +0 -0
  48. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/credits.md +0 -0
  49. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/css/insiders.css +0 -0
  50. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/css/material.css +0 -0
  51. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/css/mkdocstrings.css +0 -0
  52. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/insiders/changelog.md +0 -0
  53. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/insiders/goals.yml +0 -0
  54. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/insiders/installation.md +0 -0
  55. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/js/insiders.js +0 -0
  56. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/schema.json +0 -0
  57. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/ansi.sh +0 -0
  58. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/argparse.py +0 -0
  59. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/argparse_format.py +0 -0
  60. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/chalk.py +0 -0
  61. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/d2.py +0 -0
  62. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/diagrams.py +0 -0
  63. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/drawsvg.py +0 -0
  64. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/hyperbolic.py +0 -0
  65. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/plotly.py +0 -0
  66. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/pydeps.py +0 -0
  67. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/pytermgui.py +0 -0
  68. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/qrcode.py +0 -0
  69. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/rich.py +0 -0
  70. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/rich_terminal.py +0 -0
  71. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/runpy.py +0 -0
  72. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/gallery/textual.py +0 -0
  73. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/usage/boolean_matrix.py +0 -0
  74. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/usage/hide.py +0 -0
  75. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/usage/multiple.pycon +0 -0
  76. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/usage/platform_html.py +0 -0
  77. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/usage/platform_md.py +0 -0
  78. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/usage/source.py +0 -0
  79. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/snippets/usage/source.pycon +0 -0
  80. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/usage/index.md +0 -0
  81. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/usage/python.md +0 -0
  82. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/docs/usage/tree.md +0 -0
  83. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/scripts/gen_ref_nav.py +0 -0
  84. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/__init__.py +0 -0
  85. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/ansi.css +0 -0
  86. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/debug.py +0 -0
  87. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/__init__.py +0 -0
  88. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/console.py +0 -0
  89. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/markdown.py +0 -0
  90. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/pycon.py +0 -0
  91. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/formatters/tree.py +0 -0
  92. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/logger.py +0 -0
  93. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/processors.py +0 -0
  94. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/py.typed +0 -0
  95. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/pyodide.css +0 -0
  96. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/src/markdown_exec/pyodide.js +0 -0
  97. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/__init__.py +0 -0
  98. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_base_formatter.py +0 -0
  99. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_converter.py +0 -0
  100. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_headings.py +0 -0
  101. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_python.py +0 -0
  102. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_shell.py +0 -0
  103. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_toc.py +0 -0
  104. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_tree.py +0 -0
  105. {markdown_exec-1.9.3 → markdown_exec-1.10.0}/tests/test_validator.py +0 -0
@@ -5,6 +5,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  <!-- insertion marker -->
8
+ ## [1.10.0](https://github.com/pawamoy/markdown-exec/releases/tag/1.10.0) - 2024-12-06
9
+
10
+ <small>[Compare with 1.9.3](https://github.com/pawamoy/markdown-exec/compare/1.9.3...1.10.0)</small>
11
+
12
+ ### Build
13
+
14
+ - Drop support for Python 3.8 ([103bc1d](https://github.com/pawamoy/markdown-exec/commit/103bc1dc5f07f330b9e7ca4f052714350c52389d) by Timothée Mazzucotelli).
15
+
16
+ ### Features
17
+
18
+ - Allow setting Pyodide version ([912c8c7](https://github.com/pawamoy/markdown-exec/commit/912c8c75a5f579a949644f33bcead0b71e9637fd) by Andrew). [Issue-66](https://github.com/pawamoy/markdown-exec/issues/66), [PR-67](https://github.com/pawamoy/markdown-exec/pull/67), Co-authored-by: Timothée Mazzucotelli <dev@pawamoy.fr>
19
+
8
20
  ## [1.9.3](https://github.com/pawamoy/markdown-exec/releases/tag/1.9.3) - 2024-06-24
9
21
 
10
22
  <small>[Compare with 1.9.2](https://github.com/pawamoy/markdown-exec/compare/1.9.2...1.9.3)</small>
@@ -23,12 +23,11 @@ make setup
23
23
  > You can install it with:
24
24
  >
25
25
  > ```bash
26
- > python3 -m pip install --user pipx
27
- > pipx install uv
26
+ > curl -LsSf https://astral.sh/uv/install.sh | sh
28
27
  > ```
29
28
  >
30
29
  > Now you can try running `make setup` again,
31
- > or simply `uv install`.
30
+ > or simply `uv sync`.
32
31
 
33
32
  You now have the dependencies installed.
34
33
 
@@ -36,13 +35,11 @@ Run `make help` to see all the available actions!
36
35
 
37
36
  ## Tasks
38
37
 
39
- This project uses [duty](https://github.com/pawamoy/duty) to run tasks.
40
- A Makefile is also provided. The Makefile will try to run certain tasks
41
- on multiple Python versions. If for some reason you don't want to run the task
42
- on multiple Python versions, you run the task directly with `make run duty TASK`.
43
-
44
- The Makefile detects if a virtual environment is activated,
45
- so `make` will work the same with the virtualenv activated or not.
38
+ The entry-point to run commands and tasks is the `make` Python script,
39
+ located in the `scripts` directory. Try running `make` to show the available commands and tasks.
40
+ The *commands* do not need the Python dependencies to be installed,
41
+ while the *tasks* do.
42
+ The cross-platform tasks are written in Python, thanks to [duty](https://github.com/pawamoy/duty).
46
43
 
47
44
  If you work in VSCode, we provide
48
45
  [an action to configure VSCode](https://pawamoy.github.io/copier-uv/work/#vscode-setup)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: markdown-exec
3
- Version: 1.9.3
3
+ Version: 1.10.0
4
4
  Summary: Utilities to execute code blocks in Markdown files.
5
5
  Keywords: markdown,python,exec,shell,bash,mkdocs
6
6
  Author-Email: =?utf-8?q?Timoth=C3=A9e_Mazzucotelli?= <dev@pawamoy.fr>
@@ -10,12 +10,12 @@ Classifier: Intended Audience :: Developers
10
10
  Classifier: Programming Language :: Python
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3 :: Only
13
- Classifier: Programming Language :: Python :: 3.8
14
13
  Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
19
  Classifier: Topic :: Documentation
20
20
  Classifier: Topic :: Software Development
21
21
  Classifier: Topic :: Utilities
@@ -28,10 +28,10 @@ Project-URL: Issues, https://github.com/pawamoy/markdown-exec/issues
28
28
  Project-URL: Discussions, https://github.com/pawamoy/markdown-exec/discussions
29
29
  Project-URL: Gitter, https://gitter.im/markdown-exec/community
30
30
  Project-URL: Funding, https://github.com/sponsors/pawamoy
31
- Requires-Python: >=3.8
31
+ Requires-Python: >=3.9
32
32
  Requires-Dist: pymdown-extensions>=9
33
- Requires-Dist: pygments-ansi-color; extra == "ansi"
34
33
  Provides-Extra: ansi
34
+ Requires-Dist: pygments-ansi-color; extra == "ansi"
35
35
  Description-Content-Type: text/markdown
36
36
 
37
37
  # Markdown Exec
@@ -39,7 +39,6 @@ Description-Content-Type: text/markdown
39
39
  [![ci](https://github.com/pawamoy/markdown-exec/workflows/ci/badge.svg)](https://github.com/pawamoy/markdown-exec/actions?query=workflow%3Aci)
40
40
  [![documentation](https://img.shields.io/badge/docs-mkdocs-708FCC.svg?style=flat)](https://pawamoy.github.io/markdown-exec/)
41
41
  [![pypi version](https://img.shields.io/pypi/v/markdown-exec.svg)](https://pypi.org/project/markdown-exec/)
42
- [![gitpod](https://img.shields.io/badge/gitpod-workspace-708FCC.svg?style=flat)](https://gitpod.io/#https://github.com/pawamoy/markdown-exec)
43
42
  [![gitter](https://badges.gitter.im/join%20chat.svg)](https://app.gitter.im/#/room/#markdown-exec:gitter.im)
44
43
 
45
44
  Utilities to execute code blocks in Markdown files.
@@ -49,8 +48,6 @@ and this HTML is injected in place of the code block.
49
48
 
50
49
  ## Installation
51
50
 
52
- With `pip`:
53
-
54
51
  ```bash
55
52
  pip install markdown-exec[ansi]
56
53
  ```
@@ -3,7 +3,6 @@
3
3
  [![ci](https://github.com/pawamoy/markdown-exec/workflows/ci/badge.svg)](https://github.com/pawamoy/markdown-exec/actions?query=workflow%3Aci)
4
4
  [![documentation](https://img.shields.io/badge/docs-mkdocs-708FCC.svg?style=flat)](https://pawamoy.github.io/markdown-exec/)
5
5
  [![pypi version](https://img.shields.io/pypi/v/markdown-exec.svg)](https://pypi.org/project/markdown-exec/)
6
- [![gitpod](https://img.shields.io/badge/gitpod-workspace-708FCC.svg?style=flat)](https://gitpod.io/#https://github.com/pawamoy/markdown-exec)
7
6
  [![gitter](https://badges.gitter.im/join%20chat.svg)](https://app.gitter.im/#/room/#markdown-exec:gitter.im)
8
7
 
9
8
  Utilities to execute code blocks in Markdown files.
@@ -13,8 +12,6 @@ and this HTML is injected in place of the code block.
13
12
 
14
13
  ## Installation
15
14
 
16
- With `pip`:
17
-
18
15
  ```bash
19
16
  pip install markdown-exec[ansi]
20
17
  ```
@@ -1,4 +1,4 @@
1
- target-version = "py38"
1
+ target-version = "py39"
2
2
  line-length = 120
3
3
 
4
4
  [lint]
@@ -2,17 +2,19 @@
2
2
 
3
3
  {% block announce %}
4
4
 
5
- <a href="{{ 'insiders/#how-to-become-a-sponsor' | url }}"><strong>Sponsorship</strong></a>
6
- is now available!
5
+ <strong>Fund this project</strong> through
6
+ <a href="{{ 'insiders/#how-to-become-a-sponsor' | url }}"><strong>sponsorship</strong></a>
7
7
  <span class="twemoji heart pulse">
8
8
  {% include ".icons/octicons/heart-fill-16.svg" %}
9
9
  </span> &mdash;
10
10
 
11
- For updates follow <strong>@pawamoy</strong> on
11
+ Follow
12
+ <strong>@pawamoy</strong> on
12
13
  <a rel="me" href="https://fosstodon.org/@pawamoy">
13
14
  <span class="twemoji mastodon">
14
15
  {% include ".icons/fontawesome/brands/mastodon.svg" %}
15
16
  </span>
16
17
  <strong>Fosstodon</strong>
17
18
  </a>
19
+ for updates
18
20
  {% endblock %}
@@ -0,0 +1,57 @@
1
+ <!-- Giscus -->
2
+ <!-- https://squidfunk.github.io/mkdocs-material/setup/adding-a-comment-system/#giscus-integration -->
3
+ <div id="feedback" style="display: none;">
4
+ <h2 id="__comments">Feedback</h2>
5
+ <script src="https://giscus.app/client.js"
6
+ data-repo="pawamoy/markdown-exec"
7
+ data-repo-id="R_kgDOG1IOMQ"
8
+ data-category="Documentation"
9
+ data-category-id="DIC_kwDOG1IOMc4Ck2cD"
10
+ data-mapping="pathname"
11
+ data-strict="1"
12
+ data-reactions-enabled="0"
13
+ data-emit-metadata="0"
14
+ data-input-position="top"
15
+ data-theme="preferred_color_scheme"
16
+ data-lang="en"
17
+ data-loading="lazy"
18
+ crossorigin="anonymous"
19
+ async>
20
+ </script>
21
+
22
+ <!-- Synchronize Giscus theme with palette -->
23
+ <script>
24
+ var giscus = document.querySelector("script[src*=giscus]")
25
+
26
+ // Set palette on initial load
27
+ var palette = __md_get("__palette")
28
+ if (palette && typeof palette.color === "object") {
29
+ var theme = palette.color.scheme === "slate"
30
+ ? "transparent_dark"
31
+ : "light"
32
+
33
+ // Instruct Giscus to set theme
34
+ giscus.setAttribute("data-theme", theme)
35
+ }
36
+
37
+ // Register event handlers after documented loaded
38
+ document.addEventListener("DOMContentLoaded", function() {
39
+ var ref = document.querySelector("[data-md-component=palette]")
40
+ ref.addEventListener("change", function() {
41
+ var palette = __md_get("__palette")
42
+ if (palette && typeof palette.color === "object") {
43
+ var theme = palette.color.scheme === "slate"
44
+ ? "transparent_dark"
45
+ : "light"
46
+
47
+ // Instruct Giscus to change theme
48
+ var frame = document.querySelector(".giscus-frame")
49
+ frame.contentWindow.postMessage(
50
+ { giscus: { setConfig: { theme } } },
51
+ "https://giscus.app"
52
+ )
53
+ }
54
+ })
55
+ })
56
+ </script>
57
+ </div>
@@ -184,6 +184,20 @@ If you installed Markdown Exec with the `ansi` extra (`pip install markdown-exec
184
184
  ```
185
185
  ````
186
186
 
187
+ ## File-trees
188
+
189
+ This example displays a file-tree of the current project, in which you can descend thanks to Material for MkDocs' [code annotations](https://squidfunk.github.io/mkdocs-material/reference/code-blocks/#code-annotations). It uses a recursive Python function which accept a code block session name as parameter 🤯:
190
+
191
+ ````md exec="1" source="tabbed-right"
192
+ ```python exec="1" session="filetree"
193
+ --8<-- "gallery/expandable_filetree.py"
194
+ ```
195
+
196
+ ```python exec="1" session="filetree"
197
+ exptree(".", "filetree")
198
+ ```
199
+ ````
200
+
187
201
  ## Python CLI documentation
188
202
 
189
203
  ### with [`argparse`](https://docs.python.org/3/library/argparse.html#module-argparse) (code block)
@@ -206,8 +220,6 @@ In this example, we inspect the `argparse` parser to build better-looking Markdo
206
220
  ```
207
221
  ````
208
222
 
209
- ## Other techniques
210
-
211
223
  ### with [`runpy`](https://docs.python.org/3/library/runpy.html#module-runpy)
212
224
 
213
225
  This example uses Python's `runpy` module to run another Python module. This other module's output is captured by temporarily patching `sys.stdout` with a text buffer.
@@ -0,0 +1,6 @@
1
+ ---
2
+ hide:
3
+ - feedback
4
+ ---
5
+
6
+ --8<-- "README.md"
@@ -95,6 +95,10 @@ with your GitHub account, visit [pawamoy's sponsor profile][github sponsor profi
95
95
  and complete a sponsorship of **$10 a month or more**.
96
96
  You can use your individual or organization GitHub account for sponsoring.
97
97
 
98
+ Sponsorships lower than $10 a month are also very much appreciated, and useful.
99
+ They won't grant you access to Insiders, but they will be counted towards reaching sponsorship goals.
100
+ *Every* sponsorship helps us implementing new features and releasing them to the public.
101
+
98
102
  **Important**: If you're sponsoring **[@pawamoy][github sponsor profile]**
99
103
  through a GitHub organization, please send a short email
100
104
  to insiders@pawamoy.fr with the name of your
@@ -0,0 +1,14 @@
1
+ const feedback = document.forms.feedback;
2
+ feedback.hidden = false;
3
+
4
+ feedback.addEventListener("submit", function(ev) {
5
+ ev.preventDefault();
6
+ const commentElement = document.getElementById("feedback");
7
+ commentElement.style.display = "block";
8
+ feedback.firstElementChild.disabled = true;
9
+ const data = ev.submitter.getAttribute("data-md-value");
10
+ const note = feedback.querySelector(".md-feedback__note [data-md-value='" + data + "']");
11
+ if (note) {
12
+ note.hidden = false;
13
+ }
14
+ })
@@ -1,3 +1,8 @@
1
+ ---
2
+ hide:
3
+ - feedback
4
+ ---
5
+
1
6
  # License
2
7
 
3
8
  ```
@@ -0,0 +1,41 @@
1
+ from fnmatch import fnmatch
2
+ from pathlib import Path
3
+
4
+ exclude = {"dist", "*cache*", ".devbox", ".hypothesis", ".pdm*", ".coverage*", "profile.*"}
5
+ no_recurse = {".venv*", "site", "htmlcov", ".git"}
6
+
7
+
8
+ def exptree(path: str, session: str) -> None:
9
+ # List files and directories separately.
10
+ files = []
11
+ dirs = []
12
+ for node in Path(path).iterdir():
13
+ if any(fnmatch(node.name, pattern) for pattern in exclude):
14
+ continue
15
+ if node.is_dir():
16
+ dirs.append(node)
17
+ else:
18
+ files.append(node)
19
+
20
+ # Print directories first, then files (both sorted).
21
+ recurse = []
22
+ print("```tree")
23
+ for directory in sorted(dirs):
24
+ if any(fnmatch(directory.name, pattern) for pattern in no_recurse):
25
+ print(f"{directory.name}/")
26
+ else:
27
+ recurse.append(directory.name)
28
+ # Add code annotation at the end.
29
+ print(f"{directory.name}/ # ({len(recurse)})!")
30
+ for file in sorted(files):
31
+ print(file.name)
32
+ print("```\n")
33
+
34
+ # Print contents of each annotated directory.
35
+ for index, directory in enumerate(recurse, 1):
36
+ new_path = f"{path}/{directory}"
37
+ print(f"{index}. \n")
38
+ # The recursive part!
39
+ print(f' ```python exec="1" session="{session}"')
40
+ print(f' exptree("{new_path}", "{session}")')
41
+ print(" ```\n")
@@ -8,14 +8,14 @@ import numpy as np
8
8
  # Load a numpy record array from yahoo csv data with fields date, open, close,
9
9
  # volume, adj_close from the mpl-data/example directory. The record array
10
10
  # stores the date as an np.datetime64 with a day unit ('D') in the date column.
11
- price_data = cbook.get_sample_data("goog.npz", np_load=True)["price_data"].view(np.recarray)
11
+ price_data = cbook.get_sample_data("goog.npz")["price_data"]
12
12
  price_data = price_data[-250:] # get the most recent 250 trading days
13
13
 
14
- delta1 = np.diff(price_data.adj_close) / price_data.adj_close[:-1]
14
+ delta1 = np.diff(price_data["adj_close"]) / price_data["adj_close"][:-1]
15
15
 
16
16
  # Marker size in units of points^2
17
- volume = (15 * price_data.volume[:-2] / price_data.volume[0]) ** 2
18
- close = 0.003 * price_data.close[:-2] / 0.003 * price_data.open[:-2]
17
+ volume = (15 * price_data["volume"][:-2] / price_data["volume"][0])**2
18
+ close = 0.003 * price_data["close"][:-2] / 0.003 * price_data["open"][:-2]
19
19
 
20
20
  fig, ax = plt.subplots()
21
21
  ax.scatter(delta1[:-1], delta1[1:], c=close, s=volume, alpha=0.5)
@@ -33,6 +33,18 @@ cowsay.cow("Hello World")
33
33
  Packages installed with Micropip are cached by the browser as well,
34
34
  making future installations much faster.
35
35
 
36
+ ## Pyodide version
37
+
38
+ You can select a specific Pyodide version with the `version` option:
39
+
40
+ ````md
41
+ ```pyodide version="0.26.4"
42
+ print("Hello.")
43
+ ```
44
+ ````md
45
+
46
+ NOTE: **All Pyodide blocks on the same page should use the same version!**
47
+
36
48
  ## Sessions
37
49
 
38
50
  Editors with the same session share the same `globals()` dictionary,
@@ -2,7 +2,7 @@
2
2
 
3
3
  Shell code blocks are executed using the same interpreter specified
4
4
  as language of the code block, in sub-processes. The output is captured
5
- and rendered as Markdown or HTML (see [Usage](../index.md#html-vs-markdown)).
5
+ and rendered as Markdown or HTML (see [Usage](index.md#html-vs-markdown)).
6
6
 
7
7
  ## Bash
8
8
 
@@ -7,11 +7,13 @@ import sys
7
7
  from contextlib import contextmanager
8
8
  from importlib.metadata import version as pkgversion
9
9
  from pathlib import Path
10
- from typing import TYPE_CHECKING, Iterator
10
+ from typing import TYPE_CHECKING
11
11
 
12
12
  from duty import duty, tools
13
13
 
14
14
  if TYPE_CHECKING:
15
+ from collections.abc import Iterator
16
+
15
17
  from duty.context import Context
16
18
 
17
19
 
@@ -43,8 +45,8 @@ def material_insiders() -> Iterator[bool]: # noqa: D103
43
45
  yield False
44
46
 
45
47
 
46
- below_312 = sys.version_info < (3, 12)
47
- skip_docs_reason = pyprefix("Building docs is not supported on Python 3.12, skipping")
48
+ below_314 = sys.version_info < (3, 14)
49
+ skip_docs_reason = pyprefix("Building docs is not supported on Python 3.14, skipping")
48
50
 
49
51
 
50
52
  @duty
@@ -57,8 +59,8 @@ def changelog(ctx: Context, bump: str = "") -> None:
57
59
  ctx.run(tools.git_changelog(bump=bump or None), title="Updating changelog")
58
60
 
59
61
 
60
- @duty(pre=["check_quality", "check_types", "check_docs", "check_dependencies", "check-api"])
61
- def check(ctx: Context) -> None: # noqa: ARG001
62
+ @duty(pre=["check-quality", "check-types", "check-docs", "check-api"])
63
+ def check(ctx: Context) -> None:
62
64
  """Check it all!"""
63
65
 
64
66
 
@@ -71,7 +73,7 @@ def check_quality(ctx: Context) -> None:
71
73
  )
72
74
 
73
75
 
74
- @duty(skip_if=not below_312, skip_reason=skip_docs_reason)
76
+ @duty(skip_if=not below_314, skip_reason=skip_docs_reason)
75
77
  def check_docs(ctx: Context) -> None:
76
78
  """Check if the documentation builds correctly."""
77
79
  Path("htmlcov").mkdir(parents=True, exist_ok=True)
@@ -102,7 +104,7 @@ def check_api(ctx: Context, *cli_args: str) -> None:
102
104
  )
103
105
 
104
106
 
105
- @duty(skip_if=not below_312, skip_reason=skip_docs_reason)
107
+ @duty(skip_if=not below_314, skip_reason=skip_docs_reason)
106
108
  def docs(ctx: Context, *cli_args: str, host: str = "127.0.0.1", port: int = 8000) -> None:
107
109
  """Serve the documentation (localhost:8000).
108
110
 
@@ -118,17 +120,40 @@ def docs(ctx: Context, *cli_args: str, host: str = "127.0.0.1", port: int = 8000
118
120
  )
119
121
 
120
122
 
121
- @duty(skip_if=not below_312, skip_reason=skip_docs_reason)
122
- def docs_deploy(ctx: Context) -> None:
123
- """Deploy the documentation to GitHub pages."""
123
+ @duty(skip_if=not below_314, skip_reason=skip_docs_reason)
124
+ def docs_deploy(ctx: Context, *, force: bool = False) -> None:
125
+ """Deploy the documentation to GitHub pages.
126
+
127
+ Parameters:
128
+ force: Whether to force deployment, even from non-Insiders version.
129
+ """
124
130
  os.environ["DEPLOY"] = "true"
125
131
  with material_insiders() as insiders:
126
132
  if not insiders:
127
133
  ctx.run(lambda: False, title="Not deploying docs without Material for MkDocs Insiders!")
128
- ctx.run(
129
- tools.mkdocs.gh_deploy(force=True),
130
- title="Deploying documentation",
131
- )
134
+ origin = ctx.run("git config --get remote.origin.url", silent=True, allow_overrides=False)
135
+ if "pawamoy-insiders/markdown-exec" in origin:
136
+ ctx.run(
137
+ "git remote add upstream git@github.com:pawamoy/markdown-exec",
138
+ silent=True,
139
+ nofail=True,
140
+ allow_overrides=False,
141
+ )
142
+ ctx.run(
143
+ tools.mkdocs.gh_deploy(remote_name="upstream", force=True),
144
+ title="Deploying documentation",
145
+ )
146
+ elif force:
147
+ ctx.run(
148
+ tools.mkdocs.gh_deploy(force=True),
149
+ title="Deploying documentation",
150
+ )
151
+ else:
152
+ ctx.run(
153
+ lambda: False,
154
+ title="Not deploying docs from public repository (do that from insiders instead!)",
155
+ nofail=True,
156
+ )
132
157
 
133
158
 
134
159
  @duty
@@ -86,6 +86,9 @@ extra_css:
86
86
  - css/mkdocstrings.css
87
87
  - css/insiders.css
88
88
 
89
+ extra_javascript:
90
+ - js/feedback.js
91
+
89
92
  markdown_extensions:
90
93
  - admonition
91
94
  - attr_list
@@ -100,9 +103,8 @@ markdown_extensions:
100
103
  emoji_generator: !!python/name:material.extensions.emoji.to_svg
101
104
  - pymdownx.magiclink
102
105
  - pymdownx.snippets:
103
- base_path: [!relative $config_dir]
106
+ base_path: [!relative $config_dir, !relative $docs_dir/snippets]
104
107
  check_paths: true
105
- base_path: [docs/snippets, "."]
106
108
  - pymdownx.highlight
107
109
  - pymdownx.keys
108
110
  - pymdownx.superfences:
@@ -155,9 +157,10 @@ plugins:
155
157
  show_symbol_type_toc: true
156
158
  signature_crossrefs: true
157
159
  summary: true
158
- - git-committers:
160
+ - git-revision-date-localized:
159
161
  enabled: !ENV [DEPLOY, false]
160
- repository: pawamoy/markdown-exec
162
+ enable_creation_date: true
163
+ type: timeago
161
164
  - minify:
162
165
  minify_html: !ENV [DEPLOY, false]
163
166
  - group:
@@ -177,3 +180,15 @@ extra:
177
180
  link: https://gitter.im/markdown-exec/community
178
181
  - icon: fontawesome/brands/python
179
182
  link: https://pypi.org/project/markdown-exec/
183
+ analytics:
184
+ feedback:
185
+ title: Was this page helpful?
186
+ ratings:
187
+ - icon: material/emoticon-happy-outline
188
+ name: This page was helpful
189
+ data: 1
190
+ note: Thanks for your feedback!
191
+ - icon: material/emoticon-sad-outline
192
+ name: This page could be improved
193
+ data: 0
194
+ note: Let us know how we can improve this page.
@@ -11,7 +11,7 @@ authors = [
11
11
  { name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr" },
12
12
  ]
13
13
  readme = "README.md"
14
- requires-python = ">=3.8"
14
+ requires-python = ">=3.9"
15
15
  keywords = [
16
16
  "markdown",
17
17
  "python",
@@ -27,12 +27,12 @@ classifiers = [
27
27
  "Programming Language :: Python",
28
28
  "Programming Language :: Python :: 3",
29
29
  "Programming Language :: Python :: 3 :: Only",
30
- "Programming Language :: Python :: 3.8",
31
30
  "Programming Language :: Python :: 3.9",
32
31
  "Programming Language :: Python :: 3.10",
33
32
  "Programming Language :: Python :: 3.11",
34
33
  "Programming Language :: Python :: 3.12",
35
34
  "Programming Language :: Python :: 3.13",
35
+ "Programming Language :: Python :: 3.14",
36
36
  "Topic :: Documentation",
37
37
  "Topic :: Software Development",
38
38
  "Topic :: Utilities",
@@ -41,7 +41,7 @@ classifiers = [
41
41
  dependencies = [
42
42
  "pymdown-extensions>=9",
43
43
  ]
44
- version = "1.9.3"
44
+ version = "1.10.0"
45
45
 
46
46
  [project.license]
47
47
  text = "ISC"
@@ -79,7 +79,6 @@ source-includes = [
79
79
  "scripts",
80
80
  "share",
81
81
  "tests",
82
- "devdeps.txt",
83
82
  "duties.py",
84
83
  "mkdocs.yml",
85
84
  "*.md",
@@ -90,3 +89,49 @@ source-includes = [
90
89
  data = [
91
90
  { path = "share/**/*", relative-to = "." },
92
91
  ]
92
+
93
+ [dependency-groups]
94
+ dev = [
95
+ "editables>=0.5",
96
+ "build>=1.2",
97
+ "git-changelog>=2.5",
98
+ "twine>=5.1",
99
+ "duty>=1.4",
100
+ "ruff>=0.4",
101
+ "pytest>=8.2",
102
+ "pytest-cov>=5.0",
103
+ "pytest-randomly>=3.15",
104
+ "pytest-xdist>=3.6",
105
+ "mypy>=1.10",
106
+ "types-markdown>=3.6",
107
+ "types-pyyaml>=6.0",
108
+ "black>=24.4",
109
+ "markdown-callouts>=0.4",
110
+ "markdown-exec>=1.8",
111
+ "mkdocs>=1.6",
112
+ "mkdocs-coverage>=1.0",
113
+ "mkdocs-gen-files>=0.5",
114
+ "mkdocs-git-revision-date-localized-plugin>=1.2",
115
+ "mkdocs-literate-nav>=0.6",
116
+ "mkdocs-material>=9.5",
117
+ "mkdocs-minify-plugin>=0.8",
118
+ "mkdocstrings[python]>=0.25",
119
+ "tomli>=2.0; python_version < '3.11'",
120
+ "pydeps>=1.12; python_version < '3.14'",
121
+ "diagrams>=0.21; python_version < '3.14'",
122
+ "rich>=12.3; python_version < '3.14'",
123
+ "matplotlib>=3.5; python_version < '3.14'",
124
+ "numpy>=1.24.4; python_version < '3.13'",
125
+ "numpy>=2.1; python_version >= '3.13' and python_version < '3.14'",
126
+ "textual>=0.67; python_version < '3.14'",
127
+ "pytermgui>=6.3; python_version < '3.14'",
128
+ "pipdeptree>=2.6; python_version < '3.14'",
129
+ "pip>=24; python_version < '3.14'",
130
+ "pygments>=2.15; python_version < '3.14'",
131
+ "drawsvg>=2.3; python_version < '3.14'",
132
+ "hyperbolic>=2.0; python_version < '3.14'",
133
+ "qrcode>=7.4; python_version < '3.14'",
134
+ "plotly>=5.22; python_version < '3.14'",
135
+ "pandas>=2.2; python_version < '3.14'",
136
+ "chalk-diagrams>=0.2; python_version < '3.14'",
137
+ ]
@@ -5,17 +5,18 @@ from __future__ import annotations
5
5
  import os
6
6
  import sys
7
7
  from collections import defaultdict
8
+ from collections.abc import Iterable
8
9
  from importlib.metadata import distributions
9
10
  from itertools import chain
10
11
  from pathlib import Path
11
12
  from textwrap import dedent
12
- from typing import Dict, Iterable, Union
13
+ from typing import Union
13
14
 
14
15
  from jinja2 import StrictUndefined
15
16
  from jinja2.sandbox import SandboxedEnvironment
16
17
  from packaging.requirements import Requirement
17
18
 
18
- # TODO: Remove once support for Python 3.10 is dropped.
19
+ # YORE: EOL 3.10: Replace block with line 2.
19
20
  if sys.version_info >= (3, 11):
20
21
  import tomllib
21
22
  else:
@@ -26,11 +27,10 @@ with project_dir.joinpath("pyproject.toml").open("rb") as pyproject_file:
26
27
  pyproject = tomllib.load(pyproject_file)
27
28
  project = pyproject["project"]
28
29
  project_name = project["name"]
29
- with project_dir.joinpath("devdeps.txt").open() as devdeps_file:
30
- devdeps = [line.strip() for line in devdeps_file if line.strip() and not line.strip().startswith(("-e", "#"))]
30
+ devdeps = [dep for dep in pyproject["dependency-groups"]["dev"] if not dep.startswith("-e")]
31
31
 
32
- PackageMetadata = Dict[str, Union[str, Iterable[str]]]
33
- Metadata = Dict[str, PackageMetadata]
32
+ PackageMetadata = dict[str, Union[str, Iterable[str]]]
33
+ Metadata = dict[str, PackageMetadata]
34
34
 
35
35
 
36
36
  def _merge_fields(metadata: dict) -> PackageMetadata: