pytrain-ogr-deck 2.9.10__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 (696) hide show
  1. pytrain_ogr_deck-2.9.10/.github/workflows/python-package.yml +48 -0
  2. pytrain_ogr_deck-2.9.10/.github/workflows/release.yml +87 -0
  3. pytrain_ogr_deck-2.9.10/.gitignore +24 -0
  4. pytrain_ogr_deck-2.9.10/.idea/dictionaries/project.xml +162 -0
  5. pytrain_ogr_deck-2.9.10/.junie/plans/auto-reload-accessory-config.md +184 -0
  6. pytrain_ogr_deck-2.9.10/.junie/plans/configurable-panel-bindings.md +356 -0
  7. pytrain_ogr_deck-2.9.10/.junie/plans/create-acc-switch-entities.md +509 -0
  8. pytrain_ogr_deck-2.9.10/.junie/plans/equalize-landscape-admin-button-heights.md +116 -0
  9. pytrain_ogr_deck-2.9.10/.junie/plans/lcs-module-config-panel.md +354 -0
  10. pytrain_ogr_deck-2.9.10/.junie/plans/quilling-horn-triggers.md +205 -0
  11. pytrain_ogr_deck-2.9.10/.junie/plans/steam-deck-accessory-input-contexts.md +987 -0
  12. pytrain_ogr_deck-2.9.10/.junie/plans/steam-deck-landscape-controller.md +306 -0
  13. pytrain_ogr_deck-2.9.10/.run/PyTrain CityLife Client.run.xml +37 -0
  14. pytrain_ogr_deck-2.9.10/.run/PyTrain CityLife Server.run.xml +37 -0
  15. pytrain_ogr_deck-2.9.10/.run/PyTrain Sprucewood Server.run.xml +37 -0
  16. pytrain_ogr_deck-2.9.10/AGENTS.md +6 -0
  17. pytrain_ogr_deck-2.9.10/AUTHORS +1 -0
  18. pytrain_ogr_deck-2.9.10/LICENSE +165 -0
  19. pytrain_ogr_deck-2.9.10/PKG-INFO +823 -0
  20. pytrain_ogr_deck-2.9.10/README.md +615 -0
  21. pytrain_ogr_deck-2.9.10/cli/acc.py +13 -0
  22. pytrain_ogr_deck-2.9.10/cli/cache.py +16 -0
  23. pytrain_ogr_deck-2.9.10/cli/clear.py +16 -0
  24. pytrain_ogr_deck-2.9.10/cli/configure.py +13 -0
  25. pytrain_ogr_deck-2.9.10/cli/engine.py +13 -0
  26. pytrain_ogr_deck-2.9.10/cli/lcs.py +16 -0
  27. pytrain_ogr_deck-2.9.10/cli/make_gui.py +13 -0
  28. pytrain_ogr_deck-2.9.10/cli/make_service.py +13 -0
  29. pytrain_ogr_deck-2.9.10/cli/piconfig.py +13 -0
  30. pytrain_ogr_deck-2.9.10/cli/pytrain.py +13 -0
  31. pytrain_ogr_deck-2.9.10/cli/reindex.py +16 -0
  32. pytrain_ogr_deck-2.9.10/cli/switch.py +13 -0
  33. pytrain_ogr_deck-2.9.10/doc/fonts/14 Segment LED Regular.ttf +0 -0
  34. pytrain_ogr_deck-2.9.10/doc/fonts/Digital Display.ttf +0 -0
  35. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAM.ttf +0 -0
  36. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAMFAT.ttf +0 -0
  37. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAMFATNARROW.ttf +0 -0
  38. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAMFATSKEW.ttf +0 -0
  39. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAMFATSKEWNARROW.ttf +0 -0
  40. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAMNARROW.ttf +0 -0
  41. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAMSKEW.ttf +0 -0
  42. pytrain_ogr_deck-2.9.10/doc/fonts/digital-dream/DIGITALDREAMSKEWNARROW.ttf +0 -0
  43. pytrain_ogr_deck-2.9.10/doc/fonts/digital-readout/SFDigitalReadout-Heavy.ttf +0 -0
  44. pytrain_ogr_deck-2.9.10/doc/fonts/digital-readout/SFDigitalReadout-HeavyObliq.ttf +0 -0
  45. pytrain_ogr_deck-2.9.10/doc/fonts/digital-readout/SFDigitalReadout-Light.ttf +0 -0
  46. pytrain_ogr_deck-2.9.10/doc/fonts/digital-readout/SFDigitalReadout-LightObliq.ttf +0 -0
  47. pytrain_ogr_deck-2.9.10/doc/fonts/digital-readout/SFDigitalReadout-Medium.ttf +0 -0
  48. pytrain_ogr_deck-2.9.10/doc/fonts/digital-readout/SFDigitalReadout-MediumObli.ttf +0 -0
  49. pytrain_ogr_deck-2.9.10/doc/images/gantry.jpg +0 -0
  50. pytrain_ogr_deck-2.9.10/doc/images/gantry.pdf +0 -0
  51. pytrain_ogr_deck-2.9.10/doc/images/switch-example.png +0 -0
  52. pytrain_ogr_deck-2.9.10/doc/reference/steam-deck-controller-layout-screen.png +0 -0
  53. pytrain_ogr_deck-2.9.10/examples/README.MD +1 -0
  54. pytrain_ogr_deck-2.9.10/examples/buttons.py +37 -0
  55. pytrain_ogr_deck-2.9.10/examples/gantry_crane_block.py +36 -0
  56. pytrain_ogr_deck-2.9.10/examples/steam-deck.json +67 -0
  57. pytrain_ogr_deck-2.9.10/pyproject.toml +110 -0
  58. pytrain_ogr_deck-2.9.10/pytest.ini +5 -0
  59. pytrain_ogr_deck-2.9.10/requirements-nogpio.txt +15 -0
  60. pytrain_ogr_deck-2.9.10/requirements.txt +4 -0
  61. pytrain_ogr_deck-2.9.10/ruff.toml +4 -0
  62. pytrain_ogr_deck-2.9.10/scripts/README.md +1 -0
  63. pytrain_ogr_deck-2.9.10/scripts/build_deck.py +237 -0
  64. pytrain_ogr_deck-2.9.10/scripts/change.py +56 -0
  65. pytrain_ogr_deck-2.9.10/scripts/compress.py +83 -0
  66. pytrain_ogr_deck-2.9.10/scripts/controlspreview.py +178 -0
  67. pytrain_ogr_deck-2.9.10/scripts/deckinfo.py +393 -0
  68. pytrain_ogr_deck-2.9.10/scripts/delete_failed_runs.sh +43 -0
  69. pytrain_ogr_deck-2.9.10/scripts/fonttest.py +51 -0
  70. pytrain_ogr_deck-2.9.10/scripts/generate_lcs_icons.py +141 -0
  71. pytrain_ogr_deck-2.9.10/scripts/rcr.py +433 -0
  72. pytrain_ogr_deck-2.9.10/scripts/restore.py +37 -0
  73. pytrain_ogr_deck-2.9.10/setup.cfg +4 -0
  74. pytrain_ogr_deck-2.9.10/src/__init__.py +9 -0
  75. pytrain_ogr_deck-2.9.10/src/pytrain/__init__.py +230 -0
  76. pytrain_ogr_deck-2.9.10/src/pytrain/_version.py +24 -0
  77. pytrain_ogr_deck-2.9.10/src/pytrain/atc/__init__.py +9 -0
  78. pytrain_ogr_deck-2.9.10/src/pytrain/atc/block.py +494 -0
  79. pytrain_ogr_deck-2.9.10/src/pytrain/cli/__init__.py +334 -0
  80. pytrain_ogr_deck-2.9.10/src/pytrain/cli/acc.py +135 -0
  81. pytrain_ogr_deck-2.9.10/src/pytrain/cli/amc2.py +188 -0
  82. pytrain_ogr_deck-2.9.10/src/pytrain/cli/asc2.py +116 -0
  83. pytrain_ogr_deck-2.9.10/src/pytrain/cli/bpc2.py +84 -0
  84. pytrain_ogr_deck-2.9.10/src/pytrain/cli/cache.py +260 -0
  85. pytrain_ogr_deck-2.9.10/src/pytrain/cli/clear.py +158 -0
  86. pytrain_ogr_deck-2.9.10/src/pytrain/cli/configure.py +1130 -0
  87. pytrain_ogr_deck-2.9.10/src/pytrain/cli/csv_export.py +209 -0
  88. pytrain_ogr_deck-2.9.10/src/pytrain/cli/dialogs.py +512 -0
  89. pytrain_ogr_deck-2.9.10/src/pytrain/cli/echo.py +39 -0
  90. pytrain_ogr_deck-2.9.10/src/pytrain/cli/effects.py +297 -0
  91. pytrain_ogr_deck-2.9.10/src/pytrain/cli/engine.py +881 -0
  92. pytrain_ogr_deck-2.9.10/src/pytrain/cli/halt.py +43 -0
  93. pytrain_ogr_deck-2.9.10/src/pytrain/cli/lcs.py +188 -0
  94. pytrain_ogr_deck-2.9.10/src/pytrain/cli/lighting.py +299 -0
  95. pytrain_ogr_deck-2.9.10/src/pytrain/cli/make_base.py +371 -0
  96. pytrain_ogr_deck-2.9.10/src/pytrain/cli/make_gui.py +827 -0
  97. pytrain_ogr_deck-2.9.10/src/pytrain/cli/make_service.py +194 -0
  98. pytrain_ogr_deck-2.9.10/src/pytrain/cli/piconfig.py +480 -0
  99. pytrain_ogr_deck-2.9.10/src/pytrain/cli/pytrain.py +1833 -0
  100. pytrain_ogr_deck-2.9.10/src/pytrain/cli/reindex.py +462 -0
  101. pytrain_ogr_deck-2.9.10/src/pytrain/cli/route.py +44 -0
  102. pytrain_ogr_deck-2.9.10/src/pytrain/cli/sounds.py +244 -0
  103. pytrain_ogr_deck-2.9.10/src/pytrain/cli/switch.py +67 -0
  104. pytrain_ogr_deck-2.9.10/src/pytrain/comm/__init__.py +8 -0
  105. pytrain_ogr_deck-2.9.10/src/pytrain/comm/comm_buffer.py +962 -0
  106. pytrain_ogr_deck-2.9.10/src/pytrain/comm/command_listener.py +963 -0
  107. pytrain_ogr_deck-2.9.10/src/pytrain/comm/enqueue_proxy_requests.py +359 -0
  108. pytrain_ogr_deck-2.9.10/src/pytrain/comm/serial_reader.py +93 -0
  109. pytrain_ogr_deck-2.9.10/src/pytrain/db/__init__.py +0 -0
  110. pytrain_ogr_deck-2.9.10/src/pytrain/db/accessory_state.py +315 -0
  111. pytrain_ogr_deck-2.9.10/src/pytrain/db/base_state.py +163 -0
  112. pytrain_ogr_deck-2.9.10/src/pytrain/db/block_state.py +168 -0
  113. pytrain_ogr_deck-2.9.10/src/pytrain/db/cache_sync.py +722 -0
  114. pytrain_ogr_deck-2.9.10/src/pytrain/db/client_state_listener.py +226 -0
  115. pytrain_ogr_deck-2.9.10/src/pytrain/db/comp_data.py +1254 -0
  116. pytrain_ogr_deck-2.9.10/src/pytrain/db/component_state.py +1120 -0
  117. pytrain_ogr_deck-2.9.10/src/pytrain/db/component_state_store.py +602 -0
  118. pytrain_ogr_deck-2.9.10/src/pytrain/db/components.py +239 -0
  119. pytrain_ogr_deck-2.9.10/src/pytrain/db/engine_state.py +1341 -0
  120. pytrain_ogr_deck-2.9.10/src/pytrain/db/irda_state.py +207 -0
  121. pytrain_ogr_deck-2.9.10/src/pytrain/db/prod_info.py +245 -0
  122. pytrain_ogr_deck-2.9.10/src/pytrain/db/startup_state.py +203 -0
  123. pytrain_ogr_deck-2.9.10/src/pytrain/db/state_watcher.py +87 -0
  124. pytrain_ogr_deck-2.9.10/src/pytrain/db/sync_state.py +92 -0
  125. pytrain_ogr_deck-2.9.10/src/pytrain/db/watchable.py +37 -0
  126. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/__init__.py +0 -0
  127. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/base_watcher.py +101 -0
  128. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/controller.py +629 -0
  129. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/crane_car.py +283 -0
  130. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/culvert_loader.py +39 -0
  131. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/engine_controller.py +639 -0
  132. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/engine_status.py +248 -0
  133. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/gantry_crane.py +251 -0
  134. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/gpio_device.py +174 -0
  135. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/gpio_handler.py +843 -0
  136. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/__init__.py +0 -0
  137. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/ads_1x15.py +579 -0
  138. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/analog_handler_i2c.py +161 -0
  139. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/button_i2c.py +132 -0
  140. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/i2c.py +40 -0
  141. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/i2c_device.py +18 -0
  142. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/lcd.py +150 -0
  143. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/led_i2c.py +203 -0
  144. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/mcp23017.py +631 -0
  145. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/i2c/oled.py +450 -0
  146. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/keypad.py +494 -0
  147. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/launch_pad.py +193 -0
  148. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/launch_status.py +331 -0
  149. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/power_district.py +63 -0
  150. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/power_watcher.py +45 -0
  151. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/py_rotary_encoder.py +163 -0
  152. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/route.py +72 -0
  153. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/smoke_fluid_loader.py +104 -0
  154. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/state_source.py +170 -0
  155. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/switch.py +67 -0
  156. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/sys_admin.py +92 -0
  157. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/utils/__init__.py +0 -0
  158. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/utils/sh1122.py +115 -0
  159. pytrain_ogr_deck-2.9.10/src/pytrain/gpio/utils/text_buffer.py +248 -0
  160. pytrain_ogr_deck-2.9.10/src/pytrain/gui/__init__.py +0 -0
  161. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/__init__.py +8 -0
  162. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/accessory_base.py +723 -0
  163. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/accessory_gui.py +144 -0
  164. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/accessory_gui_catalog.py +114 -0
  165. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/accessory_registry.py +507 -0
  166. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/accessory_type.py +59 -0
  167. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/bootstrap_accessories.py +70 -0
  168. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/config.py +246 -0
  169. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/configured_accessory.py +892 -0
  170. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/construction_gui.py +113 -0
  171. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/control_tower_gui.py +138 -0
  172. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/culvert_gui.py +91 -0
  173. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/__init__.py +8 -0
  174. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/base_defs.py +223 -0
  175. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/construction_defs.py +108 -0
  176. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/control_tower_defs.py +142 -0
  177. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/culvert_handler_defs.py +161 -0
  178. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/fire_station_defs.py +128 -0
  179. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/freight_depot_defs.py +107 -0
  180. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/gas_station_defs.py +154 -0
  181. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/hobby_shop_defs.py +135 -0
  182. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/milk_loader_defs.py +143 -0
  183. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/playground_defs.py +142 -0
  184. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/single_latch_defs.py +126 -0
  185. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/smoke_fluid_loader_defs.py +130 -0
  186. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/station_defs.py +228 -0
  187. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/defs/uncoupler_defs.py +106 -0
  188. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/fire_station_gui.py +133 -0
  189. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/freight_depot_gui.py +120 -0
  190. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/gas_station_gui.py +112 -0
  191. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/hobby_shop_gui.py +99 -0
  192. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/milk_loader_gui.py +128 -0
  193. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/playground_gui.py +127 -0
  194. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/single_latch_gui.py +134 -0
  195. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/smoke_fluid_loader_gui.py +191 -0
  196. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/station_gui.py +164 -0
  197. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories/uncoupler_gui.py +89 -0
  198. pytrain_ogr_deck-2.9.10/src/pytrain/gui/accessories_gui.py +123 -0
  199. pytrain_ogr_deck-2.9.10/src/pytrain/gui/component_state_gui.py +176 -0
  200. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/__init__.py +8 -0
  201. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/analog_gauge.py +420 -0
  202. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/checkbox_group.py +694 -0
  203. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/editable_text.py +1142 -0
  204. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/hold_button.py +1159 -0
  205. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/scroll_box.py +620 -0
  206. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/scrolling_text.py +333 -0
  207. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/spinner.py +533 -0
  208. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/swipe_detector.py +232 -0
  209. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/touch_contact.py +217 -0
  210. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/touch_list.py +155 -0
  211. pytrain_ogr_deck-2.9.10/src/pytrain/gui/components/touch_list_box.py +426 -0
  212. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/__init__.py +8 -0
  213. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/accessory_bindings.py +800 -0
  214. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/admin_panel.py +1062 -0
  215. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/amc2_ops_panel.py +705 -0
  216. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/bell_horn_panel.py +129 -0
  217. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/catalog_panel.py +346 -0
  218. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/configured_accessory_adapter.py +234 -0
  219. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/configured_accessory_adapter_provider.py +227 -0
  220. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/control_labels.py +651 -0
  221. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/controller_view.py +1494 -0
  222. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/controls_panel.py +1304 -0
  223. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/engine_gui.py +2978 -0
  224. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/engine_gui_conf.py +594 -0
  225. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/image_presenter.py +440 -0
  226. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/keypad_view.py +1518 -0
  227. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/lcs_config_panel.py +5536 -0
  228. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/lcs_device_registry.py +992 -0
  229. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/lcs_gui.py +223 -0
  230. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/lcs_id_map.py +557 -0
  231. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/lcs_sequence_builder.py +111 -0
  232. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/lighting_panel.py +119 -0
  233. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/overlay_panel.py +106 -0
  234. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/popup_manager.py +918 -0
  235. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/rr_speed_panel.py +75 -0
  236. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/speed_limit_panel.py +127 -0
  237. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/state_info_overlay.py +444 -0
  238. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/steam_deck_default.json +183 -0
  239. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/steam_deck_gui.py +562 -0
  240. pytrain_ogr_deck-2.9.10/src/pytrain/gui/controller/steam_deck_input.py +2553 -0
  241. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAM.ttf +0 -0
  242. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAMFAT.ttf +0 -0
  243. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAMFATNARROW.ttf +0 -0
  244. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAMFATSKEW.ttf +0 -0
  245. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAMFATSKEWNARROW.ttf +0 -0
  246. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAMNARROW.ttf +0 -0
  247. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAMSKEW.ttf +0 -0
  248. pytrain_ogr_deck-2.9.10/src/pytrain/gui/fonts/digital-dream/DIGITALDREAMSKEWNARROW.ttf +0 -0
  249. pytrain_ogr_deck-2.9.10/src/pytrain/gui/guizero_base.py +1039 -0
  250. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/192-Control-Tower-6-37996.jpg +0 -0
  251. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/192-Control-Tower-6-82014.jpg +0 -0
  252. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/192R-Railroad-Control-Tower-6-32988.jpg +0 -0
  253. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Adolph-Coors-Brewing-Co-30-9161.jpg +0 -0
  254. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Advanced-Smoke-Fluid-Loader-6-37821.jpg +0 -0
  255. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Altoona-Brewing-CO-30-90191.jpg +0 -0
  256. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Atlantic-Gas-Station-30-91003.jpg +0 -0
  257. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/BP-Gas-Station-30-9181.jpg +0 -0
  258. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Backhoe-Construction-Scene-K-42416.gif +0 -0
  259. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Breaking-News-Emoji.gif +0 -0
  260. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Budweiser-30-9171.jpg +0 -0
  261. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Citgo-Gas-Station-30-9113.jpg +0 -0
  262. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Dairymens-League-6-14291.jpg +0 -0
  263. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Engine-Company-1-MTH-30-9136.jpg +0 -0
  264. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Engine-Company-219-MTH-30-9159.jpg +0 -0
  265. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Engine-Company-234-MTH-30-9102.jpg +0 -0
  266. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Engine-Company-54-MTH-30-9196.jpg +0 -0
  267. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Esso-Gas-Station-30-9106.jpg +0 -0
  268. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Fastrack-Uncoupling-6-12020.jpg +0 -0
  269. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Fire-Station-MTH-30-9157.jpg +0 -0
  270. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Freight-Depot-Platform-30-9199.jpg +0 -0
  271. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Gray-Fire-Station-MTH-30-9112.jpg +0 -0
  272. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Gulf-Gas-Station-30-9168.jpg +0 -0
  273. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Hobo-Depot-6-34191.jpg +0 -0
  274. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/K-Line-Operating-Freight-Platform-6-21449.jpg +0 -0
  275. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/K-Lineville-Freight-Depot-K-42418.jpg +0 -0
  276. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Keystone-Smoke-Fluid-Loader-6-83634.jpg +0 -0
  277. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/LCS-AMC2-6-81641.jpg +0 -0
  278. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/LCS-ASC2-6-81639.jpg +0 -0
  279. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/LCS-BPC2-6-81640.jpg +0 -0
  280. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/LCS-Sensor-Track-6-81294.jpg +0 -0
  281. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Lionelville-Culvert-Loader-6-82029.jpg +0 -0
  282. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Lionelville-Culvert-Unloader-6-82030.jpg +0 -0
  283. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Lionelville-Hobby-Shop-6-85294.jpg +0 -0
  284. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Madison-Hobby-Shop-6-14133.jpg +0 -0
  285. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Man-With-Handcart.png +0 -0
  286. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Middletown-Freight-Station-30-9184.jpg +0 -0
  287. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Middletown-Military-Station-30-9183.jpg +0 -0
  288. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Middletown-Passenger-Station-30-9125.jpg +0 -0
  289. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Midtown-Models-Hobby-Shop-6-32998.jpg +0 -0
  290. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Mobile-Gas-Station-30-9124.jpg +0 -0
  291. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Moose-Pond-Creamery-6-22660.jpg +0 -0
  292. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Mountain-View-Creamery-6-21675.jpg +0 -0
  293. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/NASA-Mission-Control-Tower-2229040.jpg +0 -0
  294. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/New-York-Central-Freight-Station-30-9151.jpg +0 -0
  295. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/New-York-Central-Passenger-Station-30-9164.jpg +0 -0
  296. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Numbers-1-Black-icon.png +0 -0
  297. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Old-Reading-Brewing-Co-30-90190.jpg +0 -0
  298. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Pennsylvania-Railroad-PRR-30-9152.jpg +0 -0
  299. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Pittsburgh-Brewing-Co-30-90189.jpg +0 -0
  300. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Playground-6-82104.jpg +0 -0
  301. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Radio-Control-Tower-6-24153.jpg +0 -0
  302. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Route-66-Gas-Station-30-91002.jpg +0 -0
  303. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Safety-Attention-Sticker.gif +0 -0
  304. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Shell-Gas-Station-30-9182.jpg +0 -0
  305. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Sinclair-Gas-Station-30-9101.jpg +0 -0
  306. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Sunoco-Gas-Station-30-9154.jpg +0 -0
  307. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Swing-6-14199.jpg +0 -0
  308. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Texaco-Gas-Station-30-91001.jpg +0 -0
  309. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Tidewater-Oil-Gas-Station-30-9181.jpg +0 -0
  310. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Tire-Swing-6-82105.jpg +0 -0
  311. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Tug-of-War-6-82107.jpg +0 -0
  312. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/Union-76-Gas-Station-30-9109.jpg +0 -0
  313. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/__init__.py +0 -0
  314. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/abort.jpg +0 -0
  315. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/animated_backhoe.gif +0 -0
  316. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/brews-waiting.png +0 -0
  317. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/bulb-power-off.png +0 -0
  318. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/bulb-power-on.png +0 -0
  319. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/control_tower_animation.gif +0 -0
  320. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/delete-key.jpg +0 -0
  321. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/depot-milk-can-eject.jpeg +0 -0
  322. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/RR-Speeds.jpg +0 -0
  323. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/acela.jpg +0 -0
  324. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/aux-hook.jpg +0 -0
  325. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/bell.jpg +0 -0
  326. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/blend-down.jpg +0 -0
  327. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/blend-up.jpg +0 -0
  328. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/boom.jpg +0 -0
  329. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/boost.jpg +0 -0
  330. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/brake.jpg +0 -0
  331. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/car-lights-off.jpg +0 -0
  332. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/car-lights-on.jpg +0 -0
  333. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/conductor.jpg +0 -0
  334. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/effect-down.jpg +0 -0
  335. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/effect-up.jpg +0 -0
  336. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/flat-wheel-off.jpg +0 -0
  337. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/flat-wheel-on.jpg +0 -0
  338. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/front-coupler.jpg +0 -0
  339. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/front-lamp.jpg +0 -0
  340. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/fuel-level.jpg +0 -0
  341. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_crane_car.jpg +0 -0
  342. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_diesel.jpg +0 -0
  343. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_diesel_switcher.jpg +0 -0
  344. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_electric.jpg +0 -0
  345. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_freight.jpg +0 -0
  346. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_passenger_car.jpg +0 -0
  347. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_steam.jpg +0 -0
  348. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_steam_santa.jpg +0 -0
  349. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/generic_steam_switcher.jpg +0 -0
  350. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/horn.jpg +0 -0
  351. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/lights-off.jpg +0 -0
  352. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/lights-on.jpg +0 -0
  353. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/load.jpg +0 -0
  354. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/loading_image.png +0 -0
  355. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/main-hook.jpg +0 -0
  356. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/master-down.jpg +0 -0
  357. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/master-up.jpg +0 -0
  358. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/next-stop.jpg +0 -0
  359. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/outriggers.jpg +0 -0
  360. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto-down-a.jpg +0 -0
  361. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto-down-f.jpg +0 -0
  362. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto-down-r.jpg +0 -0
  363. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto-up-a.jpg +0 -0
  364. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto-up-f.jpg +0 -0
  365. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto-up-r.jpg +0 -0
  366. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto_down.jpg +0 -0
  367. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/panto_up.jpg +0 -0
  368. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/power_master.jpg +0 -0
  369. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/rail_crossing.jpg +0 -0
  370. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/rear-coupler.jpg +0 -0
  371. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/rear-lamp.jpg +0 -0
  372. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/roll-speed.jpg +0 -0
  373. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/rpm-down.jpg +0 -0
  374. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/rpm-up.jpg +0 -0
  375. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/smoke-down.jpg +0 -0
  376. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/smoke-high.jpg +0 -0
  377. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/smoke-low.jpg +0 -0
  378. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/smoke-med.jpg +0 -0
  379. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/smoke-off.jpg +0 -0
  380. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/smoke-on.jpg +0 -0
  381. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/smoke-up.jpg +0 -0
  382. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/sound-off.jpg +0 -0
  383. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/sound-on.jpg +0 -0
  384. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/station.jpg +0 -0
  385. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/steward.jpg +0 -0
  386. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/stock-a-off.jpg +0 -0
  387. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/stock-a-on.jpg +0 -0
  388. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/stock-b-off.jpg +0 -0
  389. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/stock-b-on.jpg +0 -0
  390. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/toggle.jpg +0 -0
  391. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/unload.jpg +0 -0
  392. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/vol-down.jpg +0 -0
  393. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/vol-up.jpg +0 -0
  394. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/water-level.jpg +0 -0
  395. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engine_gui/whistle.jpg +0 -0
  396. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2127380.jpg +0 -0
  397. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2127390.jpg +0 -0
  398. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2133640.jpg +0 -0
  399. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2133760.jpg +0 -0
  400. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2135110.jpg +0 -0
  401. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2229300.jpg +0 -0
  402. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2234040.jpg +0 -0
  403. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2333080.jpg +0 -0
  404. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2333088.jpg +0 -0
  405. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2333331-B.jpg +0 -0
  406. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2335090.jpg +0 -0
  407. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2427170.jpg +0 -0
  408. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2526430.jpg +0 -0
  409. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2527180.jpg +0 -0
  410. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2535130.jpg +0 -0
  411. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/2633240.jpg +0 -0
  412. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-11224.jpg +0 -0
  413. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-18353.jpg +0 -0
  414. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-28338.jpg +0 -0
  415. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-28411.jpg +0 -0
  416. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-31747.jpg +0 -0
  417. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-37064.jpg +0 -0
  418. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-38466.jpg +0 -0
  419. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-38527.jpg +0 -0
  420. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-38528.jpg +0 -0
  421. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-38805.jpg +0 -0
  422. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-51007.jpg +0 -0
  423. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-81142.jpg +0 -0
  424. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-81212.jpg +0 -0
  425. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-81443.jpg +0 -0
  426. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-81883.jpg +0 -0
  427. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-81888.jpg +0 -0
  428. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/engines/6-85183.jpg +0 -0
  429. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/freight-waiting.jpg +0 -0
  430. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/gas-station-car.png +0 -0
  431. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/green_light.jpg +0 -0
  432. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/green_light_off.jpg +0 -0
  433. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/launch.jpg +0 -0
  434. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/launch_btn.jpg +0 -0
  435. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/left_arrow.jpg +0 -0
  436. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/let-off.jpg +0 -0
  437. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/load_culvert.png +0 -0
  438. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/loaded.png +0 -0
  439. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/off_button.jpg +0 -0
  440. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/on_button.jpg +0 -0
  441. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-acc.jpg +0 -0
  442. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-asc2.jpg +0 -0
  443. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-bpc2.jpg +0 -0
  444. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-control-tower.jpg +0 -0
  445. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-fire-station.jpg +0 -0
  446. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-gas-station.jpg +0 -0
  447. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-hobby-shop.jpg +0 -0
  448. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-hobo-depot.jpg +0 -0
  449. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-log-loader.jpg +0 -0
  450. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-milk-loader.jpg +0 -0
  451. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-playground.jpg +0 -0
  452. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-screen.jpg +0 -0
  453. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-smoke-fluid.jpg +0 -0
  454. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-station.jpg +0 -0
  455. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/op-uncoupler.jpg +0 -0
  456. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/passengers-waiting.png +0 -0
  457. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/raw-acc.jpg +0 -0
  458. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/raw-acs2.jpg +0 -0
  459. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/raw-keypad.jpg +0 -0
  460. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/red_light.jpg +0 -0
  461. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/red_light_off.jpg +0 -0
  462. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/right_arrow.jpg +0 -0
  463. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/smoke-fluid.png +0 -0
  464. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/swinging-child.jpg +0 -0
  465. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/tire-swing-child.jpg +0 -0
  466. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/tower.jpg +0 -0
  467. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/tower.png +0 -0
  468. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/tug-of-war.jpg +0 -0
  469. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/uncouple-motion.jpg +0 -0
  470. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/unload_culvert.png +0 -0
  471. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/walkie_talkie.jpg +0 -0
  472. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/walkie_talkie.png +0 -0
  473. pytrain_ogr_deck-2.9.10/src/pytrain/gui/images/water-inject.jpg +0 -0
  474. pytrain_ogr_deck-2.9.10/src/pytrain/gui/launch_gui.py +650 -0
  475. pytrain_ogr_deck-2.9.10/src/pytrain/gui/motors_gui.py +657 -0
  476. pytrain_ogr_deck-2.9.10/src/pytrain/gui/power_district_gui.py +84 -0
  477. pytrain_ogr_deck-2.9.10/src/pytrain/gui/routes_gui.py +71 -0
  478. pytrain_ogr_deck-2.9.10/src/pytrain/gui/state_based_gui.py +524 -0
  479. pytrain_ogr_deck-2.9.10/src/pytrain/gui/switches_gui.py +71 -0
  480. pytrain_ogr_deck-2.9.10/src/pytrain/gui/systems_gui.py +171 -0
  481. pytrain_ogr_deck-2.9.10/src/pytrain/gui/wide_component_state_gui.py +649 -0
  482. pytrain_ogr_deck-2.9.10/src/pytrain/installation/__init__.py +9 -0
  483. pytrain_ogr_deck-2.9.10/src/pytrain/installation/buttons_gui.py.template +14 -0
  484. pytrain_ogr_deck-2.9.10/src/pytrain/installation/launch_pytrain.bash.template +80 -0
  485. pytrain_ogr_deck-2.9.10/src/pytrain/installation/pytrain.bash.template +45 -0
  486. pytrain_ogr_deck-2.9.10/src/pytrain/installation/pytrain.service.template +14 -0
  487. pytrain_ogr_deck-2.9.10/src/pytrain/installation/pytrain_desktop.template +6 -0
  488. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/__init__.py +0 -0
  489. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/amc2_req.py +383 -0
  490. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/asc2_req.py +222 -0
  491. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/base3_buffer.py +292 -0
  492. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/base3_db_refresh_manager.py +222 -0
  493. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/base_req.py +934 -0
  494. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/block_req.py +146 -0
  495. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/bpc2_req.py +181 -0
  496. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/constants.py +561 -0
  497. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/d4_req.py +251 -0
  498. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/irda_req.py +310 -0
  499. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/lcs_req.py +268 -0
  500. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/pdi_device.py +518 -0
  501. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/pdi_listener.py +472 -0
  502. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/pdi_req.py +460 -0
  503. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/pdi_state_store.py +106 -0
  504. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/stm2_req.py +122 -0
  505. pytrain_ogr_deck-2.9.10/src/pytrain/pdi/wifi_req.py +78 -0
  506. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/__init__.py +0 -0
  507. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/command_base.py +234 -0
  508. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/command_def.py +344 -0
  509. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/command_req.py +762 -0
  510. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/constants.py +395 -0
  511. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/__init__.py +0 -0
  512. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/dcds_command_req.py +179 -0
  513. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/dialog_cmd.py +17 -0
  514. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/effects_cmd.py +17 -0
  515. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/lighting_cmd.py +17 -0
  516. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/masking_cmd.py +17 -0
  517. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/multibyte_command_req.py +228 -0
  518. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/multibyte_constants.py +908 -0
  519. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/param_command_req.py +113 -0
  520. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/r4lc_command_req.py +86 -0
  521. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/multibyte/sound_effects_cmd.py +17 -0
  522. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/__init__.py +0 -0
  523. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/abs_speed_rpm.py +49 -0
  524. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/cycle_tone_req.py +82 -0
  525. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/grade_crossing_req.py +48 -0
  526. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/labor_effect.py +90 -0
  527. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/ramped_speed_req.py +191 -0
  528. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/sequence_constants.py +75 -0
  529. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/sequence_req.py +368 -0
  530. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/set_speed_req.py +66 -0
  531. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/speed_req.py +27 -0
  532. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/sequence/steward_chatter_req.py +44 -0
  533. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/__init__.py +0 -0
  534. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/acc_cmd.py +21 -0
  535. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/engine_cmd.py +26 -0
  536. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/halt_cmd.py +16 -0
  537. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/route_cmd.py +16 -0
  538. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/switch_cmd.py +21 -0
  539. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/tmcc1_command.py +41 -0
  540. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc1/tmcc1_constants.py +658 -0
  541. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc2/__init__.py +0 -0
  542. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc2/engine_cmd.py +24 -0
  543. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc2/halt_cmd.py +15 -0
  544. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc2/route_cmd.py +18 -0
  545. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc2/tmcc2_command.py +62 -0
  546. pytrain_ogr_deck-2.9.10/src/pytrain/protocol/tmcc2/tmcc2_constants.py +459 -0
  547. pytrain_ogr_deck-2.9.10/src/pytrain/utils/__init__.py +10 -0
  548. pytrain_ogr_deck-2.9.10/src/pytrain/utils/argument_parser.py +202 -0
  549. pytrain_ogr_deck-2.9.10/src/pytrain/utils/dual_logging.py +159 -0
  550. pytrain_ogr_deck-2.9.10/src/pytrain/utils/expiring_set.py +65 -0
  551. pytrain_ogr_deck-2.9.10/src/pytrain/utils/host_info.py +139 -0
  552. pytrain_ogr_deck-2.9.10/src/pytrain/utils/image_utils.py +106 -0
  553. pytrain_ogr_deck-2.9.10/src/pytrain/utils/ip_tools.py +144 -0
  554. pytrain_ogr_deck-2.9.10/src/pytrain/utils/path_utils.py +168 -0
  555. pytrain_ogr_deck-2.9.10/src/pytrain/utils/perf_utils.py +37 -0
  556. pytrain_ogr_deck-2.9.10/src/pytrain/utils/pollable_queue.py +49 -0
  557. pytrain_ogr_deck-2.9.10/src/pytrain/utils/singleton.py +82 -0
  558. pytrain_ogr_deck-2.9.10/src/pytrain/utils/text_utils.py +67 -0
  559. pytrain_ogr_deck-2.9.10/src/pytrain/utils/unique_deque.py +147 -0
  560. pytrain_ogr_deck-2.9.10/src/pytrain/utils/validations.py +68 -0
  561. pytrain_ogr_deck-2.9.10/src/pytrain/utils/wifi_info.py +264 -0
  562. pytrain_ogr_deck-2.9.10/src/pytrain_ogr_deck.egg-info/PKG-INFO +823 -0
  563. pytrain_ogr_deck-2.9.10/src/pytrain_ogr_deck.egg-info/SOURCES.txt +694 -0
  564. pytrain_ogr_deck-2.9.10/src/pytrain_ogr_deck.egg-info/dependency_links.txt +1 -0
  565. pytrain_ogr_deck-2.9.10/src/pytrain_ogr_deck.egg-info/entry_points.txt +11 -0
  566. pytrain_ogr_deck-2.9.10/src/pytrain_ogr_deck.egg-info/requires.txt +15 -0
  567. pytrain_ogr_deck-2.9.10/src/pytrain_ogr_deck.egg-info/top_level.txt +1 -0
  568. pytrain_ogr_deck-2.9.10/tests/README.md +1 -0
  569. pytrain_ogr_deck-2.9.10/tests/__init__.py +0 -0
  570. pytrain_ogr_deck-2.9.10/tests/atc/__init__.py +0 -0
  571. pytrain_ogr_deck-2.9.10/tests/atc/test_block.py +27 -0
  572. pytrain_ogr_deck-2.9.10/tests/cli/__init__.py +0 -0
  573. pytrain_ogr_deck-2.9.10/tests/cli/test_cache.py +42 -0
  574. pytrain_ogr_deck-2.9.10/tests/cli/test_cache_sync_service.py +24 -0
  575. pytrain_ogr_deck-2.9.10/tests/cli/test_configure.py +223 -0
  576. pytrain_ogr_deck-2.9.10/tests/cli/test_lcs.py +456 -0
  577. pytrain_ogr_deck-2.9.10/tests/cli/test_make_gui.py +355 -0
  578. pytrain_ogr_deck-2.9.10/tests/cli/test_make_service.py +107 -0
  579. pytrain_ogr_deck-2.9.10/tests/cli/test_pytrain_update.py +354 -0
  580. pytrain_ogr_deck-2.9.10/tests/comm/__init__.py +0 -0
  581. pytrain_ogr_deck-2.9.10/tests/comm/conftest.py +23 -0
  582. pytrain_ogr_deck-2.9.10/tests/comm/test_command_listener.py +98 -0
  583. pytrain_ogr_deck-2.9.10/tests/comm/test_command_listener_ai.py +142 -0
  584. pytrain_ogr_deck-2.9.10/tests/comm/test_dispatch_listener.py +362 -0
  585. pytrain_ogr_deck-2.9.10/tests/comm/test_enqueue_proxy_requests.py +194 -0
  586. pytrain_ogr_deck-2.9.10/tests/db/__init__.py +0 -0
  587. pytrain_ogr_deck-2.9.10/tests/db/conftest.py +9 -0
  588. pytrain_ogr_deck-2.9.10/tests/db/test_accessory_state.py +315 -0
  589. pytrain_ogr_deck-2.9.10/tests/db/test_cache_sync.py +391 -0
  590. pytrain_ogr_deck-2.9.10/tests/db/test_client_state_listener.py +237 -0
  591. pytrain_ogr_deck-2.9.10/tests/db/test_comp_data.py +576 -0
  592. pytrain_ogr_deck-2.9.10/tests/db/test_component_state.py +672 -0
  593. pytrain_ogr_deck-2.9.10/tests/db/test_component_state_store.py +103 -0
  594. pytrain_ogr_deck-2.9.10/tests/db/test_component_state_store_ai.py +330 -0
  595. pytrain_ogr_deck-2.9.10/tests/db/test_components.py +155 -0
  596. pytrain_ogr_deck-2.9.10/tests/db/test_engine_state.py +348 -0
  597. pytrain_ogr_deck-2.9.10/tests/db/test_lcs_state_serialization.py +141 -0
  598. pytrain_ogr_deck-2.9.10/tests/db/test_prod_info.py +298 -0
  599. pytrain_ogr_deck-2.9.10/tests/db/test_startup_state.py +372 -0
  600. pytrain_ogr_deck-2.9.10/tests/db/test_state_watcher.py +129 -0
  601. pytrain_ogr_deck-2.9.10/tests/gpio/__init__.py +0 -0
  602. pytrain_ogr_deck-2.9.10/tests/gpio/i2c/__init__.py +0 -0
  603. pytrain_ogr_deck-2.9.10/tests/gpio/i2c/smbusmock.py +18 -0
  604. pytrain_ogr_deck-2.9.10/tests/gpio/i2c/test_i2c.py +29 -0
  605. pytrain_ogr_deck-2.9.10/tests/gpio/i2c/test_mcp23017.py +125 -0
  606. pytrain_ogr_deck-2.9.10/tests/gpio/test_engine_status.py +293 -0
  607. pytrain_ogr_deck-2.9.10/tests/gpio/test_gpio_device.py +18 -0
  608. pytrain_ogr_deck-2.9.10/tests/gpio/utils/__init__.py +9 -0
  609. pytrain_ogr_deck-2.9.10/tests/gpio/utils/test_text_buffer.py +143 -0
  610. pytrain_ogr_deck-2.9.10/tests/gui/__init__.py +8 -0
  611. pytrain_ogr_deck-2.9.10/tests/gui/accessory/__init__.py +8 -0
  612. pytrain_ogr_deck-2.9.10/tests/gui/accessory/test_accessories_gui_catalog.py +99 -0
  613. pytrain_ogr_deck-2.9.10/tests/gui/accessory/test_accessory_gui.py +323 -0
  614. pytrain_ogr_deck-2.9.10/tests/gui/accessory/test_accessory_registry.py +221 -0
  615. pytrain_ogr_deck-2.9.10/tests/gui/accessory/test_station_gui.py +40 -0
  616. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_accessory_bindings.py +930 -0
  617. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_admin_panel_layout.py +850 -0
  618. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_bell_horn_panel.py +148 -0
  619. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_control_labels.py +569 -0
  620. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_controls_panel.py +1644 -0
  621. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_engine_gui_compatibility.py +1079 -0
  622. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_engine_gui_conf_import.py +58 -0
  623. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_popup_manager_compatibility.py +1151 -0
  624. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_steam_deck_input.py +5328 -0
  625. pytrain_ogr_deck-2.9.10/tests/gui/controller/test_steam_deck_packaging.py +69 -0
  626. pytrain_ogr_deck-2.9.10/tests/gui/test_amc2_ops_panel.py +227 -0
  627. pytrain_ogr_deck-2.9.10/tests/gui/test_catalog_panel.py +145 -0
  628. pytrain_ogr_deck-2.9.10/tests/gui/test_checkbox_group.py +957 -0
  629. pytrain_ogr_deck-2.9.10/tests/gui/test_component_state_gui.py +212 -0
  630. pytrain_ogr_deck-2.9.10/tests/gui/test_controller_view.py +679 -0
  631. pytrain_ogr_deck-2.9.10/tests/gui/test_dummy_gui_components.py +390 -0
  632. pytrain_ogr_deck-2.9.10/tests/gui/test_editable_text.py +1121 -0
  633. pytrain_ogr_deck-2.9.10/tests/gui/test_engine_gui_accessories.py +1129 -0
  634. pytrain_ogr_deck-2.9.10/tests/gui/test_engine_gui_create.py +433 -0
  635. pytrain_ogr_deck-2.9.10/tests/gui/test_engine_gui_transitions.py +702 -0
  636. pytrain_ogr_deck-2.9.10/tests/gui/test_gui_checkpoint.py +944 -0
  637. pytrain_ogr_deck-2.9.10/tests/gui/test_gui_deck_parity.py +550 -0
  638. pytrain_ogr_deck-2.9.10/tests/gui/test_guizero_base.py +590 -0
  639. pytrain_ogr_deck-2.9.10/tests/gui/test_hold_button.py +1051 -0
  640. pytrain_ogr_deck-2.9.10/tests/gui/test_image_presenter.py +232 -0
  641. pytrain_ogr_deck-2.9.10/tests/gui/test_keypad_view.py +1498 -0
  642. pytrain_ogr_deck-2.9.10/tests/gui/test_lcs_config_panel.py +7371 -0
  643. pytrain_ogr_deck-2.9.10/tests/gui/test_lcs_device_registry.py +986 -0
  644. pytrain_ogr_deck-2.9.10/tests/gui/test_lcs_icons.py +45 -0
  645. pytrain_ogr_deck-2.9.10/tests/gui/test_lcs_id_map.py +757 -0
  646. pytrain_ogr_deck-2.9.10/tests/gui/test_lcs_imports.py +123 -0
  647. pytrain_ogr_deck-2.9.10/tests/gui/test_lcs_panel_wiring.py +119 -0
  648. pytrain_ogr_deck-2.9.10/tests/gui/test_lcs_sequence_builder.py +368 -0
  649. pytrain_ogr_deck-2.9.10/tests/gui/test_motors_gui.py +493 -0
  650. pytrain_ogr_deck-2.9.10/tests/gui/test_scroll_box.py +927 -0
  651. pytrain_ogr_deck-2.9.10/tests/gui/test_scrolling_text.py +154 -0
  652. pytrain_ogr_deck-2.9.10/tests/gui/test_state_info_overlay.py +309 -0
  653. pytrain_ogr_deck-2.9.10/tests/gui/test_steam_deck_gui.py +680 -0
  654. pytrain_ogr_deck-2.9.10/tests/gui/test_swipe_detector.py +246 -0
  655. pytrain_ogr_deck-2.9.10/tests/gui/test_touch_list_box.py +202 -0
  656. pytrain_ogr_deck-2.9.10/tests/gui/test_wide_component_state_gui.py +227 -0
  657. pytrain_ogr_deck-2.9.10/tests/pdi/__init__.py +8 -0
  658. pytrain_ogr_deck-2.9.10/tests/pdi/conftest.py +10 -0
  659. pytrain_ogr_deck-2.9.10/tests/pdi/test_amc2_req.py +230 -0
  660. pytrain_ogr_deck-2.9.10/tests/pdi/test_asc2_req.py +210 -0
  661. pytrain_ogr_deck-2.9.10/tests/pdi/test_base3_buffer.py +220 -0
  662. pytrain_ogr_deck-2.9.10/tests/pdi/test_base_req.py +130 -0
  663. pytrain_ogr_deck-2.9.10/tests/pdi/test_bpc2_req.py +148 -0
  664. pytrain_ogr_deck-2.9.10/tests/pdi/test_constants.py +192 -0
  665. pytrain_ogr_deck-2.9.10/tests/pdi/test_d4_req.py +120 -0
  666. pytrain_ogr_deck-2.9.10/tests/pdi/test_irda_req.py +106 -0
  667. pytrain_ogr_deck-2.9.10/tests/pdi/test_lcs_req.py +194 -0
  668. pytrain_ogr_deck-2.9.10/tests/pdi/test_pdi_listener.py +198 -0
  669. pytrain_ogr_deck-2.9.10/tests/pdi/test_pdi_req.py +181 -0
  670. pytrain_ogr_deck-2.9.10/tests/pdi/test_pdi_state_store.py +92 -0
  671. pytrain_ogr_deck-2.9.10/tests/pdi/test_stm2_req.py +119 -0
  672. pytrain_ogr_deck-2.9.10/tests/protocol/__init__.py +0 -0
  673. pytrain_ogr_deck-2.9.10/tests/protocol/test_command_base.py +11 -0
  674. pytrain_ogr_deck-2.9.10/tests/protocol/test_command_req.py +442 -0
  675. pytrain_ogr_deck-2.9.10/tests/protocol/test_constants.py +205 -0
  676. pytrain_ogr_deck-2.9.10/tests/protocol/test_tmcc1_acc_aux_numbers.py +54 -0
  677. pytrain_ogr_deck-2.9.10/tests/protocol/test_validations.py +44 -0
  678. pytrain_ogr_deck-2.9.10/tests/requirements.txt +11 -0
  679. pytrain_ogr_deck-2.9.10/tests/test_base.py +138 -0
  680. pytrain_ogr_deck-2.9.10/tests/test_deck_packaging.py +265 -0
  681. pytrain_ogr_deck-2.9.10/tests/test_pytest.py +32 -0
  682. pytrain_ogr_deck-2.9.10/tests/utils/__init__.py +9 -0
  683. pytrain_ogr_deck-2.9.10/tests/utils/test_argument_parser.py +128 -0
  684. pytrain_ogr_deck-2.9.10/tests/utils/test_dual_logging.py +159 -0
  685. pytrain_ogr_deck-2.9.10/tests/utils/test_expiring_set.py +167 -0
  686. pytrain_ogr_deck-2.9.10/tests/utils/test_host_info.py +76 -0
  687. pytrain_ogr_deck-2.9.10/tests/utils/test_ip_tools.py +169 -0
  688. pytrain_ogr_deck-2.9.10/tests/utils/test_path_util.py +113 -0
  689. pytrain_ogr_deck-2.9.10/tests/utils/test_path_utils.py +180 -0
  690. pytrain_ogr_deck-2.9.10/tests/utils/test_pollable_queue.py +101 -0
  691. pytrain_ogr_deck-2.9.10/tests/utils/test_singleton.py +111 -0
  692. pytrain_ogr_deck-2.9.10/tests/utils/test_text_utils.py +68 -0
  693. pytrain_ogr_deck-2.9.10/tests/utils/test_unique_deque.py +229 -0
  694. pytrain_ogr_deck-2.9.10/tests/utils/test_validations.py +123 -0
  695. pytrain_ogr_deck-2.9.10/tests/utils/test_wifi_info.py +172 -0
  696. pytrain_ogr_deck-2.9.10/tox.ini +42 -0
@@ -0,0 +1,48 @@
1
+ # file: noinspection UndefinedParamsPresent,UndefinedAction
2
+ # This workflow will installation Python dependencies, run tests and lint with a variety of Python versions
3
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
4
+
5
+ name: Python package
6
+
7
+ on:
8
+ push:
9
+ branches: [ "master" ]
10
+ pull_request:
11
+ branches: [ "master" ]
12
+
13
+ jobs:
14
+ build:
15
+
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python-version: [ "3.11", "3.12", "3.13", "3.14" ]
21
+
22
+ steps:
23
+ - uses: actions/checkout@v6
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ uses: actions/setup-python@v7
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+ - name: Prepare lgpio sources (only on 3.13)
29
+ if: matrix.python-version >= '3.13'
30
+ run: |
31
+ sudo apt-get update
32
+ sudo apt-get install -y build-essential swig python3-dev python3-setuptools
33
+ rm -rf /tmp/lg
34
+ git clone https://github.com/joan2937/lg /tmp/lg
35
+ cd /tmp/lg
36
+ make
37
+ sudo make install
38
+ - name: Install dependencies
39
+ run: |
40
+ python -m pip install --upgrade pip
41
+ python -m pip install ruff pytest
42
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
43
+ - name: Lint with ruff
44
+ run: ruff check --output-format=github --target-version=py310
45
+ - name: check code formatting
46
+ run: ruff format --diff --target-version=py310
47
+ - name: Test with pytest
48
+ run: pytest
@@ -0,0 +1,87 @@
1
+ name: release.yml
2
+ on:
3
+ push:
4
+ tags:
5
+ - '*'
6
+
7
+ jobs:
8
+ build:
9
+ name: Build pytrain-ogr distribution
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - uses: actions/checkout@v6
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v7
16
+ with:
17
+ python-version: "3.11"
18
+ - name: Install pypa/build
19
+ run: python3 -m pip install build
20
+ - name: Build a binary wheel and a source tarball
21
+ run: python3 -m build
22
+ - name: Store the distribution packages
23
+ uses: actions/upload-artifact@v7
24
+ with:
25
+ name: python-package-distributions
26
+ path: dist/
27
+
28
+ build-deck:
29
+ name: Build pytrain-ogr-deck distribution
30
+ runs-on: ubuntu-latest
31
+
32
+ steps:
33
+ - uses: actions/checkout@v6
34
+ - name: Set up Python
35
+ uses: actions/setup-python@v7
36
+ with:
37
+ python-version: "3.11"
38
+ - name: Install pypa/build
39
+ # setuptools-scm is needed outside the build as well: build_deck.py reads the
40
+ # version before it rewrites pyproject.toml, so the rewrite cannot make the
41
+ # working tree look dirty and add a local segment PyPI rejects
42
+ run: python3 -m pip install build setuptools-scm
43
+ - name: Build a binary wheel and a source tarball
44
+ run: python3 scripts/build_deck.py --outdir dist-deck
45
+ - name: Store the distribution packages
46
+ uses: actions/upload-artifact@v7
47
+ with:
48
+ name: python-package-distributions-deck
49
+ path: dist-deck/
50
+
51
+ pypi-publish:
52
+ name: Upload release to PyPI
53
+ needs:
54
+ - build
55
+ runs-on: ubuntu-latest
56
+ environment:
57
+ name: pypi
58
+ url: https://pypi.org/p/pytrain-ogr
59
+ permissions:
60
+ id-token: write
61
+ steps:
62
+ - name: Download all the dists
63
+ uses: actions/download-artifact@v7
64
+ with:
65
+ name: python-package-distributions
66
+ path: dist/
67
+ - name: Publish package distributions to PyPI
68
+ uses: pypa/gh-action-pypi-publish@release/v1
69
+
70
+ pypi-publish-deck:
71
+ name: Upload pytrain-ogr-deck release to PyPI
72
+ needs:
73
+ - build-deck
74
+ runs-on: ubuntu-latest
75
+ environment:
76
+ name: pypi
77
+ url: https://pypi.org/p/pytrain-ogr-deck
78
+ permissions:
79
+ id-token: write
80
+ steps:
81
+ - name: Download all the dists
82
+ uses: actions/download-artifact@v7
83
+ with:
84
+ name: python-package-distributions-deck
85
+ path: dist/
86
+ - name: Publish package distributions to PyPI
87
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,24 @@
1
+ *.bak
2
+ *.csv
3
+ *.pyc
4
+ !.idea/
5
+ !.idea/dictionaries/
6
+ !.idea/dictionaries/project.xml
7
+ .DS_Store
8
+ .env
9
+ .idea/
10
+ .idea/*
11
+ .pytrain.history
12
+ .tox/
13
+ __pycache__
14
+ accessory_config.json
15
+ buttons.py
16
+ cache/
17
+ dist-deck/
18
+ dist/
19
+ pytrain.history
20
+ pytrain.log*
21
+ raspinfo.txt
22
+ replay.txt
23
+ src/*.egg-info/
24
+ src/pytrain/_version.py
@@ -0,0 +1,162 @@
1
+ <component name="ProjectDictionaryState">
2
+ <dictionary name="project">
3
+ <words>
4
+ <w>CONTROLLERTOUCHPAD</w>
5
+ <w>CONTROLLERTOUCHPADDOWN</w>
6
+ <w>CONTROLLERTOUCHPADMOTION</w>
7
+ <w>CONTROLLERTOUCHPADUP</w>
8
+ <w>Citgo</w>
9
+ <w>Dairymens</w>
10
+ <w>ELFCLASS</w>
11
+ <w>Esso</w>
12
+ <w>Fonic</w>
13
+ <w>Gamescope</w>
14
+ <w>HIDRAW</w>
15
+ <w>JOYBUTTONDOWN</w>
16
+ <w>KDE's</w>
17
+ <w>Lineville</w>
18
+ <w>Lionelville</w>
19
+ <w>Misalignd</w>
20
+ <w>RPAD</w>
21
+ <w>Sunoco</w>
22
+ <w>Swindell</w>
23
+ <w>VIDEODRIVER</w>
24
+ <w>accs</w>
25
+ <w>activebackground</w>
26
+ <w>addrs</w>
27
+ <w>admingeom</w>
28
+ <w>adolph</w>
29
+ <w>altoona</w>
30
+ <w>appendleft</w>
31
+ <w>atexit</w>
32
+ <w>autoremove</w>
33
+ <w>baudrate</w>
34
+ <w>baudrates</w>
35
+ <w>bluealsa</w>
36
+ <w>bluetooth</w>
37
+ <w>btid</w>
38
+ <w>btns</w>
39
+ <w>caap</w>
40
+ <w>chksum</w>
41
+ <w>chorded</w>
42
+ <w>citgo</w>
43
+ <w>columnspan</w>
44
+ <w>coors</w>
45
+ <w>cplr</w>
46
+ <w>ctors</w>
47
+ <w>cupsd</w>
48
+ <w>dairymens</w>
49
+ <w>dcds</w>
50
+ <w>debounces</w>
51
+ <w>defaultdict</w>
52
+ <w>dflt</w>
53
+ <w>disablers</w>
54
+ <w>disambig</w>
55
+ <w>disambiguates</w>
56
+ <w>dtoverlay</w>
57
+ <w>dtparam</w>
58
+ <w>dups</w>
59
+ <w>ebuf</w>
60
+ <w>eeprom</w>
61
+ <w>elete</w>
62
+ <w>envtmpdir</w>
63
+ <w>esso</w>
64
+ <w>etype</w>
65
+ <w>extendleft</w>
66
+ <w>gamescope</w>
67
+ <w>getcwd</w>
68
+ <w>gethostbyname</w>
69
+ <w>gethostname</w>
70
+ <w>getifaddr</w>
71
+ <w>guizero's</w>
72
+ <w>gvfs</w>
73
+ <w>hciuart</w>
74
+ <w>hexid</w>
75
+ <w>holdbtn</w>
76
+ <w>hpad</w>
77
+ <w>iwgetid</w>
78
+ <w>labwc</w>
79
+ <w>lcsser</w>
80
+ <w>libcups</w>
81
+ <w>libegl</w>
82
+ <w>libgallium</w>
83
+ <w>libgl</w>
84
+ <w>lightdm</w>
85
+ <w>lineville</w>
86
+ <w>lionelbase</w>
87
+ <w>lionelville</w>
88
+ <w>logind</w>
89
+ <w>lpgl</w>
90
+ <w>mailcap</w>
91
+ <w>maxlen</w>
92
+ <w>middletown</w>
93
+ <w>mobintl</w>
94
+ <w>modemmanager</w>
95
+ <w>mome</w>
96
+ <w>mvalue</w>
97
+ <w>myhost</w>
98
+ <w>nodash</w>
99
+ <w>ntum</w>
100
+ <w>nwse</w>
101
+ <w>ocal</w>
102
+ <w>oled</w>
103
+ <w>padx</w>
104
+ <w>pady</w>
105
+ <w>pendings</w>
106
+ <w>pennsylvania</w>
107
+ <w>piconfig</w>
108
+ <w>pittsburgh</w>
109
+ <w>pmid</w>
110
+ <w>polkit</w>
111
+ <w>powermaster</w>
112
+ <w>poweroff</w>
113
+ <w>precreate</w>
114
+ <w>pullmor</w>
115
+ <w>pycharm</w>
116
+ <w>pytrain</w>
117
+ <w>pytrainhome</w>
118
+ <w>pytraininfo</w>
119
+ <w>quilling</w>
120
+ <w>rbuttons</w>
121
+ <w>repeatdelay</w>
122
+ <w>repeatinterval</w>
123
+ <w>requeues</w>
124
+ <w>respbcasts</w>
125
+ <w>retryhost</w>
126
+ <w>returncode</w>
127
+ <w>rnum</w>
128
+ <w>rpad</w>
129
+ <w>rpicam</w>
130
+ <w>selectbackground</w>
131
+ <w>selectforeground</w>
132
+ <w>setsid</w>
133
+ <w>settimeout</w>
134
+ <w>squeekboard</w>
135
+ <w>steamdeck</w>
136
+ <w>sunoco</w>
137
+ <w>svsc</w>
138
+ <w>swapchains</w>
139
+ <w>tids</w>
140
+ <w>titlebox</w>
141
+ <w>titleized</w>
142
+ <w>tk's</w>
143
+ <w>tkfont</w>
144
+ <w>tk’s</w>
145
+ <w>tmcc</w>
146
+ <w>toxworkdir</w>
147
+ <w>troughcolor</w>
148
+ <w>uevent</w>
149
+ <w>unsel</w>
150
+ <w>userhome</w>
151
+ <w>valids</w>
152
+ <w>vdiag</w>
153
+ <w>vpad</w>
154
+ <w>wayvnc</w>
155
+ <w>wcomp</w>
156
+ <w>weakref</w>
157
+ <w>wraplength</w>
158
+ <w>wvkbd</w>
159
+ <w>zxcvbnm</w>
160
+ </words>
161
+ </dictionary>
162
+ </component>
@@ -0,0 +1,184 @@
1
+ ---
2
+ sessionId: session-260806-094756-1vjd
3
+ ---
4
+
5
+ # Requirements
6
+
7
+ ### Overview & Goals
8
+
9
+ Automatically reload EngineGui’s configured accessory state when `accessory_config.json` changes, including changes
10
+ propagated into `cache/config/accessory_config.json` by cache sync.
11
+
12
+ ### Scope
13
+
14
+ #### In Scope
15
+
16
+ - Detect changes to the currently resolved accessory config file used by `ConfiguredAccessorySet`.
17
+ - Run file monitoring and JSON/config parsing outside the GUI thread.
18
+ - Apply the already-loaded configuration to `EngineGui` safely using the existing GUI scheduling/message patterns.
19
+ - Preserve the existing manual Admin panel `Accessories` reload button as a user-triggered fallback.
20
+ - Avoid repeated reload storms by using polling/debounce or signature comparison.
21
+
22
+ #### Out of Scope
23
+
24
+ - Changing cache sync behavior itself; the file is already synchronized by `CacheSyncManager`/`SidecarCacheTransport`.
25
+ - Live-editing individual accessory widgets in place; reload will reuse the existing teardown/rebuild behavior.
26
+ - Adding a new external file-watching dependency unless already present in the project.
27
+
28
+ ### Functional Requirements
29
+
30
+ - When the effective config file changes on disk, `EngineGui` reloads configured accessories automatically.
31
+ - Invalid JSON or invalid config entries must not replace the current working accessory set.
32
+ - Reload failures should be logged and the watcher should continue monitoring later changes.
33
+ - The GUI thread must not perform file polling or config parsing; it should only apply the resulting
34
+ `ConfiguredAccessorySet` and update GUI state.
35
+ - Both top-level `accessory_config.json` and cache-resolved `cache/config/accessory_config.json` must be handled
36
+ according to the existing resolution rules in `ConfiguredAccessorySet.resolve_config_path()`.
37
+
38
+ # Technical Design
39
+
40
+ ### Current Implementation
41
+
42
+ - `src/pytrain/gui/accessories/configured_accessory.py` defines `DEFAULT_CONFIG_FILE = "accessory_config.json"` and
43
+ `DEFAULT_CONFIG_CACHE_DIR = Path("cache") / "config"`.
44
+ - `ConfiguredAccessorySet.from_file()` calls `_load()`, resolves the effective path, reads/parses JSON, validates
45
+ entries, and rebuilds indexes synchronously.
46
+ - `EngineGui.__init__()` stores `self._accessory_config_file = config_file`, then loads
47
+ `self._caa = ConfiguredAccessorySet.from_file(config_file, verify=True)` and creates
48
+ `ConfiguredAccessoryAdapterProvider`.
49
+ - `EngineGui.reload_configured_accessories()` currently rereads the file and then clears/rebuilds adapter, overlay,
50
+ recents, catalog, options, and prewarm state.
51
+ - `EngineGui` already has background support via `self._executor.submit(...)`, GUI scheduling via
52
+ `self.app.tk.after(...)`, and lifecycle cleanup in `destroy_gui()`.
53
+ - Cache sync (`src/pytrain/db/cache_sync.py`) already polls/manifests cache file changes in a daemon thread, but it does
54
+ not notify `EngineGui`.
55
+
56
+ ### Key Decisions
57
+
58
+ - Use lightweight polling with file signature comparison instead of adding a dependency such as `watchdog`.
59
+ - Rationale: the project already uses polling/debounce for cache sync, and this avoids platform-specific watcher
60
+ concerns.
61
+ - Split reload into two phases:
62
+ - background phase: detect file changes and build a fresh `ConfiguredAccessorySet`;
63
+ - GUI phase: apply the prepared set to `EngineGui` using existing GUI scheduling/locking.
64
+ - Keep the watcher owned by `EngineGui`, because the reload affects GUI-owned adapter, popup, option, and prewarm state.
65
+
66
+ ### Proposed Changes
67
+
68
+ - Add a small internal watcher mechanism near `EngineGui` or as a helper class in
69
+ `src/pytrain/gui/controller/engine_gui.py`.
70
+ - Track the effective config path from `self.accessories.path` after initial load.
71
+ - Compare a signature such as `(resolved_path, exists, st_mtime_ns, st_size)` on a polling interval.
72
+ - Debounce changed signatures briefly before loading to avoid partial writes while cache sync/configure writes the
73
+ file.
74
+ - Refactor `EngineGui.reload_configured_accessories()` into:
75
+ - a loading method that can run off the GUI thread, e.g. `_load_configured_accessories()` returning
76
+ `ConfiguredAccessorySet | None`;
77
+ - an apply method that only runs on the GUI thread, e.g. `_apply_configured_accessories(configured)`.
78
+ - Add a non-GUI-thread auto reload flow:
79
+ - watcher detects file signature change;
80
+ - background worker calls `ConfiguredAccessorySet.from_file(self._accessory_config_file, verify=True)`;
81
+ - if successful, schedule `_apply_configured_accessories(configured)` via `self.app.tk.after(0, ...)` or the
82
+ existing message queue pattern.
83
+ - Preserve manual reload:
84
+ - `AdminPanel` line 181 can continue calling `self._gui.reload_configured_accessories`;
85
+ - manual reload may synchronously schedule/load through the same split implementation, but config parsing should
86
+ also avoid blocking the GUI if feasible.
87
+ - Add shutdown cleanup:
88
+ - stop the watcher when `EngineGui.destroy_gui()` runs or when `self._shutdown_flag` is set;
89
+ - ensure pending callbacks no-op if shutdown has started.
90
+
91
+ ### Data Flow
92
+
93
+ ```mermaid
94
+ graph LR
95
+ F[accessory_config.json] --> W[background watcher]
96
+ W --> L[background load]
97
+ L --> S[ConfiguredAccessorySet]
98
+ S --> A[GUI-thread apply]
99
+ A --> P[adapters/overlays/options]
100
+ ```
101
+
102
+ ### Files Affected
103
+
104
+ - `src/pytrain/gui/controller/engine_gui.py`
105
+ - Add watcher state fields and startup scheduling after initial UI setup.
106
+ - Split reload into load/apply helpers.
107
+ - Start/stop watcher in existing lifecycle methods.
108
+ - `src/pytrain/gui/accessories/configured_accessory.py`
109
+ - No required behavioral change expected; use existing `ConfiguredAccessorySet.path` and resolution behavior.
110
+ - `tests/` if GUI-controller tests exist or can be added without requiring a real display.
111
+ - Prefer unit-level coverage around file signature/watcher helper and reload apply behavior with fakes/mocks.
112
+
113
+ ### Risks & Mitigations
114
+
115
+ - **Partial writes:** debounce and catch parse errors; keep current config on failure.
116
+ - **GUI-thread safety:** perform only final state mutation and Tk scheduling on the GUI thread.
117
+ - **Config path switching:** because resolution prefers top-level file over cache file, each successful load should
118
+ update the watched path from `configured.path`.
119
+ - **Duplicate reloads:** track last successfully applied file signature and ignore unchanged signatures.
120
+
121
+ # Testing
122
+
123
+ ### Validation Approach
124
+
125
+ Use unit-level tests where possible and manual validation notes for GUI behavior that is hard to automate headlessly.
126
+
127
+ ### Key Scenarios
128
+
129
+ - Initial load watches the resolved top-level config when it exists.
130
+ - Initial load watches `cache/config/accessory_config.json` when no top-level file exists.
131
+ - A valid changed file causes a new `ConfiguredAccessorySet` to be loaded and applied.
132
+ - Invalid JSON logs an error and leaves the previous accessory set intact.
133
+ - Multiple quick changes trigger at most one applied reload after debounce.
134
+ - Shutdown prevents further reload callbacks.
135
+
136
+ ### Project Validation Commands
137
+
138
+ - For changed Python files: `../bin/python -m ruff format --check <changed Python files>`
139
+ - Full test suite: `../bin/python -m pytest`
140
+
141
+ # Delivery Steps
142
+
143
+ ### ✓ Step 1: split-accessory-reload-into-load-and-apply
144
+
145
+ `EngineGui` has a reusable reload path where config parsing can happen off the GUI thread and GUI mutation is isolated.
146
+
147
+ - Extract the existing state-replacement logic from `reload_configured_accessories()` into a helper that accepts an
148
+ already-built `ConfiguredAccessorySet`.
149
+ - Keep adapter/provider reset, accessory view clearing, overlay discard, catalog reset, options rebuild, and overlay
150
+ prewarm in the GUI-side helper.
151
+ - Add a background-safe load helper that calls
152
+ `ConfiguredAccessorySet.from_file(self._accessory_config_file, verify=True)` and logs failures without replacing
153
+ current state.
154
+ - Update the manual Admin panel reload path to use the refactored helpers while preserving the same visible behavior.
155
+
156
+ ### ✓ Step 2: add-background-config-change-watcher
157
+
158
+ `EngineGui` detects changes to the resolved accessory config file without polling or parsing in the GUI thread.
159
+
160
+ - Add watcher state to `EngineGui`, including last applied file signature, debounce timing, and a shutdown-aware
161
+ background loop or executor task.
162
+ - Watch the effective path from `self.accessories.path`, respecting the existing top-level-then-cache resolution
163
+ behavior.
164
+ - Compare file signatures using existence, modification time, and size rather than reading file contents on every poll.
165
+ - On a stable changed signature, load a fresh `ConfiguredAccessorySet` in the background and schedule the GUI-side apply
166
+ helper.
167
+
168
+ ### ✓ Step 3: wire-watcher-lifecycle-and-path-updates
169
+
170
+ The automatic reload watcher starts after GUI initialization and stops cleanly with the window.
171
+
172
+ - Start the watcher after the initial config load/UI setup is complete, avoiding startup reload duplication.
173
+ - After every successful reload, update the watched path/signature from the newly loaded `ConfiguredAccessorySet.path`.
174
+ - Ensure pending background completions and scheduled GUI callbacks check `self._shutdown_flag` before applying changes.
175
+ - Stop/join or otherwise cancel watcher activity from `destroy_gui()` alongside existing GUI cleanup.
176
+
177
+ ### ✓ Step 4: validate-reload-behavior
178
+
179
+ The change is covered by focused tests or reliable validation for change detection and failure handling.
180
+
181
+ - Add tests for file signature detection and debounce behavior if the watcher is factored into a testable helper.
182
+ - Add tests or mocks confirming invalid config does not replace the current configured accessory set.
183
+ - Run the required formatter check for changed Python files.
184
+ - Run the full unit test suite with `../bin/python -m pytest`.