ophyd-async 0.14.1__tar.gz → 0.14.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ophyd_async-0.14.1/src/ophyd_async.egg-info → ophyd_async-0.14.2}/PKG-INFO +1 -1
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/_version.py +3 -3
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_derived_signal.py +56 -23
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_device_filler.py +28 -3
- {ophyd_async-0.14.1 → ophyd_async-0.14.2/src/ophyd_async.egg-info}/PKG-INFO +1 -1
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_device.py +48 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_multi_derived_signal.py +62 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_observe.py +8 -4
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_single_derived_signal.py +24 -1
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/pvi/test_pvi.py +17 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.codecov.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.copier-answers.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.devcontainer/devcontainer.json +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.git-blame-ignore-revs +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/CONTRIBUTING.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/codeql/codeql-config.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/pages/index.html +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/pages/make_switcher.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/_codeql.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/_dist.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/_docs.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/_pypi.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/_release.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/_test.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/_tox.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/ci.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/claude.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/workflows/periodic.yml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.gitignore +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.gitleaks.toml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.gitmodules +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.pre-commit-config.yaml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/.python-version +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/Dockerfile +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/LICENSE +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/README.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/_static/custom.css +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/conf.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0008-signal-types.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0010-docstring-format.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0011-buffer-updates-camonitor.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/COPYME +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/declarative-vs-procedural.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/design-goals.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/device-connection-strategies.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/devices-signals-backends.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/fly-scanning.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/plan-stubs.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/when-to-extend-movable.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/where-device-logic.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/genindex.rst +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to/choose-right-baseclass.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to/contribute.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to/derive-one-signal-from-others.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to/implement-ad-detector.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to/interact-with-signals.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to/put-device-back.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to/store-and-retrieve.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/how-to.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/images/ophyd-async-logo.svg +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/images/ophyd-favicon.svg +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/index.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/reference.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/tutorials/implementing-detectors.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/tutorials/implementing-devices.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/tutorials/installation.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/tutorials/using-devices.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/tutorials/writing-tests-for-devices.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/tutorials.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/pyproject.toml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/renovate.json +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/setup.cfg +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/__main__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/_docs_parser.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_device.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_enums.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_flyer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_hdf_dataset.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_log.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_mock_signal_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_protocol.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_providers.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_readable.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_settings.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_signal.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_signal_backend.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_status.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_table.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/core/_yaml_settings.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/_andor.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_logic.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_writer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_hdf_writer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_aioca.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_epics_device.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_p4p.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_signal.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_util.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/__main__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_ioc.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_motor.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_stage.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/motor.db +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/point_detector.db +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/motor.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/odin/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/odin/_odin_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_pmac_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_pmac_trajectory.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_pmac_trajectory_generation.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/signal.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/test_records.db +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/core.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/_eiger_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_jungfrau.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_signals.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_block.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_control.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_table.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_fly.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_panda.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_settings.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/py.typed +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/__main__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_blob_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_motor.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_pattern_generator.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_point_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/sim/_stage.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_base_device.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_converters.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_signal.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_tango_transport.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_counter.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_mover.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/testing/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/tango/testing/_test_config.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/testing/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/testing/_assert.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/testing/_single_derived.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/testing/_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/SOURCES.txt +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/requires.txt +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/top_level.txt +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/README.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/conftest.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/conftest.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/adsim/baseline.yaml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/adsim/external_dependencies.sh +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/adsim/test_adsim_system.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/eiger/README.md +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/eiger/test_eiger_system.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/signal/test_signals.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/signal/test_yaml_save_ca.yaml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/epics/signal/test_yaml_save_pva.yaml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/fastcs/panda/test_panda_connect.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests/test_tutorials.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests_tango/conftest.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests_tango/context_subprocess.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests_tango/test_base_device.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests_tango/test_tango_signals.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/system_tests_tango/test_tango_transport.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_auto_init_devices.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_flyer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_log.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_mock_signal_backend.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_protocol.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_providers.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_readable.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_signal.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_soft_signal_backend.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_status.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_subset_enum.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_table.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_watchable_async_status.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adandor/test_andor.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adaravis/test_aravis.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_cont_acq_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_detectors.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_drivers.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_plugins.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_scans.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_single_trigger.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_writers.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adkinetix/test_kinetix.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adpilatus/test_pilatus.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/adsimdetector/test_sim.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/advimba/test_vimba.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/conftest.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/demo/test_epics_demo.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/eiger/test_odin_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/conftest.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_io.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_trajectory.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_trajectory_generation.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/signal/test_common.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/test_areadetector_subclass_naming.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/epics/test_motor.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/eiger/test_eiger_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/eiger/test_eiger_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/jungfrau/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/jungfrau/test_controller.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/jungfrau/test_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/db/panda.db +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_hdf_panda.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_panda_connect_mock.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_panda_control.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_panda_utils.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_seq_table.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_trigger.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_writer.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_ensure_connected.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_fly.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_settings.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_setup.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/sim/__init__.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/sim/test_sim_blob_detector.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/sim/test_sim_motor.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/test_branching.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/test_cli.py +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/test_data/test_yaml_config_save.yaml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/test_data/test_yaml_save.yaml +0 -0
- {ophyd_async-0.14.1 → ophyd_async-0.14.2}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.14.
|
|
3
|
+
Version: 0.14.2
|
|
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
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.14.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 14,
|
|
31
|
+
__version__ = version = '0.14.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 14, 2)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'ga221add53'
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
from
|
|
1
|
+
import functools
|
|
2
|
+
from collections.abc import Awaitable, Callable, Mapping
|
|
3
|
+
from inspect import Parameter, signature
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
Generic,
|
|
7
|
+
TypeVar,
|
|
8
|
+
get_args,
|
|
9
|
+
get_origin,
|
|
10
|
+
get_type_hints,
|
|
11
|
+
is_typeddict,
|
|
12
|
+
)
|
|
3
13
|
|
|
4
14
|
from bluesky.protocols import Locatable
|
|
5
15
|
|
|
@@ -53,12 +63,13 @@ class DerivedSignalFactory(Generic[TransformT]):
|
|
|
53
63
|
# Populate expected parameters and types
|
|
54
64
|
expected = {
|
|
55
65
|
**{k: f.annotation for k, f in transform_cls.model_fields.items()},
|
|
56
|
-
**
|
|
57
|
-
k: v
|
|
58
|
-
for k, v in get_type_hints(transform_cls.raw_to_derived).items()
|
|
59
|
-
if k not in {"self", "return"}
|
|
60
|
-
},
|
|
66
|
+
**_get_params_types_dict(transform_cls.raw_to_derived),
|
|
61
67
|
}
|
|
68
|
+
if empty_keys := [k for k, v in expected.items() if v == Parameter.empty]:
|
|
69
|
+
raise TypeError(
|
|
70
|
+
f"{transform_cls.raw_to_derived} is missing a type "
|
|
71
|
+
f"hint for arguments: {empty_keys}"
|
|
72
|
+
)
|
|
62
73
|
|
|
63
74
|
# Populate received parameters and types
|
|
64
75
|
# Use Primitive's type, Signal's datatype,
|
|
@@ -76,7 +87,19 @@ class DerivedSignalFactory(Generic[TransformT]):
|
|
|
76
87
|
f"Expected the following to be passed as keyword arguments "
|
|
77
88
|
f"{expected}, got {received}"
|
|
78
89
|
)
|
|
79
|
-
|
|
90
|
+
if set(expected.keys()) - set(received.keys()):
|
|
91
|
+
raise TypeError(msg)
|
|
92
|
+
|
|
93
|
+
for k in set(expected.keys()):
|
|
94
|
+
if isinstance(expected[k], type):
|
|
95
|
+
if not issubclass(received[k], expected[k]):
|
|
96
|
+
raise TypeError(msg)
|
|
97
|
+
elif isinstance(expected[k], TypeVar):
|
|
98
|
+
bound = expected[k].__bound__
|
|
99
|
+
if isinstance(bound, type) and not issubclass(
|
|
100
|
+
received[k], bound
|
|
101
|
+
):
|
|
102
|
+
raise TypeError(msg)
|
|
80
103
|
self._set_derived_takes_dict = (
|
|
81
104
|
is_typeddict(_get_first_arg_datatype(set_derived)) if set_derived else False
|
|
82
105
|
)
|
|
@@ -195,28 +218,28 @@ def _get_return_datatype(func: Callable[..., SignalDatatypeT]) -> type[SignalDat
|
|
|
195
218
|
def _get_first_arg_datatype(
|
|
196
219
|
func: Callable[[SignalDatatypeT], Any],
|
|
197
220
|
) -> type[SignalDatatypeT]:
|
|
198
|
-
args =
|
|
199
|
-
args.pop("return", None)
|
|
221
|
+
args = _get_params_types_dict(func)
|
|
200
222
|
if not args:
|
|
201
223
|
msg = f"{func} does not have a type hinted argument"
|
|
202
224
|
raise TypeError(msg)
|
|
203
225
|
return list(args.values())[0]
|
|
204
226
|
|
|
205
227
|
|
|
228
|
+
def _get_params_types_dict(inspected_function: Callable) -> Mapping[str, Any]:
|
|
229
|
+
sig = signature(inspected_function, eval_str=True)
|
|
230
|
+
exclude_keys = {"self", "args", "kwargs", "cls"}
|
|
231
|
+
return {k: v.annotation for k, v in sig.parameters.items() if k not in exclude_keys}
|
|
232
|
+
|
|
233
|
+
|
|
206
234
|
def _make_factory(
|
|
207
|
-
|
|
235
|
+
raw_to_derived_func: Callable[..., SignalDatatypeT] | None = None,
|
|
208
236
|
set_derived: Callable[[SignalDatatypeT], Awaitable[None]] | None = None,
|
|
209
237
|
raw_devices_and_constants: dict[str, Device | Primitive] | None = None,
|
|
210
238
|
) -> DerivedSignalFactory:
|
|
211
|
-
if
|
|
239
|
+
if raw_to_derived_func:
|
|
212
240
|
|
|
213
241
|
class DerivedTransform(Transform):
|
|
214
|
-
|
|
215
|
-
return {"value": raw_to_derived(**kwargs)}
|
|
216
|
-
|
|
217
|
-
# Update the signature for raw_to_derived to match what we are passed as this
|
|
218
|
-
# will be checked in DerivedSignalFactory
|
|
219
|
-
DerivedTransform.raw_to_derived.__annotations__ = get_type_hints(raw_to_derived)
|
|
242
|
+
raw_to_derived = _dict_wrapper(raw_to_derived_func)
|
|
220
243
|
|
|
221
244
|
return DerivedSignalFactory(
|
|
222
245
|
DerivedTransform,
|
|
@@ -245,7 +268,7 @@ def derived_signal_r(
|
|
|
245
268
|
The names of these arguments must match the arguments of raw_to_derived.
|
|
246
269
|
"""
|
|
247
270
|
factory = _make_factory(
|
|
248
|
-
|
|
271
|
+
raw_to_derived_func=raw_to_derived,
|
|
249
272
|
raw_devices_and_constants=raw_devices_and_constants,
|
|
250
273
|
)
|
|
251
274
|
return factory.derived_signal_r(
|
|
@@ -278,16 +301,16 @@ def derived_signal_rw(
|
|
|
278
301
|
The names of these arguments must match the arguments of raw_to_derived.
|
|
279
302
|
"""
|
|
280
303
|
raw_to_derived_datatype = _get_return_datatype(raw_to_derived)
|
|
281
|
-
|
|
282
|
-
if raw_to_derived_datatype !=
|
|
304
|
+
set_derived_arg_datatype = _get_first_arg_datatype(set_derived)
|
|
305
|
+
if raw_to_derived_datatype != set_derived_arg_datatype:
|
|
283
306
|
msg = (
|
|
284
307
|
f"{raw_to_derived} has datatype {raw_to_derived_datatype} "
|
|
285
|
-
f"!= {
|
|
308
|
+
f"!= {set_derived_arg_datatype} datatype {set_derived_arg_datatype}"
|
|
286
309
|
)
|
|
287
310
|
raise TypeError(msg)
|
|
288
311
|
|
|
289
312
|
factory = _make_factory(
|
|
290
|
-
|
|
313
|
+
raw_to_derived_func=raw_to_derived,
|
|
291
314
|
set_derived=set_derived,
|
|
292
315
|
raw_devices_and_constants=raw_devices_and_constants,
|
|
293
316
|
)
|
|
@@ -343,3 +366,13 @@ def _partition_by_keys(data: dict, keys: set) -> tuple[dict, dict]:
|
|
|
343
366
|
else:
|
|
344
367
|
group_excluded[k] = v
|
|
345
368
|
return group_excluded, group_included
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def _dict_wrapper(
|
|
372
|
+
fn: Callable[..., SignalDatatypeT],
|
|
373
|
+
) -> Callable[..., dict[str, SignalDatatypeT]]:
|
|
374
|
+
@functools.wraps(fn)
|
|
375
|
+
def wrapped(self, **kwargs):
|
|
376
|
+
return {"value": fn(**kwargs)}
|
|
377
|
+
|
|
378
|
+
return wrapped
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import types
|
|
3
4
|
from abc import abstractmethod
|
|
4
5
|
from collections.abc import Callable, Iterator, Sequence
|
|
5
6
|
from typing import (
|
|
@@ -9,8 +10,10 @@ from typing import (
|
|
|
9
10
|
NoReturn,
|
|
10
11
|
Protocol,
|
|
11
12
|
TypeVar,
|
|
13
|
+
Union,
|
|
12
14
|
cast,
|
|
13
15
|
get_args,
|
|
16
|
+
get_origin,
|
|
14
17
|
get_type_hints,
|
|
15
18
|
runtime_checkable,
|
|
16
19
|
)
|
|
@@ -76,6 +79,7 @@ class DeviceFiller(Generic[SignalBackendT, DeviceConnectorT]):
|
|
|
76
79
|
self._extras: dict[UniqueName, Sequence[Any]] = {}
|
|
77
80
|
self._signal_datatype: dict[LogicalName, type | None] = {}
|
|
78
81
|
self._vector_device_type: dict[LogicalName, type[Device] | None] = {}
|
|
82
|
+
self._optional_devices: set[str] = set()
|
|
79
83
|
self.ignored_signals: set[str] = set()
|
|
80
84
|
# Backends and Connectors stored ready for the connection phase
|
|
81
85
|
self._unfilled_backends: dict[
|
|
@@ -121,6 +125,20 @@ class DeviceFiller(Generic[SignalBackendT, DeviceConnectorT]):
|
|
|
121
125
|
self.ignored_signals.add(attr_name)
|
|
122
126
|
name = UniqueName(attr_name)
|
|
123
127
|
origin = get_origin_class(annotation)
|
|
128
|
+
args = get_args(annotation)
|
|
129
|
+
|
|
130
|
+
if (
|
|
131
|
+
get_origin(annotation) is Union
|
|
132
|
+
and types.NoneType in args
|
|
133
|
+
and len(args) == 2
|
|
134
|
+
):
|
|
135
|
+
# Annotation is an Union with two arguments, one of which is None
|
|
136
|
+
# Make this signal an optional parameter and set origin to T
|
|
137
|
+
# so the device is added to unfilled_connectors
|
|
138
|
+
self._optional_devices.add(name)
|
|
139
|
+
(annotation,) = [x for x in args if x is not types.NoneType]
|
|
140
|
+
origin = get_origin_class(annotation)
|
|
141
|
+
|
|
124
142
|
if (
|
|
125
143
|
name == "parent"
|
|
126
144
|
or name.startswith("_")
|
|
@@ -241,10 +259,17 @@ class DeviceFiller(Generic[SignalBackendT, DeviceConnectorT]):
|
|
|
241
259
|
:param source: The source of the data that should have done the filling, for
|
|
242
260
|
reporting as an error message
|
|
243
261
|
"""
|
|
244
|
-
unfilled =
|
|
245
|
-
|
|
262
|
+
unfilled = set(self._unfilled_connectors).union(self._unfilled_backends)
|
|
263
|
+
unfilled_optional = sorted(unfilled.intersection(self._optional_devices))
|
|
264
|
+
|
|
265
|
+
for name in unfilled_optional:
|
|
266
|
+
setattr(self._device, name, None)
|
|
267
|
+
|
|
268
|
+
required = sorted(unfilled.difference(unfilled_optional))
|
|
269
|
+
|
|
270
|
+
if required:
|
|
246
271
|
raise RuntimeError(
|
|
247
|
-
f"{self._device.name}: cannot provision {
|
|
272
|
+
f"{self._device.name}: cannot provision {required} from {source}"
|
|
248
273
|
)
|
|
249
274
|
|
|
250
275
|
def _ensure_device_vector(self, name: LogicalName) -> DeviceVector:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ophyd-async
|
|
3
|
-
Version: 0.14.
|
|
3
|
+
Version: 0.14.2
|
|
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
|
|
@@ -8,6 +8,7 @@ import pytest
|
|
|
8
8
|
from ophyd_async.core import (
|
|
9
9
|
DEFAULT_TIMEOUT,
|
|
10
10
|
Device,
|
|
11
|
+
DeviceFiller,
|
|
11
12
|
DeviceVector,
|
|
12
13
|
NotConnectedError,
|
|
13
14
|
Reference,
|
|
@@ -266,3 +267,50 @@ def test_setitem_with_non_device_value():
|
|
|
266
267
|
device_vector = DeviceVector(children={})
|
|
267
268
|
with pytest.raises(TypeError, match="Expected Device, got"):
|
|
268
269
|
device_vector[1] = "not_a_device"
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def test_device_filler_check_filled_with_optional_signals():
|
|
273
|
+
"""Test DeviceFiller.check_filled with both mandatory and optional Signals."""
|
|
274
|
+
|
|
275
|
+
class TestDevice(Device):
|
|
276
|
+
mandatory_signal: SignalRW[int]
|
|
277
|
+
optional_signal: SignalRW[int] | None
|
|
278
|
+
|
|
279
|
+
# Create a mock backend factory
|
|
280
|
+
def mock_backend_factory(datatype):
|
|
281
|
+
backend = Mock()
|
|
282
|
+
backend.datatype = datatype
|
|
283
|
+
return backend
|
|
284
|
+
|
|
285
|
+
# Create a mock connector factory
|
|
286
|
+
def mock_connector_factory():
|
|
287
|
+
return Mock()
|
|
288
|
+
|
|
289
|
+
device = TestDevice()
|
|
290
|
+
filler = DeviceFiller(
|
|
291
|
+
device=device,
|
|
292
|
+
signal_backend_factory=mock_backend_factory,
|
|
293
|
+
device_connector_factory=mock_connector_factory,
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
# Create signals from annotations (unfilled)
|
|
297
|
+
list(filler.create_signals_from_annotations(filled=False))
|
|
298
|
+
|
|
299
|
+
assert hasattr(device, "optional_signal")
|
|
300
|
+
assert isinstance(device.optional_signal, SignalRW)
|
|
301
|
+
|
|
302
|
+
# Test failure path: check_filled should fail when mandatory signal is unfilled
|
|
303
|
+
with pytest.raises(RuntimeError, match="cannot provision.*mandatory_signal"):
|
|
304
|
+
filler.check_filled("test_source")
|
|
305
|
+
|
|
306
|
+
# Fill the mandatory signal
|
|
307
|
+
filler.fill_child_signal("mandatory_signal", SignalRW, None)
|
|
308
|
+
|
|
309
|
+
# Test success path: check_filled should succeed and set optional_signal to None
|
|
310
|
+
filler.check_filled("test_source")
|
|
311
|
+
|
|
312
|
+
# Verify mandatory signal exists and optional signal is None
|
|
313
|
+
assert hasattr(device, "mandatory_signal")
|
|
314
|
+
assert isinstance(device.mandatory_signal, SignalRW)
|
|
315
|
+
assert hasattr(device, "optional_signal")
|
|
316
|
+
assert device.optional_signal is None
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_multi_derived_signal.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import math
|
|
3
3
|
import re
|
|
4
|
+
from typing import TypeVar
|
|
4
5
|
from unittest.mock import ANY, call
|
|
5
6
|
|
|
6
7
|
import pytest
|
|
@@ -8,8 +9,12 @@ from bluesky.protocols import Reading
|
|
|
8
9
|
|
|
9
10
|
from ophyd_async.core import (
|
|
10
11
|
DerivedSignalFactory,
|
|
12
|
+
EnableDisable,
|
|
13
|
+
EnumTypes,
|
|
11
14
|
SignalRW,
|
|
15
|
+
StrictEnum,
|
|
12
16
|
Table,
|
|
17
|
+
Transform,
|
|
13
18
|
derived_signal_rw,
|
|
14
19
|
get_mock,
|
|
15
20
|
set_mock_value,
|
|
@@ -187,3 +192,60 @@ def test_make_rw_signal_type_mismatch():
|
|
|
187
192
|
match=re.escape("Must define a set_derived method to support derived"),
|
|
188
193
|
):
|
|
189
194
|
factory.derived_signal_rw(datatype=Table, name="")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def test_missing_type_hint_in_raw_to_derived_transform():
|
|
198
|
+
class UnTypedTransform(Transform):
|
|
199
|
+
def raw_to_derived(self, x) -> float:
|
|
200
|
+
return x
|
|
201
|
+
|
|
202
|
+
with pytest.raises(
|
|
203
|
+
TypeError,
|
|
204
|
+
match=re.escape(" is missing a type hint for arguments: ['x']"),
|
|
205
|
+
):
|
|
206
|
+
DerivedSignalFactory(
|
|
207
|
+
UnTypedTransform,
|
|
208
|
+
set_derived=None,
|
|
209
|
+
x=soft_signal_rw(float),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def test_sub_type_hint_in_raw_to_derived_transform():
|
|
214
|
+
class SubTypedTransform(Transform):
|
|
215
|
+
def raw_to_derived(self, x: StrictEnum) -> StrictEnum:
|
|
216
|
+
return x
|
|
217
|
+
|
|
218
|
+
DerivedSignalFactory(
|
|
219
|
+
SubTypedTransform,
|
|
220
|
+
set_derived=None,
|
|
221
|
+
x=soft_signal_rw(EnableDisable),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
with pytest.raises(
|
|
225
|
+
TypeError,
|
|
226
|
+
match=re.escape(
|
|
227
|
+
"Expected the following to be passed as keyword arguments "
|
|
228
|
+
"{'x': <enum 'StrictEnum'>}, "
|
|
229
|
+
"got {'x': <class 'float'>}"
|
|
230
|
+
),
|
|
231
|
+
):
|
|
232
|
+
DerivedSignalFactory(
|
|
233
|
+
SubTypedTransform,
|
|
234
|
+
set_derived=None,
|
|
235
|
+
x=soft_signal_rw(float),
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
EnumTypesT = TypeVar("EnumTypesT", bound=EnumTypes)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_protocol_type_hint_in_raw_to_derived_transform():
|
|
243
|
+
class SubTypedTransform(Transform):
|
|
244
|
+
def raw_to_derived(self, x: EnumTypesT) -> EnumTypesT:
|
|
245
|
+
return x
|
|
246
|
+
|
|
247
|
+
DerivedSignalFactory(
|
|
248
|
+
SubTypedTransform,
|
|
249
|
+
set_derived=None,
|
|
250
|
+
x=soft_signal_rw(EnableDisable),
|
|
251
|
+
)
|
|
@@ -113,17 +113,21 @@ async def test_observe_value_times_out_with_no_external_task():
|
|
|
113
113
|
|
|
114
114
|
recv = []
|
|
115
115
|
|
|
116
|
+
start = time.monotonic()
|
|
117
|
+
|
|
116
118
|
async def watch(done_timeout):
|
|
117
119
|
async for val in observe_value(sig, done_timeout=done_timeout):
|
|
118
|
-
recv.append(
|
|
120
|
+
recv.append(time.monotonic() - start)
|
|
119
121
|
setter(val + 1)
|
|
120
122
|
|
|
121
|
-
start = time.monotonic()
|
|
122
123
|
with pytest.raises(asyncio.TimeoutError):
|
|
123
|
-
await watch(done_timeout=0.
|
|
124
|
+
await watch(done_timeout=0.07)
|
|
124
125
|
# On a dev machine we can do >200 iterations in 0.1s, but CI is slower
|
|
125
126
|
assert len(recv) > 10
|
|
126
|
-
|
|
127
|
+
elapsed = time.monotonic() - start
|
|
128
|
+
assert elapsed == pytest.approx(0.07, abs=0.05), (
|
|
129
|
+
f"Elapsed: {elapsed} Received: {recv}"
|
|
130
|
+
)
|
|
127
131
|
|
|
128
132
|
|
|
129
133
|
async def test_observe_value_uses_correct_timeout():
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/tests/unit_tests/core/test_single_derived_signal.py
RENAMED
|
@@ -88,7 +88,7 @@ async def test_get_returns_right_position(
|
|
|
88
88
|
|
|
89
89
|
@pytest.mark.parametrize("cls", [ReadOnlyBeamstop, MovableBeamstop])
|
|
90
90
|
async def test_monitoring_position(cls: type[ReadOnlyBeamstop | MovableBeamstop]):
|
|
91
|
-
results = asyncio.Queue
|
|
91
|
+
results: asyncio.Queue[dict[str, Reading]] = asyncio.Queue()
|
|
92
92
|
inst = cls("inst")
|
|
93
93
|
inst.position.subscribe_reading(results.put_nowait)
|
|
94
94
|
assert (await results.get())["inst-position"][
|
|
@@ -181,6 +181,29 @@ async def _put(value: float) -> None:
|
|
|
181
181
|
pass
|
|
182
182
|
|
|
183
183
|
|
|
184
|
+
# function without type hint on first argument
|
|
185
|
+
def _get_no_type(ts) -> float:
|
|
186
|
+
return ts
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
async def test_derived_signal_rw_get_method_no_param_type():
|
|
190
|
+
signal_rw = soft_signal_rw(int, initial_value=4)
|
|
191
|
+
with pytest.raises(
|
|
192
|
+
TypeError,
|
|
193
|
+
match=re.escape(" is missing a type hint for arguments: ['ts']"),
|
|
194
|
+
):
|
|
195
|
+
derived_signal_rw(_get_no_type, _put, ts=signal_rw)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
async def test_derived_signal_r_get_method_no_param_type():
|
|
199
|
+
signal_rw = soft_signal_rw(int, initial_value=4)
|
|
200
|
+
with pytest.raises(
|
|
201
|
+
TypeError,
|
|
202
|
+
match=re.escape(" is missing a type hint for arguments: ['ts']"),
|
|
203
|
+
):
|
|
204
|
+
derived_signal_r(_get_no_type, ts=signal_rw)
|
|
205
|
+
|
|
206
|
+
|
|
184
207
|
@pytest.fixture
|
|
185
208
|
def derived_signal_backend() -> SignalBackend[SignalDatatype]:
|
|
186
209
|
signal_rw = soft_signal_rw(int, initial_value=4)
|
|
@@ -52,6 +52,10 @@ class Block4(StandardReadable):
|
|
|
52
52
|
signal_rw: SignalRW[int]
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
class Block5(Device):
|
|
56
|
+
signal_rw: SignalRW[int] | None
|
|
57
|
+
|
|
58
|
+
|
|
55
59
|
DeviceT = TypeVar("DeviceT", bound=Device)
|
|
56
60
|
|
|
57
61
|
|
|
@@ -133,6 +137,19 @@ async def test_device_create_children_from_annotations():
|
|
|
133
137
|
assert device.signal_device is top_block_1_device
|
|
134
138
|
|
|
135
139
|
|
|
140
|
+
async def test_device_create_device_with_optional_signals():
|
|
141
|
+
device = with_pvi_connector(Block5, "PREFIX:")
|
|
142
|
+
|
|
143
|
+
# Makes sure before connecting we create a signal and it exists in the device
|
|
144
|
+
assert hasattr(device, "signal_rw")
|
|
145
|
+
assert isinstance(device.signal_rw, SignalRW)
|
|
146
|
+
|
|
147
|
+
await device.connect(mock=True)
|
|
148
|
+
|
|
149
|
+
# After connecting if the optional signal is not filled it's set to None
|
|
150
|
+
assert isinstance(device.signal_rw, SignalRW)
|
|
151
|
+
|
|
152
|
+
|
|
136
153
|
async def test_device_create_children_from_annotations_with_device_vectors():
|
|
137
154
|
device = with_pvi_connector(Block4, "PREFIX:", name="test_device")
|
|
138
155
|
await device.connect(mock=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0003-ophyd-async-migration.rst
RENAMED
|
File without changes
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0004-repository-structure.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0007-subpackage-structure.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/explanations/decisions/0010-docstring-format.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/images/fly_scan_collection_windows_and_frames.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ophyd_async-0.14.1 → ophyd_async-0.14.2}/docs/images/set_and_wait_for_other_value.excalidraw.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|