runtimepy 5.5.0__tar.gz → 5.6.1__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 (280) hide show
  1. {runtimepy-5.5.0/runtimepy.egg-info → runtimepy-5.6.1}/PKG-INFO +14 -7
  2. {runtimepy-5.5.0 → runtimepy-5.6.1}/README.md +11 -4
  3. {runtimepy-5.5.0 → runtimepy-5.6.1}/pyproject.toml +1 -1
  4. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/__init__.py +2 -2
  5. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/server.py +35 -3
  6. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/App.js +33 -0
  7. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/PlotModalManager.js +3 -1
  8. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/WindowHashManager.js +17 -2
  9. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/init.js +12 -0
  10. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/util.js +12 -3
  11. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/worker.js +18 -3
  12. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/tcp/__init__.py +1 -0
  13. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/__init__.py +21 -20
  14. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/__init__.py +2 -2
  15. runtimepy-5.6.1/runtimepy/net/server/app/env/settings.py +59 -0
  16. runtimepy-5.6.1/runtimepy/net/ssl.py +33 -0
  17. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/connection.py +37 -10
  18. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/create.py +2 -1
  19. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/http/__init__.py +6 -1
  20. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/util.py +11 -2
  21. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/websocket/connection.py +28 -6
  22. {runtimepy-5.5.0 → runtimepy-5.6.1/runtimepy.egg-info}/PKG-INFO +14 -7
  23. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy.egg-info/SOURCES.txt +2 -0
  24. {runtimepy-5.5.0 → runtimepy-5.6.1}/LICENSE +0 -0
  25. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/__main__.py +0 -0
  26. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/app.py +0 -0
  27. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/__init__.py +0 -0
  28. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/__init__.py +0 -0
  29. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/array.py +0 -0
  30. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/base.py +0 -0
  31. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/command/__init__.py +0 -0
  32. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/command/parser.py +0 -0
  33. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/command/processor.py +0 -0
  34. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/command/result.py +0 -0
  35. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/create.py +0 -0
  36. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/file.py +0 -0
  37. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/sample.py +0 -0
  38. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/environment/telemetry.py +0 -0
  39. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/event/__init__.py +0 -0
  40. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/event/header.py +0 -0
  41. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/channel/registry.py +0 -0
  42. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/codec/__init__.py +0 -0
  43. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/codec/protocol/__init__.py +0 -0
  44. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/codec/protocol/base.py +0 -0
  45. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/codec/protocol/json.py +0 -0
  46. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/codec/system/__init__.py +0 -0
  47. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/__init__.py +0 -0
  48. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/all.py +0 -0
  49. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/arbiter.py +0 -0
  50. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/common.py +0 -0
  51. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/mtu.py +0 -0
  52. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/task.py +0 -0
  53. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/tftp.py +0 -0
  54. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/commands/tui.py +0 -0
  55. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/control/__init__.py +0 -0
  56. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/control/env/__init__.py +0 -0
  57. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/control/source.py +0 -0
  58. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/control/step.py +0 -0
  59. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/browser.yaml +0 -0
  60. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/css/bootstrap_extra.css +0 -0
  61. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/css/main.css +0 -0
  62. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/dummy_load.yaml +0 -0
  63. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/factories.yaml +0 -0
  64. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/favicon.ico +0 -0
  65. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/DataConnection.js +0 -0
  66. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/JsonConnection.js +0 -0
  67. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/audio.js +0 -0
  68. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/ChannelTable.js +0 -0
  69. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/DataConnection.js +0 -0
  70. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/JsonConnection.js +0 -0
  71. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/OverlayManager.js +0 -0
  72. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/Plot.js +0 -0
  73. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/PlotDrawer.js +0 -0
  74. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/PlotManager.js +0 -0
  75. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/PointBuffer.js +0 -0
  76. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/PointManager.js +0 -0
  77. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/TabFilter.js +0 -0
  78. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/TabInterface.js +0 -0
  79. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/UnitSystem.js +0 -0
  80. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/classes/WorkerInterface.js +0 -0
  81. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/events.js +0 -0
  82. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/main.js +0 -0
  83. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/tab/env.js +0 -0
  84. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/tab/sound.js +0 -0
  85. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/third-party/webgl-debug.js +0 -0
  86. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/js/unused/pyodide.js +0 -0
  87. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/sample_telemetry.yaml +0 -0
  88. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/BitFields.yaml +0 -0
  89. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/Channel.yaml +0 -0
  90. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/ChannelCommand.yaml +0 -0
  91. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/ChannelRegistry.yaml +0 -0
  92. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/ClientConnectionConfig.yaml +0 -0
  93. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/ConnectionArbiterConfig.yaml +0 -0
  94. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/EnumRegistry.yaml +0 -0
  95. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/FindFile.yaml +0 -0
  96. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/PeerProcessConfig.yaml +0 -0
  97. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/RuntimeEnum.yaml +0 -0
  98. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/ServerConnectionConfig.yaml +0 -0
  99. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/StructConfig.yaml +0 -0
  100. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/TaskConfig.yaml +0 -0
  101. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/channel_controls.yaml +0 -0
  102. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/has_config.yaml +0 -0
  103. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/has_factory.yaml +0 -0
  104. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/has_name.yaml +0 -0
  105. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/schemas/has_request_flag.yaml +0 -0
  106. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/server.yaml +0 -0
  107. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/server_base.yaml +0 -0
  108. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/server_dev.yaml +0 -0
  109. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/data/tftp_server.yaml +0 -0
  110. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/dev_requirements.txt +0 -0
  111. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/entry.py +0 -0
  112. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/enum/__init__.py +0 -0
  113. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/enum/registry.py +0 -0
  114. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/enum/types.py +0 -0
  115. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mapping.py +0 -0
  116. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/message/__init__.py +0 -0
  117. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/message/handlers.py +0 -0
  118. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/message/interface.py +0 -0
  119. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/message/types.py +0 -0
  120. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/metrics/__init__.py +0 -0
  121. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/metrics/channel.py +0 -0
  122. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/metrics/connection.py +0 -0
  123. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/metrics/task.py +0 -0
  124. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/__init__.py +0 -0
  125. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/async_command.py +0 -0
  126. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/enum.py +0 -0
  127. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/environment.py +0 -0
  128. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/finalize.py +0 -0
  129. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/logging.py +0 -0
  130. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/psutil.py +0 -0
  131. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/regex.py +0 -0
  132. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/mixins/trig.py +0 -0
  133. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/__init__.py +0 -0
  134. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/apps/__init__.py +0 -0
  135. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/__init__.py +0 -0
  136. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/base.py +0 -0
  137. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/config/__init__.py +0 -0
  138. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/config/codec.py +0 -0
  139. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/config/util.py +0 -0
  140. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/factory/__init__.py +0 -0
  141. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/factory/connection.py +0 -0
  142. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/factory/task.py +0 -0
  143. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/housekeeping/__init__.py +0 -0
  144. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/imports/__init__.py +0 -0
  145. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/imports/util.py +0 -0
  146. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/info.py +0 -0
  147. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/result.py +0 -0
  148. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/struct/__init__.py +0 -0
  149. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/task.py +0 -0
  150. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/tcp/json.py +0 -0
  151. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/udp.py +0 -0
  152. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/arbiter/websocket.py +0 -0
  153. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/backoff.py +0 -0
  154. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/connection.py +0 -0
  155. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/factories/__init__.py +0 -0
  156. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/http/__init__.py +0 -0
  157. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/http/common.py +0 -0
  158. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/http/header.py +0 -0
  159. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/http/request_target.py +0 -0
  160. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/http/response.py +0 -0
  161. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/http/state.py +0 -0
  162. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/http/version.py +0 -0
  163. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/manager.py +0 -0
  164. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/mixin.py +0 -0
  165. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/mtu.py +0 -0
  166. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/__init__.py +0 -0
  167. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/base.py +0 -0
  168. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/bootstrap/__init__.py +0 -0
  169. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/bootstrap/elements.py +0 -0
  170. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/bootstrap/tabs.py +0 -0
  171. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/create.py +0 -0
  172. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/elements.py +0 -0
  173. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/modal.py +0 -0
  174. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/tab/__init__.py +0 -0
  175. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/tab/base.py +0 -0
  176. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/tab/controls.py +0 -0
  177. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/tab/html.py +0 -0
  178. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/tab/message.py +0 -0
  179. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/env/widgets.py +0 -0
  180. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/files.py +0 -0
  181. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/landing_page.py +0 -0
  182. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/placeholder.py +0 -0
  183. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/pyodide.py +0 -0
  184. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/sound.py +0 -0
  185. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/app/tab.py +0 -0
  186. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/html.py +0 -0
  187. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/json.py +0 -0
  188. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/struct/__init__.py +0 -0
  189. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/websocket/__init__.py +0 -0
  190. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/server/websocket/state.py +0 -0
  191. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/stream/__init__.py +0 -0
  192. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/stream/base.py +0 -0
  193. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/stream/json/__init__.py +0 -0
  194. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/stream/string.py +0 -0
  195. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/__init__.py +0 -0
  196. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/protocol.py +0 -0
  197. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/scpi/__init__.py +0 -0
  198. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/telnet/__init__.py +0 -0
  199. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/telnet/codes.py +0 -0
  200. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/tcp/telnet/np_05b.py +0 -0
  201. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/__init__.py +0 -0
  202. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/connection.py +0 -0
  203. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/create.py +0 -0
  204. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/protocol.py +0 -0
  205. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/queue.py +0 -0
  206. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/tftp/__init__.py +0 -0
  207. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/tftp/base.py +0 -0
  208. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/tftp/endpoint.py +0 -0
  209. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/tftp/enums.py +0 -0
  210. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/udp/tftp/io.py +0 -0
  211. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/net/websocket/__init__.py +0 -0
  212. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/noise/__init__.py +0 -0
  213. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/__init__.py +0 -0
  214. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/array/__init__.py +0 -0
  215. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/base.py +0 -0
  216. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/bool.py +0 -0
  217. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/byte_order.py +0 -0
  218. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/evaluation.py +0 -0
  219. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/field/__init__.py +0 -0
  220. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/field/fields.py +0 -0
  221. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/field/manager/__init__.py +0 -0
  222. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/field/manager/base.py +0 -0
  223. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/float.py +0 -0
  224. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/int.py +0 -0
  225. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/scaling.py +0 -0
  226. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/serializable/__init__.py +0 -0
  227. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/serializable/base.py +0 -0
  228. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/serializable/fixed.py +0 -0
  229. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/serializable/framer.py +0 -0
  230. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/serializable/prefixed.py +0 -0
  231. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/string.py +0 -0
  232. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/types/__init__.py +0 -0
  233. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/types/base.py +0 -0
  234. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/types/bool.py +0 -0
  235. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/types/bounds.py +0 -0
  236. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/types/float.py +0 -0
  237. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/primitives/types/int.py +0 -0
  238. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/py.typed +0 -0
  239. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/registry/__init__.py +0 -0
  240. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/registry/bool.py +0 -0
  241. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/registry/item.py +0 -0
  242. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/registry/name.py +0 -0
  243. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/requirements.txt +0 -0
  244. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/sample/__init__.py +0 -0
  245. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/sample/peer.py +0 -0
  246. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/sample/program.py +0 -0
  247. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/schemas.py +0 -0
  248. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/struct/__init__.py +0 -0
  249. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/subprocess/__init__.py +0 -0
  250. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/subprocess/interface.py +0 -0
  251. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/subprocess/peer.py +0 -0
  252. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/subprocess/program.py +0 -0
  253. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/subprocess/protocol.py +0 -0
  254. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/task/__init__.py +0 -0
  255. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/task/asynchronous.py +0 -0
  256. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/task/basic/__init__.py +0 -0
  257. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/task/basic/manager.py +0 -0
  258. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/task/basic/periodic.py +0 -0
  259. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/task/sample.py +0 -0
  260. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/task/trig/__init__.py +0 -0
  261. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/telemetry/__init__.py +0 -0
  262. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/telemetry/sample.py +0 -0
  263. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/tui/__init__.py +0 -0
  264. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/tui/channels/__init__.py +0 -0
  265. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/tui/cursor.py +0 -0
  266. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/tui/mixin.py +0 -0
  267. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/tui/mock.py +0 -0
  268. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/tui/task.py +0 -0
  269. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/ui/__init__.py +0 -0
  270. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/ui/controls.py +0 -0
  271. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy/util.py +0 -0
  272. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy.egg-info/dependency_links.txt +0 -0
  273. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy.egg-info/entry_points.txt +0 -0
  274. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy.egg-info/requires.txt +2 -2
  275. {runtimepy-5.5.0 → runtimepy-5.6.1}/runtimepy.egg-info/top_level.txt +0 -0
  276. {runtimepy-5.5.0 → runtimepy-5.6.1}/setup.cfg +0 -0
  277. {runtimepy-5.5.0 → runtimepy-5.6.1}/setup.py +0 -0
  278. {runtimepy-5.5.0 → runtimepy-5.6.1}/tests/test_entry.py +0 -0
  279. {runtimepy-5.5.0 → runtimepy-5.6.1}/tests/test_mapping.py +0 -0
  280. {runtimepy-5.5.0 → runtimepy-5.6.1}/tests/test_resources.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: runtimepy
3
- Version: 5.5.0
3
+ Version: 5.6.1
4
4
  Summary: A framework for implementing Python services.
5
5
  Home-page: https://github.com/vkottler/runtimepy
6
6
  Author: Vaughn Kottler
@@ -17,10 +17,10 @@ Classifier: License :: OSI Approved :: MIT License
17
17
  Requires-Python: >=3.11
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
- Requires-Dist: websockets
20
+ Requires-Dist: vcorelib>=3.3.1
21
21
  Requires-Dist: svgen>=0.6.8
22
+ Requires-Dist: websockets
22
23
  Requires-Dist: psutil
23
- Requires-Dist: vcorelib>=3.3.1
24
24
  Provides-Extra: test
25
25
  Requires-Dist: pylint; extra == "test"
26
26
  Requires-Dist: flake8; extra == "test"
@@ -44,11 +44,11 @@ Requires-Dist: uvloop; (sys_platform != "win32" and sys_platform != "cygwin") an
44
44
  =====================================
45
45
  generator=datazen
46
46
  version=3.1.4
47
- hash=5c5edaf1332d842e9ca04a018455beba
47
+ hash=a82bbd8413b0036b345251da16b462c3
48
48
  =====================================
49
49
  -->
50
50
 
51
- # runtimepy ([5.5.0](https://pypi.org/project/runtimepy/))
51
+ # runtimepy ([5.6.1](https://pypi.org/project/runtimepy/))
52
52
 
53
53
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
54
54
  ![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
@@ -165,8 +165,10 @@ options:
165
165
  ```
166
166
  $ ./venv3.12/bin/runtimepy server -h
167
167
 
168
- usage: runtimepy server [-h] [-i] [-w] [--no-poller] [--host HOST] [-p PORT]
169
- [-u] [-l]
168
+ usage: runtimepy server [-h] [-i] [-w] [--no-poller] [--cafile CAFILE]
169
+ [--capath CAPATH] [--cadata CADATA]
170
+ [--certfile CERTFILE] [--keyfile KEYFILE]
171
+ [--host HOST] [-p PORT] [-u] [-l]
170
172
  factory [configs ...]
171
173
 
172
174
  positional arguments:
@@ -181,6 +183,11 @@ options:
181
183
  ensure that a 'wait_for_stop' application method is
182
184
  run last
183
185
  --no-poller don't run a connection-metrics poller task
186
+ --cafile CAFILE passed directly to instantiation
187
+ --capath CAPATH passed directly to instantiation
188
+ --cadata CADATA passed directly to instantiation
189
+ --certfile CERTFILE passed directly to instantiation
190
+ --keyfile KEYFILE passed directly to instantiation
184
191
  --host HOST host address to listen on (default: '0.0.0.0')
185
192
  -p PORT, --port PORT port to listen on (default: 0)
186
193
  -u, --udp whether or not this is a UDP-based server (otherwise
@@ -2,11 +2,11 @@
2
2
  =====================================
3
3
  generator=datazen
4
4
  version=3.1.4
5
- hash=5c5edaf1332d842e9ca04a018455beba
5
+ hash=a82bbd8413b0036b345251da16b462c3
6
6
  =====================================
7
7
  -->
8
8
 
9
- # runtimepy ([5.5.0](https://pypi.org/project/runtimepy/))
9
+ # runtimepy ([5.6.1](https://pypi.org/project/runtimepy/))
10
10
 
11
11
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
12
12
  ![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
@@ -123,8 +123,10 @@ options:
123
123
  ```
124
124
  $ ./venv3.12/bin/runtimepy server -h
125
125
 
126
- usage: runtimepy server [-h] [-i] [-w] [--no-poller] [--host HOST] [-p PORT]
127
- [-u] [-l]
126
+ usage: runtimepy server [-h] [-i] [-w] [--no-poller] [--cafile CAFILE]
127
+ [--capath CAPATH] [--cadata CADATA]
128
+ [--certfile CERTFILE] [--keyfile KEYFILE]
129
+ [--host HOST] [-p PORT] [-u] [-l]
128
130
  factory [configs ...]
129
131
 
130
132
  positional arguments:
@@ -139,6 +141,11 @@ options:
139
141
  ensure that a 'wait_for_stop' application method is
140
142
  run last
141
143
  --no-poller don't run a connection-metrics poller task
144
+ --cafile CAFILE passed directly to instantiation
145
+ --capath CAPATH passed directly to instantiation
146
+ --cadata CADATA passed directly to instantiation
147
+ --certfile CERTFILE passed directly to instantiation
148
+ --keyfile KEYFILE passed directly to instantiation
142
149
  --host HOST host address to listen on (default: '0.0.0.0')
143
150
  -p PORT, --port PORT port to listen on (default: 0)
144
151
  -u, --udp whether or not this is a UDP-based server (otherwise
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"
4
4
 
5
5
  [project]
6
6
  name = "runtimepy"
7
- version = "5.5.0"
7
+ version = "5.6.1"
8
8
  description = "A framework for implementing Python services."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,7 +1,7 @@
1
1
  # =====================================
2
2
  # generator=datazen
3
3
  # version=3.1.4
4
- # hash=e8348ec684fac751916510d1d8c7dafb
4
+ # hash=d200504a923864c56b7eb211fd10233a
5
5
  # =====================================
6
6
 
7
7
  """
@@ -10,7 +10,7 @@ Useful defaults and other package metadata.
10
10
 
11
11
  DESCRIPTION = "A framework for implementing Python services."
12
12
  PKG_NAME = "runtimepy"
13
- VERSION = "5.5.0"
13
+ VERSION = "5.6.1"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -14,6 +14,9 @@ from vcorelib.args import CommandFunction as _CommandFunction
14
14
  from runtimepy.commands.arbiter import arbiter_cmd
15
15
  from runtimepy.commands.common import FACTORIES, arbiter_args, cmd_with_jit
16
16
 
17
+ SSL_PASSTHROUGH = ["cafile", "capath", "cadata", "certfile"]
18
+ PASSTHROUGH = SSL_PASSTHROUGH + ["keyfile"]
19
+
17
20
 
18
21
  def port_name(args: _Namespace, port: str = "port") -> str:
19
22
  """Get the name for a connection factory's port."""
@@ -25,7 +28,7 @@ def server_data(args: _Namespace) -> dict[str, Any]:
25
28
 
26
29
  return {
27
30
  "factory": args.factory,
28
- "kwargs": {"port": f"${port_name(args)}", "host": args.host},
31
+ "kwargs": get_kwargs(args, port=f"${port_name(args)}", host=args.host),
29
32
  }
30
33
 
31
34
 
@@ -34,6 +37,26 @@ def is_websocket(args: _Namespace) -> bool:
34
37
  return "websocket" in args.factory.lower()
35
38
 
36
39
 
40
+ def is_ssl(kwargs: dict[str, Any]) -> bool:
41
+ """Determine if server arugments indicate SSL use."""
42
+ return any(x in kwargs for x in SSL_PASSTHROUGH)
43
+
44
+
45
+ def get_kwargs(args: _Namespace, **kwargs) -> dict[str, Any]:
46
+ """Get boilerplate kwargs."""
47
+
48
+ new_kwargs: dict[str, Any] = {**kwargs}
49
+
50
+ # Pass additional arguments through.
51
+ print(args)
52
+ for opt in PASSTHROUGH:
53
+ value = getattr(args, opt, None)
54
+ if value is not None:
55
+ new_kwargs[opt] = value
56
+
57
+ return new_kwargs
58
+
59
+
37
60
  def client_data(args: _Namespace) -> dict[str, Any]:
38
61
  """Get client data based on command-line arguments."""
39
62
 
@@ -43,7 +66,9 @@ def client_data(args: _Namespace) -> dict[str, Any]:
43
66
  kwargs: dict[str, Any] = {}
44
67
 
45
68
  if is_websocket(args):
46
- arg_list.append(f"ws://localhost:{port}")
69
+ arg_list.append(
70
+ f"ws{'s' if is_ssl(get_kwargs(args)) else ''}://localhost:{port}"
71
+ )
47
72
  elif not args.udp:
48
73
  kwargs["host"] = "localhost"
49
74
  kwargs["port"] = port
@@ -76,7 +101,9 @@ def config_data(args: _Namespace) -> dict[str, Any]:
76
101
  {
77
102
  "name": port_name(args, port="server"),
78
103
  "factory": args.factory,
79
- "kwargs": {"local_addr": ["0.0.0.0", f"${port_name(args)}"]},
104
+ "kwargs": get_kwargs(
105
+ args, local_addr=["0.0.0.0", f"${port_name(args)}"]
106
+ ),
80
107
  }
81
108
  )
82
109
 
@@ -108,6 +135,11 @@ def add_server_cmd(parser: _ArgumentParser) -> _CommandFunction:
108
135
  """Add server-command arguments to its parser."""
109
136
 
110
137
  with arbiter_args(parser, nargs="*"):
138
+ for optional in PASSTHROUGH:
139
+ parser.add_argument(
140
+ f"--{optional}", help="passed directly to instantiation"
141
+ )
142
+
111
143
  parser.add_argument(
112
144
  "--host",
113
145
  default="0.0.0.0",
@@ -53,6 +53,12 @@ class App {
53
53
  this.switchTab(hash.tab);
54
54
  }
55
55
 
56
+ /* Handle settings controls. */
57
+ loadSettings();
58
+
59
+ /* Handle individual settings. */
60
+ this.handleInitialMinTxPeriod();
61
+
56
62
  startMainLoop();
57
63
  }
58
64
  }, {once : true});
@@ -62,6 +68,33 @@ class App {
62
68
 
63
69
  bootstrap_init();
64
70
  }
71
+
72
+ handleInitialMinTxPeriod() {
73
+ if ("min-tx-period-ms" in settings) {
74
+ /* Set up event handle. */
75
+ setupCursorContext(settings["min-tx-period-ms"], (elem, down, move,
76
+ up) => {
77
+ setupCursorMove(
78
+ elem, down, move, up,
79
+ (event) => { this.updateMinTxPeriod(Number(event.target.value)); });
80
+ });
81
+
82
+ /* Set slider to correct value. */
83
+ settings["min-tx-period-ms"].value = hash.minTxPeriod;
84
+ settings["min-tx-period-ms"].title = hash.minTxPeriod;
85
+ }
86
+
87
+ this.updateMinTxPeriod();
88
+ }
89
+
90
+ updateMinTxPeriod(value) {
91
+ if (value || value === 0) {
92
+ hash.setMinTxPeriod(value);
93
+ settings["min-tx-period-ms"].title = value;
94
+ }
95
+ this.worker.postMessage(
96
+ {"event" : {"worker" : {"min-tx-period-ms" : hash.minTxPeriod}}});
97
+ }
65
98
  }
66
99
 
67
100
  function startMainLoop() {
@@ -6,6 +6,8 @@ class PlotModalManager {
6
6
  this.body = this.container.querySelector(".modal-body");
7
7
  this.footer = this.container.querySelector(".modal-footer");
8
8
 
9
+ this.plotStatus = this.container.querySelector("#plot-status-inner");
10
+
9
11
  this.byEnv = {};
10
12
  }
11
13
 
@@ -34,7 +36,7 @@ class PlotModalManager {
34
36
  }
35
37
  }
36
38
 
37
- this.body.innerHTML = content;
39
+ this.plotStatus.innerHTML = content;
38
40
  }
39
41
  }
40
42
 
@@ -9,6 +9,7 @@ class WindowHashManager {
9
9
  this.channelsShown = true;
10
10
  this.plotChannels = {};
11
11
  this.filters = {};
12
+ this.minTxPeriod = 0.0;
12
13
  }
13
14
 
14
15
  tabClick(event) {
@@ -160,8 +161,13 @@ class WindowHashManager {
160
161
  for (let item of split) {
161
162
  if (item.includes("=")) {
162
163
  let keyVal = item.split("=");
163
- if (keyVal.length == 2 && keyVal[0] == "filter" && keyVal[1]) {
164
- this.updateTabFilter(keyVal[1]);
164
+ if (keyVal.length == 2) {
165
+ if (keyVal[0] == "filter" && keyVal[1]) {
166
+ this.updateTabFilter(keyVal[1]);
167
+ }
168
+ if (keyVal[0] == "min-tx-period-ms") {
169
+ this.minTxPeriod = Number(keyVal[1]);
170
+ }
165
171
  }
166
172
  }
167
173
  }
@@ -176,6 +182,11 @@ class WindowHashManager {
176
182
  return result;
177
183
  }
178
184
 
185
+ setMinTxPeriod(value) {
186
+ this.minTxPeriod = value;
187
+ this.update();
188
+ }
189
+
179
190
  buildHash() {
180
191
  let hash = this.tab;
181
192
 
@@ -189,6 +200,10 @@ class WindowHashManager {
189
200
  hash += ",hide-channels"
190
201
  }
191
202
 
203
+ if (this.minTxPeriod != 0.0) {
204
+ hash += `,min-tx-period-ms=${this.minTxPeriod}`;
205
+ }
206
+
192
207
  for (let tab in tabs) {
193
208
  let firstChan = true;
194
209
 
@@ -46,3 +46,15 @@ function setupCursorMove(elem, down, move, up, handleMove) {
46
46
  function randomHexColor() {
47
47
  return "#" + (Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, "0");
48
48
  }
49
+
50
+ /* Load settings control mappings. */
51
+ let settings = {};
52
+
53
+ function loadSettings() {
54
+ for (const key of ["min-tx-period-ms"]) {
55
+ let elem = document.getElementById(`setting-${key}`);
56
+ if (elem) {
57
+ settings[key] = elem;
58
+ }
59
+ }
60
+ }
@@ -1,6 +1,15 @@
1
1
  function worker_config(config) {
2
2
  let worker_cfg = {};
3
3
 
4
+ let port_name = "runtimepy_websocket";
5
+ let uri_prefix = "ws";
6
+
7
+ /* Ensured TLS is handled properly. */
8
+ if (location.protocol.includes("https")) {
9
+ port_name = "runtimepy_secure_websocket";
10
+ uri_prefix += "s";
11
+ }
12
+
4
13
  /* Look for connections to establish. */
5
14
  let ports = config["config"]["ports"];
6
15
  for (let port_idx in ports) {
@@ -10,11 +19,11 @@ function worker_config(config) {
10
19
  let hostname = window.location.hostname;
11
20
 
12
21
  /* This business logic could use some work. */
13
- if (port["name"].includes("runtimepy_websocket")) {
22
+ if (port["name"].includes(port_name)) {
14
23
  if (port["name"].includes("data")) {
15
- worker_cfg["data"] = "ws://" + hostname + ":" + port["port"];
24
+ worker_cfg["data"] = `${uri_prefix}://${hostname}:` + port["port"];
16
25
  } else {
17
- worker_cfg["json"] = "ws://" + hostname + ":" + port["port"];
26
+ worker_cfg["json"] = `${uri_prefix}://${hostname}:` + port["port"];
18
27
  }
19
28
  }
20
29
  }
@@ -13,11 +13,16 @@ function create_connections(config) {
13
13
 
14
14
  const plots = new PlotManager();
15
15
 
16
+ /* Used to control messaging rate with server. */
17
+ let minTxPeriod = 0.0;
18
+
16
19
  async function message(data) {
17
20
  if ("plot" in data) {
18
21
  /* Forward the 'name' field. */
19
22
  data["plot"]["name"] = data["name"];
20
23
  await plots.handleMessage(data["plot"]);
24
+ } else if ("min-tx-period-ms" in data) {
25
+ minTxPeriod = data["min-tx-period-ms"];
21
26
  } else {
22
27
  console.log(`Message for worker:`);
23
28
  console.log(data);
@@ -38,9 +43,14 @@ async function start(config) {
38
43
  onmessage = async (event) => {
39
44
  /* Handle messages meant for this thread. */
40
45
  if ("event" in event.data && "worker" in event.data["event"]) {
46
+ let data = event.data["event"]["worker"];
47
+
41
48
  /* Forward the 'name' field. */
42
- event.data["event"]["worker"]["name"] = event.data["name"];
43
- await message(event.data["event"]["worker"]);
49
+ if ("name" in event.data) {
50
+ data["name"] = event.data["name"];
51
+ }
52
+
53
+ await message(data);
44
54
  }
45
55
  /* Forward all other messages to the server. */
46
56
  else {
@@ -63,13 +73,18 @@ async function start(config) {
63
73
  /* Tell main thread we're ready to go. */
64
74
  postMessage(0);
65
75
 
76
+ let messageTxTime = 0.0;
77
+
66
78
  /* Set up the main request-animation-frame loop. */
67
79
  function render(time) {
68
80
  /* Render plot. */
69
81
  plots.render(time);
70
82
 
71
83
  /* Keep the server synchronized with frames. */
72
- conns["json"].send_json({"ui" : {"time" : time}});
84
+ if (messageTxTime + minTxPeriod <= time) {
85
+ conns["json"].send_json({"ui" : {"time" : time}});
86
+ messageTxTime = time;
87
+ }
73
88
 
74
89
  requestAnimationFrame(render);
75
90
  }
@@ -42,6 +42,7 @@ class TcpConnectionFactory(_ConnectionFactory, _Generic[T]):
42
42
  """Create a task that will run a connection server."""
43
43
 
44
44
  assert not [*args], "Only keyword arguments are used!"
45
+
45
46
  return self.kind.app(
46
47
  stop_sig,
47
48
  manager=manager,
@@ -27,26 +27,27 @@ async def launch_browser(app: AppInfo) -> None:
27
27
  """
28
28
 
29
29
  # Launch browser based on config option.
30
- if config_param(app, "xdg_open_http", False):
31
-
32
- port: Any
33
- for port in app.config["root"]["ports"]: # type: ignore
34
- if "http_server" in port["name"]:
35
- # URI parameters.
36
- hostname = config_param(app, "xdg_host", "localhost")
37
-
38
- # Assemble URI.
39
- uri = f"http://{hostname}:{port['port']}/"
40
-
41
- # Add a fragment if one was specified.
42
- fragment = config_param(app, "xdg_fragment", "")
43
- if fragment:
44
- uri += "#" + fragment
45
-
46
- with suppress(FileNotFoundError):
47
- await app.stack.enter_async_context(
48
- spawn_exec("xdg-open", uri)
49
- )
30
+ for prefix in ["http", "https"]:
31
+ if config_param(app, f"xdg_open_{prefix}", False):
32
+
33
+ port: Any
34
+ for port in app.config["root"]["ports"]: # type: ignore
35
+ if f"{prefix}_server" in port["name"]:
36
+ # URI parameters.
37
+ hostname = config_param(app, "xdg_host", "localhost")
38
+
39
+ # Assemble URI.
40
+ uri = f"{prefix}://{hostname}:{port['port']}/"
41
+
42
+ # Add a fragment if one was specified.
43
+ fragment = config_param(app, "xdg_fragment", "")
44
+ if fragment:
45
+ uri += "#" + fragment
46
+
47
+ with suppress(FileNotFoundError):
48
+ await app.stack.enter_async_context(
49
+ spawn_exec("xdg-open", uri)
50
+ )
50
51
 
51
52
 
52
53
  # Could add an interface for adding multiple applications.
@@ -11,6 +11,7 @@ from runtimepy.net.arbiter.info import AppInfo
11
11
  from runtimepy.net.server.app.bootstrap.elements import input_box
12
12
  from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
13
13
  from runtimepy.net.server.app.env.modal import Modal
14
+ from runtimepy.net.server.app.env.settings import plot_settings
14
15
  from runtimepy.net.server.app.env.tab import ChannelEnvironmentTab
15
16
  from runtimepy.net.server.app.placeholder import dummy_tabs, under_construction
16
17
  from runtimepy.net.server.app.sound import SoundTab
@@ -85,8 +86,7 @@ def channel_environments(app: AppInfo, tabs: TabbedContent) -> None:
85
86
  )
86
87
 
87
88
  # Plot settings modal.
88
- plot_settings = Modal(tabs, name="plot", icon="graph-up")
89
- under_construction(plot_settings.footer)
89
+ plot_settings(tabs)
90
90
 
91
91
  # Experimental features.
92
92
  if app.config_param("experimental", False):
@@ -0,0 +1,59 @@
1
+ """
2
+ A module implementing an application-settings modal.
3
+ """
4
+
5
+ # third-party
6
+ from svgen.element.html import div
7
+
8
+ # internal
9
+ from runtimepy.net.server.app.bootstrap.elements import flex, slider
10
+ from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
11
+ from runtimepy.net.server.app.env.modal import Modal
12
+ from runtimepy.net.server.app.placeholder import under_construction
13
+
14
+
15
+ def plot_settings(tabs: TabbedContent) -> None:
16
+ """Create the plot settings modal."""
17
+
18
+ modal = Modal(tabs, name="plot", icon="graph-up")
19
+ under_construction(modal.footer)
20
+
21
+ div(tag="h1", text="settings", parent=modal.body)
22
+ div(tag="hr", parent=modal.body)
23
+
24
+ div(tag="h2", text="plot status", parent=modal.body)
25
+ div(id="plot-status-inner", parent=modal.body)
26
+ div(tag="hr", parent=modal.body)
27
+
28
+ div(tag="h2", text="minimum transmit period (ms)", parent=modal.body)
29
+
30
+ div(
31
+ tag="p",
32
+ text=(
33
+ "Can be used to throttle the rate of "
34
+ "client <-> server communication. Use the 'ui' tab's metrics to "
35
+ "determine performance impact. Note that only this browser tab's "
36
+ "messaging rate can be controlled (not other connected clients')."
37
+ ),
38
+ parent=modal.body,
39
+ )
40
+
41
+ container = flex(parent=modal.body)
42
+
43
+ div(
44
+ text="0 ms ('high', run at native refresh rate)",
45
+ parent=container,
46
+ class_str="text-nowrap text-primary",
47
+ )
48
+
49
+ slider(
50
+ 0, 100, 100, parent=container, value=0, id="setting-min-tx-period-ms"
51
+ ).add_class("ms-3 me-3")
52
+
53
+ div(
54
+ text="100 ms ('low', 10 Hz)",
55
+ parent=container,
56
+ class_str="text-nowrap text-primary",
57
+ )
58
+
59
+ div(tag="hr", parent=modal.body)
@@ -0,0 +1,33 @@
1
+ """
2
+ A module implementing SSL-related interfaces.
3
+ """
4
+
5
+ # built-in
6
+ import ssl
7
+ from typing import Any
8
+
9
+
10
+ def handle_possible_ssl(client: bool = True, **kwargs) -> dict[str, Any]:
11
+ """Handle creating an SSL context based on keyword arguments."""
12
+
13
+ args = ["cafile", "capath", "cadata"]
14
+ if (
15
+ kwargs.pop("use_ssl", False)
16
+ or any(x in kwargs for x in args)
17
+ or "certfile" in kwargs
18
+ ):
19
+ context = ssl.create_default_context(
20
+ purpose=(
21
+ ssl.Purpose.SERVER_AUTH if client else ssl.Purpose.CLIENT_AUTH
22
+ ),
23
+ **{x: kwargs.pop(x, None) for x in args},
24
+ )
25
+
26
+ if "certfile" in kwargs:
27
+ context.load_cert_chain(
28
+ kwargs.pop("certfile"), keyfile=kwargs.pop("keyfile", None)
29
+ )
30
+
31
+ kwargs["ssl"] = context
32
+
33
+ return kwargs