runtimepy 4.2.0__tar.gz → 4.2.2__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.
- {runtimepy-4.2.0/runtimepy.egg-info → runtimepy-4.2.2}/PKG-INFO +5 -5
- {runtimepy-4.2.0 → runtimepy-4.2.2}/README.md +2 -2
- {runtimepy-4.2.0 → runtimepy-4.2.2}/pyproject.toml +1 -1
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/__init__.py +2 -2
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/__init__.py +4 -8
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/base.py +19 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/command/__init__.py +3 -2
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/create.py +0 -14
- runtimepy-4.2.2/runtimepy/channel/environment/telemetry.py +173 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/event/__init__.py +4 -2
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/registry.py +1 -45
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/dummy_load.yaml +15 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/factories.yaml +1 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/TabFilter.js +2 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/TabInterface.js +3 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/WindowHashManager.js +82 -12
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/util.js +3 -1
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/BitFields.yaml +3 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mapping.py +2 -14
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/message/interface.py +17 -15
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/base.py +10 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/field/__init__.py +2 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/field/fields.py +16 -3
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/field/manager/base.py +19 -1
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/subprocess/interface.py +5 -3
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/subprocess/peer.py +0 -1
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/subprocess/program.py +7 -1
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/task/sample.py +29 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/util.py +29 -1
- {runtimepy-4.2.0 → runtimepy-4.2.2/runtimepy.egg-info}/PKG-INFO +5 -5
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy.egg-info/SOURCES.txt +1 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/LICENSE +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/__main__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/app.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/array.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/command/parser.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/command/processor.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/command/result.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/file.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/environment/sample.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/channel/event/header.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/codec/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/codec/protocol/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/codec/protocol/base.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/codec/protocol/json.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/codec/system/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/commands/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/commands/all.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/commands/arbiter.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/commands/common.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/commands/server.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/commands/task.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/commands/tui.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/css/bootstrap_extra.css +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/css/main.css +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/favicon.ico +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/DataConnection.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/JsonConnection.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/audio.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/App.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/ChannelTable.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/DataConnection.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/JsonConnection.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/Plot.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/PlotManager.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/PlotModalManager.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/classes/WorkerInterface.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/init.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/main.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/tab/env.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/tab/sound.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/unused/pyodide.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/js/worker.js +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/Channel.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/ChannelCommand.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/ChannelRegistry.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/ClientConnectionConfig.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/ConnectionArbiterConfig.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/EnumRegistry.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/FindFile.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/PeerProcessConfig.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/RuntimeEnum.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/ServerConnectionConfig.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/StructConfig.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/TaskConfig.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/has_config.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/has_factory.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/has_name.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/schemas/has_request_flag.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/server.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/server_base.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/data/server_dev.yaml +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/dev_requirements.txt +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/entry.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/enum/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/enum/registry.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/enum/types.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/message/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/message/handlers.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/message/types.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/metrics/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/metrics/channel.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/metrics/connection.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/metrics/task.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/async_command.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/enum.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/environment.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/finalize.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/logging.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/psutil.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/mixins/regex.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/apps/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/base.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/config/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/config/codec.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/config/util.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/factory/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/factory/connection.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/factory/task.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/housekeeping/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/imports/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/imports/util.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/info.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/result.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/task.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/tcp/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/tcp/json.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/udp.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/arbiter/websocket.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/backoff.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/connection.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/factories/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/http/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/http/common.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/http/header.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/http/request_target.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/http/response.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/http/state.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/http/version.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/manager.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/mixin.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/base.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/bootstrap/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/bootstrap/elements.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/bootstrap/tabs.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/create.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/elements.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/env/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/env/modal.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/env/tab/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/env/tab/base.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/env/tab/html.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/env/tab/message.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/env/widgets.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/files.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/placeholder.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/pyodide.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/sound.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/app/tab.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/html.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/json.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/struct/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/websocket/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/server/websocket/state.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/stream/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/stream/base.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/stream/json/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/stream/string.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/tcp/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/tcp/connection.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/tcp/create.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/tcp/http/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/tcp/protocol.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/tcp/telnet/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/tcp/telnet/codes.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/udp/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/udp/connection.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/udp/create.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/udp/protocol.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/util.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/websocket/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/net/websocket/connection.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/array/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/bool.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/byte_order.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/field/manager/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/float.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/int.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/scaling.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/serializable/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/serializable/base.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/serializable/fixed.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/serializable/prefixed.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/string.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/types/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/types/base.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/types/bool.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/types/bounds.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/types/float.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/primitives/types/int.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/py.typed +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/registry/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/registry/bool.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/registry/item.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/registry/name.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/requirements.txt +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/sample/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/sample/peer.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/sample/program.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/schemas.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/struct/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/subprocess/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/subprocess/protocol.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/task/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/task/asynchronous.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/task/basic/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/task/basic/manager.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/task/basic/periodic.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/task/trig/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/telemetry/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/tui/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/tui/channels/__init__.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/tui/cursor.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/tui/mixin.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/tui/mock.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy/tui/task.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy.egg-info/dependency_links.txt +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy.egg-info/entry_points.txt +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy.egg-info/requires.txt +2 -2
- {runtimepy-4.2.0 → runtimepy-4.2.2}/runtimepy.egg-info/top_level.txt +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/setup.cfg +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/setup.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/tests/test_entry.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/tests/test_mapping.py +0 -0
- {runtimepy-4.2.0 → runtimepy-4.2.2}/tests/test_resources.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: runtimepy
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.2
|
|
4
4
|
Summary: A framework for implementing Python services.
|
|
5
5
|
Home-page: https://github.com/vkottler/runtimepy
|
|
6
6
|
Author: Vaughn Kottler
|
|
@@ -17,10 +17,10 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
17
17
|
Requires-Python: >=3.11
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: psutil
|
|
21
21
|
Requires-Dist: vcorelib>=3.2.4
|
|
22
22
|
Requires-Dist: svgen>=0.6.6
|
|
23
|
-
Requires-Dist:
|
|
23
|
+
Requires-Dist: websockets
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: pylint; extra == "test"
|
|
26
26
|
Requires-Dist: flake8; extra == "test"
|
|
@@ -44,11 +44,11 @@ Requires-Dist: uvloop; (sys_platform != "win32" and sys_platform != "cygwin") an
|
|
|
44
44
|
=====================================
|
|
45
45
|
generator=datazen
|
|
46
46
|
version=3.1.4
|
|
47
|
-
hash=
|
|
47
|
+
hash=5f56531d1be3002a8547ddb013d713f9
|
|
48
48
|
=====================================
|
|
49
49
|
-->
|
|
50
50
|
|
|
51
|
-
# runtimepy ([4.2.
|
|
51
|
+
# runtimepy ([4.2.2](https://pypi.org/project/runtimepy/))
|
|
52
52
|
|
|
53
53
|
[](https://pypi.org/project/runtimepy/)
|
|
54
54
|

|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
=====================================
|
|
3
3
|
generator=datazen
|
|
4
4
|
version=3.1.4
|
|
5
|
-
hash=
|
|
5
|
+
hash=5f56531d1be3002a8547ddb013d713f9
|
|
6
6
|
=====================================
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
|
-
# runtimepy ([4.2.
|
|
9
|
+
# runtimepy ([4.2.2](https://pypi.org/project/runtimepy/))
|
|
10
10
|
|
|
11
11
|
[](https://pypi.org/project/runtimepy/)
|
|
12
12
|

|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# =====================================
|
|
2
2
|
# generator=datazen
|
|
3
3
|
# version=3.1.4
|
|
4
|
-
# hash=
|
|
4
|
+
# hash=9427b9a1aadbcbc5e128b88c10b37dbe
|
|
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 = "4.2.
|
|
13
|
+
VERSION = "4.2.2"
|
|
14
14
|
|
|
15
15
|
# runtimepy-specific content.
|
|
16
16
|
METRICS_NAME = "metrics"
|
|
@@ -15,23 +15,19 @@ from runtimepy.channel.environment.create import (
|
|
|
15
15
|
from runtimepy.channel.environment.file import (
|
|
16
16
|
FileChannelEnvironment as _FileChannelEnvironment,
|
|
17
17
|
)
|
|
18
|
-
from runtimepy.channel.
|
|
18
|
+
from runtimepy.channel.environment.telemetry import (
|
|
19
|
+
TelemetryChannelEnvironment as _TelemetryChannelEnvironment,
|
|
20
|
+
)
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
class ChannelEnvironment(
|
|
24
|
+
_TelemetryChannelEnvironment,
|
|
22
25
|
_ArrayChannelEnvironment,
|
|
23
26
|
_FileChannelEnvironment,
|
|
24
27
|
_CreateChannelEnvironment,
|
|
25
28
|
):
|
|
26
29
|
"""A class integrating channel and enumeration registries."""
|
|
27
30
|
|
|
28
|
-
def ingest(self, point: ParsedEvent) -> None:
|
|
29
|
-
"""
|
|
30
|
-
Update internal state based on an event. Note that the event timestamp
|
|
31
|
-
is not respected.
|
|
32
|
-
"""
|
|
33
|
-
self.set(point.name, point.value)
|
|
34
|
-
|
|
35
31
|
@property
|
|
36
32
|
def names(self) -> _Iterator[str]:
|
|
37
33
|
"""Iterate over registered names in the environment."""
|
|
@@ -73,6 +73,8 @@ class BaseChannelEnvironment(_NamespaceMixin, FinalizeMixin):
|
|
|
73
73
|
for field in fields:
|
|
74
74
|
self.fields.add(field)
|
|
75
75
|
|
|
76
|
+
self.to_add: list[_BitFields] = []
|
|
77
|
+
|
|
76
78
|
# Keep a mapping of each channel's name and integer identifier to the
|
|
77
79
|
# underlying enumeration.
|
|
78
80
|
self.channel_enums: dict[_AnyChannel, _RuntimeEnum] = {
|
|
@@ -282,3 +284,20 @@ class BaseChannelEnvironment(_NamespaceMixin, FinalizeMixin):
|
|
|
282
284
|
prim = self.fields[key].raw
|
|
283
285
|
|
|
284
286
|
return prim.age_ns()
|
|
287
|
+
|
|
288
|
+
def add_field(self, field: _BitField, namespace: Namespace = None) -> str:
|
|
289
|
+
"""Add a bit field to the environment."""
|
|
290
|
+
|
|
291
|
+
result = self.fields.add_field(field)
|
|
292
|
+
if result is not None:
|
|
293
|
+
self.to_add.append(result)
|
|
294
|
+
|
|
295
|
+
return self.namespace(name=field.name, namespace=namespace)
|
|
296
|
+
|
|
297
|
+
def finalize(self, strict: bool = True) -> None:
|
|
298
|
+
"""Finalize this instance."""
|
|
299
|
+
|
|
300
|
+
for fields in self.to_add:
|
|
301
|
+
self.fields.add(fields)
|
|
302
|
+
|
|
303
|
+
super().finalize(strict=strict)
|
|
@@ -25,7 +25,8 @@ from runtimepy.channel.environment.command.processor import (
|
|
|
25
25
|
EnvironmentMap,
|
|
26
26
|
)
|
|
27
27
|
from runtimepy.channel.registry import ParsedEvent
|
|
28
|
-
from runtimepy.mapping import DEFAULT_PATTERN
|
|
28
|
+
from runtimepy.mapping import DEFAULT_PATTERN
|
|
29
|
+
from runtimepy.util import name_search
|
|
29
30
|
|
|
30
31
|
# Declared so we re-export FieldOrChannel after moving where it's declared.
|
|
31
32
|
__all__ = [
|
|
@@ -115,7 +116,7 @@ class GlobalEnvironment(UserDict[str, ChannelCommandProcessor], LoggerMixin):
|
|
|
115
116
|
"""Reade events from a specific environment."""
|
|
116
117
|
|
|
117
118
|
with self.valid_root.joinpath(env, path).open("rb") as path_fd:
|
|
118
|
-
yield from self[env].env.
|
|
119
|
+
yield from self[env].env.parse_event_stream(path_fd)
|
|
119
120
|
|
|
120
121
|
def export(self, env: str) -> Path:
|
|
121
122
|
"""Export an environment to a sub-directory of the root directory."""
|
|
@@ -28,8 +28,6 @@ from runtimepy.enum.types import EnumTypelike as _EnumTypelike
|
|
|
28
28
|
from runtimepy.mapping import EnumMappingData as _EnumMappingData
|
|
29
29
|
from runtimepy.primitives import ChannelScaling, Primitive
|
|
30
30
|
from runtimepy.primitives import Primitivelike as _Primitivelike
|
|
31
|
-
from runtimepy.primitives.field import BitField
|
|
32
|
-
from runtimepy.primitives.field.fields import BitFields
|
|
33
31
|
from runtimepy.registry.name import RegistryKey as _RegistryKey
|
|
34
32
|
|
|
35
33
|
|
|
@@ -184,15 +182,3 @@ class CreateChannelEnvironment(_BaseChannelEnvironment):
|
|
|
184
182
|
)
|
|
185
183
|
assert result is not None, f"Can't create enum '{name}'!"
|
|
186
184
|
return result
|
|
187
|
-
|
|
188
|
-
def add_field(self, field: BitField, namespace: _Namespace = None) -> str:
|
|
189
|
-
"""Add a bit field to the environment."""
|
|
190
|
-
|
|
191
|
-
fields = BitFields.new()
|
|
192
|
-
fields.claim_field(field)
|
|
193
|
-
|
|
194
|
-
name = self.namespace(name=field.name, namespace=namespace)
|
|
195
|
-
|
|
196
|
-
self.fields.add(fields)
|
|
197
|
-
|
|
198
|
-
return name
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A module implementing channel-environment telemetry registration.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# built-in
|
|
6
|
+
from contextlib import ExitStack, contextmanager
|
|
7
|
+
from typing import BinaryIO, Iterator, Optional, cast
|
|
8
|
+
|
|
9
|
+
# internal
|
|
10
|
+
from runtimepy.channel.environment.base import (
|
|
11
|
+
BaseChannelEnvironment as _BaseChannelEnvironment,
|
|
12
|
+
)
|
|
13
|
+
from runtimepy.channel.event import PrimitiveEvent
|
|
14
|
+
from runtimepy.channel.registry import ParsedEvent
|
|
15
|
+
from runtimepy.mapping import DEFAULT_PATTERN
|
|
16
|
+
from runtimepy.metrics.channel import ChannelMetrics
|
|
17
|
+
from runtimepy.util import name_search
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TelemetryChannelEnvironment(_BaseChannelEnvironment):
|
|
21
|
+
"""A class integrating telemetry streaming."""
|
|
22
|
+
|
|
23
|
+
events: list[str]
|
|
24
|
+
|
|
25
|
+
@contextmanager
|
|
26
|
+
def registered(
|
|
27
|
+
self,
|
|
28
|
+
stream: BinaryIO,
|
|
29
|
+
pattern: str = DEFAULT_PATTERN,
|
|
30
|
+
exact: bool = False,
|
|
31
|
+
flush: bool = False,
|
|
32
|
+
channel: ChannelMetrics = None,
|
|
33
|
+
) -> Iterator[list[str]]:
|
|
34
|
+
"""
|
|
35
|
+
Register a stream as a managed context. Returns a list of all channels
|
|
36
|
+
registered.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
names: list[str] = []
|
|
40
|
+
events: list[PrimitiveEvent] = []
|
|
41
|
+
|
|
42
|
+
# Gather event telemetry emitters for bit-fields.
|
|
43
|
+
for fields in self.fields.fields:
|
|
44
|
+
for name in name_search(fields.fields, pattern, exact=exact):
|
|
45
|
+
names.append(name)
|
|
46
|
+
field = fields.fields[name]
|
|
47
|
+
|
|
48
|
+
ident = self.channels.names.identifier(name)
|
|
49
|
+
assert ident is not None, name
|
|
50
|
+
|
|
51
|
+
events.append(PrimitiveEvent(field.raw, ident))
|
|
52
|
+
|
|
53
|
+
with ExitStack() as stack:
|
|
54
|
+
# Register bit-field event telemetry.
|
|
55
|
+
for event in events:
|
|
56
|
+
stack.enter_context(
|
|
57
|
+
event.registered(
|
|
58
|
+
stream, flush=flush, channel=channel, force=True
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Register channel telemetry.
|
|
63
|
+
names += stack.enter_context(
|
|
64
|
+
self.channels.registered(
|
|
65
|
+
stream,
|
|
66
|
+
pattern=pattern,
|
|
67
|
+
exact=exact,
|
|
68
|
+
flush=flush,
|
|
69
|
+
channel=channel,
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
yield names
|
|
74
|
+
|
|
75
|
+
def ingest(self, point: ParsedEvent) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Update internal state based on an event. Note that the event timestamp
|
|
78
|
+
is not respected.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
if self.fields.has_field(point.name):
|
|
82
|
+
self.fields[point.name].raw.value = point.value # type: ignore
|
|
83
|
+
else:
|
|
84
|
+
self.set(point.name, point.value)
|
|
85
|
+
|
|
86
|
+
def _parse_channel_event(self, name: str) -> Optional[ParsedEvent]:
|
|
87
|
+
"""Attempt to parse a channel event from the fifo."""
|
|
88
|
+
|
|
89
|
+
result = None
|
|
90
|
+
channels = self.channels
|
|
91
|
+
|
|
92
|
+
kind = channels[name].type
|
|
93
|
+
data = channels.event_fifo.pop(kind.size)
|
|
94
|
+
if data is not None:
|
|
95
|
+
result = ParsedEvent(
|
|
96
|
+
name,
|
|
97
|
+
cast(int, channels.event_header["timestamp"]),
|
|
98
|
+
kind.decode(
|
|
99
|
+
data,
|
|
100
|
+
byte_order=channels.event_header.array.byte_order,
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return result
|
|
105
|
+
|
|
106
|
+
def _parse_field_event(self, name: str) -> Optional[ParsedEvent]:
|
|
107
|
+
"""Attempt to parse a bit-field event from the fifo."""
|
|
108
|
+
|
|
109
|
+
result = None
|
|
110
|
+
|
|
111
|
+
field = self.fields[name]
|
|
112
|
+
|
|
113
|
+
kind = field.raw.kind
|
|
114
|
+
data = self.channels.event_fifo.pop(kind.size)
|
|
115
|
+
if data is not None:
|
|
116
|
+
result = ParsedEvent(
|
|
117
|
+
name,
|
|
118
|
+
cast(int, self.channels.event_header["timestamp"]),
|
|
119
|
+
kind.decode(
|
|
120
|
+
data,
|
|
121
|
+
byte_order=self.channels.event_header.array.byte_order,
|
|
122
|
+
),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return result
|
|
126
|
+
|
|
127
|
+
def parse_event_stream(self, stream: BinaryIO) -> Iterator[ParsedEvent]:
|
|
128
|
+
"""Parse individual events from a stream."""
|
|
129
|
+
|
|
130
|
+
channels = self.channels
|
|
131
|
+
|
|
132
|
+
# Ingest stream.
|
|
133
|
+
channels.event_fifo.ingest(stream.read())
|
|
134
|
+
|
|
135
|
+
ident = -1
|
|
136
|
+
name = ""
|
|
137
|
+
|
|
138
|
+
keep_going = True
|
|
139
|
+
while keep_going:
|
|
140
|
+
keep_going = False
|
|
141
|
+
|
|
142
|
+
# Read header.
|
|
143
|
+
if not channels.header_ready:
|
|
144
|
+
read_size = channels.event_header.size
|
|
145
|
+
data = channels.event_fifo.pop(read_size)
|
|
146
|
+
if data is not None:
|
|
147
|
+
channels.event_header.array.update(data)
|
|
148
|
+
|
|
149
|
+
# Update local variables.
|
|
150
|
+
ident = cast(int, channels.event_header["identifier"])
|
|
151
|
+
name = channels.names.name(ident) # type: ignore
|
|
152
|
+
assert name is not None, ident
|
|
153
|
+
|
|
154
|
+
# Update state.
|
|
155
|
+
channels.header_ready = True
|
|
156
|
+
keep_going = True
|
|
157
|
+
else:
|
|
158
|
+
event = None
|
|
159
|
+
|
|
160
|
+
# Handle bit-field.
|
|
161
|
+
if self.fields.has_field(name):
|
|
162
|
+
event = self._parse_field_event(name)
|
|
163
|
+
|
|
164
|
+
# Handle channel.
|
|
165
|
+
elif name in channels.items:
|
|
166
|
+
event = self._parse_channel_event(name)
|
|
167
|
+
|
|
168
|
+
if event is not None:
|
|
169
|
+
yield event
|
|
170
|
+
|
|
171
|
+
# Update state.
|
|
172
|
+
channels.header_ready = False
|
|
173
|
+
keep_going = True
|
|
@@ -44,6 +44,7 @@ class PrimitiveEvent:
|
|
|
44
44
|
stream: BinaryIO,
|
|
45
45
|
flush: bool = False,
|
|
46
46
|
channel: ChannelMetrics = None,
|
|
47
|
+
force: bool = False,
|
|
47
48
|
) -> Iterator[None]:
|
|
48
49
|
"""Register a stream as a managed context."""
|
|
49
50
|
|
|
@@ -51,7 +52,7 @@ class PrimitiveEvent:
|
|
|
51
52
|
|
|
52
53
|
def callback(_, __) -> None:
|
|
53
54
|
"""Emit a change event to the stream."""
|
|
54
|
-
self._poll(stream, flush=flush, channel=channel)
|
|
55
|
+
self._poll(stream, flush=flush, channel=channel, force=force)
|
|
55
56
|
|
|
56
57
|
# Poll immediately.
|
|
57
58
|
self.prev_ns = 0
|
|
@@ -71,6 +72,7 @@ class PrimitiveEvent:
|
|
|
71
72
|
stream: BinaryIO,
|
|
72
73
|
flush: bool = False,
|
|
73
74
|
channel: ChannelMetrics = None,
|
|
75
|
+
force: bool = False,
|
|
74
76
|
) -> int:
|
|
75
77
|
"""
|
|
76
78
|
Poll this event so that if the underlying channel has changed since the
|
|
@@ -83,7 +85,7 @@ class PrimitiveEvent:
|
|
|
83
85
|
raw = self.primitive
|
|
84
86
|
curr_ns = raw.last_updated_ns
|
|
85
87
|
|
|
86
|
-
if curr_ns - self.prev_ns >= self.min_period_ns:
|
|
88
|
+
if force or curr_ns - self.prev_ns >= self.min_period_ns:
|
|
87
89
|
self.prev_ns = curr_ns
|
|
88
90
|
self.header["timestamp"] = curr_ns
|
|
89
91
|
|
|
@@ -7,7 +7,7 @@ from contextlib import ExitStack, contextmanager
|
|
|
7
7
|
from typing import Any as _Any
|
|
8
8
|
from typing import BinaryIO, Iterable, Iterator, NamedTuple
|
|
9
9
|
from typing import Optional as _Optional
|
|
10
|
-
from typing import Union
|
|
10
|
+
from typing import Union
|
|
11
11
|
|
|
12
12
|
# third-party
|
|
13
13
|
from vcorelib.io import ByteFifo
|
|
@@ -150,47 +150,3 @@ class ChannelRegistry(_Registry[_Channel[_Any]]):
|
|
|
150
150
|
names.append(name)
|
|
151
151
|
|
|
152
152
|
yield names
|
|
153
|
-
|
|
154
|
-
def parse_event_stream(self, stream: BinaryIO) -> Iterator[ParsedEvent]:
|
|
155
|
-
"""Parse individual events from a stream."""
|
|
156
|
-
|
|
157
|
-
# Ingest stream.
|
|
158
|
-
self.event_fifo.ingest(stream.read())
|
|
159
|
-
|
|
160
|
-
ident = -1
|
|
161
|
-
name = ""
|
|
162
|
-
|
|
163
|
-
keep_going = True
|
|
164
|
-
while keep_going:
|
|
165
|
-
keep_going = False
|
|
166
|
-
|
|
167
|
-
# Read header.
|
|
168
|
-
if not self.header_ready:
|
|
169
|
-
read_size = self.event_header.size
|
|
170
|
-
data = self.event_fifo.pop(read_size)
|
|
171
|
-
if data is not None:
|
|
172
|
-
self.event_header.array.update(data)
|
|
173
|
-
|
|
174
|
-
# Update local variables.
|
|
175
|
-
ident = cast(int, self.event_header["identifier"])
|
|
176
|
-
name = self.names.name(ident) # type: ignore
|
|
177
|
-
assert name is not None, ident
|
|
178
|
-
|
|
179
|
-
# Update state.
|
|
180
|
-
self.header_ready = True
|
|
181
|
-
keep_going = True
|
|
182
|
-
else:
|
|
183
|
-
kind = self[name].type
|
|
184
|
-
data = self.event_fifo.pop(kind.size)
|
|
185
|
-
if data is not None:
|
|
186
|
-
yield ParsedEvent(
|
|
187
|
-
name,
|
|
188
|
-
cast(int, self.event_header["timestamp"]),
|
|
189
|
-
kind.decode(
|
|
190
|
-
data, byte_order=self.event_header.array.byte_order
|
|
191
|
-
),
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
# Update state.
|
|
195
|
-
self.header_ready = False
|
|
196
|
-
keep_going = True
|
|
@@ -11,6 +11,21 @@ tasks:
|
|
|
11
11
|
- {name: wave2, factory: sinusoid, period_s: 0.02}
|
|
12
12
|
- {name: wave3, factory: sinusoid, period_s: 0.03}
|
|
13
13
|
|
|
14
|
+
# Drive interactions with runtime entities that won't otherwise be polled.
|
|
15
|
+
- {name: app, factory: SampleApp, period_s: 0.25}
|
|
16
|
+
|
|
17
|
+
# UDP JSON clients.
|
|
18
|
+
clients:
|
|
19
|
+
- factory: udp_json
|
|
20
|
+
name: udp_json_client
|
|
21
|
+
defer: true
|
|
22
|
+
kwargs:
|
|
23
|
+
remote_addr: [localhost, "$udp_json"]
|
|
24
|
+
- factory: udp_json
|
|
25
|
+
name: udp_json_server
|
|
26
|
+
kwargs:
|
|
27
|
+
local_addr: [localhost, "$udp_json"]
|
|
28
|
+
|
|
14
29
|
# Add some sample structs.
|
|
15
30
|
structs:
|
|
16
31
|
- name: example.struct1
|
|
@@ -71,6 +71,8 @@ class TabInterface {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
updateChannelStyles(pattern) {
|
|
74
|
+
hash.handleChannelFilter(this.name, pattern);
|
|
75
|
+
|
|
74
76
|
if (!pattern) {
|
|
75
77
|
pattern = ".*";
|
|
76
78
|
}
|
|
@@ -96,6 +98,7 @@ class TabInterface {
|
|
|
96
98
|
} else {
|
|
97
99
|
curr += event.key;
|
|
98
100
|
}
|
|
101
|
+
|
|
99
102
|
this.updateChannelStyles(curr);
|
|
100
103
|
}
|
|
101
104
|
}
|
|
@@ -4,9 +4,11 @@ class WindowHashManager {
|
|
|
4
4
|
this.original = this.hash();
|
|
5
5
|
|
|
6
6
|
this.tab = "";
|
|
7
|
+
this.tabFilter = "";
|
|
7
8
|
this.tabsShown = true;
|
|
8
9
|
this.channelsShown = true;
|
|
9
10
|
this.plotChannels = {};
|
|
11
|
+
this.filters = {};
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
tabClick(event) {
|
|
@@ -29,6 +31,11 @@ class WindowHashManager {
|
|
|
29
31
|
this.update();
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
handleChannelFilter(tabName, value) {
|
|
35
|
+
this.filters[tabName] = value;
|
|
36
|
+
this.update();
|
|
37
|
+
}
|
|
38
|
+
|
|
32
39
|
handlePlotChannelToggle(tabName, channel, state) {
|
|
33
40
|
/* Service settings modal. */
|
|
34
41
|
if (modalManager) {
|
|
@@ -51,6 +58,29 @@ class WindowHashManager {
|
|
|
51
58
|
}
|
|
52
59
|
}
|
|
53
60
|
|
|
61
|
+
setTabFilter(value) {
|
|
62
|
+
this.tabFilter = value;
|
|
63
|
+
this.update();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
updateTabFilter(value) {
|
|
67
|
+
this.tabFilter = value;
|
|
68
|
+
if (tabFilter) {
|
|
69
|
+
tabFilter.input.value = value;
|
|
70
|
+
tabFilter.updateStyles(value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
setTabChannelFilter(tabName, value) {
|
|
75
|
+
this.filters[tabName] = value;
|
|
76
|
+
|
|
77
|
+
let elem = tabs[tabName].query("#channel-filter");
|
|
78
|
+
if (elem) {
|
|
79
|
+
elem.value = value;
|
|
80
|
+
tabs[tabName].updateChannelStyles(value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
54
84
|
clearPlotChannels(tabName) {
|
|
55
85
|
if (tabName in this.plotChannels) {
|
|
56
86
|
let channels = this.plotChannels[tabName];
|
|
@@ -85,7 +115,16 @@ class WindowHashManager {
|
|
|
85
115
|
for (let i = 1; i < boolsChannels.length; i++) {
|
|
86
116
|
let nameChannels = boolsChannels[i].split(":");
|
|
87
117
|
for (let chan of nameChannels[1].split(",")) {
|
|
88
|
-
|
|
118
|
+
if (!chan.includes("=")) {
|
|
119
|
+
/* Handle regular channel names. */
|
|
120
|
+
this.togglePlotChannel(nameChannels[0], chan);
|
|
121
|
+
} else {
|
|
122
|
+
/* Handle key-value pairs. */
|
|
123
|
+
let keyVal = chan.split("=");
|
|
124
|
+
if (keyVal.length == 2 && keyVal[0] == "filter" && keyVal[1]) {
|
|
125
|
+
this.setTabChannelFilter(nameChannels[0], keyVal[1]);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
89
128
|
}
|
|
90
129
|
}
|
|
91
130
|
|
|
@@ -95,6 +134,16 @@ class WindowHashManager {
|
|
|
95
134
|
if (split.includes("hide-channels")) {
|
|
96
135
|
channelsButton.click();
|
|
97
136
|
}
|
|
137
|
+
|
|
138
|
+
/* Check for tab filter. */
|
|
139
|
+
for (let item of split) {
|
|
140
|
+
if (item.includes("=")) {
|
|
141
|
+
let keyVal = item.split("=");
|
|
142
|
+
if (keyVal.length == 2 && keyVal[0] == "filter" && keyVal[1]) {
|
|
143
|
+
this.updateTabFilter(keyVal[1]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
98
147
|
}
|
|
99
148
|
}
|
|
100
149
|
|
|
@@ -109,6 +158,9 @@ class WindowHashManager {
|
|
|
109
158
|
update() {
|
|
110
159
|
let hash = this.tab;
|
|
111
160
|
|
|
161
|
+
if (this.tabFilter) {
|
|
162
|
+
hash += ",filter=" + this.tabFilter;
|
|
163
|
+
}
|
|
112
164
|
if (!this.tabsShown) {
|
|
113
165
|
hash += ",hide-tabs"
|
|
114
166
|
}
|
|
@@ -116,22 +168,40 @@ class WindowHashManager {
|
|
|
116
168
|
hash += ",hide-channels"
|
|
117
169
|
}
|
|
118
170
|
|
|
119
|
-
for (let tab in
|
|
171
|
+
for (let tab in tabs) {
|
|
120
172
|
let firstChan = true;
|
|
121
|
-
let channels = this.plotChannels[tab];
|
|
122
|
-
for (let name in channels) {
|
|
123
|
-
if (channels[name]) {
|
|
124
|
-
if (firstChan) {
|
|
125
|
-
hash += "/" + tab + ":"
|
|
126
|
-
firstChan = false;
|
|
127
|
-
}
|
|
128
173
|
|
|
129
|
-
|
|
130
|
-
|
|
174
|
+
/* Write plot channels if present. */
|
|
175
|
+
if (tab in this.plotChannels) {
|
|
176
|
+
let channels = this.plotChannels[tab];
|
|
177
|
+
|
|
178
|
+
for (let name in channels) {
|
|
179
|
+
if (channels[name]) {
|
|
180
|
+
if (firstChan) {
|
|
181
|
+
hash += "/" + tab + ":"
|
|
182
|
+
firstChan = false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (hash.slice(-1) != ":") {
|
|
186
|
+
hash += ",";
|
|
187
|
+
}
|
|
188
|
+
hash += name;
|
|
131
189
|
}
|
|
132
|
-
hash += name;
|
|
133
190
|
}
|
|
134
191
|
}
|
|
192
|
+
|
|
193
|
+
/* Write tab filter if present. */
|
|
194
|
+
if (tab in this.filters && this.filters[tab]) {
|
|
195
|
+
if (firstChan) {
|
|
196
|
+
hash += "/" + tab + ":"
|
|
197
|
+
firstChan = false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (hash.slice(-1) != ":") {
|
|
201
|
+
hash += ",";
|
|
202
|
+
}
|
|
203
|
+
hash += "filter=" + this.filters[tab];
|
|
204
|
+
}
|
|
135
205
|
}
|
|
136
206
|
|
|
137
207
|
window.location.hash = hash;
|
|
@@ -22,6 +22,8 @@ function worker_config(config) {
|
|
|
22
22
|
return worker_cfg;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
let tabFilter = undefined;
|
|
26
|
+
|
|
25
27
|
function bootstrap_init() {
|
|
26
28
|
/*
|
|
27
29
|
* Enable tooltips.
|
|
@@ -34,6 +36,6 @@ function bootstrap_init() {
|
|
|
34
36
|
/* Initialize tab filter. */
|
|
35
37
|
let tabs = document.getElementById("runtimepy-tabs");
|
|
36
38
|
if (tabs) {
|
|
37
|
-
|
|
39
|
+
tabFilter = new TabFilter(tabs);
|
|
38
40
|
}
|
|
39
41
|
}
|