ultraplot 2.1.5__tar.gz → 2.2.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 (466) hide show
  1. {ultraplot-2.1.5 → ultraplot-2.2.0}/.github/workflows/build-ultraplot.yml +2 -2
  2. {ultraplot-2.1.5 → ultraplot-2.2.0}/.github/workflows/main.yml +3 -3
  3. {ultraplot-2.1.5 → ultraplot-2.2.0}/.github/workflows/publish-pypi.yml +33 -12
  4. {ultraplot-2.1.5 → ultraplot-2.2.0}/.github/workflows/test-map.yml +2 -2
  5. {ultraplot-2.1.5 → ultraplot-2.2.0}/.pre-commit-config.yaml +1 -1
  6. {ultraplot-2.1.5 → ultraplot-2.2.0}/CITATION.cff +2 -2
  7. {ultraplot-2.1.5/ultraplot.egg-info → ultraplot-2.2.0}/PKG-INFO +2 -2
  8. ultraplot-2.2.0/docs/_scripts/fetch_releases.py +154 -0
  9. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/custom.css +38 -0
  10. {ultraplot-2.1.5 → ultraplot-2.2.0}/environment.yml +2 -0
  11. {ultraplot-2.1.5 → ultraplot-2.2.0}/pyproject.toml +1 -1
  12. {ultraplot-2.1.5 → ultraplot-2.2.0}/tools/release/publish_zenodo.py +62 -5
  13. ultraplot-2.2.0/tools/release/sync_citation.py +168 -0
  14. ultraplot-2.2.0/ultraplot/_version.py +1 -0
  15. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/base.py +81 -7
  16. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/geo.py +133 -73
  17. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/plot.py +51 -21
  18. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/plot_types/curved_quiver.py +42 -13
  19. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/figure.py +447 -81
  20. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/gridspec.py +44 -20
  21. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/labels.py +1 -3
  22. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_axes.py +31 -0
  23. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_colorbar.py +364 -0
  24. ultraplot-2.2.0/ultraplot/tests/test_docs_fetch_releases.py +172 -0
  25. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_figure.py +407 -0
  26. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_gridspec.py +145 -0
  27. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_plot.py +95 -2
  28. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_release_metadata.py +66 -41
  29. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_subplots.py +38 -0
  30. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_ultralayout.py +20 -0
  31. {ultraplot-2.1.5 → ultraplot-2.2.0/ultraplot.egg-info}/PKG-INFO +2 -2
  32. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot.egg-info/SOURCES.txt +2 -1
  33. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot.egg-info/requires.txt +1 -1
  34. ultraplot-2.1.5/AGENTS.md +0 -21
  35. ultraplot-2.1.5/docs/_scripts/fetch_releases.py +0 -139
  36. ultraplot-2.1.5/ultraplot/_version.py +0 -1
  37. {ultraplot-2.1.5 → ultraplot-2.2.0}/.github/ISSUE_TEMPLATE.md +0 -0
  38. {ultraplot-2.1.5 → ultraplot-2.2.0}/.github/dependabot.yml +0 -0
  39. {ultraplot-2.1.5 → ultraplot-2.2.0}/.github/micromamba-condarc.yml +0 -0
  40. {ultraplot-2.1.5 → ultraplot-2.2.0}/.gitignore +0 -0
  41. {ultraplot-2.1.5 → ultraplot-2.2.0}/.readthedocs.yml +0 -0
  42. {ultraplot-2.1.5 → ultraplot-2.2.0}/CODEOFCONDUCT.md +0 -0
  43. {ultraplot-2.1.5 → ultraplot-2.2.0}/CONTRIBUTING.rst +0 -0
  44. {ultraplot-2.1.5 → ultraplot-2.2.0}/INSTALL.rst +0 -0
  45. {ultraplot-2.1.5 → ultraplot-2.2.0}/LICENSE.txt +0 -0
  46. {ultraplot-2.1.5 → ultraplot-2.2.0}/README.rst +0 -0
  47. {ultraplot-2.1.5 → ultraplot-2.2.0}/UltraPlotLogo.svg +0 -0
  48. {ultraplot-2.1.5 → ultraplot-2.2.0}/codecov.yml +0 -0
  49. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/1dplots.py +0 -0
  50. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/2dplots.py +0 -0
  51. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/Makefile +0 -0
  52. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_ext/notoc.py +0 -0
  53. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/custom.js +0 -0
  54. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/example_plots/cartesian_example.svg +0 -0
  55. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/example_plots/colorbars_legends_example.svg +0 -0
  56. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/example_plots/colormaps_example.svg +0 -0
  57. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/example_plots/panels_example.svg +0 -0
  58. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/example_plots/projection_example.svg +0 -0
  59. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/example_plots/subplot_example.svg +0 -0
  60. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/logo_blank.svg +0 -0
  61. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/logo_long.png +0 -0
  62. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/logo_long.svg +0 -0
  63. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/logo_social.png +0 -0
  64. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/logo_social.svg +0 -0
  65. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_static/logo_square.png +0 -0
  66. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/_templates/whatsnew_sidebar.html +0 -0
  67. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/about.rst +0 -0
  68. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/api.rst +0 -0
  69. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/basics.py +0 -0
  70. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/cartesian.py +0 -0
  71. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/colorbars_legends.py +0 -0
  72. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/colormaps.py +0 -0
  73. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/colors.py +0 -0
  74. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/conf.py +0 -0
  75. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/configuration.rst +0 -0
  76. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/contributing.rst +0 -0
  77. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/cycles.py +0 -0
  78. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/README.txt +0 -0
  79. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/colors/01_cycle_colormap.py +0 -0
  80. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/colors/02_diverging_colormap.py +0 -0
  81. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/colors/README.txt +0 -0
  82. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/geo/01_robin_tracks.py +0 -0
  83. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/geo/02_orthographic_views.py +0 -0
  84. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/geo/03_projections_features.py +0 -0
  85. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/geo/04_choropleth.py +0 -0
  86. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/geo/README.txt +0 -0
  87. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/layouts/01_shared_axes_abc.py +0 -0
  88. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/layouts/02_complex_layout_insets.py +0 -0
  89. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/layouts/03_spanning_labels.py +0 -0
  90. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/layouts/README.txt +0 -0
  91. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/legends_colorbars/01_multi_colorbars.py +0 -0
  92. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/legends_colorbars/02_legend_inset_colorbar.py +0 -0
  93. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/legends_colorbars/03_semantic_legends.py +0 -0
  94. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/legends_colorbars/README.txt +0 -0
  95. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/01_curved_quiver.py +0 -0
  96. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/02_network_graph.py +0 -0
  97. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/03_lollipop.py +0 -0
  98. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/04_datetime_series.py +0 -0
  99. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/05_box_violin.py +0 -0
  100. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/06_ridge_plot.py +0 -0
  101. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/07_radar.py +0 -0
  102. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/07_sankey.py +0 -0
  103. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/08_chord_diagram.py +0 -0
  104. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/08_ternary.py +0 -0
  105. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/09_phylogeny.py +0 -0
  106. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/10_circos_bed.py +0 -0
  107. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/11_topic_ribbon.py +0 -0
  108. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/examples/plot_types/README.txt +0 -0
  109. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/external-links.rst +0 -0
  110. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/faq.rst +0 -0
  111. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/fonts.py +0 -0
  112. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/index.rst +0 -0
  113. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/insets_panels.py +0 -0
  114. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/install.rst +0 -0
  115. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/lazy_loading.rst +0 -0
  116. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/make.bat +0 -0
  117. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/networks.py +0 -0
  118. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/projections.py +0 -0
  119. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/requirements-rtd.txt +0 -0
  120. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/sphinxext/custom_roles.py +0 -0
  121. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/sphinxext/jupytext_cache.py +0 -0
  122. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/stats.py +0 -0
  123. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/subplots.py +0 -0
  124. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/ultraplotrc +0 -0
  125. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/usage.rst +0 -0
  126. {ultraplot-2.1.5 → ultraplot-2.2.0}/docs/why.rst +0 -0
  127. {ultraplot-2.1.5 → ultraplot-2.2.0}/logo/PermanentMarker-Regular.ttf +0 -0
  128. {ultraplot-2.1.5 → ultraplot-2.2.0}/logo/environment-logo.yml +0 -0
  129. {ultraplot-2.1.5 → ultraplot-2.2.0}/logo/logo.py +0 -0
  130. {ultraplot-2.1.5 → ultraplot-2.2.0}/logo/run-linter.sh +0 -0
  131. {ultraplot-2.1.5 → ultraplot-2.2.0}/logo/webicon.py +0 -0
  132. {ultraplot-2.1.5 → ultraplot-2.2.0}/logo/whyUltraPlot.svg +0 -0
  133. {ultraplot-2.1.5 → ultraplot-2.2.0}/noxfile.py +0 -0
  134. {ultraplot-2.1.5 → ultraplot-2.2.0}/requirements-minimal.txt +0 -0
  135. {ultraplot-2.1.5 → ultraplot-2.2.0}/setup.cfg +0 -0
  136. {ultraplot-2.1.5 → ultraplot-2.2.0}/tools/ci/build_test_map.py +0 -0
  137. {ultraplot-2.1.5 → ultraplot-2.2.0}/tools/ci/select_tests.py +0 -0
  138. {ultraplot-2.1.5 → ultraplot-2.2.0}/tools/ci/version_support.py +0 -0
  139. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/__init__.py +0 -0
  140. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/_lazy.py +0 -0
  141. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/__init__.py +0 -0
  142. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/cartesian.py +0 -0
  143. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/container.py +0 -0
  144. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/plot_types/__init__.py +0 -0
  145. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/plot_types/circlize.py +0 -0
  146. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/plot_types/ribbon.py +0 -0
  147. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/plot_types/sankey.py +0 -0
  148. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/polar.py +0 -0
  149. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/shared.py +0 -0
  150. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/axes/three.py +0 -0
  151. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Algae.rgb +0 -0
  152. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Amp.rgb +0 -0
  153. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/BR.rgb +0 -0
  154. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Balance.rgb +0 -0
  155. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues1_r.xml +0 -0
  156. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues2.xml +0 -0
  157. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues3.xml +0 -0
  158. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues4_r.xml +0 -0
  159. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues5.xml +0 -0
  160. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues6.xml +0 -0
  161. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues7.xml +0 -0
  162. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues8.xml +0 -0
  163. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Blues9.xml +0 -0
  164. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Boreal.json +0 -0
  165. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns1.xml +0 -0
  166. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns2.xml +0 -0
  167. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns3.xml +0 -0
  168. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns4.xml +0 -0
  169. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns5.xml +0 -0
  170. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns6.xml +0 -0
  171. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns7.xml +0 -0
  172. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns8.xml +0 -0
  173. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Browns9.xml +0 -0
  174. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/ColdHot.rgb +0 -0
  175. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Crest.rgb +0 -0
  176. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Curl.rgb +0 -0
  177. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Deep.rgb +0 -0
  178. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Delta.rgb +0 -0
  179. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Dense.rgb +0 -0
  180. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Div.json +0 -0
  181. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/DryWet.json +0 -0
  182. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Dusk.json +0 -0
  183. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Fire.json +0 -0
  184. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Flare.rgb +0 -0
  185. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Glacial.json +0 -0
  186. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens1_r.xml +0 -0
  187. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens2.xml +0 -0
  188. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens3_r.xml +0 -0
  189. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens4.xml +0 -0
  190. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens5.xml +0 -0
  191. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens6_r.xml +0 -0
  192. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens7.xml +0 -0
  193. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Greens8.xml +0 -0
  194. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Haline.rgb +0 -0
  195. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Ice.rgb +0 -0
  196. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/IceFire.rgb +0 -0
  197. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Mako.rgb +0 -0
  198. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Marine.json +0 -0
  199. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Matter.rgb +0 -0
  200. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Mono.txt +0 -0
  201. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/MonoCycle.txt +0 -0
  202. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/NegPos.json +0 -0
  203. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Oranges1.xml +0 -0
  204. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Oranges2.xml +0 -0
  205. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Oranges3.xml +0 -0
  206. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Oranges4.xml +0 -0
  207. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Oxy.rgb +0 -0
  208. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Phase.rgb +0 -0
  209. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Purples1_r.xml +0 -0
  210. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Purples2.xml +0 -0
  211. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Purples3.xml +0 -0
  212. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Reds1.xml +0 -0
  213. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Reds2.xml +0 -0
  214. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Reds3.xml +0 -0
  215. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Reds4.xml +0 -0
  216. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Reds5.xml +0 -0
  217. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Rocket.rgb +0 -0
  218. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Solar.rgb +0 -0
  219. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Speed.rgb +0 -0
  220. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Stellar.json +0 -0
  221. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Sunrise.json +0 -0
  222. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Sunset.json +0 -0
  223. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Tempo.rgb +0 -0
  224. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Thermal.rgb +0 -0
  225. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Turbid.rgb +0 -0
  226. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Vivid.xml +0 -0
  227. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Vlag.rgb +0 -0
  228. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Yellows1.xml +0 -0
  229. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Yellows2.xml +0 -0
  230. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Yellows3.xml +0 -0
  231. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/Yellows4.xml +0 -0
  232. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/acton.txt +0 -0
  233. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/bam.txt +0 -0
  234. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/bamO.txt +0 -0
  235. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/bamako.txt +0 -0
  236. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/batlow.txt +0 -0
  237. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/batlowK.txt +0 -0
  238. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/batlowW.txt +0 -0
  239. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/berlin.txt +0 -0
  240. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/bilbao.txt +0 -0
  241. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/broc.txt +0 -0
  242. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/brocO.txt +0 -0
  243. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/buda.txt +0 -0
  244. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/bukavu.txt +0 -0
  245. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/cork.txt +0 -0
  246. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/corkO.txt +0 -0
  247. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/davos.txt +0 -0
  248. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/devon.txt +0 -0
  249. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/fes.txt +0 -0
  250. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/hawaii.txt +0 -0
  251. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/imola.txt +0 -0
  252. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/lajolla.txt +0 -0
  253. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/lapaz.txt +0 -0
  254. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/lisbon.txt +0 -0
  255. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/nuuk.txt +0 -0
  256. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/oleron.txt +0 -0
  257. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/oslo.txt +0 -0
  258. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/roma.txt +0 -0
  259. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/romaO.txt +0 -0
  260. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/tofino.txt +0 -0
  261. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/tokyo.txt +0 -0
  262. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/turku.txt +0 -0
  263. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/vanimo.txt +0 -0
  264. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/vik.txt +0 -0
  265. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cmaps/vikO.txt +0 -0
  266. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/colorbar.py +0 -0
  267. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/colors/opencolor.txt +0 -0
  268. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/colors/xkcd.txt +0 -0
  269. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/colors.py +0 -0
  270. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/config.py +0 -0
  271. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/constructor.py +0 -0
  272. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/538.hex +0 -0
  273. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/FlatUI.hex +0 -0
  274. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/Qual1.rgb +0 -0
  275. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/Qual2.rgb +0 -0
  276. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/bmh.hex +0 -0
  277. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/classic.hex +0 -0
  278. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/colorblind.hex +0 -0
  279. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/colorblind10.hex +0 -0
  280. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/default.hex +0 -0
  281. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/ggplot.hex +0 -0
  282. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/seaborn.hex +0 -0
  283. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/cycles/tableau.hex +0 -0
  284. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/demos.py +0 -0
  285. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/externals/__init__.py +0 -0
  286. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/externals/hsluv.py +0 -0
  287. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-Bold.ttf +0 -0
  288. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-ExtraLight.ttf +0 -0
  289. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-Heavy.ttf +0 -0
  290. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-Light.ttf +0 -0
  291. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-Medium.ttf +0 -0
  292. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-Regular.ttf +0 -0
  293. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-SemiBold.ttf +0 -0
  294. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraMath-UltraLight.ttf +0 -0
  295. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-Black.ttf +0 -0
  296. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-BlackItalic.ttf +0 -0
  297. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-Bold.ttf +0 -0
  298. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-BoldItalic.ttf +0 -0
  299. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-ExtraBold.ttf +0 -0
  300. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-ExtraBoldItalic.ttf +0 -0
  301. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-ExtraLight.ttf +0 -0
  302. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-ExtraLightItalic.ttf +0 -0
  303. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-Italic.ttf +0 -0
  304. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-Light.ttf +0 -0
  305. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-LightItalic.ttf +0 -0
  306. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-Medium.ttf +0 -0
  307. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-MediumItalic.ttf +0 -0
  308. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-Regular.ttf +0 -0
  309. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-SemiBold.ttf +0 -0
  310. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/FiraSans-SemiBoldItalic.ttf +0 -0
  311. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_FIRAMATH.txt +0 -0
  312. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_FIRASANS.txt +0 -0
  313. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_NOTOSANS.txt +0 -0
  314. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_NOTOSERIF.txt +0 -0
  315. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_OPENSANS.txt +0 -0
  316. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_ROBOTO.txt +0 -0
  317. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_SOURCESANS.txt +0 -0
  318. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_SOURCESERIF.txt +0 -0
  319. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_TEXGYRE.txt +0 -0
  320. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/LICENSE_UBUNTU.txt +0 -0
  321. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSans-Bold.ttf +0 -0
  322. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSans-BoldItalic.ttf +0 -0
  323. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSans-Italic.ttf +0 -0
  324. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSans-Regular.ttf +0 -0
  325. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSerif-Bold.ttf +0 -0
  326. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSerif-BoldItalic.ttf +0 -0
  327. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSerif-Italic.ttf +0 -0
  328. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/NotoSerif-Regular.ttf +0 -0
  329. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/OpenSans-Bold.ttf +0 -0
  330. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/OpenSans-BoldItalic.ttf +0 -0
  331. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/OpenSans-Italic.ttf +0 -0
  332. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/OpenSans-Regular.ttf +0 -0
  333. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/OpenSans-Semibold.ttf +0 -0
  334. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/OpenSans-SemiboldItalic.ttf +0 -0
  335. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-Black.ttf +0 -0
  336. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-BlackItalic.ttf +0 -0
  337. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-Bold.ttf +0 -0
  338. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-BoldItalic.ttf +0 -0
  339. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-Italic.ttf +0 -0
  340. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-Light.ttf +0 -0
  341. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-LightItalic.ttf +0 -0
  342. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-Medium.ttf +0 -0
  343. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-MediumItalic.ttf +0 -0
  344. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Roboto-Regular.ttf +0 -0
  345. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-Black.ttf +0 -0
  346. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-BlackItalic.ttf +0 -0
  347. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-Bold.ttf +0 -0
  348. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-BoldItalic.ttf +0 -0
  349. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-ExtraLight.ttf +0 -0
  350. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-ExtraLightItalic.ttf +0 -0
  351. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-Italic.ttf +0 -0
  352. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-Light.ttf +0 -0
  353. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-LightItalic.ttf +0 -0
  354. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-Regular.ttf +0 -0
  355. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-SemiBold.ttf +0 -0
  356. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSansPro-SemiBoldItalic.ttf +0 -0
  357. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-Black.ttf +0 -0
  358. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-BlackItalic.ttf +0 -0
  359. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-Bold.ttf +0 -0
  360. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-BoldItalic.ttf +0 -0
  361. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-ExtraLight.ttf +0 -0
  362. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-ExtraLightItalic.ttf +0 -0
  363. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-Italic.ttf +0 -0
  364. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-Light.ttf +0 -0
  365. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-LightItalic.ttf +0 -0
  366. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-Regular.ttf +0 -0
  367. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-SemiBold.ttf +0 -0
  368. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/SourceSerifPro-SemiBoldItalic.ttf +0 -0
  369. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-Bold.ttf +0 -0
  370. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-BoldItalic.ttf +0 -0
  371. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-Italic.ttf +0 -0
  372. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-Light.ttf +0 -0
  373. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-LightItalic.ttf +0 -0
  374. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-Medium.ttf +0 -0
  375. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-MediumItalic.ttf +0 -0
  376. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/Ubuntu-Regular.ttf +0 -0
  377. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreadventor-bold.ttf +0 -0
  378. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreadventor-bolditalic.ttf +0 -0
  379. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreadventor-italic.ttf +0 -0
  380. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreadventor-regular.ttf +0 -0
  381. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrebonum-bold.ttf +0 -0
  382. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrebonum-bolditalic.ttf +0 -0
  383. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrebonum-italic.ttf +0 -0
  384. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrebonum-regular.ttf +0 -0
  385. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrechorus-mediumitalic.ttf +0 -0
  386. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrecursor-bold.ttf +0 -0
  387. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrecursor-bolditalic.ttf +0 -0
  388. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrecursor-italic.ttf +0 -0
  389. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrecursor-regular.ttf +0 -0
  390. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreheros-bold.ttf +0 -0
  391. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreheros-bolditalic.ttf +0 -0
  392. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreheros-italic.ttf +0 -0
  393. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreheros-regular.ttf +0 -0
  394. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrepagella-bold.ttf +0 -0
  395. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrepagella-bolditalic.ttf +0 -0
  396. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrepagella-italic.ttf +0 -0
  397. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyrepagella-regular.ttf +0 -0
  398. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreschola-bold.ttf +0 -0
  399. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreschola-bolditalic.ttf +0 -0
  400. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreschola-italic.ttf +0 -0
  401. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyreschola-regular.ttf +0 -0
  402. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyretermes-bold.ttf +0 -0
  403. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyretermes-bolditalic.ttf +0 -0
  404. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyretermes-italic.ttf +0 -0
  405. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/fonts/texgyretermes-regular.ttf +0 -0
  406. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/__init__.py +0 -0
  407. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/benchmarks.py +0 -0
  408. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/context.py +0 -0
  409. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/docstring.py +0 -0
  410. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/fonts.py +0 -0
  411. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/guides.py +0 -0
  412. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/inputs.py +0 -0
  413. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/rcsetup.py +0 -0
  414. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/versions.py +0 -0
  415. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/internals/warnings.py +0 -0
  416. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/legend.py +0 -0
  417. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/proj.py +0 -0
  418. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/scale.py +0 -0
  419. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/__init__.py +0 -0
  420. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/conftest.py +0 -0
  421. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_1dplots.py +0 -0
  422. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_2dplots.py +0 -0
  423. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_animation.py +0 -0
  424. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_axes_base_colorbar_helpers.py +0 -0
  425. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_base.py +0 -0
  426. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_circlize_integration.py +0 -0
  427. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_colorbar_helpers_extra.py +0 -0
  428. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_colormap.py +0 -0
  429. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_colormap_helpers_extra.py +0 -0
  430. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_colors.py +0 -0
  431. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_colors_helpers.py +0 -0
  432. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_config.py +0 -0
  433. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_config_helpers_extra.py +0 -0
  434. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_constructor.py +0 -0
  435. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_constructor_helpers_extra.py +0 -0
  436. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_core_versions.py +0 -0
  437. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_demos.py +0 -0
  438. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_docs.py +0 -0
  439. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_external_axes_container_integration.py +0 -0
  440. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_external_container_edge_cases.py +0 -0
  441. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_external_container_mocked.py +0 -0
  442. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_fonts.py +0 -0
  443. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_format.py +0 -0
  444. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_geographic.py +0 -0
  445. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_handlers.py +0 -0
  446. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_imports.py +0 -0
  447. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_imshow.py +0 -0
  448. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_inputs.py +0 -0
  449. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_inputs_helpers.py +0 -0
  450. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_inset.py +0 -0
  451. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_integration.py +0 -0
  452. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_legend.py +0 -0
  453. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_proj_helpers.py +0 -0
  454. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_projections.py +0 -0
  455. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_rcsetup_helpers.py +0 -0
  456. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_scale_helpers.py +0 -0
  457. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_statistical_plotting.py +0 -0
  458. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_text_helpers.py +0 -0
  459. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/tests/test_tickers.py +0 -0
  460. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/text.py +0 -0
  461. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/ticker.py +0 -0
  462. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/ui.py +0 -0
  463. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/ultralayout.py +0 -0
  464. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot/utils.py +0 -0
  465. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot.egg-info/dependency_links.txt +0 -0
  466. {ultraplot-2.1.5 → ultraplot-2.2.0}/ultraplot.egg-info/top_level.txt +0 -0
@@ -53,7 +53,7 @@ jobs:
53
53
  with:
54
54
  fetch-depth: 0
55
55
 
56
- - uses: mamba-org/setup-micromamba@v2.0.7
56
+ - uses: mamba-org/setup-micromamba@v3.0.0
57
57
  with:
58
58
  environment-file: ./environment.yml
59
59
  init-shell: bash
@@ -100,7 +100,7 @@ jobs:
100
100
 
101
101
  - uses: actions/checkout@v6
102
102
 
103
- - uses: mamba-org/setup-micromamba@v2.0.7
103
+ - uses: mamba-org/setup-micromamba@v3.0.0
104
104
  with:
105
105
  environment-file: ./environment.yml
106
106
  init-shell: bash
@@ -50,7 +50,7 @@ jobs:
50
50
 
51
51
  - name: Build test map on cache miss
52
52
  if: steps.restore-map.outputs.cache-hit != 'true'
53
- uses: mamba-org/setup-micromamba@v2.0.7
53
+ uses: mamba-org/setup-micromamba@v3.0.0
54
54
  with:
55
55
  environment-file: ./environment.yml
56
56
  init-shell: bash
@@ -157,7 +157,7 @@ jobs:
157
157
  with:
158
158
  fetch-depth: 0
159
159
 
160
- - uses: mamba-org/setup-micromamba@v2.0.7
160
+ - uses: mamba-org/setup-micromamba@v3.0.0
161
161
  with:
162
162
  environment-file: ./environment.yml
163
163
  init-shell: bash
@@ -182,7 +182,7 @@ jobs:
182
182
  ultraplot/tests
183
183
 
184
184
  - name: Upload coverage reports to Codecov
185
- uses: codecov/codecov-action@v5
185
+ uses: codecov/codecov-action@v6
186
186
  with:
187
187
  token: ${{ secrets.CODECOV_TOKEN }}
188
188
  files: ./coverage.xml
@@ -1,11 +1,12 @@
1
1
  name: Publish to PyPI
2
+
2
3
  on:
3
4
  pull_request:
4
5
  push:
5
6
  tags: ["v*"]
6
7
 
7
8
  concurrency:
8
- group: publish-pypi-{{ github.sha }}
9
+ group: publish-pypi-${{ github.sha }}
9
10
  cancel-in-progress: false
10
11
 
11
12
  jobs:
@@ -17,22 +18,25 @@ jobs:
17
18
  with:
18
19
  fetch-depth: 0
19
20
 
20
- - name: Get tags
21
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
22
- shell: bash
23
-
24
21
  - uses: actions/setup-python@v6
25
22
  with:
26
23
  python-version: "3.12"
27
24
 
25
+ - name: Ensure clean tree before build
26
+ run: |
27
+ git diff --quiet || (git status --short && git diff && exit 1)
28
+ shell: bash
29
+
28
30
  - name: Build package
29
31
  run: |
30
- python -m pip install --upgrade pip wheel setuptools setuptools_scm build twine
32
+ python -m pip install --upgrade pip
33
+ python -m pip install wheel setuptools setuptools_scm build twine
31
34
  python -m build --sdist --wheel . --outdir dist
35
+ shell: bash
32
36
 
33
37
  - name: Check files
34
38
  run: |
35
- ls dist
39
+ ls -lah dist
36
40
  shell: bash
37
41
 
38
42
  - name: Test wheels
@@ -78,7 +82,7 @@ jobs:
78
82
 
79
83
  - name: Check files
80
84
  run: |
81
- ls dist
85
+ ls -lah dist
82
86
  shell: bash
83
87
 
84
88
  - name: Publish to TestPyPI
@@ -91,11 +95,11 @@ jobs:
91
95
  publish-pypi:
92
96
  name: Publish to PyPI
93
97
  needs: publish-pypi-test
98
+ if: github.event_name == 'push'
94
99
  environment:
95
100
  name: prod
96
101
  url: https://pypi.org/project/ultraplot/
97
102
  runs-on: ubuntu-latest
98
- if: github.event_name == 'push'
99
103
  permissions:
100
104
  id-token: write
101
105
  contents: read
@@ -108,7 +112,7 @@ jobs:
108
112
 
109
113
  - name: Check files
110
114
  run: |
111
- ls dist
115
+ ls -lah dist
112
116
  shell: bash
113
117
 
114
118
  - name: Publish to PyPI
@@ -141,6 +145,8 @@ jobs:
141
145
  ZENODO_ACCESS_TOKEN: ${{ secrets.ZENODO_ACCESS_TOKEN }}
142
146
  steps:
143
147
  - uses: actions/checkout@v6
148
+ with:
149
+ fetch-depth: 0
144
150
 
145
151
  - uses: actions/setup-python@v6
146
152
  with:
@@ -148,7 +154,8 @@ jobs:
148
154
 
149
155
  - name: Install release tooling
150
156
  run: |
151
- python -m pip install --upgrade pip PyYAML
157
+ python -m pip install --upgrade pip
158
+ python -m pip install PyYAML
152
159
  shell: bash
153
160
 
154
161
  - name: Download artifacts
@@ -157,7 +164,21 @@ jobs:
157
164
  name: dist-${{ github.sha }}-${{ github.run_id }}-${{ github.run_number }}
158
165
  path: dist
159
166
 
167
+ - name: Generate release citation metadata
168
+ run: |
169
+ python tools/release/sync_citation.py \
170
+ --tag "${GITHUB_REF_NAME}" \
171
+ --output "${RUNNER_TEMP}/CITATION.cff"
172
+ shell: bash
173
+
174
+ - name: Check tree stayed clean
175
+ run: |
176
+ git diff --quiet || (git status --short && git diff && exit 1)
177
+ shell: bash
178
+
160
179
  - name: Publish to Zenodo
161
180
  run: |
162
- python tools/release/publish_zenodo.py --dist-dir dist
181
+ python tools/release/publish_zenodo.py \
182
+ --dist-dir dist \
183
+ --citation-file "${RUNNER_TEMP}/CITATION.cff"
163
184
  shell: bash
@@ -23,7 +23,7 @@ jobs:
23
23
  with:
24
24
  fetch-depth: 0
25
25
 
26
- - uses: mamba-org/setup-micromamba@v2.0.7
26
+ - uses: mamba-org/setup-micromamba@v3.0.0
27
27
  with:
28
28
  environment-file: ./environment.yml
29
29
  init-shell: bash
@@ -48,7 +48,7 @@ jobs:
48
48
  python tools/ci/build_test_map.py --coverage-file .coverage --output .ci/test-map.json --root .
49
49
 
50
50
  - name: Upload coverage reports to Codecov
51
- uses: codecov/codecov-action@v5
51
+ uses: codecov/codecov-action@v6
52
52
  with:
53
53
  token: ${{ secrets.CODECOV_TOKEN }}
54
54
  files: ./coverage.xml
@@ -11,6 +11,6 @@ ci:
11
11
 
12
12
  repos:
13
13
  - repo: https://github.com/psf/black-pre-commit-mirror
14
- rev: 26.1.0
14
+ rev: 26.3.1
15
15
  hooks:
16
16
  - id: black
@@ -8,8 +8,8 @@ authors:
8
8
  - family-names: "Becker"
9
9
  given-names: "Matthew R."
10
10
  orcid: "https://orcid.org/0000-0001-7774-2246"
11
- date-released: "2026-03-11"
12
- version: "2.1.3"
11
+ date-released: "2026-03-30"
12
+ version: "2.1.5"
13
13
  doi: "10.5281/zenodo.15733564"
14
14
  repository-code: "https://github.com/Ultraplot/UltraPlot"
15
15
  license: "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ultraplot
3
- Version: 2.1.5
3
+ Version: 2.2.0
4
4
  Summary: A succinct matplotlib wrapper for making beautiful, publication-quality graphics.
5
5
  Author-email: Casper van Elteren <caspervanelteren@gmail.com>, Luke Davis <lukelbd@gmail.com>
6
6
  Maintainer-email: Casper van Elteren <caspervanelteren@gmail.com>, "Matthew R. Becker" <becker.mr@gmail.com>
@@ -29,7 +29,7 @@ Provides-Extra: docs
29
29
  Requires-Dist: jupyter; extra == "docs"
30
30
  Requires-Dist: jupytext; extra == "docs"
31
31
  Requires-Dist: lxml-html-clean; extra == "docs"
32
- Requires-Dist: m2r2; extra == "docs"
32
+ Requires-Dist: markdown; extra == "docs"
33
33
  Requires-Dist: mpltern; extra == "docs"
34
34
  Requires-Dist: nbsphinx; extra == "docs"
35
35
  Requires-Dist: sphinx; extra == "docs"
@@ -0,0 +1,154 @@
1
+ """
2
+ Dynamically build the "What's new?" page from the GitHub releases feed.
3
+
4
+ The release notes on GitHub are written in Markdown and frequently mix raw
5
+ HTML (``<details><summary>`` blocks wrapping fenced code samples). The
6
+ previous implementation converted the body to RST via ``m2r2``, which left
7
+ the inner Markdown code fences inside ``.. raw:: html`` directives — Sphinx
8
+ then rendered them as literal text. This module instead converts each
9
+ release body to HTML (so fences become ``<pre><code>`` elements) and emits
10
+ a single ``.. raw:: html`` block per release wrapped in a styling hook
11
+ ``div.uplt-whats-new-release-body``.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import re
17
+ from pathlib import Path
18
+ from typing import Iterable
19
+
20
+ import markdown
21
+ import requests
22
+
23
+ GITHUB_REPO = "ultraplot/ultraplot"
24
+ OUTPUT_RST = Path("whats_new.rst")
25
+ GITHUB_API_URL = f"https://api.github.com/repos/{GITHUB_REPO}/releases"
26
+
27
+ # Markdown extensions: fenced code (for ```python blocks), tables, attribute
28
+ # lists for class hooks, and md_in_html so block-level HTML such as
29
+ # ``<details>`` correctly contains parsed Markdown children.
30
+ _MD_EXTENSIONS = ("fenced_code", "tables", "attr_list", "md_in_html")
31
+
32
+ # Strip the trailing "by @user in PR_URL" attribution that GitHub auto-adds
33
+ # to release notes. Keep the PR link in parentheses so credit/traceability
34
+ # remains while removing the contributor handles from rendered output.
35
+ # GitHub author handles can include ``[bot]`` suffixes (``@dependabot[bot]``,
36
+ # ``@pre-commit-ci[bot]``); ``\w`` alone misses the brackets.
37
+ _PR_ATTRIBUTION = re.compile(
38
+ r" by @[\w.\-]+(?:\[bot\])? in (https://github\.com/[^\s]+)"
39
+ )
40
+
41
+ # Match an ATX heading line, tolerating up-to-3 leading spaces. Authors
42
+ # occasionally indent whole sections by two spaces in the GitHub release
43
+ # editor (e.g. v2.0.1's "### Layout, Rendering, and Geo Improvements"),
44
+ # which python-markdown then parses as a paragraph rather than a heading.
45
+ # We capture the ``#`` run so we can both strip the indent and downgrade
46
+ # one level — the page already provides the H1 ("What's new?") and each
47
+ # release contributes a per-release RST H2, so body headings start at H2.
48
+ _ATX_HEADING = re.compile(r"^[ ]{0,3}(#{1,5})(?=\s)", flags=re.MULTILINE)
49
+
50
+
51
+ def _strip_pr_attribution(text: str) -> str:
52
+ return _PR_ATTRIBUTION.sub(r" (\1)", text)
53
+
54
+
55
+ def _downgrade_headings(text: str) -> str:
56
+ """Demote every Markdown ATX heading by one level (``#`` → ``##``, etc.)."""
57
+ return _ATX_HEADING.sub(lambda m: "#" + m.group(1), text)
58
+
59
+
60
+ def _normalize_unicode(text: str) -> str:
61
+ return text.replace("→", "->")
62
+
63
+
64
+ def _indent_html(html: str, indent: str = " ") -> str:
65
+ """Indent every line of ``html`` by ``indent`` for inclusion under ``.. raw:: html``."""
66
+ return "\n".join(indent + line if line else line for line in html.splitlines())
67
+
68
+
69
+ def format_release_body(text: str) -> str:
70
+ """
71
+ Convert a GitHub release body (Markdown + embedded HTML) into an RST
72
+ ``.. raw:: html`` block wrapped in ``div.uplt-whats-new-release-body``.
73
+
74
+ Parameters
75
+ ----------
76
+ text : str
77
+ Raw Markdown release body as returned by the GitHub releases API.
78
+
79
+ Returns
80
+ -------
81
+ str
82
+ Indented RST snippet ready to be appended to ``whats_new.rst``.
83
+ """
84
+ cleaned = _downgrade_headings(
85
+ _normalize_unicode(_strip_pr_attribution(text or ""))
86
+ ).strip()
87
+ html_body = markdown.markdown(cleaned, extensions=list(_MD_EXTENSIONS))
88
+ wrapped = f'<div class="uplt-whats-new-release-body">\n{html_body}\n</div>'
89
+ return ".. raw:: html\n\n" + _indent_html(wrapped) + "\n"
90
+
91
+
92
+ def _format_release_title(release: dict) -> str:
93
+ """
94
+ Build the per-release section title in ``"<tag>: <name>"`` form,
95
+ de-duplicating the tag if it is already a prefix of the release name.
96
+ """
97
+ tag = release["tag_name"].lower()
98
+ title = (release.get("name") or "").strip()
99
+ if title.lower().startswith(tag):
100
+ title = title[len(tag) :].lstrip(" :-—–")
101
+ return f"{tag}: {title}" if title else tag
102
+
103
+
104
+ def fetch_all_releases() -> list[dict]:
105
+ """Fetch every GitHub release across paginated responses."""
106
+ releases: list[dict] = []
107
+ page = 1
108
+ while True:
109
+ response = requests.get(GITHUB_API_URL, params={"per_page": 30, "page": page})
110
+ if response.status_code != 200:
111
+ print(f"Error fetching releases: {response.status_code}")
112
+ break
113
+ page_data = response.json()
114
+ if not page_data:
115
+ break
116
+ releases.extend(page_data)
117
+ page += 1
118
+ return releases
119
+
120
+
121
+ def _render_releases(releases: Iterable[dict]) -> str:
122
+ """Render an iterable of release dicts to the full ``whats_new.rst`` body."""
123
+ header = "What's new?"
124
+ out = f".. _whats_new:\n\n{header}\n{'=' * len(header)}\n\n"
125
+ for release in releases:
126
+ title = _format_release_title(release)
127
+ date = release["published_at"][:10]
128
+ heading = f"{title} ({date})"
129
+ out += f"{heading}\n{'-' * len(heading)}\n\n"
130
+ out += format_release_body(release.get("body") or "") + "\n"
131
+ return out
132
+
133
+
134
+ def fetch_releases() -> str:
135
+ """Fetch the latest releases from GitHub and format them as RST."""
136
+ releases = fetch_all_releases()
137
+ if not releases:
138
+ print("Error fetching releases!")
139
+ return ""
140
+ return _render_releases(releases)
141
+
142
+
143
+ def write_rst() -> None:
144
+ """Write fetched releases to ``whats_new.rst``."""
145
+ content = fetch_releases()
146
+ if content:
147
+ OUTPUT_RST.write_text(content, encoding="utf-8")
148
+ print(f"Updated {OUTPUT_RST}")
149
+ else:
150
+ print("No updates to write.")
151
+
152
+
153
+ if __name__ == "__main__":
154
+ write_rst()
@@ -1212,3 +1212,41 @@ body.wy-body-for-nav
1212
1212
  border-radius: 0.2rem;
1213
1213
  background: var(--uplt-color-sidebar-bg);
1214
1214
  }
1215
+
1216
+ /* What's-new release bodies generated by docs/_scripts/fetch_releases.py.
1217
+ Each release is emitted inside a <div class="uplt-whats-new-release-body">
1218
+ so we have a single styling hook for spacing, code-block padding, and the
1219
+ <details> snippet affordance. */
1220
+ .uplt-whats-new-release-body {
1221
+ margin-top: 0.5rem;
1222
+ margin-bottom: 1.5rem;
1223
+ }
1224
+
1225
+ .uplt-whats-new-release-body h2,
1226
+ .uplt-whats-new-release-body h3,
1227
+ .uplt-whats-new-release-body h4 {
1228
+ margin-top: 1.25rem;
1229
+ margin-bottom: 0.5rem;
1230
+ }
1231
+
1232
+ .uplt-whats-new-release-body details {
1233
+ margin: 0.5rem 0 1rem;
1234
+ padding: 0.25rem 0.75rem;
1235
+ border: 1px solid var(--uplt-color-sidebar-bg, #e5e7eb);
1236
+ border-radius: 0.35rem;
1237
+ background: var(--uplt-color-sidebar-bg, #f9fafb);
1238
+ }
1239
+
1240
+ .uplt-whats-new-release-body details > summary {
1241
+ cursor: pointer;
1242
+ font-weight: 600;
1243
+ }
1244
+
1245
+ .uplt-whats-new-release-body pre {
1246
+ overflow-x: auto;
1247
+ }
1248
+
1249
+ .uplt-whats-new-release-body img {
1250
+ max-width: 100%;
1251
+ height: auto;
1252
+ }
@@ -20,5 +20,7 @@ dependencies:
20
20
  - networkx
21
21
  - pyarrow
22
22
  - cftime
23
+ - markdown
24
+ - requests
23
25
  - pip:
24
26
  - pycirclize
@@ -74,7 +74,7 @@ docs = [
74
74
  "jupyter",
75
75
  "jupytext",
76
76
  "lxml-html-clean",
77
- "m2r2",
77
+ "markdown",
78
78
  "mpltern",
79
79
  "nbsphinx",
80
80
  "sphinx",
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
 
4
4
  import argparse
5
5
  import json
6
- import mimetypes
7
6
  import os
8
7
  import sys
9
8
  from pathlib import Path
@@ -43,6 +42,12 @@ def parse_args() -> argparse.Namespace:
43
42
  default=Path("CITATION.cff"),
44
43
  help="Path to the repository CITATION.cff file.",
45
44
  )
45
+ parser.add_argument(
46
+ "--citation-file",
47
+ type=Path,
48
+ default=Path("CITATION.cff"),
49
+ help="Path to the citation metadata file to upload.",
50
+ )
46
51
  parser.add_argument(
47
52
  "--pyproject",
48
53
  type=Path,
@@ -244,14 +249,15 @@ def upload_dist_files(draft: dict, token: str, dist_dir: Path) -> None:
244
249
  for path in sorted(dist_dir.iterdir()):
245
250
  if not path.is_file():
246
251
  continue
247
- content_type = mimetypes.guess_type(path.name)[0] or "application/octet-stream"
248
252
  with path.open("rb") as handle:
249
253
  api_request(
250
254
  "PUT",
251
255
  f"{bucket_url}/{parse.quote(path.name)}",
252
256
  token=token,
253
257
  data=handle.read(),
254
- content_type=content_type,
258
+ # Zenodo bucket uploads reject extension-specific types like
259
+ # application/gzip for source tarballs and require raw bytes.
260
+ content_type="application/octet-stream",
255
261
  )
256
262
  print(f"Uploaded {path.name} to Zenodo draft {draft['id']}.")
257
263
 
@@ -282,19 +288,70 @@ def validate_inputs(dist_dir: Path, access_token: str | None) -> None:
282
288
  raise SystemExit(f"Distribution directory {dist_dir} does not contain files.")
283
289
 
284
290
 
291
+ def find_existing_draft(api_url: str, token: str, record_id: int) -> dict | None:
292
+ record = api_request("GET", f"{api_url}/records/{record_id}", token=token)
293
+ conceptrecid = str(record.get("conceptrecid") or record.get("id"))
294
+
295
+ page = 1
296
+ while True:
297
+ payload = api_request(
298
+ "GET",
299
+ f"{api_url}/deposit/depositions?page={page}&size=100",
300
+ token=token,
301
+ )
302
+
303
+ if not payload:
304
+ break
305
+
306
+ for dep in payload:
307
+ if str(dep.get("conceptrecid")) != conceptrecid:
308
+ continue
309
+ if dep.get("submitted"):
310
+ continue
311
+
312
+ print(f"Found existing draft deposition {dep['id']}")
313
+ return dep
314
+
315
+ if len(payload) < 100:
316
+ break
317
+
318
+ page += 1
319
+
320
+ return None
321
+
322
+
323
+ def get_or_create_draft(api_url: str, token: str, record_id: int) -> dict:
324
+ try:
325
+ return create_new_version(api_url, token, record_id)
326
+ except RuntimeError as exc:
327
+ message = str(exc)
328
+ if "files.enabled" not in message:
329
+ raise
330
+
331
+ draft = find_existing_draft(api_url, token, record_id)
332
+ if draft is None:
333
+ raise
334
+ print(f"Reusing existing Zenodo draft {draft['id']}.")
335
+ return draft
336
+
337
+
285
338
  def main() -> int:
286
339
  args = parse_args()
287
340
  validate_inputs(args.dist_dir, args.access_token)
288
- citation = load_citation(args.citation)
341
+
342
+ citation = load_citation(args.citation_file)
289
343
  pyproject = load_pyproject(args.pyproject)
290
344
  metadata = build_metadata(citation, pyproject)
345
+
291
346
  conceptrecid = resolve_concept_recid(args.api_url, citation["doi"])
292
347
  record_id = latest_record_id(args.api_url, conceptrecid)
293
- draft = create_new_version(args.api_url, args.access_token, record_id)
348
+
349
+ draft = get_or_create_draft(args.api_url, args.access_token, record_id)
294
350
  clear_draft_files(draft, args.access_token)
295
351
  upload_dist_files(draft, args.access_token, args.dist_dir)
296
352
  draft = update_metadata(draft, args.access_token, metadata)
297
353
  published = publish_draft(draft, args.access_token)
354
+
298
355
  doi = published.get("doi") or published.get("metadata", {}).get("doi")
299
356
  print(
300
357
  f"Published Zenodo release record {published['id']} for "