ophyd-async 0.8.0a5__tar.gz → 0.8.0a6__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.
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/PKG-INFO +1 -1
- ophyd_async-0.8.0a6/docs/how-to/use_set_and_wait_for_other_value.md +45 -0
- ophyd_async-0.8.0a6/docs/images/set_and_wait_for_other_value.svg +10 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/_version.py +1 -1
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/__init__.py +2 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_signal.py +90 -17
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_table.py +9 -4
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adcore/_core_logic.py +3 -1
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/eiger/_eiger_controller.py +6 -1
- ophyd_async-0.8.0a6/src/ophyd_async/epics/testing/__init__.py +24 -0
- ophyd_async-0.8.0a6/src/ophyd_async/epics/testing/_example_ioc.py +105 -0
- ophyd_async-0.8.0a6/src/ophyd_async/epics/testing/_utils.py +78 -0
- ophyd_async-0.8.0a6/src/ophyd_async/epics/testing/test_records.db +152 -0
- ophyd_async-0.8.0a6/src/ophyd_async/epics/testing/test_records_pva.db +177 -0
- {ophyd_async-0.8.0a5/src/ophyd_async/tango/signal → ophyd_async-0.8.0a6/src/ophyd_async/tango/core}/__init__.py +7 -2
- {ophyd_async-0.8.0a5/src/ophyd_async/tango/base_devices → ophyd_async-0.8.0a6/src/ophyd_async/tango/core}/_base_device.py +38 -64
- {ophyd_async-0.8.0a5/src/ophyd_async/tango/signal → ophyd_async-0.8.0a6/src/ophyd_async/tango/core}/_signal.py +13 -3
- {ophyd_async-0.8.0a5/src/ophyd_async/tango/base_devices → ophyd_async-0.8.0a6/src/ophyd_async/tango/core}/_tango_readable.py +3 -4
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/tango/demo/_counter.py +6 -7
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/tango/demo/_mover.py +8 -7
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async.egg-info/PKG-INFO +1 -1
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async.egg-info/SOURCES.txt +12 -7
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_device_save_loader.py +27 -59
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_observe.py +28 -1
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_signal.py +53 -12
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/signal/test_signals.py +267 -270
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/test_trigger.py +1 -1
- ophyd_async-0.8.0a6/tests/sim/demo/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/tango/test_base_device.py +1 -1
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/tango/test_tango_signals.py +1 -1
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/tango/test_tango_transport.py +1 -1
- ophyd_async-0.8.0a6/tests/test_data/test_yaml_save.yml +40 -0
- ophyd_async-0.8.0a5/src/ophyd_async/tango/__init__.py +0 -43
- ophyd_async-0.8.0a5/src/ophyd_async/tango/base_devices/__init__.py +0 -4
- ophyd_async-0.8.0a5/tests/epics/signal/test_records.db +0 -330
- ophyd_async-0.8.0a5/tests/test_data/test_yaml_save.yml +0 -46
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.codecov.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.copier-answers.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.devcontainer/devcontainer.json +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.git-blame-ignore-revs +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/CONTRIBUTING.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/actions/install_requirements/action.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/dependabot.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/pages/index.html +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/pages/make_switcher.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/_check.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/_dist.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/_docs.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/_pypi.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/_release.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/_test.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/_tox.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/ci.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.github/workflows/periodic.yml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.gitignore +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.mailmap +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/.pre-commit-config.yaml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/Dockerfile +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/LICENSE +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/README.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/_api.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/_templates/custom-module-template.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/conf.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/examples/epics_demo.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/examples/foo_detector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/examples/tango_demo.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0008-signal-types.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions/COPYME +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/decisions.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/design-goals.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/event-loop-choice.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations/flyscanning.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/explanations.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/genindex.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/how-to/choose-interfaces-for-devices.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/how-to/compound-devices.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/how-to/contribute.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/how-to/make-a-simple-device.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/how-to/make-a-standard-detector.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/how-to/write-tests-for-devices.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/how-to.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/images/ophyd-async-logo.svg +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/images/ophyd-favicon.svg +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/index.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/reference.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/tutorials/installation.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/tutorials/using-existing-devices.rst +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/docs/tutorials.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/pyproject.toml +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/setup.cfg +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/__main__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_detector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_device.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_device_filler.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_device_save_loader.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_flyer.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_hdf_dataset.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_log.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_mock_signal_utils.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_protocol.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_providers.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_readable.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_signal_backend.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_status.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/core/_utils.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adcore/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adcore/_hdf_writer.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adcore/_utils.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/advimba/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/_aioca.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/_epics_device.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/_p4p.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/_signal.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/core/_util.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/demo/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/demo/_mover.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/demo/_sensor.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/demo/mover.db +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/demo/sensor.db +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/eiger/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/eiger/_eiger.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/eiger/_eiger_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/eiger/_odin_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/motor.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/signal.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/core.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/_block.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/_control.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/_table.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/_utils.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/plan_stubs/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/plan_stubs/_fly.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/py.typed +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/demo/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/demo/_pattern_detector/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_detector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_detector_controller.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_detector_writer.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_generator.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/demo/_sim_motor.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/sim/testing/__init__.py +0 -0
- {ophyd_async-0.8.0a5/tests/sim → ophyd_async-0.8.0a6/src/ophyd_async/tango}/__init__.py +0 -0
- {ophyd_async-0.8.0a5/src/ophyd_async/tango/signal → ophyd_async-0.8.0a6/src/ophyd_async/tango/core}/_tango_transport.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/tango/demo/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/tango/demo/_detector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async.egg-info/entry_points.txt +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async.egg-info/requires.txt +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async.egg-info/top_level.txt +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/system_tests/epics/eiger/README.md +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/system_tests/epics/eiger/test_eiger_system.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/conftest.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_device.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_device_collector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_flyer.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_log.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_mock_signal_backend.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_protocol.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_providers.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_readable.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_soft_signal_backend.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_status.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_subset_enum.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_table.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_utils.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/core/test_watchable_async_status.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adaravis/test_aravis.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adcore/test_drivers.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adcore/test_scans.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adcore/test_single_trigger.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adcore/test_writers.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adkinetix/test_kinetix.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adpilatus/test_pilatus.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/adsimdetector/test_sim.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/advimba/test_vimba.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/conftest.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/demo/test_demo.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/eiger/test_eiger_controller.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/eiger/test_eiger_detector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/eiger/test_odin_io.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/pvi/test_pvi.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/signal/test_common.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/test_areadetector_subclass_naming.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/epics/test_motor.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/db/panda.db +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/test_hdf_panda.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/test_panda_connect.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/test_panda_control.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/test_panda_utils.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/test_seq_table.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/fastcs/panda/test_writer.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/plan_stubs/test_ensure_connected.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/plan_stubs/test_fly.py +0 -0
- {ophyd_async-0.8.0a5/tests/sim/demo → ophyd_async-0.8.0a6/tests/sim}/__init__.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/sim/conftest.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/sim/demo/test_sim_motor.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/sim/test_pattern_generator.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/sim/test_sim_detector.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/sim/test_sim_writer.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/sim/test_streaming_plan.py +0 -0
- {ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/tests/test_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.0a6
|
|
4
4
|
Summary: Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
|
|
5
5
|
Author-email: Tom Cobb <tom.cobb@diamond.ac.uk>
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# `set_and_wait_for_other_value`
|
|
2
|
+
|
|
3
|
+
The `set_and_wait_for_other_value` function (defined in `_signal.py`) is a utility designed to:
|
|
4
|
+
|
|
5
|
+
1. **Set a signal**.
|
|
6
|
+
2. **Wait for another signal to reach a specified value (`match_value`)**.
|
|
7
|
+
|
|
8
|
+
The behavior of the function depends on the value of the `wait_for_set_completion` parameter:
|
|
9
|
+
|
|
10
|
+
- **If `wait_for_set_completion = True`:**
|
|
11
|
+
The function returns at **1** (see diagram below), which occurs when the "set operation" is complete.
|
|
12
|
+
|
|
13
|
+
- **If `wait_for_set_completion = False`:**
|
|
14
|
+
The function returns at **2**, which occurs when the `match_signal` reaches the `match_value`.
|
|
15
|
+
|
|
16
|
+
In **AreaDetector**, the `wait_for_set_completion` parameter should generally be set to **`False`**, as the preferred behavior is to return when the `match_signal` achieves the `match_value`.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Behavior Diagram:
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Example Usage
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
# Example code snippet for using set_and_wait_for_other_value in an AreaDetector driver
|
|
30
|
+
self._arm_status = set_and_wait_for_other_value(
|
|
31
|
+
self._drv.arm,
|
|
32
|
+
1,
|
|
33
|
+
self._drv.state,
|
|
34
|
+
"ready",
|
|
35
|
+
timeout=DEFAULT_TIMEOUT,
|
|
36
|
+
wait_for_set_completion=False,
|
|
37
|
+
)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
In this **AreaDetector driver**, the function ensures that the detector's `arm_status` reaches `"ready"` before capturing data. To achieve this:
|
|
41
|
+
|
|
42
|
+
- The detector is instructed to transition to the "armed" state by setting the driver's `arm` signal to `1`.
|
|
43
|
+
- The function waits until the driver's `state` signal equals `"ready"`.
|
|
44
|
+
|
|
45
|
+
This approach ensures that data capture is only initiated once the detector is fully prepared.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1187.8240472771774 784.5838303364346" width="1187.8240472771774" height="784.5838303364346">
|
|
2
|
+
<!-- svg-source:excalidraw -->
|
|
3
|
+
|
|
4
|
+
<defs>
|
|
5
|
+
<style class="style-fonts">
|
|
6
|
+
@font-face { font-family: Excalifont; src: url(data:font/woff2;base64,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); }
|
|
7
|
+
</style>
|
|
8
|
+
|
|
9
|
+
</defs>
|
|
10
|
+
<rect x="0" y="0" width="1187.8240472771774" height="784.5838303364346" fill="#ffffff"></rect><g stroke-linecap="round"><g transform="translate(43.84248105120804 302.75444427692025) rotate(0 109.31598350459507 0)"><path d="M-0.45 -0.7 C35.76 -0.86, 180.92 -1.39, 217.58 -1.19 M1.51 1.54 C38.06 1.51, 183.45 0.24, 219.75 -0.28" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(262.4744480603982 302.8253415087969) rotate(0 0 -82.9293667965893)"><path d="M0.64 0.3 C0.59 -27.08, -0.08 -137.51, -0.32 -165.29 M-0.48 -0.59 C-0.72 -28.23, -1.79 -139.66, -1.44 -167.12" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(258.8706526177911 134.14839879518058) rotate(0 332.5798441252804 -1.9202069522244898)"><path d="M-0.18 0.98 C110.67 0.28, 554.82 -2.97, 665.76 -3.76 M-1.73 0.45 C108.95 -0.07, 554.04 -1.71, 665.12 -2.18" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(925.5665064301318 131.8441504525112) rotate(0 1.1521241713346626 80.10711520276767)"><path d="M0.54 0.53 C0.98 27.16, 1.63 133.33, 2.07 159.95 M-0.63 -0.24 C-0.32 26.56, 0.42 134.38, 1 161.35" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(926.3345892110212 293.1415344393678) rotate(0 68.92542750440384 -1.152124171334691)"><path d="M1.09 -0.33 C24.12 -0.33, 115.62 -0.86, 138.29 -1.2 M0.21 -1.54 C23.1 -1.75, 114.33 -2.82, 137.57 -2.74" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(154.08449781789392 67.15748673767692) rotate(0 52.98975332972128 33.34186726364484)"><path d="M-1.06 0.7 C16.59 11.86, 88.97 56.89, 106.91 67.72 M0.58 0.03 C18.07 10.8, 88.85 55.06, 106.45 66.14" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(154.08449781789392 67.15748673767692) rotate(0 52.98975332972128 33.34186726364484)"><path d="M82 60.91 C92.6 64.68, 102.53 66.17, 106.45 66.14 M82 60.91 C86.56 61.38, 93.31 62.59, 106.45 66.14" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(154.08449781789392 67.15748673767692) rotate(0 52.98975332972128 33.34186726364484)"><path d="M91.08 46.42 C98.28 55.67, 104.73 62.72, 106.45 66.14 M91.08 46.42 C93.64 50.1, 98.42 54.45, 106.45 66.14" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(73.11139160618495 10) rotate(0 47.0625 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">set called</text></g><g stroke-linecap="round"><g transform="translate(931.6644736450401 312.4583673202069) rotate(0 4.167733407955666 192.31112725280877)"><path d="M-0.34 -0.98 C1.13 63.35, 6.73 321.09, 8.05 385.17 M1.68 1.12 C3.03 65.16, 5.56 319.49, 6.94 383.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(931.6644736450401 312.4583673202069) rotate(0 4.167733407955666 192.31112725280877)"><path d="M-1.96 359.97 C-1.66 365.01, 2.98 369.66, 6.94 383.33 M-1.96 359.97 C0.77 365.61, 2.46 369.39, 6.94 383.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(931.6644736450401 312.4583673202069) rotate(0 4.167733407955666 192.31112725280877)"><path d="M15.14 359.71 C11.41 364.76, 12.02 369.48, 6.94 383.33 M15.14 359.71 C14.41 365.37, 12.64 369.21, 6.94 383.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(889.4853986759654 715.0686100052003) rotate(0 66.3862760711362 24.140464025867686)"><text x="0" y="17.014199045431567" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="19.312371220694175px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Set completed</text><text x="0" y="41.15466307129928" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="19.312371220694175px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"></text></g><g stroke-linecap="round"><g transform="translate(45.723429211048085 551.6184165698157) rotate(0 208.3866703977804 -2.9769524342540308)"><path d="M1.15 -0.09 C70.36 -1.4, 346.52 -5.76, 415.96 -6.64 M0.29 -1.19 C69.83 -1.84, 348.7 -4.42, 418.24 -5.46" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(462.49677000660887 545.6645117013077) rotate(0 -1.190780973701635 -80.97310621170891)"><path d="M-0.62 -0.09 C-1.05 -26.87, -1.53 -134.53, -1.9 -161.39 M1.25 -1.18 C0.65 -28.26, -1.74 -136.22, -2.59 -163.22" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(460.1152080592056 380.14595635678495) rotate(0 105.3841161725918 -1.1907809737016066)"><path d="M0.98 -0.93 C36.1 -1.01, 176.54 -1, 211.51 -1.27 M0.04 1.2 C34.99 0.88, 175.96 -2.39, 210.95 -2.82" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(669.6926594306876 376.57361343568016) rotate(0 0.5953904868507607 82.75927767226133)"><path d="M-0.99 -0.41 C-0.54 27.2, 1.55 136.9, 1.72 164.64 M0.7 -1.68 C1.12 26.16, 0.78 138.12, 1.04 165.72" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(672.0742213780909 542.0921687802029) rotate(0 191.12034627910714 -2.976952434253974)"><path d="M0.95 0.4 C64.42 -0.86, 317.63 -5.42, 381.15 -6.62 M0 -0.44 C63.78 -1.63, 319.76 -4.51, 383.29 -5.43" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(672.1152080592055 548.1907594909206) rotate(0 0.5953904868508175 65.49295355358805)"><path d="M-0.92 1.14 C-0.95 23.33, -0.16 110.39, 0.31 131.92 M0.8 0.7 C1.09 22.66, 2.45 108.52, 2.56 130.29" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(672.1152080592055 548.1907594909206) rotate(0 0.5953904868508175 65.49295355358805)"><path d="M-6.25 106.9 C-1.55 113.53, 1.13 124.19, 2.56 130.29 M-6.25 106.9 C-4.64 113.13, -2.21 118.07, 2.56 130.29" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(672.1152080592055 548.1907594909206) rotate(0 0.5953904868508175 65.49295355358805)"><path d="M10.85 106.7 C9.68 113.27, 6.5 123.99, 2.56 130.29 M10.85 106.7 C8.22 113.14, 6.41 118.12, 2.56 130.29" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(616.1485022952302 694.6568192562175) rotate(0 69.97916412353516 25)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">RBV Matched </text><text x="0" y="42.62" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Return here</text></g><g transform="translate(10 264.6402019077296) rotate(0 47.8125 12.500000000000014)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Set signal</text></g><g transform="translate(869.5323806105109 749.2654514964912) rotate(0 154.14583333333326 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">wait_for_set_completion= True</text></g><g transform="translate(521.8463297153439 749.5838303364346) rotate(0 160.32291666666663 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">wait_for_set_completion = False</text></g><g transform="translate(20.535767711378583 514.1120161220821) rotate(0 59.5625 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">match signal</text></g><g transform="translate(957.8616550664754 651.6440183607504) rotate(0 7.677083492279053 22.5)"><text x="0" y="31.716" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="36px" fill="#e03131" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">1</text></g><g transform="translate(691.1677036384312 638.6901134922423) rotate(0 12.583333015441895 22.5)"><text x="0" y="31.716" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="36px" fill="#e03131" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">2</text></g></svg>
|
|
@@ -61,6 +61,7 @@ from ._signal import (
|
|
|
61
61
|
assert_emitted,
|
|
62
62
|
assert_reading,
|
|
63
63
|
assert_value,
|
|
64
|
+
observe_signals_value,
|
|
64
65
|
observe_value,
|
|
65
66
|
set_and_wait_for_other_value,
|
|
66
67
|
set_and_wait_for_value,
|
|
@@ -158,6 +159,7 @@ __all__ = [
|
|
|
158
159
|
"assert_reading",
|
|
159
160
|
"assert_value",
|
|
160
161
|
"observe_value",
|
|
162
|
+
"observe_signals_value",
|
|
161
163
|
"set_and_wait_for_value",
|
|
162
164
|
"set_and_wait_for_other_value",
|
|
163
165
|
"soft_signal_r_and_setter",
|
|
@@ -28,7 +28,7 @@ from ._signal_backend import (
|
|
|
28
28
|
SignalDatatypeV,
|
|
29
29
|
)
|
|
30
30
|
from ._soft_signal_backend import SoftSignalBackend
|
|
31
|
-
from ._status import AsyncStatus
|
|
31
|
+
from ._status import AsyncStatus, completed_status
|
|
32
32
|
from ._utils import (
|
|
33
33
|
CALCULATE_TIMEOUT,
|
|
34
34
|
DEFAULT_TIMEOUT,
|
|
@@ -448,27 +448,79 @@ async def observe_value(
|
|
|
448
448
|
do_something_with(value)
|
|
449
449
|
"""
|
|
450
450
|
|
|
451
|
-
|
|
451
|
+
async for _, value in observe_signals_value(
|
|
452
|
+
signal, timeout=timeout, done_status=done_status
|
|
453
|
+
):
|
|
454
|
+
yield value
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
async def observe_signals_value(
|
|
458
|
+
*signals: SignalR[SignalDatatypeT],
|
|
459
|
+
timeout: float | None = None,
|
|
460
|
+
done_status: Status | None = None,
|
|
461
|
+
) -> AsyncGenerator[tuple[SignalR[SignalDatatypeT], SignalDatatypeT], None]:
|
|
462
|
+
"""Subscribe to the value of a signal so it can be iterated from.
|
|
463
|
+
|
|
464
|
+
Parameters
|
|
465
|
+
----------
|
|
466
|
+
signals:
|
|
467
|
+
Call subscribe_value on all the signals at the start, and clear_sub on it at the
|
|
468
|
+
end
|
|
469
|
+
timeout:
|
|
470
|
+
If given, how long to wait for each updated value in seconds. If an update
|
|
471
|
+
is not produced in this time then raise asyncio.TimeoutError
|
|
472
|
+
done_status:
|
|
473
|
+
If this status is complete, stop observing and make the iterator return.
|
|
474
|
+
If it raises an exception then this exception will be raised by the iterator.
|
|
475
|
+
|
|
476
|
+
Notes
|
|
477
|
+
-----
|
|
478
|
+
Example usage::
|
|
479
|
+
|
|
480
|
+
async for signal,value in observe_signals_values(sig1,sig2,..):
|
|
481
|
+
if signal is sig1:
|
|
482
|
+
do_something_with(value)
|
|
483
|
+
elif signal is sig2:
|
|
484
|
+
do_something_else_with(value)
|
|
485
|
+
"""
|
|
486
|
+
q: asyncio.Queue[tuple[SignalR[SignalDatatypeT], SignalDatatypeT] | Status] = (
|
|
487
|
+
asyncio.Queue()
|
|
488
|
+
)
|
|
489
|
+
if timeout is None:
|
|
490
|
+
get_value = q.get
|
|
491
|
+
else:
|
|
492
|
+
|
|
493
|
+
async def get_value():
|
|
494
|
+
return await asyncio.wait_for(q.get(), timeout)
|
|
495
|
+
|
|
496
|
+
cbs: dict[SignalR, Callback] = {}
|
|
497
|
+
for signal in signals:
|
|
498
|
+
|
|
499
|
+
def queue_value(value: SignalDatatypeT, signal=signal):
|
|
500
|
+
q.put_nowait((signal, value))
|
|
501
|
+
|
|
502
|
+
cbs[signal] = queue_value
|
|
503
|
+
signal.subscribe_value(queue_value)
|
|
452
504
|
|
|
453
505
|
if done_status is not None:
|
|
454
506
|
done_status.add_callback(q.put_nowait)
|
|
455
507
|
|
|
456
|
-
signal.subscribe_value(q.put_nowait)
|
|
457
508
|
try:
|
|
458
509
|
while True:
|
|
459
510
|
# yield here in case something else is filling the queue
|
|
460
511
|
# like in test_observe_value_times_out_with_no_external_task()
|
|
461
512
|
await asyncio.sleep(0)
|
|
462
|
-
item = await
|
|
513
|
+
item = await get_value()
|
|
463
514
|
if done_status and item is done_status:
|
|
464
515
|
if exc := done_status.exception():
|
|
465
516
|
raise exc
|
|
466
517
|
else:
|
|
467
518
|
break
|
|
468
519
|
else:
|
|
469
|
-
yield cast(SignalDatatypeT, item)
|
|
520
|
+
yield cast(tuple[SignalR[SignalDatatypeT], SignalDatatypeT], item)
|
|
470
521
|
finally:
|
|
471
|
-
signal.
|
|
522
|
+
for signal, cb in cbs.items():
|
|
523
|
+
signal.clear_sub(cb)
|
|
472
524
|
|
|
473
525
|
|
|
474
526
|
class _ValueChecker(Generic[SignalDatatypeT]):
|
|
@@ -533,15 +585,16 @@ async def wait_for_value(
|
|
|
533
585
|
async def set_and_wait_for_other_value(
|
|
534
586
|
set_signal: SignalW[SignalDatatypeT],
|
|
535
587
|
set_value: SignalDatatypeT,
|
|
536
|
-
|
|
537
|
-
|
|
588
|
+
match_signal: SignalR[SignalDatatypeV],
|
|
589
|
+
match_value: SignalDatatypeV | Callable[[SignalDatatypeV], bool],
|
|
538
590
|
timeout: float = DEFAULT_TIMEOUT,
|
|
539
591
|
set_timeout: float | None = None,
|
|
592
|
+
wait_for_set_completion: bool = True,
|
|
540
593
|
) -> AsyncStatus:
|
|
541
594
|
"""Set a signal and monitor another signal until it has the specified value.
|
|
542
595
|
|
|
543
596
|
This function sets a set_signal to a specified set_value and waits for
|
|
544
|
-
a
|
|
597
|
+
a match_signal to have the match_value.
|
|
545
598
|
|
|
546
599
|
Parameters
|
|
547
600
|
----------
|
|
@@ -549,14 +602,16 @@ async def set_and_wait_for_other_value(
|
|
|
549
602
|
The signal to set
|
|
550
603
|
set_value:
|
|
551
604
|
The value to set it to
|
|
552
|
-
|
|
605
|
+
match_signal:
|
|
553
606
|
The signal to monitor
|
|
554
|
-
|
|
607
|
+
match_value:
|
|
555
608
|
The value to wait for
|
|
556
609
|
timeout:
|
|
557
610
|
How long to wait for the signal to have the value
|
|
558
611
|
set_timeout:
|
|
559
612
|
How long to wait for the set to complete
|
|
613
|
+
wait_for_set_completion:
|
|
614
|
+
This will wait for set completion #More info in how-to docs
|
|
560
615
|
|
|
561
616
|
Notes
|
|
562
617
|
-----
|
|
@@ -565,7 +620,7 @@ async def set_and_wait_for_other_value(
|
|
|
565
620
|
set_and_wait_for_value(device.acquire, 1, device.acquire_rbv, 1)
|
|
566
621
|
"""
|
|
567
622
|
# Start monitoring before the set to avoid a race condition
|
|
568
|
-
values_gen = observe_value(
|
|
623
|
+
values_gen = observe_value(match_signal)
|
|
569
624
|
|
|
570
625
|
# Get the initial value from the monitor to make sure we've created it
|
|
571
626
|
current_value = await anext(values_gen)
|
|
@@ -573,28 +628,33 @@ async def set_and_wait_for_other_value(
|
|
|
573
628
|
status = set_signal.set(set_value, timeout=set_timeout)
|
|
574
629
|
|
|
575
630
|
# If the value was the same as before no need to wait for it to change
|
|
576
|
-
if current_value !=
|
|
631
|
+
if current_value != match_value:
|
|
577
632
|
|
|
578
633
|
async def _wait_for_value():
|
|
579
634
|
async for value in values_gen:
|
|
580
|
-
if value ==
|
|
635
|
+
if value == match_value:
|
|
581
636
|
break
|
|
582
637
|
|
|
583
638
|
try:
|
|
584
639
|
await asyncio.wait_for(_wait_for_value(), timeout)
|
|
640
|
+
if wait_for_set_completion:
|
|
641
|
+
await status
|
|
642
|
+
return status
|
|
585
643
|
except asyncio.TimeoutError as e:
|
|
586
644
|
raise TimeoutError(
|
|
587
|
-
f"{
|
|
645
|
+
f"{match_signal.name} didn't match {match_value} in {timeout}s"
|
|
588
646
|
) from e
|
|
589
647
|
|
|
590
|
-
return
|
|
648
|
+
return completed_status()
|
|
591
649
|
|
|
592
650
|
|
|
593
651
|
async def set_and_wait_for_value(
|
|
594
652
|
signal: SignalRW[SignalDatatypeT],
|
|
595
653
|
value: SignalDatatypeT,
|
|
654
|
+
match_value: SignalDatatypeT | Callable[[SignalDatatypeT], bool] | None = None,
|
|
596
655
|
timeout: float = DEFAULT_TIMEOUT,
|
|
597
656
|
status_timeout: float | None = None,
|
|
657
|
+
wait_for_set_completion: bool = True,
|
|
598
658
|
) -> AsyncStatus:
|
|
599
659
|
"""Set a signal and monitor it until it has that value.
|
|
600
660
|
|
|
@@ -609,10 +669,15 @@ async def set_and_wait_for_value(
|
|
|
609
669
|
The signal to set
|
|
610
670
|
value:
|
|
611
671
|
The value to set it to
|
|
672
|
+
match_value:
|
|
673
|
+
The expected value of the signal after the operation.
|
|
674
|
+
Used to verify that the set operation was successful.
|
|
612
675
|
timeout:
|
|
613
676
|
How long to wait for the signal to have the value
|
|
614
677
|
status_timeout:
|
|
615
678
|
How long the returned Status will wait for the set to complete
|
|
679
|
+
wait_for_set_completion:
|
|
680
|
+
This will wait for set completion #More info in how-to docs
|
|
616
681
|
|
|
617
682
|
Notes
|
|
618
683
|
-----
|
|
@@ -620,6 +685,14 @@ async def set_and_wait_for_value(
|
|
|
620
685
|
|
|
621
686
|
set_and_wait_for_value(device.acquire, 1)
|
|
622
687
|
"""
|
|
688
|
+
if match_value is None:
|
|
689
|
+
match_value = value
|
|
623
690
|
return await set_and_wait_for_other_value(
|
|
624
|
-
signal,
|
|
691
|
+
signal,
|
|
692
|
+
value,
|
|
693
|
+
signal,
|
|
694
|
+
match_value,
|
|
695
|
+
timeout,
|
|
696
|
+
status_timeout,
|
|
697
|
+
wait_for_set_completion,
|
|
625
698
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from collections.abc import Sequence
|
|
3
|
+
from collections.abc import Callable, Sequence
|
|
4
4
|
from typing import Annotated, Any, TypeVar, get_origin
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
@@ -19,6 +19,13 @@ def _concat(value1, value2):
|
|
|
19
19
|
return value1 + value2
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _make_default_factory(dtype: np.dtype) -> Callable[[], np.ndarray]:
|
|
23
|
+
def numpy_array_default_factory() -> np.ndarray:
|
|
24
|
+
return np.array([], dtype)
|
|
25
|
+
|
|
26
|
+
return numpy_array_default_factory
|
|
27
|
+
|
|
28
|
+
|
|
22
29
|
class Table(BaseModel):
|
|
23
30
|
"""An abstraction of a Table of str to numpy array."""
|
|
24
31
|
|
|
@@ -45,9 +52,7 @@ class Table(BaseModel):
|
|
|
45
52
|
NpArrayPydanticAnnotation.factory(
|
|
46
53
|
data_type=dtype.type, dimensions=1, strict_data_typing=False
|
|
47
54
|
),
|
|
48
|
-
Field(
|
|
49
|
-
default_factory=lambda dtype=dtype: np.array([], dtype=dtype)
|
|
50
|
-
),
|
|
55
|
+
Field(default_factory=_make_default_factory(dtype)),
|
|
51
56
|
]
|
|
52
57
|
elif get_origin(anno) is Sequence:
|
|
53
58
|
new_anno = Annotated[anno, Field(default_factory=list)]
|
|
@@ -91,7 +91,9 @@ async def start_acquiring_driver_and_ensure_status(
|
|
|
91
91
|
subsequent raising (if applicable) due to detector state.
|
|
92
92
|
"""
|
|
93
93
|
|
|
94
|
-
status = await set_and_wait_for_value(
|
|
94
|
+
status = await set_and_wait_for_value(
|
|
95
|
+
driver.acquire, True, timeout=timeout, wait_for_set_completion=False
|
|
96
|
+
)
|
|
95
97
|
|
|
96
98
|
async def complete_acquisition() -> None:
|
|
97
99
|
"""NOTE: possible race condition here between the callback from
|
{ophyd_async-0.8.0a5 → ophyd_async-0.8.0a6}/src/ophyd_async/epics/eiger/_eiger_controller.py
RENAMED
|
@@ -55,7 +55,12 @@ class EigerController(DetectorController):
|
|
|
55
55
|
async def arm(self):
|
|
56
56
|
# TODO: Detector state should be an enum see https://github.com/DiamondLightSource/eiger-fastcs/issues/43
|
|
57
57
|
self._arm_status = set_and_wait_for_other_value(
|
|
58
|
-
self._drv.arm,
|
|
58
|
+
self._drv.arm,
|
|
59
|
+
1,
|
|
60
|
+
self._drv.state,
|
|
61
|
+
"ready",
|
|
62
|
+
timeout=DEFAULT_TIMEOUT,
|
|
63
|
+
wait_for_set_completion=False,
|
|
59
64
|
)
|
|
60
65
|
|
|
61
66
|
async def wait_for_idle(self):
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from ._example_ioc import (
|
|
2
|
+
CA_PVA_RECORDS,
|
|
3
|
+
PVA_RECORDS,
|
|
4
|
+
ExampleCaDevice,
|
|
5
|
+
ExampleEnum,
|
|
6
|
+
ExamplePvaDevice,
|
|
7
|
+
ExampleTable,
|
|
8
|
+
connect_example_device,
|
|
9
|
+
get_example_ioc,
|
|
10
|
+
)
|
|
11
|
+
from ._utils import TestingIOC, generate_random_PV_prefix
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"CA_PVA_RECORDS",
|
|
15
|
+
"PVA_RECORDS",
|
|
16
|
+
"ExampleCaDevice",
|
|
17
|
+
"ExampleEnum",
|
|
18
|
+
"ExamplePvaDevice",
|
|
19
|
+
"ExampleTable",
|
|
20
|
+
"connect_example_device",
|
|
21
|
+
"get_example_ioc",
|
|
22
|
+
"TestingIOC",
|
|
23
|
+
"generate_random_PV_prefix",
|
|
24
|
+
]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Annotated as A
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from ophyd_async.core import (
|
|
9
|
+
Array1D,
|
|
10
|
+
SignalRW,
|
|
11
|
+
StrictEnum,
|
|
12
|
+
Table,
|
|
13
|
+
)
|
|
14
|
+
from ophyd_async.epics.core import (
|
|
15
|
+
EpicsDevice,
|
|
16
|
+
PvSuffix,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from ._utils import TestingIOC
|
|
20
|
+
|
|
21
|
+
CA_PVA_RECORDS = str(Path(__file__).parent / "test_records.db")
|
|
22
|
+
PVA_RECORDS = str(Path(__file__).parent / "test_records_pva.db")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ExampleEnum(StrictEnum):
|
|
26
|
+
a = "Aaa"
|
|
27
|
+
b = "Bbb"
|
|
28
|
+
c = "Ccc"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ExampleTable(Table):
|
|
32
|
+
bool: Array1D[np.bool_]
|
|
33
|
+
int: Array1D[np.int32]
|
|
34
|
+
float: Array1D[np.float64]
|
|
35
|
+
str: Sequence[str]
|
|
36
|
+
enum: Sequence[ExampleEnum]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ExampleCaDevice(EpicsDevice):
|
|
40
|
+
my_int: A[SignalRW[int], PvSuffix("int")]
|
|
41
|
+
my_float: A[SignalRW[float], PvSuffix("float")]
|
|
42
|
+
my_str: A[SignalRW[str], PvSuffix("str")]
|
|
43
|
+
my_bool: A[SignalRW[bool], PvSuffix("bool")]
|
|
44
|
+
enum: A[SignalRW[ExampleEnum], PvSuffix("enum")]
|
|
45
|
+
enum2: A[SignalRW[ExampleEnum], PvSuffix("enum2")]
|
|
46
|
+
bool_unnamed: A[SignalRW[bool], PvSuffix("bool_unnamed")]
|
|
47
|
+
partialint: A[SignalRW[int], PvSuffix("partialint")]
|
|
48
|
+
lessint: A[SignalRW[int], PvSuffix("lessint")]
|
|
49
|
+
uint8a: A[SignalRW[Array1D[np.uint8]], PvSuffix("uint8a")]
|
|
50
|
+
int16a: A[SignalRW[Array1D[np.int16]], PvSuffix("int16a")]
|
|
51
|
+
int32a: A[SignalRW[Array1D[np.int32]], PvSuffix("int32a")]
|
|
52
|
+
float32a: A[SignalRW[Array1D[np.float32]], PvSuffix("float32a")]
|
|
53
|
+
float64a: A[SignalRW[Array1D[np.float64]], PvSuffix("float64a")]
|
|
54
|
+
stra: A[SignalRW[Sequence[str]], PvSuffix("stra")]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ExamplePvaDevice(ExampleCaDevice): # pva can support all signal types that ca can
|
|
58
|
+
int8a: A[SignalRW[Array1D[np.int8]], PvSuffix("int8a")]
|
|
59
|
+
uint16a: A[SignalRW[Array1D[np.uint16]], PvSuffix("uint16a")]
|
|
60
|
+
uint32a: A[SignalRW[Array1D[np.uint32]], PvSuffix("uint32a")]
|
|
61
|
+
int64a: A[SignalRW[Array1D[np.int64]], PvSuffix("int64a")]
|
|
62
|
+
uint64a: A[SignalRW[Array1D[np.uint64]], PvSuffix("uint64a")]
|
|
63
|
+
table: A[SignalRW[ExampleTable], PvSuffix("table")]
|
|
64
|
+
ntndarray_data: A[SignalRW[Array1D[np.int64]], PvSuffix("ntndarray:data")]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
async def connect_example_device(
|
|
68
|
+
ioc: TestingIOC, protocol: Literal["ca", "pva"]
|
|
69
|
+
) -> ExamplePvaDevice | ExampleCaDevice:
|
|
70
|
+
"""Helper function to return a connected example device.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
|
|
75
|
+
ioc: TestingIOC
|
|
76
|
+
TestingIOC configured to provide the records needed for the device
|
|
77
|
+
|
|
78
|
+
protocol: Literal["ca", "pva"]
|
|
79
|
+
The transport protocol of the device
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
ExamplePvaDevice | ExampleCaDevice
|
|
84
|
+
a connected EpicsDevice with signals of many EPICS record types
|
|
85
|
+
"""
|
|
86
|
+
device_cls = ExamplePvaDevice if protocol == "pva" else ExampleCaDevice
|
|
87
|
+
device = device_cls(f"{protocol}://{ioc.prefix_for(device_cls)}")
|
|
88
|
+
await device.connect()
|
|
89
|
+
return device
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_example_ioc() -> TestingIOC:
|
|
93
|
+
"""Get TestingIOC instance with the example databases loaded.
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
TestingIOC
|
|
98
|
+
instance with test_records.db loaded for ExampleCaDevice and
|
|
99
|
+
test_records.db and test_records_pva.db loaded for ExamplePvaDevice.
|
|
100
|
+
"""
|
|
101
|
+
ioc = TestingIOC()
|
|
102
|
+
ioc.database_for(PVA_RECORDS, ExamplePvaDevice)
|
|
103
|
+
ioc.database_for(CA_PVA_RECORDS, ExamplePvaDevice)
|
|
104
|
+
ioc.database_for(CA_PVA_RECORDS, ExampleCaDevice)
|
|
105
|
+
return ioc
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import string
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
import time
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from aioca import purge_channel_caches
|
|
9
|
+
|
|
10
|
+
from ophyd_async.core import Device
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def generate_random_PV_prefix() -> str:
|
|
14
|
+
return "".join(random.choice(string.ascii_lowercase) for _ in range(12)) + ":"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TestingIOC:
|
|
18
|
+
_dbs: dict[type[Device], list[Path]] = {}
|
|
19
|
+
_prefixes: dict[type[Device], str] = {}
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def with_database(cls, db: Path | str): # use as a decorator
|
|
23
|
+
def inner(device_cls: type[Device]):
|
|
24
|
+
cls.database_for(db, device_cls)
|
|
25
|
+
return device_cls
|
|
26
|
+
|
|
27
|
+
return inner
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def database_for(cls, db, device_cls):
|
|
31
|
+
path = Path(db)
|
|
32
|
+
if not path.is_file():
|
|
33
|
+
raise OSError(f"{path} is not a file.")
|
|
34
|
+
if device_cls not in cls._dbs:
|
|
35
|
+
cls._dbs[device_cls] = []
|
|
36
|
+
cls._dbs[device_cls].append(path)
|
|
37
|
+
|
|
38
|
+
def prefix_for(self, device_cls):
|
|
39
|
+
# generate random prefix, return existing if already generated
|
|
40
|
+
return self._prefixes.setdefault(device_cls, generate_random_PV_prefix())
|
|
41
|
+
|
|
42
|
+
def start_ioc(self):
|
|
43
|
+
ioc_args = [
|
|
44
|
+
sys.executable,
|
|
45
|
+
"-m",
|
|
46
|
+
"epicscorelibs.ioc",
|
|
47
|
+
]
|
|
48
|
+
for device_cls, dbs in self._dbs.items():
|
|
49
|
+
prefix = self.prefix_for(device_cls)
|
|
50
|
+
for db in dbs:
|
|
51
|
+
ioc_args += ["-m", f"device={prefix}", "-d", str(db)]
|
|
52
|
+
self._process = subprocess.Popen(
|
|
53
|
+
ioc_args,
|
|
54
|
+
stdin=subprocess.PIPE,
|
|
55
|
+
stdout=subprocess.PIPE,
|
|
56
|
+
stderr=subprocess.STDOUT,
|
|
57
|
+
universal_newlines=True,
|
|
58
|
+
)
|
|
59
|
+
start_time = time.monotonic()
|
|
60
|
+
while "iocRun: All initialization complete" not in (
|
|
61
|
+
self._process.stdout.readline().strip() # type: ignore
|
|
62
|
+
):
|
|
63
|
+
if time.monotonic() - start_time > 10:
|
|
64
|
+
try:
|
|
65
|
+
print(self._process.communicate("exit()")[0])
|
|
66
|
+
except ValueError:
|
|
67
|
+
# Someone else already called communicate
|
|
68
|
+
pass
|
|
69
|
+
raise TimeoutError("IOC did not start in time")
|
|
70
|
+
|
|
71
|
+
def stop_ioc(self):
|
|
72
|
+
# close backend caches before the event loop
|
|
73
|
+
purge_channel_caches()
|
|
74
|
+
try:
|
|
75
|
+
print(self._process.communicate("exit()")[0])
|
|
76
|
+
except ValueError:
|
|
77
|
+
# Someone else already called communicate
|
|
78
|
+
pass
|