runtimepy 5.5.0__tar.gz → 5.6.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.
- {runtimepy-5.5.0/runtimepy.egg-info → runtimepy-5.6.0}/PKG-INFO +4 -4
- {runtimepy-5.5.0 → runtimepy-5.6.0}/README.md +2 -2
- {runtimepy-5.5.0 → runtimepy-5.6.0}/pyproject.toml +1 -1
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/__init__.py +2 -2
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/server.py +35 -3
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/util.js +12 -3
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/tcp/__init__.py +1 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/__init__.py +21 -20
- runtimepy-5.6.0/runtimepy/net/ssl.py +33 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/connection.py +38 -7
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/create.py +2 -1
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/http/__init__.py +6 -1
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/websocket/connection.py +28 -6
- {runtimepy-5.5.0 → runtimepy-5.6.0/runtimepy.egg-info}/PKG-INFO +4 -4
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy.egg-info/SOURCES.txt +1 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/LICENSE +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/__main__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/app.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/array.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/command/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/command/parser.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/command/processor.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/command/result.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/create.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/file.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/sample.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/environment/telemetry.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/event/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/event/header.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/channel/registry.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/codec/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/codec/protocol/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/codec/protocol/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/codec/protocol/json.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/codec/system/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/all.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/arbiter.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/common.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/mtu.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/task.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/tftp.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/commands/tui.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/control/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/control/env/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/control/source.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/control/step.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/browser.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/css/bootstrap_extra.css +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/css/main.css +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/dummy_load.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/factories.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/favicon.ico +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/DataConnection.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/JsonConnection.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/audio.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/App.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/ChannelTable.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/DataConnection.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/JsonConnection.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/OverlayManager.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/Plot.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/PlotDrawer.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/PlotManager.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/PlotModalManager.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/PointBuffer.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/PointManager.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/TabFilter.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/TabInterface.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/UnitSystem.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/WindowHashManager.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/classes/WorkerInterface.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/events.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/init.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/main.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/tab/env.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/tab/sound.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/third-party/webgl-debug.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/unused/pyodide.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/js/worker.js +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/sample_telemetry.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/BitFields.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/Channel.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/ChannelCommand.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/ChannelRegistry.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/ClientConnectionConfig.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/ConnectionArbiterConfig.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/EnumRegistry.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/FindFile.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/PeerProcessConfig.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/RuntimeEnum.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/ServerConnectionConfig.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/StructConfig.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/TaskConfig.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/channel_controls.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/has_config.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/has_factory.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/has_name.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/schemas/has_request_flag.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/server.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/server_base.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/server_dev.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/data/tftp_server.yaml +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/dev_requirements.txt +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/entry.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/enum/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/enum/registry.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/enum/types.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mapping.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/message/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/message/handlers.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/message/interface.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/message/types.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/metrics/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/metrics/channel.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/metrics/connection.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/metrics/task.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/async_command.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/enum.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/environment.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/finalize.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/logging.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/psutil.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/regex.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/mixins/trig.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/apps/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/config/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/config/codec.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/config/util.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/factory/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/factory/connection.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/factory/task.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/housekeeping/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/imports/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/imports/util.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/info.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/result.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/struct/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/task.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/tcp/json.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/udp.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/arbiter/websocket.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/backoff.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/connection.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/factories/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/http/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/http/common.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/http/header.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/http/request_target.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/http/response.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/http/state.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/http/version.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/manager.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/mixin.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/mtu.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/bootstrap/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/bootstrap/elements.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/bootstrap/tabs.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/create.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/elements.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/modal.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/tab/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/tab/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/tab/controls.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/tab/html.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/tab/message.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/env/widgets.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/files.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/landing_page.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/placeholder.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/pyodide.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/sound.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/app/tab.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/html.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/json.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/struct/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/websocket/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/server/websocket/state.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/stream/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/stream/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/stream/json/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/stream/string.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/protocol.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/scpi/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/telnet/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/telnet/codes.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/tcp/telnet/np_05b.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/connection.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/create.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/protocol.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/queue.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/tftp/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/tftp/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/tftp/endpoint.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/tftp/enums.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/udp/tftp/io.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/util.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/net/websocket/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/noise/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/array/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/bool.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/byte_order.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/evaluation.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/field/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/field/fields.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/field/manager/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/field/manager/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/float.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/int.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/scaling.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/serializable/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/serializable/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/serializable/fixed.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/serializable/framer.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/serializable/prefixed.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/string.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/types/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/types/base.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/types/bool.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/types/bounds.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/types/float.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/primitives/types/int.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/py.typed +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/registry/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/registry/bool.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/registry/item.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/registry/name.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/requirements.txt +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/sample/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/sample/peer.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/sample/program.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/schemas.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/struct/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/subprocess/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/subprocess/interface.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/subprocess/peer.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/subprocess/program.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/subprocess/protocol.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/task/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/task/asynchronous.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/task/basic/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/task/basic/manager.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/task/basic/periodic.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/task/sample.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/task/trig/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/telemetry/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/telemetry/sample.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/tui/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/tui/channels/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/tui/cursor.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/tui/mixin.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/tui/mock.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/tui/task.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/ui/__init__.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/ui/controls.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy/util.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy.egg-info/dependency_links.txt +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy.egg-info/entry_points.txt +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy.egg-info/requires.txt +1 -1
- {runtimepy-5.5.0 → runtimepy-5.6.0}/runtimepy.egg-info/top_level.txt +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/setup.cfg +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/setup.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/tests/test_entry.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/tests/test_mapping.py +0 -0
- {runtimepy-5.5.0 → runtimepy-5.6.0}/tests/test_resources.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: runtimepy
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.6.0
|
|
4
4
|
Summary: A framework for implementing Python services.
|
|
5
5
|
Home-page: https://github.com/vkottler/runtimepy
|
|
6
6
|
Author: Vaughn Kottler
|
|
@@ -17,9 +17,9 @@ 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
21
|
Requires-Dist: websockets
|
|
21
22
|
Requires-Dist: svgen>=0.6.8
|
|
22
|
-
Requires-Dist: psutil
|
|
23
23
|
Requires-Dist: vcorelib>=3.3.1
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: pylint; 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=cd04f0ce079f8c60bc93c7f1d098316b
|
|
48
48
|
=====================================
|
|
49
49
|
-->
|
|
50
50
|
|
|
51
|
-
# runtimepy ([5.
|
|
51
|
+
# runtimepy ([5.6.0](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=cd04f0ce079f8c60bc93c7f1d098316b
|
|
6
6
|
=====================================
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
|
-
# runtimepy ([5.
|
|
9
|
+
# runtimepy ([5.6.0](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=6c21c41096ed57b6c6469232c97787cd
|
|
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.
|
|
13
|
+
VERSION = "5.6.0"
|
|
14
14
|
|
|
15
15
|
# runtimepy-specific content.
|
|
16
16
|
METRICS_NAME = "metrics"
|
|
@@ -14,6 +14,9 @@ from vcorelib.args import CommandFunction as _CommandFunction
|
|
|
14
14
|
from runtimepy.commands.arbiter import arbiter_cmd
|
|
15
15
|
from runtimepy.commands.common import FACTORIES, arbiter_args, cmd_with_jit
|
|
16
16
|
|
|
17
|
+
SSL_PASSTHROUGH = ["cafile", "capath", "cadata", "certfile"]
|
|
18
|
+
PASSTHROUGH = SSL_PASSTHROUGH + ["keyfile"]
|
|
19
|
+
|
|
17
20
|
|
|
18
21
|
def port_name(args: _Namespace, port: str = "port") -> str:
|
|
19
22
|
"""Get the name for a connection factory's port."""
|
|
@@ -25,7 +28,7 @@ def server_data(args: _Namespace) -> dict[str, Any]:
|
|
|
25
28
|
|
|
26
29
|
return {
|
|
27
30
|
"factory": args.factory,
|
|
28
|
-
"kwargs":
|
|
31
|
+
"kwargs": get_kwargs(args, port=f"${port_name(args)}", host=args.host),
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
|
|
@@ -34,6 +37,26 @@ def is_websocket(args: _Namespace) -> bool:
|
|
|
34
37
|
return "websocket" in args.factory.lower()
|
|
35
38
|
|
|
36
39
|
|
|
40
|
+
def is_ssl(kwargs: dict[str, Any]) -> bool:
|
|
41
|
+
"""Determine if server arugments indicate SSL use."""
|
|
42
|
+
return any(x in kwargs for x in SSL_PASSTHROUGH)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_kwargs(args: _Namespace, **kwargs) -> dict[str, Any]:
|
|
46
|
+
"""Get boilerplate kwargs."""
|
|
47
|
+
|
|
48
|
+
new_kwargs: dict[str, Any] = {**kwargs}
|
|
49
|
+
|
|
50
|
+
# Pass additional arguments through.
|
|
51
|
+
print(args)
|
|
52
|
+
for opt in PASSTHROUGH:
|
|
53
|
+
value = getattr(args, opt, None)
|
|
54
|
+
if value is not None:
|
|
55
|
+
new_kwargs[opt] = value
|
|
56
|
+
|
|
57
|
+
return new_kwargs
|
|
58
|
+
|
|
59
|
+
|
|
37
60
|
def client_data(args: _Namespace) -> dict[str, Any]:
|
|
38
61
|
"""Get client data based on command-line arguments."""
|
|
39
62
|
|
|
@@ -43,7 +66,9 @@ def client_data(args: _Namespace) -> dict[str, Any]:
|
|
|
43
66
|
kwargs: dict[str, Any] = {}
|
|
44
67
|
|
|
45
68
|
if is_websocket(args):
|
|
46
|
-
arg_list.append(
|
|
69
|
+
arg_list.append(
|
|
70
|
+
f"ws{'s' if is_ssl(get_kwargs(args)) else ''}://localhost:{port}"
|
|
71
|
+
)
|
|
47
72
|
elif not args.udp:
|
|
48
73
|
kwargs["host"] = "localhost"
|
|
49
74
|
kwargs["port"] = port
|
|
@@ -76,7 +101,9 @@ def config_data(args: _Namespace) -> dict[str, Any]:
|
|
|
76
101
|
{
|
|
77
102
|
"name": port_name(args, port="server"),
|
|
78
103
|
"factory": args.factory,
|
|
79
|
-
"kwargs":
|
|
104
|
+
"kwargs": get_kwargs(
|
|
105
|
+
args, local_addr=["0.0.0.0", f"${port_name(args)}"]
|
|
106
|
+
),
|
|
80
107
|
}
|
|
81
108
|
)
|
|
82
109
|
|
|
@@ -108,6 +135,11 @@ def add_server_cmd(parser: _ArgumentParser) -> _CommandFunction:
|
|
|
108
135
|
"""Add server-command arguments to its parser."""
|
|
109
136
|
|
|
110
137
|
with arbiter_args(parser, nargs="*"):
|
|
138
|
+
for optional in PASSTHROUGH:
|
|
139
|
+
parser.add_argument(
|
|
140
|
+
f"--{optional}", help="passed directly to instantiation"
|
|
141
|
+
)
|
|
142
|
+
|
|
111
143
|
parser.add_argument(
|
|
112
144
|
"--host",
|
|
113
145
|
default="0.0.0.0",
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
function worker_config(config) {
|
|
2
2
|
let worker_cfg = {};
|
|
3
3
|
|
|
4
|
+
let port_name = "runtimepy_websocket";
|
|
5
|
+
let uri_prefix = "ws";
|
|
6
|
+
|
|
7
|
+
/* Ensured TLS is handled properly. */
|
|
8
|
+
if (location.protocol.includes("https")) {
|
|
9
|
+
port_name = "runtimepy_secure_websocket";
|
|
10
|
+
uri_prefix += "s";
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
/* Look for connections to establish. */
|
|
5
14
|
let ports = config["config"]["ports"];
|
|
6
15
|
for (let port_idx in ports) {
|
|
@@ -10,11 +19,11 @@ function worker_config(config) {
|
|
|
10
19
|
let hostname = window.location.hostname;
|
|
11
20
|
|
|
12
21
|
/* This business logic could use some work. */
|
|
13
|
-
if (port["name"].includes(
|
|
22
|
+
if (port["name"].includes(port_name)) {
|
|
14
23
|
if (port["name"].includes("data")) {
|
|
15
|
-
worker_cfg["data"] =
|
|
24
|
+
worker_cfg["data"] = `${uri_prefix}://${hostname}:` + port["port"];
|
|
16
25
|
} else {
|
|
17
|
-
worker_cfg["json"] =
|
|
26
|
+
worker_cfg["json"] = `${uri_prefix}://${hostname}:` + port["port"];
|
|
18
27
|
}
|
|
19
28
|
}
|
|
20
29
|
}
|
|
@@ -27,26 +27,27 @@ async def launch_browser(app: AppInfo) -> None:
|
|
|
27
27
|
"""
|
|
28
28
|
|
|
29
29
|
# Launch browser based on config option.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
30
|
+
for prefix in ["http", "https"]:
|
|
31
|
+
if config_param(app, f"xdg_open_{prefix}", False):
|
|
32
|
+
|
|
33
|
+
port: Any
|
|
34
|
+
for port in app.config["root"]["ports"]: # type: ignore
|
|
35
|
+
if f"{prefix}_server" in port["name"]:
|
|
36
|
+
# URI parameters.
|
|
37
|
+
hostname = config_param(app, "xdg_host", "localhost")
|
|
38
|
+
|
|
39
|
+
# Assemble URI.
|
|
40
|
+
uri = f"{prefix}://{hostname}:{port['port']}/"
|
|
41
|
+
|
|
42
|
+
# Add a fragment if one was specified.
|
|
43
|
+
fragment = config_param(app, "xdg_fragment", "")
|
|
44
|
+
if fragment:
|
|
45
|
+
uri += "#" + fragment
|
|
46
|
+
|
|
47
|
+
with suppress(FileNotFoundError):
|
|
48
|
+
await app.stack.enter_async_context(
|
|
49
|
+
spawn_exec("xdg-open", uri)
|
|
50
|
+
)
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
# Could add an interface for adding multiple applications.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A module implementing SSL-related interfaces.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# built-in
|
|
6
|
+
import ssl
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def handle_possible_ssl(client: bool = True, **kwargs) -> dict[str, Any]:
|
|
11
|
+
"""Handle creating an SSL context based on keyword arguments."""
|
|
12
|
+
|
|
13
|
+
args = ["cafile", "capath", "cadata"]
|
|
14
|
+
if (
|
|
15
|
+
kwargs.pop("use_ssl", False)
|
|
16
|
+
or any(x in kwargs for x in args)
|
|
17
|
+
or "certfile" in kwargs
|
|
18
|
+
):
|
|
19
|
+
context = ssl.create_default_context(
|
|
20
|
+
purpose=(
|
|
21
|
+
ssl.Purpose.SERVER_AUTH if client else ssl.Purpose.CLIENT_AUTH
|
|
22
|
+
),
|
|
23
|
+
**{x: kwargs.pop(x, None) for x in args},
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if "certfile" in kwargs:
|
|
27
|
+
context.load_cert_chain(
|
|
28
|
+
kwargs.pop("certfile"), keyfile=kwargs.pop("keyfile", None)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
kwargs["ssl"] = context
|
|
32
|
+
|
|
33
|
+
return kwargs
|
|
@@ -27,6 +27,7 @@ from runtimepy.net.connection import EchoConnection as _EchoConnection
|
|
|
27
27
|
from runtimepy.net.connection import NullConnection as _NullConnection
|
|
28
28
|
from runtimepy.net.manager import ConnectionManager as _ConnectionManager
|
|
29
29
|
from runtimepy.net.mixin import TransportMixin as _TransportMixin
|
|
30
|
+
from runtimepy.net.ssl import handle_possible_ssl
|
|
30
31
|
from runtimepy.net.tcp.create import (
|
|
31
32
|
TcpTransportProtocol,
|
|
32
33
|
tcp_transport_protocol_backoff,
|
|
@@ -70,6 +71,20 @@ class TcpConnection(_Connection, _TransportMixin):
|
|
|
70
71
|
self._protocol = protocol
|
|
71
72
|
self._protocol.conn = self
|
|
72
73
|
|
|
74
|
+
@classmethod
|
|
75
|
+
def get_log_prefix(cls, is_ssl: bool = False) -> str:
|
|
76
|
+
"""Get a logging prefix for this instance."""
|
|
77
|
+
|
|
78
|
+
# Default implementation doesn't handle this.
|
|
79
|
+
del is_ssl
|
|
80
|
+
|
|
81
|
+
return cls.log_prefix
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def is_ssl(self) -> bool:
|
|
85
|
+
"""Determine if this connection uses SSL."""
|
|
86
|
+
return self._transport.get_extra_info("sslcontext") is not None
|
|
87
|
+
|
|
73
88
|
async def _await_message(self) -> _Optional[_Union[_BinaryMessage, str]]:
|
|
74
89
|
"""Await the next message. Return None on error or failure."""
|
|
75
90
|
|
|
@@ -142,18 +157,24 @@ class TcpConnection(_Connection, _TransportMixin):
|
|
|
142
157
|
callback(self.conn)
|
|
143
158
|
|
|
144
159
|
eloop = _get_event_loop()
|
|
160
|
+
|
|
161
|
+
server_kwargs = handle_possible_ssl(client=False, **kwargs)
|
|
162
|
+
is_ssl = "ssl" in server_kwargs
|
|
145
163
|
server = await eloop.create_server(
|
|
146
|
-
CallbackProtocol,
|
|
164
|
+
CallbackProtocol,
|
|
165
|
+
family=_socket.AF_INET,
|
|
166
|
+
**server_kwargs,
|
|
147
167
|
)
|
|
148
168
|
async with server:
|
|
149
169
|
for socket in server.sockets:
|
|
150
170
|
sockname = socket.getsockname()
|
|
151
171
|
LOG.info(
|
|
152
|
-
"Started %s server listening on '%s%s' (%s%s:%d).",
|
|
172
|
+
"Started %s%s server listening on '%s%s' (%s%s:%d).",
|
|
173
|
+
"secure " if is_ssl else "",
|
|
153
174
|
cls.log_alias,
|
|
154
|
-
cls.
|
|
175
|
+
cls.get_log_prefix(is_ssl=is_ssl),
|
|
155
176
|
_sockname(socket),
|
|
156
|
-
cls.
|
|
177
|
+
cls.get_log_prefix(is_ssl=is_ssl),
|
|
157
178
|
sockname[0] if sockname[0] != "0.0.0.0" else "localhost",
|
|
158
179
|
sockname[1],
|
|
159
180
|
)
|
|
@@ -193,7 +214,10 @@ class TcpConnection(_Connection, _TransportMixin):
|
|
|
193
214
|
@classmethod
|
|
194
215
|
@_asynccontextmanager
|
|
195
216
|
async def create_pair(
|
|
196
|
-
cls: type[T],
|
|
217
|
+
cls: type[T],
|
|
218
|
+
peer: type[V] = None,
|
|
219
|
+
serve_kwargs: dict[str, _Any] = None,
|
|
220
|
+
connect_kwargs: dict[str, _Any] = None,
|
|
197
221
|
) -> _AsyncIterator[tuple[V, T]]:
|
|
198
222
|
"""Create a connection pair."""
|
|
199
223
|
|
|
@@ -212,13 +236,20 @@ class TcpConnection(_Connection, _TransportMixin):
|
|
|
212
236
|
peer = cls # type: ignore
|
|
213
237
|
assert peer is not None
|
|
214
238
|
|
|
239
|
+
if serve_kwargs is None:
|
|
240
|
+
serve_kwargs = {}
|
|
241
|
+
|
|
215
242
|
server = await stack.enter_async_context(
|
|
216
|
-
peer.serve(callback, port=0, backlog=1)
|
|
243
|
+
peer.serve(callback, port=0, backlog=1, **serve_kwargs)
|
|
217
244
|
)
|
|
218
245
|
|
|
219
246
|
host = server.sockets[0].getsockname()
|
|
247
|
+
|
|
248
|
+
if connect_kwargs is None:
|
|
249
|
+
connect_kwargs = {}
|
|
250
|
+
|
|
220
251
|
client = await cls.create_connection(
|
|
221
|
-
host="localhost", port=host[1]
|
|
252
|
+
host="localhost", port=host[1], **connect_kwargs
|
|
222
253
|
)
|
|
223
254
|
await cond.acquire()
|
|
224
255
|
|
|
@@ -11,6 +11,7 @@ from typing import Callable, Optional
|
|
|
11
11
|
|
|
12
12
|
# internal
|
|
13
13
|
from runtimepy.net.backoff import ExponentialBackoff
|
|
14
|
+
from runtimepy.net.ssl import handle_possible_ssl
|
|
14
15
|
from runtimepy.net.tcp.protocol import QueueProtocol
|
|
15
16
|
from runtimepy.net.util import try_log_connection_error
|
|
16
17
|
|
|
@@ -26,7 +27,7 @@ async def tcp_transport_protocol(**kwargs) -> TcpTransportProtocol:
|
|
|
26
27
|
|
|
27
28
|
transport: _Transport
|
|
28
29
|
transport, protocol = await _asyncio.get_event_loop().create_connection(
|
|
29
|
-
QueueProtocol, **kwargs
|
|
30
|
+
QueueProtocol, **handle_possible_ssl(**kwargs)
|
|
30
31
|
)
|
|
31
32
|
return transport, protocol
|
|
32
33
|
|
|
@@ -58,7 +58,6 @@ class HttpConnection(_TcpConnection):
|
|
|
58
58
|
expecting_response: bool
|
|
59
59
|
|
|
60
60
|
log_alias = "HTTP"
|
|
61
|
-
log_prefix = "http://"
|
|
62
61
|
|
|
63
62
|
# Handlers registered at the class level so that instances created at
|
|
64
63
|
# runtime don't need additional initialization.
|
|
@@ -79,6 +78,12 @@ class HttpConnection(_TcpConnection):
|
|
|
79
78
|
self.handlers[http.HTTPMethod.GET] = self.get_handler
|
|
80
79
|
self.handlers[http.HTTPMethod.POST] = self.post_handler
|
|
81
80
|
|
|
81
|
+
@classmethod
|
|
82
|
+
def get_log_prefix(cls, is_ssl: bool = False) -> str:
|
|
83
|
+
"""Get a logging prefix for this instance."""
|
|
84
|
+
|
|
85
|
+
return f"http{'s' if is_ssl else ''}://"
|
|
86
|
+
|
|
82
87
|
async def get_handler(
|
|
83
88
|
self,
|
|
84
89
|
response: ResponseHeader,
|
|
@@ -10,6 +10,7 @@ from contextlib import AsyncExitStack as _AsyncExitStack
|
|
|
10
10
|
from contextlib import asynccontextmanager as _asynccontextmanager
|
|
11
11
|
from contextlib import suppress as _suppress
|
|
12
12
|
from logging import getLogger as _getLogger
|
|
13
|
+
from typing import Any as _Any
|
|
13
14
|
from typing import AsyncIterator as _AsyncIterator
|
|
14
15
|
from typing import Awaitable as _Awaitable
|
|
15
16
|
from typing import Callable as _Callable
|
|
@@ -36,6 +37,7 @@ from runtimepy.net.connection import BinaryMessage, Connection
|
|
|
36
37
|
from runtimepy.net.connection import EchoConnection as _EchoConnection
|
|
37
38
|
from runtimepy.net.connection import NullConnection as _NullConnection
|
|
38
39
|
from runtimepy.net.manager import ConnectionManager as _ConnectionManager
|
|
40
|
+
from runtimepy.net.ssl import handle_possible_ssl
|
|
39
41
|
|
|
40
42
|
T = _TypeVar("T", bound="WebsocketConnection")
|
|
41
43
|
ConnectionInit = _Callable[[T], _Awaitable[bool]]
|
|
@@ -93,7 +95,11 @@ class WebsocketConnection(Connection):
|
|
|
93
95
|
async def create_connection(cls: type[T], uri: str, **kwargs) -> T:
|
|
94
96
|
"""Connect a client to an endpoint."""
|
|
95
97
|
|
|
96
|
-
|
|
98
|
+
kwargs.setdefault("use_ssl", uri.startswith("wss"))
|
|
99
|
+
|
|
100
|
+
protocol = await getattr(websockets, "connect")(
|
|
101
|
+
uri, **handle_possible_ssl(**kwargs)
|
|
102
|
+
)
|
|
97
103
|
return cls(protocol)
|
|
98
104
|
|
|
99
105
|
@classmethod
|
|
@@ -101,7 +107,11 @@ class WebsocketConnection(Connection):
|
|
|
101
107
|
async def client(cls: type[T], uri: str, **kwargs) -> _AsyncIterator[T]:
|
|
102
108
|
"""A wrapper for connecting a client."""
|
|
103
109
|
|
|
104
|
-
|
|
110
|
+
kwargs.setdefault("use_ssl", uri.startswith("wss"))
|
|
111
|
+
|
|
112
|
+
async with getattr(websockets, "connect")(
|
|
113
|
+
uri, **handle_possible_ssl(**kwargs)
|
|
114
|
+
) as protocol:
|
|
105
115
|
yield cls(protocol)
|
|
106
116
|
|
|
107
117
|
@classmethod
|
|
@@ -154,7 +164,9 @@ class WebsocketConnection(Connection):
|
|
|
154
164
|
|
|
155
165
|
@classmethod
|
|
156
166
|
@_asynccontextmanager
|
|
157
|
-
async def create_pair(
|
|
167
|
+
async def create_pair(
|
|
168
|
+
cls: type[T], serve_kwargs: dict[str, _Any] = None
|
|
169
|
+
) -> _AsyncIterator[tuple[T, T]]:
|
|
158
170
|
"""Obtain a connected pair of WebsocketConnection objects."""
|
|
159
171
|
|
|
160
172
|
server_conn: _Optional[T] = None
|
|
@@ -167,15 +179,21 @@ class WebsocketConnection(Connection):
|
|
|
167
179
|
return True
|
|
168
180
|
|
|
169
181
|
async with _AsyncExitStack() as stack:
|
|
182
|
+
if serve_kwargs is None:
|
|
183
|
+
serve_kwargs = {}
|
|
184
|
+
|
|
185
|
+
serve_kwargs = handle_possible_ssl(client=False, **serve_kwargs)
|
|
186
|
+
is_ssl = "ssl" in serve_kwargs
|
|
187
|
+
|
|
170
188
|
# Start a server.
|
|
171
189
|
server = await stack.enter_async_context(
|
|
172
|
-
_serve(server_init, host="0.0.0.0", port=0)
|
|
190
|
+
_serve(server_init, host="0.0.0.0", port=0, **serve_kwargs)
|
|
173
191
|
)
|
|
174
192
|
|
|
175
193
|
host = list(server.sockets)[0].getsockname()
|
|
176
194
|
|
|
177
195
|
client_conn = await stack.enter_async_context(
|
|
178
|
-
cls.client(f"ws://localhost:{host[1]}")
|
|
196
|
+
cls.client(f"ws{'s' if is_ssl else ''}://localhost:{host[1]}")
|
|
179
197
|
)
|
|
180
198
|
|
|
181
199
|
# Connect a client and yield both sides of the connection.
|
|
@@ -193,13 +211,17 @@ class WebsocketConnection(Connection):
|
|
|
193
211
|
) -> _AsyncIterator[_WebSocketServer]:
|
|
194
212
|
"""Serve a WebSocket server."""
|
|
195
213
|
|
|
214
|
+
kwargs = handle_possible_ssl(client=False, **kwargs)
|
|
215
|
+
is_ssl = "ssl" in kwargs
|
|
216
|
+
|
|
196
217
|
async with _serve(
|
|
197
218
|
cls.server_handler(init=init, stop_sig=stop_sig, manager=manager),
|
|
198
219
|
**kwargs,
|
|
199
220
|
) as server:
|
|
200
221
|
for socket in server.sockets:
|
|
201
222
|
LOG.info(
|
|
202
|
-
"Started WebSocket server listening on '%s'.",
|
|
223
|
+
"Started WebSocket server listening on 'ws%s://%s'.",
|
|
224
|
+
"s" if is_ssl else "",
|
|
203
225
|
_sockname(socket),
|
|
204
226
|
)
|
|
205
227
|
yield server
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: runtimepy
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.6.0
|
|
4
4
|
Summary: A framework for implementing Python services.
|
|
5
5
|
Home-page: https://github.com/vkottler/runtimepy
|
|
6
6
|
Author: Vaughn Kottler
|
|
@@ -17,9 +17,9 @@ 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
21
|
Requires-Dist: websockets
|
|
21
22
|
Requires-Dist: svgen>=0.6.8
|
|
22
|
-
Requires-Dist: psutil
|
|
23
23
|
Requires-Dist: vcorelib>=3.3.1
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: pylint; 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=cd04f0ce079f8c60bc93c7f1d098316b
|
|
48
48
|
=====================================
|
|
49
49
|
-->
|
|
50
50
|
|
|
51
|
-
# runtimepy ([5.
|
|
51
|
+
# runtimepy ([5.6.0](https://pypi.org/project/runtimepy/))
|
|
52
52
|
|
|
53
53
|
[](https://pypi.org/project/runtimepy/)
|
|
54
54
|

|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|