pycontrol-core 3.0.0b2__tar.gz → 3.0.0b3__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.
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/PKG-INFO +1 -1
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/changelog.md +7 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/public-api.md +10 -5
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/task-handlers.md +10 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/__init__.py +1 -1
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/addons/__init__.py +5 -1
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bus/__init__.py +3 -1
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bus/status.py +50 -2
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/framework.py +1 -1
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_status_fields.py +15 -1
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/.complexipy_cache/.gitignore +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/.complexipy_cache/CACHEDIR.TAG +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/.complexipy_cache/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/.complexipy_cache/v/cache/functions +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/.gitignore +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/.pre-commit-config.yaml +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/.python-version +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/CONTRIBUTING.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/LICENSE.txt +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/addon-settings.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/architecture.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/cli-reference.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/contracts.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/core-walkthrough.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/data-format.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/design-history/simplified-pycontrol-provenance-and-sharing-motivation.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/design-history/simplified-pycontrol-provenance-and-sharing-plan.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/experiment-handlers.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/getting-started.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/hardware-definitions.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/maintainability.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/migration-from-official.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/release-acceptance.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/sharing.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/subscriber-api.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/testing.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/threading-and-state.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/troubleshooting.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/wire-protocol.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/docs/writing-tasks.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/pyproject.toml +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/addons/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/addons/controls_context.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/addons/experiment_api.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/addons/loader.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/addons/task_api.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/analysis/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/analysis/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/analysis/data_import.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bundles/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bundles/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bundles/collect.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bundles/models.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bundles/protocol.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bundles/run.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bundles/zipio.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bus/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bus/events.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/bus/subscriber.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/board.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/board_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/common.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/data.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/data_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/experiment.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/experiment_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/firmware.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/firmware_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/gui.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/gui_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/run.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/run_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/setups.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/setups_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/vars.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/vars_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/workspace.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/workspace_impl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/main.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/config/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/config/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/config/io.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/config/models.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/hooks.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/models.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/planning.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/run.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/run_recording.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/experiment/supervisor.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/device_helpers.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/LED_driver.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/MCP.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/VL53L4.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/analog_LED.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/audio_board.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/audio_player.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/breakout_10port_r0_4_h7.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/breakout_10port_r0_8_h7.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/breakout_6port_r0_1_h7.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/breakout_6port_r0_2_h7.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/breakout_6port_r1_2_f4.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/five_poke.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/frame_logger.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/frame_trigger.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/grid_maze.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/lickometer.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/load_cell.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/nine_poke.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/poke.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/port_expander.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/rotary_encoder.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/schmitt_trigger.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/solenoid_driver.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/stepper_motor.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/uRFID.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/uart_handler.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/audio.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/hardware.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/profiles.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/state_machine.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/timer.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/utility.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/fsutil.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/_queue.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/notify/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/notify/slack.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/notify/telegram.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/mcu.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/protocol/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/protocol/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/protocol/analog.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/protocol/decoder.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/protocol/encoder.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/protocol/messages.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/provenance/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/provenance/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/provenance/archive.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/provenance/collect.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/provenance/hashing.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/provenance/models.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/provenance/source.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/recording/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/recording/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/recording/analog_writer.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/recording/console.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/recording/event_rows.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/recording/native_event_logger.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/repl/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/repl/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/repl/device_helpers.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/repl/file_transfer.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/repl/json_repl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/repl/raw_repl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/board_session.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/device_resolution.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/info.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/link.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/phases.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/protocols.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/pump.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/rows.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/services/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/services/firmware.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/services/maintenance.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/services/setup.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/services/sync.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/types.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/session/variables.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/testing/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/testing/fake_board.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/testing/frames.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/transport/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/transport/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/transport/base.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/transport/mock.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/transport/replay.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/transport/serial.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace/creation.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace/hwdef_inspect.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace/task_inspect.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/controls/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/controls/blinker_gui.json +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/controls/example_dialog.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/experiment_handlers/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/experiment_handlers/notion_logger.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/experiment_handlers/s3_data_exporter.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/plotters/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/task_handlers/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/task_handlers/example_handler.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/task_handlers/run_notify.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/addons/task_handlers/trial_summary.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/devices/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/devices/example_device.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/experiments/blink_demo.json +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/settings.json +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/setups.json +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/workspace_template/tasks/examples/blinker-pattern-h7.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/CLASSIFICATION.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/contracts/test_wire_contract.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/firmware_stubs/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/firmware_stubs/machine.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/firmware_stubs/micropython.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/firmware_stubs/pyb.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/firmware_stubs/ucollections.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/firmware_stubs/ujson.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/frames/blinker_real.in.bin +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/frames/blinker_real.out.bin +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/frames/counter_demo_real.in.bin +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/frames/counter_demo_real.out.bin +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/frames/encoder_real.in.bin +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/frames/encoder_real.out.bin +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/replay.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/blinker_real.meta.json +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/blinker_real.tsv +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/counter_demo_real.meta.json +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/counter_demo_real.tsv +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/encoder_real.meta.json +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/encoder_real.tsv +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/encoder_real_encoder.data.npy +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/sessions/encoder_real_encoder.time.npy +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/tasks/blinker_real.task.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/tasks/counter_demo_real.task.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/golden/tasks/encoder_real.task.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/integration/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/integration/test_board_session.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/integration/test_cli_workspace.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/integration/test_experiment_runner.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/integration/test_real_hardware_replay.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/integration/test_repl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/integration/test_run.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/__init__.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/conftest.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_analog_trigger_variables.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_audio.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_breakout_qwiic.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_device_helpers.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_devices_init.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_hardware_uses_profile.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_profiles.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_rotary_encoder.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_run_sequence.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_schmitt_trigger_threshold.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_state_machine_variables.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_timer_rounding.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_utility_log.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/firmware/test_vl53l4.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_addons.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_analysis_data_import.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_board_link.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_bundles_collect.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_bus_subscriber.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_cli.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_cli_setups.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_config_models.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_device_resolution.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_device_table_consistency.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_experiment_hook_sequencer.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_experiment_planning.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_file_transfer_errors.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_firmware_root.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_firmware_service.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_firmware_status.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_integrations_notify.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_maintenance_service.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_phases.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_protocol_decoder.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_protocol_encoder.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_provenance.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_public_api.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_raw_repl.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_recording.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_run_bundle_format.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_run_data_durability.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_run_recovery.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_serial_transport.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_session_pump.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_session_rows.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_session_variables.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_setup_identity.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_subject_id.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_supervisor_join.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_transport_mock.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_workspace.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_workspace_hwdef_inspect.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tests/unit/test_workspace_template.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tools/README.md +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tools/capture_fixtures.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tools/hardware_acceptance.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tools/maintainability_metrics.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/tools/run_tests.py +0 -0
- {pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/uv.lock +0 -0
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
### Styled status text
|
|
6
|
+
|
|
7
|
+
- `TaskHandler.update_status(...)` accepts a `StyledText(*parts)` value, drawn
|
|
8
|
+
as text whose `Span(text, color=None, bold=False)` parts are coloured or bold.
|
|
9
|
+
Its `StatusField` has `kind == "styled"` and the spans in the new `spans`
|
|
10
|
+
attribute; `value` is still the plain text.
|
|
11
|
+
|
|
5
12
|
### Breakout naming
|
|
6
13
|
|
|
7
14
|
- Breakout filenames and classes now identify port count, PCB revision, and
|
|
@@ -39,7 +39,9 @@ from pycontrol.addons import (
|
|
|
39
39
|
Log,
|
|
40
40
|
Print,
|
|
41
41
|
Progress,
|
|
42
|
+
Span,
|
|
42
43
|
State,
|
|
44
|
+
StyledText,
|
|
43
45
|
TaskHandler,
|
|
44
46
|
Var,
|
|
45
47
|
)
|
|
@@ -47,8 +49,9 @@ from pycontrol.addons import (
|
|
|
47
49
|
|
|
48
50
|
See `docs/task-handlers.md`. A task handler publishes frontend status with
|
|
49
51
|
`update_status(...)` (a mapping of labels to values, where a `Progress` value
|
|
50
|
-
draws a bar
|
|
51
|
-
|
|
52
|
+
draws a bar and a `StyledText` value draws coloured or bold `Span`s) and
|
|
53
|
+
reports problems with the diagnostics helpers; it does not reach into the
|
|
54
|
+
subscriber registry. Its `set_variable()` and `trigger_event()`
|
|
52
55
|
are recorded with source `task_handler`.
|
|
53
56
|
|
|
54
57
|
### Experiment handlers
|
|
@@ -109,6 +112,7 @@ from pycontrol.bus import (
|
|
|
109
112
|
SessionEnded,
|
|
110
113
|
SessionEndReason,
|
|
111
114
|
SessionStarted,
|
|
115
|
+
Span,
|
|
112
116
|
StatusField,
|
|
113
117
|
Subscriber,
|
|
114
118
|
TaskStatusUpdated,
|
|
@@ -126,10 +130,11 @@ A subscriber implements any of `on_session_start`, `on_data`,
|
|
|
126
130
|
`TaskStatusUpdated` is emitted by host-side task handlers through
|
|
127
131
|
`TaskHandler.update_status(...)` and forwarded through the normal subscriber
|
|
128
132
|
registry. Its `fields` are `StatusField` records (`label`, `value`, `kind`,
|
|
129
|
-
`fraction`, `fill_color`, `text_color`). `value` is always a display string, so a
|
|
133
|
+
`fraction`, `fill_color`, `text_color`, `spans`). `value` is always a display string, so a
|
|
130
134
|
consumer that only handles `kind == "text"` renders every field correctly; a
|
|
131
|
-
field is `kind == "progress"` when the task handler passed a `Progress` value
|
|
132
|
-
`
|
|
135
|
+
field is `kind == "progress"` when the task handler passed a `Progress` value,
|
|
136
|
+
and `kind == "styled"`, with its `Span`s in `spans`, for a `StyledText` value.
|
|
137
|
+
`clean_color` is the colour check frontends apply before styling a bar or span.
|
|
133
138
|
|
|
134
139
|
`SessionEnded.reason` (a `SessionEndReason` literal: `"stopped"`,
|
|
135
140
|
`"task_ended"`, `"task_error"`, `"connection_lost"`, `"pump_crashed"`) is the
|
|
@@ -214,6 +214,16 @@ class WaterBudget(TaskHandler):
|
|
|
214
214
|
})
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
+
A `StyledText` value is drawn as text with coloured or bold runs. Each part is a
|
|
218
|
+
plain string or a `Span(text, color=None, bold=False)`, with colours checked like
|
|
219
|
+
`Progress`'s:
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from pycontrol.addons import Span, StyledText
|
|
223
|
+
|
|
224
|
+
self.update_status({"Side": StyledText("last: ", Span("L", color="#FF9A00", bold=True))})
|
|
225
|
+
```
|
|
226
|
+
|
|
217
227
|
Every field also carries a plain display string, so a frontend that only renders
|
|
218
228
|
text still shows the value, and the run bundle records `label: "0.75 / 1.50 mL"`
|
|
219
229
|
either way.
|
|
@@ -5,6 +5,8 @@ A minimal, Qt-free contract for user code to plug into a session:
|
|
|
5
5
|
- :class:`TaskHandler` -- subscriber base that converts native row batches
|
|
6
6
|
into ergonomic ``State``/``Event``/``Var``/``Analog`` namedtuples.
|
|
7
7
|
- :class:`Progress` -- a live status value a frontend draws as a progress bar.
|
|
8
|
+
- :class:`StyledText` and :class:`Span` -- a live status value drawn as text
|
|
9
|
+
with coloured or bold runs.
|
|
8
10
|
- :class:`ExperimentHandler` -- host-side experiment lifecycle callbacks.
|
|
9
11
|
- :class:`TaskControlsContext` -- Qt-free runtime API passed to custom task
|
|
10
12
|
controls built by a frontend.
|
|
@@ -29,7 +31,7 @@ from pycontrol.addons.loader import (
|
|
|
29
31
|
loaded_module_for_path,
|
|
30
32
|
)
|
|
31
33
|
from pycontrol.addons.task_api import Analog, Event, Log, Print, State, TaskHandler, Var
|
|
32
|
-
from pycontrol.bus.status import Progress
|
|
34
|
+
from pycontrol.bus.status import Progress, Span, StyledText
|
|
33
35
|
|
|
34
36
|
__all__ = [
|
|
35
37
|
"AddonDiscoveryFailure",
|
|
@@ -40,7 +42,9 @@ __all__ = [
|
|
|
40
42
|
"Log",
|
|
41
43
|
"Print",
|
|
42
44
|
"Progress",
|
|
45
|
+
"Span",
|
|
43
46
|
"State",
|
|
47
|
+
"StyledText",
|
|
44
48
|
"TaskControlsContext",
|
|
45
49
|
"TaskControlsDefinition",
|
|
46
50
|
"TaskControlsWidgetBuilder",
|
|
@@ -16,7 +16,7 @@ from pycontrol.bus.events import (
|
|
|
16
16
|
TaskStatusUpdated,
|
|
17
17
|
Warning,
|
|
18
18
|
)
|
|
19
|
-
from pycontrol.bus.status import Progress, StatusField, clean_color, normalise_status_fields
|
|
19
|
+
from pycontrol.bus.status import Progress, Span, StatusField, StyledText, clean_color, normalise_status_fields
|
|
20
20
|
from pycontrol.bus.subscriber import Subscriber, SubscriberRegistry
|
|
21
21
|
|
|
22
22
|
__all__ = [
|
|
@@ -28,7 +28,9 @@ __all__ = [
|
|
|
28
28
|
"SessionEndReason",
|
|
29
29
|
"SessionEnded",
|
|
30
30
|
"SessionStarted",
|
|
31
|
+
"Span",
|
|
31
32
|
"StatusField",
|
|
33
|
+
"StyledText",
|
|
32
34
|
"Subscriber",
|
|
33
35
|
"SubscriberRegistry",
|
|
34
36
|
"TaskStatusUpdated",
|
|
@@ -4,7 +4,8 @@ A task handler publishes a snapshot as a plain mapping of label to value.
|
|
|
4
4
|
Values are normalised here into :class:`StatusField` records so every frontend
|
|
5
5
|
renders the same thing, and so a richer field kind (a progress bar) can travel
|
|
6
6
|
on the bus without breaking a consumer that only understands text: ``value`` is
|
|
7
|
-
always the display string, whatever the kind.
|
|
7
|
+
always the display string, whatever the kind. Richer kinds are a progress bar
|
|
8
|
+
and styled text with coloured or bold spans.
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
from __future__ import annotations
|
|
@@ -16,6 +17,7 @@ from typing import Any
|
|
|
16
17
|
|
|
17
18
|
TEXT = "text"
|
|
18
19
|
PROGRESS = "progress"
|
|
20
|
+
STYLED = "styled"
|
|
19
21
|
|
|
20
22
|
# Frontends may paste these into a stylesheet, so only simple colour forms pass.
|
|
21
23
|
_COLOR_RE = re.compile(
|
|
@@ -42,6 +44,34 @@ class Progress:
|
|
|
42
44
|
text_color: str | None = None
|
|
43
45
|
|
|
44
46
|
|
|
47
|
+
@dataclass(frozen=True, slots=True)
|
|
48
|
+
class Span:
|
|
49
|
+
"""One run of :class:`StyledText`: ``text`` drawn in ``color``, optionally bold.
|
|
50
|
+
|
|
51
|
+
``color`` is a CSS colour like :class:`Progress`'s; anything else is ignored.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
text: str
|
|
55
|
+
color: str | None = None
|
|
56
|
+
bold: bool = False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True, slots=True, init=False)
|
|
60
|
+
class StyledText:
|
|
61
|
+
"""A status value a frontend renders as text with coloured or bold runs.
|
|
62
|
+
|
|
63
|
+
Each part is a plain string or a :class:`Span`::
|
|
64
|
+
|
|
65
|
+
StyledText("Block ", Span("L", color="#FF9A00", bold=True))
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
spans: tuple[Span, ...]
|
|
69
|
+
|
|
70
|
+
def __init__(self, *parts: str | Span) -> None:
|
|
71
|
+
spans = tuple(part if isinstance(part, Span) else Span(str(part)) for part in parts)
|
|
72
|
+
object.__setattr__(self, "spans", spans)
|
|
73
|
+
|
|
74
|
+
|
|
45
75
|
@dataclass(frozen=True, slots=True)
|
|
46
76
|
class StatusField:
|
|
47
77
|
"""One normalised field of a live status snapshot."""
|
|
@@ -52,6 +82,7 @@ class StatusField:
|
|
|
52
82
|
fraction: float | None = None
|
|
53
83
|
fill_color: str | None = None
|
|
54
84
|
text_color: str | None = None
|
|
85
|
+
spans: tuple[Span, ...] = ()
|
|
55
86
|
|
|
56
87
|
|
|
57
88
|
def normalise_status_fields(status: Mapping[str, Any]) -> tuple[StatusField, ...]:
|
|
@@ -74,6 +105,8 @@ def clean_color(color: object) -> str | None:
|
|
|
74
105
|
def _status_field(label: str, value: Any) -> StatusField:
|
|
75
106
|
if isinstance(value, Progress):
|
|
76
107
|
return _progress_field(label, value)
|
|
108
|
+
if isinstance(value, StyledText):
|
|
109
|
+
return _styled_field(label, value)
|
|
77
110
|
return StatusField(label=label, value="" if value is None else str(value))
|
|
78
111
|
|
|
79
112
|
|
|
@@ -97,10 +130,25 @@ def _progress_field(label: str, progress: Progress) -> StatusField:
|
|
|
97
130
|
)
|
|
98
131
|
|
|
99
132
|
|
|
133
|
+
def _styled_field(label: str, styled: StyledText) -> StatusField:
|
|
134
|
+
spans = tuple(Span(str(span.text), clean_color(span.color), bool(span.bold)) for span in styled.spans)
|
|
135
|
+
return StatusField(label=label, value="".join(span.text for span in spans), kind=STYLED, spans=spans)
|
|
136
|
+
|
|
137
|
+
|
|
100
138
|
def _format_number(value: float) -> str:
|
|
101
139
|
if value == int(value):
|
|
102
140
|
return str(int(value))
|
|
103
141
|
return f"{value:.3f}".rstrip("0").rstrip(".")
|
|
104
142
|
|
|
105
143
|
|
|
106
|
-
__all__ = [
|
|
144
|
+
__all__ = [
|
|
145
|
+
"PROGRESS",
|
|
146
|
+
"STYLED",
|
|
147
|
+
"TEXT",
|
|
148
|
+
"Progress",
|
|
149
|
+
"Span",
|
|
150
|
+
"StatusField",
|
|
151
|
+
"StyledText",
|
|
152
|
+
"clean_color",
|
|
153
|
+
"normalise_status_fields",
|
|
154
|
+
]
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
|
-
from pycontrol.bus.status import Progress, StatusField, clean_color, normalise_status_fields
|
|
7
|
+
from pycontrol.bus.status import STYLED, Progress, Span, StatusField, StyledText, clean_color, normalise_status_fields
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def test_plain_values_become_text_fields() -> None:
|
|
@@ -71,3 +71,17 @@ def test_a_rejected_color_leaves_the_field_unstyled() -> None:
|
|
|
71
71
|
[status_field] = normalise_status_fields({"Bar": Progress(1, 2, fill_color="}; evil")})
|
|
72
72
|
|
|
73
73
|
assert status_field.fill_color is None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_styled_text_keeps_spans_and_a_plain_display_string() -> None:
|
|
77
|
+
[status_field] = normalise_status_fields({"Block": StyledText("1X ", Span("L", color="#FF9A00", bold=True))})
|
|
78
|
+
|
|
79
|
+
assert status_field.kind == STYLED
|
|
80
|
+
assert status_field.value == "1X L"
|
|
81
|
+
assert status_field.spans == (Span("1X "), Span("L", color="#FF9A00", bold=True))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_styled_text_drops_rejected_span_colors() -> None:
|
|
85
|
+
[status_field] = normalise_status_fields({"Block": StyledText(Span("L", color="red; } * { x"))})
|
|
86
|
+
|
|
87
|
+
assert status_field.spans == (Span("L"),)
|
|
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
|
|
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
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/experiment_impl.py
RENAMED
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/firmware_impl.py
RENAMED
|
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
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/cli/commands/workspace_impl.py
RENAMED
|
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
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/LED_driver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/__init__.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/analog_LED.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/audio_board.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/audio_player.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/five_poke.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/frame_logger.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/frame_trigger.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/grid_maze.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/lickometer.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/load_cell.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/nine_poke.py
RENAMED
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/port_expander.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/rotary_encoder.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/schmitt_trigger.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/solenoid_driver.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/stepper_motor.py
RENAMED
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/devices/uart_handler.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/hardware.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/profiles.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/state_machine.py
RENAMED
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/firmware/pycontrol/utility.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/notify/__init__.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/notify/slack.py
RENAMED
|
File without changes
|
{pycontrol_core-3.0.0b2 → pycontrol_core-3.0.0b3}/src/pycontrol/integrations/notify/telegram.py
RENAMED
|
File without changes
|
|
File without changes
|