pysextant 1.1.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 (353) hide show
  1. pysextant-1.1.0/.github/workflows/teardown_bisect.yml +113 -0
  2. pysextant-1.1.0/.github/workflows/tests.yml +74 -0
  3. pysextant-1.1.0/.github/workflows/wheels.yml +220 -0
  4. pysextant-1.1.0/.gitignore +9 -0
  5. pysextant-1.1.0/.gitmodules +4 -0
  6. pysextant-1.1.0/.python-version +1 -0
  7. pysextant-1.1.0/CMakeLists.txt +72 -0
  8. pysextant-1.1.0/LICENSE +21 -0
  9. pysextant-1.1.0/PKG-INFO +128 -0
  10. pysextant-1.1.0/README.md +98 -0
  11. pysextant-1.1.0/doc/3d.md +415 -0
  12. pysextant-1.1.0/doc/README.md +12 -0
  13. pysextant-1.1.0/doc/api.md +950 -0
  14. pysextant-1.1.0/doc/install.md +248 -0
  15. pysextant-1.1.0/doc/pyplot.md +342 -0
  16. pysextant-1.1.0/doc/reference.md +614 -0
  17. pysextant-1.1.0/extern/sextant/.git +1 -0
  18. pysextant-1.1.0/extern/sextant/.github/workflows/ci.yml +391 -0
  19. pysextant-1.1.0/extern/sextant/.github/workflows/vcpkg-port.yml +130 -0
  20. pysextant-1.1.0/extern/sextant/.gitignore +69 -0
  21. pysextant-1.1.0/extern/sextant/CMakeLists.txt +823 -0
  22. pysextant-1.1.0/extern/sextant/LICENSE +21 -0
  23. pysextant-1.1.0/extern/sextant/README.md +331 -0
  24. pysextant-1.1.0/extern/sextant/THIRD_PARTY_NOTICES.md +54 -0
  25. pysextant-1.1.0/extern/sextant/cmake/freetype/sextant_hidden_api.h +15 -0
  26. pysextant-1.1.0/extern/sextant/cmake/glfw/0001-nsgl-software-renderer-fallback.patch +19 -0
  27. pysextant-1.1.0/extern/sextant/cmake/glfw/0002-nsgl-lock-context-around-update.patch +66 -0
  28. pysextant-1.1.0/extern/sextant/cmake/glfw/apply_patches.cmake +23 -0
  29. pysextant-1.1.0/extern/sextant/cmake/sextantConfig.cmake.in +36 -0
  30. pysextant-1.1.0/extern/sextant/doc/3d.md +453 -0
  31. pysextant-1.1.0/extern/sextant/doc/api.md +1044 -0
  32. pysextant-1.1.0/extern/sextant/doc/build.md +308 -0
  33. pysextant-1.1.0/extern/sextant/doc/icons/favicon.ico +0 -0
  34. pysextant-1.1.0/extern/sextant/doc/icons/sextant-banner.svg +1 -0
  35. pysextant-1.1.0/extern/sextant/doc/icons/sextant-icon-dark.svg +1 -0
  36. pysextant-1.1.0/extern/sextant/doc/icons/sextant-icon.svg +1 -0
  37. pysextant-1.1.0/extern/sextant/doc/icons/sextant-logo-dark.svg +1 -0
  38. pysextant-1.1.0/extern/sextant/doc/icons/sextant-logo.svg +1 -0
  39. pysextant-1.1.0/extern/sextant/doc/icons/sextant-mark-dark.svg +1 -0
  40. pysextant-1.1.0/extern/sextant/doc/icons/sextant-mark.svg +1 -0
  41. pysextant-1.1.0/extern/sextant/doc/images/docs/backgrounds.png +0 -0
  42. pysextant-1.1.0/extern/sextant/doc/images/docs/bar.png +0 -0
  43. pysextant-1.1.0/extern/sextant/doc/images/docs/bar3d.png +0 -0
  44. pysextant-1.1.0/extern/sextant/doc/images/docs/colormaps.png +0 -0
  45. pysextant-1.1.0/extern/sextant/doc/images/docs/contours.png +0 -0
  46. pysextant-1.1.0/extern/sextant/doc/images/docs/errorbar3d.png +0 -0
  47. pysextant-1.1.0/extern/sextant/doc/images/docs/errorbars.png +0 -0
  48. pysextant-1.1.0/extern/sextant/doc/images/docs/heatmap.png +0 -0
  49. pysextant-1.1.0/extern/sextant/doc/images/docs/hist.png +0 -0
  50. pysextant-1.1.0/extern/sextant/doc/images/docs/legend_ticks.png +0 -0
  51. pysextant-1.1.0/extern/sextant/doc/images/docs/line.png +0 -0
  52. pysextant-1.1.0/extern/sextant/doc/images/docs/line3d.png +0 -0
  53. pysextant-1.1.0/extern/sextant/doc/images/docs/markers.png +0 -0
  54. pysextant-1.1.0/extern/sextant/doc/images/docs/mathtext.png +0 -0
  55. pysextant-1.1.0/extern/sextant/doc/images/docs/plane2d.png +0 -0
  56. pysextant-1.1.0/extern/sextant/doc/images/docs/projection.png +0 -0
  57. pysextant-1.1.0/extern/sextant/doc/images/docs/scatter.png +0 -0
  58. pysextant-1.1.0/extern/sextant/doc/images/docs/scatter3d.png +0 -0
  59. pysextant-1.1.0/extern/sextant/doc/images/docs/scatter_z.png +0 -0
  60. pysextant-1.1.0/extern/sextant/doc/images/docs/styling.png +0 -0
  61. pysextant-1.1.0/extern/sextant/doc/images/docs/subplot3d.png +0 -0
  62. pysextant-1.1.0/extern/sextant/doc/images/docs/subplots.png +0 -0
  63. pysextant-1.1.0/extern/sextant/doc/images/docs/surface.png +0 -0
  64. pysextant-1.1.0/extern/sextant/doc/images/docs/surface_tri.png +0 -0
  65. pysextant-1.1.0/extern/sextant/doc/images/docs/text.png +0 -0
  66. pysextant-1.1.0/extern/sextant/doc/images/docs/translucency.png +0 -0
  67. pysextant-1.1.0/extern/sextant/doc/images/hero/banner.png +0 -0
  68. pysextant-1.1.0/extern/sextant/doc/images/readme/gallery_2d.png +0 -0
  69. pysextant-1.1.0/extern/sextant/doc/images/readme/gallery_3d.png +0 -0
  70. pysextant-1.1.0/extern/sextant/doc/images/readme/quickstart.png +0 -0
  71. pysextant-1.1.0/extern/sextant/doc/images/readme/text_math.png +0 -0
  72. pysextant-1.1.0/extern/sextant/doc/reference.md +651 -0
  73. pysextant-1.1.0/extern/sextant/include/sextant/axes.h +214 -0
  74. pysextant-1.1.0/extern/sextant/include/sextant/axes3d.h +853 -0
  75. pysextant-1.1.0/extern/sextant/include/sextant/events.h +111 -0
  76. pysextant-1.1.0/extern/sextant/include/sextant/export.h +13 -0
  77. pysextant-1.1.0/extern/sextant/include/sextant/figure.h +364 -0
  78. pysextant-1.1.0/extern/sextant/include/sextant/sextant.h +12 -0
  79. pysextant-1.1.0/extern/sextant/include/sextant/style.h +544 -0
  80. pysextant-1.1.0/extern/sextant/scripts/generate_font_header.sh +97 -0
  81. pysextant-1.1.0/extern/sextant/scripts/generate_window_icon.py +70 -0
  82. pysextant-1.1.0/extern/sextant/scripts/setup_deps.bat +96 -0
  83. pysextant-1.1.0/extern/sextant/scripts/setup_deps.sh +67 -0
  84. pysextant-1.1.0/extern/sextant/src/axes.cpp +550 -0
  85. pysextant-1.1.0/extern/sextant/src/axes3d.cpp +792 -0
  86. pysextant-1.1.0/extern/sextant/src/axes3d_impl.h +157 -0
  87. pysextant-1.1.0/extern/sextant/src/axes_impl.h +123 -0
  88. pysextant-1.1.0/extern/sextant/src/axis_limits.h +96 -0
  89. pysextant-1.1.0/extern/sextant/src/axis_placement.h +76 -0
  90. pysextant-1.1.0/extern/sextant/src/colormaps.cpp +302 -0
  91. pysextant-1.1.0/extern/sextant/src/colormaps.h +10 -0
  92. pysextant-1.1.0/extern/sextant/src/contour.cpp +335 -0
  93. pysextant-1.1.0/extern/sextant/src/contour.h +137 -0
  94. pysextant-1.1.0/extern/sextant/src/coord_transform.h +289 -0
  95. pysextant-1.1.0/extern/sextant/src/coord_transform3d.h +792 -0
  96. pysextant-1.1.0/extern/sextant/src/cow_vec.h +63 -0
  97. pysextant-1.1.0/extern/sextant/src/delaunay.cpp +140 -0
  98. pysextant-1.1.0/extern/sextant/src/delaunay.h +17 -0
  99. pysextant-1.1.0/extern/sextant/src/describe.h +267 -0
  100. pysextant-1.1.0/extern/sextant/src/edit_box.h +323 -0
  101. pysextant-1.1.0/extern/sextant/src/event_channel.cpp +178 -0
  102. pysextant-1.1.0/extern/sextant/src/event_channel.h +94 -0
  103. pysextant-1.1.0/extern/sextant/src/figure.cpp +753 -0
  104. pysextant-1.1.0/extern/sextant/src/figure_edits.h +1531 -0
  105. pysextant-1.1.0/extern/sextant/src/figure_export.cpp +223 -0
  106. pysextant-1.1.0/extern/sextant/src/figure_export.h +77 -0
  107. pysextant-1.1.0/extern/sextant/src/figure_impl.h +280 -0
  108. pysextant-1.1.0/extern/sextant/src/font_discovery.cpp +315 -0
  109. pysextant-1.1.0/extern/sextant/src/font_discovery.h +32 -0
  110. pysextant-1.1.0/extern/sextant/src/hint.cpp +506 -0
  111. pysextant-1.1.0/extern/sextant/src/hint.h +135 -0
  112. pysextant-1.1.0/extern/sextant/src/hint_index.h +198 -0
  113. pysextant-1.1.0/extern/sextant/src/key_names.cpp +94 -0
  114. pysextant-1.1.0/extern/sextant/src/key_names.h +11 -0
  115. pysextant-1.1.0/extern/sextant/src/line_dash.h +44 -0
  116. pysextant-1.1.0/extern/sextant/src/messages.cpp +55 -0
  117. pysextant-1.1.0/extern/sextant/src/messages.h +14 -0
  118. pysextant-1.1.0/extern/sextant/src/output/file_write.cpp +55 -0
  119. pysextant-1.1.0/extern/sextant/src/output/file_write.h +14 -0
  120. pysextant-1.1.0/extern/sextant/src/output/png_writer.cpp +93 -0
  121. pysextant-1.1.0/extern/sextant/src/output/png_writer.h +16 -0
  122. pysextant-1.1.0/extern/sextant/src/output/svg_writer.cpp +1305 -0
  123. pysextant-1.1.0/extern/sextant/src/output/svg_writer.h +94 -0
  124. pysextant-1.1.0/extern/sextant/src/plane2d.cpp +183 -0
  125. pysextant-1.1.0/extern/sextant/src/plane2d_impl.h +31 -0
  126. pysextant-1.1.0/extern/sextant/src/platform/linux/offscreen_egl.cpp +332 -0
  127. pysextant-1.1.0/extern/sextant/src/platform/macos/platform_macos.mm +142 -0
  128. pysextant-1.1.0/extern/sextant/src/platform/platform.h +104 -0
  129. pysextant-1.1.0/extern/sextant/src/platform/platform_generic.cpp +34 -0
  130. pysextant-1.1.0/extern/sextant/src/plot_data_view.cpp +229 -0
  131. pysextant-1.1.0/extern/sextant/src/plot_data_view.h +84 -0
  132. pysextant-1.1.0/extern/sextant/src/plot_events.cpp +189 -0
  133. pysextant-1.1.0/extern/sextant/src/plot_events.h +71 -0
  134. pysextant-1.1.0/extern/sextant/src/plot_objects.h +884 -0
  135. pysextant-1.1.0/extern/sextant/src/read_back.h +118 -0
  136. pysextant-1.1.0/extern/sextant/src/render_frame.cpp +138 -0
  137. pysextant-1.1.0/extern/sextant/src/render_frame.h +44 -0
  138. pysextant-1.1.0/extern/sextant/src/renderer/bar3d.cpp +264 -0
  139. pysextant-1.1.0/extern/sextant/src/renderer/bar3d.h +106 -0
  140. pysextant-1.1.0/extern/sextant/src/renderer/box3d.cpp +269 -0
  141. pysextant-1.1.0/extern/sextant/src/renderer/box3d.h +50 -0
  142. pysextant-1.1.0/extern/sextant/src/renderer/data_renderer.cpp +4739 -0
  143. pysextant-1.1.0/extern/sextant/src/renderer/data_renderer.h +603 -0
  144. pysextant-1.1.0/extern/sextant/src/renderer/error_bar3d.cpp +241 -0
  145. pysextant-1.1.0/extern/sextant/src/renderer/error_bar3d.h +96 -0
  146. pysextant-1.1.0/extern/sextant/src/renderer/error_bar_shape.h +55 -0
  147. pysextant-1.1.0/extern/sextant/src/renderer/fbo_readback.cpp +96 -0
  148. pysextant-1.1.0/extern/sextant/src/renderer/fbo_readback.h +43 -0
  149. pysextant-1.1.0/extern/sextant/src/renderer/figure_layout.cpp +965 -0
  150. pysextant-1.1.0/extern/sextant/src/renderer/figure_layout.h +335 -0
  151. pysextant-1.1.0/extern/sextant/src/renderer/gl_context.cpp +141 -0
  152. pysextant-1.1.0/extern/sextant/src/renderer/gl_context.h +95 -0
  153. pysextant-1.1.0/extern/sextant/src/renderer/line3d.cpp +168 -0
  154. pysextant-1.1.0/extern/sextant/src/renderer/line3d.h +75 -0
  155. pysextant-1.1.0/extern/sextant/src/renderer/marker_shape.h +103 -0
  156. pysextant-1.1.0/extern/sextant/src/renderer/nvg_renderer.cpp +818 -0
  157. pysextant-1.1.0/extern/sextant/src/renderer/nvg_renderer.h +114 -0
  158. pysextant-1.1.0/extern/sextant/src/renderer/painter3d.cpp +877 -0
  159. pysextant-1.1.0/extern/sextant/src/renderer/painter3d.h +135 -0
  160. pysextant-1.1.0/extern/sextant/src/renderer/plane2d.cpp +618 -0
  161. pysextant-1.1.0/extern/sextant/src/renderer/plane2d.h +207 -0
  162. pysextant-1.1.0/extern/sextant/src/renderer/plot_fbo.cpp +206 -0
  163. pysextant-1.1.0/extern/sextant/src/renderer/plot_fbo.h +67 -0
  164. pysextant-1.1.0/extern/sextant/src/renderer/plot_rect.h +37 -0
  165. pysextant-1.1.0/extern/sextant/src/renderer/render_device.cpp +42 -0
  166. pysextant-1.1.0/extern/sextant/src/renderer/render_device.h +48 -0
  167. pysextant-1.1.0/extern/sextant/src/renderer/saved_target.cpp +19 -0
  168. pysextant-1.1.0/extern/sextant/src/renderer/saved_target.h +17 -0
  169. pysextant-1.1.0/extern/sextant/src/renderer/scatter3d.cpp +115 -0
  170. pysextant-1.1.0/extern/sextant/src/renderer/scatter3d.h +77 -0
  171. pysextant-1.1.0/extern/sextant/src/renderer/surface.cpp +299 -0
  172. pysextant-1.1.0/extern/sextant/src/renderer/surface.h +90 -0
  173. pysextant-1.1.0/extern/sextant/src/renderer/surface_tri.cpp +324 -0
  174. pysextant-1.1.0/extern/sextant/src/renderer/surface_tri.h +122 -0
  175. pysextant-1.1.0/extern/sextant/src/renderer/text_plan.cpp +293 -0
  176. pysextant-1.1.0/extern/sextant/src/renderer/text_plan.h +73 -0
  177. pysextant-1.1.0/extern/sextant/src/rich_text.cpp +763 -0
  178. pysextant-1.1.0/extern/sextant/src/rich_text.h +90 -0
  179. pysextant-1.1.0/extern/sextant/src/snapshot_box.h +28 -0
  180. pysextant-1.1.0/extern/sextant/src/style.cpp +55 -0
  181. pysextant-1.1.0/extern/sextant/src/text_metrics.cpp +340 -0
  182. pysextant-1.1.0/extern/sextant/src/text_metrics.h +36 -0
  183. pysextant-1.1.0/extern/sextant/src/tick.h +29 -0
  184. pysextant-1.1.0/extern/sextant/src/widgets/cell_shading.h +133 -0
  185. pysextant-1.1.0/extern/sextant/src/widgets/data_panel.cpp +1842 -0
  186. pysextant-1.1.0/extern/sextant/src/widgets/data_panel.h +29 -0
  187. pysextant-1.1.0/extern/sextant/src/widgets/figure_context.h +52 -0
  188. pysextant-1.1.0/extern/sextant/src/widgets/figure_window_shell.cpp +287 -0
  189. pysextant-1.1.0/extern/sextant/src/widgets/figure_window_shell.h +47 -0
  190. pysextant-1.1.0/extern/sextant/src/widgets/imgui_context.cpp +104 -0
  191. pysextant-1.1.0/extern/sextant/src/widgets/imgui_context.h +61 -0
  192. pysextant-1.1.0/extern/sextant/src/widgets/imgui_impl_sextant.cpp +346 -0
  193. pysextant-1.1.0/extern/sextant/src/widgets/imgui_impl_sextant.h +28 -0
  194. pysextant-1.1.0/extern/sextant/src/widgets/panel.cpp +1601 -0
  195. pysextant-1.1.0/extern/sextant/src/widgets/panel.h +125 -0
  196. pysextant-1.1.0/extern/sextant/src/widgets/panel_font.h +4151 -0
  197. pysextant-1.1.0/extern/sextant/src/widgets/panel_state.h +369 -0
  198. pysextant-1.1.0/extern/sextant/src/widgets/panel_widgets.h +286 -0
  199. pysextant-1.1.0/extern/sextant/src/widgets/plot_view.cpp +373 -0
  200. pysextant-1.1.0/extern/sextant/src/widgets/plot_view.h +56 -0
  201. pysextant-1.1.0/extern/sextant/src/widgets/sextant_imconfig.h +29 -0
  202. pysextant-1.1.0/extern/sextant/src/window_broker.cpp +343 -0
  203. pysextant-1.1.0/extern/sextant/src/window_broker.h +105 -0
  204. pysextant-1.1.0/extern/sextant/src/window_icon.h +2099 -0
  205. pysextant-1.1.0/extern/sextant/src/window_link.cpp +275 -0
  206. pysextant-1.1.0/extern/sextant/src/window_link.h +202 -0
  207. pysextant-1.1.0/extern/sextant/src/window_registry.cpp +82 -0
  208. pysextant-1.1.0/extern/sextant/src/window_registry.h +43 -0
  209. pysextant-1.1.0/extern/sextant/src/window_thread.cpp +234 -0
  210. pysextant-1.1.0/extern/sextant/src/window_thread.h +138 -0
  211. pysextant-1.1.0/extern/sextant/tests/basic_smoke/main.cpp +37 -0
  212. pysextant-1.1.0/extern/sextant/tests/gl_probe/cgl_probe.cpp +110 -0
  213. pysextant-1.1.0/extern/sextant/tests/gl_probe/main.cpp +160 -0
  214. pysextant-1.1.0/extern/sextant/tests/headless_probe/main.cpp +250 -0
  215. pysextant-1.1.0/extern/sextant/tests/layout_test/axes3d.cpp +892 -0
  216. pysextant-1.1.0/extern/sextant/tests/layout_test/axis_position.cpp +551 -0
  217. pysextant-1.1.0/extern/sextant/tests/layout_test/background.cpp +105 -0
  218. pysextant-1.1.0/extern/sextant/tests/layout_test/bar3d.cpp +1019 -0
  219. pysextant-1.1.0/extern/sextant/tests/layout_test/camera3d.cpp +478 -0
  220. pysextant-1.1.0/extern/sextant/tests/layout_test/cell_shading.cpp +256 -0
  221. pysextant-1.1.0/extern/sextant/tests/layout_test/color.cpp +45 -0
  222. pysextant-1.1.0/extern/sextant/tests/layout_test/common.cpp +273 -0
  223. pysextant-1.1.0/extern/sextant/tests/layout_test/contour.cpp +272 -0
  224. pysextant-1.1.0/extern/sextant/tests/layout_test/describe.cpp +253 -0
  225. pysextant-1.1.0/extern/sextant/tests/layout_test/dialogs.cpp +494 -0
  226. pysextant-1.1.0/extern/sextant/tests/layout_test/edge_markers.cpp +239 -0
  227. pysextant-1.1.0/extern/sextant/tests/layout_test/errorbar2d.cpp +461 -0
  228. pysextant-1.1.0/extern/sextant/tests/layout_test/errorbar3d.cpp +568 -0
  229. pysextant-1.1.0/extern/sextant/tests/layout_test/events.cpp +1082 -0
  230. pysextant-1.1.0/extern/sextant/tests/layout_test/figure_impl.cpp +163 -0
  231. pysextant-1.1.0/extern/sextant/tests/layout_test/frame_size.cpp +335 -0
  232. pysextant-1.1.0/extern/sextant/tests/layout_test/gl_poison.cpp +176 -0
  233. pysextant-1.1.0/extern/sextant/tests/layout_test/gl_poison.h +18 -0
  234. pysextant-1.1.0/extern/sextant/tests/layout_test/glyph_boxes.cpp +93 -0
  235. pysextant-1.1.0/extern/sextant/tests/layout_test/glyph_boxes.h +30 -0
  236. pysextant-1.1.0/extern/sextant/tests/layout_test/grid_ratios.cpp +343 -0
  237. pysextant-1.1.0/extern/sextant/tests/layout_test/headless_export.cpp +244 -0
  238. pysextant-1.1.0/extern/sextant/tests/layout_test/heatmap.cpp +424 -0
  239. pysextant-1.1.0/extern/sextant/tests/layout_test/layout.cpp +959 -0
  240. pysextant-1.1.0/extern/sextant/tests/layout_test/layout_test.h +603 -0
  241. pysextant-1.1.0/extern/sextant/tests/layout_test/line2d.cpp +221 -0
  242. pysextant-1.1.0/extern/sextant/tests/layout_test/line3d.cpp +1049 -0
  243. pysextant-1.1.0/extern/sextant/tests/layout_test/main.cpp +303 -0
  244. pysextant-1.1.0/extern/sextant/tests/layout_test/memory_export.cpp +250 -0
  245. pysextant-1.1.0/extern/sextant/tests/layout_test/messages.cpp +194 -0
  246. pysextant-1.1.0/extern/sextant/tests/layout_test/object_id.cpp +307 -0
  247. pysextant-1.1.0/extern/sextant/tests/layout_test/panel.cpp +1547 -0
  248. pysextant-1.1.0/extern/sextant/tests/layout_test/placement.cpp +527 -0
  249. pysextant-1.1.0/extern/sextant/tests/layout_test/plane2d.cpp +468 -0
  250. pysextant-1.1.0/extern/sextant/tests/layout_test/plane2d_panel.cpp +433 -0
  251. pysextant-1.1.0/extern/sextant/tests/layout_test/plane2d_render.cpp +1119 -0
  252. pysextant-1.1.0/extern/sextant/tests/layout_test/plot_view.cpp +267 -0
  253. pysextant-1.1.0/extern/sextant/tests/layout_test/read_back.cpp +868 -0
  254. pysextant-1.1.0/extern/sextant/tests/layout_test/render_device.cpp +267 -0
  255. pysextant-1.1.0/extern/sextant/tests/layout_test/rich_text.cpp +493 -0
  256. pysextant-1.1.0/extern/sextant/tests/layout_test/scatter3d.cpp +1012 -0
  257. pysextant-1.1.0/extern/sextant/tests/layout_test/scene3d.cpp +511 -0
  258. pysextant-1.1.0/extern/sextant/tests/layout_test/scene3d_svg.cpp +1053 -0
  259. pysextant-1.1.0/extern/sextant/tests/layout_test/stored_layout.cpp +334 -0
  260. pysextant-1.1.0/extern/sextant/tests/layout_test/surface3d.cpp +968 -0
  261. pysextant-1.1.0/extern/sextant/tests/layout_test/surface_tri.cpp +1318 -0
  262. pysextant-1.1.0/extern/sextant/tests/layout_test/text.cpp +514 -0
  263. pysextant-1.1.0/extern/sextant/tests/layout_test/text_metrics.cpp +293 -0
  264. pysextant-1.1.0/extern/sextant/tests/layout_test/ticks_hidden.cpp +136 -0
  265. pysextant-1.1.0/extern/sextant/tests/layout_test/undo.cpp +399 -0
  266. pysextant-1.1.0/extern/sextant/tests/layout_test/window_broker.cpp +151 -0
  267. pysextant-1.1.0/extern/sextant/tests/layout_test/window_input.cpp +265 -0
  268. pysextant-1.1.0/extern/sextant/tests/layout_test/window_shell.cpp +175 -0
  269. pysextant-1.1.0/extern/sextant/tests/layout_test/window_wait.cpp +208 -0
  270. pysextant-1.1.0/extern/sextant/tests/module_consumer/CMakeLists.txt +31 -0
  271. pysextant-1.1.0/extern/sextant/tests/module_consumer/check_module.sh +72 -0
  272. pysextant-1.1.0/extern/sextant/tests/module_consumer/loader.cpp +50 -0
  273. pysextant-1.1.0/extern/sextant/tests/module_consumer/probe_module.cpp +84 -0
  274. pysextant-1.1.0/extern/sextant/tests/perf_test/main.cpp +1227 -0
  275. pysextant-1.1.0/extern/sextant/tests/split_probe/main.cpp +451 -0
  276. pysextant-1.1.0/extern/sextant/tests/vcpkg_consumer/CMakeLists.txt +25 -0
  277. pysextant-1.1.0/extern/sextant/tests/window_probe/main.cpp +348 -0
  278. pysextant-1.1.0/extern/sextant/tests/window_test/main.cpp +1969 -0
  279. pysextant-1.1.0/extern/sextant/third_party/glad/include/KHR/khrplatform.h +311 -0
  280. pysextant-1.1.0/extern/sextant/third_party/glad/include/glad/glad.h +2652 -0
  281. pysextant-1.1.0/extern/sextant/third_party/glad/src/glad.c +1421 -0
  282. pysextant-1.1.0/extern/sextant/third_party/imgui/backends/imgui_impl_glfw.cpp +1727 -0
  283. pysextant-1.1.0/extern/sextant/third_party/imgui/backends/imgui_impl_glfw.h +73 -0
  284. pysextant-1.1.0/extern/sextant/third_party/imgui/backends/imgui_impl_opengl3.cpp +1150 -0
  285. pysextant-1.1.0/extern/sextant/third_party/imgui/backends/imgui_impl_opengl3.h +69 -0
  286. pysextant-1.1.0/extern/sextant/third_party/imgui/backends/imgui_impl_opengl3_loader.h +958 -0
  287. pysextant-1.1.0/extern/sextant/third_party/imgui/imconfig.h +147 -0
  288. pysextant-1.1.0/extern/sextant/third_party/imgui/imgui.cpp +24359 -0
  289. pysextant-1.1.0/extern/sextant/third_party/imgui/imgui.h +4519 -0
  290. pysextant-1.1.0/extern/sextant/third_party/imgui/imgui_demo.cpp +11540 -0
  291. pysextant-1.1.0/extern/sextant/third_party/imgui/imgui_draw.cpp +6791 -0
  292. pysextant-1.1.0/extern/sextant/third_party/imgui/imgui_internal.h +4321 -0
  293. pysextant-1.1.0/extern/sextant/third_party/imgui/imgui_tables.cpp +4665 -0
  294. pysextant-1.1.0/extern/sextant/third_party/imgui/imgui_widgets.cpp +11119 -0
  295. pysextant-1.1.0/extern/sextant/third_party/imgui/imstb_rectpack.h +627 -0
  296. pysextant-1.1.0/extern/sextant/third_party/imgui/imstb_textedit.h +1527 -0
  297. pysextant-1.1.0/extern/sextant/third_party/imgui/imstb_truetype.h +5085 -0
  298. pysextant-1.1.0/extern/sextant/third_party/imgui/misc/fonts/Roboto-Medium.ttf +0 -0
  299. pysextant-1.1.0/extern/sextant/third_party/imgui/misc/fonts/binary_to_compressed_c.cpp +424 -0
  300. pysextant-1.1.0/extern/sextant/third_party/nanovg/fontstash.h +1792 -0
  301. pysextant-1.1.0/extern/sextant/third_party/nanovg/nanovg.c +2949 -0
  302. pysextant-1.1.0/extern/sextant/third_party/nanovg/nanovg.h +697 -0
  303. pysextant-1.1.0/extern/sextant/third_party/nanovg/nanovg_gl.h +1660 -0
  304. pysextant-1.1.0/extern/sextant/third_party/nanovg/nanovg_gl_utils.h +154 -0
  305. pysextant-1.1.0/extern/sextant/third_party/nanovg/stb_image.h +7988 -0
  306. pysextant-1.1.0/extern/sextant/third_party/nanovg/stb_truetype.h +5079 -0
  307. pysextant-1.1.0/extern/sextant/third_party/stb/stb_image.h +7988 -0
  308. pysextant-1.1.0/extern/sextant/third_party/stb/stb_image_write.h +1724 -0
  309. pysextant-1.1.0/extern/sextant/third_party/stb/stb_truetype.h +5079 -0
  310. pysextant-1.1.0/pyproject.toml +148 -0
  311. pysextant-1.1.0/src/ext/_sextant.map +7 -0
  312. pysextant-1.1.0/src/ext/axes.cpp +420 -0
  313. pysextant-1.1.0/src/ext/axes3d.cpp +548 -0
  314. pysextant-1.1.0/src/ext/casters.cpp +146 -0
  315. pysextant-1.1.0/src/ext/casters.h +382 -0
  316. pysextant-1.1.0/src/ext/data.cpp +289 -0
  317. pysextant-1.1.0/src/ext/events.cpp +260 -0
  318. pysextant-1.1.0/src/ext/figure.cpp +375 -0
  319. pysextant-1.1.0/src/ext/lifecycle.cpp +292 -0
  320. pysextant-1.1.0/src/ext/messages.cpp +76 -0
  321. pysextant-1.1.0/src/ext/module.cpp +40 -0
  322. pysextant-1.1.0/src/ext/options.h +233 -0
  323. pysextant-1.1.0/src/ext/state.h +119 -0
  324. pysextant-1.1.0/src/ext/wrappers.h +151 -0
  325. pysextant-1.1.0/src/sextant/__init__.py +103 -0
  326. pysextant-1.1.0/src/sextant/_enums.py +203 -0
  327. pysextant-1.1.0/src/sextant/_interactive.py +137 -0
  328. pysextant-1.1.0/src/sextant/_mpl.py +1711 -0
  329. pysextant-1.1.0/src/sextant/_sextant.pyi +1735 -0
  330. pysextant-1.1.0/src/sextant/py.typed +0 -0
  331. pysextant-1.1.0/src/sextant/pyplot.py +323 -0
  332. pysextant-1.1.0/tests/_subproc.py +62 -0
  333. pysextant-1.1.0/tests/conftest.py +25 -0
  334. pysextant-1.1.0/tests/test_axes2d.py +222 -0
  335. pysextant-1.1.0/tests/test_axes3d.py +228 -0
  336. pysextant-1.1.0/tests/test_enums.py +50 -0
  337. pysextant-1.1.0/tests/test_events.py +200 -0
  338. pysextant-1.1.0/tests/test_export.py +113 -0
  339. pysextant-1.1.0/tests/test_interactive.py +154 -0
  340. pysextant-1.1.0/tests/test_kernel.py +119 -0
  341. pysextant-1.1.0/tests/test_lifecycle.py +273 -0
  342. pysextant-1.1.0/tests/test_options.py +209 -0
  343. pysextant-1.1.0/tests/test_pyplot.py +716 -0
  344. pysextant-1.1.0/tests/test_smoke.py +47 -0
  345. pysextant-1.1.0/tests/test_stubs.py +37 -0
  346. pysextant-1.1.0/tests/test_styling.py +183 -0
  347. pysextant-1.1.0/tests/test_text.py +217 -0
  348. pysextant-1.1.0/tests/typing_usage.py +66 -0
  349. pysextant-1.1.0/tools/gen_stubs.py +123 -0
  350. pysextant-1.1.0/tools/icon_check.py +75 -0
  351. pysextant-1.1.0/tools/stress_exit.py +138 -0
  352. pysextant-1.1.0/tools/teardown_bisect.py +150 -0
  353. pysextant-1.1.0/uv.lock +1403 -0
@@ -0,0 +1,113 @@
1
+ # Diagnostic, run by hand: which teardown pattern makes a window's render
2
+ # thread hang while the main thread joins it. Seen on GPU-less runner VMs:
3
+ # macOS (Apple's software GL; fixed in sextant b1edbb7) and Linux (llvmpipe
4
+ # under xvfb, Python 3.14). Each scenario of tools/teardown_bisect.py runs as
5
+ # its own job, against the wheel of an earlier `wheels` run, so the binary is
6
+ # the one that hung. Results: the run's summary page (one table row per
7
+ # scenario) and, for each hang, its Python and native stacks (macOS `sample`,
8
+ # Linux gdb) as an artifact.
9
+ #
10
+ # gh workflow run teardown_bisect.yml -f wheels_run_id=<id> [-f platform=Linux] [-f python=3.14] [-f runs=40]
11
+ name: teardown bisect
12
+
13
+ on:
14
+ workflow_dispatch:
15
+ inputs:
16
+ wheels_run_id:
17
+ description: Run id of a `wheels` run whose wheels-<platform> artifact to test
18
+ required: true
19
+ type: string
20
+ platform:
21
+ description: Which wheel, on which runner
22
+ type: choice
23
+ options: [macOS, Linux]
24
+ default: macOS
25
+ python:
26
+ description: Python version (the abi3 wheel is used)
27
+ default: "3.12"
28
+ type: string
29
+ runs:
30
+ description: Fresh-Python runs per scenario
31
+ default: "40"
32
+ type: string
33
+ runner:
34
+ description: Runner image; empty = macos-15 for macOS, ubuntu-24.04 for Linux
35
+ default: ""
36
+ type: string
37
+
38
+ permissions:
39
+ contents: read
40
+ actions: read # the other run's artifact
41
+
42
+ jobs:
43
+ bisect:
44
+ name: ${{ matrix.scenario }}
45
+ runs-on: ${{ inputs.runner || (inputs.platform == 'Linux' && 'ubuntu-24.04' || 'macos-15') }}
46
+ timeout-minutes: 60
47
+ env:
48
+ GALLIUM_DRIVER: llvmpipe # Linux: as the wheels workflow's display job
49
+ strategy:
50
+ fail-fast: false
51
+ matrix:
52
+ scenario:
53
+ - exit3
54
+ - exit1
55
+ - exit3_framed
56
+ - exit3_staggered
57
+ - close3
58
+ - close_other_first
59
+ - close_self_first
60
+ steps:
61
+ - uses: actions/checkout@v7 # tools/ only; the wheel is not rebuilt
62
+
63
+ - uses: actions/download-artifact@v8
64
+ with:
65
+ name: wheels-${{ inputs.platform }}
66
+ path: wheelhouse
67
+ run-id: ${{ inputs.wheels_run_id }}
68
+ github-token: ${{ github.token }}
69
+
70
+ - uses: actions/setup-python@v7
71
+ with:
72
+ python-version: ${{ inputs.python }}
73
+
74
+ - name: Install runtime dependencies (Linux)
75
+ if: inputs.platform == 'Linux'
76
+ run: |
77
+ sudo apt-get update
78
+ sudo apt-get install -y --no-install-recommends \
79
+ libgl1 libgl1-mesa-dri libegl1 libegl-mesa0 xvfb xauth fonts-dejavu-core gdb
80
+
81
+ - name: Install the wheel
82
+ run: |
83
+ python -m venv "$RUNNER_TEMP/venv"
84
+ if [ "${{ inputs.platform }}" = Linux ]; then
85
+ wheel=$(ls wheelhouse/*-abi3-manylinux*.whl)
86
+ else
87
+ wheel=$(ls wheelhouse/*-cp312-abi3-macosx_*_arm64.whl)
88
+ fi
89
+ "$RUNNER_TEMP/venv/bin/python" -m pip install -q "$wheel"
90
+ "$RUNNER_TEMP/venv/bin/python" -c "import sys, sextant; print(sys.version, sextant.__file__)"
91
+ if [ "${{ inputs.platform }}" = Linux ]; then uname -a; else sw_vers; fi
92
+
93
+ - name: Run ${{ matrix.scenario }}
94
+ run: |
95
+ {
96
+ echo "| scenario | hangs | other failures | runs done | first hang | slowest |"
97
+ echo "|---|---|---|---|---|---|"
98
+ } >> "$GITHUB_STEP_SUMMARY"
99
+ cd "$RUNNER_TEMP"
100
+ run=("$RUNNER_TEMP/venv/bin/python" "$GITHUB_WORKSPACE/tools/teardown_bisect.py"
101
+ "${{ matrix.scenario }}" "${{ inputs.runs }}" --report-dir "$RUNNER_TEMP/reports")
102
+ if [ "${{ inputs.platform }}" = Linux ]; then
103
+ xvfb-run -a -s "-screen 0 1920x1080x24" "${run[@]}"
104
+ else
105
+ "${run[@]}"
106
+ fi
107
+
108
+ - uses: actions/upload-artifact@v7
109
+ if: always()
110
+ with:
111
+ name: reports-${{ matrix.scenario }}
112
+ path: ${{ runner.temp }}/reports
113
+ if-no-files-found: ignore
@@ -0,0 +1,74 @@
1
+ # The dev path: an editable build from the checkout (uv sync) and the whole
2
+ # suite, on each OS. Release wheels are built and tested in wheels.yml.
3
+ name: tests
4
+
5
+ on:
6
+ push:
7
+ branches: [dev]
8
+ pull_request:
9
+ workflow_dispatch:
10
+
11
+ concurrency:
12
+ group: tests-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ test:
17
+ name: ${{ matrix.name }}
18
+ runs-on: ${{ matrix.os }}
19
+ timeout-minutes: 40
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ include:
24
+ - { name: Windows, os: windows-2025 }
25
+ - { name: Linux, os: ubuntu-24.04 }
26
+ - { name: macOS, os: macos-15 }
27
+ env:
28
+ # The runners have no GPU: Mesa's software rasterizer on Windows and Linux.
29
+ GALLIUM_DRIVER: llvmpipe
30
+ defaults:
31
+ run:
32
+ shell: bash
33
+ steps:
34
+ - uses: actions/checkout@v7
35
+ with:
36
+ submodules: recursive
37
+
38
+ # GLFW's X11 backend and GL headers to build; EGL + llvmpipe for the
39
+ # display-less export, xvfb for the window tests, a font.
40
+ - name: Install dependencies (Linux)
41
+ if: runner.os == 'Linux'
42
+ run: |
43
+ sudo apt-get update
44
+ sudo apt-get install -y --no-install-recommends \
45
+ libgl-dev libgl1-mesa-dri libegl1 libegl-mesa0 libopengl0 \
46
+ libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev \
47
+ xvfb xauth fonts-dejavu-core
48
+
49
+ # Windows' own opengl32 stops at GL 1.1; sextant needs 3.3.
50
+ - name: Install Mesa llvmpipe (Windows)
51
+ if: runner.os == 'Windows'
52
+ uses: ssciwr/setup-mesa-dist-win@v3
53
+
54
+ - uses: astral-sh/setup-uv@v10.2.0 # no floating major tag
55
+ with:
56
+ enable-cache: true
57
+
58
+ # Builds sextant and the extension from source (~2 min).
59
+ - name: Build (uv sync)
60
+ run: uv sync
61
+
62
+ - name: Tests
63
+ if: runner.os != 'Linux'
64
+ run: uv run pytest
65
+
66
+ # Twice on Linux: with no display (the EGL export path, window tests
67
+ # skipped) and under xvfb (everything).
68
+ - name: Tests, no display (Linux)
69
+ if: runner.os == 'Linux'
70
+ run: uv run pytest
71
+
72
+ - name: Tests, xvfb (Linux)
73
+ if: runner.os == 'Linux'
74
+ run: xvfb-run -a -s "-screen 0 1920x1080x24" uv run pytest
@@ -0,0 +1,220 @@
1
+ # Release wheels and the sdist, tested, and published on a version tag.
2
+ #
3
+ # The build settings are [tool.cibuildwheel] in pyproject.toml, so a local
4
+ # `cibuildwheel` run builds the same wheels.
5
+ #
6
+ # Publishing uses PyPI trusted publishing (no token): register this repository,
7
+ # this workflow and the environment name ("pypi" / "testpypi") as a trusted
8
+ # publisher on the project's PyPI / TestPyPI page first.
9
+ name: wheels
10
+
11
+ on:
12
+ push:
13
+ tags: ["v*"]
14
+ branches: [dev]
15
+ paths:
16
+ - pyproject.toml
17
+ - CMakeLists.txt
18
+ - extern/sextant
19
+ - .github/workflows/wheels.yml
20
+ pull_request:
21
+ paths:
22
+ - pyproject.toml
23
+ - CMakeLists.txt
24
+ - extern/sextant
25
+ - .github/workflows/wheels.yml
26
+ workflow_dispatch:
27
+ inputs:
28
+ target:
29
+ description: Where to upload the built distributions
30
+ type: choice
31
+ options: [none, testpypi, pypi]
32
+ default: none
33
+
34
+ permissions:
35
+ contents: read
36
+
37
+ jobs:
38
+ build_wheels:
39
+ name: Wheels, ${{ matrix.name }}
40
+ runs-on: ${{ matrix.os }}
41
+ timeout-minutes: 90
42
+ strategy:
43
+ fail-fast: false
44
+ matrix:
45
+ include:
46
+ - { name: Windows, os: windows-2025 }
47
+ - { name: Linux, os: ubuntu-24.04 }
48
+ # arm64 runner: builds arm64 and x86_64, and tests x86_64 under Rosetta.
49
+ - { name: macOS, os: macos-15 }
50
+ steps:
51
+ - uses: actions/checkout@v7
52
+ with:
53
+ submodules: recursive
54
+
55
+ # The wheel tests render: Windows' own opengl32 stops at GL 1.1.
56
+ - name: Install Mesa llvmpipe (Windows)
57
+ if: runner.os == 'Windows'
58
+ uses: ssciwr/setup-mesa-dist-win@v3
59
+
60
+ - uses: pypa/cibuildwheel@v4.2
61
+ env:
62
+ GALLIUM_DRIVER: llvmpipe
63
+ with:
64
+ output-dir: wheelhouse
65
+
66
+ - uses: actions/upload-artifact@v7
67
+ with:
68
+ name: wheels-${{ matrix.name }}
69
+ path: wheelhouse/*.whl
70
+
71
+ # A rare exit hang (a window's first GL draw vs. the main thread joining
72
+ # its render thread) was seen only on these VMs, in about one wheel test
73
+ # run in twenty: one pytest run cannot show it is gone. Tear windows down
74
+ # early, many times, with the abi3 arm64 wheel built above.
75
+ - uses: actions/setup-python@v7
76
+ if: runner.os == 'macOS'
77
+ with:
78
+ python-version: "3.12"
79
+ - name: Stress window teardown (macOS)
80
+ if: runner.os == 'macOS'
81
+ run: |
82
+ python -m venv "$RUNNER_TEMP/stress"
83
+ "$RUNNER_TEMP/stress/bin/python" -m pip install -q wheelhouse/*-cp312-abi3-macosx_*_arm64.whl
84
+ cd "$RUNNER_TEMP"
85
+ "$RUNNER_TEMP/stress/bin/python" "$GITHUB_WORKSPACE/tools/stress_exit.py" 100
86
+
87
+ build_sdist:
88
+ name: sdist
89
+ runs-on: ubuntu-24.04
90
+ steps:
91
+ - uses: actions/checkout@v7
92
+ with:
93
+ submodules: recursive
94
+ - uses: astral-sh/setup-uv@v10.2.0 # no floating major tag
95
+ # pypa/build, not `uv build`: [tool.uv]'s no-build-isolation-package
96
+ # (for the dev venv) makes uv build without isolation, and there is no
97
+ # venv with scikit-build-core here.
98
+ - run: uvx --from build pyproject-build --sdist --installer uv --outdir dist .
99
+ - uses: actions/upload-artifact@v7
100
+ with:
101
+ name: sdist
102
+ path: dist/*.tar.gz
103
+
104
+ # The manylinux container has no X server, so cibuildwheel's tests skip the
105
+ # window tests there. Here the abi3 wheel runs the whole suite on the host,
106
+ # under xvfb, and once more with no display.
107
+ test_linux_display:
108
+ name: Linux wheel with a display, Python ${{ matrix.python }}
109
+ needs: build_wheels
110
+ runs-on: ubuntu-24.04
111
+ strategy:
112
+ fail-fast: false
113
+ matrix:
114
+ python: ["3.12", "3.14"]
115
+ env:
116
+ GALLIUM_DRIVER: llvmpipe
117
+ steps:
118
+ - uses: actions/checkout@v7
119
+ with:
120
+ submodules: recursive
121
+ - uses: actions/setup-python@v7
122
+ with:
123
+ python-version: ${{ matrix.python }}
124
+ - uses: actions/download-artifact@v8
125
+ with:
126
+ name: wheels-Linux
127
+ path: wheelhouse
128
+ - name: Install runtime dependencies
129
+ run: |
130
+ sudo apt-get update
131
+ sudo apt-get install -y --no-install-recommends \
132
+ libgl1 libgl1-mesa-dri libegl1 libegl-mesa0 xvfb xauth fonts-dejavu-core
133
+ - name: Install the wheel
134
+ run: python -m pip install wheelhouse/*-abi3-manylinux*.whl pytest pytest-timeout
135
+ # As cibuildwheel runs them: away from the source tree, so the installed
136
+ # package is what gets imported.
137
+ - name: Copy the tests
138
+ run: |
139
+ mkdir -p "$RUNNER_TEMP/t/extern/sextant"
140
+ cp -R pyproject.toml tests "$RUNNER_TEMP/t/"
141
+ cp -R extern/sextant/include "$RUNNER_TEMP/t/extern/sextant/"
142
+ - name: Tests, xvfb
143
+ working-directory: ${{ runner.temp }}/t
144
+ run: xvfb-run -a -s "-screen 0 1920x1080x24" python -m pytest -q
145
+ - name: Tests, no display
146
+ working-directory: ${{ runner.temp }}/t
147
+ run: python -m pytest -q
148
+
149
+ # A user without a matching wheel gets the sdist: it must build with pip
150
+ # alone (sextant's dependencies are fetched at configure time).
151
+ test_sdist:
152
+ name: sdist builds and passes
153
+ needs: build_sdist
154
+ runs-on: ubuntu-24.04
155
+ env:
156
+ GALLIUM_DRIVER: llvmpipe
157
+ steps:
158
+ - uses: actions/checkout@v7
159
+ with:
160
+ submodules: recursive
161
+ - uses: actions/setup-python@v7
162
+ with:
163
+ python-version: "3.12"
164
+ - uses: actions/download-artifact@v8
165
+ with:
166
+ name: sdist
167
+ path: dist
168
+ - name: Install build dependencies
169
+ run: |
170
+ sudo apt-get update
171
+ sudo apt-get install -y --no-install-recommends \
172
+ libgl-dev libgl1-mesa-dri libegl1 libegl-mesa0 \
173
+ libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev \
174
+ fonts-dejavu-core
175
+ - name: Install the sdist
176
+ run: python -m pip install dist/*.tar.gz pytest pytest-timeout
177
+ - name: Copy the tests
178
+ run: |
179
+ mkdir -p "$RUNNER_TEMP/t/extern/sextant"
180
+ cp -R pyproject.toml tests "$RUNNER_TEMP/t/"
181
+ cp -R extern/sextant/include "$RUNNER_TEMP/t/extern/sextant/"
182
+ - name: Tests, no display
183
+ working-directory: ${{ runner.temp }}/t
184
+ run: python -m pytest -q
185
+
186
+ publish:
187
+ name: Publish to ${{ github.event_name == 'workflow_dispatch' && inputs.target || 'pypi' }}
188
+ needs: [build_wheels, build_sdist, test_linux_display, test_sdist]
189
+ if: >-
190
+ (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
191
+ (github.event_name == 'workflow_dispatch' && inputs.target != 'none')
192
+ runs-on: ubuntu-24.04
193
+ environment:
194
+ name: ${{ github.event_name == 'workflow_dispatch' && inputs.target || 'pypi' }}
195
+ permissions:
196
+ id-token: write
197
+ steps:
198
+ - uses: actions/checkout@v7
199
+ # A tag must name the version being uploaded: v1.1.0 <-> version = "1.1.0".
200
+ - name: Tag matches the project version
201
+ if: startsWith(github.ref, 'refs/tags/v')
202
+ run: |
203
+ version=$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
204
+ if [ "v$version" != "$GITHUB_REF_NAME" ]; then
205
+ echo "::error::tag $GITHUB_REF_NAME does not match pyproject.toml version $version"
206
+ exit 1
207
+ fi
208
+ - uses: actions/download-artifact@v8
209
+ with:
210
+ path: dist
211
+ merge-multiple: true
212
+ - run: ls -l dist
213
+ - name: Upload to TestPyPI
214
+ if: github.event_name == 'workflow_dispatch' && inputs.target == 'testpypi'
215
+ uses: pypa/gh-action-pypi-publish@release/v1
216
+ with:
217
+ repository-url: https://test.pypi.org/legacy/
218
+ - name: Upload to PyPI
219
+ if: github.event_name != 'workflow_dispatch' || inputs.target == 'pypi'
220
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,9 @@
1
+ /build/
2
+ /dist/
3
+ /.venv/
4
+ __pycache__/
5
+ *.py[cod]
6
+ *.pyd
7
+ *.so
8
+ .pytest_cache/
9
+ *.egg-info/
@@ -0,0 +1,4 @@
1
+ [submodule "extern/sextant"]
2
+ path = extern/sextant
3
+ url = https://github.com/BackslashStudio/sextant.git
4
+ branch = dev
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,72 @@
1
+ cmake_minimum_required(VERSION 3.21...4.3)
2
+ project(sextant_py LANGUAGES CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 20)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+ set(CMAKE_CXX_EXTENSIONS OFF)
7
+
8
+ # sextant is compiled in this build and linked statically into the extension:
9
+ # one module cannot disagree with itself about the C++ ABI (the API passes
10
+ # std::string/std::vector across), and the wheel carries no second binary.
11
+ set(SEXTANT_SOURCE_DIR "" CACHE PATH "sextant source tree; empty = the extern/sextant submodule")
12
+ if(NOT SEXTANT_SOURCE_DIR)
13
+ set(SEXTANT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extern/sextant")
14
+ endif()
15
+ if(NOT EXISTS "${SEXTANT_SOURCE_DIR}/CMakeLists.txt")
16
+ message(FATAL_ERROR "No sextant sources at ${SEXTANT_SOURCE_DIR}: "
17
+ "run `git submodule update --init`, or set SEXTANT_SOURCE_DIR")
18
+ endif()
19
+ message(STATUS "sextant sources: ${SEXTANT_SOURCE_DIR}")
20
+
21
+ # Link libGL.so.1, not GLVND's libOpenGL.so.0 + libGLX.so.0: manylinux allows
22
+ # only the former, and auditwheel would bundle the latter into the wheel.
23
+ set(OpenGL_GL_PREFERENCE LEGACY)
24
+
25
+ # Static C++ runtime for everything in the build (sextant, its bundled deps,
26
+ # nanobind): python.org's Python ships no msvcp140.dll, and a process that
27
+ # loaded an older one first would break std::mutex in a /MD module.
28
+ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
29
+
30
+ set(SEXTANT_BUILD_SHARED OFF CACHE BOOL "" FORCE)
31
+ set(SEXTANT_BUNDLE_DEPS ON CACHE BOOL "" FORCE)
32
+ set(SEXTANT_BUILD_TESTS OFF CACHE BOOL "" FORCE)
33
+ # sextant pins GLFW to X11 on Linux, so its Wayland backend is dead code, and
34
+ # building it needs wayland-scanner/protocols and xkbcommon headers.
35
+ set(GLFW_BUILD_WAYLAND OFF CACHE BOOL "" FORCE)
36
+ add_subdirectory("${SEXTANT_SOURCE_DIR}" sextant EXCLUDE_FROM_ALL)
37
+
38
+ find_package(Python 3.10 REQUIRED
39
+ COMPONENTS Interpreter Development.Module
40
+ OPTIONAL_COMPONENTS Development.SABIModule)
41
+ find_package(nanobind CONFIG REQUIRED)
42
+
43
+ nanobind_add_module(_sextant STABLE_ABI NB_STATIC
44
+ src/ext/module.cpp
45
+ src/ext/axes.cpp
46
+ src/ext/axes3d.cpp
47
+ src/ext/casters.cpp
48
+ src/ext/data.cpp
49
+ src/ext/events.cpp
50
+ src/ext/figure.cpp
51
+ src/ext/lifecycle.cpp
52
+ src/ext/messages.cpp)
53
+ target_link_libraries(_sextant PRIVATE sextant::sextant_static)
54
+
55
+ # Export PyInit__sextant alone (see the map file). Not on macOS: arm64 already
56
+ # exports that symbol only, and x86_64's extra exports are weak typeinfo that
57
+ # libc++ there compares by address, so hiding them could break a catch across
58
+ # images.
59
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
60
+ # Static libstdc++: a module built with a newer GCC than the host Python
61
+ # env's libstdc++ (conda's lags the system's) would fail to import on a
62
+ # missing GLIBCXX_* version. The version script below keeps it all local.
63
+ # libgcc stays dynamic: with a second, static unwinder an exception thrown
64
+ # through glibc frames (std::call_once -> pthread_once) reaches libgcc_s's
65
+ # personality routine with the wrong unwinder's context and aborts.
66
+ target_link_options(_sextant PRIVATE -static-libstdc++)
67
+ set(_sextant_map "${CMAKE_CURRENT_SOURCE_DIR}/src/ext/_sextant.map")
68
+ target_link_options(_sextant PRIVATE "LINKER:--version-script=${_sextant_map}")
69
+ set_property(TARGET _sextant APPEND PROPERTY LINK_DEPENDS "${_sextant_map}")
70
+ endif()
71
+
72
+ install(TARGETS _sextant LIBRARY DESTINATION sextant COMPONENT python)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 The sextant authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysextant
3
+ Version: 1.1.0
4
+ Summary: Scientific plotting from a C++20 core: matplotlib-like figures, 2D and 3D, PNG/SVG export
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ License-File: extern/sextant/LICENSE
8
+ License-File: extern/sextant/THIRD_PARTY_NOTICES.md
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Operating System :: MacOS
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: C++
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Scientific/Engineering :: Visualization
23
+ Classifier: Typing :: Typed
24
+ Project-URL: Homepage, https://github.com/BackslashStudio/sextant
25
+ Project-URL: Source, https://github.com/BackslashStudio/sextant_py
26
+ Project-URL: Issues, https://github.com/BackslashStudio/sextant_py/issues
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: numpy>=1.23
29
+ Description-Content-Type: text/markdown
30
+
31
+ # sextant for Python
32
+
33
+ Python bindings for [sextant](https://github.com/BackslashStudio/sextant), a C++20 library for scientific
34
+ plotting: 2D and 3D figures in an interactive OpenGL window, and PNG/SVG export with or without a display.
35
+ Two ways in: the core API, which maps sextant's C++ API name for name, and `sextant.pyplot`, which runs
36
+ matplotlib-style code.
37
+
38
+ ## Install
39
+
40
+ ```sh
41
+ python -m pip install pysextant
42
+ ```
43
+
44
+ On PyPI it is **`pysextant`** (`sextant` there is an unrelated project); it imports as `sextant`. The current
45
+ release is 1.1.0. Wheels cover Python 3.10 or later on Windows (x86-64), Linux (x86-64, glibc 2.27+) and macOS 11+ (Apple Silicon and Intel);
46
+ the only dependency is numpy. **[doc/install.md](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/install.md)** has everything else: building
47
+ [from source](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/install.md#from-source), [conda](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/install.md#in-a-conda-environment),
48
+ [what each platform needs at run time](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/install.md#running-it) (X11/EGL on Linux, the main thread on macOS,
49
+ OpenGL 3.3 on Windows) and [troubleshooting](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/install.md#troubleshooting).
50
+
51
+ ## Documentation
52
+
53
+ [doc/README.md](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/README.md) indexes it: the [core API guide](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/api.md), [3D plots](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/3d.md),
54
+ [`sextant.pyplot`](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/pyplot.md) and the [option reference](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/reference.md).
55
+
56
+ ## Examples
57
+
58
+ The core API: keyword arguments are the C++ option structs' fields, enums are strings, and plotting calls
59
+ chain.
60
+
61
+ ```python
62
+ import numpy as np
63
+ import sextant
64
+
65
+ x = np.linspace(0, 2 * np.pi, 200)
66
+ fig = sextant.Figure(width=800, height=500, title="waves")
67
+ ax = fig.axes()
68
+ ax.line(x, np.sin(x), color="blue", name="sin").line(x, np.cos(x), color="red", linestyle="--", name="cos")
69
+ ax.set_title("sin and cos").legend()
70
+ fig.savefig("waves.png") # needs no window
71
+ fig.show() # in a script, blocks until the window is closed
72
+ ```
73
+
74
+ matplotlib-style code through `sextant.pyplot`:
75
+
76
+ ```python
77
+ import numpy as np
78
+ import sextant.pyplot as plt
79
+
80
+ x = np.linspace(0, 10, 100)
81
+ fig, ax = plt.subplots(figsize=(7, 4))
82
+ ax.plot(x, np.sin(x), "r-", label="sin")
83
+ ax.scatter(x[::10], np.cos(x[::10]), label="cos, sampled")
84
+ ax.set_xlabel("x")
85
+ ax.legend()
86
+ plt.savefig("mpl.png")
87
+ plt.show()
88
+ ```
89
+
90
+ `pyplot` covers the common calls (`plot`, `scatter`, `bar`, `hist`, `errorbar`, `imshow`, `pcolormesh`, 3D
91
+ `plot_surface`/`scatter`/`bar3d`, `text`/`annotate`, `$...$` math in labels, colorbars, `mpl_connect` events,
92
+ `pause`/`ion`); what sextant cannot draw
93
+ raises an error rather than being ignored. In Jupyter a figure displays inline as PNG.
94
+
95
+ Windows are interactive (pan, zoom, a panel to edit titles, ticks and data). In a script `show()` blocks until
96
+ the window closes; in a REPL or IPython it returns and the window stays live.
97
+
98
+ The package is typed (`py.typed`): keyword options and enum names are checked by a type checker (tested with mypy).
99
+
100
+ ## Development
101
+
102
+ Building needs the toolchain in [doc/install.md](https://github.com/BackslashStudio/sextant_py/blob/v1.1.0/doc/install.md#1-the-c-toolchain).
103
+
104
+ ```sh
105
+ git clone --recursive https://github.com/BackslashStudio/sextant_py.git
106
+ cd sextant_py
107
+ uv sync
108
+ uv run pytest
109
+ ```
110
+
111
+ The install is editable: after a change to the C++ sources, the next `import sextant` rebuilds the extension.
112
+ On Windows any shell works (Visual Studio with the C++ workload is found by itself).
113
+
114
+ - sextant comes from the `extern/sextant` submodule, pinned to a commit. After a `git pull` that moves the
115
+ pin, run `git submodule update` (or pull with `--recurse-submodules`).
116
+ - To build against another sextant checkout, set `SEXTANT_SOURCE_DIR` to its absolute path and run
117
+ `uv sync --reinstall-package pysextant`.
118
+ - After changing a signature, an option field or an enum name, regenerate the type stub with
119
+ `uv run python tools/gen_stubs.py`; `tests/test_stubs.py` fails until it matches.
120
+ - Release wheels are built by `cibuildwheel` with the settings in `pyproject.toml`, locally the same as in CI
121
+ (`.github/workflows/wheels.yml`).
122
+
123
+ ## License
124
+
125
+ MIT. The extension links sextant and the code it bundles (FreeType, libpng, zlib, GLFW, Dear ImGui, NanoVG,
126
+ stb, glad); their notices are in `extern/sextant/THIRD_PARTY_NOTICES.md`, which every wheel and sdist carries
127
+ (`*.dist-info/licenses/`). Portions of this software are copyright © 2026 The FreeType Project
128
+ (www.freetype.org). All rights reserved.