runtimepy 5.10.1__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 (304) hide show
  1. {runtimepy-5.10.1/runtimepy.egg-info → runtimepy-5.11.0}/PKG-INFO +6 -5
  2. {runtimepy-5.10.1 → runtimepy-5.11.0}/README.md +2 -2
  3. {runtimepy-5.10.1 → runtimepy-5.11.0}/pyproject.toml +1 -1
  4. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/__init__.py +2 -2
  5. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/array.py +4 -4
  6. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/telemetry.py +3 -3
  7. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/event/__init__.py +1 -1
  8. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/codec/protocol/__init__.py +3 -2
  9. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/codec/protocol/base.py +97 -54
  10. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/codec/protocol/json.py +18 -13
  11. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/codec/system/__init__.py +2 -3
  12. runtimepy-5.11.0/runtimepy/data/favicon.ico +0 -0
  13. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/svg/chip-circle-bootstrap.svg +1 -1
  14. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/__init__.py +24 -3
  15. runtimepy-5.11.0/runtimepy/net/server/markdown.py +53 -0
  16. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/__init__.py +0 -1
  17. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/array/__init__.py +28 -9
  18. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/bool.py +13 -6
  19. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/float.py +5 -0
  20. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/int.py +7 -0
  21. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/serializable/__init__.py +1 -1
  22. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/serializable/base.py +47 -19
  23. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/types/bounds.py +5 -0
  24. {runtimepy-5.10.1 → runtimepy-5.11.0/runtimepy.egg-info}/PKG-INFO +6 -5
  25. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy.egg-info/SOURCES.txt +1 -0
  26. runtimepy-5.10.1/runtimepy/data/favicon.ico +0 -0
  27. {runtimepy-5.10.1 → runtimepy-5.11.0}/LICENSE +0 -0
  28. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/__main__.py +0 -0
  29. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/app.py +0 -0
  30. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/__init__.py +0 -0
  31. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/__init__.py +0 -0
  32. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/base.py +0 -0
  33. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/command/__init__.py +0 -0
  34. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/command/parser.py +0 -0
  35. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/command/processor.py +0 -0
  36. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/command/result.py +0 -0
  37. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/create.py +0 -0
  38. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/file.py +0 -0
  39. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/environment/sample.py +0 -0
  40. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/event/header.py +0 -0
  41. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/channel/registry.py +0 -0
  42. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/codec/__init__.py +0 -0
  43. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/__init__.py +0 -0
  44. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/all.py +0 -0
  45. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/arbiter.py +0 -0
  46. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/common.py +0 -0
  47. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/mtu.py +0 -0
  48. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/server.py +0 -0
  49. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/task.py +0 -0
  50. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/tftp.py +0 -0
  51. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/commands/tui.py +0 -0
  52. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/control/__init__.py +0 -0
  53. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/control/env/__init__.py +0 -0
  54. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/control/source.py +0 -0
  55. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/control/step.py +0 -0
  56. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/404.html +0 -0
  57. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/browser.yaml +0 -0
  58. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/css/bootstrap_extra.css +0 -0
  59. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/css/font.css +0 -0
  60. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/css/main.css +0 -0
  61. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/dummy_load.yaml +0 -0
  62. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/factories.yaml +0 -0
  63. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/DataConnection.js +0 -0
  64. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/JsonConnection.js +0 -0
  65. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/audio.js +0 -0
  66. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/App.js +0 -0
  67. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/ChannelTable.js +0 -0
  68. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/DataConnection.js +0 -0
  69. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/JsonConnection.js +0 -0
  70. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/OverlayManager.js +0 -0
  71. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/Plot.js +0 -0
  72. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/PlotDrawer.js +0 -0
  73. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/PlotManager.js +0 -0
  74. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/PlotModalManager.js +0 -0
  75. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/PointBuffer.js +0 -0
  76. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/PointManager.js +0 -0
  77. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/TabFilter.js +0 -0
  78. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/TabInterface.js +0 -0
  79. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/UnitSystem.js +0 -0
  80. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/WindowHashManager.js +0 -0
  81. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/classes/WorkerInterface.js +0 -0
  82. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/events.js +0 -0
  83. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/init.js +0 -0
  84. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/main.js +0 -0
  85. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/markdown_page.js +0 -0
  86. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/tab/env.js +0 -0
  87. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/tab/sound.js +0 -0
  88. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/third-party/webgl-debug.js +0 -0
  89. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/unused/pyodide.js +0 -0
  90. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/util.js +0 -0
  91. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/js/worker.js +0 -0
  92. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/md/Connection.md +0 -0
  93. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/md/PeriodicTask.md +0 -0
  94. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/md/RuntimeStruct.md +0 -0
  95. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/md/RuntimepyPeer.md +0 -0
  96. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/md/SinusoidTask.md +0 -0
  97. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/sample_telemetry.yaml +0 -0
  98. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/BitFields.yaml +0 -0
  99. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/Channel.yaml +0 -0
  100. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/ChannelCommand.yaml +0 -0
  101. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/ChannelRegistry.yaml +0 -0
  102. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/ClientConnectionConfig.yaml +0 -0
  103. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/ConnectionArbiterConfig.yaml +0 -0
  104. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/EnumRegistry.yaml +0 -0
  105. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/FindFile.yaml +0 -0
  106. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/PeerProcessConfig.yaml +0 -0
  107. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/RuntimeEnum.yaml +0 -0
  108. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/ServerConnectionConfig.yaml +0 -0
  109. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/StructConfig.yaml +0 -0
  110. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/TaskConfig.yaml +0 -0
  111. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/channel_controls.yaml +0 -0
  112. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/has_config.yaml +0 -0
  113. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/has_factory.yaml +0 -0
  114. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/has_markdown.yaml +0 -0
  115. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/has_name.yaml +0 -0
  116. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/schemas/has_request_flag.yaml +0 -0
  117. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/server.yaml +0 -0
  118. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/server_base.yaml +0 -0
  119. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/server_dev.yaml +0 -0
  120. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-Bold.woff2 +0 -0
  121. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-BoldItalic.woff2 +0 -0
  122. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-Italic.woff2 +0 -0
  123. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaCode-Regular.woff2 +0 -0
  124. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-Bold.woff2 +0 -0
  125. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-BoldItalic.woff2 +0 -0
  126. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-Italic.woff2 +0 -0
  127. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/CascadiaMono-Regular.woff2 +0 -0
  128. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/static/woff2/README.md +0 -0
  129. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/data/tftp_server.yaml +0 -0
  130. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/dev_requirements.txt +0 -0
  131. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/entry.py +0 -0
  132. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/enum/__init__.py +0 -0
  133. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/enum/registry.py +0 -0
  134. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/enum/types.py +0 -0
  135. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mapping.py +0 -0
  136. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/message/__init__.py +0 -0
  137. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/message/handlers.py +0 -0
  138. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/message/interface.py +0 -0
  139. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/message/types.py +0 -0
  140. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/metrics/__init__.py +0 -0
  141. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/metrics/channel.py +0 -0
  142. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/metrics/connection.py +0 -0
  143. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/metrics/task.py +0 -0
  144. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/__init__.py +0 -0
  145. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/async_command.py +0 -0
  146. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/enum.py +0 -0
  147. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/environment.py +0 -0
  148. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/finalize.py +0 -0
  149. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/logging.py +0 -0
  150. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/psutil.py +0 -0
  151. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/regex.py +0 -0
  152. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/mixins/trig.py +0 -0
  153. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/__init__.py +0 -0
  154. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/apps/__init__.py +0 -0
  155. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/__init__.py +0 -0
  156. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/base.py +0 -0
  157. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/config/__init__.py +0 -0
  158. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/config/codec.py +0 -0
  159. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/config/util.py +0 -0
  160. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/factory/__init__.py +0 -0
  161. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/factory/connection.py +0 -0
  162. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/factory/task.py +0 -0
  163. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/housekeeping/__init__.py +0 -0
  164. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/imports/__init__.py +0 -0
  165. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/imports/util.py +0 -0
  166. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/info.py +0 -0
  167. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/result.py +0 -0
  168. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/struct/__init__.py +0 -0
  169. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/task.py +0 -0
  170. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/tcp/__init__.py +0 -0
  171. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/tcp/json.py +0 -0
  172. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/udp.py +0 -0
  173. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/arbiter/websocket.py +0 -0
  174. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/backoff.py +0 -0
  175. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/connection.py +0 -0
  176. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/factories/__init__.py +0 -0
  177. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/html/__init__.py +0 -0
  178. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/html/arbiter.py +0 -0
  179. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/html/bootstrap/__init__.py +0 -0
  180. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/html/bootstrap/elements.py +0 -0
  181. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/html/bootstrap/tabs.py +0 -0
  182. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/http/__init__.py +0 -0
  183. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/http/common.py +0 -0
  184. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/http/header.py +0 -0
  185. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/http/request_target.py +0 -0
  186. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/http/response.py +0 -0
  187. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/http/state.py +0 -0
  188. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/http/version.py +0 -0
  189. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/manager.py +0 -0
  190. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/mixin.py +0 -0
  191. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/mtu.py +0 -0
  192. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/__init__.py +0 -0
  193. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/base.py +0 -0
  194. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/create.py +0 -0
  195. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/elements.py +0 -0
  196. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/__init__.py +0 -0
  197. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/modal.py +0 -0
  198. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/settings.py +0 -0
  199. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/__init__.py +0 -0
  200. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/base.py +0 -0
  201. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/controls.py +0 -0
  202. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/html.py +0 -0
  203. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/tab/message.py +0 -0
  204. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/env/widgets.py +0 -0
  205. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/files.py +0 -0
  206. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/landing_page.py +0 -0
  207. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/placeholder.py +0 -0
  208. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/pyodide.py +0 -0
  209. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/sound.py +0 -0
  210. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/app/tab.py +0 -0
  211. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/html.py +0 -0
  212. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/json.py +0 -0
  213. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/struct/__init__.py +0 -0
  214. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/websocket/__init__.py +0 -0
  215. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/server/websocket/state.py +0 -0
  216. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/ssl.py +0 -0
  217. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/stream/__init__.py +0 -0
  218. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/stream/base.py +0 -0
  219. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/stream/json/__init__.py +0 -0
  220. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/stream/string.py +0 -0
  221. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/__init__.py +0 -0
  222. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/connection.py +0 -0
  223. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/create.py +0 -0
  224. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/http/__init__.py +0 -0
  225. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/protocol.py +0 -0
  226. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/scpi/__init__.py +0 -0
  227. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/telnet/__init__.py +0 -0
  228. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/telnet/codes.py +0 -0
  229. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/tcp/telnet/np_05b.py +0 -0
  230. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/__init__.py +0 -0
  231. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/connection.py +0 -0
  232. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/create.py +0 -0
  233. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/protocol.py +0 -0
  234. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/queue.py +0 -0
  235. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/base.py +0 -0
  236. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/endpoint.py +0 -0
  237. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/enums.py +0 -0
  238. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/udp/tftp/io.py +0 -0
  239. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/util.py +0 -0
  240. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/websocket/__init__.py +0 -0
  241. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/net/websocket/connection.py +0 -0
  242. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/noise/__init__.py +0 -0
  243. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/__init__.py +0 -0
  244. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/base.py +0 -0
  245. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/byte_order.py +0 -0
  246. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/evaluation.py +0 -0
  247. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/field/__init__.py +0 -0
  248. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/field/fields.py +0 -0
  249. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/field/manager/__init__.py +0 -0
  250. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/field/manager/base.py +0 -0
  251. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/scaling.py +0 -0
  252. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/serializable/fixed.py +0 -0
  253. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/serializable/framer.py +0 -0
  254. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/serializable/prefixed.py +0 -0
  255. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/string.py +0 -0
  256. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/types/__init__.py +0 -0
  257. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/types/base.py +0 -0
  258. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/types/bool.py +0 -0
  259. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/types/float.py +0 -0
  260. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/primitives/types/int.py +0 -0
  261. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/py.typed +0 -0
  262. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/registry/__init__.py +0 -0
  263. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/registry/bool.py +0 -0
  264. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/registry/item.py +0 -0
  265. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/registry/name.py +0 -0
  266. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/requirements.txt +0 -0
  267. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/sample/__init__.py +0 -0
  268. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/sample/peer.py +0 -0
  269. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/sample/program.py +0 -0
  270. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/schemas.py +0 -0
  271. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/struct/__init__.py +0 -0
  272. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/subprocess/__init__.py +0 -0
  273. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/subprocess/interface.py +0 -0
  274. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/subprocess/peer.py +0 -0
  275. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/subprocess/program.py +0 -0
  276. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/subprocess/protocol.py +0 -0
  277. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/task/__init__.py +0 -0
  278. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/task/asynchronous.py +0 -0
  279. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/task/basic/__init__.py +0 -0
  280. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/task/basic/manager.py +0 -0
  281. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/task/basic/periodic.py +0 -0
  282. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/task/sample.py +0 -0
  283. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/task/trig/__init__.py +0 -0
  284. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/telemetry/__init__.py +0 -0
  285. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/telemetry/sample.py +0 -0
  286. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/tui/__init__.py +0 -0
  287. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/tui/channels/__init__.py +0 -0
  288. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/tui/cursor.py +0 -0
  289. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/tui/mixin.py +0 -0
  290. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/tui/mock.py +0 -0
  291. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/tui/task.py +0 -0
  292. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/ui/__init__.py +0 -0
  293. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/ui/controls.py +0 -0
  294. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy/util.py +0 -0
  295. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy.egg-info/dependency_links.txt +0 -0
  296. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy.egg-info/entry_points.txt +0 -0
  297. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy.egg-info/requires.txt +1 -1
  298. {runtimepy-5.10.1 → runtimepy-5.11.0}/runtimepy.egg-info/top_level.txt +0 -0
  299. {runtimepy-5.10.1 → runtimepy-5.11.0}/setup.cfg +0 -0
  300. {runtimepy-5.10.1 → runtimepy-5.11.0}/setup.py +0 -0
  301. {runtimepy-5.10.1 → runtimepy-5.11.0}/tests/test_entry.py +0 -0
  302. {runtimepy-5.10.1 → runtimepy-5.11.0}/tests/test_mapping.py +0 -0
  303. {runtimepy-5.10.1 → runtimepy-5.11.0}/tests/test_resources.py +0 -0
  304. {runtimepy-5.10.1 → runtimepy-5.11.0}/tests/test_util.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: runtimepy
3
- Version: 5.10.1
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
@@ -20,8 +20,8 @@ License-File: LICENSE
20
20
  Requires-Dist: websockets
21
21
  Requires-Dist: aiofiles
22
22
  Requires-Dist: svgen>=0.7.4
23
- Requires-Dist: psutil
24
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"
@@ -42,6 +42,7 @@ Requires-Dist: types-setuptools; extra == "test"
42
42
  Requires-Dist: uvloop; (sys_platform != "win32" and sys_platform != "cygwin") and extra == "test"
43
43
  Dynamic: author
44
44
  Dynamic: home-page
45
+ Dynamic: license-file
45
46
  Dynamic: requires-dist
46
47
  Dynamic: requires-python
47
48
 
@@ -49,11 +50,11 @@ Dynamic: requires-python
49
50
  =====================================
50
51
  generator=datazen
51
52
  version=3.1.4
52
- hash=a8fb82d7f11d94c5c3ad4adea1026d9e
53
+ hash=12eb2a9d91dea3ae83e38a864f6cab4b
53
54
  =====================================
54
55
  -->
55
56
 
56
- # runtimepy ([5.10.1](https://pypi.org/project/runtimepy/))
57
+ # runtimepy ([5.11.0](https://pypi.org/project/runtimepy/))
57
58
 
58
59
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
59
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=a8fb82d7f11d94c5c3ad4adea1026d9e
5
+ hash=12eb2a9d91dea3ae83e38a864f6cab4b
6
6
  =====================================
7
7
  -->
8
8
 
9
- # runtimepy ([5.10.1](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.1"
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=649474f8a3122bccd6febc4bb2156b11
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.1"
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()
@@ -1,5 +1,5 @@
1
1
  <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
2
- <circle r="50.0" cx="50.0" cy="50.0" style="fill: #ADB5BD" />
2
+ <circle r="50.0" cx="50.0" cy="50.0" style="fill: #6C757D" />
3
3
  <rect x="16.666666666666664" y="33.333333333333336" width="16.666666666666668" height="8.333333333333334" rx="4.166666666666667" ry="4.166666666666667" style="fill: #495057" />
4
4
  <rect x="16.666666666666664" y="45.833333333333336" width="16.666666666666668" height="8.333333333333334" rx="4.166666666666667" ry="4.166666666666667" style="fill: #495057" />
5
5
  <rect x="16.666666666666664" y="58.333333333333336" width="16.666666666666668" height="8.333333333333334" rx="4.166666666666667" ry="4.166666666666667" style="fill: #495057" />
@@ -24,6 +24,7 @@ from runtimepy.net.http.request_target import PathMaybeQuery
24
24
  from runtimepy.net.http.response import ResponseHeader
25
25
  from runtimepy.net.server.html import HtmlApp, HtmlApps, get_html, html_handler
26
26
  from runtimepy.net.server.json import encode_json, json_handler
27
+ from runtimepy.net.server.markdown import markdown_for_dir
27
28
  from runtimepy.net.tcp.http import HttpConnection
28
29
  from runtimepy.util import normalize_root, path_has_part, read_binary
29
30
 
@@ -177,10 +178,20 @@ class RuntimepyServerConnection(HttpConnection):
177
178
 
178
179
  result = None
179
180
 
180
- # Try serving the path as a file.
181
+ # Keep track of directories encountered.
182
+ directories: list[Path] = []
183
+
184
+ # Build a list of all candidate files to check.
185
+ candidates: list[Path] = []
181
186
  for search in self.paths:
182
187
  candidate = search.joinpath(path[0][1:])
188
+ if candidate.is_dir():
189
+ directories.append(candidate)
190
+ candidates.append(candidate.joinpath("index.html"))
191
+ else:
192
+ candidates.append(candidate)
183
193
 
194
+ for candidate in candidates:
184
195
  # Handle markdown sources.
185
196
  if candidate.name:
186
197
  md_candidate = candidate.with_suffix(".md")
@@ -189,6 +200,7 @@ class RuntimepyServerConnection(HttpConnection):
189
200
  md_candidate, response, path[1]
190
201
  )
191
202
 
203
+ # Handle files.
192
204
  if candidate.is_file():
193
205
  mime, encoding = mimetypes.guess_type(candidate, strict=False)
194
206
 
@@ -203,9 +215,18 @@ class RuntimepyServerConnection(HttpConnection):
203
215
 
204
216
  # Return the file data.
205
217
  result = await read_binary(candidate)
206
-
207
218
  break
208
219
 
220
+ # Handle a directory as a last resort.
221
+ if not result and directories:
222
+ result = self.render_markdown(
223
+ markdown_for_dir(
224
+ directories[0], {"applications": self.apps.keys()}
225
+ ),
226
+ response,
227
+ path[1],
228
+ )
229
+
209
230
  return result
210
231
 
211
232
  def handle_command(
@@ -278,7 +299,7 @@ class RuntimepyServerConnection(HttpConnection):
278
299
  return self.favicon_data
279
300
 
280
301
  # Try serving a file and handling redirects.
281
- for handler in [self.try_file, self.try_redirect]:
302
+ for handler in [self.try_redirect, self.try_file]:
282
303
  result = await handler(
283
304
  request.target.origin_form, response
284
305
  )