pysual 0.1.2__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 (341) hide show
  1. pysual-0.1.2/.clang-format +13 -0
  2. pysual-0.1.2/CHANGELOG.md +49 -0
  3. pysual-0.1.2/CONTRIBUTING.md +42 -0
  4. pysual-0.1.2/LICENSE +21 -0
  5. pysual-0.1.2/MANIFEST.in +19 -0
  6. pysual-0.1.2/PKG-INFO +236 -0
  7. pysual-0.1.2/README.md +199 -0
  8. pysual-0.1.2/docs/api.md +922 -0
  9. pysual-0.1.2/docs/building.md +407 -0
  10. pysual-0.1.2/docs/control-architecture.md +206 -0
  11. pysual-0.1.2/docs/native.md +183 -0
  12. pysual-0.1.2/docs/theme-families.png +0 -0
  13. pysual-0.1.2/docs/web.md +131 -0
  14. pysual-0.1.2/examples/catalog_controls.py +278 -0
  15. pysual-0.1.2/examples/composite_control.py +126 -0
  16. pysual-0.1.2/examples/custom_control.py +49 -0
  17. pysual-0.1.2/examples/dashboard.py +143 -0
  18. pysual-0.1.2/examples/hello.py +31 -0
  19. pysual-0.1.2/examples/pyrightconfig.json +20 -0
  20. pysual-0.1.2/examples/showcase.py +1166 -0
  21. pysual-0.1.2/examples/stress_test.py +767 -0
  22. pysual-0.1.2/examples/theme_gallery.py +404 -0
  23. pysual-0.1.2/native/clipboard.h +30 -0
  24. pysual-0.1.2/native/command_schema.h +38 -0
  25. pysual-0.1.2/native/host.c +800 -0
  26. pysual-0.1.2/native/notices/.gitattributes +3 -0
  27. pysual-0.1.2/native/notices/SDL3_ttf-FreeType-BDF-LICENSE.txt +152 -0
  28. pysual-0.1.2/native/notices/SDL3_ttf-FreeType-FTL.txt +169 -0
  29. pysual-0.1.2/native/notices/SDL3_ttf-FreeType-LICENSE.txt +46 -0
  30. pysual-0.1.2/native/notices/SDL3_ttf-FreeType-PCF-LICENSE.txt +96 -0
  31. pysual-0.1.2/native/notices/SDL3_ttf-HarfBuzz-LICENSE.txt +42 -0
  32. pysual-0.1.2/native/notices/SDL3_ttf-NOTICES.txt +50 -0
  33. pysual-0.1.2/native/notices/SDL3_ttf-PlutoSVG-LICENSE.txt +21 -0
  34. pysual-0.1.2/native/notices/SDL3_ttf-PlutoVG-LICENSE.txt +21 -0
  35. pysual-0.1.2/native/notices/manifest.json +65 -0
  36. pysual-0.1.2/native/pt_unicode.h +5815 -0
  37. pysual-0.1.2/native/px_backend.h +46 -0
  38. pysual-0.1.2/native/sdl_renderer.c +3697 -0
  39. pysual-0.1.2/native/terminal_renderer.c +3315 -0
  40. pysual-0.1.2/native/vendor/cJSON.LICENSE +19 -0
  41. pysual-0.1.2/native/vendor/cJSON.c +3191 -0
  42. pysual-0.1.2/native/vendor/cJSON.h +306 -0
  43. pysual-0.1.2/native/window_stub.c +23 -0
  44. pysual-0.1.2/pyproject.toml +59 -0
  45. pysual-0.1.2/pyrightconfig.json +15 -0
  46. pysual-0.1.2/setup.cfg +4 -0
  47. pysual-0.1.2/setup.py +97 -0
  48. pysual-0.1.2/src/pysual/__init__.py +154 -0
  49. pysual-0.1.2/src/pysual/__main__.py +6 -0
  50. pysual-0.1.2/src/pysual/_blueprint.py +102 -0
  51. pysual-0.1.2/src/pysual/_build_assets.py +53 -0
  52. pysual-0.1.2/src/pysual/_catalog.py +91 -0
  53. pysual-0.1.2/src/pysual/_config.py +236 -0
  54. pysual-0.1.2/src/pysual/_controls/__init__.py +5 -0
  55. pysual-0.1.2/src/pysual/_controls/actions.py +164 -0
  56. pysual-0.1.2/src/pysual/_controls/basic.py +150 -0
  57. pysual-0.1.2/src/pysual/_controls/choices.py +253 -0
  58. pysual-0.1.2/src/pysual/_controls/indicators.py +328 -0
  59. pysual-0.1.2/src/pysual/_controls/lists.py +261 -0
  60. pysual-0.1.2/src/pysual/_controls/media.py +39 -0
  61. pysual-0.1.2/src/pysual/_controls/ranges.py +357 -0
  62. pysual-0.1.2/src/pysual/_controls/viewports.py +148 -0
  63. pysual-0.1.2/src/pysual/_controls/windows.py +324 -0
  64. pysual-0.1.2/src/pysual/_drawing.py +70 -0
  65. pysual-0.1.2/src/pysual/_engine.py +718 -0
  66. pysual-0.1.2/src/pysual/_factory_types.py +8 -0
  67. pysual-0.1.2/src/pysual/_factory_types.pyi +1137 -0
  68. pysual-0.1.2/src/pysual/_grapheme_data.py +2025 -0
  69. pysual-0.1.2/src/pysual/_image_fit.py +22 -0
  70. pysual-0.1.2/src/pysual/_modality.py +327 -0
  71. pysual-0.1.2/src/pysual/_namespace_handlers.py +105 -0
  72. pysual-0.1.2/src/pysual/_nine_slice.py +41 -0
  73. pysual-0.1.2/src/pysual/_png.py +339 -0
  74. pysual-0.1.2/src/pysual/_ranges.py +35 -0
  75. pysual-0.1.2/src/pysual/_registry.py +173 -0
  76. pysual-0.1.2/src/pysual/_scrolling.py +140 -0
  77. pysual-0.1.2/src/pysual/_terminal_data.py +124 -0
  78. pysual-0.1.2/src/pysual/_text_display.py +6 -0
  79. pysual-0.1.2/src/pysual/_value_bag.py +20 -0
  80. pysual-0.1.2/src/pysual/_value_bag.pyi +69 -0
  81. pysual-0.1.2/src/pysual/app.py +441 -0
  82. pysual-0.1.2/src/pysual/assets/DejaVu-LICENSE.txt +187 -0
  83. pysual-0.1.2/src/pysual/assets/DejaVuSans.ttf +0 -0
  84. pysual-0.1.2/src/pysual/assets/DejaVuSansMono.ttf +0 -0
  85. pysual-0.1.2/src/pysual/assets/UNICODE-LICENSE.txt +39 -0
  86. pysual-0.1.2/src/pysual/assets/manifest.json +12 -0
  87. pysual-0.1.2/src/pysual/autoconfig.py +11 -0
  88. pysual-0.1.2/src/pysual/backends/__init__.py +140 -0
  89. pysual-0.1.2/src/pysual/backends/_files.py +190 -0
  90. pysual-0.1.2/src/pysual/backends/_font.py +182 -0
  91. pysual-0.1.2/src/pysual/backends/_gradient.py +29 -0
  92. pysual-0.1.2/src/pysual/backends/_native.py +105 -0
  93. pysual-0.1.2/src/pysual/backends/_native_client.py +592 -0
  94. pysual-0.1.2/src/pysual/backends/_term_cells.py +1007 -0
  95. pysual-0.1.2/src/pysual/backends/_term_images.py +278 -0
  96. pysual-0.1.2/src/pysual/backends/_term_input.py +299 -0
  97. pysual-0.1.2/src/pysual/backends/_term_io.py +284 -0
  98. pysual-0.1.2/src/pysual/backends/_term_session.py +516 -0
  99. pysual-0.1.2/src/pysual/backends/_web_native.py +949 -0
  100. pysual-0.1.2/src/pysual/backends/_web_pyodide.py +410 -0
  101. pysual-0.1.2/src/pysual/backends/_web_svg.py +957 -0
  102. pysual-0.1.2/src/pysual/backends/native.py +714 -0
  103. pysual-0.1.2/src/pysual/backends/term_text.py +744 -0
  104. pysual-0.1.2/src/pysual/backends/terminal.py +358 -0
  105. pysual-0.1.2/src/pysual/backends/web.py +32 -0
  106. pysual-0.1.2/src/pysual/behaviors.py +94 -0
  107. pysual-0.1.2/src/pysual/bundle.py +210 -0
  108. pysual-0.1.2/src/pysual/cards.py +458 -0
  109. pysual-0.1.2/src/pysual/charts.py +441 -0
  110. pysual-0.1.2/src/pysual/cli.py +296 -0
  111. pysual-0.1.2/src/pysual/commands.py +123 -0
  112. pysual-0.1.2/src/pysual/composition.py +426 -0
  113. pysual-0.1.2/src/pysual/controls.py +1348 -0
  114. pysual-0.1.2/src/pysual/data_grid.py +1173 -0
  115. pysual-0.1.2/src/pysual/dates.py +359 -0
  116. pysual-0.1.2/src/pysual/editing.py +178 -0
  117. pysual-0.1.2/src/pysual/editors.py +372 -0
  118. pysual-0.1.2/src/pysual/errors.py +25 -0
  119. pysual-0.1.2/src/pysual/events.py +489 -0
  120. pysual-0.1.2/src/pysual/extras.py +113 -0
  121. pysual-0.1.2/src/pysual/feedback.py +399 -0
  122. pysual-0.1.2/src/pysual/fields.py +221 -0
  123. pysual-0.1.2/src/pysual/geometry.py +40 -0
  124. pysual-0.1.2/src/pysual/graphemes.py +141 -0
  125. pysual-0.1.2/src/pysual/hints.py +129 -0
  126. pysual-0.1.2/src/pysual/host.py +535 -0
  127. pysual-0.1.2/src/pysual/icons.py +308 -0
  128. pysual-0.1.2/src/pysual/image_resources.py +57 -0
  129. pysual-0.1.2/src/pysual/input.py +941 -0
  130. pysual-0.1.2/src/pysual/inspection.py +120 -0
  131. pysual-0.1.2/src/pysual/layout.py +875 -0
  132. pysual-0.1.2/src/pysual/menus.py +682 -0
  133. pysual-0.1.2/src/pysual/motion.py +273 -0
  134. pysual-0.1.2/src/pysual/navigation.py +458 -0
  135. pysual-0.1.2/src/pysual/painting.py +1562 -0
  136. pysual-0.1.2/src/pysual/popup.py +140 -0
  137. pysual-0.1.2/src/pysual/presentation.py +81 -0
  138. pysual-0.1.2/src/pysual/py.typed +0 -0
  139. pysual-0.1.2/src/pysual/render_cache.py +337 -0
  140. pysual-0.1.2/src/pysual/runtime.py +1112 -0
  141. pysual-0.1.2/src/pysual/schema.py +730 -0
  142. pysual-0.1.2/src/pysual/selection.py +15 -0
  143. pysual-0.1.2/src/pysual/text.py +1293 -0
  144. pysual-0.1.2/src/pysual/theme.py +1720 -0
  145. pysual-0.1.2/src/pysual/tree.py +534 -0
  146. pysual-0.1.2/src/pysual/web/__init__.py +1 -0
  147. pysual-0.1.2/src/pysual/web/host.js +329 -0
  148. pysual-0.1.2/src/pysual/web/input.js +52 -0
  149. pysual-0.1.2/src/pysual/web/live.html +31 -0
  150. pysual-0.1.2/src/pysual/web/live.js +195 -0
  151. pysual-0.1.2/src/pysual/web/notices/.gitattributes +3 -0
  152. pysual-0.1.2/src/pysual/web/notices/CPython-LICENSE.txt +1134 -0
  153. pysual-0.1.2/src/pysual/web/notices/Emscripten-LICENSE.txt +102 -0
  154. pysual-0.1.2/src/pysual/web/notices/HACL-LICENSE.txt +23 -0
  155. pysual-0.1.2/src/pysual/web/notices/LLVM-RUNTIME-LICENSES.txt +1266 -0
  156. pysual-0.1.2/src/pysual/web/notices/MiniLZ4-LICENSE.txt +29 -0
  157. pysual-0.1.2/src/pysual/web/notices/Pyodide-LICENSE.txt +373 -0
  158. pysual-0.1.2/src/pysual/web/notices/WEB-NOTICES.txt +42 -0
  159. pysual-0.1.2/src/pysual/web/notices/bzip2-LICENSE.txt +42 -0
  160. pysual-0.1.2/src/pysual/web/notices/hiwire-LICENSE.txt +373 -0
  161. pysual-0.1.2/src/pysual/web/notices/libffi-LICENSE.txt +21 -0
  162. pysual-0.1.2/src/pysual/web/notices/manifest.json +429 -0
  163. pysual-0.1.2/src/pysual/web/notices/musl-COPYRIGHT.txt +193 -0
  164. pysual-0.1.2/src/pysual/web/notices/musl-INCORPORATED-NOTICES.txt +1000 -0
  165. pysual-0.1.2/src/pysual/web/notices/zlib-LICENSE.txt +22 -0
  166. pysual-0.1.2/src/pysual/web/services.js +217 -0
  167. pysual-0.1.2/src/pysual/web/standalone.js +91 -0
  168. pysual-0.1.2/src/pysual/web/svg.js +254 -0
  169. pysual-0.1.2/src/pysual/widgets.py +22 -0
  170. pysual-0.1.2/src/pysual.egg-info/PKG-INFO +236 -0
  171. pysual-0.1.2/src/pysual.egg-info/SOURCES.txt +339 -0
  172. pysual-0.1.2/src/pysual.egg-info/dependency_links.txt +1 -0
  173. pysual-0.1.2/src/pysual.egg-info/entry_points.txt +2 -0
  174. pysual-0.1.2/src/pysual.egg-info/requires.txt +12 -0
  175. pysual-0.1.2/src/pysual.egg-info/top_level.txt +1 -0
  176. pysual-0.1.2/tests/_support.py +85 -0
  177. pysual-0.1.2/tests/_terminal.py +33 -0
  178. pysual-0.1.2/tests/_ui_testcase.py +95 -0
  179. pysual-0.1.2/tests/fixtures/unicode/GraphemeBreakTest-17.0.0.txt +796 -0
  180. pysual-0.1.2/tests/test_activation.py +87 -0
  181. pysual-0.1.2/tests/test_api_recipes.py +55 -0
  182. pysual-0.1.2/tests/test_binding_ambiguity.py +97 -0
  183. pysual-0.1.2/tests/test_blueprints.py +261 -0
  184. pysual-0.1.2/tests/test_build.py +304 -0
  185. pysual-0.1.2/tests/test_build_includes.py +140 -0
  186. pysual-0.1.2/tests/test_build_native.py +208 -0
  187. pysual-0.1.2/tests/test_cards.py +356 -0
  188. pysual-0.1.2/tests/test_catalog_controls.py +97 -0
  189. pysual-0.1.2/tests/test_charts_hints.py +454 -0
  190. pysual-0.1.2/tests/test_clipboard_limits.py +89 -0
  191. pysual-0.1.2/tests/test_close_decisions.py +231 -0
  192. pysual-0.1.2/tests/test_composition_headers.py +53 -0
  193. pysual-0.1.2/tests/test_configuration.py +122 -0
  194. pysual-0.1.2/tests/test_construction.py +221 -0
  195. pysual-0.1.2/tests/test_control_families.py +263 -0
  196. pysual-0.1.2/tests/test_control_focus_scroll.py +69 -0
  197. pysual-0.1.2/tests/test_control_interactions.py +344 -0
  198. pysual-0.1.2/tests/test_control_registry.py +219 -0
  199. pysual-0.1.2/tests/test_control_updates.py +451 -0
  200. pysual-0.1.2/tests/test_core.py +940 -0
  201. pysual-0.1.2/tests/test_data_grid.py +976 -0
  202. pysual-0.1.2/tests/test_date_picker.py +367 -0
  203. pysual-0.1.2/tests/test_diagnostics.py +184 -0
  204. pysual-0.1.2/tests/test_editor_composition.py +283 -0
  205. pysual-0.1.2/tests/test_effect_clipping.py +155 -0
  206. pysual-0.1.2/tests/test_embedded_nul.py +411 -0
  207. pysual-0.1.2/tests/test_event_dispatch.py +168 -0
  208. pysual-0.1.2/tests/test_examples.py +518 -0
  209. pysual-0.1.2/tests/test_extras.py +154 -0
  210. pysual-0.1.2/tests/test_factory_type_generator.py +157 -0
  211. pysual-0.1.2/tests/test_feedback_controls.py +380 -0
  212. pysual-0.1.2/tests/test_fixed_captions.py +336 -0
  213. pysual-0.1.2/tests/test_fixed_collection_rows.py +348 -0
  214. pysual-0.1.2/tests/test_fixed_popup_rows.py +153 -0
  215. pysual-0.1.2/tests/test_focus_navigation.py +225 -0
  216. pysual-0.1.2/tests/test_font_metrics.py +48 -0
  217. pysual-0.1.2/tests/test_grid_clipboard.py +95 -0
  218. pysual-0.1.2/tests/test_grid_presentation.py +375 -0
  219. pysual-0.1.2/tests/test_hit_index.py +241 -0
  220. pysual-0.1.2/tests/test_interval_indicators.py +353 -0
  221. pysual-0.1.2/tests/test_layouts.py +387 -0
  222. pysual-0.1.2/tests/test_library.py +862 -0
  223. pysual-0.1.2/tests/test_literal_properties.py +188 -0
  224. pysual-0.1.2/tests/test_marker_styles.py +113 -0
  225. pysual-0.1.2/tests/test_measure_cache.py +342 -0
  226. pysual-0.1.2/tests/test_measure_cache_runtime.py +149 -0
  227. pysual-0.1.2/tests/test_menus.py +329 -0
  228. pysual-0.1.2/tests/test_model_gate.py +301 -0
  229. pysual-0.1.2/tests/test_motion.py +388 -0
  230. pysual-0.1.2/tests/test_namespace_handlers.py +435 -0
  231. pysual-0.1.2/tests/test_native_client_startup.py +203 -0
  232. pysual-0.1.2/tests/test_native_clipboard_bounds.py +84 -0
  233. pysual-0.1.2/tests/test_native_image_limits.py +160 -0
  234. pysual-0.1.2/tests/test_native_io_progress.py +289 -0
  235. pysual-0.1.2/tests/test_native_message_wait.py +31 -0
  236. pysual-0.1.2/tests/test_native_metric_cache.py +137 -0
  237. pysual-0.1.2/tests/test_native_palette.py +72 -0
  238. pysual-0.1.2/tests/test_native_protocol.py +529 -0
  239. pysual-0.1.2/tests/test_native_reader_buffering.py +132 -0
  240. pysual-0.1.2/tests/test_native_resources.py +217 -0
  241. pysual-0.1.2/tests/test_native_runtime.py +128 -0
  242. pysual-0.1.2/tests/test_native_scene_parity.py +197 -0
  243. pysual-0.1.2/tests/test_native_terminal.py +746 -0
  244. pysual-0.1.2/tests/test_native_text.py +73 -0
  245. pysual-0.1.2/tests/test_native_wake_batches.py +138 -0
  246. pysual-0.1.2/tests/test_native_window.py +757 -0
  247. pysual-0.1.2/tests/test_navigation_controls.py +356 -0
  248. pysual-0.1.2/tests/test_packaging.py +201 -0
  249. pysual-0.1.2/tests/test_png_codec.py +354 -0
  250. pysual-0.1.2/tests/test_popup_owner_input.py +214 -0
  251. pysual-0.1.2/tests/test_popup_themes.py +103 -0
  252. pysual-0.1.2/tests/test_press_behaviors.py +363 -0
  253. pysual-0.1.2/tests/test_range_composition.py +131 -0
  254. pysual-0.1.2/tests/test_range_polish.py +207 -0
  255. pysual-0.1.2/tests/test_rating.py +250 -0
  256. pysual-0.1.2/tests/test_render_cache.py +163 -0
  257. pysual-0.1.2/tests/test_retained_paint.py +510 -0
  258. pysual-0.1.2/tests/test_search_field.py +434 -0
  259. pysual-0.1.2/tests/test_segment_batches.py +88 -0
  260. pysual-0.1.2/tests/test_selection.py +493 -0
  261. pysual-0.1.2/tests/test_shutdown.py +49 -0
  262. pysual-0.1.2/tests/test_stress_measurements.py +254 -0
  263. pysual-0.1.2/tests/test_stress_test.py +282 -0
  264. pysual-0.1.2/tests/test_style_composition.py +182 -0
  265. pysual-0.1.2/tests/test_terminal_image_loading.py +331 -0
  266. pysual-0.1.2/tests/test_terminal_selection.py +173 -0
  267. pysual-0.1.2/tests/test_terminal_signals.py +89 -0
  268. pysual-0.1.2/tests/test_terminal_surfaces.py +256 -0
  269. pysual-0.1.2/tests/test_text.py +146 -0
  270. pysual-0.1.2/tests/test_text_autoscroll.py +147 -0
  271. pysual-0.1.2/tests/test_text_composition_fonts.py +341 -0
  272. pysual-0.1.2/tests/test_text_hit_cache.py +76 -0
  273. pysual-0.1.2/tests/test_text_tabs_clicks.py +277 -0
  274. pysual-0.1.2/tests/test_text_visual_navigation.py +251 -0
  275. pysual-0.1.2/tests/test_theme_catalog.py +103 -0
  276. pysual-0.1.2/tests/test_theme_surfaces.py +700 -0
  277. pysual-0.1.2/tests/test_transparent_properties.py +425 -0
  278. pysual-0.1.2/tests/test_tree.py +335 -0
  279. pysual-0.1.2/tests/test_tree_updates.py +262 -0
  280. pysual-0.1.2/tests/test_unicode_generators.py +95 -0
  281. pysual-0.1.2/tests/test_value_editors.py +318 -0
  282. pysual-0.1.2/tests/test_verified_layout_interactions.py +313 -0
  283. pysual-0.1.2/tests/test_visual_capture.py +42 -0
  284. pysual-0.1.2/tests/test_web_app.py +48 -0
  285. pysual-0.1.2/tests/test_web_bridge.py +420 -0
  286. pysual-0.1.2/tests/test_web_build.py +136 -0
  287. pysual-0.1.2/tests/test_web_compression.py +247 -0
  288. pysual-0.1.2/tests/test_web_delivery.py +411 -0
  289. pysual-0.1.2/tests/test_web_gradients.py +75 -0
  290. pysual-0.1.2/tests/test_web_stable_ids.py +264 -0
  291. pysual-0.1.2/tests/test_web_svg.py +749 -0
  292. pysual-0.1.2/tests/test_web_transport.py +1223 -0
  293. pysual-0.1.2/tests/test_window_chrome.py +194 -0
  294. pysual-0.1.2/tests/test_window_lifecycle.py +896 -0
  295. pysual-0.1.2/tests/typing/cards_feedback.py +44 -0
  296. pysual-0.1.2/tests/typing/indicators.py +38 -0
  297. pysual-0.1.2/tests/typing/invalid.py +88 -0
  298. pysual-0.1.2/tests/typing/marker_valid.py +13 -0
  299. pysual-0.1.2/tests/typing/navigation.py +42 -0
  300. pysual-0.1.2/tests/typing/pyrightconfig.json +7 -0
  301. pysual-0.1.2/tests/typing/terminal_invalid.py +18 -0
  302. pysual-0.1.2/tests/typing/terminal_valid.py +56 -0
  303. pysual-0.1.2/tests/typing/valid.py +170 -0
  304. pysual-0.1.2/tests/visual_baselines/windows/native/environment.json +13 -0
  305. pysual-0.1.2/tests/visual_baselines/windows/native/macos.png +0 -0
  306. pysual-0.1.2/tests/visual_baselines/windows/native/modern.png +0 -0
  307. pysual-0.1.2/tests/visual_baselines/windows/native/modern_dark.png +0 -0
  308. pysual-0.1.2/tests/visual_baselines/windows/web/environment.json +35 -0
  309. pysual-0.1.2/tests/visual_baselines/windows/web/macos.png +0 -0
  310. pysual-0.1.2/tests/visual_baselines/windows/web/modern.png +0 -0
  311. pysual-0.1.2/tests/visual_baselines/windows/web/modern_dark.png +0 -0
  312. pysual-0.1.2/tests/web/_web_native.test.mjs +342 -0
  313. pysual-0.1.2/tests/web/_web_pyodide.test.mjs +989 -0
  314. pysual-0.1.2/tests/web/browser_services.test.mjs +143 -0
  315. pysual-0.1.2/tests/web/build_asset_smoke.py +95 -0
  316. pysual-0.1.2/tools/_benchmark.py +33 -0
  317. pysual-0.1.2/tools/_unicode_data.py +94 -0
  318. pysual-0.1.2/tools/benchmark_bindings.py +100 -0
  319. pysual-0.1.2/tools/benchmark_core.py +348 -0
  320. pysual-0.1.2/tools/benchmark_png.py +71 -0
  321. pysual-0.1.2/tools/benchmark_web_scene.py +70 -0
  322. pysual-0.1.2/tools/check_frozen.py +71 -0
  323. pysual-0.1.2/tools/check_typing.py +229 -0
  324. pysual-0.1.2/tools/check_visual.py +241 -0
  325. pysual-0.1.2/tools/check_web.py +592 -0
  326. pysual-0.1.2/tools/check_wheel.py +78 -0
  327. pysual-0.1.2/tools/fetch_native_deps.py +176 -0
  328. pysual-0.1.2/tools/frozen_probe.py +93 -0
  329. pysual-0.1.2/tools/generate_factory_types.py +139 -0
  330. pysual-0.1.2/tools/generate_graphemes.py +29 -0
  331. pysual-0.1.2/tools/generate_terminal_unicode.py +153 -0
  332. pysual-0.1.2/tools/native.py +286 -0
  333. pysual-0.1.2/tools/unicode_data/15.1.0-DerivedCoreProperties.txt.gz +0 -0
  334. pysual-0.1.2/tools/unicode_data/15.1.0-EastAsianWidth.txt.gz +0 -0
  335. pysual-0.1.2/tools/unicode_data/15.1.0-SpecialCasing.txt.gz +0 -0
  336. pysual-0.1.2/tools/unicode_data/15.1.0-UnicodeData.txt.gz +0 -0
  337. pysual-0.1.2/tools/unicode_data/17.0.0-DerivedCoreProperties.txt.gz +0 -0
  338. pysual-0.1.2/tools/unicode_data/17.0.0-GraphemeBreakProperty.txt.gz +0 -0
  339. pysual-0.1.2/tools/unicode_data/17.0.0-emoji-data.txt.gz +0 -0
  340. pysual-0.1.2/tools/unicode_data/README.md +22 -0
  341. pysual-0.1.2/tools/wheel_probe.py +135 -0
@@ -0,0 +1,13 @@
1
+ # Match the existing native renderer's four-space, attached-brace style.
2
+ # Apply to hand-written files explicitly; leave vendor and generated code alone.
3
+ BasedOnStyle: LLVM
4
+ IndentWidth: 4
5
+ ColumnLimit: 120
6
+ BreakBeforeBraces: Attach
7
+ AllowShortFunctionsOnASingleLine: None
8
+ AllowShortIfStatementsOnASingleLine: Never
9
+ AllowShortLoopsOnASingleLine: false
10
+ AllowShortBlocksOnASingleLine: Never
11
+ PointerAlignment: Right
12
+ SortIncludes: Never
13
+ ReflowComments: false
@@ -0,0 +1,49 @@
1
+ # Changelog
2
+
3
+ ## 0.1.2 — 2026-10-16
4
+
5
+ Published releases install with `pip install pysual`. Windows x64, Linux x64,
6
+ and Apple Silicon wheels include the native window host and its SDL libraries.
7
+ Other platforms receive the pure-Python wheel, with the Python terminal and web
8
+ backends. A `v*` tag that matches `__version__` builds those wheels, checks
9
+ them outside the build SDK, and publishes the GitHub Release and the PyPI files.
10
+
11
+ Linux wheels require glibc 2.28 or newer. X11, Wayland, OpenGL, and GLib stay
12
+ on the recipient's machine.
13
+
14
+ ## 0.1.1 — 2026-10-09
15
+
16
+ First public release of Pysual, a Python 3.11+ UI library for native windows,
17
+ terminals, and the web. It includes 43 controls, 18 themes, typed factories,
18
+ Unicode text editing, retained rendering, and executable/HTML build tools.
19
+
20
+ ### Fixes
21
+
22
+ - Keep the C terminal session usable when a paste exceeds the encoded event
23
+ budget, and encode common control characters compactly.
24
+ - Bound caption measurement work so long Unicode labels do not exceed native
25
+ batch or transport limits.
26
+ - Preserve text-selection autoscroll when rendering is delayed or the frame
27
+ rate is low.
28
+ - Validate default numeric grid formatting before accepting rows and edits.
29
+ - Isolate chart axis formatting from an application's Decimal precision and
30
+ exception traps.
31
+ - Reject unsupported native animation metadata before retaining or comparing
32
+ commands.
33
+ - Clarify when installed packages need a prebuilt native host or a source
34
+ checkout for executable builds.
35
+
36
+ ### Supported scope
37
+
38
+ The API remains in early development. Native builds target Windows, Linux, and
39
+ macOS; the Python terminal and live web hosts also work without a native helper.
40
+ Standalone web applications require a browser with WebAssembly JSPI support.
41
+ Linux/macOS native library wheels require their documented SDL shared libraries
42
+ unless separately bundled and repaired. Build frozen applications on their
43
+ target OS and architecture.
44
+
45
+ Controls are custom drawn. OS accessibility bridges, complex-script shaping,
46
+ full font fallback, mobile hosts, and OS-level modality across native processes
47
+ are not provided in this release. See [building](docs/building.md),
48
+ [native rendering](docs/native.md), and [web delivery](docs/web.md) for platform
49
+ requirements and validation commands.
@@ -0,0 +1,42 @@
1
+ # Contributing
2
+
3
+ Pysual is the library, the `pysual` import, and the `pysual` installable package.
4
+ The repository is [Pysual](https://github.com/PabloMP2P/Pysual).
5
+
6
+ ## Setup
7
+
8
+ ```sh
9
+ git clone https://github.com/PabloMP2P/Pysual.git
10
+ cd Pysual
11
+ python -m venv .venv
12
+ # Activate .venv using your shell, then:
13
+ python -m pip install -e '.[dev,build]'
14
+ python -m pytest
15
+ ```
16
+
17
+ The [README](README.md#develop) covers the factory-type generator.
18
+ [Building](docs/building.md) covers the typing check, native build, compilers,
19
+ and packaging.
20
+
21
+ ## Style
22
+
23
+ Python follows [PEP 8](https://peps.python.org/pep-0008/). Match the module you
24
+ are editing, including its import order and docstring style.
25
+
26
+ Hand-written C in `native/host.c`, `native/sdl_renderer.c`, and
27
+ `native/terminal_renderer.c` follows `.clang-format`. Leave generated Unicode
28
+ tables and vendor sources unchanged.
29
+
30
+ ## Commits
31
+
32
+ Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/):
33
+
34
+ ```
35
+ type: short imperative summary
36
+ ```
37
+
38
+ An optional scope is fine: `fix(terminal): keep selection inside the viewport`.
39
+
40
+ Use `feat`, `fix`, `docs`, `test`, `refactor`, `build`, `ci`, or `chore`.
41
+ Write the summary in the imperative, lowercase, with no trailing period.
42
+ Keep each commit to one logical change.
pysual-0.1.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pablo Soto
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,19 @@
1
+ include README.md CONTRIBUTING.md CHANGELOG.md LICENSE pyproject.toml setup.py .clang-format
2
+ recursive-include src/pysual *.py *.pyi *.typed *.js *.html *.ttf *LICENSE* *.txt *.json
3
+ include src/pysual/web/notices/.gitattributes
4
+ recursive-include native *.c *.h *LICENSE*
5
+ recursive-include native/notices *.txt *.json .gitattributes
6
+ recursive-include tools *.py *.md *.gz
7
+ recursive-include examples *.py
8
+ recursive-include docs *.md
9
+ include docs/theme-families.png
10
+ recursive-include tests *.py *.mjs *.txt
11
+ recursive-include tests/visual_baselines *.png *.json *.md
12
+ include pyrightconfig.json examples/pyrightconfig.json tests/typing/pyrightconfig.json
13
+ recursive-exclude src/pysual/bin *
14
+ prune .build
15
+ prune .venv
16
+ prune build
17
+ prune dist
18
+ prune work
19
+ global-exclude __pycache__ *.py[cod] *.exe *.dll *.so *.dylib *.o *.obj
pysual-0.1.2/PKG-INFO ADDED
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysual
3
+ Version: 0.1.2
4
+ Summary: Python interfaces for native windows, terminals, and the web
5
+ Author: Pysual contributors
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/PabloMP2P/Pysual
8
+ Project-URL: Documentation, https://github.com/PabloMP2P/Pysual/blob/main/docs/api.md
9
+ Project-URL: Issues, https://github.com/PabloMP2P/Pysual/issues
10
+ Keywords: gui,ui,widgets,sdl3,terminal,tui,svg,web,pyodide
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Environment :: Console
20
+ Classifier: Environment :: Web Environment
21
+ Classifier: Topic :: Software Development :: User Interfaces
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: build
27
+ Requires-Dist: pyinstaller<7,>=6.16; extra == "build"
28
+ Requires-Dist: build>=1.2; extra == "build"
29
+ Requires-Dist: setuptools>=77; extra == "build"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=8; extra == "dev"
32
+ Requires-Dist: pillow>=10; extra == "dev"
33
+ Requires-Dist: setuptools>=77; extra == "dev"
34
+ Requires-Dist: playwright<2,>=1.55; extra == "dev"
35
+ Requires-Dist: pyright<2,>=1.1.414; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # Pysual
39
+
40
+ Python interfaces for **Window**, **Terminal**, and **Web**.
41
+
42
+ Assign controls, change their properties, and name event handlers. The same
43
+ application runs in a native window, a terminal, or an SVG browser interface.
44
+ Python 3.11+. MIT licensed. Early development; APIs may change.
45
+
46
+ See the [0.1.2 release notes](https://github.com/PabloMP2P/Pysual/blob/main/CHANGELOG.md) for fixes and supported scope.
47
+
48
+ ## Install
49
+
50
+ A published release installs with pip. Python 3.11 or newer:
51
+
52
+ ```sh
53
+ python -m pip install pysual
54
+ ```
55
+
56
+ Windows x64, Linux x64, and Apple Silicon wheels include the native window host
57
+ and the SDL libraries it needs. Other platforms receive the pure-Python wheel,
58
+ whose Python terminal and web backends are ready to use. Building a window host
59
+ for another platform is described in
60
+ [building](https://github.com/PabloMP2P/Pysual/blob/main/docs/building.md).
61
+
62
+ ## Start in a browser
63
+
64
+ ```sh
65
+ git clone https://github.com/PabloMP2P/Pysual.git
66
+ cd Pysual
67
+ python -m venv .venv
68
+ # Activate .venv using your shell, then:
69
+ python -m pip install -e '.[dev,build]'
70
+ python examples/hello.py --backend web
71
+ ```
72
+
73
+ Activate with `.venv\Scripts\Activate.ps1` in PowerShell or
74
+ `source .venv/bin/activate` on macOS/Linux. The live Web host and Python terminal
75
+ renderer need no graphics packages or C compiler. For library-only installation,
76
+ use `python -m pip install .`.
77
+
78
+ ```sh
79
+ python examples/hello.py --backend terminal --terminal python
80
+ python -m pysual native
81
+ python examples/hello.py --backend window
82
+ ```
83
+
84
+ The native builder finds a C compiler and provisions checksum-pinned SDL
85
+ development packages on Windows. Linux/macOS require a C11 compiler,
86
+ `pkg-config`, SDL3, SDL3_ttf, and SDL3_image development libraries.
87
+ See [building](https://github.com/PabloMP2P/Pysual/blob/main/docs/building.md) for compiler and platform details.
88
+
89
+ ## Write an application
90
+
91
+ ```python
92
+ from pysual import App, Button, Label
93
+
94
+ class Hello(App):
95
+ def build(self):
96
+ self.title = "Hello"
97
+ self.layout, self.padding, self.spacing = "stack", 24, 12
98
+ self.message = Label(text="Ready")
99
+ self.greet = Button(text="Say hello")
100
+
101
+ def greet_on_click(self, event):
102
+ self.message.text = "Hello, Pysual!"
103
+
104
+ Hello().run_blocking(backend="web")
105
+ ```
106
+
107
+ Assignment adopts and names each control; `greet_on_click` binds automatically.
108
+ Names must not collide with existing members: the factory names `label`,
109
+ `button`, `image`, `slider`, `menu` and the other snake-case control names are
110
+ taken, so prefer descriptive names such as `message` or `save_button`
111
+ (a `BindingError` names the conflict). Handlers can be synchronous or `async def`. Properties and public methods route
112
+ to the UI owner automatically. `run()` returns after the first frame for REPLs
113
+ and scripts doing other work; `wait()` waits for closure. `run_blocking()` combines
114
+ the two. Import `pysual.autoconfig` before creating controls to enable
115
+ `--backend`, `--terminal`, `--pysual-theme`, and `--pysual-scale` in your own script.
116
+
117
+ ## Three backends
118
+
119
+ | Backend | Runtime | Distribution |
120
+ | --- | --- | --- |
121
+ | `window` | Standalone C renderer with SDL3, text, images, effects, retained scenes, and native animations | Executable for the build machine's OS and architecture |
122
+ | `terminal` | C character renderer; `auto`, `c`, or `python` renderer selection | Executable, including a Python-only option requiring no C build |
123
+ | `web` | SVG with local Python when served; Python in Pyodide when bundled | One HTML file embedding the application, fonts, and runtime |
124
+
125
+ Terminal `auto` prefers an available C host and falls back to Python when it
126
+ cannot start. Choose `--terminal c` to require C, or `--terminal python` for a
127
+ dependency-free renderer. Terminal typography follows the emulator's cell grid.
128
+
129
+ ```sh
130
+ python -m pysual examples/hello.py --backend window -o dist/hello.exe
131
+ python -m pysual examples/hello.py --backend terminal --terminal python -o dist/hello-terminal.exe
132
+ python -m pysual examples/hello.py --backend web -o dist/hello.html
133
+ ```
134
+
135
+ Use extensionless executable names on Linux/macOS. Build on each target OS;
136
+ these commands do not cross-compile. Outside a checkout the same commands are
137
+ `pysual build …` (or `python -m pysual build …`) after `pip install`. Web builds fetch a checksum-pinned Pyodide
138
+ runtime once; `--runtime PATH` makes subsequent builds fully local. Serve the
139
+ bundled HTML from a static HTTP host. Application handlers remain Python and
140
+ need no application Python server. See [Web delivery](https://github.com/PabloMP2P/Pysual/blob/main/docs/web.md).
141
+
142
+ ## Included
143
+
144
+ - 43 catalog controls: editable grids, virtual lists/trees, tabs, menus, dialogs,
145
+ text and value editors, charts, range selection, navigation, choice cards,
146
+ disclosure groups, badges, actionable alerts, meters, and progress.
147
+ - Five layout modes, nine theme families in light and dark (18 themes), 44 icons, bundled fonts, shadows, gradients,
148
+ surfaces, interaction motion, and custom painting.
149
+ - Unicode text editing, selection, clipboard where supported, undo/redo,
150
+ async events, drag/drop, and batched property updates.
151
+ - Retained rendering, bounded caches, on-demand frames, and incremental native
152
+ scene updates.
153
+
154
+ | Example | What it demonstrates |
155
+ | --- | --- |
156
+ | [hello.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/hello.py) | Automatic binding, text input, async events |
157
+ | [dashboard.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/dashboard.py) | Editable data, filtering, charts |
158
+ | [showcase.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/showcase.py) | Controls, themes, layout, effects |
159
+ | [theme_gallery.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/theme_gallery.py) | An interactive control studio with all nine theme families, light/dark switching, and desktop-inspired materials |
160
+ | [stress_test.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/stress_test.py) | Configurable control mixes, workloads, timing, and JSON reports |
161
+ | [custom_control.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/custom_control.py) | Observable properties and portable drawing |
162
+ | [composite_control.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/composite_control.py) | Reusable compound controls with independent child state and handlers |
163
+ | [catalog_controls.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/catalog_controls.py) | Thirteen catalog ideas in a responsive review workspace with collapsible filters, review plans, status feedback, and live theme switching |
164
+
165
+ Choose Modern, Windows, macOS, Terminal, Win31, WinXP, Macintosh, Analog arcade,
166
+ or Neon. Each has a light and dark version with its own control surfaces,
167
+ typography, borders, and interaction states. Preview them with:
168
+
169
+ ```sh
170
+ python examples/theme_gallery.py --backend web
171
+ ```
172
+
173
+ See the [rendered comparison of all 18 appearances](https://github.com/PabloMP2P/Pysual/blob/main/docs/theme-families.png).
174
+
175
+ Use `get_theme("winxp")` for light and `get_theme("winxp_dark")` for dark.
176
+ See [themes and custom painting](https://github.com/PabloMP2P/Pysual/blob/main/docs/api.md#themes-and-custom-painting) for the
177
+ complete catalog and compatibility details.
178
+
179
+ ### Stress test
180
+
181
+ The stress lab mixes 20 control types, including grids, trees, charts, images,
182
+ and editors. Choose balanced, text, forms, visual, or collections scenes, with
183
+ presets from 100 to 5,000 controls or an exact count up to 20,000. It opens on
184
+ the large preset with continuous redraw and VSync off.
185
+
186
+ ```sh
187
+ python examples/stress_test.py --backend window --controls 2000 --mix balanced --workload local-update
188
+ python examples/stress_test.py --backend terminal --terminal python --controls 100 --mix forms
189
+ python examples/stress_test.py --backend web --mix visual
190
+ python examples/stress_test.py --controls 500 --workload property --fraction 0.25 --rate 60 --warmup 2 --duration 10 --report work/stress.json
191
+ ```
192
+
193
+ Changing a preset or another dashboard control applies it immediately. Pause,
194
+ restart measurements, or export a JSON report from the same bar. `--help` lists
195
+ the control mixes and rendering options. Timed runs
196
+ measure `--duration` seconds after warmup. Use the same seed, viewport, theme,
197
+ workload, and rendering settings when comparing runs.
198
+
199
+ Workloads cover idle scenes, paint invalidation, layout changes, property
200
+ updates, and one-control updates. Rendering options include the presentation
201
+ cap, redraw interval, VSync, body reuse, and surface-cache budget.
202
+
203
+ Python submission rates, native presentation loops, and terminal output counters
204
+ are reported separately. These do not measure physical screen refresh or browser
205
+ paint. Live metrics refresh at 4 Hz by default and add work to a static scene;
206
+ pass `--no-telemetry` to leave them on demand. Collection rows and chart points
207
+ are counted separately from widgets.
208
+
209
+ ## Develop
210
+
211
+ Style and commit conventions are in [Contributing](https://github.com/PabloMP2P/Pysual/blob/main/CONTRIBUTING.md).
212
+
213
+ ```sh
214
+ python -m pytest
215
+ python tools/check_typing.py
216
+ ```
217
+
218
+ After changing control properties, run `python tools/generate_factory_types.py`
219
+ to refresh the factory typing signatures. Add `--check` to verify them without
220
+ writing changes; the generator needs only the Python standard library.
221
+
222
+ For new controls, see [control composition and catalog development](https://github.com/PabloMP2P/Pysual/blob/main/docs/control-architecture.md).
223
+
224
+ The full test suite requires Node.js 24 for the Web JavaScript contracts.
225
+ Native tests require a built host and report explicit skips otherwise. CI builds
226
+ and checks the native implementation separately. Applications need no Node.js
227
+ or npm project.
228
+
229
+ [API guide](https://github.com/PabloMP2P/Pysual/blob/main/docs/api.md) · [Native rendering](https://github.com/PabloMP2P/Pysual/blob/main/docs/native.md) ·
230
+ [Building](https://github.com/PabloMP2P/Pysual/blob/main/docs/building.md) · [Web](https://github.com/PabloMP2P/Pysual/blob/main/docs/web.md) ·
231
+ [Contributing](https://github.com/PabloMP2P/Pysual/blob/main/CONTRIBUTING.md)
232
+
233
+ Controls are custom drawn. OS accessibility bridges, complex-script shaping,
234
+ full font fallback, mobile hosts, and OS-level modality between separate native
235
+ processes are outside this release's supported scope. Real display, terminal,
236
+ clipboard, IME, and packaged-app behavior should be checked on the target system.
pysual-0.1.2/README.md ADDED
@@ -0,0 +1,199 @@
1
+ # Pysual
2
+
3
+ Python interfaces for **Window**, **Terminal**, and **Web**.
4
+
5
+ Assign controls, change their properties, and name event handlers. The same
6
+ application runs in a native window, a terminal, or an SVG browser interface.
7
+ Python 3.11+. MIT licensed. Early development; APIs may change.
8
+
9
+ See the [0.1.2 release notes](https://github.com/PabloMP2P/Pysual/blob/main/CHANGELOG.md) for fixes and supported scope.
10
+
11
+ ## Install
12
+
13
+ A published release installs with pip. Python 3.11 or newer:
14
+
15
+ ```sh
16
+ python -m pip install pysual
17
+ ```
18
+
19
+ Windows x64, Linux x64, and Apple Silicon wheels include the native window host
20
+ and the SDL libraries it needs. Other platforms receive the pure-Python wheel,
21
+ whose Python terminal and web backends are ready to use. Building a window host
22
+ for another platform is described in
23
+ [building](https://github.com/PabloMP2P/Pysual/blob/main/docs/building.md).
24
+
25
+ ## Start in a browser
26
+
27
+ ```sh
28
+ git clone https://github.com/PabloMP2P/Pysual.git
29
+ cd Pysual
30
+ python -m venv .venv
31
+ # Activate .venv using your shell, then:
32
+ python -m pip install -e '.[dev,build]'
33
+ python examples/hello.py --backend web
34
+ ```
35
+
36
+ Activate with `.venv\Scripts\Activate.ps1` in PowerShell or
37
+ `source .venv/bin/activate` on macOS/Linux. The live Web host and Python terminal
38
+ renderer need no graphics packages or C compiler. For library-only installation,
39
+ use `python -m pip install .`.
40
+
41
+ ```sh
42
+ python examples/hello.py --backend terminal --terminal python
43
+ python -m pysual native
44
+ python examples/hello.py --backend window
45
+ ```
46
+
47
+ The native builder finds a C compiler and provisions checksum-pinned SDL
48
+ development packages on Windows. Linux/macOS require a C11 compiler,
49
+ `pkg-config`, SDL3, SDL3_ttf, and SDL3_image development libraries.
50
+ See [building](https://github.com/PabloMP2P/Pysual/blob/main/docs/building.md) for compiler and platform details.
51
+
52
+ ## Write an application
53
+
54
+ ```python
55
+ from pysual import App, Button, Label
56
+
57
+ class Hello(App):
58
+ def build(self):
59
+ self.title = "Hello"
60
+ self.layout, self.padding, self.spacing = "stack", 24, 12
61
+ self.message = Label(text="Ready")
62
+ self.greet = Button(text="Say hello")
63
+
64
+ def greet_on_click(self, event):
65
+ self.message.text = "Hello, Pysual!"
66
+
67
+ Hello().run_blocking(backend="web")
68
+ ```
69
+
70
+ Assignment adopts and names each control; `greet_on_click` binds automatically.
71
+ Names must not collide with existing members: the factory names `label`,
72
+ `button`, `image`, `slider`, `menu` and the other snake-case control names are
73
+ taken, so prefer descriptive names such as `message` or `save_button`
74
+ (a `BindingError` names the conflict). Handlers can be synchronous or `async def`. Properties and public methods route
75
+ to the UI owner automatically. `run()` returns after the first frame for REPLs
76
+ and scripts doing other work; `wait()` waits for closure. `run_blocking()` combines
77
+ the two. Import `pysual.autoconfig` before creating controls to enable
78
+ `--backend`, `--terminal`, `--pysual-theme`, and `--pysual-scale` in your own script.
79
+
80
+ ## Three backends
81
+
82
+ | Backend | Runtime | Distribution |
83
+ | --- | --- | --- |
84
+ | `window` | Standalone C renderer with SDL3, text, images, effects, retained scenes, and native animations | Executable for the build machine's OS and architecture |
85
+ | `terminal` | C character renderer; `auto`, `c`, or `python` renderer selection | Executable, including a Python-only option requiring no C build |
86
+ | `web` | SVG with local Python when served; Python in Pyodide when bundled | One HTML file embedding the application, fonts, and runtime |
87
+
88
+ Terminal `auto` prefers an available C host and falls back to Python when it
89
+ cannot start. Choose `--terminal c` to require C, or `--terminal python` for a
90
+ dependency-free renderer. Terminal typography follows the emulator's cell grid.
91
+
92
+ ```sh
93
+ python -m pysual examples/hello.py --backend window -o dist/hello.exe
94
+ python -m pysual examples/hello.py --backend terminal --terminal python -o dist/hello-terminal.exe
95
+ python -m pysual examples/hello.py --backend web -o dist/hello.html
96
+ ```
97
+
98
+ Use extensionless executable names on Linux/macOS. Build on each target OS;
99
+ these commands do not cross-compile. Outside a checkout the same commands are
100
+ `pysual build …` (or `python -m pysual build …`) after `pip install`. Web builds fetch a checksum-pinned Pyodide
101
+ runtime once; `--runtime PATH` makes subsequent builds fully local. Serve the
102
+ bundled HTML from a static HTTP host. Application handlers remain Python and
103
+ need no application Python server. See [Web delivery](https://github.com/PabloMP2P/Pysual/blob/main/docs/web.md).
104
+
105
+ ## Included
106
+
107
+ - 43 catalog controls: editable grids, virtual lists/trees, tabs, menus, dialogs,
108
+ text and value editors, charts, range selection, navigation, choice cards,
109
+ disclosure groups, badges, actionable alerts, meters, and progress.
110
+ - Five layout modes, nine theme families in light and dark (18 themes), 44 icons, bundled fonts, shadows, gradients,
111
+ surfaces, interaction motion, and custom painting.
112
+ - Unicode text editing, selection, clipboard where supported, undo/redo,
113
+ async events, drag/drop, and batched property updates.
114
+ - Retained rendering, bounded caches, on-demand frames, and incremental native
115
+ scene updates.
116
+
117
+ | Example | What it demonstrates |
118
+ | --- | --- |
119
+ | [hello.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/hello.py) | Automatic binding, text input, async events |
120
+ | [dashboard.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/dashboard.py) | Editable data, filtering, charts |
121
+ | [showcase.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/showcase.py) | Controls, themes, layout, effects |
122
+ | [theme_gallery.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/theme_gallery.py) | An interactive control studio with all nine theme families, light/dark switching, and desktop-inspired materials |
123
+ | [stress_test.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/stress_test.py) | Configurable control mixes, workloads, timing, and JSON reports |
124
+ | [custom_control.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/custom_control.py) | Observable properties and portable drawing |
125
+ | [composite_control.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/composite_control.py) | Reusable compound controls with independent child state and handlers |
126
+ | [catalog_controls.py](https://github.com/PabloMP2P/Pysual/blob/main/examples/catalog_controls.py) | Thirteen catalog ideas in a responsive review workspace with collapsible filters, review plans, status feedback, and live theme switching |
127
+
128
+ Choose Modern, Windows, macOS, Terminal, Win31, WinXP, Macintosh, Analog arcade,
129
+ or Neon. Each has a light and dark version with its own control surfaces,
130
+ typography, borders, and interaction states. Preview them with:
131
+
132
+ ```sh
133
+ python examples/theme_gallery.py --backend web
134
+ ```
135
+
136
+ See the [rendered comparison of all 18 appearances](https://github.com/PabloMP2P/Pysual/blob/main/docs/theme-families.png).
137
+
138
+ Use `get_theme("winxp")` for light and `get_theme("winxp_dark")` for dark.
139
+ See [themes and custom painting](https://github.com/PabloMP2P/Pysual/blob/main/docs/api.md#themes-and-custom-painting) for the
140
+ complete catalog and compatibility details.
141
+
142
+ ### Stress test
143
+
144
+ The stress lab mixes 20 control types, including grids, trees, charts, images,
145
+ and editors. Choose balanced, text, forms, visual, or collections scenes, with
146
+ presets from 100 to 5,000 controls or an exact count up to 20,000. It opens on
147
+ the large preset with continuous redraw and VSync off.
148
+
149
+ ```sh
150
+ python examples/stress_test.py --backend window --controls 2000 --mix balanced --workload local-update
151
+ python examples/stress_test.py --backend terminal --terminal python --controls 100 --mix forms
152
+ python examples/stress_test.py --backend web --mix visual
153
+ python examples/stress_test.py --controls 500 --workload property --fraction 0.25 --rate 60 --warmup 2 --duration 10 --report work/stress.json
154
+ ```
155
+
156
+ Changing a preset or another dashboard control applies it immediately. Pause,
157
+ restart measurements, or export a JSON report from the same bar. `--help` lists
158
+ the control mixes and rendering options. Timed runs
159
+ measure `--duration` seconds after warmup. Use the same seed, viewport, theme,
160
+ workload, and rendering settings when comparing runs.
161
+
162
+ Workloads cover idle scenes, paint invalidation, layout changes, property
163
+ updates, and one-control updates. Rendering options include the presentation
164
+ cap, redraw interval, VSync, body reuse, and surface-cache budget.
165
+
166
+ Python submission rates, native presentation loops, and terminal output counters
167
+ are reported separately. These do not measure physical screen refresh or browser
168
+ paint. Live metrics refresh at 4 Hz by default and add work to a static scene;
169
+ pass `--no-telemetry` to leave them on demand. Collection rows and chart points
170
+ are counted separately from widgets.
171
+
172
+ ## Develop
173
+
174
+ Style and commit conventions are in [Contributing](https://github.com/PabloMP2P/Pysual/blob/main/CONTRIBUTING.md).
175
+
176
+ ```sh
177
+ python -m pytest
178
+ python tools/check_typing.py
179
+ ```
180
+
181
+ After changing control properties, run `python tools/generate_factory_types.py`
182
+ to refresh the factory typing signatures. Add `--check` to verify them without
183
+ writing changes; the generator needs only the Python standard library.
184
+
185
+ For new controls, see [control composition and catalog development](https://github.com/PabloMP2P/Pysual/blob/main/docs/control-architecture.md).
186
+
187
+ The full test suite requires Node.js 24 for the Web JavaScript contracts.
188
+ Native tests require a built host and report explicit skips otherwise. CI builds
189
+ and checks the native implementation separately. Applications need no Node.js
190
+ or npm project.
191
+
192
+ [API guide](https://github.com/PabloMP2P/Pysual/blob/main/docs/api.md) · [Native rendering](https://github.com/PabloMP2P/Pysual/blob/main/docs/native.md) ·
193
+ [Building](https://github.com/PabloMP2P/Pysual/blob/main/docs/building.md) · [Web](https://github.com/PabloMP2P/Pysual/blob/main/docs/web.md) ·
194
+ [Contributing](https://github.com/PabloMP2P/Pysual/blob/main/CONTRIBUTING.md)
195
+
196
+ Controls are custom drawn. OS accessibility bridges, complex-script shaping,
197
+ full font fallback, mobile hosts, and OS-level modality between separate native
198
+ processes are outside this release's supported scope. Real display, terminal,
199
+ clipboard, IME, and packaged-app behavior should be checked on the target system.