termapy 0.77.0__tar.gz → 0.78.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 (379) hide show
  1. termapy-0.78.0/LICENSE +21 -0
  2. {termapy-0.77.0 → termapy-0.78.0}/PKG-INFO +28 -17
  3. {termapy-0.77.0 → termapy-0.78.0}/README.md +21 -10
  4. termapy-0.78.0/pyproject.toml +149 -0
  5. termapy-0.77.0/pyproject.toml → termapy-0.78.0/pyproject.toml.orig +35 -12
  6. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/app.py +326 -341
  7. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/app_dirs.py +2 -6
  8. termapy-0.78.0/src/termapy/app_hooks.py +213 -0
  9. termapy-0.78.0/src/termapy/builtins/__init__.py +1 -0
  10. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/_cfg_icon.py +53 -30
  11. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/_crc_verbs.py +62 -27
  12. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/_run_record.py +6 -8
  13. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/_xmodem_handlers.py +22 -24
  14. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/app.py +1 -4
  15. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/cap.py +127 -73
  16. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/cfg.py +255 -63
  17. termapy-0.78.0/src/termapy/builtins/commands/delay.py +105 -0
  18. termapy-0.78.0/src/termapy/builtins/commands/demo.py +58 -0
  19. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/dev.py +63 -44
  20. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/edit.py +61 -44
  21. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/env.py +4 -1
  22. termapy-0.78.0/src/termapy/builtins/commands/expect.py +133 -0
  23. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/find.py +6 -9
  24. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/grep.py +8 -2
  25. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/help.py +40 -51
  26. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/log.py +61 -41
  27. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/mcp.py +22 -33
  28. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/mem.py +189 -107
  29. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/os_cmd.py +1 -3
  30. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/ping.py +1 -3
  31. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/port.py +67 -55
  32. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/profile.py +30 -34
  33. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/proto.py +254 -234
  34. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/raw.py +5 -5
  35. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/repeat.py +7 -2
  36. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/run.py +70 -13
  37. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/search.py +48 -37
  38. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/seq.py +3 -1
  39. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/show.py +1 -3
  40. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/sym.py +40 -30
  41. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/term.py +26 -45
  42. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/var.py +8 -17
  43. termapy-0.78.0/src/termapy/builtins/crc/__init__.py +1 -0
  44. termapy-0.78.0/src/termapy/builtins/demo/__init__.py +1 -0
  45. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/plugin/temp_plot.py +1 -4
  46. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/plugin/traffic.py +23 -20
  47. termapy-0.78.0/src/termapy/builtins/viz/__init__.py +1 -0
  48. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/viz/hex_view.py +3 -1
  49. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/viz/text_view.py +3 -1
  50. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/capture.py +3 -4
  51. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/capture_view.py +2 -37
  52. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/cli.py +90 -340
  53. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/cli_flags.py +108 -35
  54. termapy-0.78.0/src/termapy/cli_prompt.py +155 -0
  55. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/config.py +363 -32
  56. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/converters.py +3 -4
  57. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/credits_data.py +79 -33
  58. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/defaults.py +6 -3
  59. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/demo.py +91 -58
  60. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/demo_ndjson.py +2 -6
  61. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/demo_vt100.py +17 -11
  62. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/devices/__init__.py +55 -36
  63. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/devices/converters/__init__.py +5 -2
  64. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/devices/converters/svd.py +29 -12
  65. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/__init__.py +0 -4
  66. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/_common.py +158 -7
  67. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/cfg_confirm.py +3 -7
  68. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/config_editor.py +100 -39
  69. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/config_picker.py +36 -108
  70. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/confirm_dialog.py +2 -4
  71. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/filename_dialog.py +2 -10
  72. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/port_picker.py +6 -7
  73. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/proto_editor.py +15 -19
  74. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/proto_picker.py +87 -33
  75. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/quick_setup.py +37 -28
  76. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/script_editor.py +11 -19
  77. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/script_picker.py +67 -29
  78. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/set_var_dialog.py +5 -9
  79. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/dialogs/update_available.py +5 -7
  80. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/entry.py +94 -36
  81. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/folder_ops.py +33 -27
  82. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/folders.py +12 -10
  83. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/cli.md +1 -0
  84. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/commands.md +16 -12
  85. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/config.md +4 -4
  86. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/file-transfer.md +3 -1
  87. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/getting-started.md +21 -1
  88. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/installation.md +3 -3
  89. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/mcp-server.md +1 -1
  90. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/protocol-testing.md +5 -3
  91. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/scripting.md +6 -7
  92. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/serial-tools.md +10 -1
  93. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/symbols.md +2 -1
  94. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/writing-plugins.md +77 -55
  95. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help_dynamic.py +11 -6
  96. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/404.html +6 -6
  97. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/acknowledgments.html +6 -6
  98. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/authoring-profiles.html +6 -6
  99. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/cli.html +10 -6
  100. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/commands.html +36 -30
  101. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/config.html +10 -10
  102. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/custom-buttons.html +6 -6
  103. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/data-capture.html +6 -6
  104. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/demo.html +6 -6
  105. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/device-help.html +6 -6
  106. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/devices.html +6 -6
  107. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/environment.html +6 -6
  108. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/file-transfer.html +9 -7
  109. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/getting-started.html +51 -35
  110. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/index.html +6 -6
  111. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/installation.html +9 -9
  112. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/mcp-server.html +7 -7
  113. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/memory.html +6 -6
  114. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/on-ai-assistance.html +6 -6
  115. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/ports.html +6 -6
  116. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/protocol-testing.html +11 -9
  117. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/scripting.html +11 -25
  118. termapy-0.78.0/src/termapy/html/search.json +1 -0
  119. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/serial-tools.html +30 -21
  120. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/symbols.html +11 -10
  121. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/toolbar.html +6 -6
  122. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/using-git.html +6 -6
  123. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/variables.html +6 -6
  124. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/vt100.html +6 -6
  125. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/writing-plugins.html +176 -154
  126. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/info_views.py +4 -6
  127. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/legacy.py +29 -42
  128. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/markup.py +10 -4
  129. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/mcp/catalog.py +19 -18
  130. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/mcp/prompts.py +2 -4
  131. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/mcp/server.py +59 -124
  132. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/memory.py +32 -14
  133. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/memory_views.py +30 -11
  134. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/migration.py +14 -15
  135. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/pickers.py +38 -26
  136. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/capabilities.py +239 -83
  137. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/command.py +19 -23
  138. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/context.py +7 -6
  139. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/handles/__init__.py +1 -1
  140. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/handles/fs.py +1 -1
  141. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/handles/internal.py +34 -7
  142. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/handles/io.py +1 -1
  143. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/handles/serial.py +9 -3
  144. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/handles/ui.py +12 -13
  145. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/loader.py +3 -6
  146. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/output_levels.py +4 -6
  147. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/params.py +9 -20
  148. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/views.py +22 -7
  149. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/port_control.py +67 -68
  150. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/port_format.py +13 -9
  151. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/profile/loader.py +12 -15
  152. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/profile/matcher.py +3 -2
  153. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/profile/types.py +71 -43
  154. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/proto_debug.py +166 -135
  155. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/protocol/__init__.py +4 -38
  156. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/protocol/core.py +34 -13
  157. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/protocol/crc.py +19 -15
  158. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/protocol/runner.py +20 -9
  159. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/protocol/viz.py +4 -12
  160. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/repl.py +155 -330
  161. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/request_response.py +2 -1
  162. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/response_parsers.py +1 -3
  163. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/run_docstring.py +1 -1
  164. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/run_legacy.py +6 -11
  165. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/scripting.py +47 -37
  166. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/serial_engine.py +13 -8
  167. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/serial_port.py +6 -6
  168. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/address.py +6 -7
  169. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/converters/__init__.py +5 -2
  170. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/converters/xc32.py +31 -26
  171. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/format.py +21 -14
  172. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/session.py +16 -5
  173. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/table.py +48 -33
  174. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/terminal_host.py +122 -57
  175. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/title_bar.py +6 -8
  176. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/tree_render.py +3 -9
  177. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/update_check.py +13 -11
  178. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/usb/aliases.py +26 -26
  179. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/usb/vendors.py +6 -8
  180. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/usb_tree.py +52 -51
  181. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/variables.py +6 -7
  182. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/__init__.py +1 -1
  183. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vt100.py +8 -14
  184. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/widgets/suggester.py +1 -1
  185. termapy-0.77.0/src/termapy/app_hooks.py +0 -630
  186. termapy-0.77.0/src/termapy/builtins/demo/plugin/__init__.py +0 -0
  187. termapy-0.77.0/src/termapy/builtins/viz/__init__.py +0 -0
  188. termapy-0.77.0/src/termapy/builtins/viz/modbus_view.py.old +0 -163
  189. termapy-0.77.0/src/termapy/dialogs/name_picker.py +0 -68
  190. termapy-0.77.0/src/termapy/dialogs/welcome_dialog.py +0 -60
  191. termapy-0.77.0/src/termapy/html/search.json +0 -1
  192. termapy-0.77.0/src/termapy/run_profile_hooks.py +0 -192
  193. termapy-0.77.0/src/termapy/smoke.txt +0 -41
  194. termapy-0.77.0/src/termapy/vendor/serial/tools/__init__.py +0 -0
  195. termapy-0.77.0/src/termapy/vendor/serial/urlhandler/__init__.py +0 -0
  196. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/__init__.py +0 -0
  197. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/__main__.py +0 -0
  198. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/_ymodem_handlers.py +0 -0
  199. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/cls.py +0 -0
  200. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/confirm.py +0 -0
  201. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/credits.py +0 -0
  202. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/exit.py +0 -0
  203. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/plugin.py +0 -0
  204. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/print.py +0 -0
  205. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/ss.py +0 -0
  206. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/stop.py +0 -0
  207. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/commands/xfer.py +0 -0
  208. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/crc/sum16.py +0 -0
  209. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/crc/sum8.py +0 -0
  210. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/.gitignore +0 -0
  211. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/demo.cfg +0 -0
  212. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/demo.profile.json +0 -0
  213. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/demo.symbols.json +0 -0
  214. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/demo_legacy.profile.json +0 -0
  215. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/demo_ndjson.profile.json +0 -0
  216. {termapy-0.77.0/src/termapy/builtins → termapy-0.78.0/src/termapy/builtins/demo/plugin}/__init__.py +0 -0
  217. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/plugin/cmd.py +0 -0
  218. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/plugin/probe.py +0 -0
  219. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/proto/at_test.pro +0 -0
  220. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/proto/bitfield_inline.pro +0 -0
  221. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/proto/modbus_inline.pro +0 -0
  222. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/at_demo.run +0 -0
  223. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/crc_tour.run +0 -0
  224. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/doc_screenshots.run +0 -0
  225. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/expect_test.run +0 -0
  226. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/gps_demo.run +0 -0
  227. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/smoke_test.run +0 -0
  228. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/status_check.run +0 -0
  229. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/var_demo.run +0 -0
  230. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/builtins/demo/run/welcome.run +0 -0
  231. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/config_resolve.py +0 -0
  232. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/env_flags.py +0 -0
  233. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/.coverage +0 -0
  234. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/acknowledgments.md +0 -0
  235. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/authoring-profiles.md +0 -0
  236. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/custom-buttons.md +0 -0
  237. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/data-capture.md +0 -0
  238. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/demo.md +0 -0
  239. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/device-help.md +0 -0
  240. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/devices.md +0 -0
  241. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/environment.md +0 -0
  242. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_01_main_tui.svg +0 -0
  243. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_02_help.svg +0 -0
  244. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_03_help_proto.svg +0 -0
  245. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_04_proto_send.svg +0 -0
  246. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_05_proto_crc.svg +0 -0
  247. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_06_proto_delay.svg +0 -0
  248. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_07_crc_python.svg +0 -0
  249. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_08_variables.svg +0 -0
  250. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_09_target_help.svg +0 -0
  251. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_10_config_info.svg +0 -0
  252. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_11_proto_run.svg +0 -0
  253. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_12_cap_struct.svg +0 -0
  254. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_13_cap_progress.svg +0 -0
  255. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_14_port_list.svg +0 -0
  256. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_15_xfer.svg +0 -0
  257. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_16_toolbar.svg +0 -0
  258. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_17_proto_debug.svg +0 -0
  259. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_20_palette.svg +0 -0
  260. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_21_script_picker.svg +0 -0
  261. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_22_script_editor.svg +0 -0
  262. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_23_config_editor.svg +0 -0
  263. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_24_cmd_picker.svg +0 -0
  264. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_30_new_cfg.png +0 -0
  265. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_31_cli_completion.png +0 -0
  266. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_32_port_picker.png +0 -0
  267. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_33_port_tooltip.png +0 -0
  268. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_34_latency_timer.png +0 -0
  269. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_35_vt100_menu.png +0 -0
  270. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_36_vt100_status.png +0 -0
  271. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/img/doc_37_config_picker.svg +0 -0
  272. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/index.md +0 -0
  273. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/memory.md +0 -0
  274. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/on-ai-assistance.md +0 -0
  275. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/ports.md +0 -0
  276. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/toolbar.md +0 -0
  277. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/using-git.md +0 -0
  278. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/variables.md +0 -0
  279. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help/vt100.md +0 -0
  280. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/help_tooltip.py +0 -0
  281. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/history_nav.py +0 -0
  282. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/.coverage +0 -0
  283. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/images/favicon.png +0 -0
  284. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/javascripts/LICENSE +0 -0
  285. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/javascripts/bundle.a2388154.min.js +0 -0
  286. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/javascripts/workers/search.c47bb847.min.js +0 -0
  287. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/stylesheets/classic/main.68ef4dbf.min.css +0 -0
  288. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/stylesheets/classic/palette.813d4b3f.min.css +0 -0
  289. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/stylesheets/modern/main.e442bf79.min.css +0 -0
  290. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/assets/stylesheets/modern/palette.b60ce83d.min.css +0 -0
  291. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_01_main_tui.svg +0 -0
  292. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_02_help.svg +0 -0
  293. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_03_help_proto.svg +0 -0
  294. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_04_proto_send.svg +0 -0
  295. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_05_proto_crc.svg +0 -0
  296. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_06_proto_delay.svg +0 -0
  297. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_07_crc_python.svg +0 -0
  298. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_08_variables.svg +0 -0
  299. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_09_target_help.svg +0 -0
  300. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_10_config_info.svg +0 -0
  301. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_11_proto_run.svg +0 -0
  302. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_12_cap_struct.svg +0 -0
  303. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_13_cap_progress.svg +0 -0
  304. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_14_port_list.svg +0 -0
  305. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_15_xfer.svg +0 -0
  306. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_16_toolbar.svg +0 -0
  307. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_17_proto_debug.svg +0 -0
  308. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_20_palette.svg +0 -0
  309. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_21_script_picker.svg +0 -0
  310. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_22_script_editor.svg +0 -0
  311. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_23_config_editor.svg +0 -0
  312. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_24_cmd_picker.svg +0 -0
  313. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_30_new_cfg.png +0 -0
  314. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_31_cli_completion.png +0 -0
  315. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_32_port_picker.png +0 -0
  316. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_33_port_tooltip.png +0 -0
  317. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_34_latency_timer.png +0 -0
  318. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_35_vt100_menu.png +0 -0
  319. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_36_vt100_status.png +0 -0
  320. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/img/doc_37_config_picker.svg +0 -0
  321. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/html/sitemap.xml +0 -0
  322. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/install_info.py +0 -0
  323. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/mcp/__init__.py +0 -0
  324. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/palette_provider.py +0 -0
  325. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/plugins/__init__.py +0 -0
  326. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/profile/__init__.py +0 -0
  327. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/profile/schema.json +0 -0
  328. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/protocol/type_codes.py +0 -0
  329. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/__init__.py +0 -0
  330. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/symbols/provenance.py +0 -0
  331. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/templates/icons/termapy.icns +0 -0
  332. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/templates/icons/termapy.ico +0 -0
  333. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/templates/icons/termapy.png +0 -0
  334. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/templates/icons/termapy.svg +0 -0
  335. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/templates/linux/termapy.desktop.template +0 -0
  336. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/templates/macos/Termapy.app/Contents/Info.plist +0 -0
  337. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/templates/macos/Termapy.app/Contents/MacOS/launcher.template +0 -0
  338. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/usb/__init__.py +0 -0
  339. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/usb/_vendors_full.py +0 -0
  340. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/usb/chips.py +0 -0
  341. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/LICENSES.md +0 -0
  342. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/__init__.py +0 -0
  343. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/__main__.py +0 -0
  344. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/rfc2217.py +0 -0
  345. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/rs485.py +0 -0
  346. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/serialcli.py +0 -0
  347. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/serialjava.py +0 -0
  348. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/serialposix.py +0 -0
  349. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/serialutil.py +0 -0
  350. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/serialwin32.py +0 -0
  351. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/threaded/__init__.py +0 -0
  352. {termapy-0.77.0/src/termapy/builtins/crc → termapy-0.78.0/src/termapy/vendor/serial/tools}/__init__.py +0 -0
  353. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/hexlify_codec.py +0 -0
  354. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/list_ports.py +0 -0
  355. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/list_ports_common.py +0 -0
  356. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/list_ports_linux.py +0 -0
  357. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/list_ports_osx.py +0 -0
  358. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/list_ports_posix.py +0 -0
  359. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/list_ports_windows.py +0 -0
  360. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/tools/miniterm.py +0 -0
  361. {termapy-0.77.0/src/termapy/builtins/demo → termapy-0.78.0/src/termapy/vendor/serial/urlhandler}/__init__.py +0 -0
  362. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/urlhandler/protocol_alt.py +0 -0
  363. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/urlhandler/protocol_cp2110.py +0 -0
  364. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/urlhandler/protocol_hwgrep.py +0 -0
  365. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/urlhandler/protocol_loop.py +0 -0
  366. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/urlhandler/protocol_rfc2217.py +0 -0
  367. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/urlhandler/protocol_socket.py +0 -0
  368. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/urlhandler/protocol_spy.py +0 -0
  369. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/serial/win32.py +0 -0
  370. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/xmodem.py +0 -0
  371. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/ymodem/CRC.py +0 -0
  372. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/ymodem/Platform.py +0 -0
  373. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/ymodem/Protocol.py +0 -0
  374. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/ymodem/Socket.py +0 -0
  375. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/ymodem/Version.py +0 -0
  376. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/vendor/ymodem/__init__.py +0 -0
  377. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/widgets/__init__.py +0 -0
  378. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/widgets/checkbox.py +0 -0
  379. {termapy-0.77.0 → termapy-0.78.0}/src/termapy/widgets/status_bar.py +0 -0
termapy-0.78.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Chuck Bass
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.
@@ -1,15 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: termapy
3
- Version: 0.77.0
3
+ Version: 0.78.0
4
4
  Summary: A TUI serial terminal with ANSI color support, built on Textual and pyserial
5
5
  Keywords: serial,terminal,tui,textual,pyserial,embedded,xmodem,ymodem
6
6
  Author: Chuck Bass
7
7
  Author-email: Chuck Bass <chuck@acrocad.net>
8
8
  License-Expression: MIT
9
+ License-File: LICENSE
9
10
  Classifier: Development Status :: 4 - Beta
10
11
  Classifier: Environment :: Console
11
12
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Programming Language :: Python :: 3.11
@@ -23,14 +23,14 @@ Classifier: Topic :: Terminals :: Serial
23
23
  Requires-Dist: textual>=0.80
24
24
  Requires-Dist: prompt-toolkit>=3.0
25
25
  Requires-Dist: pygments>=2.20.0
26
- Requires-Dist: tree-sitter>=0.25.0,<0.27 ; python_full_version >= '3.10'
27
- Requires-Dist: tree-sitter-json>=0.24.0,<0.25 ; python_full_version >= '3.10'
28
- Requires-Dist: tree-sitter-toml>=0.6.0,<0.8 ; python_full_version >= '3.10'
29
- Requires-Dist: tree-sitter-bash>=0.23.0,<0.26 ; python_full_version >= '3.10'
26
+ Requires-Dist: tree-sitter>=0.25.0,<0.27
27
+ Requires-Dist: tree-sitter-json>=0.24.0,<0.25
28
+ Requires-Dist: tree-sitter-toml>=0.6.0,<0.8
29
+ Requires-Dist: tree-sitter-bash>=0.23.0,<0.26
30
30
  Requires-Dist: packaging>=24.0
31
31
  Requires-Dist: frist>=0.21
32
32
  Requires-Dist: platformdirs>=4.0
33
- Requires-Dist: crcglot>=0.31.0
33
+ Requires-Dist: crcglot>=0.32.1
34
34
  Requires-Dist: termapy[mcp,web] ; extra == 'all'
35
35
  Requires-Dist: mcp>=2,<3 ; extra == 'mcp'
36
36
  Requires-Dist: textual-serve>=1.1 ; extra == 'web'
@@ -47,11 +47,11 @@ Description-Content-Type: text/markdown
47
47
 
48
48
  # termapy
49
49
 
50
- **Project Status:** [![CI](https://github.com/hucker/termapy/actions/workflows/tests.yml/badge.svg)](https://github.com/hucker/termapy/actions/workflows/tests.yml) [![codecov](https://codecov.io/gh/hucker/termapy/graph/badge.svg)](https://codecov.io/gh/hucker/termapy) [![ty](https://img.shields.io/badge/ty-0%20issues-brightgreen)](https://github.com/astral-sh/ty) ![license](https://img.shields.io/badge/license-MIT-green) [![docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://hucker.github.io/termapy/)
50
+ **Project Status:** [![CI](https://github.com/hucker/termapy/actions/workflows/tests.yml/badge.svg)](https://github.com/hucker/termapy/actions/workflows/tests.yml) [![coverage](https://img.shields.io/codecov/c/github/hucker/termapy?logo=codecov)](https://codecov.io/gh/hucker/termapy) [![ty](https://img.shields.io/badge/ty-0%20issues-brightgreen)](https://github.com/astral-sh/ty) ![license](https://img.shields.io/badge/license-MIT-green) [![docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://hucker.github.io/termapy/)
51
51
 
52
52
  **Powered by:** [![Textual](https://img.shields.io/badge/Textual-TUI-blue?logo=python)](https://textual.textualize.io/) [![pySerial](https://img.shields.io/badge/pySerial-serial%20I%2FO-orange?logo=python)](https://pyserial.readthedocs.io/) [![zensical](https://img.shields.io/badge/zensical-docs-green)](https://github.com/hucker/zensical)
53
53
 
54
- **Built with:** ![python](https://img.shields.io/badge/python-3.11--3.15-blue) [![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet?logo=astral)](https://docs.astral.sh/uv/) [![pytest](https://img.shields.io/badge/pytest-testing-yellow?logo=pytest)](https://pytest.org/) [![coverage](https://img.shields.io/badge/coverage-84%25-brightgreen)](https://coverage.readthedocs.io/)
54
+ **Built with:** ![python](https://img.shields.io/badge/python-3.11--3.15-blue) [![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet?logo=astral)](https://docs.astral.sh/uv/) [![pytest](https://img.shields.io/badge/pytest-testing-yellow?logo=pytest)](https://pytest.org/) [![coverage](https://img.shields.io/badge/coverage-code%20coverage-green)](https://coverage.readthedocs.io/)
55
55
 
56
56
  Pronounced "ter-map-ee"
57
57
 
@@ -95,6 +95,12 @@ Low time commitment: about 1 minute from scratch, or under 10 seconds if you alr
95
95
  uv tool uninstall termapy
96
96
  ```
97
97
 
98
+ For your own device, one line creates a config and connects:
99
+
100
+ ```sh
101
+ termapy --new my_device COM4 115200 8N1
102
+ ```
103
+
98
104
  For a plain-text terminal (no TUI), use CLI mode:
99
105
 
100
106
  ```sh
@@ -250,8 +256,8 @@ The most common ones:
250
256
  | `/run.list` | List .run files in run/, newest first, with size, age, and summary |
251
257
  | `/run.rename <old> <new>` | Rename a script (`.run` kept; never overwrites) |
252
258
  | `/run.help` | Same as `/help run` |
253
- | `/delay <duration>` | Wait for a duration (e.g. `500ms`, `1.5s`) |
254
- | `/confirm {message}` | Show Yes/Cancel dialog; Cancel stops a running script (see `at_demo.run`) |
259
+ | `/delay <duration>` | Wait for a duration (e.g. `500ms`, `1.5s`); Escape or Ctrl+C cancels |
260
+ | `/confirm {message}` | Ask Yes/Cancel (TUI dialog, CLI y/n); Cancel stops a running script |
255
261
  | `/stop` | Abort a running script |
256
262
  | `/seq` | Show sequence counters |
257
263
  | `/seq.reset` | Reset all sequence counters to zero |
@@ -271,7 +277,7 @@ The most common ones:
271
277
  | `/term.encoding {name}` | Show or set byte-decoding encoding (utf-8, latin-1, ...) |
272
278
  | `/term.json {compact\|indent\|color\|cycle}` | How JSON answers print: one line, indented, or indented and colored |
273
279
  | `/term.send_bare_enter {on\|off\|toggle}` | Send line ending on empty Enter |
274
- | `/edit <file>` | Edit a project file (`run/`/`proto/` path) |
280
+ | `/edit <file>` | Edit a project file (`run/`, `proto/` or `plugin/`) |
275
281
  | `/edit.cfg` | Edit the current config file |
276
282
  | `/edit.log` | Open the session log in the system viewer |
277
283
  | `/edit.info` | Open the info report in the system viewer |
@@ -282,7 +288,7 @@ The most common ones:
282
288
  | `/proto.help` | Same as `/help proto` |
283
289
  | `/proto.send <hex>` | Send raw hex bytes and/or quoted text, display response as hex (see below) |
284
290
  | `/proto.run <file>` | Run a binary protocol test script (.pro) with pass/fail |
285
- | `/proto.list` | List .pro files in proto/, newest first, with size and age |
291
+ | `/proto.list` | List .pro files in proto/, newest first, with size, age and each one's `name` |
286
292
  | `/proto.rename <old> <new>` | Rename a protocol script (`.pro` kept; never overwrites) |
287
293
  | `/proto.hex {on\|off\|toggle}` | Same flag as `/term.hex` |
288
294
  | `/proto.crc.list {pat}` | List available CRC algorithms (optional glob filter) |
@@ -1017,14 +1023,16 @@ Add custom REPL commands by dropping a `.py` file in a plugin folder. No classes
1017
1023
  # hello.py - drop into termapy_cfg/plugin/ or termapy_cfg/<config>/plugin/
1018
1024
  from termapy.plugins import Command, PluginContext
1019
1025
 
1026
+
1020
1027
  def _handler(ctx: PluginContext, args: str):
1021
1028
  name = args.strip() or "world"
1022
1029
  ctx.io.result(f"Hello, {name}!")
1023
1030
 
1031
+
1024
1032
  # ── COMMAND (must be at end of file) ──────────────────────────────────────────
1025
1033
  COMMAND = Command(
1026
1034
  name="hello",
1027
- args="{name}", # {braces} = optional, <angle> = required, "" = no args
1035
+ args="{name}", # {braces} = optional, <angle> = required, "" = no args
1028
1036
  help="Say hello.",
1029
1037
  handler=_handler,
1030
1038
  )
@@ -1035,7 +1043,7 @@ COMMAND = Command(
1035
1043
  1. **Built-in:** shipped with termapy, always available
1036
1044
  2. **Global:** `termapy_cfg/plugin/*.py`, shared across all configs
1037
1045
  3. **Per-config:** `termapy_cfg/<name>/plugin/*.py`, specific to one config
1038
- 4. **App hooks:** frontend-specific commands (`/ss`, `/delay`, `/run`, etc.)
1046
+ 4. **App hooks:** frontend-specific commands (`/ss.svg`, `/vt100`, `/tui`, etc.)
1039
1047
 
1040
1048
  Resolution is the same in every frontend (TUI, CLI, MCP server) and reruns on every config switch; a folder plugin can never take an app hook's name.
1041
1049
 
@@ -1158,6 +1166,7 @@ For non-standard checksums, add a CRC plugin (3 lines of Python):
1158
1166
  NAME = "sum8"
1159
1167
  WIDTH = 1
1160
1168
 
1169
+
1161
1170
  def compute(data: bytes) -> int:
1162
1171
  return sum(data) & 0xFF
1163
1172
  ```
@@ -1203,10 +1212,12 @@ Every command runs on a worker thread, the serial reader is the only long-lived
1203
1212
  </details>
1204
1213
 
1205
1214
  <details>
1206
- <summary><strong>Test coverage</strong> - 4913 tests, 84% core-module coverage</summary>
1215
+ <summary><strong>Test coverage</strong> - 5077 tests</summary>
1207
1216
 
1208
1217
  Run the full suite with `uv run pytest`. (The count above is the one place it
1209
- is tracked; `release_prep` refreshes it each release.)
1218
+ is tracked; `release_prep` refreshes it each release.) The coverage figure is
1219
+ the coverage badge at the top, live from Codecov, measured by CI on every
1220
+ push to main.
1210
1221
 
1211
1222
  Tests are scoped to **termapy's own concerns** — REPL dispatch, serial
1212
1223
  engine, CLI flow, plugin loading, capture, protocol toolkit. CRC
@@ -1,10 +1,10 @@
1
1
  # termapy
2
2
 
3
- **Project Status:** [![CI](https://github.com/hucker/termapy/actions/workflows/tests.yml/badge.svg)](https://github.com/hucker/termapy/actions/workflows/tests.yml) [![codecov](https://codecov.io/gh/hucker/termapy/graph/badge.svg)](https://codecov.io/gh/hucker/termapy) [![ty](https://img.shields.io/badge/ty-0%20issues-brightgreen)](https://github.com/astral-sh/ty) ![license](https://img.shields.io/badge/license-MIT-green) [![docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://hucker.github.io/termapy/)
3
+ **Project Status:** [![CI](https://github.com/hucker/termapy/actions/workflows/tests.yml/badge.svg)](https://github.com/hucker/termapy/actions/workflows/tests.yml) [![coverage](https://img.shields.io/codecov/c/github/hucker/termapy?logo=codecov)](https://codecov.io/gh/hucker/termapy) [![ty](https://img.shields.io/badge/ty-0%20issues-brightgreen)](https://github.com/astral-sh/ty) ![license](https://img.shields.io/badge/license-MIT-green) [![docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://hucker.github.io/termapy/)
4
4
 
5
5
  **Powered by:** [![Textual](https://img.shields.io/badge/Textual-TUI-blue?logo=python)](https://textual.textualize.io/) [![pySerial](https://img.shields.io/badge/pySerial-serial%20I%2FO-orange?logo=python)](https://pyserial.readthedocs.io/) [![zensical](https://img.shields.io/badge/zensical-docs-green)](https://github.com/hucker/zensical)
6
6
 
7
- **Built with:** ![python](https://img.shields.io/badge/python-3.11--3.15-blue) [![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet?logo=astral)](https://docs.astral.sh/uv/) [![pytest](https://img.shields.io/badge/pytest-testing-yellow?logo=pytest)](https://pytest.org/) [![coverage](https://img.shields.io/badge/coverage-84%25-brightgreen)](https://coverage.readthedocs.io/)
7
+ **Built with:** ![python](https://img.shields.io/badge/python-3.11--3.15-blue) [![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet?logo=astral)](https://docs.astral.sh/uv/) [![pytest](https://img.shields.io/badge/pytest-testing-yellow?logo=pytest)](https://pytest.org/) [![coverage](https://img.shields.io/badge/coverage-code%20coverage-green)](https://coverage.readthedocs.io/)
8
8
 
9
9
  Pronounced "ter-map-ee"
10
10
 
@@ -48,6 +48,12 @@ Low time commitment: about 1 minute from scratch, or under 10 seconds if you alr
48
48
  uv tool uninstall termapy
49
49
  ```
50
50
 
51
+ For your own device, one line creates a config and connects:
52
+
53
+ ```sh
54
+ termapy --new my_device COM4 115200 8N1
55
+ ```
56
+
51
57
  For a plain-text terminal (no TUI), use CLI mode:
52
58
 
53
59
  ```sh
@@ -203,8 +209,8 @@ The most common ones:
203
209
  | `/run.list` | List .run files in run/, newest first, with size, age, and summary |
204
210
  | `/run.rename <old> <new>` | Rename a script (`.run` kept; never overwrites) |
205
211
  | `/run.help` | Same as `/help run` |
206
- | `/delay <duration>` | Wait for a duration (e.g. `500ms`, `1.5s`) |
207
- | `/confirm {message}` | Show Yes/Cancel dialog; Cancel stops a running script (see `at_demo.run`) |
212
+ | `/delay <duration>` | Wait for a duration (e.g. `500ms`, `1.5s`); Escape or Ctrl+C cancels |
213
+ | `/confirm {message}` | Ask Yes/Cancel (TUI dialog, CLI y/n); Cancel stops a running script |
208
214
  | `/stop` | Abort a running script |
209
215
  | `/seq` | Show sequence counters |
210
216
  | `/seq.reset` | Reset all sequence counters to zero |
@@ -224,7 +230,7 @@ The most common ones:
224
230
  | `/term.encoding {name}` | Show or set byte-decoding encoding (utf-8, latin-1, ...) |
225
231
  | `/term.json {compact\|indent\|color\|cycle}` | How JSON answers print: one line, indented, or indented and colored |
226
232
  | `/term.send_bare_enter {on\|off\|toggle}` | Send line ending on empty Enter |
227
- | `/edit <file>` | Edit a project file (`run/`/`proto/` path) |
233
+ | `/edit <file>` | Edit a project file (`run/`, `proto/` or `plugin/`) |
228
234
  | `/edit.cfg` | Edit the current config file |
229
235
  | `/edit.log` | Open the session log in the system viewer |
230
236
  | `/edit.info` | Open the info report in the system viewer |
@@ -235,7 +241,7 @@ The most common ones:
235
241
  | `/proto.help` | Same as `/help proto` |
236
242
  | `/proto.send <hex>` | Send raw hex bytes and/or quoted text, display response as hex (see below) |
237
243
  | `/proto.run <file>` | Run a binary protocol test script (.pro) with pass/fail |
238
- | `/proto.list` | List .pro files in proto/, newest first, with size and age |
244
+ | `/proto.list` | List .pro files in proto/, newest first, with size, age and each one's `name` |
239
245
  | `/proto.rename <old> <new>` | Rename a protocol script (`.pro` kept; never overwrites) |
240
246
  | `/proto.hex {on\|off\|toggle}` | Same flag as `/term.hex` |
241
247
  | `/proto.crc.list {pat}` | List available CRC algorithms (optional glob filter) |
@@ -970,14 +976,16 @@ Add custom REPL commands by dropping a `.py` file in a plugin folder. No classes
970
976
  # hello.py - drop into termapy_cfg/plugin/ or termapy_cfg/<config>/plugin/
971
977
  from termapy.plugins import Command, PluginContext
972
978
 
979
+
973
980
  def _handler(ctx: PluginContext, args: str):
974
981
  name = args.strip() or "world"
975
982
  ctx.io.result(f"Hello, {name}!")
976
983
 
984
+
977
985
  # ── COMMAND (must be at end of file) ──────────────────────────────────────────
978
986
  COMMAND = Command(
979
987
  name="hello",
980
- args="{name}", # {braces} = optional, <angle> = required, "" = no args
988
+ args="{name}", # {braces} = optional, <angle> = required, "" = no args
981
989
  help="Say hello.",
982
990
  handler=_handler,
983
991
  )
@@ -988,7 +996,7 @@ COMMAND = Command(
988
996
  1. **Built-in:** shipped with termapy, always available
989
997
  2. **Global:** `termapy_cfg/plugin/*.py`, shared across all configs
990
998
  3. **Per-config:** `termapy_cfg/<name>/plugin/*.py`, specific to one config
991
- 4. **App hooks:** frontend-specific commands (`/ss`, `/delay`, `/run`, etc.)
999
+ 4. **App hooks:** frontend-specific commands (`/ss.svg`, `/vt100`, `/tui`, etc.)
992
1000
 
993
1001
  Resolution is the same in every frontend (TUI, CLI, MCP server) and reruns on every config switch; a folder plugin can never take an app hook's name.
994
1002
 
@@ -1111,6 +1119,7 @@ For non-standard checksums, add a CRC plugin (3 lines of Python):
1111
1119
  NAME = "sum8"
1112
1120
  WIDTH = 1
1113
1121
 
1122
+
1114
1123
  def compute(data: bytes) -> int:
1115
1124
  return sum(data) & 0xFF
1116
1125
  ```
@@ -1156,10 +1165,12 @@ Every command runs on a worker thread, the serial reader is the only long-lived
1156
1165
  </details>
1157
1166
 
1158
1167
  <details>
1159
- <summary><strong>Test coverage</strong> - 4913 tests, 84% core-module coverage</summary>
1168
+ <summary><strong>Test coverage</strong> - 5077 tests</summary>
1160
1169
 
1161
1170
  Run the full suite with `uv run pytest`. (The count above is the one place it
1162
- is tracked; `release_prep` refreshes it each release.)
1171
+ is tracked; `release_prep` refreshes it each release.) The coverage figure is
1172
+ the coverage badge at the top, live from Codecov, measured by CI on every
1173
+ push to main.
1163
1174
 
1164
1175
  Tests are scoped to **termapy's own concerns** — REPL dispatch, serial
1165
1176
  engine, CLI flow, plugin loading, capture, protocol toolkit. CRC
@@ -0,0 +1,149 @@
1
+ [project]
2
+ name = "termapy"
3
+ version = "0.78.0"
4
+ description = "A TUI serial terminal with ANSI color support, built on Textual and pyserial"
5
+ license = "MIT"
6
+ license-files = ["LICENSE"]
7
+ requires-python = ">=3.11"
8
+ readme = "README.md"
9
+ keywords = [
10
+ "serial",
11
+ "terminal",
12
+ "tui",
13
+ "textual",
14
+ "pyserial",
15
+ "embedded",
16
+ "xmodem",
17
+ "ymodem",
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Environment :: Console",
22
+ "Intended Audience :: Developers",
23
+ "Operating System :: OS Independent",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Programming Language :: Python :: 3.14",
29
+ "Programming Language :: Python :: 3.15",
30
+ "Topic :: Communications",
31
+ "Topic :: System :: Hardware",
32
+ "Topic :: Terminals :: Serial",
33
+ ]
34
+ dependencies = [
35
+ "textual>=0.80",
36
+ "prompt-toolkit>=3.0",
37
+ "pygments>=2.20.0",
38
+ "tree-sitter>=0.25.0,<0.27",
39
+ "tree-sitter-json>=0.24.0,<0.25",
40
+ "tree-sitter-toml>=0.6.0,<0.8",
41
+ "tree-sitter-bash>=0.23.0,<0.26",
42
+ "packaging>=24.0",
43
+ "frist>=0.21",
44
+ "platformdirs>=4.0",
45
+ "crcglot>=0.32.1",
46
+ ]
47
+
48
+ [[project.authors]]
49
+ name = "Chuck Bass"
50
+ email = "chuck@acrocad.net"
51
+
52
+ [project.optional-dependencies]
53
+ web = ["textual-serve>=1.1"]
54
+ mcp = ["mcp>=2,<3"]
55
+ all = ["termapy[mcp,web]"]
56
+
57
+ [project.scripts]
58
+ termapy = "termapy:run"
59
+
60
+ [project.urls]
61
+ Homepage = "https://github.com/hucker/termapy"
62
+ Documentation = "https://hucker.github.io/termapy/"
63
+ Repository = "https://github.com/hucker/termapy"
64
+ Changelog = "https://github.com/hucker/termapy/blob/main/CHANGELOG.md"
65
+ Issues = "https://github.com/hucker/termapy/issues"
66
+
67
+ [tool.uv.build-backend]
68
+ wheel-exclude = [
69
+ "*.md",
70
+ "**/*.md",
71
+ ]
72
+
73
+ [tool.pytest.ini_options]
74
+ testpaths = ["tests"]
75
+ addopts = "-v --cov --cov-report=term-missing -n auto --dist loadgroup"
76
+ markers = [
77
+ "slow: subprocess-spawning, hw_loopback, or sleep-based test (~80s of full-suite runtime). Skip during fast iteration with -m 'not slow'.",
78
+ "sw_loopback: software loopback, pyserial's virtual loop:// port. No hardware; runs anywhere, CI included.",
79
+ "hw_loopback: hardware loopback, a TX-RX-jumpered USB-serial adapter attached; found by serial number (TERMAPY_HW_LOOPBACK_SN, default BG03U7VTA). Gated: deselected unless --run-hw-loopback, FAILS when absent under --require-hw-loopback (release_prep), refused on GitHub Actions. Run with --run-hw-loopback -m hw_loopback -n 0 --no-cov.",
80
+ ]
81
+
82
+ [tool.ty.environment]
83
+ extra-paths = [
84
+ "src/termapy/vendor",
85
+ "scripts",
86
+ ]
87
+
88
+ [tool.ty.src]
89
+ exclude = ["src/termapy/vendor/**"]
90
+
91
+ [tool.pyright]
92
+ extraPaths = [
93
+ "src/termapy/vendor",
94
+ "scripts",
95
+ ]
96
+ exclude = [
97
+ "src/termapy/vendor",
98
+ "src/termapy/html",
99
+ ]
100
+
101
+ [tool.ruff]
102
+ line-length = 100
103
+ exclude = [
104
+ "src/termapy/vendor",
105
+ "src/termapy/html",
106
+ ]
107
+
108
+ [tool.ruff.format]
109
+ exclude = ["src/termapy/usb/_vendors_full.py"]
110
+
111
+ [tool.ruff.lint]
112
+ select = [
113
+ "E4",
114
+ "E7",
115
+ "E9",
116
+ "F",
117
+ "I",
118
+ "UP",
119
+ ]
120
+
121
+ [tool.ruff.lint.isort]
122
+ combine-as-imports = true
123
+
124
+ [tool.coverage.run]
125
+ source = ["src/termapy"]
126
+ omit = [
127
+ "src/termapy/__init__.py",
128
+ "src/termapy/builtins/*.py",
129
+ "src/termapy/vendor/*",
130
+ ]
131
+
132
+ [tool.coverage.report]
133
+ exclude_lines = [
134
+ "if __name__",
135
+ "pragma: no cover",
136
+ ]
137
+ show_missing = true
138
+
139
+ [build-system]
140
+ requires = ["uv_build>=0.13,<0.14"]
141
+ build-backend = "uv_build"
142
+
143
+ [dependency-groups]
144
+ dev = [
145
+ "pytest-cov>=7.0.0",
146
+ "pytest-xdist>=3.8.0",
147
+ "ruff==0.17.1",
148
+ "ty==0.0.89",
149
+ ]
@@ -1,8 +1,9 @@
1
1
  [project]
2
2
  name = "termapy"
3
- version = "0.77.0"
3
+ version = "0.78.0"
4
4
  description = "A TUI serial terminal with ANSI color support, built on Textual and pyserial"
5
5
  license = "MIT"
6
+ license-files = ["LICENSE"]
6
7
  requires-python = ">=3.11"
7
8
  readme = "README.md"
8
9
  authors = [{name = "Chuck Bass", email = "chuck@acrocad.net"}]
@@ -11,7 +12,6 @@ classifiers = [
11
12
  "Development Status :: 4 - Beta",
12
13
  "Environment :: Console",
13
14
  "Intended Audience :: Developers",
14
- "License :: OSI Approved :: MIT License",
15
15
  "Operating System :: OS Independent",
16
16
  "Programming Language :: Python :: 3",
17
17
  "Programming Language :: Python :: 3.11",
@@ -35,10 +35,10 @@ dependencies = [
35
35
  # currently-tested release; pre-1.0 tree-sitter libraries routinely
36
36
  # break their API between minor versions. Bump the caps manually
37
37
  # after smoke-testing a new release locally.
38
- "tree-sitter>=0.25.0,<0.27; python_version >= '3.10'",
39
- "tree-sitter-json>=0.24.0,<0.25; python_version >= '3.10'",
40
- "tree-sitter-toml>=0.6.0,<0.8; python_version >= '3.10'",
41
- "tree-sitter-bash>=0.23.0,<0.26; python_version >= '3.10'",
38
+ "tree-sitter>=0.25.0,<0.27",
39
+ "tree-sitter-json>=0.24.0,<0.25",
40
+ "tree-sitter-toml>=0.6.0,<0.8",
41
+ "tree-sitter-bash>=0.23.0,<0.26",
42
42
  # PEP 440 version parsing for the update_check module (release-notification
43
43
  # path). Used to compare an installed termapy version against the latest
44
44
  # PyPI release.
@@ -136,7 +136,7 @@ dependencies = [
136
136
  # positional and multi-frame detect is NOT yet reachable from
137
137
  # /proto.crc.detect (single-frame is unaffected). Surfacing it is a
138
138
  # follow-up, not a floor concern. Floor moves to 0.31.0.
139
- "crcglot>=0.31.0",
139
+ "crcglot>=0.32.1",
140
140
  ]
141
141
 
142
142
  [project.optional-dependencies]
@@ -173,7 +173,12 @@ all = ["termapy[mcp,web]"]
173
173
  wheel-exclude = ["*.md", "**/*.md"]
174
174
 
175
175
  [build-system]
176
- requires = ["uv_build"]
176
+ # Bounded to the uv frontend's series: unbounded, the build pulled uv_build
177
+ # 0.13 under a uv 0.9 frontend, whose tar reader then failed on the new
178
+ # backend's sdist in both `uv build` and `uv publish` (the v0.77.0 release).
179
+ # Move this bound in the same chore as a uv upgrade (0.9 -> 0.13 on
180
+ # 2026-10-17, proven with a `uv build` of sdist and wheel).
181
+ requires = ["uv_build>=0.13,<0.14"]
177
182
  build-backend = "uv_build"
178
183
 
179
184
  [project.scripts]
@@ -223,6 +228,10 @@ extraPaths = ["src/termapy/vendor", "scripts"]
223
228
  exclude = ["src/termapy/vendor", "src/termapy/html"]
224
229
 
225
230
  [tool.ty.src]
231
+ # The gate (.githooks/pre-commit, release_prep) runs `ty check` with no
232
+ # paths, so this table is its scope: every first-party file is checked
233
+ # unless it is excluded here.
234
+ #
226
235
  # Don't type-check the vendored code itself. pyserial uses Linux-only
227
236
  # modules (fcntl, termios, select.POLL*) in its platform shims, and ty
228
237
  # flags every reference as unresolved on Windows. We still need the
@@ -233,11 +242,23 @@ exclude = ["src/termapy/vendor/**"]
233
242
  # 100 (not the black-default 88) buys room for inline suppression reasons
234
243
  # (`# noqa: CODE -- why`) and generally-descriptive names without wrapping.
235
244
  line-length = 100
245
+ # The gate runs `ruff check` and `ruff format --check` with no paths, so
246
+ # these excludes are its scope, as [tool.ty.src] is ty's.
247
+ #
236
248
  # Vendored pyserial uses wildcard imports, lowercase l/I/O variable
237
249
  # names, and other patterns we don't own. Skip lint entirely; same
238
250
  # reasoning as the ty exclude above.
239
251
  exclude = ["src/termapy/vendor", "src/termapy/html"]
240
252
 
253
+ [tool.ruff.format]
254
+ # Code is formatted by ruff, always, no exceptions: no hand layout and no
255
+ # `# fmt: off` carve-outs (decision 2026-10-17). The whole project is
256
+ # formatted; line-length comes from [tool.ruff], and the lint excludes
257
+ # above apply here too. _vendors_full.py is generated by
258
+ # scripts/refresh_usb_ids.py and rewritten on each refresh, so it keeps the
259
+ # generator's layout rather than fighting it.
260
+ exclude = ["src/termapy/usb/_vendors_full.py"]
261
+
241
262
  [tool.ruff.lint]
242
263
  # Selected EXPLICITLY rather than riding ruff's implicit default. The
243
264
  # default is not a stable contract: 0.16 widened it from 59 rules to 414,
@@ -245,11 +266,13 @@ exclude = ["src/termapy/vendor", "src/termapy/html"]
245
266
  #
246
267
  # E4/E7/E9 + F are the classic defaults this gate has always effectively
247
268
  # enforced. I (import sorting) is the one addition -- deterministic import
248
- # blocks, and every finding is auto-fixable.
269
+ # blocks, and every finding is auto-fixable. UP (pyupgrade) holds the code
270
+ # to the Python floor ruff infers from requires-python: added 2026-10-17
271
+ # when 3.10 was dropped, and it flags the next set when the floor moves.
249
272
  #
250
273
  # Adding a rule family is a deliberate change: select it here, fix the
251
274
  # findings, and land it on its own branch.
252
- select = ["E4", "E7", "E9", "F", "I"]
275
+ select = ["E4", "E7", "E9", "F", "I", "UP"]
253
276
 
254
277
  [tool.ruff.lint.isort]
255
278
  # Keep aliased members in the SAME statement as their siblings. isort's
@@ -290,7 +313,7 @@ dev = [
290
313
  # whatever ruff happened to be on PATH and `uvx ty` fetched the latest
291
314
  # release on every invocation. Bump these deliberately, on a chore
292
315
  # branch, with the new findings reviewed -- never as a side effect.
293
- "ruff==0.16.8",
316
+ "ruff==0.17.1",
294
317
  # ty is 0.0.x and ships near-daily; an unpinned check is a moving target.
295
- "ty==0.0.82",
318
+ "ty==0.0.89",
296
319
  ]