anyplotlib 0.1.0b1__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 (224) hide show
  1. anyplotlib-0.1.0b1/.github/workflows/ci.yml +35 -0
  2. anyplotlib-0.1.0b1/.github/workflows/docs.yml +169 -0
  3. anyplotlib-0.1.0b1/.github/workflows/prepare_release.yml +218 -0
  4. anyplotlib-0.1.0b1/.github/workflows/release.yml +115 -0
  5. anyplotlib-0.1.0b1/.github/workflows/tests.yml +80 -0
  6. anyplotlib-0.1.0b1/.gitignore +53 -0
  7. anyplotlib-0.1.0b1/AGENTS.md +127 -0
  8. anyplotlib-0.1.0b1/CHANGELOG.rst +220 -0
  9. anyplotlib-0.1.0b1/Examples/Benchmarks/README.rst +8 -0
  10. anyplotlib-0.1.0b1/Examples/Benchmarks/plot_benchmark_comparison.py +559 -0
  11. anyplotlib-0.1.0b1/Examples/Interactive/README.rst +6 -0
  12. anyplotlib-0.1.0b1/Examples/Interactive/plot_3d_spectral_viewer.py +229 -0
  13. anyplotlib-0.1.0b1/Examples/Interactive/plot_eels_explorer.py +211 -0
  14. anyplotlib-0.1.0b1/Examples/Interactive/plot_interactive_fft.py +180 -0
  15. anyplotlib-0.1.0b1/Examples/Interactive/plot_interactive_fitting.py +297 -0
  16. anyplotlib-0.1.0b1/Examples/Interactive/plot_ipf_density_map.py +235 -0
  17. anyplotlib-0.1.0b1/Examples/Interactive/plot_ipf_explorer.py +125 -0
  18. anyplotlib-0.1.0b1/Examples/Interactive/plot_key_bindings.py +128 -0
  19. anyplotlib-0.1.0b1/Examples/Interactive/plot_particle_picker.py +209 -0
  20. anyplotlib-0.1.0b1/Examples/Interactive/plot_point_widget.py +109 -0
  21. anyplotlib-0.1.0b1/Examples/Interactive/plot_segment_by_contrast.py +245 -0
  22. anyplotlib-0.1.0b1/Examples/Interactive/plot_segment_by_contrast_advanced.py +355 -0
  23. anyplotlib-0.1.0b1/Examples/Interactive/plot_spectra_roi_inspector.py +265 -0
  24. anyplotlib-0.1.0b1/Examples/Interactive/plot_threshold_explorer.py +138 -0
  25. anyplotlib-0.1.0b1/Examples/Interactive/plot_voxel_grain_explorer.py +292 -0
  26. anyplotlib-0.1.0b1/Examples/Markers/README.rst +3 -0
  27. anyplotlib-0.1.0b1/Examples/Markers/plot_arrows.py +35 -0
  28. anyplotlib-0.1.0b1/Examples/Markers/plot_circles.py +34 -0
  29. anyplotlib-0.1.0b1/Examples/Markers/plot_ellipses.py +37 -0
  30. anyplotlib-0.1.0b1/Examples/Markers/plot_horizontal_lines.py +29 -0
  31. anyplotlib-0.1.0b1/Examples/Markers/plot_line_segments.py +40 -0
  32. anyplotlib-0.1.0b1/Examples/Markers/plot_points.py +32 -0
  33. anyplotlib-0.1.0b1/Examples/Markers/plot_polygons.py +38 -0
  34. anyplotlib-0.1.0b1/Examples/Markers/plot_rectangles.py +34 -0
  35. anyplotlib-0.1.0b1/Examples/Markers/plot_squares.py +38 -0
  36. anyplotlib-0.1.0b1/Examples/Markers/plot_texts.py +34 -0
  37. anyplotlib-0.1.0b1/Examples/Markers/plot_vertical_lines.py +29 -0
  38. anyplotlib-0.1.0b1/Examples/PlotTypes/README.rst +3 -0
  39. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_3d.py +74 -0
  40. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_bar.py +151 -0
  41. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_gridspec_custom.py +187 -0
  42. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_image2d.py +130 -0
  43. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_inset.py +90 -0
  44. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_label_formatting.py +42 -0
  45. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_line_styles.py +159 -0
  46. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_pcolormesh.py +65 -0
  47. anyplotlib-0.1.0b1/Examples/PlotTypes/plot_spectra1d.py +112 -0
  48. anyplotlib-0.1.0b1/Examples/README.rst +4 -0
  49. anyplotlib-0.1.0b1/Examples/Widgets/README.rst +3 -0
  50. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget1d_hline.py +20 -0
  51. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget1d_range.py +21 -0
  52. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget1d_vline.py +20 -0
  53. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget2d_annular.py +21 -0
  54. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget2d_circle.py +22 -0
  55. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget2d_crosshair.py +21 -0
  56. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget2d_label.py +23 -0
  57. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget2d_polygon.py +23 -0
  58. anyplotlib-0.1.0b1/Examples/Widgets/plot_widget2d_rectangle.py +22 -0
  59. anyplotlib-0.1.0b1/LICENSE +21 -0
  60. anyplotlib-0.1.0b1/Makefile +25 -0
  61. anyplotlib-0.1.0b1/ORIX_BACKEND_PLAN.md +133 -0
  62. anyplotlib-0.1.0b1/PKG-INFO +160 -0
  63. anyplotlib-0.1.0b1/README.md +119 -0
  64. anyplotlib-0.1.0b1/RELEASE_NOTES.md +94 -0
  65. anyplotlib-0.1.0b1/RELEASE_PLAN.md +104 -0
  66. anyplotlib-0.1.0b1/WEBGPU_PLAN.md +234 -0
  67. anyplotlib-0.1.0b1/anyplotlib/FIGURE_ESM.md +311 -0
  68. anyplotlib-0.1.0b1/anyplotlib/__init__.py +53 -0
  69. anyplotlib-0.1.0b1/anyplotlib/_base_plot.py +229 -0
  70. anyplotlib-0.1.0b1/anyplotlib/_electron.py +74 -0
  71. anyplotlib-0.1.0b1/anyplotlib/_repr_utils.py +345 -0
  72. anyplotlib-0.1.0b1/anyplotlib/_utils.py +194 -0
  73. anyplotlib-0.1.0b1/anyplotlib/axes/__init__.py +6 -0
  74. anyplotlib-0.1.0b1/anyplotlib/axes/_axes.py +510 -0
  75. anyplotlib-0.1.0b1/anyplotlib/axes/_inset_axes.py +126 -0
  76. anyplotlib-0.1.0b1/anyplotlib/callbacks.py +328 -0
  77. anyplotlib-0.1.0b1/anyplotlib/conftest.py +26 -0
  78. anyplotlib-0.1.0b1/anyplotlib/embed.py +194 -0
  79. anyplotlib-0.1.0b1/anyplotlib/figure/__init__.py +7 -0
  80. anyplotlib-0.1.0b1/anyplotlib/figure/_figure.py +633 -0
  81. anyplotlib-0.1.0b1/anyplotlib/figure/_gridspec.py +99 -0
  82. anyplotlib-0.1.0b1/anyplotlib/figure/_subplots.py +100 -0
  83. anyplotlib-0.1.0b1/anyplotlib/figure_esm.js +6011 -0
  84. anyplotlib-0.1.0b1/anyplotlib/markers.py +704 -0
  85. anyplotlib-0.1.0b1/anyplotlib/plot1d/__init__.py +6 -0
  86. anyplotlib-0.1.0b1/anyplotlib/plot1d/_plot1d.py +1376 -0
  87. anyplotlib-0.1.0b1/anyplotlib/plot1d/_plotbar.py +436 -0
  88. anyplotlib-0.1.0b1/anyplotlib/plot2d/__init__.py +5 -0
  89. anyplotlib-0.1.0b1/anyplotlib/plot2d/_plot2d.py +726 -0
  90. anyplotlib-0.1.0b1/anyplotlib/plot2d/_plotmesh.py +116 -0
  91. anyplotlib-0.1.0b1/anyplotlib/plot3d/__init__.py +4 -0
  92. anyplotlib-0.1.0b1/anyplotlib/plot3d/_plot3d.py +524 -0
  93. anyplotlib-0.1.0b1/anyplotlib/plotxy/__init__.py +4 -0
  94. anyplotlib-0.1.0b1/anyplotlib/plotxy/_plotxy.py +273 -0
  95. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/__init__.py +177 -0
  96. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/_directive.py +245 -0
  97. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/_repr_utils.py +298 -0
  98. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/_scraper.py +390 -0
  99. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/_wheel_builder.py +84 -0
  100. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/static/anywidget_bridge.js +1099 -0
  101. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/static/anywidget_overlay.css +100 -0
  102. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/tests/__init__.py +0 -0
  103. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/tests/conftest.py +125 -0
  104. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/tests/test_directive.py +220 -0
  105. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/tests/test_init.py +251 -0
  106. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/tests/test_repr_utils.py +261 -0
  107. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/tests/test_scraper.py +269 -0
  108. anyplotlib-0.1.0b1/anyplotlib/sphinx_anywidget/tests/test_wheel_builder.py +93 -0
  109. anyplotlib-0.1.0b1/anyplotlib/tests/__init__.py +0 -0
  110. anyplotlib-0.1.0b1/anyplotlib/tests/_png_utils.py +289 -0
  111. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/bar_basic.png +0 -0
  112. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/gridspec_3col_equal_spectra.png +0 -0
  113. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/gridspec_asymmetric_width_ratios.png +0 -0
  114. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/gridspec_height_ratio_image_histogram.png +0 -0
  115. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/gridspec_image_two_spectra.png +0 -0
  116. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/gridspec_side_by_side_1d.png +0 -0
  117. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/gridspec_spanning_top_two_bottom.png +0 -0
  118. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/imshow_axis_off.png +0 -0
  119. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/imshow_checkerboard.png +0 -0
  120. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/imshow_gradient.png +0 -0
  121. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/imshow_labels.png +0 -0
  122. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/imshow_viridis.png +0 -0
  123. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/inset_1d.png +0 -0
  124. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/inset_maximized.png +0 -0
  125. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/inset_minimized.png +0 -0
  126. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/inset_normal_2d.png +0 -0
  127. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/inset_stacked.png +0 -0
  128. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/inset_stacked_one_minimized.png +0 -0
  129. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/pcolormesh_uniform.png +0 -0
  130. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_all_linestyles.png +0 -0
  131. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_alpha.png +0 -0
  132. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_axis_off.png +0 -0
  133. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_dashed.png +0 -0
  134. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_marker_symbols.png +0 -0
  135. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_markers.png +0 -0
  136. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_multi.png +0 -0
  137. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_sine.png +0 -0
  138. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot1d_title.png +0 -0
  139. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/plot3d_surface.png +0 -0
  140. anyplotlib-0.1.0b1/anyplotlib/tests/baselines/subplots_2x1.png +0 -0
  141. anyplotlib-0.1.0b1/anyplotlib/tests/conftest.py +435 -0
  142. anyplotlib-0.1.0b1/anyplotlib/tests/test_benchmarks/__init__.py +0 -0
  143. anyplotlib-0.1.0b1/anyplotlib/tests/test_benchmarks/baselines.json +321 -0
  144. anyplotlib-0.1.0b1/anyplotlib/tests/test_benchmarks/benchmarks/baselines.json +46 -0
  145. anyplotlib-0.1.0b1/anyplotlib/tests/test_benchmarks/test_benchmarks.py +524 -0
  146. anyplotlib-0.1.0b1/anyplotlib/tests/test_benchmarks/test_benchmarks_py.py +279 -0
  147. anyplotlib-0.1.0b1/anyplotlib/tests/test_documentation/__init__.py +0 -0
  148. anyplotlib-0.1.0b1/anyplotlib/tests/test_documentation/test_bridge.py +572 -0
  149. anyplotlib-0.1.0b1/anyplotlib/tests/test_documentation/test_push_hook.py +158 -0
  150. anyplotlib-0.1.0b1/anyplotlib/tests/test_documentation/test_scraper.py +123 -0
  151. anyplotlib-0.1.0b1/anyplotlib/tests/test_embed/__init__.py +0 -0
  152. anyplotlib-0.1.0b1/anyplotlib/tests/test_embed/test_embed_api.py +133 -0
  153. anyplotlib-0.1.0b1/anyplotlib/tests/test_embed/test_embed_mount.py +237 -0
  154. anyplotlib-0.1.0b1/anyplotlib/tests/test_examples/__init__.py +0 -0
  155. anyplotlib-0.1.0b1/anyplotlib/tests/test_examples/test_interactive_examples.py +28 -0
  156. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/__init__.py +0 -0
  157. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/_event_test_utils.py +35 -0
  158. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_blit_audit.py +496 -0
  159. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_callbacks_playwright.py +491 -0
  160. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_callbacks_unit.py +528 -0
  161. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_event_pause_hold.py +214 -0
  162. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_event_plots.py +295 -0
  163. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_event_settled.py +185 -0
  164. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_events_regression.py +1078 -0
  165. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_title.py +157 -0
  166. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_touch.py +229 -0
  167. anyplotlib-0.1.0b1/anyplotlib/tests/test_interactive/test_widgets.py +1380 -0
  168. anyplotlib-0.1.0b1/anyplotlib/tests/test_labels/__init__.py +0 -0
  169. anyplotlib-0.1.0b1/anyplotlib/tests/test_labels/test_label_api.py +132 -0
  170. anyplotlib-0.1.0b1/anyplotlib/tests/test_labels/test_label_rendering.py +137 -0
  171. anyplotlib-0.1.0b1/anyplotlib/tests/test_labels/test_no_clipping.py +102 -0
  172. anyplotlib-0.1.0b1/anyplotlib/tests/test_layouts/__init__.py +0 -0
  173. anyplotlib-0.1.0b1/anyplotlib/tests/test_layouts/test_batch.py +90 -0
  174. anyplotlib-0.1.0b1/anyplotlib/tests/test_layouts/test_geom_channel.py +71 -0
  175. anyplotlib-0.1.0b1/anyplotlib/tests/test_layouts/test_gridspec.py +1141 -0
  176. anyplotlib-0.1.0b1/anyplotlib/tests/test_layouts/test_inset.py +386 -0
  177. anyplotlib-0.1.0b1/anyplotlib/tests/test_layouts/test_interaction.py +1153 -0
  178. anyplotlib-0.1.0b1/anyplotlib/tests/test_layouts/test_visual.py +343 -0
  179. anyplotlib-0.1.0b1/anyplotlib/tests/test_markers/__init__.py +0 -0
  180. anyplotlib-0.1.0b1/anyplotlib/tests/test_markers/test_marker_transforms.py +224 -0
  181. anyplotlib-0.1.0b1/anyplotlib/tests/test_markers/test_markers.py +726 -0
  182. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot1d/__init__.py +0 -0
  183. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot1d/test_plot1d.py +1017 -0
  184. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot1d/test_plotbar.py +995 -0
  185. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot2d/__init__.py +0 -0
  186. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot2d/test_imshow.py +633 -0
  187. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot2d/test_imshow_rgb.py +117 -0
  188. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot2d/test_pcolormesh.py +194 -0
  189. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot2d/test_plot2d_api.py +506 -0
  190. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot3d/__init__.py +0 -0
  191. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot3d/test_colors_highlight.py +174 -0
  192. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot3d/test_gpu_fallback.py +240 -0
  193. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot3d/test_plot3d.py +361 -0
  194. anyplotlib-0.1.0b1/anyplotlib/tests/test_plot3d/test_voxels_planes.py +247 -0
  195. anyplotlib-0.1.0b1/anyplotlib/tests/test_plotxy/test_plotxy.py +207 -0
  196. anyplotlib-0.1.0b1/anyplotlib/widgets/__init__.py +18 -0
  197. anyplotlib-0.1.0b1/anyplotlib/widgets/_base.py +218 -0
  198. anyplotlib-0.1.0b1/anyplotlib/widgets/_widgets1d.py +109 -0
  199. anyplotlib-0.1.0b1/anyplotlib/widgets/_widgets2d.py +141 -0
  200. anyplotlib-0.1.0b1/anyplotlib/widgets/_widgets3d.py +50 -0
  201. anyplotlib-0.1.0b1/docs/_root/index.html +16 -0
  202. anyplotlib-0.1.0b1/docs/_root/switcher.json +12 -0
  203. anyplotlib-0.1.0b1/docs/_sg_html_scraper.py +21 -0
  204. anyplotlib-0.1.0b1/docs/_static/anyplotlib.svg +48 -0
  205. anyplotlib-0.1.0b1/docs/_static/custom.css +23 -0
  206. anyplotlib-0.1.0b1/docs/_static/pyodide_bridge.js +400 -0
  207. anyplotlib-0.1.0b1/docs/_templates/autosummary/class.rst +34 -0
  208. anyplotlib-0.1.0b1/docs/api/callbacks.rst +31 -0
  209. anyplotlib-0.1.0b1/docs/api/figure.rst +34 -0
  210. anyplotlib-0.1.0b1/docs/api/figure_plots.rst +88 -0
  211. anyplotlib-0.1.0b1/docs/api/index.rst +173 -0
  212. anyplotlib-0.1.0b1/docs/api/markers.rst +38 -0
  213. anyplotlib-0.1.0b1/docs/api/widgets.rst +93 -0
  214. anyplotlib-0.1.0b1/docs/benchmarking.rst +54 -0
  215. anyplotlib-0.1.0b1/docs/conf.py +126 -0
  216. anyplotlib-0.1.0b1/docs/dev/index.rst +334 -0
  217. anyplotlib-0.1.0b1/docs/embedding.rst +181 -0
  218. anyplotlib-0.1.0b1/docs/events.rst +630 -0
  219. anyplotlib-0.1.0b1/docs/getting_started.rst +170 -0
  220. anyplotlib-0.1.0b1/docs/index.rst +128 -0
  221. anyplotlib-0.1.0b1/make.bat +44 -0
  222. anyplotlib-0.1.0b1/pyproject.toml +138 -0
  223. anyplotlib-0.1.0b1/upcoming_changes/README.rst +84 -0
  224. anyplotlib-0.1.0b1/uv.lock +3394 -0
@@ -0,0 +1,35 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Set up uv
15
+ uses: astral-sh/setup-uv@v5
16
+ with:
17
+ python-version: "3.12"
18
+ enable-cache: true
19
+
20
+ - name: Install dependencies
21
+ run: uv sync --group dev
22
+
23
+ - name: Install Playwright browsers
24
+ run: uv run playwright install --with-deps chromium
25
+
26
+ - name: Run tests with coverage
27
+ run: uv run pytest
28
+
29
+ - name: Upload coverage to Codecov
30
+ uses: codecov/codecov-action@v5
31
+ with:
32
+ files: coverage.xml
33
+ fail_ci_if_error: false
34
+ env:
35
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,169 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ # Publish to dev/ on every push to main …
6
+ branches: [main]
7
+ # … and to a versioned directory on every release tag.
8
+ tags: ["v*.*.*"]
9
+ pull_request:
10
+ branches: [main]
11
+ # Allow manual re-builds from the Actions tab.
12
+ workflow_dispatch:
13
+
14
+ # Only one docs deployment should run at a time to avoid race conditions on
15
+ # the gh-pages branch.
16
+ concurrency:
17
+ group: docs-${{ github.ref }}
18
+ cancel-in-progress: true
19
+
20
+ permissions:
21
+ contents: write # needed to push to gh-pages
22
+
23
+ jobs:
24
+ # ── Build ──────────────────────────────────────────────────────────────────
25
+ # Runs on every push and every pull request. Treats warnings as errors so
26
+ # broken cross-references and bad docstrings are caught before merge.
27
+ build:
28
+ name: Build docs
29
+ runs-on: ubuntu-latest
30
+
31
+ steps:
32
+ - name: Checkout repository
33
+ uses: actions/checkout@v4
34
+ with:
35
+ fetch-depth: 0
36
+
37
+ # ── uv + Python ──────────────────────────────────────────────────────
38
+ - name: Set up uv
39
+ uses: astral-sh/setup-uv@v5
40
+ with:
41
+ python-version: "3.13"
42
+ enable-cache: true
43
+
44
+ # ── Dependencies ─────────────────────────────────────────────────────
45
+ # Install the package itself plus the [docs] optional-dependency group
46
+ # (sphinx, pydata-sphinx-theme, sphinx-gallery, pillow, playwright).
47
+ - name: Install dependencies (with docs extras)
48
+ run: uv sync --extra docs
49
+
50
+ # Playwright ships the Python bindings but NOT the browser binaries.
51
+ # --with-deps also installs the OS-level shared libraries Chromium needs
52
+ # (libglib2, libnss3, etc.) on bare Ubuntu runners.
53
+ - name: Install Playwright browser
54
+ run: uv run playwright install chromium --with-deps
55
+
56
+ # ── Build Pyodide wheel ───────────────────────────────────────────────
57
+ # Produces docs/_static/wheels/anyplotlib-0.0.0-py3-none-any.whl so the
58
+ # in-browser Pyodide bridge can install the exact source tree that built
59
+ # these docs — no PyPI release required.
60
+ - name: Build Pyodide wheel
61
+ run: |
62
+ mkdir -p docs/_static/wheels
63
+ uv build --wheel --out-dir docs/_static/wheels/
64
+ # Rename to the stable sentinel name micropip expects for URL installs.
65
+ cd docs/_static/wheels
66
+ for f in anyplotlib-*.whl; do
67
+ [ "$f" != "anyplotlib-0.0.0-py3-none-any.whl" ] && mv "$f" anyplotlib-0.0.0-py3-none-any.whl
68
+ done
69
+
70
+ # ── Sphinx build ─────────────────────────────────────────────────────
71
+ # -W turns warnings into errors; --keep-going collects all of them.
72
+ - name: Build HTML documentation
73
+ run: |
74
+ uv run sphinx-build -b html docs build/html -W --keep-going
75
+
76
+ # ── Upload built HTML as an artifact so it can be inspected on PRs ──
77
+ - name: Upload HTML artifact
78
+ uses: actions/upload-artifact@v4
79
+ with:
80
+ name: docs-html
81
+ path: build/html
82
+ retention-days: 7
83
+
84
+ # ── Deploy ─────────────────────────────────────────────────────────────────
85
+ # Only runs after a successful build on pushes to main or release tags.
86
+ # Pull requests skip this job entirely.
87
+ deploy:
88
+ name: Deploy docs
89
+ needs: build
90
+ runs-on: ubuntu-latest
91
+ # Skip deployment for pull requests.
92
+ if: github.event_name != 'pull_request'
93
+
94
+ steps:
95
+ - name: Checkout repository
96
+ uses: actions/checkout@v4
97
+ with:
98
+ fetch-depth: 0
99
+
100
+ # ── uv + Python ──────────────────────────────────────────────────────
101
+ - name: Set up uv
102
+ uses: astral-sh/setup-uv@v5
103
+ with:
104
+ python-version: "3.13"
105
+ enable-cache: true
106
+
107
+ # ── Dependencies ─────────────────────────────────────────────────────
108
+ - name: Install dependencies (with docs extras)
109
+ run: uv sync --extra docs
110
+
111
+ - name: Install Playwright browser
112
+ run: uv run playwright install chromium --with-deps
113
+
114
+ # ── Determine deployment target ──────────────────────────────────────
115
+ # Release tag (refs/tags/v1.2.3) → destination = "v1.2.3"
116
+ # Everything else (push to main, manual dispatch) → destination = "dev"
117
+ - name: Determine deployment directory
118
+ id: target
119
+ shell: bash
120
+ run: |
121
+ if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
122
+ echo "dest_dir=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
123
+ else
124
+ echo "dest_dir=dev" >> "$GITHUB_OUTPUT"
125
+ fi
126
+
127
+ # ── Build Pyodide wheel ───────────────────────────────────────────────
128
+ - name: Build Pyodide wheel
129
+ run: |
130
+ mkdir -p docs/_static/wheels
131
+ uv build --wheel --out-dir docs/_static/wheels/
132
+ cd docs/_static/wheels
133
+ for f in anyplotlib-*.whl; do
134
+ [ "$f" != "anyplotlib-0.0.0-py3-none-any.whl" ] && mv "$f" anyplotlib-0.0.0-py3-none-any.whl
135
+ done
136
+
137
+ # ── Sphinx build ─────────────────────────────────────────────────────
138
+ - name: Build HTML documentation
139
+ env:
140
+ DOCS_VERSION: ${{ steps.target.outputs.dest_dir }}
141
+ run: |
142
+ uv run sphinx-build -b html docs build/html -W --keep-going
143
+
144
+ # ── Deploy to gh-pages ───────────────────────────────────────────────
145
+ # keep_files: true preserves all existing directories on the branch so
146
+ # versioned releases accumulate rather than overwriting each other.
147
+ - name: Deploy to GitHub Pages
148
+ uses: peaceiris/actions-gh-pages@v4
149
+ with:
150
+ github_token: ${{ secrets.GITHUB_TOKEN }}
151
+ publish_dir: ./build/html
152
+ destination_dir: ${{ steps.target.outputs.dest_dir }}
153
+ keep_files: true
154
+ commit_message: |
155
+ docs: deploy ${{ steps.target.outputs.dest_dir }} @ ${{ github.sha }}
156
+
157
+ # ── Deploy root files (redirect + switcher) ──────────────────────────
158
+ # Places index.html and switcher.json at the root of gh-pages so the
159
+ # bare URL redirects to dev/ and the version switcher is always reachable.
160
+ - name: Deploy root redirect and switcher
161
+ uses: peaceiris/actions-gh-pages@v4
162
+ with:
163
+ github_token: ${{ secrets.GITHUB_TOKEN }}
164
+ publish_dir: ./docs/_root
165
+ destination_dir: .
166
+ keep_files: true
167
+ commit_message: |
168
+ docs: update root redirect and switcher.json @ ${{ github.sha }}
169
+
@@ -0,0 +1,218 @@
1
+ name: Prepare Release
2
+
3
+ # Run manually from the Actions tab.
4
+ # Creates a branch + PR that bumps the version, builds the changelog,
5
+ # and updates the docs switcher — ready to review before tagging.
6
+ on:
7
+ workflow_dispatch:
8
+ inputs:
9
+ bump:
10
+ description: "Version component to bump"
11
+ required: true
12
+ type: choice
13
+ options:
14
+ - minor
15
+ - bugfix
16
+ - major
17
+ - pre-release # increments the bN counter on the current base version
18
+ beta:
19
+ description: "Mark as beta pre-release (adds bN suffix; always true for pre-release)"
20
+ required: false
21
+ type: boolean
22
+ default: false
23
+
24
+ permissions:
25
+ contents: write # push branch
26
+ pull-requests: write # open PR
27
+
28
+ jobs:
29
+ prepare:
30
+ name: Prepare release PR
31
+ runs-on: ubuntu-latest
32
+
33
+ steps:
34
+ - name: Checkout repository
35
+ uses: actions/checkout@v4
36
+ with:
37
+ fetch-depth: 0
38
+
39
+ - name: Set up uv
40
+ uses: astral-sh/setup-uv@v5
41
+ with:
42
+ python-version: "3.13"
43
+ enable-cache: true
44
+
45
+ - name: Install dev dependencies
46
+ run: uv sync
47
+
48
+ # ── Compute the new version ──────────────────────────────────────────
49
+ - name: Compute new version
50
+ id: version
51
+ env:
52
+ BUMP: ${{ inputs.bump }}
53
+ IS_BETA: ${{ inputs.beta }}
54
+ run: |
55
+ CURRENT=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
56
+ export CURRENT_VERSION="$CURRENT"
57
+
58
+ NEW_VERSION=$(python3 - <<'PYEOF'
59
+ import re, os
60
+
61
+ current = os.environ["CURRENT_VERSION"]
62
+ bump = os.environ["BUMP"]
63
+ is_beta = os.environ["IS_BETA"].lower() == "true"
64
+
65
+ m = re.match(r"^(\d+)\.(\d+)\.(\d+)(?:b(\d+))?", current)
66
+ major = int(m.group(1))
67
+ minor = int(m.group(2))
68
+ patch = int(m.group(3))
69
+ beta_n = int(m.group(4)) if m.group(4) else None
70
+
71
+ if bump == "major":
72
+ major, minor, patch = major + 1, 0, 0
73
+ elif bump == "minor":
74
+ minor, patch = minor + 1, 0
75
+ elif bump == "bugfix":
76
+ patch += 1
77
+ elif bump == "pre-release":
78
+ # Keep the same base; just walk the beta counter forward.
79
+ is_beta = True
80
+ beta_n = (beta_n or 0) + 1
81
+
82
+ if is_beta:
83
+ if bump != "pre-release":
84
+ beta_n = 1 # fresh beta series for the new base
85
+ print(f"{major}.{minor}.{patch}b{beta_n}", end="")
86
+ else:
87
+ print(f"{major}.{minor}.{patch}", end="")
88
+ PYEOF
89
+ )
90
+
91
+ echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
92
+ echo "tag=v$NEW_VERSION" >> "$GITHUB_OUTPUT"
93
+ echo "branch=release/v$NEW_VERSION" >> "$GITHUB_OUTPUT"
94
+ echo "is_beta=${{ inputs.beta }}" >> "$GITHUB_OUTPUT"
95
+ echo "Bumping (${{ inputs.bump }}): $CURRENT → $NEW_VERSION"
96
+
97
+ # ── Bump version strings ─────────────────────────────────────────────
98
+ - name: Bump version in pyproject.toml
99
+ run: |
100
+ sed -i 's/^version = ".*"/version = "${{ steps.version.outputs.new_version }}"/' pyproject.toml
101
+
102
+ - name: Bump version in docs/conf.py
103
+ run: |
104
+ sed -i 's/^release = ".*"/release = "${{ steps.version.outputs.new_version }}"/' docs/conf.py
105
+
106
+ # ── Build changelog ──────────────────────────────────────────────────
107
+ - name: Build changelog with towncrier
108
+ run: |
109
+ FRAGMENT_COUNT=$(find upcoming_changes -maxdepth 1 -name "*.rst" \
110
+ ! -name "README.rst" | wc -l)
111
+ if [ "$FRAGMENT_COUNT" -eq 0 ]; then
112
+ echo "⚠ No news fragments found — skipping towncrier (CHANGELOG.rst unchanged)."
113
+ else
114
+ uvx towncrier build --yes --version "${{ steps.version.outputs.new_version }}"
115
+ fi
116
+
117
+ # ── Update docs switcher.json ────────────────────────────────────────
118
+ - name: Update docs/switcher.json
119
+ env:
120
+ VERSION_TAG: ${{ steps.version.outputs.tag }}
121
+ IS_BETA: ${{ inputs.beta }}
122
+ shell: python
123
+ run: |
124
+ import json, re, pathlib, os
125
+
126
+ version = os.environ["VERSION_TAG"]
127
+ is_beta = os.environ["IS_BETA"].lower() == "true"
128
+
129
+ path = pathlib.Path("docs/_root/switcher.json")
130
+ text = path.read_text()
131
+ # The file may contain a trailing comma; strip it before parsing.
132
+ text_clean = re.sub(r",(\s*[\]\}])", r"\1", text)
133
+ entries = json.loads(text_clean)
134
+
135
+ # Remove any existing entry for this version (makes the step idempotent).
136
+ entries = [e for e in entries if e.get("version") != version]
137
+
138
+ label = f"{version} (beta)" if is_beta else f"{version} (stable)"
139
+ url = f"https://cssfrancis.github.io/anyplotlib/{version}/"
140
+ # Insert right after the "dev" entry so newest stable floats to top.
141
+ entries.insert(1, {"name": label, "version": version, "url": url})
142
+
143
+ path.write_text(json.dumps(entries, indent=2) + "\n")
144
+
145
+ # ── Update root redirect for stable releases ─────────────────────────
146
+ - name: Update root redirect (stable releases only)
147
+ if: ${{ inputs.beta == false && inputs.bump != 'pre-release' }}
148
+ env:
149
+ VERSION_TAG: ${{ steps.version.outputs.tag }}
150
+ shell: python
151
+ run: |
152
+ import re, pathlib, os
153
+
154
+ version = os.environ["VERSION_TAG"]
155
+ path = pathlib.Path("docs/_root/index.html")
156
+ text = path.read_text()
157
+
158
+ text = re.sub(r'(content="0; url=)[^"]+(")', rf"\g<1>{version}/\2", text)
159
+ text = re.sub(r'(rel="canonical" href=")[^"]+(")', rf"\g<1>{version}/\2", text)
160
+ text = re.sub(r'(<a href=")[^"]+(">[^<]*</a>)', rf"\g<1>{version}/\2", text)
161
+ text = re.sub(r'(Redirecting to <a href="[^"]+">)[^<]*(</a>)',
162
+ rf"\g<1>{version} documentation\2", text)
163
+
164
+ path.write_text(text)
165
+
166
+ # ── Commit and push ──────────────────────────────────────────────────
167
+ - name: Configure git
168
+ run: |
169
+ git config user.name "github-actions[bot]"
170
+ git config user.email "github-actions[bot]@users.noreply.github.com"
171
+
172
+ - name: Commit release changes
173
+ run: |
174
+ git checkout -b "${{ steps.version.outputs.branch }}"
175
+
176
+ # Stage version bumps, updated changelog, and consumed fragments.
177
+ git add pyproject.toml docs/conf.py CHANGELOG.rst
178
+ git add docs/_root/switcher.json docs/_root/index.html
179
+ git add -A upcoming_changes/ # stages deleted fragment files
180
+
181
+ git commit -m "chore: prepare release ${{ steps.version.outputs.tag }}"
182
+ git push origin "${{ steps.version.outputs.branch }}"
183
+
184
+ # ── Open pull request ────────────────────────────────────────────────
185
+ - name: Open pull request
186
+ env:
187
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
188
+ TAG: ${{ steps.version.outputs.tag }}
189
+ BRANCH: ${{ steps.version.outputs.branch }}
190
+ run: |
191
+ gh pr create \
192
+ --title "Release ${TAG}" \
193
+ --base main \
194
+ --head "${BRANCH}" \
195
+ --body "## Release ${TAG}
196
+
197
+ > Auto-generated by the **Prepare Release** workflow.
198
+
199
+ ### What changed
200
+ - Version bumped to \`${TAG}\` in \`pyproject.toml\` and \`docs/conf.py\`
201
+ - \`CHANGELOG.rst\` updated from towncrier fragments
202
+ - \`docs/_root/switcher.json\` updated with the new version entry
203
+ $([ '${{ inputs.beta }}' = 'false' ] && echo '- Root redirect updated to point to this release' || echo '')
204
+
205
+ ### Review checklist
206
+ - [ ] \`CHANGELOG.rst\` reads well — edit the fragment text directly if needed
207
+ - [ ] Version strings are correct in \`pyproject.toml\` and \`docs/conf.py\`
208
+ - [ ] \`switcher.json\` has the right label and URL
209
+ - [ ] CI passes
210
+
211
+ ### After merging
212
+ Create and push the tag to trigger the Release and Docs workflows:
213
+ \`\`\`bash
214
+ git fetch origin
215
+ git tag ${TAG} origin/main
216
+ git push origin ${TAG}
217
+ \`\`\`"
218
+
@@ -0,0 +1,115 @@
1
+ name: Release
2
+
3
+ # Fires when a version tag is pushed (manually, after the Prepare Release PR
4
+ # is merged and reviewed).
5
+ #
6
+ # Jobs:
7
+ # build - build wheel + sdist with uv
8
+ # publish - upload to PyPI via OIDC trusted publishing (no API token needed)
9
+ # release - create a GitHub Release with the dist files and changelog notes
10
+
11
+ on:
12
+ push:
13
+ tags: ["v*.*.*"]
14
+
15
+ permissions:
16
+ contents: write # create GitHub Releases and upload assets
17
+ id-token: write # OIDC token for PyPI trusted publishing
18
+
19
+ jobs:
20
+ # --------------------------------------------------------------------------
21
+ build:
22
+ name: Build distribution
23
+ runs-on: ubuntu-latest
24
+
25
+ steps:
26
+ - name: Checkout repository
27
+ uses: actions/checkout@v4
28
+
29
+ - name: Set up uv
30
+ uses: astral-sh/setup-uv@v5
31
+ with:
32
+ python-version: "3.13"
33
+ enable-cache: true
34
+
35
+ - name: Build wheel and sdist
36
+ run: uv build
37
+
38
+ - name: Upload dist artifact
39
+ uses: actions/upload-artifact@v4
40
+ with:
41
+ name: dist
42
+ path: dist/
43
+ if-no-files-found: error
44
+ retention-days: 7
45
+
46
+ # --------------------------------------------------------------------------
47
+ publish:
48
+ name: Publish to PyPI
49
+ needs: build
50
+ runs-on: ubuntu-latest
51
+
52
+ environment:
53
+ name: pypi
54
+ url: https://pypi.org/p/anyplotlib
55
+
56
+ steps:
57
+ - name: Download dist artifact
58
+ uses: actions/download-artifact@v4
59
+ with:
60
+ name: dist
61
+ path: dist/
62
+
63
+ # Trusted publishing - no API token required.
64
+ # One-time setup on pypi.org: add a pending publisher for
65
+ # Owner: CSSFrancis Repo: anyplotlib Workflow: release.yml
66
+ - name: Publish to PyPI
67
+ uses: pypa/gh-action-pypi-publish@release/v1
68
+
69
+ # --------------------------------------------------------------------------
70
+ release:
71
+ name: Create GitHub Release
72
+ needs: build
73
+ runs-on: ubuntu-latest
74
+
75
+ steps:
76
+ - name: Checkout repository
77
+ uses: actions/checkout@v4
78
+
79
+ - name: Download dist artifact
80
+ uses: actions/download-artifact@v4
81
+ with:
82
+ name: dist
83
+ path: dist/
84
+
85
+ - name: Prepare release notes
86
+ env:
87
+ TAG: ${{ github.ref_name }}
88
+ shell: python
89
+ run: |
90
+ import re, pathlib, os
91
+ tag = os.environ["TAG"]
92
+ # Prefer the curated RELEASE_NOTES.md; fall back to the matching
93
+ # CHANGELOG.rst section, then to a generic stub.
94
+ curated = pathlib.Path("RELEASE_NOTES.md")
95
+ if curated.exists():
96
+ notes = curated.read_text()
97
+ else:
98
+ text = pathlib.Path("CHANGELOG.rst").read_text()
99
+ parts = re.split(r"(?m)(?=^\S[^\n]*\n=+\n)", text)
100
+ section = next((p.strip() for p in parts if p.strip().startswith(tag)), None)
101
+ notes = section or ("Release " + tag + "\n\nSee CHANGELOG.rst.")
102
+ pathlib.Path("release_notes.md").write_text(notes)
103
+
104
+ - name: Create GitHub Release
105
+ env:
106
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
107
+ TAG: ${{ github.ref_name }}
108
+ run: |
109
+ PRERELEASE_FLAG=""
110
+ if [[ "$TAG" == *b* ]]; then PRERELEASE_FLAG="--prerelease"; fi
111
+ gh release create "$TAG" \
112
+ --title "$TAG" \
113
+ --notes-file release_notes.md \
114
+ $PRERELEASE_FLAG \
115
+ dist/*
@@ -0,0 +1,80 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: tests-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ test:
14
+ name: Python ${{ matrix.python-version }} / ${{ matrix.os }}
15
+ runs-on: ${{ matrix.os }}
16
+
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os: [ubuntu-latest, macos-latest, windows-latest]
21
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
22
+ exclude:
23
+ - os: macos-latest
24
+ python-version: "3.10"
25
+ - os: macos-latest
26
+ python-version: "3.11"
27
+ - os: windows-latest
28
+ python-version: "3.10"
29
+ - os: windows-latest
30
+ python-version: "3.11"
31
+
32
+ steps:
33
+ - name: Checkout repository
34
+ uses: actions/checkout@v4
35
+
36
+ - name: Set up uv
37
+ uses: astral-sh/setup-uv@v5
38
+ with:
39
+ python-version: ${{ matrix.python-version }}
40
+ enable-cache: true
41
+
42
+ - name: Install dependencies
43
+ run: uv sync
44
+
45
+ - name: Install Playwright browsers (Linux)
46
+ if: runner.os == 'Linux'
47
+ run: uv run playwright install chromium --with-deps
48
+
49
+ - name: Install Playwright browsers (macOS / Windows)
50
+ if: runner.os != 'Linux'
51
+ run: uv run playwright install chromium
52
+
53
+ - name: Run tests
54
+ run: uv run pytest anyplotlib/tests/ -v --tb=short
55
+
56
+ minimum-deps:
57
+ name: Minimum deps (Python 3.10 / ubuntu)
58
+ runs-on: ubuntu-latest
59
+
60
+ steps:
61
+ - name: Checkout repository
62
+ uses: actions/checkout@v4
63
+
64
+ - name: Set up uv
65
+ uses: astral-sh/setup-uv@v5
66
+ with:
67
+ python-version: "3.10"
68
+ enable-cache: true
69
+
70
+ - name: Install dependencies at minimum versions
71
+ run: uv sync --resolution lowest-direct
72
+
73
+ - name: Show installed versions
74
+ run: uv run pip list --format=columns
75
+
76
+ - name: Install Playwright browsers
77
+ run: uv run playwright install chromium --with-deps
78
+
79
+ - name: Run tests
80
+ run: uv run pytest anyplotlib/tests/ -v --tb=short
@@ -0,0 +1,53 @@
1
+ # Python bytecode / caches
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.pyo
6
+
7
+ # Distribution / packaging
8
+ dist/
9
+ build/
10
+ *.egg-info/
11
+ *.egg
12
+ .eggs/
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+ env/
18
+
19
+ # Test / coverage artefacts
20
+ .pytest_cache/
21
+ .coverage
22
+ coverage.xml
23
+ htmlcov/
24
+
25
+ # Jupyter notebooks checkpoints
26
+ .ipynb_checkpoints/
27
+
28
+ # Sphinx build output
29
+ docs/_build/
30
+ docs/api/generated/
31
+ docs/auto_examples/
32
+ docs/sg_execution_times.rst
33
+ build/html/
34
+ build/doctrees/
35
+
36
+ # Generated Pyodide wheel (built by workflow / make html — never commit)
37
+ docs/_static/wheels/
38
+ docs/_static/anywidget_config.js
39
+
40
+ # Editor / IDE
41
+ .idea/
42
+ .vscode/
43
+ *.swp
44
+ *.swo
45
+
46
+ # macOS
47
+ .DS_Store
48
+
49
+ # Git worktrees
50
+ .worktrees/
51
+
52
+ # Generated by Sphinx-Gallery (anywidget iframe HTML) — never commit
53
+ docs/_static/viewer_widgets/