runtimepy 5.7.2__tar.gz → 5.7.4__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 (299) hide show
  1. {runtimepy-5.7.2/runtimepy.egg-info → runtimepy-5.7.4}/PKG-INFO +5 -5
  2. {runtimepy-5.7.2 → runtimepy-5.7.4}/README.md +2 -2
  3. {runtimepy-5.7.2 → runtimepy-5.7.4}/pyproject.toml +1 -1
  4. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/__init__.py +2 -2
  5. runtimepy-5.7.4/runtimepy/data/js/markdown_page.js +24 -0
  6. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/logging.py +26 -3
  7. runtimepy-5.7.2/runtimepy/net/server/app/files.py → runtimepy-5.7.4/runtimepy/net/html/__init__.py +77 -40
  8. {runtimepy-5.7.2/runtimepy/net/server/app → runtimepy-5.7.4/runtimepy/net/html}/bootstrap/elements.py +4 -2
  9. {runtimepy-5.7.2/runtimepy/net/server/app → runtimepy-5.7.4/runtimepy/net/html}/bootstrap/tabs.py +3 -24
  10. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/__init__.py +37 -7
  11. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/base.py +4 -11
  12. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/create.py +1 -1
  13. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/__init__.py +2 -5
  14. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/modal.py +2 -2
  15. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/settings.py +2 -2
  16. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/tab/base.py +1 -1
  17. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/tab/controls.py +1 -1
  18. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/tab/html.py +4 -2
  19. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/widgets.py +1 -1
  20. runtimepy-5.7.4/runtimepy/net/server/app/files.py +41 -0
  21. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/landing_page.py +7 -1
  22. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/placeholder.py +2 -2
  23. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/sound.py +1 -1
  24. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/tab.py +3 -3
  25. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/html.py +7 -5
  26. {runtimepy-5.7.2 → runtimepy-5.7.4/runtimepy.egg-info}/PKG-INFO +5 -5
  27. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy.egg-info/SOURCES.txt +5 -3
  28. {runtimepy-5.7.2 → runtimepy-5.7.4}/LICENSE +0 -0
  29. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/__main__.py +0 -0
  30. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/app.py +0 -0
  31. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/__init__.py +0 -0
  32. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/__init__.py +0 -0
  33. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/array.py +0 -0
  34. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/base.py +0 -0
  35. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/command/__init__.py +0 -0
  36. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/command/parser.py +0 -0
  37. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/command/processor.py +0 -0
  38. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/command/result.py +0 -0
  39. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/create.py +0 -0
  40. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/file.py +0 -0
  41. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/sample.py +0 -0
  42. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/environment/telemetry.py +0 -0
  43. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/event/__init__.py +0 -0
  44. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/event/header.py +0 -0
  45. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/channel/registry.py +0 -0
  46. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/codec/__init__.py +0 -0
  47. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/codec/protocol/__init__.py +0 -0
  48. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/codec/protocol/base.py +0 -0
  49. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/codec/protocol/json.py +0 -0
  50. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/codec/system/__init__.py +0 -0
  51. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/__init__.py +0 -0
  52. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/all.py +0 -0
  53. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/arbiter.py +0 -0
  54. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/common.py +0 -0
  55. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/mtu.py +0 -0
  56. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/server.py +0 -0
  57. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/task.py +0 -0
  58. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/tftp.py +0 -0
  59. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/commands/tui.py +0 -0
  60. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/control/__init__.py +0 -0
  61. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/control/env/__init__.py +0 -0
  62. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/control/source.py +0 -0
  63. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/control/step.py +0 -0
  64. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/browser.yaml +0 -0
  65. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/css/bootstrap_extra.css +0 -0
  66. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/css/font.css +0 -0
  67. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/css/main.css +0 -0
  68. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/dummy_load.yaml +0 -0
  69. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/factories.yaml +0 -0
  70. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/favicon.ico +0 -0
  71. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/DataConnection.js +0 -0
  72. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/JsonConnection.js +0 -0
  73. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/audio.js +0 -0
  74. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/App.js +0 -0
  75. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/ChannelTable.js +0 -0
  76. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/DataConnection.js +0 -0
  77. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/JsonConnection.js +0 -0
  78. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/OverlayManager.js +0 -0
  79. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/Plot.js +0 -0
  80. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/PlotDrawer.js +0 -0
  81. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/PlotManager.js +0 -0
  82. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/PlotModalManager.js +0 -0
  83. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/PointBuffer.js +0 -0
  84. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/PointManager.js +0 -0
  85. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/TabFilter.js +0 -0
  86. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/TabInterface.js +0 -0
  87. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/UnitSystem.js +0 -0
  88. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/WindowHashManager.js +0 -0
  89. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/classes/WorkerInterface.js +0 -0
  90. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/events.js +0 -0
  91. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/init.js +0 -0
  92. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/main.js +0 -0
  93. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/tab/env.js +0 -0
  94. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/tab/sound.js +0 -0
  95. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/third-party/webgl-debug.js +0 -0
  96. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/unused/pyodide.js +0 -0
  97. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/util.js +0 -0
  98. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/js/worker.js +0 -0
  99. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/md/Connection.md +0 -0
  100. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/md/PeriodicTask.md +0 -0
  101. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/md/RuntimeStruct.md +0 -0
  102. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/md/RuntimepyPeer.md +0 -0
  103. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/md/SinusoidTask.md +0 -0
  104. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/sample_telemetry.yaml +0 -0
  105. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/BitFields.yaml +0 -0
  106. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/Channel.yaml +0 -0
  107. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/ChannelCommand.yaml +0 -0
  108. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/ChannelRegistry.yaml +0 -0
  109. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/ClientConnectionConfig.yaml +0 -0
  110. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/ConnectionArbiterConfig.yaml +0 -0
  111. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/EnumRegistry.yaml +0 -0
  112. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/FindFile.yaml +0 -0
  113. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/PeerProcessConfig.yaml +0 -0
  114. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/RuntimeEnum.yaml +0 -0
  115. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/ServerConnectionConfig.yaml +0 -0
  116. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/StructConfig.yaml +0 -0
  117. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/TaskConfig.yaml +0 -0
  118. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/channel_controls.yaml +0 -0
  119. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/has_config.yaml +0 -0
  120. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/has_factory.yaml +0 -0
  121. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/has_markdown.yaml +0 -0
  122. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/has_name.yaml +0 -0
  123. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/schemas/has_request_flag.yaml +0 -0
  124. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/server.yaml +0 -0
  125. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/server_base.yaml +0 -0
  126. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/server_dev.yaml +0 -0
  127. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/svg/chip-circle-bootstrap.svg +0 -0
  128. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaCode-Bold.woff2 +0 -0
  129. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaCode-BoldItalic.woff2 +0 -0
  130. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaCode-Italic.woff2 +0 -0
  131. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaCode-Regular.woff2 +0 -0
  132. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaMono-Bold.woff2 +0 -0
  133. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaMono-BoldItalic.woff2 +0 -0
  134. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaMono-Italic.woff2 +0 -0
  135. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/CascadiaMono-Regular.woff2 +0 -0
  136. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/static/woff2/README.md +0 -0
  137. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/data/tftp_server.yaml +0 -0
  138. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/dev_requirements.txt +0 -0
  139. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/entry.py +0 -0
  140. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/enum/__init__.py +0 -0
  141. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/enum/registry.py +0 -0
  142. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/enum/types.py +0 -0
  143. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mapping.py +0 -0
  144. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/message/__init__.py +0 -0
  145. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/message/handlers.py +0 -0
  146. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/message/interface.py +0 -0
  147. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/message/types.py +0 -0
  148. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/metrics/__init__.py +0 -0
  149. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/metrics/channel.py +0 -0
  150. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/metrics/connection.py +0 -0
  151. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/metrics/task.py +0 -0
  152. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/__init__.py +0 -0
  153. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/async_command.py +0 -0
  154. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/enum.py +0 -0
  155. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/environment.py +0 -0
  156. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/finalize.py +0 -0
  157. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/psutil.py +0 -0
  158. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/regex.py +0 -0
  159. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/mixins/trig.py +0 -0
  160. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/__init__.py +0 -0
  161. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/apps/__init__.py +0 -0
  162. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/__init__.py +0 -0
  163. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/base.py +0 -0
  164. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/config/__init__.py +0 -0
  165. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/config/codec.py +0 -0
  166. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/config/util.py +0 -0
  167. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/factory/__init__.py +0 -0
  168. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/factory/connection.py +0 -0
  169. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/factory/task.py +0 -0
  170. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/housekeeping/__init__.py +0 -0
  171. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/imports/__init__.py +0 -0
  172. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/imports/util.py +0 -0
  173. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/info.py +0 -0
  174. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/result.py +0 -0
  175. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/struct/__init__.py +0 -0
  176. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/task.py +0 -0
  177. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/tcp/__init__.py +0 -0
  178. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/tcp/json.py +0 -0
  179. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/udp.py +0 -0
  180. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/arbiter/websocket.py +0 -0
  181. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/backoff.py +0 -0
  182. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/connection.py +0 -0
  183. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/factories/__init__.py +0 -0
  184. {runtimepy-5.7.2/runtimepy/net/server/app → runtimepy-5.7.4/runtimepy/net/html}/bootstrap/__init__.py +0 -0
  185. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/http/__init__.py +0 -0
  186. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/http/common.py +0 -0
  187. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/http/header.py +0 -0
  188. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/http/request_target.py +0 -0
  189. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/http/response.py +0 -0
  190. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/http/state.py +0 -0
  191. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/http/version.py +0 -0
  192. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/manager.py +0 -0
  193. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/mixin.py +0 -0
  194. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/mtu.py +0 -0
  195. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/__init__.py +0 -0
  196. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/elements.py +0 -0
  197. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/tab/__init__.py +0 -0
  198. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/env/tab/message.py +0 -0
  199. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/app/pyodide.py +0 -0
  200. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/json.py +0 -0
  201. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/struct/__init__.py +0 -0
  202. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/websocket/__init__.py +0 -0
  203. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/server/websocket/state.py +0 -0
  204. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/ssl.py +0 -0
  205. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/stream/__init__.py +0 -0
  206. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/stream/base.py +0 -0
  207. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/stream/json/__init__.py +0 -0
  208. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/stream/string.py +0 -0
  209. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/__init__.py +0 -0
  210. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/connection.py +0 -0
  211. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/create.py +0 -0
  212. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/http/__init__.py +0 -0
  213. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/protocol.py +0 -0
  214. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/scpi/__init__.py +0 -0
  215. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/telnet/__init__.py +0 -0
  216. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/telnet/codes.py +0 -0
  217. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/tcp/telnet/np_05b.py +0 -0
  218. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/__init__.py +0 -0
  219. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/connection.py +0 -0
  220. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/create.py +0 -0
  221. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/protocol.py +0 -0
  222. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/queue.py +0 -0
  223. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/tftp/__init__.py +0 -0
  224. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/tftp/base.py +0 -0
  225. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/tftp/endpoint.py +0 -0
  226. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/tftp/enums.py +0 -0
  227. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/udp/tftp/io.py +0 -0
  228. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/util.py +0 -0
  229. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/websocket/__init__.py +0 -0
  230. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/net/websocket/connection.py +0 -0
  231. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/noise/__init__.py +0 -0
  232. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/__init__.py +0 -0
  233. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/array/__init__.py +0 -0
  234. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/base.py +0 -0
  235. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/bool.py +0 -0
  236. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/byte_order.py +0 -0
  237. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/evaluation.py +0 -0
  238. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/field/__init__.py +0 -0
  239. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/field/fields.py +0 -0
  240. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/field/manager/__init__.py +0 -0
  241. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/field/manager/base.py +0 -0
  242. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/float.py +0 -0
  243. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/int.py +0 -0
  244. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/scaling.py +0 -0
  245. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/serializable/__init__.py +0 -0
  246. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/serializable/base.py +0 -0
  247. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/serializable/fixed.py +0 -0
  248. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/serializable/framer.py +0 -0
  249. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/serializable/prefixed.py +0 -0
  250. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/string.py +0 -0
  251. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/types/__init__.py +0 -0
  252. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/types/base.py +0 -0
  253. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/types/bool.py +0 -0
  254. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/types/bounds.py +0 -0
  255. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/types/float.py +0 -0
  256. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/primitives/types/int.py +0 -0
  257. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/py.typed +0 -0
  258. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/registry/__init__.py +0 -0
  259. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/registry/bool.py +0 -0
  260. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/registry/item.py +0 -0
  261. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/registry/name.py +0 -0
  262. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/requirements.txt +0 -0
  263. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/sample/__init__.py +0 -0
  264. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/sample/peer.py +0 -0
  265. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/sample/program.py +0 -0
  266. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/schemas.py +0 -0
  267. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/struct/__init__.py +0 -0
  268. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/subprocess/__init__.py +0 -0
  269. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/subprocess/interface.py +0 -0
  270. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/subprocess/peer.py +0 -0
  271. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/subprocess/program.py +0 -0
  272. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/subprocess/protocol.py +0 -0
  273. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/task/__init__.py +0 -0
  274. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/task/asynchronous.py +0 -0
  275. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/task/basic/__init__.py +0 -0
  276. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/task/basic/manager.py +0 -0
  277. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/task/basic/periodic.py +0 -0
  278. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/task/sample.py +0 -0
  279. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/task/trig/__init__.py +0 -0
  280. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/telemetry/__init__.py +0 -0
  281. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/telemetry/sample.py +0 -0
  282. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/tui/__init__.py +0 -0
  283. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/tui/channels/__init__.py +0 -0
  284. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/tui/cursor.py +0 -0
  285. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/tui/mixin.py +0 -0
  286. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/tui/mock.py +0 -0
  287. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/tui/task.py +0 -0
  288. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/ui/__init__.py +0 -0
  289. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/ui/controls.py +0 -0
  290. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy/util.py +0 -0
  291. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy.egg-info/dependency_links.txt +0 -0
  292. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy.egg-info/entry_points.txt +0 -0
  293. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy.egg-info/requires.txt +2 -2
  294. {runtimepy-5.7.2 → runtimepy-5.7.4}/runtimepy.egg-info/top_level.txt +0 -0
  295. {runtimepy-5.7.2 → runtimepy-5.7.4}/setup.cfg +0 -0
  296. {runtimepy-5.7.2 → runtimepy-5.7.4}/setup.py +0 -0
  297. {runtimepy-5.7.2 → runtimepy-5.7.4}/tests/test_entry.py +0 -0
  298. {runtimepy-5.7.2 → runtimepy-5.7.4}/tests/test_mapping.py +0 -0
  299. {runtimepy-5.7.2 → runtimepy-5.7.4}/tests/test_resources.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: runtimepy
3
- Version: 5.7.2
3
+ Version: 5.7.4
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.11
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
- Requires-Dist: psutil
20
+ Requires-Dist: vcorelib>=3.4.2
21
21
  Requires-Dist: svgen>=0.6.8
22
22
  Requires-Dist: websockets
23
- Requires-Dist: vcorelib>=3.4.2
24
23
  Requires-Dist: aiofiles
24
+ Requires-Dist: psutil
25
25
  Provides-Extra: test
26
26
  Requires-Dist: pylint; extra == "test"
27
27
  Requires-Dist: flake8; extra == "test"
@@ -45,11 +45,11 @@ Requires-Dist: uvloop; (sys_platform != "win32" and sys_platform != "cygwin") an
45
45
  =====================================
46
46
  generator=datazen
47
47
  version=3.1.4
48
- hash=618546df79dd7f387faa6f84f9a58c79
48
+ hash=fbb71900eae64b008d2a2df1b7dde92b
49
49
  =====================================
50
50
  -->
51
51
 
52
- # runtimepy ([5.7.2](https://pypi.org/project/runtimepy/))
52
+ # runtimepy ([5.7.4](https://pypi.org/project/runtimepy/))
53
53
 
54
54
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
55
55
  ![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=618546df79dd7f387faa6f84f9a58c79
5
+ hash=fbb71900eae64b008d2a2df1b7dde92b
6
6
  =====================================
7
7
  -->
8
8
 
9
- # runtimepy ([5.7.2](https://pypi.org/project/runtimepy/))
9
+ # runtimepy ([5.7.4](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.7.2"
7
+ version = "5.7.4"
8
8
  description = "A framework for implementing Python services."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,7 +1,7 @@
1
1
  # =====================================
2
2
  # generator=datazen
3
3
  # version=3.1.4
4
- # hash=0a0c607a8f78dc35cf48427539c9bafa
4
+ # hash=cb3ed2d01203d78ad794d39500d706f9
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.7.2"
13
+ VERSION = "5.7.4"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -0,0 +1,24 @@
1
+ /* Dark is hard-coded initial state (in HTML). */
2
+ let lightMode = false;
3
+
4
+ function lightDarkClick(event) {
5
+ lightMode = !lightMode;
6
+
7
+ document.getElementById("runtimepy")
8
+ .setAttribute("data-bs-theme", lightMode ? "light" : "dark");
9
+
10
+ window.location.hash = lightMode ? "#light-mode" : "";
11
+ }
12
+
13
+ let lightDarkButton = document.getElementById("theme-button");
14
+ if (lightDarkButton) {
15
+ lightDarkButton.addEventListener("click", lightDarkClick);
16
+ }
17
+
18
+ if (window.location.hash) {
19
+ let parts = window.location.hash.slice(1).split(",");
20
+
21
+ if (parts.includes("light-mode")) {
22
+ lightDarkButton.click();
23
+ }
24
+ }
@@ -10,7 +10,7 @@ from typing import Any, Iterable
10
10
 
11
11
  # third-party
12
12
  import aiofiles
13
- from vcorelib.logging import LoggerMixin, LoggerType
13
+ from vcorelib.logging import ListLogger, LoggerMixin, LoggerType
14
14
  from vcorelib.paths import Pathlike, normalize
15
15
 
16
16
  # internal
@@ -66,6 +66,25 @@ class LoggerMixinLevelControl(LoggerMixin):
66
66
 
67
67
 
68
68
  LogPaths = Iterable[tuple[LogLevellike, Pathlike]]
69
+ EXT_LOG_EXTRA = {"external": True}
70
+
71
+
72
+ def handle_safe_log(
73
+ logger: LoggerType, level: int, data: str, safe_to_log: bool
74
+ ) -> None:
75
+ """handle a log filtering scenario."""
76
+
77
+ if safe_to_log:
78
+ logger.log(level, data, extra=EXT_LOG_EXTRA)
79
+ else:
80
+ record = logging.LogRecord(
81
+ logger.name, level, __file__, -1, data, (), None
82
+ )
83
+ record.external = True
84
+
85
+ for handler in logger.handlers: # type: ignore
86
+ if isinstance(handler, ListLogger):
87
+ handler.emit(record)
69
88
 
70
89
 
71
90
  class LogCaptureMixin:
@@ -76,7 +95,10 @@ class LogCaptureMixin:
76
95
  # Open aiofiles handles.
77
96
  streams: list[tuple[int, Any]]
78
97
 
79
- ext_log_extra = {"external": True}
98
+ # Set false to only forward to ListLogger handlers. Required for when the
99
+ # system log / process-management logs are being forwarded (otherwise also
100
+ # logging would lead to infinite spam).
101
+ safe_to_log = True
80
102
 
81
103
  async def init_log_capture(
82
104
  self, stack: AsyncExitStack, log_paths: LogPaths
@@ -98,7 +120,8 @@ class LogCaptureMixin:
98
120
 
99
121
  def log_line(self, level: int, data: str) -> None:
100
122
  """Log a line for output."""
101
- self.logger.log(level, data, extra=self.ext_log_extra)
123
+
124
+ handle_safe_log(self.logger, level, data, self.safe_to_log)
102
125
 
103
126
  async def dispatch_log_capture(self) -> None:
104
127
  """Get the next line from this log stream."""
@@ -1,5 +1,5 @@
1
1
  """
2
- A module implementing interfaces for working with file contents.
2
+ A module implementing HTML-related interfaces.
3
3
  """
4
4
 
5
5
  # built-in
@@ -8,12 +8,88 @@ from typing import Optional
8
8
 
9
9
  # third-party
10
10
  from svgen.element import Element
11
+ from svgen.element.html import Html, div
11
12
  from vcorelib import DEFAULT_ENCODING
12
13
  from vcorelib.io import IndentedFileWriter
13
14
  from vcorelib.paths import find_file
14
15
 
15
16
  # internal
16
17
  from runtimepy import PKG_NAME
18
+ from runtimepy.net.html.bootstrap import (
19
+ add_bootstrap_css,
20
+ add_bootstrap_js,
21
+ icon_str,
22
+ )
23
+ from runtimepy.net.html.bootstrap.elements import (
24
+ bootstrap_button,
25
+ centered_markdown,
26
+ )
27
+
28
+
29
+ def create_app_shell(parent: Element, **kwargs) -> tuple[Element, Element]:
30
+ """Create a bootstrap-based application shell."""
31
+
32
+ container = div(parent=parent, **kwargs)
33
+ container.add_class("d-flex", "align-items-start", "bg-body")
34
+
35
+ # Dark theme.
36
+ container["data-bs-theme"] = "dark"
37
+
38
+ # Buttons.
39
+ button_column = div(parent=container)
40
+ button_column.add_class("d-flex", "flex-column", "h-100", "bg-dark-subtle")
41
+
42
+ # Dark/light theme switch button.
43
+ bootstrap_button(
44
+ icon_str("lightbulb"),
45
+ tooltip=" Toggle light/dark.",
46
+ id="theme-button",
47
+ parent=button_column,
48
+ )
49
+
50
+ return container, button_column
51
+
52
+
53
+ def markdown_page(parent: Element, markdown: str, **kwargs) -> None:
54
+ """Compose a landing page."""
55
+
56
+ container = centered_markdown(
57
+ create_app_shell(parent, **kwargs)[0], markdown, "h-100", "text-body"
58
+ )
59
+ container.add_class("overflow-y-auto")
60
+
61
+
62
+ def common_css(document: Html) -> None:
63
+ """Add common CSS to an HTML document."""
64
+
65
+ append_kind(document.head, "font", kind="css", tag="style")
66
+ add_bootstrap_css(document.head)
67
+ append_kind(
68
+ document.head, "main", "bootstrap_extra", kind="css", tag="style"
69
+ )
70
+
71
+
72
+ def full_markdown_page(document: Html, markdown: str) -> None:
73
+ """Render a full markdown HTML app."""
74
+
75
+ common_css(document)
76
+ markdown_page(document.body, markdown, id=PKG_NAME)
77
+
78
+ # JavaScript.
79
+ append_kind(document.body, "markdown_page")
80
+ add_bootstrap_js(document.body)
81
+
82
+
83
+ def handle_worker(writer: IndentedFileWriter) -> int:
84
+ """Boilerplate contents for worker thread block."""
85
+
86
+ # Not currently used.
87
+ # return write_found_file(
88
+ # writer, kind_url("js", "webgl-debug", subdir="third-party")
89
+ # )
90
+ del writer
91
+
92
+ return 0
17
93
 
18
94
 
19
95
  def write_found_file(writer: IndentedFileWriter, *args, **kwargs) -> bool:
@@ -32,19 +108,6 @@ def write_found_file(writer: IndentedFileWriter, *args, **kwargs) -> bool:
32
108
  return result
33
109
 
34
110
 
35
- def set_text_to_file(element: Element, *args, **kwargs) -> bool:
36
- """Set an element's text to the contents of a file."""
37
-
38
- with StringIO() as stream:
39
- result = write_found_file(
40
- IndentedFileWriter(stream, per_indent=2), *args, **kwargs
41
- )
42
- if result:
43
- element.text = stream.getvalue()
44
-
45
- return result
46
-
47
-
48
111
  def kind_url(
49
112
  kind: str, name: str, subdir: str = None, package: str = PKG_NAME
50
113
  ) -> str:
@@ -60,35 +123,9 @@ def kind_url(
60
123
  return f"package://{package}/{path}.{kind}"
61
124
 
62
125
 
63
- def set_text_to_kind(
64
- element: Element,
65
- kind: str,
66
- name: str,
67
- package: str = PKG_NAME,
68
- subdir: str = None,
69
- ) -> bool:
70
- """Set text to HTML-file contents at a predictable path."""
71
-
72
- return set_text_to_file(
73
- element, kind_url(kind, name, subdir=subdir, package=package)
74
- )
75
-
76
-
77
126
  WORKER_TYPE = "text/js-worker"
78
127
 
79
128
 
80
- def handle_worker(writer: IndentedFileWriter) -> int:
81
- """Boilerplate contents for worker thread block."""
82
-
83
- # Not currently used.
84
- # return write_found_file(
85
- # writer, kind_url("js", "webgl-debug", subdir="third-party")
86
- # )
87
- del writer
88
-
89
- return 0
90
-
91
-
92
129
  def append_kind(
93
130
  element: Element,
94
131
  *names: str,
@@ -12,7 +12,7 @@ from svgen.element.html import div
12
12
  from vcorelib.io.file_writer import IndentedFileWriter
13
13
 
14
14
  # internal
15
- from runtimepy.net.server.app.bootstrap import icon_str
15
+ from runtimepy.net.html.bootstrap import icon_str
16
16
 
17
17
  TEXT = "font-monospace"
18
18
  BOOTSTRAP_BUTTON = f"rounded-0 {TEXT} button-bodge text-nowrap"
@@ -167,7 +167,7 @@ def slider(
167
167
 
168
168
  def centered_markdown(
169
169
  parent: Element, markdown: str, *container_classes: str
170
- ) -> None:
170
+ ) -> Element:
171
171
  """Add centered markdown."""
172
172
 
173
173
  container = div(parent=parent)
@@ -198,3 +198,5 @@ def centered_markdown(
198
198
  div(parent=horiz_container)
199
199
 
200
200
  div(parent=container)
201
+
202
+ return container
@@ -8,10 +8,9 @@ from svgen.element.html import div
8
8
 
9
9
  # internal
10
10
  from runtimepy import PKG_NAME
11
- from runtimepy.net.server.app.bootstrap import icon_str
12
- from runtimepy.net.server.app.bootstrap.elements import (
11
+ from runtimepy.net.html import create_app_shell
12
+ from runtimepy.net.html.bootstrap.elements import (
13
13
  BOOTSTRAP_BUTTON,
14
- bootstrap_button,
15
14
  collapse_button,
16
15
  flex,
17
16
  toggle_button,
@@ -84,27 +83,7 @@ class TabbedContent:
84
83
  """Initialize this instance."""
85
84
 
86
85
  self.name = name
87
-
88
- # Create application container.
89
- self.container = div(parent=parent, id=name)
90
- self.container.add_class("d-flex", "align-items-start", "bg-body")
91
-
92
- # Dark theme.
93
- self.container["data-bs-theme"] = "dark"
94
-
95
- # Buttons.
96
- self.button_column = div(parent=self.container)
97
- self.button_column.add_class(
98
- "d-flex", "flex-column", "h-100", "bg-dark-subtle"
99
- )
100
-
101
- # Dark/light theme switch button.
102
- bootstrap_button(
103
- icon_str("lightbulb"),
104
- tooltip=" Toggle light/dark.",
105
- id="theme-button",
106
- parent=self.button_column,
107
- )
86
+ self.container, self.button_column = create_app_shell(parent, id=name)
108
87
 
109
88
  # Toggle tabs button.
110
89
  self.add_button("Toggle tabs", f"#{PKG_NAME}-tabs", id="tabs-button")
@@ -11,16 +11,19 @@ from pathlib import Path
11
11
  from typing import Any, Optional, TextIO, Union
12
12
 
13
13
  # third-party
14
- from vcorelib.io import JsonObject
14
+ import aiofiles
15
+ from vcorelib import DEFAULT_ENCODING
16
+ from vcorelib.io import IndentedFileWriter, JsonObject
15
17
  from vcorelib.paths import Pathlike, find_file, normalize
16
18
 
17
19
  # internal
18
20
  from runtimepy import DEFAULT_EXT, PKG_NAME
19
21
  from runtimepy.channel.environment.command import GLOBAL
22
+ from runtimepy.net.html import full_markdown_page
20
23
  from runtimepy.net.http.header import RequestHeader
21
24
  from runtimepy.net.http.request_target import PathMaybeQuery
22
25
  from runtimepy.net.http.response import ResponseHeader
23
- from runtimepy.net.server.html import HtmlApp, HtmlApps, html_handler
26
+ from runtimepy.net.server.html import HtmlApp, HtmlApps, get_html, html_handler
24
27
  from runtimepy.net.server.json import encode_json, json_handler
25
28
  from runtimepy.net.tcp.http import HttpConnection
26
29
  from runtimepy.util import normalize_root, path_has_part
@@ -106,7 +109,7 @@ class RuntimepyServerConnection(HttpConnection):
106
109
  with favicon.open("rb") as favicon_fd:
107
110
  type(self).favicon_data = favicon_fd.read()
108
111
 
109
- def try_redirect(
112
+ async def try_redirect(
110
113
  self, path: PathMaybeQuery, response: ResponseHeader
111
114
  ) -> Optional[bytes]:
112
115
  """Try handling any HTTP redirect rules."""
@@ -123,7 +126,26 @@ class RuntimepyServerConnection(HttpConnection):
123
126
 
124
127
  return result
125
128
 
126
- def try_file(
129
+ async def render_markdown(
130
+ self, path: Path, response: ResponseHeader, **kwargs
131
+ ) -> bytes:
132
+ """Render a markdown file as HTML and return the result."""
133
+
134
+ document = get_html()
135
+
136
+ async with aiofiles.open(path, mode="r") as path_fd:
137
+ with IndentedFileWriter.string() as writer:
138
+ writer.write_markdown(await path_fd.read(), **kwargs)
139
+ full_markdown_page(
140
+ document,
141
+ writer.stream.getvalue(), # type: ignore
142
+ )
143
+
144
+ response["Content-Type"] = f"text/html; charset={DEFAULT_ENCODING}"
145
+
146
+ return document.encode_str().encode()
147
+
148
+ async def try_file(
127
149
  self, path: PathMaybeQuery, response: ResponseHeader
128
150
  ) -> Optional[bytes]:
129
151
  """Try serving this path as a file directly from the file-system."""
@@ -133,6 +155,12 @@ class RuntimepyServerConnection(HttpConnection):
133
155
  # Try serving the path as a file.
134
156
  for search in self.paths:
135
157
  candidate = search.joinpath(path[0][1:])
158
+
159
+ # Handle markdown sources.
160
+ md_candidate = candidate.with_suffix(".md")
161
+ if md_candidate.is_file():
162
+ return await self.render_markdown(md_candidate, response)
163
+
136
164
  if candidate.is_file():
137
165
  mime, encoding = mimetypes.guess_type(candidate, strict=False)
138
166
 
@@ -146,8 +174,8 @@ class RuntimepyServerConnection(HttpConnection):
146
174
  self.logger.info("Serving '%s' (MIME: %s)", candidate, mime)
147
175
 
148
176
  # Return the file data.
149
- with candidate.open("rb") as path_fd:
150
- result = path_fd.read()
177
+ async with aiofiles.open(candidate, mode="rb") as path_fd:
178
+ result = await path_fd.read()
151
179
 
152
180
  break
153
181
 
@@ -223,7 +251,9 @@ class RuntimepyServerConnection(HttpConnection):
223
251
 
224
252
  # Try serving a file and handling redirects.
225
253
  for handler in [self.try_redirect, self.try_file]:
226
- result = handler(request.target.origin_form, response)
254
+ result = await handler(
255
+ request.target.origin_form, response
256
+ )
227
257
  if result is not None:
228
258
  return result
229
259
 
@@ -11,12 +11,9 @@ from svgen.element.html import Html
11
11
  # internal
12
12
  from runtimepy import PKG_NAME
13
13
  from runtimepy.net.arbiter.info import AppInfo
14
- from runtimepy.net.server.app.bootstrap import (
15
- add_bootstrap_css,
16
- add_bootstrap_js,
17
- )
18
- from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
19
- from runtimepy.net.server.app.files import append_kind
14
+ from runtimepy.net.html import append_kind, common_css
15
+ from runtimepy.net.html.bootstrap import add_bootstrap_js
16
+ from runtimepy.net.html.bootstrap.tabs import TabbedContent
20
17
 
21
18
  TabPopulater = Callable[[TabbedContent], None]
22
19
 
@@ -53,11 +50,7 @@ class WebApplication:
53
50
  """Populate the body element with the application."""
54
51
 
55
52
  # CSS.
56
- append_kind(document.head, "font", kind="css", tag="style")
57
- add_bootstrap_css(document.head)
58
- append_kind(
59
- document.head, "main", "bootstrap_extra", kind="css", tag="style"
60
- )
53
+ common_css(document)
61
54
 
62
55
  # Worker code.
63
56
  append_kind(
@@ -11,10 +11,10 @@ from vcorelib.logging import LoggerMixin
11
11
 
12
12
  # internal
13
13
  from runtimepy.net.arbiter.info import AppInfo
14
+ from runtimepy.net.html.bootstrap.tabs import TabbedContent
14
15
  from runtimepy.net.http.header import RequestHeader
15
16
  from runtimepy.net.http.response import ResponseHeader
16
17
  from runtimepy.net.server.app.base import WebApplication
17
- from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
18
18
  from runtimepy.net.server.html import HtmlApp
19
19
 
20
20
  DOCUMENTS: dict[str, Html] = {}
@@ -8,11 +8,8 @@ from svgen.element.html import div
8
8
  # internal
9
9
  from runtimepy import PKG_NAME
10
10
  from runtimepy.net.arbiter.info import AppInfo
11
- from runtimepy.net.server.app.bootstrap.elements import (
12
- centered_markdown,
13
- input_box,
14
- )
15
- from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
11
+ from runtimepy.net.html.bootstrap.elements import centered_markdown, input_box
12
+ from runtimepy.net.html.bootstrap.tabs import TabbedContent
16
13
  from runtimepy.net.server.app.env.modal import Modal
17
14
  from runtimepy.net.server.app.env.settings import plot_settings
18
15
  from runtimepy.net.server.app.env.tab import ChannelEnvironmentTab
@@ -7,8 +7,8 @@ from svgen.element.html import div
7
7
 
8
8
  # internal
9
9
  from runtimepy import PKG_NAME
10
- from runtimepy.net.server.app.bootstrap.elements import TEXT
11
- from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
10
+ from runtimepy.net.html.bootstrap.elements import TEXT
11
+ from runtimepy.net.html.bootstrap.tabs import TabbedContent
12
12
 
13
13
 
14
14
  class Modal:
@@ -6,8 +6,8 @@ A module implementing an application-settings modal.
6
6
  from svgen.element.html import div
7
7
 
8
8
  # internal
9
- from runtimepy.net.server.app.bootstrap.elements import flex, slider
10
- from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
9
+ from runtimepy.net.html.bootstrap.elements import flex, slider
10
+ from runtimepy.net.html.bootstrap.tabs import TabbedContent
11
11
  from runtimepy.net.server.app.env.modal import Modal
12
12
  from runtimepy.net.server.app.placeholder import under_construction
13
13
 
@@ -13,7 +13,7 @@ from runtimepy.channel.environment.command.processor import (
13
13
  ChannelCommandProcessor,
14
14
  )
15
15
  from runtimepy.net.arbiter.info import AppInfo
16
- from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
16
+ from runtimepy.net.html.bootstrap.tabs import TabbedContent
17
17
  from runtimepy.net.server.app.tab import Tab
18
18
 
19
19
 
@@ -13,7 +13,7 @@ from svgen.element.html import div
13
13
  from runtimepy.channel import AnyChannel
14
14
  from runtimepy.channel.environment import ChannelEnvironment
15
15
  from runtimepy.enum import RuntimeEnum
16
- from runtimepy.net.server.app.bootstrap.elements import slider, toggle_button
16
+ from runtimepy.net.html.bootstrap.elements import slider, toggle_button
17
17
  from runtimepy.net.server.app.env.tab.base import ChannelEnvironmentTabBase
18
18
  from runtimepy.net.server.app.env.widgets import (
19
19
  TABLE_BUTTON_CLASSES,
@@ -12,7 +12,7 @@ from svgen.element.html import div
12
12
  # internal
13
13
  from runtimepy.channel import AnyChannel
14
14
  from runtimepy.enum import RuntimeEnum
15
- from runtimepy.net.server.app.bootstrap.elements import (
15
+ from runtimepy.net.html.bootstrap.elements import (
16
16
  TEXT,
17
17
  centered_markdown,
18
18
  flex,
@@ -241,7 +241,9 @@ class ChannelEnvironmentTabHtml(ChannelEnvironmentTabControls):
241
241
  logs = div(
242
242
  tag="textarea",
243
243
  parent=div(parent=vert_container, class_str="form-floating"),
244
- class_str=(f"form-control rounded-0 {TEXT} text-logs"),
244
+ class_str=(
245
+ f"form-control rounded-0 {TEXT} text-body-emphasis text-logs"
246
+ ),
245
247
  id=self.get_id("logs"),
246
248
  title=f"Text logs for {self.name}.",
247
249
  )
@@ -14,7 +14,7 @@ from runtimepy.channel.environment.command.processor import (
14
14
  ChannelCommandProcessor,
15
15
  )
16
16
  from runtimepy.enum import RuntimeEnum
17
- from runtimepy.net.server.app.bootstrap.elements import (
17
+ from runtimepy.net.html.bootstrap.elements import (
18
18
  flex,
19
19
  input_box,
20
20
  set_tooltip,
@@ -0,0 +1,41 @@
1
+ """
2
+ A module implementing interfaces for working with file contents.
3
+ """
4
+
5
+ # built-in
6
+ from io import StringIO
7
+
8
+ # third-party
9
+ from svgen.element import Element
10
+ from vcorelib.io import IndentedFileWriter
11
+
12
+ # internal
13
+ from runtimepy import PKG_NAME
14
+ from runtimepy.net.html import kind_url, write_found_file
15
+
16
+
17
+ def set_text_to_file(element: Element, *args, **kwargs) -> bool:
18
+ """Set an element's text to the contents of a file."""
19
+
20
+ with StringIO() as stream:
21
+ result = write_found_file(
22
+ IndentedFileWriter(stream, per_indent=2), *args, **kwargs
23
+ )
24
+ if result:
25
+ element.text = stream.getvalue()
26
+
27
+ return result
28
+
29
+
30
+ def set_text_to_kind(
31
+ element: Element,
32
+ kind: str,
33
+ name: str,
34
+ package: str = PKG_NAME,
35
+ subdir: str = None,
36
+ ) -> bool:
37
+ """Set text to HTML-file contents at a predictable path."""
38
+
39
+ return set_text_to_file(
40
+ element, kind_url(kind, name, subdir=subdir, package=package)
41
+ )
@@ -10,6 +10,7 @@ from svgen.element.html import Html
10
10
 
11
11
  # internal
12
12
  from runtimepy.net.arbiter.info import AppInfo
13
+ from runtimepy.net.html import full_markdown_page
13
14
  from runtimepy.net.http.header import RequestHeader
14
15
  from runtimepy.net.http.response import ResponseHeader
15
16
 
@@ -28,6 +29,11 @@ def landing_page(
28
29
  del response
29
30
  del request_data
30
31
 
31
- print(app)
32
+ full_markdown_page(
33
+ document,
34
+ app.config_param("landing_page", {}, strict=True).get( # type: ignore
35
+ "markdown", "no data"
36
+ ),
37
+ )
32
38
 
33
39
  return document