ophyd-async 0.3a6__tar.gz → 0.3.1a1__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.3a6 → ophyd_async-0.3.1a1}/PKG-INFO +2 -2
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/README.md +1 -1
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/how-to/write-tests-for-devices.rst +5 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/_version.py +2 -2
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/__init__.py +3 -5
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/detector.py +15 -10
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/mock_signal_backend.py +5 -8
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/mock_signal_utils.py +25 -11
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/signal_backend.py +1 -1
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/standard_readable.py +2 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/pilatus_controller.py +18 -5
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/pilatus_driver.py +2 -2
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/pilatus.py +21 -4
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_hdf_panda.py +0 -1
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/plan_stubs/fly.py +4 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/sim_pattern_generator.py +0 -2
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/PKG-INFO +2 -2
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_flyer.py +0 -2
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_mock_signal_backend.py +32 -27
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_standard_readable.py +12 -1
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_controllers.py +26 -16
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_pilatus.py +48 -6
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_scans.py +5 -3
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/demo/test_demo.py +24 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/plan_stubs/test_fly.py +45 -5
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.codecov.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.copier-answers.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.devcontainer/devcontainer.json +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.git-blame-ignore-revs +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/CONTRIBUTING.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/actions/install_requirements/action.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/dependabot.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/pages/index.html +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/pages/make_switcher.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/_check.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/_dist.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/_docs.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/_pypi.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/_release.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/_test.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/_tox.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/ci.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.github/workflows/periodic.yml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.gitignore +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.mailmap +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/.pre-commit-config.yaml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/Dockerfile +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/LICENSE +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/_templates/README +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/_templates/custom-class-template.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/_templates/custom-module-template.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/conf.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/examples/epics_demo.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/examples/foo_detector.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions/COPYME +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/decisions.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/design-goals.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/event-loop-choice.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations/flyscanning.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/explanations.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/genindex.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/how-to/choose-interfaces-for-devices.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/how-to/compound-devices.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/how-to/contribute.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/how-to/make-a-simple-device.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/how-to/make-a-standard-detector.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/how-to.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/images/bluesky_ophyd_epics_devices_logo.svg +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/images/bluesky_ophyd_logo.svg +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/images/ophyd_favicon.svg +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/index.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/reference/api.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/reference.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/tutorials/installation.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/tutorials/using-existing-devices.rst +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/docs/tutorials.md +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/pyproject.toml +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/setup.cfg +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/__main__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/_providers.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/async_status.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/device.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/device_save_loader.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/flyer.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/signal.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/soft_signal_backend.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/core/utils.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/_aioca.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/_p4p.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/_backend/common.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/aravis.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/ad_sim_controller.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/aravis_controller.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/kinetix_controller.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/controllers/vimba_controller.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/ad_base.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/aravis_driver.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/kinetix_driver.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/drivers/vimba_driver.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/kinetix.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/single_trigger_det.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/utils.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/vimba.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/_hdfdataset.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/_hdffile.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/hdf_writer.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/areadetector/writers/nd_plugin.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/demo_ad_sim_detector.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/mover.db +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/demo/sensor.db +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/motion/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/motion/motor.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/pvi/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/pvi/pvi.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/signal/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/signal/_epics_transport.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/epics/signal/signal.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/log.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_common_blocks.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_panda_controller.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_table.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_trigger.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/_utils.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/writers/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/writers/_hdf_writer.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/panda/writers/_panda_hdf_file.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/plan_stubs/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/plan_stubs/ensure_connected.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/protocols.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/demo/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/demo/sim_motor.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/pattern_generator.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/sim_pattern_detector_control.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async/sim/sim_pattern_detector_writer.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/SOURCES.txt +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/entry_points.txt +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/requires.txt +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/src/ophyd_async.egg-info/top_level.txt +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/conftest.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_async_status.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_device.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_device_collector.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_device_save_loader.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_signal.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_soft_signal_backend.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_utils.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/core/test_watchable_async_status.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/_backend/test_common.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_aravis.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_drivers.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_kinetix.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_single_trigger_det.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_utils.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_vimba.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/areadetector/test_writers.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/demo/test_demo_ad_sim_detector.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/motion/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/motion/test_motor.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/test_pvi.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/test_records.db +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/epics/test_signals.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/db/panda.db +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/test_hdf_panda.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/test_panda_connect.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/test_panda_controller.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/test_panda_utils.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/test_table.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/test_trigger.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/panda/test_writer.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/protocols/test_protocols.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/conftest.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/demo/__init__.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/demo/test_sim_motor.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/test_pattern_generator.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/test_sim_detector.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/test_sim_writer.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/sim/test_streaming_plan.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/test_cli.py +0 -0
- {ophyd_async-0.3a6 → ophyd_async-0.3.1a1}/tests/test_log.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1a1
|
|
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
|
|
@@ -96,7 +96,7 @@ Requires-Dist: types-pyyaml; extra == "dev"
|
|
|
96
96
|
|
|
97
97
|
# ophyd-async
|
|
98
98
|
|
|
99
|
-
Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
|
|
99
|
+
Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango.
|
|
100
100
|
|
|
101
101
|
| Source | <https://github.com/bluesky/ophyd-async> |
|
|
102
102
|
| :-----------: | :-----------------------------------------------: |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
# ophyd-async
|
|
7
7
|
|
|
8
|
-
Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
|
|
8
|
+
Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango.
|
|
9
9
|
|
|
10
10
|
| Source | <https://github.com/bluesky/ophyd-async> |
|
|
11
11
|
| :-----------: | :-----------------------------------------------: |
|
|
@@ -41,6 +41,11 @@ In addition this example also utilizes helper functions like ``assert_reading``
|
|
|
41
41
|
:pyobject: test_sensor_reading_shows_value
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
Given that the mock signal holds a ``unittest.mock.Mock`` object you can retrieve this object and assert that the device has been set correctly using ``get_mock_put``. You are also free to use any other behaviour that ``unittest.mock.Mock`` provides, such as in this example which sets the parent of the mock to allow ordering across signals to be asserted:
|
|
45
|
+
|
|
46
|
+
.. literalinclude:: ../../tests/epics/demo/test_demo.py
|
|
47
|
+
:pyobject: test_retrieve_mock_and_assert
|
|
48
|
+
|
|
44
49
|
There are several other test utility functions:
|
|
45
50
|
|
|
46
51
|
Use ``callback_on_mock_put``, for hooking in logic when a mock value changes (e.g. because someone puts to it). This can be called directly, or used as a context, with the callbacks ending after exit.
|
|
@@ -24,12 +24,10 @@ from .device_save_loader import (
|
|
|
24
24
|
walk_rw_signals,
|
|
25
25
|
)
|
|
26
26
|
from .flyer import HardwareTriggeredFlyable, TriggerLogic
|
|
27
|
-
from .mock_signal_backend import
|
|
28
|
-
MockSignalBackend,
|
|
29
|
-
)
|
|
27
|
+
from .mock_signal_backend import MockSignalBackend
|
|
30
28
|
from .mock_signal_utils import (
|
|
31
|
-
assert_mock_put_called_with,
|
|
32
29
|
callback_on_mock_put,
|
|
30
|
+
get_mock_put,
|
|
33
31
|
mock_puts_blocked,
|
|
34
32
|
reset_mock_put_calls,
|
|
35
33
|
set_mock_put_proceeds,
|
|
@@ -70,7 +68,7 @@ from .utils import (
|
|
|
70
68
|
)
|
|
71
69
|
|
|
72
70
|
__all__ = [
|
|
73
|
-
"
|
|
71
|
+
"get_mock_put",
|
|
74
72
|
"callback_on_mock_put",
|
|
75
73
|
"mock_puts_blocked",
|
|
76
74
|
"set_mock_values",
|
|
@@ -63,6 +63,8 @@ class TriggerInfo:
|
|
|
63
63
|
deadtime: float
|
|
64
64
|
#: What is the maximum high time of the triggers
|
|
65
65
|
livetime: float
|
|
66
|
+
#: What is the maximum timeout on waiting for a frame
|
|
67
|
+
frame_timeout: float | None = None
|
|
66
68
|
|
|
67
69
|
|
|
68
70
|
class DetectorControl(ABC):
|
|
@@ -162,7 +164,6 @@ class StandardDetector(
|
|
|
162
164
|
writer: DetectorWriter,
|
|
163
165
|
config_sigs: Sequence[AsyncReadable] = (),
|
|
164
166
|
name: str = "",
|
|
165
|
-
writer_timeout: float = DEFAULT_TIMEOUT,
|
|
166
167
|
) -> None:
|
|
167
168
|
"""
|
|
168
169
|
Constructor
|
|
@@ -173,16 +174,11 @@ class StandardDetector(
|
|
|
173
174
|
config_sigs: Signals to read when describe and read
|
|
174
175
|
configuration are called. Defaults to ().
|
|
175
176
|
name: Device name. Defaults to "".
|
|
176
|
-
writer_timeout: Timeout for frame writing to start, if the
|
|
177
|
-
timeout is reached, ophyd-async assumes the detector
|
|
178
|
-
has a problem and raises an error.
|
|
179
|
-
Defaults to DEFAULT_TIMEOUT.
|
|
180
177
|
"""
|
|
181
178
|
self._controller = controller
|
|
182
179
|
self._writer = writer
|
|
183
180
|
self._describe: Dict[str, DataKey] = {}
|
|
184
181
|
self._config_sigs = list(config_sigs)
|
|
185
|
-
self._frame_writing_timeout = writer_timeout
|
|
186
182
|
# For prepare
|
|
187
183
|
self._arm_status: Optional[AsyncStatus] = None
|
|
188
184
|
self._trigger_info: Optional[TriggerInfo] = None
|
|
@@ -245,17 +241,21 @@ class StandardDetector(
|
|
|
245
241
|
|
|
246
242
|
@AsyncStatus.wrap
|
|
247
243
|
async def trigger(self) -> None:
|
|
244
|
+
# set default trigger_info
|
|
245
|
+
self._trigger_info = TriggerInfo(
|
|
246
|
+
num=1, trigger=DetectorTrigger.internal, deadtime=0.0, livetime=0.0
|
|
247
|
+
)
|
|
248
248
|
# Arm the detector and wait for it to finish.
|
|
249
249
|
indices_written = await self.writer.get_indices_written()
|
|
250
250
|
written_status = await self.controller.arm(
|
|
251
|
-
num=
|
|
252
|
-
trigger=
|
|
251
|
+
num=self._trigger_info.num,
|
|
252
|
+
trigger=self._trigger_info.trigger,
|
|
253
253
|
)
|
|
254
254
|
await written_status
|
|
255
255
|
end_observation = indices_written + 1
|
|
256
256
|
|
|
257
257
|
async for index in self.writer.observe_indices_written(
|
|
258
|
-
self.
|
|
258
|
+
DEFAULT_TIMEOUT + self._trigger_info.livetime + self._trigger_info.deadtime
|
|
259
259
|
):
|
|
260
260
|
if index >= end_observation:
|
|
261
261
|
break
|
|
@@ -309,7 +309,12 @@ class StandardDetector(
|
|
|
309
309
|
assert self._arm_status, "Prepare not run"
|
|
310
310
|
assert self._trigger_info
|
|
311
311
|
async for index in self.writer.observe_indices_written(
|
|
312
|
-
self.
|
|
312
|
+
self._trigger_info.frame_timeout
|
|
313
|
+
or (
|
|
314
|
+
DEFAULT_TIMEOUT
|
|
315
|
+
+ self._trigger_info.livetime
|
|
316
|
+
+ self._trigger_info.deadtime
|
|
317
|
+
)
|
|
313
318
|
):
|
|
314
319
|
yield WatcherUpdate(
|
|
315
320
|
name=self.name,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from functools import cached_property
|
|
3
|
-
from typing import Optional, Type
|
|
3
|
+
from typing import Callable, Optional, Type
|
|
4
4
|
from unittest.mock import Mock
|
|
5
5
|
|
|
6
6
|
from bluesky.protocols import Descriptor, Reading
|
|
@@ -10,7 +10,7 @@ from ophyd_async.core.soft_signal_backend import SoftSignalBackend
|
|
|
10
10
|
from ophyd_async.core.utils import DEFAULT_TIMEOUT, ReadingValueCallback, T
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class MockSignalBackend(SignalBackend):
|
|
13
|
+
class MockSignalBackend(SignalBackend[T]):
|
|
14
14
|
def __init__(
|
|
15
15
|
self,
|
|
16
16
|
datatype: Optional[Type[T]] = None,
|
|
@@ -31,11 +31,11 @@ class MockSignalBackend(SignalBackend):
|
|
|
31
31
|
|
|
32
32
|
if not isinstance(self.initial_backend, SoftSignalBackend):
|
|
33
33
|
# If the backend is a hard signal backend, or not provided,
|
|
34
|
-
# then we create a soft signal to
|
|
34
|
+
# then we create a soft signal to mimic it
|
|
35
35
|
|
|
36
36
|
self.soft_backend = SoftSignalBackend(datatype=datatype)
|
|
37
37
|
else:
|
|
38
|
-
self.soft_backend = initial_backend
|
|
38
|
+
self.soft_backend = self.initial_backend
|
|
39
39
|
|
|
40
40
|
def source(self, name: str) -> str:
|
|
41
41
|
if self.initial_backend:
|
|
@@ -47,7 +47,7 @@ class MockSignalBackend(SignalBackend):
|
|
|
47
47
|
|
|
48
48
|
@cached_property
|
|
49
49
|
def put_mock(self) -> Mock:
|
|
50
|
-
return Mock(name="put")
|
|
50
|
+
return Mock(name="put", spec=Callable)
|
|
51
51
|
|
|
52
52
|
@cached_property
|
|
53
53
|
def put_proceeds(self) -> asyncio.Event:
|
|
@@ -65,9 +65,6 @@ class MockSignalBackend(SignalBackend):
|
|
|
65
65
|
def set_value(self, value: T):
|
|
66
66
|
self.soft_backend.set_value(value)
|
|
67
67
|
|
|
68
|
-
async def get_descriptor(self, source: str) -> Descriptor:
|
|
69
|
-
return await self.soft_backend.get_descriptor(source)
|
|
70
|
-
|
|
71
68
|
async def get_reading(self) -> Reading:
|
|
72
69
|
return await self.soft_backend.get_reading()
|
|
73
70
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from contextlib import asynccontextmanager, contextmanager
|
|
2
|
-
from typing import Any, Callable, Iterable
|
|
3
|
-
from unittest.mock import
|
|
2
|
+
from typing import Any, Callable, Iterable
|
|
3
|
+
from unittest.mock import Mock
|
|
4
4
|
|
|
5
5
|
from ophyd_async.core.signal import Signal
|
|
6
6
|
from ophyd_async.core.utils import T
|
|
@@ -22,7 +22,7 @@ def set_mock_value(signal: Signal[T], value: T):
|
|
|
22
22
|
backend.set_value(value)
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
def set_mock_put_proceeds(signal: Signal
|
|
25
|
+
def set_mock_put_proceeds(signal: Signal, proceeds: bool):
|
|
26
26
|
"""Allow or block a put with wait=True from proceeding"""
|
|
27
27
|
backend = _get_mock_signal_backend(signal)
|
|
28
28
|
|
|
@@ -33,7 +33,7 @@ def set_mock_put_proceeds(signal: Signal[T], proceeds: bool):
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
@asynccontextmanager
|
|
36
|
-
async def mock_puts_blocked(*signals:
|
|
36
|
+
async def mock_puts_blocked(*signals: Signal):
|
|
37
37
|
for signal in signals:
|
|
38
38
|
set_mock_put_proceeds(signal, False)
|
|
39
39
|
yield
|
|
@@ -41,9 +41,9 @@ async def mock_puts_blocked(*signals: List[Signal]):
|
|
|
41
41
|
set_mock_put_proceeds(signal, True)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
def get_mock_put(signal: Signal) -> Mock:
|
|
45
|
+
"""Get the mock associated with the put call on the signal."""
|
|
46
|
+
return _get_mock_signal_backend(signal).put_mock
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def reset_mock_put_calls(signal: Signal):
|
|
@@ -79,15 +79,29 @@ class _SetValuesIterator:
|
|
|
79
79
|
return next_value
|
|
80
80
|
|
|
81
81
|
def __del__(self):
|
|
82
|
-
if self.require_all_consumed
|
|
83
|
-
|
|
82
|
+
if self.require_all_consumed:
|
|
83
|
+
# Values is cast to a list here because the user has supplied
|
|
84
|
+
# require_all_consumed=True, we can therefore assume they
|
|
85
|
+
# supplied a finite list.
|
|
86
|
+
# In the case of require_all_consumed=False, an infinite
|
|
87
|
+
# iterble is permitted
|
|
88
|
+
values = list(self.values)
|
|
89
|
+
if self.index != len(values):
|
|
90
|
+
# Report the values consumed and the values yet to be
|
|
91
|
+
# consumed
|
|
92
|
+
consumed = values[0 : self.index]
|
|
93
|
+
to_be_consumed = values[self.index :]
|
|
94
|
+
raise AssertionError(
|
|
95
|
+
f"{self.signal.name}: {consumed} were consumed "
|
|
96
|
+
f"but {to_be_consumed} were not consumed"
|
|
97
|
+
)
|
|
84
98
|
|
|
85
99
|
|
|
86
100
|
def set_mock_values(
|
|
87
101
|
signal: Signal,
|
|
88
102
|
values: Iterable[Any],
|
|
89
103
|
require_all_consumed: bool = False,
|
|
90
|
-
) ->
|
|
104
|
+
) -> _SetValuesIterator:
|
|
91
105
|
"""Iterator to set a signal to a sequence of values, optionally repeating the
|
|
92
106
|
sequence.
|
|
93
107
|
|
|
@@ -127,7 +141,7 @@ def _unset_side_effect_cm(put_mock: Mock):
|
|
|
127
141
|
put_mock.side_effect = None
|
|
128
142
|
|
|
129
143
|
|
|
130
|
-
def callback_on_mock_put(signal: Signal, callback: Callable[[T], None]):
|
|
144
|
+
def callback_on_mock_put(signal: Signal[T], callback: Callable[[T], None]):
|
|
131
145
|
"""For setting a callback when a backend is put to.
|
|
132
146
|
|
|
133
147
|
Can either be used in a context, with the callback being
|
|
@@ -14,7 +14,7 @@ class SignalBackend(Generic[T]):
|
|
|
14
14
|
|
|
15
15
|
#: Like ca://PV_PREFIX:SIGNAL
|
|
16
16
|
@abstractmethod
|
|
17
|
-
def source(name: str) -> str:
|
|
17
|
+
def source(self, name: str) -> str:
|
|
18
18
|
"""Return source of signal. Signals may pass a name to the backend, which can be
|
|
19
19
|
used or discarded."""
|
|
20
20
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
|
+
from ophyd_async.core import DEFAULT_TIMEOUT, wait_for_value
|
|
4
5
|
from ophyd_async.core.async_status import AsyncStatus
|
|
5
6
|
from ophyd_async.core.detector import DetectorControl, DetectorTrigger
|
|
6
7
|
from ophyd_async.epics.areadetector.drivers.ad_base import (
|
|
@@ -23,14 +24,13 @@ class PilatusController(DetectorControl):
|
|
|
23
24
|
def __init__(
|
|
24
25
|
self,
|
|
25
26
|
driver: PilatusDriver,
|
|
27
|
+
readout_time: float,
|
|
26
28
|
) -> None:
|
|
27
29
|
self._drv = driver
|
|
30
|
+
self._readout_time = readout_time
|
|
28
31
|
|
|
29
32
|
def get_deadtime(self, exposure: float) -> float:
|
|
30
|
-
|
|
31
|
-
"""The required minimum time difference between ExpPeriod and ExpTime
|
|
32
|
-
(readout time) is 2.28 ms"""
|
|
33
|
-
return 2.28e-3
|
|
33
|
+
return self._readout_time
|
|
34
34
|
|
|
35
35
|
async def arm(
|
|
36
36
|
self,
|
|
@@ -45,7 +45,20 @@ class PilatusController(DetectorControl):
|
|
|
45
45
|
self._drv.num_images.set(999_999 if num == 0 else num),
|
|
46
46
|
self._drv.image_mode.set(ImageMode.multiple),
|
|
47
47
|
)
|
|
48
|
-
|
|
48
|
+
|
|
49
|
+
# Standard arm the detector and wait for the acquire PV to be True
|
|
50
|
+
idle_status = await start_acquiring_driver_and_ensure_status(self._drv)
|
|
51
|
+
|
|
52
|
+
# The pilatus has an additional PV that goes True when the camserver
|
|
53
|
+
# is actually ready. Should wait for that too or we risk dropping
|
|
54
|
+
# a frame
|
|
55
|
+
await wait_for_value(
|
|
56
|
+
self._drv.armed_for_triggers,
|
|
57
|
+
True,
|
|
58
|
+
timeout=DEFAULT_TIMEOUT,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return idle_status
|
|
49
62
|
|
|
50
63
|
@classmethod
|
|
51
64
|
def _get_trigger_mode(cls, trigger: DetectorTrigger) -> PilatusTriggerMode:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
|
|
3
|
+
from ...signal import epics_signal_r, epics_signal_rw_rbv
|
|
5
4
|
from .ad_base import ADBase
|
|
6
5
|
|
|
7
6
|
|
|
@@ -18,4 +17,5 @@ class PilatusDriver(ADBase):
|
|
|
18
17
|
self.trigger_mode = epics_signal_rw_rbv(
|
|
19
18
|
PilatusTriggerMode, prefix + "TriggerMode"
|
|
20
19
|
)
|
|
20
|
+
self.armed_for_triggers = epics_signal_r(bool, prefix + "Armed")
|
|
21
21
|
super().__init__(prefix, name)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
1
3
|
from bluesky.protocols import Hints
|
|
2
4
|
|
|
3
5
|
from ophyd_async.core import DirectoryProvider
|
|
@@ -11,6 +13,20 @@ from ophyd_async.epics.areadetector.writers.hdf_writer import HDFWriter
|
|
|
11
13
|
from ophyd_async.epics.areadetector.writers.nd_file_hdf import NDFileHDF
|
|
12
14
|
|
|
13
15
|
|
|
16
|
+
#: Cite: https://media.dectris.com/User_Manual-PILATUS2-V1_4.pdf
|
|
17
|
+
#: The required minimum time difference between ExpPeriod and ExpTime
|
|
18
|
+
#: (readout time) is 2.28 ms
|
|
19
|
+
#: We provide an option to override for newer Pilatus models
|
|
20
|
+
class PilatusReadoutTime(float, Enum):
|
|
21
|
+
"""Pilatus readout time per model in ms"""
|
|
22
|
+
|
|
23
|
+
# Cite: https://media.dectris.com/User_Manual-PILATUS2-V1_4.pdf
|
|
24
|
+
pilatus2 = 2.28e-3
|
|
25
|
+
|
|
26
|
+
# Cite: https://media.dectris.com/user-manual-pilatus3-2020.pdf
|
|
27
|
+
pilatus3 = 0.95e-3
|
|
28
|
+
|
|
29
|
+
|
|
14
30
|
class PilatusDetector(StandardDetector):
|
|
15
31
|
"""A Pilatus StandardDetector writing HDF files"""
|
|
16
32
|
|
|
@@ -21,15 +37,16 @@ class PilatusDetector(StandardDetector):
|
|
|
21
37
|
self,
|
|
22
38
|
prefix: str,
|
|
23
39
|
directory_provider: DirectoryProvider,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
readout_time: PilatusReadoutTime = PilatusReadoutTime.pilatus3,
|
|
41
|
+
drv_suffix: str = "cam1:",
|
|
42
|
+
hdf_suffix: str = "HDF1:",
|
|
43
|
+
name: str = "",
|
|
27
44
|
):
|
|
28
45
|
self.drv = PilatusDriver(prefix + drv_suffix)
|
|
29
46
|
self.hdf = NDFileHDF(prefix + hdf_suffix)
|
|
30
47
|
|
|
31
48
|
super().__init__(
|
|
32
|
-
PilatusController(self.drv),
|
|
49
|
+
PilatusController(self.drv, readout_time=readout_time.value),
|
|
33
50
|
HDFWriter(
|
|
34
51
|
self.hdf,
|
|
35
52
|
directory_provider,
|
|
@@ -18,6 +18,7 @@ def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
|
|
|
18
18
|
shutter_time: float,
|
|
19
19
|
repeats: int = 1,
|
|
20
20
|
period: float = 0.0,
|
|
21
|
+
frame_timeout: float | None = None,
|
|
21
22
|
):
|
|
22
23
|
"""Prepare a hardware triggered flyable and one or more detectors.
|
|
23
24
|
|
|
@@ -39,6 +40,7 @@ def prepare_static_seq_table_flyer_and_detectors_with_same_trigger(
|
|
|
39
40
|
trigger=DetectorTrigger.constant_gate,
|
|
40
41
|
deadtime=deadtime,
|
|
41
42
|
livetime=exposure,
|
|
43
|
+
frame_timeout=frame_timeout,
|
|
42
44
|
)
|
|
43
45
|
trigger_time = number_of_frames * (exposure + deadtime)
|
|
44
46
|
pre_delay = max(period - 2 * shutter_time - trigger_time, 0)
|
|
@@ -120,6 +122,7 @@ def time_resolved_fly_and_collect_with_static_seq_table(
|
|
|
120
122
|
shutter_time: float,
|
|
121
123
|
repeats: int = 1,
|
|
122
124
|
period: float = 0.0,
|
|
125
|
+
frame_timeout: float | None = None,
|
|
123
126
|
):
|
|
124
127
|
"""Run a scan wth a flyer and multiple detectors.
|
|
125
128
|
|
|
@@ -144,6 +147,7 @@ def time_resolved_fly_and_collect_with_static_seq_table(
|
|
|
144
147
|
shutter_time=shutter_time,
|
|
145
148
|
repeats=repeats,
|
|
146
149
|
period=period,
|
|
150
|
+
frame_timeout=frame_timeout,
|
|
147
151
|
)
|
|
148
152
|
# Run the fly scan
|
|
149
153
|
yield from fly_and_collect(stream_name, flyer, detectors)
|
|
@@ -16,7 +16,6 @@ class SimPatternDetector(StandardDetector):
|
|
|
16
16
|
path: Path,
|
|
17
17
|
config_sigs: Sequence[AsyncReadable] = [],
|
|
18
18
|
name: str = "sim_pattern_detector",
|
|
19
|
-
writer_timeout: float = 1,
|
|
20
19
|
) -> None:
|
|
21
20
|
self.directory_provider: DirectoryProvider = StaticDirectoryProvider(path)
|
|
22
21
|
self.pattern_generator = PatternGenerator()
|
|
@@ -33,5 +32,4 @@ class SimPatternDetector(StandardDetector):
|
|
|
33
32
|
writer=writer,
|
|
34
33
|
config_sigs=config_sigs,
|
|
35
34
|
name=name,
|
|
36
|
-
writer_timeout=writer_timeout,
|
|
37
35
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1a1
|
|
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
|
|
@@ -96,7 +96,7 @@ Requires-Dist: types-pyyaml; extra == "dev"
|
|
|
96
96
|
|
|
97
97
|
# ophyd-async
|
|
98
98
|
|
|
99
|
-
Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango
|
|
99
|
+
Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango.
|
|
100
100
|
|
|
101
101
|
| Source | <https://github.com/bluesky/ophyd-async> |
|
|
102
102
|
| :-----------: | :-----------------------------------------------: |
|
|
@@ -124,13 +124,11 @@ async def detectors(RE: RunEngine) -> tuple[StandardDetector, StandardDetector]:
|
|
|
124
124
|
Mock(spec=DetectorControl, get_deadtime=lambda num: num, arm=dummy_arm_1),
|
|
125
125
|
writers[0],
|
|
126
126
|
name="detector_1",
|
|
127
|
-
writer_timeout=3,
|
|
128
127
|
)
|
|
129
128
|
detector_2: StandardDetector[Any] = StandardDetector(
|
|
130
129
|
Mock(spec=DetectorControl, get_deadtime=lambda num: num, arm=dummy_arm_2),
|
|
131
130
|
writers[1],
|
|
132
131
|
name="detector_2",
|
|
133
|
-
writer_timeout=3,
|
|
134
132
|
)
|
|
135
133
|
|
|
136
134
|
return (detector_1, detector_2)
|
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import re
|
|
3
3
|
from itertools import repeat
|
|
4
|
-
from unittest.mock import MagicMock, call
|
|
4
|
+
from unittest.mock import ANY, MagicMock, call
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
8
|
from ophyd_async.core import MockSignalBackend, SignalRW
|
|
9
9
|
from ophyd_async.core.device import Device, DeviceCollector
|
|
10
10
|
from ophyd_async.core.mock_signal_utils import (
|
|
11
|
-
assert_mock_put_called_with,
|
|
12
11
|
callback_on_mock_put,
|
|
12
|
+
get_mock_put,
|
|
13
13
|
mock_puts_blocked,
|
|
14
14
|
reset_mock_put_calls,
|
|
15
15
|
set_mock_put_proceeds,
|
|
16
16
|
set_mock_value,
|
|
17
17
|
set_mock_values,
|
|
18
18
|
)
|
|
19
|
-
from ophyd_async.core.signal import
|
|
20
|
-
SignalW,
|
|
21
|
-
soft_signal_r_and_setter,
|
|
22
|
-
soft_signal_rw,
|
|
23
|
-
)
|
|
19
|
+
from ophyd_async.core.signal import SignalW, soft_signal_r_and_setter, soft_signal_rw
|
|
24
20
|
from ophyd_async.core.soft_signal_backend import SoftSignalBackend
|
|
25
21
|
from ophyd_async.epics.signal.signal import epics_signal_r, epics_signal_rw
|
|
26
22
|
|
|
@@ -31,6 +27,7 @@ async def test_mock_signal_backend(connect_mock_mode):
|
|
|
31
27
|
# If mock is false it will be handled like a normal signal, otherwise it will
|
|
32
28
|
# initalize a new backend from the one in the line above
|
|
33
29
|
await mock_signal.connect(mock=connect_mock_mode)
|
|
30
|
+
assert isinstance(mock_signal._backend, MockSignalBackend)
|
|
34
31
|
|
|
35
32
|
assert await mock_signal._backend.get_value() == ""
|
|
36
33
|
await mock_signal._backend.put("test")
|
|
@@ -74,6 +71,8 @@ async def test_set_mock_put_proceeds():
|
|
|
74
71
|
mock_signal = SignalW(SoftSignalBackend(str))
|
|
75
72
|
await mock_signal.connect(mock=True)
|
|
76
73
|
|
|
74
|
+
assert isinstance(mock_signal._backend, MockSignalBackend)
|
|
75
|
+
|
|
77
76
|
assert mock_signal._backend.put_proceeds.is_set() is True
|
|
78
77
|
|
|
79
78
|
set_mock_put_proceeds(mock_signal, False)
|
|
@@ -95,6 +94,7 @@ async def test_set_mock_put_proceeds_timeout():
|
|
|
95
94
|
async def test_put_proceeds_timeout():
|
|
96
95
|
mock_signal = SignalW(SoftSignalBackend(str))
|
|
97
96
|
await mock_signal.connect(mock=True)
|
|
97
|
+
assert isinstance(mock_signal._backend, MockSignalBackend)
|
|
98
98
|
|
|
99
99
|
assert mock_signal._backend.put_proceeds.is_set() is True
|
|
100
100
|
|
|
@@ -112,14 +112,14 @@ async def test_mock_utils_throw_error_if_backend_isnt_mock_signal_backend():
|
|
|
112
112
|
set_mock_value(signal, 10)
|
|
113
113
|
exc_msgs.append(str(exc.value))
|
|
114
114
|
with pytest.raises(AssertionError) as exc:
|
|
115
|
-
|
|
115
|
+
get_mock_put(signal).assert_called_once_with(10)
|
|
116
116
|
exc_msgs.append(str(exc.value))
|
|
117
117
|
with pytest.raises(AssertionError) as exc:
|
|
118
|
-
async with mock_puts_blocked(signal
|
|
118
|
+
async with mock_puts_blocked(signal):
|
|
119
119
|
...
|
|
120
120
|
exc_msgs.append(str(exc.value))
|
|
121
121
|
with pytest.raises(AssertionError) as exc:
|
|
122
|
-
with callback_on_mock_put(signal,
|
|
122
|
+
with callback_on_mock_put(signal, lambda x: _):
|
|
123
123
|
...
|
|
124
124
|
exc_msgs.append(str(exc.value))
|
|
125
125
|
with pytest.raises(AssertionError) as exc:
|
|
@@ -137,16 +137,13 @@ async def test_mock_utils_throw_error_if_backend_isnt_mock_signal_backend():
|
|
|
137
137
|
)
|
|
138
138
|
|
|
139
139
|
|
|
140
|
-
async def
|
|
140
|
+
async def test_get_mock_put():
|
|
141
141
|
mock_signal = epics_signal_rw(str, "READ_PV", "WRITE_PV", name="mock_name")
|
|
142
142
|
await mock_signal.connect(mock=True)
|
|
143
143
|
await mock_signal.set("test_value", wait=True, timeout=100)
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
assert_mock_put_called_with(mock_signal, "test_value", wait=True)
|
|
148
|
-
assert_mock_put_called_with(mock_signal, "test_value", timeout=100)
|
|
149
|
-
assert_mock_put_called_with(mock_signal, "test_value", wait=True, timeout=100)
|
|
145
|
+
mock = get_mock_put(mock_signal)
|
|
146
|
+
mock.assert_called_once_with("test_value", wait=True, timeout=100)
|
|
150
147
|
|
|
151
148
|
def err_text(text, wait, timeout):
|
|
152
149
|
return (
|
|
@@ -162,7 +159,7 @@ async def test_assert_mock_put_called_with():
|
|
|
162
159
|
("test_value", False, 0), # wait and timeout wrong
|
|
163
160
|
]:
|
|
164
161
|
with pytest.raises(AssertionError) as exc:
|
|
165
|
-
|
|
162
|
+
mock.assert_called_once_with(text, wait=wait, timeout=timeout)
|
|
166
163
|
for err_substr in err_text(text, wait, timeout):
|
|
167
164
|
assert err_substr in str(exc.value)
|
|
168
165
|
|
|
@@ -216,10 +213,8 @@ async def test_callback_on_mock_put_no_ctx():
|
|
|
216
213
|
mock_signal = SignalRW(SoftSignalBackend(float))
|
|
217
214
|
await mock_signal.connect(mock=True)
|
|
218
215
|
calls = []
|
|
219
|
-
(
|
|
220
|
-
|
|
221
|
-
mock_signal, lambda *args, **kwargs: calls.append({**kwargs, "_args": args})
|
|
222
|
-
),
|
|
216
|
+
callback_on_mock_put(
|
|
217
|
+
mock_signal, lambda *args, **kwargs: calls.append({**kwargs, "_args": args})
|
|
223
218
|
)
|
|
224
219
|
await mock_signal.set(10.0)
|
|
225
220
|
assert calls == [
|
|
@@ -249,16 +244,16 @@ async def test_callback_on_mock_put_fails_if_args_are_not_correct():
|
|
|
249
244
|
async def test_set_mock_values(mock_signals):
|
|
250
245
|
signal1, signal2 = mock_signals
|
|
251
246
|
|
|
252
|
-
await signal2.get_value() == "first_value"
|
|
247
|
+
assert await signal2.get_value() == "first_value"
|
|
253
248
|
for value_set in set_mock_values(signal1, ["second_value", "third_value"]):
|
|
254
249
|
assert await signal1.get_value() == value_set
|
|
255
250
|
|
|
256
251
|
iterator = set_mock_values(signal2, ["second_value", "third_value"])
|
|
257
|
-
await signal2.get_value() == "first_value"
|
|
252
|
+
assert await signal2.get_value() == "first_value"
|
|
258
253
|
next(iterator)
|
|
259
|
-
await signal2.get_value() == "second_value"
|
|
254
|
+
assert await signal2.get_value() == "second_value"
|
|
260
255
|
next(iterator)
|
|
261
|
-
await signal2.get_value() == "third_value"
|
|
256
|
+
assert await signal2.get_value() == "third_value"
|
|
262
257
|
|
|
263
258
|
|
|
264
259
|
async def test_set_mock_values_exhausted_passes(mock_signals):
|
|
@@ -300,10 +295,10 @@ async def test_set_mock_values_exhausted_fails(mock_signals):
|
|
|
300
295
|
async def test_reset_mock_put_calls(mock_signals):
|
|
301
296
|
signal1, signal2 = mock_signals
|
|
302
297
|
await signal1.set("test_value", wait=True, timeout=1)
|
|
303
|
-
|
|
298
|
+
get_mock_put(signal1).assert_called_with("test_value", wait=ANY, timeout=ANY)
|
|
304
299
|
reset_mock_put_calls(signal1)
|
|
305
300
|
with pytest.raises(AssertionError) as exc:
|
|
306
|
-
|
|
301
|
+
get_mock_put(signal1).assert_called_with("test_value", wait=ANY, timeout=ANY)
|
|
307
302
|
# Replacing spaces because they change between runners
|
|
308
303
|
# (e.g the github actions runner has more)
|
|
309
304
|
assert str(exc.value).replace(" ", "").replace("\n", "") == (
|
|
@@ -350,3 +345,13 @@ async def test_writing_to_soft_signals_in_mock():
|
|
|
350
345
|
assert await signal.get_value() == 0
|
|
351
346
|
backend_put(100)
|
|
352
347
|
assert await signal.get_value() == 100
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
async def test_when_put_mock_called_with_typo_then_fails_but_calling_directly_passes():
|
|
351
|
+
mock_signal = SignalRW(SoftSignalBackend(int))
|
|
352
|
+
await mock_signal.connect(mock=True)
|
|
353
|
+
assert isinstance(mock_signal._backend, MockSignalBackend)
|
|
354
|
+
mock = mock_signal._backend.put_mock
|
|
355
|
+
with pytest.raises(AttributeError):
|
|
356
|
+
mock.asssert_called_once() # Note typo here is deliberate!
|
|
357
|
+
mock()
|