runtimepy 5.10.2__tar.gz → 5.11.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. {runtimepy-5.10.2/runtimepy.egg-info → runtimepy-5.11.0}/PKG-INFO +6 -6
  2. {runtimepy-5.10.2 → runtimepy-5.11.0}/README.md +2 -2
  3. {runtimepy-5.10.2 → runtimepy-5.11.0}/pyproject.toml +1 -1
  4. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/__init__.py +2 -2
  5. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/array.py +4 -4
  6. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/telemetry.py +3 -3
  7. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/event/__init__.py +1 -1
  8. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/codec/protocol/__init__.py +3 -2
  9. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/codec/protocol/base.py +97 -54
  10. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/codec/protocol/json.py +18 -13
  11. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/codec/system/__init__.py +2 -3
  12. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/__init__.py +0 -1
  13. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/array/__init__.py +28 -9
  14. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/bool.py +13 -6
  15. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/float.py +5 -0
  16. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/int.py +7 -0
  17. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/serializable/__init__.py +1 -1
  18. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/serializable/base.py +47 -19
  19. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/types/bounds.py +5 -0
  20. {runtimepy-5.10.2 → runtimepy-5.11.0/runtimepy.egg-info}/PKG-INFO +6 -6
  21. {runtimepy-5.10.2 → runtimepy-5.11.0}/LICENSE +0 -0
  22. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/__main__.py +0 -0
  23. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/app.py +0 -0
  24. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/__init__.py +0 -0
  25. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/__init__.py +0 -0
  26. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/base.py +0 -0
  27. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/command/__init__.py +0 -0
  28. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/command/parser.py +0 -0
  29. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/command/processor.py +0 -0
  30. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/command/result.py +0 -0
  31. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/create.py +0 -0
  32. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/file.py +0 -0
  33. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/environment/sample.py +0 -0
  34. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/event/header.py +0 -0
  35. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/channel/registry.py +0 -0
  36. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/codec/__init__.py +0 -0
  37. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/__init__.py +0 -0
  38. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/all.py +0 -0
  39. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/arbiter.py +0 -0
  40. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/common.py +0 -0
  41. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/mtu.py +0 -0
  42. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/server.py +0 -0
  43. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/task.py +0 -0
  44. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/tftp.py +0 -0
  45. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/commands/tui.py +0 -0
  46. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/control/__init__.py +0 -0
  47. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/control/env/__init__.py +0 -0
  48. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/control/source.py +0 -0
  49. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/control/step.py +0 -0
  50. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/404.html +0 -0
  51. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/browser.yaml +0 -0
  52. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/css/bootstrap_extra.css +0 -0
  53. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/css/font.css +0 -0
  54. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/css/main.css +0 -0
  55. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/dummy_load.yaml +0 -0
  56. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/factories.yaml +0 -0
  57. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/favicon.ico +0 -0
  58. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/DataConnection.js +0 -0
  59. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/JsonConnection.js +0 -0
  60. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/audio.js +0 -0
  61. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/App.js +0 -0
  62. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/ChannelTable.js +0 -0
  63. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/DataConnection.js +0 -0
  64. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/JsonConnection.js +0 -0
  65. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/OverlayManager.js +0 -0
  66. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/Plot.js +0 -0
  67. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/PlotDrawer.js +0 -0
  68. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/PlotManager.js +0 -0
  69. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/PlotModalManager.js +0 -0
  70. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/PointBuffer.js +0 -0
  71. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/PointManager.js +0 -0
  72. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/TabFilter.js +0 -0
  73. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/TabInterface.js +0 -0
  74. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/UnitSystem.js +0 -0
  75. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/WindowHashManager.js +0 -0
  76. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/classes/WorkerInterface.js +0 -0
  77. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/events.js +0 -0
  78. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/init.js +0 -0
  79. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/main.js +0 -0
  80. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/markdown_page.js +0 -0
  81. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/tab/env.js +0 -0
  82. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/tab/sound.js +0 -0
  83. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/third-party/webgl-debug.js +0 -0
  84. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/unused/pyodide.js +0 -0
  85. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/util.js +0 -0
  86. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/js/worker.js +0 -0
  87. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/md/Connection.md +0 -0
  88. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/md/PeriodicTask.md +0 -0
  89. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/md/RuntimeStruct.md +0 -0
  90. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/md/RuntimepyPeer.md +0 -0
  91. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/md/SinusoidTask.md +0 -0
  92. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/sample_telemetry.yaml +0 -0
  93. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/BitFields.yaml +0 -0
  94. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/Channel.yaml +0 -0
  95. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/ChannelCommand.yaml +0 -0
  96. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/ChannelRegistry.yaml +0 -0
  97. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/ClientConnectionConfig.yaml +0 -0
  98. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/ConnectionArbiterConfig.yaml +0 -0
  99. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/EnumRegistry.yaml +0 -0
  100. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/FindFile.yaml +0 -0
  101. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/PeerProcessConfig.yaml +0 -0
  102. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/RuntimeEnum.yaml +0 -0
  103. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/ServerConnectionConfig.yaml +0 -0
  104. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/StructConfig.yaml +0 -0
  105. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/TaskConfig.yaml +0 -0
  106. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/channel_controls.yaml +0 -0
  107. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/has_config.yaml +0 -0
  108. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/has_factory.yaml +0 -0
  109. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/has_markdown.yaml +0 -0
  110. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/has_name.yaml +0 -0
  111. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/schemas/has_request_flag.yaml +0 -0
  112. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/server.yaml +0 -0
  113. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/server_base.yaml +0 -0
  114. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/server_dev.yaml +0 -0
  115. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/svg/chip-circle-bootstrap.svg +0 -0
  116. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-Bold.woff2 +0 -0
  117. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-BoldItalic.woff2 +0 -0
  118. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-Italic.woff2 +0 -0
  119. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-Regular.woff2 +0 -0
  120. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-Bold.woff2 +0 -0
  121. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-BoldItalic.woff2 +0 -0
  122. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-Italic.woff2 +0 -0
  123. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-Regular.woff2 +0 -0
  124. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/static/woff2/README.md +0 -0
  125. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/data/tftp_server.yaml +0 -0
  126. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/dev_requirements.txt +0 -0
  127. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/entry.py +0 -0
  128. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/enum/__init__.py +0 -0
  129. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/enum/registry.py +0 -0
  130. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/enum/types.py +0 -0
  131. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mapping.py +0 -0
  132. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/message/__init__.py +0 -0
  133. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/message/handlers.py +0 -0
  134. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/message/interface.py +0 -0
  135. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/message/types.py +0 -0
  136. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/metrics/__init__.py +0 -0
  137. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/metrics/channel.py +0 -0
  138. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/metrics/connection.py +0 -0
  139. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/metrics/task.py +0 -0
  140. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/__init__.py +0 -0
  141. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/async_command.py +0 -0
  142. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/enum.py +0 -0
  143. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/environment.py +0 -0
  144. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/finalize.py +0 -0
  145. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/logging.py +0 -0
  146. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/psutil.py +0 -0
  147. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/regex.py +0 -0
  148. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/mixins/trig.py +0 -0
  149. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/__init__.py +0 -0
  150. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/apps/__init__.py +0 -0
  151. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/__init__.py +0 -0
  152. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/base.py +0 -0
  153. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/config/__init__.py +0 -0
  154. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/config/codec.py +0 -0
  155. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/config/util.py +0 -0
  156. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/factory/__init__.py +0 -0
  157. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/factory/connection.py +0 -0
  158. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/factory/task.py +0 -0
  159. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/housekeeping/__init__.py +0 -0
  160. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/imports/__init__.py +0 -0
  161. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/imports/util.py +0 -0
  162. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/info.py +0 -0
  163. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/result.py +0 -0
  164. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/struct/__init__.py +0 -0
  165. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/task.py +0 -0
  166. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/tcp/__init__.py +0 -0
  167. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/tcp/json.py +0 -0
  168. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/udp.py +0 -0
  169. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/arbiter/websocket.py +0 -0
  170. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/backoff.py +0 -0
  171. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/connection.py +0 -0
  172. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/factories/__init__.py +0 -0
  173. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/html/__init__.py +0 -0
  174. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/html/arbiter.py +0 -0
  175. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/html/bootstrap/__init__.py +0 -0
  176. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/html/bootstrap/elements.py +0 -0
  177. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/html/bootstrap/tabs.py +0 -0
  178. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/http/__init__.py +0 -0
  179. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/http/common.py +0 -0
  180. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/http/header.py +0 -0
  181. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/http/request_target.py +0 -0
  182. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/http/response.py +0 -0
  183. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/http/state.py +0 -0
  184. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/http/version.py +0 -0
  185. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/manager.py +0 -0
  186. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/mixin.py +0 -0
  187. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/mtu.py +0 -0
  188. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/__init__.py +0 -0
  189. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/__init__.py +0 -0
  190. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/base.py +0 -0
  191. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/create.py +0 -0
  192. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/elements.py +0 -0
  193. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/__init__.py +0 -0
  194. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/modal.py +0 -0
  195. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/settings.py +0 -0
  196. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/__init__.py +0 -0
  197. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/base.py +0 -0
  198. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/controls.py +0 -0
  199. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/html.py +0 -0
  200. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/message.py +0 -0
  201. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/env/widgets.py +0 -0
  202. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/files.py +0 -0
  203. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/landing_page.py +0 -0
  204. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/placeholder.py +0 -0
  205. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/pyodide.py +0 -0
  206. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/sound.py +0 -0
  207. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/app/tab.py +0 -0
  208. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/html.py +0 -0
  209. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/json.py +0 -0
  210. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/markdown.py +0 -0
  211. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/struct/__init__.py +0 -0
  212. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/websocket/__init__.py +0 -0
  213. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/server/websocket/state.py +0 -0
  214. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/ssl.py +0 -0
  215. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/stream/__init__.py +0 -0
  216. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/stream/base.py +0 -0
  217. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/stream/json/__init__.py +0 -0
  218. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/stream/string.py +0 -0
  219. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/__init__.py +0 -0
  220. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/connection.py +0 -0
  221. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/create.py +0 -0
  222. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/http/__init__.py +0 -0
  223. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/protocol.py +0 -0
  224. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/scpi/__init__.py +0 -0
  225. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/telnet/__init__.py +0 -0
  226. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/telnet/codes.py +0 -0
  227. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/tcp/telnet/np_05b.py +0 -0
  228. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/__init__.py +0 -0
  229. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/connection.py +0 -0
  230. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/create.py +0 -0
  231. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/protocol.py +0 -0
  232. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/queue.py +0 -0
  233. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/base.py +0 -0
  234. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/endpoint.py +0 -0
  235. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/enums.py +0 -0
  236. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/io.py +0 -0
  237. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/util.py +0 -0
  238. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/websocket/__init__.py +0 -0
  239. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/net/websocket/connection.py +0 -0
  240. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/noise/__init__.py +0 -0
  241. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/__init__.py +0 -0
  242. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/base.py +0 -0
  243. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/byte_order.py +0 -0
  244. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/evaluation.py +0 -0
  245. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/field/__init__.py +0 -0
  246. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/field/fields.py +0 -0
  247. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/field/manager/__init__.py +0 -0
  248. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/field/manager/base.py +0 -0
  249. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/scaling.py +0 -0
  250. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/serializable/fixed.py +0 -0
  251. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/serializable/framer.py +0 -0
  252. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/serializable/prefixed.py +0 -0
  253. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/string.py +0 -0
  254. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/types/__init__.py +0 -0
  255. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/types/base.py +0 -0
  256. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/types/bool.py +0 -0
  257. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/types/float.py +0 -0
  258. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/primitives/types/int.py +0 -0
  259. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/py.typed +0 -0
  260. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/registry/__init__.py +0 -0
  261. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/registry/bool.py +0 -0
  262. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/registry/item.py +0 -0
  263. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/registry/name.py +0 -0
  264. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/requirements.txt +0 -0
  265. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/sample/__init__.py +0 -0
  266. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/sample/peer.py +0 -0
  267. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/sample/program.py +0 -0
  268. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/schemas.py +0 -0
  269. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/struct/__init__.py +0 -0
  270. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/subprocess/__init__.py +0 -0
  271. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/subprocess/interface.py +0 -0
  272. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/subprocess/peer.py +0 -0
  273. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/subprocess/program.py +0 -0
  274. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/subprocess/protocol.py +0 -0
  275. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/task/__init__.py +0 -0
  276. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/task/asynchronous.py +0 -0
  277. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/task/basic/__init__.py +0 -0
  278. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/task/basic/manager.py +0 -0
  279. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/task/basic/periodic.py +0 -0
  280. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/task/sample.py +0 -0
  281. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/task/trig/__init__.py +0 -0
  282. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/telemetry/__init__.py +0 -0
  283. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/telemetry/sample.py +0 -0
  284. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/tui/__init__.py +0 -0
  285. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/tui/channels/__init__.py +0 -0
  286. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/tui/cursor.py +0 -0
  287. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/tui/mixin.py +0 -0
  288. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/tui/mock.py +0 -0
  289. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/tui/task.py +0 -0
  290. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/ui/__init__.py +0 -0
  291. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/ui/controls.py +0 -0
  292. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy/util.py +0 -0
  293. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy.egg-info/SOURCES.txt +0 -0
  294. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy.egg-info/dependency_links.txt +0 -0
  295. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy.egg-info/entry_points.txt +0 -0
  296. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy.egg-info/requires.txt +3 -3
  297. {runtimepy-5.10.2 → runtimepy-5.11.0}/runtimepy.egg-info/top_level.txt +0 -0
  298. {runtimepy-5.10.2 → runtimepy-5.11.0}/setup.cfg +0 -0
  299. {runtimepy-5.10.2 → runtimepy-5.11.0}/setup.py +0 -0
  300. {runtimepy-5.10.2 → runtimepy-5.11.0}/tests/test_entry.py +0 -0
  301. {runtimepy-5.10.2 → runtimepy-5.11.0}/tests/test_mapping.py +0 -0
  302. {runtimepy-5.10.2 → runtimepy-5.11.0}/tests/test_resources.py +0 -0
  303. {runtimepy-5.10.2 → runtimepy-5.11.0}/tests/test_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runtimepy
3
- Version: 5.10.2
3
+ Version: 5.11.0
4
4
  Summary: A framework for implementing Python services.
5
5
  Home-page: https://github.com/vkottler/runtimepy
6
6
  Author: Vaughn Kottler
@@ -17,11 +17,11 @@ Classifier: License :: OSI Approved :: MIT License
17
17
  Requires-Python: >=3.12
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
- Requires-Dist: psutil
21
- Requires-Dist: aiofiles
22
- Requires-Dist: vcorelib>=3.5.1
23
20
  Requires-Dist: websockets
21
+ Requires-Dist: aiofiles
24
22
  Requires-Dist: svgen>=0.7.4
23
+ Requires-Dist: vcorelib>=3.5.1
24
+ Requires-Dist: psutil
25
25
  Provides-Extra: test
26
26
  Requires-Dist: pylint; extra == "test"
27
27
  Requires-Dist: flake8; extra == "test"
@@ -50,11 +50,11 @@ Dynamic: requires-python
50
50
  =====================================
51
51
  generator=datazen
52
52
  version=3.1.4
53
- hash=887650b5b88ff596b3ab067e01de6fbd
53
+ hash=12eb2a9d91dea3ae83e38a864f6cab4b
54
54
  =====================================
55
55
  -->
56
56
 
57
- # runtimepy ([5.10.2](https://pypi.org/project/runtimepy/))
57
+ # runtimepy ([5.11.0](https://pypi.org/project/runtimepy/))
58
58
 
59
59
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
60
60
  ![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
@@ -2,11 +2,11 @@
2
2
  =====================================
3
3
  generator=datazen
4
4
  version=3.1.4
5
- hash=887650b5b88ff596b3ab067e01de6fbd
5
+ hash=12eb2a9d91dea3ae83e38a864f6cab4b
6
6
  =====================================
7
7
  -->
8
8
 
9
- # runtimepy ([5.10.2](https://pypi.org/project/runtimepy/))
9
+ # runtimepy ([5.11.0](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)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"
4
4
 
5
5
  [project]
6
6
  name = "runtimepy"
7
- version = "5.10.2"
7
+ version = "5.11.0"
8
8
  description = "A framework for implementing Python services."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -1,7 +1,7 @@
1
1
  # =====================================
2
2
  # generator=datazen
3
3
  # version=3.1.4
4
- # hash=9114f245a523f60ffbbfdd040548fc7c
4
+ # hash=c4e165f8c6309dd6819689f0262cf92d
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.10.2"
13
+ VERSION = "5.11.0"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -95,10 +95,10 @@ class ArrayChannelEnvironment(_BaseChannelEnvironment):
95
95
 
96
96
  # Begin handling a new bit-fields primitive.
97
97
  if curr_fields is None:
98
- fields = self.fields.get_fields(name)
99
- assert fields is not None, f"Unknown bit-field '{name}'!"
100
- result.array.add(fields.raw)
101
- available_field_names = set(fields.names)
98
+ curr_fields = self.fields.get_fields(name)
99
+ assert curr_fields is not None, f"Unknown bit-field '{name}'!"
100
+ result.array.add(curr_fields.raw)
101
+ available_field_names = set(curr_fields.names)
102
102
 
103
103
  # Keep track of field names processed in the current bit-fields
104
104
  # primitive.
@@ -99,7 +99,7 @@ class TelemetryChannelEnvironment(_BaseChannelEnvironment):
99
99
  cast(int, channels.event_header["timestamp"]),
100
100
  kind.decode(
101
101
  data,
102
- byte_order=channels.event_header.array.byte_order,
102
+ byte_order=channels.event_header.byte_order,
103
103
  ),
104
104
  )
105
105
 
@@ -120,7 +120,7 @@ class TelemetryChannelEnvironment(_BaseChannelEnvironment):
120
120
  cast(int, self.channels.event_header["timestamp"]),
121
121
  kind.decode(
122
122
  data,
123
- byte_order=self.channels.event_header.array.byte_order,
123
+ byte_order=self.channels.event_header.byte_order,
124
124
  ),
125
125
  )
126
126
 
@@ -146,7 +146,7 @@ class TelemetryChannelEnvironment(_BaseChannelEnvironment):
146
146
  read_size = channels.event_header.size
147
147
  data = channels.event_fifo.pop(read_size)
148
148
  if data is not None:
149
- channels.event_header.array.update(data)
149
+ channels.event_header.update(data)
150
150
 
151
151
  # Update local variables.
152
152
  ident = cast(int, channels.event_header["identifier"])
@@ -90,7 +90,7 @@ class PrimitiveEvent:
90
90
  self.header["timestamp"] = curr_ns
91
91
 
92
92
  # Write header then value.
93
- array = self.header.array
93
+ array = self.header
94
94
  written += array.to_stream(stream)
95
95
  written += raw.to_stream(stream, byte_order=array.byte_order)
96
96
  if flush:
@@ -4,7 +4,6 @@ A module implementing an interface to build communication protocols.
4
4
 
5
5
  # built-in
6
6
  from abc import ABC, abstractmethod
7
- from copy import copy
8
7
  from typing import Optional
9
8
 
10
9
  # internal
@@ -40,10 +39,12 @@ class ProtocolFactory(ABC):
40
39
 
41
40
  # We only need to run the routine that populates the protocol once.
42
41
  if not cls.initialized:
42
+ if not cls.protocol.alias:
43
+ cls.protocol.alias = cls.__name__
43
44
  cls.initialize(cls.protocol)
44
45
  cls.initialized = True
45
46
 
46
- return copy(cls.protocol)
47
+ return cls.protocol.copy()
47
48
 
48
49
  @classmethod
49
50
  def singleton(cls) -> Protocol:
@@ -3,8 +3,9 @@ A module implementing an interface to build communication protocols.
3
3
  """
4
4
 
5
5
  # built-in
6
- from contextlib import contextmanager
6
+ from contextlib import contextmanager, suppress
7
7
  from copy import copy as _copy
8
+ from io import StringIO
8
9
  from typing import Iterator as _Iterator
9
10
  from typing import NamedTuple
10
11
  from typing import Optional as _Optional
@@ -57,9 +58,10 @@ class FieldSpec(NamedTuple):
57
58
 
58
59
 
59
60
  T = _TypeVar("T", bound="ProtocolBase")
61
+ ProtocolBuild = list[_Union[int, FieldSpec, tuple[str, int]]]
60
62
 
61
63
 
62
- class ProtocolBase:
64
+ class ProtocolBase(PrimitiveArray):
63
65
  """A class for defining runtime communication protocols."""
64
66
 
65
67
  def __init__(
@@ -67,14 +69,16 @@ class ProtocolBase:
67
69
  enum_registry: _EnumRegistry,
68
70
  names: _NameRegistry = None,
69
71
  fields: BitFieldsManager = None,
70
- build: list[_Union[int, FieldSpec, str]] = None,
72
+ build: ProtocolBuild = None,
71
73
  identifier: int = 1,
72
74
  byte_order: _Union[_ByteOrder, _RegistryKey] = _DEFAULT_BYTE_ORDER,
73
75
  serializables: SerializableMap = None,
76
+ alias: str = None,
74
77
  ) -> None:
75
78
  """Initialize this protocol."""
76
79
 
77
80
  self.id = identifier
81
+ self.alias = alias
78
82
 
79
83
  # Register the byte-order enumeration if it's not present.
80
84
  self._enum_registry = enum_registry
@@ -86,7 +90,8 @@ class ProtocolBase:
86
90
  byte_order = _ByteOrder(
87
91
  self._enum_registry["ByteOrder"].get_int(byte_order)
88
92
  )
89
- self.array = PrimitiveArray(byte_order=byte_order)
93
+
94
+ super().__init__(byte_order=byte_order)
90
95
 
91
96
  if names is None:
92
97
  names = _NameRegistry()
@@ -96,11 +101,11 @@ class ProtocolBase:
96
101
  fields = BitFieldsManager(self.names, self._enum_registry)
97
102
  self._fields = fields
98
103
 
99
- self._regular_fields: dict[str, _AnyPrimitive] = {}
104
+ self._regular_fields: dict[str, list[_AnyPrimitive]] = {}
100
105
  self._enum_fields: dict[str, _RuntimeEnum] = {}
101
106
 
102
107
  # Keep track of the order that the protocol was created.
103
- self._build: list[_Union[int, FieldSpec, str]] = []
108
+ self._build: ProtocolBuild = []
104
109
 
105
110
  # Keep track of named serializables.
106
111
  self.serializables: SerializableMap = {}
@@ -110,24 +115,28 @@ class ProtocolBase:
110
115
  build = []
111
116
  for item in build:
112
117
  if isinstance(item, int):
113
- self._add_bit_fields(self._fields.fields[item], track=False)
114
- elif isinstance(item, str):
115
- assert serializables, (item, serializables)
116
- self.add_field(item, serializable=serializables[item])
117
- del serializables[item]
118
- else:
118
+ self._add_bit_fields(self._fields.fields[item])
119
+ elif isinstance(item, FieldSpec):
119
120
  self.add_field(
120
121
  item.name,
121
122
  item.kind,
122
123
  enum=item.enum,
123
- track=False,
124
124
  array_length=item.array_length,
125
125
  )
126
+ else:
127
+ assert serializables, (item, serializables)
128
+ name = item[0]
129
+ self.add_serializable(
130
+ name,
131
+ serializables[name][0],
132
+ array_length=None if item[1] == 1 else item[1],
133
+ )
134
+ del serializables[name]
126
135
 
127
136
  # Ensure all serializables were handled via build.
128
137
  assert not serializables, serializables
129
138
 
130
- def __copy__(self: T) -> T:
139
+ def _copy_impl(self: T) -> T:
131
140
  """Create another protocol instance from this one."""
132
141
 
133
142
  return self.__class__(
@@ -135,11 +144,12 @@ class ProtocolBase:
135
144
  names=self.names,
136
145
  fields=_copy(self._fields),
137
146
  build=self._build,
138
- byte_order=self.array.byte_order,
147
+ byte_order=self.byte_order,
139
148
  serializables={
140
- key: val.copy_without_chain()
149
+ key: [val[0].copy_without_chain()]
141
150
  for key, val in self.serializables.items()
142
151
  },
152
+ alias=self.alias,
143
153
  )
144
154
 
145
155
  def register_name(self, name: str) -> int:
@@ -151,13 +161,14 @@ class ProtocolBase:
151
161
 
152
162
  def add_serializable(
153
163
  self, name: str, serializable: Serializable, array_length: int = None
154
- ) -> int:
164
+ ) -> None:
155
165
  """Add a serializable instance."""
156
166
 
157
167
  self.register_name(name)
158
- self.serializables[name] = serializable
159
- self._build.append(name)
160
- return self.array.add_to_end(serializable, array_length=array_length)
168
+
169
+ instances = self.add_to_end(serializable, array_length=array_length)
170
+ self._build.append((name, len(instances)))
171
+ self.serializables[name] = instances
161
172
 
162
173
  def add_field(
163
174
  self,
@@ -165,17 +176,17 @@ class ProtocolBase:
165
176
  kind: _Primitivelike = None,
166
177
  enum: _RegistryKey = None,
167
178
  serializable: Serializable = None,
168
- track: bool = True,
169
179
  array_length: int = None,
170
- ) -> int:
180
+ ) -> None:
171
181
  """Add a new field to the protocol."""
172
182
 
173
183
  # Add the serializable to the end of this protocol.
174
184
  if serializable is not None:
175
185
  assert kind is None and enum is None
176
- return self.add_serializable(
186
+ self.add_serializable(
177
187
  name, serializable, array_length=array_length
178
188
  )
189
+ return
179
190
 
180
191
  self.register_name(name)
181
192
 
@@ -189,25 +200,20 @@ class ProtocolBase:
189
200
  kind = runtime_enum.primitive
190
201
 
191
202
  assert kind is not None
192
- new = _create(kind)
193
-
194
- result = self.array.add(new, array_length=array_length)
195
- self._regular_fields[name] = new
196
203
 
197
- if track:
198
- self._build.append(
199
- FieldSpec(name, kind, enum, array_length=array_length)
200
- )
204
+ self._regular_fields[name] = self.add(
205
+ _create(kind), array_length=array_length
206
+ )
201
207
 
202
- return result
208
+ self._build.append(
209
+ FieldSpec(name, kind, enum, array_length=array_length)
210
+ )
203
211
 
204
- def _add_bit_fields(self, fields: _BitFields, track: bool = True) -> None:
212
+ def _add_bit_fields(self, fields: _BitFields) -> None:
205
213
  """Add a bit-fields instance."""
206
214
 
207
- idx = self._fields.add(fields)
208
- self.array.add(fields.raw)
209
- if track:
210
- self._build.append(idx)
215
+ self._build.append(self._fields.add(fields))
216
+ self.add(fields.raw)
211
217
 
212
218
  @contextmanager
213
219
  def add_bit_fields(
@@ -219,55 +225,92 @@ class ProtocolBase:
219
225
  yield new
220
226
  self._add_bit_fields(new)
221
227
 
222
- def value(self, name: str, resolve_enum: bool = True) -> ProtocolPrimitive:
228
+ def value(
229
+ self, name: str, resolve_enum: bool = True, index: int = 0
230
+ ) -> ProtocolPrimitive:
223
231
  """Get the value of a field belonging to the protocol."""
224
232
 
225
233
  val: ProtocolPrimitive = 0
226
234
 
227
235
  if name in self._regular_fields:
228
- val = self._regular_fields[name].value
236
+ val = self._regular_fields[name][index].value
229
237
 
230
238
  # Resolve the enum value.
231
239
  if resolve_enum and name in self._enum_fields:
232
- val = self._enum_fields[name].get_str(val) # type: ignore
240
+ with suppress(KeyError):
241
+ val = self._enum_fields[name].get_str(val) # type: ignore
233
242
 
234
243
  return val
235
244
 
236
245
  return self._fields.get(name, resolve_enum=resolve_enum)
237
246
 
238
- @property
239
- def size(self) -> int:
240
- """Get this protocol's size in bytes."""
241
- return self.array.length()
242
-
243
247
  def trace_size(self, logger: LoggerType) -> None:
244
248
  """Log a size trace."""
245
- logger.info("%s: %s", self, self.array.length_trace())
249
+ logger.info("%s: %s", self, self.length_trace(alias=self.alias))
246
250
 
247
251
  def __str__(self) -> str:
248
252
  """Get this instance as a string."""
249
253
 
250
- return f"({self.size}) " + " ".join(
251
- f"{name}={self[name]}" for name in self.names.registered_order
252
- )
254
+ with StringIO() as stream:
255
+ stream.write(
256
+ "{"
257
+ + f"{self.resolve_alias(alias=self.alias)}({self.length()}): "
258
+ )
259
+
260
+ parts = []
261
+ for name in self.names.registered_order:
262
+ part = name
263
+ count = 1
264
+
265
+ if name in self.serializables:
266
+ count = len(self.serializables[name])
267
+ part += f"<{self.serializables[name][0].resolve_alias()}>"
268
+ elif name in self._regular_fields:
269
+ count = len(self._regular_fields[name])
270
+
271
+ part += f"<{self._regular_fields[name][0].kind}>"
272
+
273
+ if count > 1:
274
+ part += f"[{count}] = ["
275
+ if name in self._regular_fields:
276
+ part += ", ".join(
277
+ str(x.value) for x in self._regular_fields[name]
278
+ )
279
+ else:
280
+ part += ", ".join("..." for _ in range(count))
281
+ part += "]"
282
+ else:
283
+ part += f" = {self[name]}"
284
+
285
+ parts.append(part)
253
286
 
254
- def __getitem__(self, name: str) -> ProtocolPrimitive:
287
+ stream.write(", ".join(parts))
288
+
289
+ stream.write("}")
290
+
291
+ return stream.getvalue()
292
+
293
+ def __getitem__(self, name: str) -> ProtocolPrimitive: # type: ignore
255
294
  """Get the value of a protocol field."""
256
295
 
257
296
  if name in self.serializables:
258
- return str(self.serializables[name])
297
+ return str(self.serializables[name][0])
259
298
 
260
299
  return self.value(name)
261
300
 
262
- def __setitem__(self, name: str, val: ProtocolPrimitive) -> None:
301
+ def set(self, name: str, val: ProtocolPrimitive, index: int = 0) -> None:
263
302
  """Set a value of a field belonging to the protocol."""
264
303
 
265
304
  if name in self._regular_fields:
266
305
  # Resolve an enum value.
267
306
  if isinstance(val, str):
268
307
  val = self._enum_fields[name].get_int(val)
269
- self._regular_fields[name].value = val
308
+ self._regular_fields[name][index].value = val
270
309
  elif name in self.serializables and isinstance(val, str):
271
- self.serializables[name].update_str(val)
310
+ self.serializables[name][index].update_str(val)
272
311
  else:
273
312
  self._fields.set(name, val) # type: ignore
313
+
314
+ def __setitem__(self, name: str, val: ProtocolPrimitive) -> None:
315
+ """Set a value of a field belonging to the protocol."""
316
+ self.set(name, val)
@@ -14,7 +14,11 @@ from vcorelib.io.types import JsonObject as _JsonObject
14
14
  from vcorelib.io.types import JsonValue as _JsonValue
15
15
 
16
16
  # internal
17
- from runtimepy.codec.protocol.base import FieldSpec, ProtocolBase
17
+ from runtimepy.codec.protocol.base import (
18
+ FieldSpec,
19
+ ProtocolBase,
20
+ ProtocolBuild,
21
+ )
18
22
  from runtimepy.primitives.field.manager import (
19
23
  ENUMS_KEY,
20
24
  NAMES_KEY,
@@ -46,9 +50,11 @@ class JsonProtocol(ProtocolBase):
46
50
  """Export this protocol's data to JSON."""
47
51
 
48
52
  data = self._fields.export_json(resolve_enum=resolve_enum)
53
+
49
54
  data[META_KEY] = {
50
55
  "id": self.id,
51
- "byte_order": self.array.byte_order.name.lower(),
56
+ "byte_order": self.byte_order.name.lower(),
57
+ "alias": self.alias,
52
58
  }
53
59
 
54
60
  # Export regular-field names.
@@ -72,12 +78,12 @@ class JsonProtocol(ProtocolBase):
72
78
  )
73
79
 
74
80
  # Export the build specification.
75
- build: list[_Union[int, _JsonObject, str]] = []
81
+ build: list[_Union[int, _JsonObject, str, tuple[str, int]]] = []
76
82
  for item in self._build:
77
- if isinstance(item, (int, str)):
78
- build.append(item)
79
- else:
83
+ if isinstance(item, FieldSpec):
80
84
  build.append(item.asdict())
85
+ else:
86
+ build.append(item)
81
87
  data[BUILD_KEY] = _cast(_JsonObject, build)
82
88
 
83
89
  # Export regular-field values.
@@ -101,18 +107,16 @@ class JsonProtocol(ProtocolBase):
101
107
  fields = BitFieldsManager.import_json(data)
102
108
 
103
109
  # Create the build specification.
104
- build: list[_Union[int, FieldSpec, str]] = []
110
+ build: ProtocolBuild = []
105
111
  for item in data[BUILD_KEY]:
106
- if isinstance(item, int):
107
- build.append(item)
108
- else:
112
+ if isinstance(item, dict):
109
113
  build.append(
110
114
  FieldSpec(
111
- item["name"], # type: ignore
112
- item["kind"], # type: ignore
113
- enum=item.get("enum"), # type: ignore
115
+ item["name"], item["kind"], enum=item.get("enum")
114
116
  )
115
117
  )
118
+ else:
119
+ build.append(item) # type: ignore
116
120
 
117
121
  result = cls(
118
122
  fields.enums,
@@ -121,6 +125,7 @@ class JsonProtocol(ProtocolBase):
121
125
  build=build,
122
126
  identifier=_cast(int, data[META_KEY]["id"]),
123
127
  byte_order=_cast(str, data[META_KEY]["byte_order"]),
128
+ alias=data[META_KEY]["alias"], # type: ignore
124
129
  )
125
130
 
126
131
  # Set values.
@@ -146,7 +146,7 @@ class TypeSystem(LoggerMixin):
146
146
  if field_type_name in self.custom:
147
147
  custom.add_serializable(
148
148
  field_name,
149
- self.custom[field_type_name].array.copy(),
149
+ self.custom[field_type_name].copy(),
150
150
  array_length=array_length,
151
151
  )
152
152
  else:
@@ -227,8 +227,7 @@ class TypeSystem(LoggerMixin):
227
227
  if found in self.primitives:
228
228
  return self.primitives[found].size
229
229
 
230
- result = self.custom[found].size
231
230
  if trace:
232
231
  self.custom[found].trace_size(self.logger)
233
232
 
234
- return result
233
+ return self.custom[found].length()
@@ -50,7 +50,6 @@ class TftpConnection(BaseTftpConnection):
50
50
 
51
51
  def ack_sender() -> None:
52
52
  """Send acks."""
53
- nonlocal idx
54
53
  endpoint.ack_sender(idx - 1, endpoint.addr)
55
54
 
56
55
  def send_rrq() -> None:
@@ -180,44 +180,50 @@ class PrimitiveArray(Serializable):
180
180
 
181
181
  def add_primitive(
182
182
  self, kind: _Primitivelike, array_length: int = None
183
- ) -> int:
183
+ ) -> list[_AnyPrimitive]:
184
184
  """Add to the array by specifying the type of element to add."""
185
+
185
186
  return self.add(_create(kind), array_length=array_length)
186
187
 
187
- def add(self, primitive: _AnyPrimitive, array_length: int = None) -> int:
188
+ def add(
189
+ self, primitive: _AnyPrimitive, array_length: int = None
190
+ ) -> list[_AnyPrimitive]:
188
191
  """Add another primitive to manage."""
189
192
 
193
+ result = []
194
+
190
195
  end = self.end
191
196
  if isinstance(end, PrimitiveArray):
192
197
  if end is self:
193
198
  self._primitives.append(primitive)
194
199
  self._format += primitive.kind.format
195
200
  self.size += primitive.size
201
+ result.append(primitive)
196
202
 
197
203
  # Handle array length.
198
204
  if array_length is not None:
199
205
  for _ in range(array_length - 1):
206
+ inst = primitive.copy()
200
207
  self._primitives.append(
201
- primitive.copy(), # type: ignore
208
+ inst, # type: ignore
202
209
  )
203
- self._format += primitive.kind.format
204
- self.size += primitive.size
210
+ self._format += inst.kind.format
211
+ self.size += inst.size
212
+ result.append(inst) # type: ignore
205
213
 
206
214
  # Add tracking information for the current tail.
207
215
  curr_idx = len(self._primitives)
208
216
  self._bytes_to_index[self.size] = curr_idx
209
217
  self._index_to_bytes[curr_idx] = self.size
210
- result = self.size
211
218
  else:
212
- result = end.add(primitive, array_length=array_length)
219
+ result.extend(end.add(primitive, array_length=array_length))
213
220
 
214
221
  # Add a new primitive array to the end of this chain for this
215
222
  # primitive.
216
223
  else:
217
224
  new_array = PrimitiveArray(byte_order=self.byte_order)
218
225
  end.assign(new_array)
219
-
220
- result = new_array.add(primitive, array_length=array_length)
226
+ result.extend(new_array.add(primitive, array_length=array_length))
221
227
 
222
228
  return result
223
229
 
@@ -245,3 +251,16 @@ class PrimitiveArray(Serializable):
245
251
  ) -> None:
246
252
  """Update a fragment by index."""
247
253
  self._fragments[index].update(data, timestamp_ns=timestamp_ns)
254
+
255
+ def randomize(self, timestamp_ns: int = None, chain: bool = True) -> None:
256
+ """Randomize array contents."""
257
+
258
+ for prim in self._primitives:
259
+ prim.randomize(timestamp_ns=timestamp_ns)
260
+
261
+ if (
262
+ chain
263
+ and self.chain is not None
264
+ and isinstance(self.chain, PrimitiveArray)
265
+ ):
266
+ self.chain.randomize(timestamp_ns=timestamp_ns, chain=chain)
@@ -2,6 +2,9 @@
2
2
  A module implementing a boolean-primitive interface.
3
3
  """
4
4
 
5
+ # built-in
6
+ from random import getrandbits
7
+
5
8
  # internal
6
9
  from runtimepy.primitives.base import Primitive as _Primitive
7
10
  from runtimepy.primitives.evaluation import EvalResult, evaluate
@@ -18,17 +21,21 @@ class BooleanPrimitive(_Primitive[bool]):
18
21
  """Initialize this boolean primitive."""
19
22
  super().__init__(value=value, **kwargs)
20
23
 
21
- def toggle(self) -> None:
24
+ def randomize(self, timestamp_ns: int = None) -> None:
25
+ """Set this primitive to a random integer."""
26
+ self.set_value(bool(getrandbits(1)), timestamp_ns=timestamp_ns)
27
+
28
+ def toggle(self, timestamp_ns: int = None) -> None:
22
29
  """Toggle the underlying value."""
23
- self.value = not self.raw.value
30
+ self.set_value(not self.raw.value, timestamp_ns=timestamp_ns)
24
31
 
25
- def set(self) -> None:
32
+ def set(self, timestamp_ns: int = None) -> None:
26
33
  """Coerce the underlying value to true."""
27
- self.value = True
34
+ self.set_value(True, timestamp_ns=timestamp_ns)
28
35
 
29
- def clear(self) -> None:
36
+ def clear(self, timestamp_ns: int = None) -> None:
30
37
  """Coerce the underlying value to false."""
31
- self.value = False
38
+ self.set_value(False, timestamp_ns=timestamp_ns)
32
39
 
33
40
  async def wait_for_state(self, state: bool, timeout: float) -> EvalResult:
34
41
  """Wait for this primitive to reach a specified state."""