ophyd-async 0.14.0__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.0 → ophyd_async-0.14.2}/.copier-answers.yml +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/CONTRIBUTING.md +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/_test.yml +0 -5
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/ci.yml +4 -2
- ophyd_async-0.14.2/.github/workflows/claude.yml +52 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.pre-commit-config.yaml +1 -1
- {ophyd_async-0.14.0/src/ophyd_async.egg-info → ophyd_async-0.14.2}/PKG-INFO +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/_version.py +3 -3
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/__init__.py +2 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_derived_signal.py +56 -23
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_device_filler.py +28 -3
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_providers.py +94 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_pmac_trajectory.py +15 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/_eiger_io.py +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_control.py +2 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/__init__.py +6 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_tango_transport.py +12 -11
- {ophyd_async-0.14.0 → ophyd_async-0.14.2/src/ophyd_async.egg-info}/PKG-INFO +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/SOURCES.txt +6 -5
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.2/tests/system_tests_tango}/conftest.py +20 -8
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.2/tests/system_tests_tango}/test_tango_signals.py +22 -12
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_device.py +48 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_multi_derived_signal.py +62 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_observe.py +8 -4
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_providers.py +57 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_single_derived_signal.py +24 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_trajectory.py +35 -16
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/pvi/test_pvi.py +17 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.codecov.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.devcontainer/devcontainer.json +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.git-blame-ignore-revs +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/codeql/codeql-config.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/pages/index.html +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/pages/make_switcher.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/_codeql.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/_dist.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/_docs.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/_pypi.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/_release.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/_tox.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.github/workflows/periodic.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.gitignore +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.gitleaks.toml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.gitmodules +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/.python-version +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/Dockerfile +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/LICENSE +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/README.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/_static/custom.css +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/conf.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0008-signal-types.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0010-docstring-format.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/0011-buffer-updates-camonitor.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions/COPYME +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/decisions.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/declarative-vs-procedural.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/design-goals.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/device-connection-strategies.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/devices-signals-backends.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/fly-scanning.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/plan-stubs.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/when-to-extend-movable.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations/where-device-logic.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/explanations.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/genindex.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to/choose-right-baseclass.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to/contribute.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to/derive-one-signal-from-others.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to/implement-ad-detector.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to/interact-with-signals.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to/put-device-back.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to/store-and-retrieve.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/how-to.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/images/ophyd-async-logo.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/images/ophyd-favicon.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/index.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/reference.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/tutorials/implementing-detectors.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/tutorials/implementing-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/tutorials/installation.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/tutorials/using-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/tutorials/writing-tests-for-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/docs/tutorials.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/pyproject.toml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/renovate.json +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/setup.cfg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/__main__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/_docs_parser.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_device.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_enums.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_flyer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_hdf_dataset.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_log.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_mock_signal_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_protocol.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_readable.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_status.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/core/_yaml_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/_andor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_logic.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_core_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_hdf_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adcore/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_aioca.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_epics_device.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_p4p.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/core/_util.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/__main__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_ioc.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/_stage.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/motor.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/point_detector.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/odin/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/odin/_odin_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_pmac_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_pmac_trajectory_generation.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/pmac/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/test_records.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/core.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_jungfrau.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_signals.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/jungfrau/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_block.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_fly.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_panda.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/py.typed +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/__main__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_blob_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_pattern_generator.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_point_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/sim/_stage.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_base_device.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_converters.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/core/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_counter.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_mover.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/testing/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/tango/testing/_test_config.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/testing/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/testing/_assert.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/testing/_single_derived.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/testing/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/requires.txt +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/src/ophyd_async.egg-info/top_level.txt +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/README.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/adsim/baseline.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/adsim/external_dependencies.sh +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/adsim/test_adsim_system.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/eiger/README.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/eiger/test_eiger_system.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/signal/test_signals.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/signal/test_yaml_save_ca.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/epics/signal/test_yaml_save_pva.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/fastcs/panda/test_panda_connect.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/system_tests/test_tutorials.py +0 -0
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.2/tests/system_tests_tango}/context_subprocess.py +0 -0
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.2/tests/system_tests_tango}/test_base_device.py +0 -0
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.2/tests/system_tests_tango}/test_tango_transport.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_auto_init_devices.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_flyer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_log.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_mock_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_protocol.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_readable.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_soft_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_status.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_subset_enum.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/core/test_watchable_async_status.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adandor/test_andor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adaravis/test_aravis.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_cont_acq_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_detectors.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_drivers.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_plugins.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_scans.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_single_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adcore/test_writers.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adkinetix/test_kinetix.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adpilatus/test_pilatus.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/adsimdetector/test_sim.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/advimba/test_vimba.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/demo/test_epics_demo.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/eiger/test_odin_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_trajectory_generation.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/pmac/test_pmac_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/signal/test_common.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/test_areadetector_subclass_naming.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/epics/test_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/eiger/test_eiger_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/eiger/test_eiger_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/jungfrau/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/jungfrau/test_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/jungfrau/test_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/db/panda.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_hdf_panda.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_panda_connect_mock.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_panda_control.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_panda_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_seq_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/fastcs/panda/test_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_ensure_connected.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_fly.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/plan_stubs/test_setup.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/sim/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/sim/test_sim_blob_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/sim/test_sim_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/test_branching.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/test_cli.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/test_data/test_yaml_config_save.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/tests/unit_tests/test_data/test_yaml_save.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.2}/uv.lock +0 -0
|
@@ -24,4 +24,4 @@ It is recommended that developers use a [vscode devcontainer](https://code.visua
|
|
|
24
24
|
|
|
25
25
|
This project was created using the [Diamond Light Source Copier Template](https://github.com/DiamondLightSource/python-copier-template) for Python projects.
|
|
26
26
|
|
|
27
|
-
For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/5.0.
|
|
27
|
+
For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/5.0.1/how-to.html).
|
|
@@ -13,9 +13,6 @@ on:
|
|
|
13
13
|
type: string
|
|
14
14
|
description: The path to look for tests
|
|
15
15
|
required: true
|
|
16
|
-
secrets:
|
|
17
|
-
CODECOV_TOKEN:
|
|
18
|
-
required: true
|
|
19
16
|
|
|
20
17
|
env:
|
|
21
18
|
# https://github.com/pytest-dev/pytest/issues/2042
|
|
@@ -59,5 +56,3 @@ jobs:
|
|
|
59
56
|
with:
|
|
60
57
|
name: ${{ inputs.python-version }}/${{ inputs.runs-on }}/${{ inputs.tests-path }}
|
|
61
58
|
files: cov.xml
|
|
62
|
-
env:
|
|
63
|
-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -20,14 +20,16 @@ jobs:
|
|
|
20
20
|
runs-on: ["ubuntu-latest", "windows-latest"] # can add macos-latest
|
|
21
21
|
python-version: ["3.11", "3.12", "3.13"]
|
|
22
22
|
tests-path: ["", "tests/system_tests"]
|
|
23
|
+
include:
|
|
24
|
+
- runs-on: "ubuntu-latest"
|
|
25
|
+
python-version: "3.11"
|
|
26
|
+
tests-path: "tests/system_tests_tango"
|
|
23
27
|
fail-fast: false
|
|
24
28
|
uses: ./.github/workflows/_test.yml
|
|
25
29
|
with:
|
|
26
30
|
runs-on: ${{ matrix.runs-on }}
|
|
27
31
|
python-version: ${{ matrix.python-version }}
|
|
28
32
|
tests-path: ${{ matrix.tests-path }}
|
|
29
|
-
secrets:
|
|
30
|
-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
31
33
|
|
|
32
34
|
docs:
|
|
33
35
|
uses: ./.github/workflows/_docs.yml
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Claude PR Comment Review
|
|
2
|
+
# https://github.com/anthropics/claude-code-action/blob/main/docs/solutions.md#automatic-pr-code-review
|
|
3
|
+
# https://skywork.ai/blog/how-to-use-claude-code-for-prs-code-reviews-guide/#step-3-add-a-comment-triggered-workflow-copy-pasteable
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
issue_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
review:
|
|
11
|
+
if: ${{ contains(github.event.comment.body, '@claude') && github.event.issue.pull_request != null }}
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
pull-requests: write
|
|
16
|
+
id-token: write
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v5
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 1
|
|
21
|
+
|
|
22
|
+
- run: find
|
|
23
|
+
|
|
24
|
+
- uses: anthropics/claude-code-action@v1
|
|
25
|
+
with:
|
|
26
|
+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
27
|
+
track_progress: true # ✨ Enables tracking comments
|
|
28
|
+
prompt: |
|
|
29
|
+
REPO: ${{ github.repository }}
|
|
30
|
+
PR NUMBER: ${{ github.event.issue.number }}
|
|
31
|
+
|
|
32
|
+
Please review this pull request with a focus on:
|
|
33
|
+
- Code quality and best practices
|
|
34
|
+
- Potential bugs or issues
|
|
35
|
+
- Security implications
|
|
36
|
+
- Performance considerations
|
|
37
|
+
|
|
38
|
+
Note: The PR branch is already checked out in the current working directory.
|
|
39
|
+
|
|
40
|
+
Make sure to:
|
|
41
|
+
- Use `gh pr comment` for concise top-level feedback
|
|
42
|
+
- Use `mcp__github_inline_comment__create_inline_comment` to highlight specific code issues
|
|
43
|
+
- Put all detailed feedback and recommendations in inline comments and do not duplicate in the main PR comment
|
|
44
|
+
- Anywhere you have a line number reference, use an inline comment
|
|
45
|
+
- Check structure is consist with existing code style
|
|
46
|
+
- Skip style issues already handled by linters
|
|
47
|
+
- Check for duplication of code already in the repository; aim for re-use where sensible
|
|
48
|
+
- Favour composition over inheritence
|
|
49
|
+
- Respond in concise bullet point form; avoid restating code
|
|
50
|
+
|
|
51
|
+
claude_args: |
|
|
52
|
+
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
|
|
@@ -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'
|
|
@@ -48,6 +48,7 @@ from ._protocol import AsyncConfigurable, AsyncReadable, AsyncStageable, Watcher
|
|
|
48
48
|
from ._providers import (
|
|
49
49
|
AutoIncrementFilenameProvider,
|
|
50
50
|
AutoIncrementingPathProvider,
|
|
51
|
+
AutoMaxIncrementingPathProvider,
|
|
51
52
|
DatasetDescriber,
|
|
52
53
|
FilenameProvider,
|
|
53
54
|
PathInfo,
|
|
@@ -222,6 +223,7 @@ __all__ = [
|
|
|
222
223
|
"FilenameProvider",
|
|
223
224
|
"StaticFilenameProvider",
|
|
224
225
|
"AutoIncrementFilenameProvider",
|
|
226
|
+
"AutoMaxIncrementingPathProvider",
|
|
225
227
|
"UUIDFilenameProvider",
|
|
226
228
|
# Datatset
|
|
227
229
|
"DatasetDescriber",
|
|
@@ -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,9 +1,10 @@
|
|
|
1
|
+
import re
|
|
1
2
|
import uuid
|
|
2
3
|
from abc import abstractmethod
|
|
3
4
|
from collections.abc import Callable
|
|
4
5
|
from dataclasses import dataclass
|
|
5
6
|
from datetime import date
|
|
6
|
-
from pathlib import PurePath, PureWindowsPath
|
|
7
|
+
from pathlib import Path, PurePath, PureWindowsPath
|
|
7
8
|
from typing import Protocol
|
|
8
9
|
from urllib.parse import urlunparse
|
|
9
10
|
|
|
@@ -157,6 +158,98 @@ class StaticPathProvider(PathProvider):
|
|
|
157
158
|
)
|
|
158
159
|
|
|
159
160
|
|
|
161
|
+
class AutoMaxIncrementingPathProvider(PathProvider):
|
|
162
|
+
"""Increment directory name on each call by checking existing directories.
|
|
163
|
+
|
|
164
|
+
Looks through directories in a specified base path to increment directory name.
|
|
165
|
+
PathInfo gives path like base_path/0001_dirname/dirname, or
|
|
166
|
+
base_path/yyyy-mm-dd/0001_dirname/dirname if dated is true. Here,
|
|
167
|
+
the '0001' is the value which gets incremented if the file exists already.
|
|
168
|
+
|
|
169
|
+
It's recommended for the base path provider to be non-incrementing.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
base_path_provider: Path to create directories inside of. Note that the filename of
|
|
173
|
+
this provider is used as the top level directory and the filename
|
|
174
|
+
max_digits: Number of digits to pad onto the parent directory.
|
|
175
|
+
starting_value: Number to start incrementing from.
|
|
176
|
+
dated: Whether to create an extra directory to specify the day.
|
|
177
|
+
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
def __init__(
|
|
181
|
+
self,
|
|
182
|
+
base_path_provider: PathProvider,
|
|
183
|
+
max_digits: int = 4,
|
|
184
|
+
starting_value: int = 0,
|
|
185
|
+
dated: bool = False,
|
|
186
|
+
):
|
|
187
|
+
self._base_path_provider = base_path_provider
|
|
188
|
+
self._max_digits = max_digits
|
|
189
|
+
self._next_value = starting_value
|
|
190
|
+
self._dated = dated
|
|
191
|
+
|
|
192
|
+
def _get_highest_number_from(self, path: Path) -> int:
|
|
193
|
+
# Look through directories in path which end in "_{number} and get highest
|
|
194
|
+
# number"
|
|
195
|
+
highest_number = 0
|
|
196
|
+
candidates = [
|
|
197
|
+
x for x in path.iterdir() if x.is_dir() and re.match(r"^\d+_", x.name)
|
|
198
|
+
]
|
|
199
|
+
if candidates:
|
|
200
|
+
highest_number = max(
|
|
201
|
+
int(x.name.split("_", maxsplit=1)[0]) for x in candidates
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
highest_number = self._next_value
|
|
205
|
+
return highest_number
|
|
206
|
+
|
|
207
|
+
def __call__(self, device_name: str | None = None) -> PathInfo:
|
|
208
|
+
base_path_info = self._base_path_provider.__call__()
|
|
209
|
+
base_path_dir = Path(base_path_info.directory_path)
|
|
210
|
+
if self._dated:
|
|
211
|
+
# Make sure we are the max ID of any other days to keep numbering
|
|
212
|
+
# consistent.
|
|
213
|
+
cands = [
|
|
214
|
+
self._get_highest_number_from(x)
|
|
215
|
+
for x in base_path_dir.iterdir()
|
|
216
|
+
if re.match(r"^\d\d\d\d-\d\d-\d\d$", x.name)
|
|
217
|
+
]
|
|
218
|
+
if cands:
|
|
219
|
+
self._next_value = max(max(cands) + 1, self._next_value)
|
|
220
|
+
|
|
221
|
+
path = base_path_dir / date.today().strftime("%Y-%m-%d")
|
|
222
|
+
else:
|
|
223
|
+
path = base_path_dir
|
|
224
|
+
|
|
225
|
+
val_to_use = self._next_value
|
|
226
|
+
|
|
227
|
+
# Get the highest number using files in path, or use
|
|
228
|
+
# stored next value if no files are found.
|
|
229
|
+
if path.exists():
|
|
230
|
+
highest_number = self._get_highest_number_from(path)
|
|
231
|
+
val_to_use = (
|
|
232
|
+
highest_number + 1
|
|
233
|
+
if not highest_number == self._next_value
|
|
234
|
+
else highest_number
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
self._next_value = val_to_use + 1
|
|
238
|
+
|
|
239
|
+
filename = base_path_info.filename
|
|
240
|
+
|
|
241
|
+
padded_counter = f"{val_to_use:0{self._max_digits}}"
|
|
242
|
+
full_path = (
|
|
243
|
+
path / f"{padded_counter}_{filename.strip('_')}" / filename.rstrip("_")
|
|
244
|
+
)
|
|
245
|
+
return PathInfo(
|
|
246
|
+
directory_path=full_path.parent,
|
|
247
|
+
directory_uri=None,
|
|
248
|
+
filename=full_path.name,
|
|
249
|
+
create_dir_depth=0,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
160
253
|
class AutoIncrementingPathProvider(PathProvider):
|
|
161
254
|
"""Provides a new numerically incremented path on each call."""
|
|
162
255
|
|
|
@@ -10,6 +10,7 @@ from ophyd_async.core import (
|
|
|
10
10
|
AsyncStatus,
|
|
11
11
|
FlyerController,
|
|
12
12
|
error_if_none,
|
|
13
|
+
gather_dict,
|
|
13
14
|
observe_value,
|
|
14
15
|
set_and_wait_for_value,
|
|
15
16
|
wait_for_value,
|
|
@@ -202,12 +203,25 @@ class PmacTrajectoryTriggerLogic(FlyerController):
|
|
|
202
203
|
coord = self.pmac.coord[motor_info.cs_number]
|
|
203
204
|
coros = []
|
|
204
205
|
await coord.defer_moves.set(True)
|
|
206
|
+
|
|
207
|
+
motor_readbacks = await gather_dict(
|
|
208
|
+
{motor: motor.user_readback.get_value() for motor in ramp_up_position}
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
move_times = [
|
|
212
|
+
abs(position - motor_readbacks[motor])
|
|
213
|
+
/ motor_info.motor_max_velocity[motor]
|
|
214
|
+
for motor, position in ramp_up_position.items()
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
longest_time = max(move_times)
|
|
218
|
+
|
|
205
219
|
for motor, position in ramp_up_position.items():
|
|
206
220
|
coros.append(
|
|
207
221
|
set_and_wait_for_value(
|
|
208
222
|
coord.cs_axis_setpoint[motor_info.motor_cs_index[motor]],
|
|
209
223
|
position,
|
|
210
|
-
set_timeout=
|
|
224
|
+
set_timeout=longest_time + DEFAULT_TIMEOUT,
|
|
211
225
|
wait_for_set_completion=False,
|
|
212
226
|
)
|
|
213
227
|
)
|
|
@@ -29,7 +29,7 @@ class EigerDetectorIO(Device):
|
|
|
29
29
|
frame_time: SignalRW[float]
|
|
30
30
|
nimages: SignalRW[int]
|
|
31
31
|
ntrigger: SignalRW[int]
|
|
32
|
-
nexpi: SignalRW[int]
|
|
32
|
+
nexpi: SignalRW[int] | None
|
|
33
33
|
trigger_mode: SignalRW[str]
|
|
34
34
|
roi_mode: SignalRW[str]
|
|
35
35
|
photon_energy: SignalRW[float]
|
|
@@ -35,7 +35,8 @@ class PandaPcapController(DetectorController):
|
|
|
35
35
|
await wait_for_value(self.pcap.active, True, timeout=1)
|
|
36
36
|
|
|
37
37
|
async def wait_for_idle(self):
|
|
38
|
-
|
|
38
|
+
if self._arm_status and not self._arm_status.done:
|
|
39
|
+
await self._arm_status
|
|
39
40
|
|
|
40
41
|
async def disarm(self):
|
|
41
42
|
await self.pcap.arm.set(False)
|
|
@@ -9,7 +9,9 @@ from ._signal import (
|
|
|
9
9
|
tango_signal_x,
|
|
10
10
|
)
|
|
11
11
|
from ._tango_transport import (
|
|
12
|
+
AttributeInfoEx,
|
|
12
13
|
AttributeProxy,
|
|
14
|
+
CommandInfo,
|
|
13
15
|
CommandProxy,
|
|
14
16
|
CommandProxyReadCharacter,
|
|
15
17
|
TangoDoubleStringTable,
|
|
@@ -21,6 +23,7 @@ from ._tango_transport import (
|
|
|
21
23
|
get_python_type,
|
|
22
24
|
get_source_metadata,
|
|
23
25
|
get_tango_trl,
|
|
26
|
+
parse_precision,
|
|
24
27
|
)
|
|
25
28
|
from ._utils import (
|
|
26
29
|
DevStateEnum,
|
|
@@ -30,7 +33,9 @@ from ._utils import (
|
|
|
30
33
|
)
|
|
31
34
|
|
|
32
35
|
__all__ = [
|
|
36
|
+
"AttributeInfoEx",
|
|
33
37
|
"AttributeProxy",
|
|
38
|
+
"CommandInfo",
|
|
34
39
|
"CommandProxy",
|
|
35
40
|
"CommandProxyReadCharacter",
|
|
36
41
|
"DevStateEnum",
|
|
@@ -44,6 +49,7 @@ __all__ = [
|
|
|
44
49
|
"infer_python_type",
|
|
45
50
|
"infer_signal_type",
|
|
46
51
|
"make_backend",
|
|
52
|
+
"parse_precision",
|
|
47
53
|
"tango_signal_r",
|
|
48
54
|
"tango_signal_rw",
|
|
49
55
|
"tango_signal_w",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import functools
|
|
3
3
|
import logging
|
|
4
|
+
import re
|
|
4
5
|
import time
|
|
5
6
|
from abc import abstractmethod
|
|
6
7
|
from collections.abc import Callable, Coroutine, Sequence
|
|
@@ -582,6 +583,15 @@ class CommandProxy(TangoProxy):
|
|
|
582
583
|
pass
|
|
583
584
|
|
|
584
585
|
|
|
586
|
+
PRECISION_PATTERN = re.compile(r"%\d*\.(\d+)f")
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def parse_precision(config: AttributeInfoEx):
|
|
590
|
+
if config.format and (matches := PRECISION_PATTERN.findall(config.format)):
|
|
591
|
+
return int(matches[0])
|
|
592
|
+
return None
|
|
593
|
+
|
|
594
|
+
|
|
585
595
|
def get_dtype_extended(datatype) -> object | None:
|
|
586
596
|
"""For converting tango types to numpy datatype formats."""
|
|
587
597
|
# DevState tango type does not have numpy equivalents
|
|
@@ -639,17 +649,8 @@ def get_source_metadata(
|
|
|
639
649
|
if tr_dtype == CmdArgType.DevState:
|
|
640
650
|
_choices = list(DevState.names.keys())
|
|
641
651
|
|
|
642
|
-
_precision =
|
|
643
|
-
|
|
644
|
-
try:
|
|
645
|
-
_precision = int(config.format.split(".")[1].split("f")[0])
|
|
646
|
-
except (ValueError, IndexError) as exc:
|
|
647
|
-
# If parsing config.format fails, _precision remains None.
|
|
648
|
-
logger.warning(
|
|
649
|
-
"Failed to parse precision from config.format: %s. Error: %s",
|
|
650
|
-
config.format,
|
|
651
|
-
exc,
|
|
652
|
-
)
|
|
652
|
+
_precision = parse_precision(config)
|
|
653
|
+
|
|
653
654
|
no_limits = Limits(
|
|
654
655
|
control=LimitsRange(high=None, low=None),
|
|
655
656
|
warning=LimitsRange(high=None, low=None),
|
|
@@ -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,6 +28,7 @@ uv.lock
|
|
|
28
28
|
.github/workflows/_test.yml
|
|
29
29
|
.github/workflows/_tox.yml
|
|
30
30
|
.github/workflows/ci.yml
|
|
31
|
+
.github/workflows/claude.yml
|
|
31
32
|
.github/workflows/periodic.yml
|
|
32
33
|
docs/conf.py
|
|
33
34
|
docs/explanations.md
|
|
@@ -250,11 +251,11 @@ tests/system_tests/epics/signal/test_signals.py
|
|
|
250
251
|
tests/system_tests/epics/signal/test_yaml_save_ca.yaml
|
|
251
252
|
tests/system_tests/epics/signal/test_yaml_save_pva.yaml
|
|
252
253
|
tests/system_tests/fastcs/panda/test_panda_connect.py
|
|
253
|
-
tests/
|
|
254
|
-
tests/
|
|
255
|
-
tests/
|
|
256
|
-
tests/
|
|
257
|
-
tests/
|
|
254
|
+
tests/system_tests_tango/conftest.py
|
|
255
|
+
tests/system_tests_tango/context_subprocess.py
|
|
256
|
+
tests/system_tests_tango/test_base_device.py
|
|
257
|
+
tests/system_tests_tango/test_tango_signals.py
|
|
258
|
+
tests/system_tests_tango/test_tango_transport.py
|
|
258
259
|
tests/unit_tests/__init__.py
|
|
259
260
|
tests/unit_tests/test_branching.py
|
|
260
261
|
tests/unit_tests/test_cli.py
|