ophyd-async 0.14.0__tar.gz → 0.14.1__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.1}/.copier-answers.yml +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/CONTRIBUTING.md +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_test.yml +0 -5
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/ci.yml +4 -2
- ophyd_async-0.14.1/.github/workflows/claude.yml +52 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.pre-commit-config.yaml +1 -1
- {ophyd_async-0.14.0/src/ophyd_async.egg-info → ophyd_async-0.14.1}/PKG-INFO +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/_version.py +3 -3
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/__init__.py +2 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_providers.py +94 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_trajectory.py +15 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger_io.py +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_control.py +2 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/__init__.py +6 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_tango_transport.py +12 -11
- {ophyd_async-0.14.0 → ophyd_async-0.14.1/src/ophyd_async.egg-info}/PKG-INFO +1 -1
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/SOURCES.txt +6 -5
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/conftest.py +20 -8
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_tango_signals.py +22 -12
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_providers.py +57 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_trajectory.py +35 -16
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.codecov.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.devcontainer/devcontainer.json +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.git-blame-ignore-revs +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/codeql/codeql-config.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/pages/index.html +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/pages/make_switcher.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_codeql.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_dist.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_docs.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_pypi.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_release.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_tox.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/periodic.yml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.gitignore +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.gitleaks.toml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.gitmodules +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.python-version +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/Dockerfile +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/LICENSE +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/README.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/_static/custom.css +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/conf.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0008-signal-types.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0010-docstring-format.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0011-buffer-updates-camonitor.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/COPYME +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/declarative-vs-procedural.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/design-goals.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/device-connection-strategies.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/devices-signals-backends.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/fly-scanning.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/plan-stubs.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/when-to-extend-movable.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/where-device-logic.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/genindex.rst +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/choose-right-baseclass.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/contribute.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/derive-one-signal-from-others.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/implement-ad-detector.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/interact-with-signals.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/put-device-back.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/store-and-retrieve.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/ophyd-async-logo.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/ophyd-favicon.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/index.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/reference.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/implementing-detectors.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/implementing-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/installation.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/using-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/writing-tests-for-devices.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/pyproject.toml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/renovate.json +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/setup.cfg +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/__main__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/_docs_parser.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_derived_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_device.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_device_filler.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_enums.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_flyer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_hdf_dataset.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_log.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_mock_signal_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_protocol.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_readable.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_status.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_yaml_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_logic.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_hdf_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_aioca.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_epics_device.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_p4p.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_util.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/__main__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_ioc.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_stage.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/motor.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/point_detector.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/odin/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/odin/_odin_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_trajectory_generation.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/test_records.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/core.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_jungfrau.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_signals.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_block.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_fly.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_panda.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/py.typed +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/__main__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_pattern_generator.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_point_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_stage.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_base_device.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_converters.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_counter.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_mover.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/_test_config.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_assert.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_one_of_everything.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_single_derived.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/requires.txt +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/top_level.txt +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/README.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/baseline.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/external_dependencies.sh +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/test_adsim_system.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/README.md +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/test_eiger_system.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_signals.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_yaml_save_ca.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_yaml_save_pva.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/fastcs/panda/test_panda_connect.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/test_tutorials.py +0 -0
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/context_subprocess.py +0 -0
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_base_device.py +0 -0
- {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_tango_transport.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_auto_init_devices.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_device.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_flyer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_log.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_mock_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_multi_derived_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_observe.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_protocol.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_readable.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_single_derived_signal.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_soft_signal_backend.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_status.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_subset_enum.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_watchable_async_status.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adandor/test_andor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adaravis/test_aravis.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_cont_acq_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_detectors.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_drivers.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_plugins.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_scans.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_single_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_writers.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adkinetix/test_kinetix.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adpilatus/test_pilatus.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adsimdetector/test_sim.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/advimba/test_vimba.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/demo/test_epics_demo.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/eiger/test_odin_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/conftest.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_io.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_trajectory_generation.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pvi/test_pvi.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/signal/test_common.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/test_areadetector_subclass_naming.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/test_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/eiger/test_eiger_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/eiger/test_eiger_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/test_controller.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/test_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/db/panda.db +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_hdf_panda.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_connect_mock.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_control.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_utils.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_seq_table.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_trigger.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_writer.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_ensure_connected.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_fly.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_settings.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_setup.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/sim/__init__.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/sim/test_sim_blob_detector.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/sim/test_sim_motor.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_branching.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_cli.py +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_data/test_yaml_config_save.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_data/test_yaml_save.yaml +0 -0
- {ophyd_async-0.14.0 → ophyd_async-0.14.1}/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.1
|
|
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.1'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 14, 1)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g9b567b214'
|
|
@@ -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,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.1
|
|
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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import asyncio
|
|
2
2
|
import pickle
|
|
3
3
|
import socket
|
|
4
4
|
import subprocess
|
|
@@ -30,15 +30,9 @@ def reset_tango_asyncio():
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def pytest_collection_modifyitems(config, items):
|
|
33
|
-
tango_dir =
|
|
33
|
+
tango_dir = "system_tests_tango"
|
|
34
34
|
for item in items:
|
|
35
35
|
if tango_dir in str(item.fspath):
|
|
36
|
-
if sys.version_info >= (3, 12):
|
|
37
|
-
item.add_marker(
|
|
38
|
-
pytest.mark.skip(
|
|
39
|
-
reason="Tango is currently not supported on Python 3.12: https://github.com/bluesky/ophyd-async/issues/681"
|
|
40
|
-
)
|
|
41
|
-
)
|
|
42
36
|
if sys.platform.startswith(
|
|
43
37
|
"win"
|
|
44
38
|
): # expect "win32", but open to a future change: https://mail.python.org/pipermail/patches/2000-May/000648.html
|
|
@@ -222,3 +216,21 @@ def everything_signal_info():
|
|
|
222
216
|
)
|
|
223
217
|
|
|
224
218
|
return signal_info
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@pytest.fixture
|
|
222
|
+
def event_loop():
|
|
223
|
+
"""Create a fresh event loop for each test."""
|
|
224
|
+
loop = asyncio.new_event_loop()
|
|
225
|
+
asyncio.set_event_loop(loop)
|
|
226
|
+
|
|
227
|
+
yield loop
|
|
228
|
+
|
|
229
|
+
# Cancel all pending tasks
|
|
230
|
+
pending = asyncio.all_tasks(loop)
|
|
231
|
+
for task in pending:
|
|
232
|
+
task.cancel()
|
|
233
|
+
loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
|
|
234
|
+
|
|
235
|
+
loop.close()
|
|
236
|
+
asyncio.set_event_loop(None)
|
|
@@ -6,6 +6,7 @@ from typing import TypeVar, get_origin
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pytest
|
|
9
|
+
from tango.asyncio import DeviceProxy
|
|
9
10
|
from test_base_device import TestDevice
|
|
10
11
|
|
|
11
12
|
from ophyd_async.core import NotConnectedError, SignalRW, StandardReadable, StrictEnum
|
|
@@ -15,6 +16,7 @@ from ophyd_async.tango.core import (
|
|
|
15
16
|
TangoDevice,
|
|
16
17
|
TangoSignalBackend,
|
|
17
18
|
get_full_attr_trl,
|
|
19
|
+
parse_precision,
|
|
18
20
|
tango_signal_r,
|
|
19
21
|
tango_signal_rw,
|
|
20
22
|
tango_signal_w,
|
|
@@ -417,11 +419,7 @@ async def test_assert_val_reading_everything_tango(
|
|
|
417
419
|
everything_device.my_state_spectrum, esi["my_state_spectrum"].initial
|
|
418
420
|
)
|
|
419
421
|
|
|
420
|
-
# await assert_val_reading(everything_device.str_image, esi["str_image"].initial)
|
|
421
422
|
await assert_val_reading(everything_device.bool_image, esi["bool_image"].initial)
|
|
422
|
-
# await assert_val_reading(
|
|
423
|
-
# everything_device.strenum_image, esi["strenum_image"].initial
|
|
424
|
-
# )
|
|
425
423
|
await assert_val_reading(everything_device.int8_image, esi["int8_image"].initial)
|
|
426
424
|
await assert_val_reading(everything_device.uint8_image, esi["uint8_image"].initial)
|
|
427
425
|
await assert_val_reading(everything_device.int16_image, esi["int16_image"].initial)
|
|
@@ -442,14 +440,10 @@ async def test_assert_val_reading_everything_tango(
|
|
|
442
440
|
await assert_val_reading(
|
|
443
441
|
everything_device.float64_image, esi["float64_image"].initial
|
|
444
442
|
)
|
|
445
|
-
# await assert_val_reading(
|
|
446
|
-
# everything_device.my_state_image, esi["my_state_image"].initial
|
|
447
|
-
# )
|
|
448
443
|
|
|
449
444
|
|
|
450
445
|
@pytest.mark.asyncio
|
|
451
446
|
async def test_set_callback(everything_device_trl):
|
|
452
|
-
# await prepare_device(everything_device_trl, "float32", 1.0)
|
|
453
447
|
source = get_full_attr_trl(everything_device_trl, "float32")
|
|
454
448
|
transport = await make_backend(float, source, connect=False)
|
|
455
449
|
|
|
@@ -496,7 +490,6 @@ async def test_set_callback(everything_device_trl):
|
|
|
496
490
|
@pytest.mark.asyncio
|
|
497
491
|
@pytest.mark.parametrize("allow", [True, False])
|
|
498
492
|
async def test_tango_transport_allow_events(everything_device_trl, allow):
|
|
499
|
-
# await prepare_device(echo_device, "float32", 1.0)
|
|
500
493
|
source = get_full_attr_trl(everything_device_trl, "float32")
|
|
501
494
|
transport = await make_backend(float, source, connect=False)
|
|
502
495
|
transport.allow_events(allow)
|
|
@@ -505,7 +498,6 @@ async def test_tango_transport_allow_events(everything_device_trl, allow):
|
|
|
505
498
|
|
|
506
499
|
@pytest.mark.asyncio
|
|
507
500
|
async def test_tango_transport_set_polling(everything_device_trl):
|
|
508
|
-
# await prepare_device(echo_device, "float32", 1.0)
|
|
509
501
|
source = get_full_attr_trl(everything_device_trl, "float32")
|
|
510
502
|
transport = await make_backend(float, source, connect=False)
|
|
511
503
|
transport.set_polling(True, 0.1, 1, 0.1)
|
|
@@ -515,7 +507,6 @@ async def test_tango_transport_set_polling(everything_device_trl):
|
|
|
515
507
|
@pytest.mark.asyncio
|
|
516
508
|
@pytest.mark.timeout(12.0)
|
|
517
509
|
async def test_attribute_subscribe_callback(everything_device_trl):
|
|
518
|
-
# await prepare_device(echo_device, "float32", 1.0)
|
|
519
510
|
source = get_full_attr_trl(everything_device_trl, "int64")
|
|
520
511
|
backend = await make_backend(int, source)
|
|
521
512
|
attr_proxy = backend.proxies[source]
|
|
@@ -543,7 +534,6 @@ async def test_attribute_subscribe_callback(everything_device_trl):
|
|
|
543
534
|
|
|
544
535
|
@pytest.mark.asyncio
|
|
545
536
|
async def test_attribute_unsubscribe_callback(everything_device_trl):
|
|
546
|
-
# await prepare_device(echo_device, "float32", 1.0)
|
|
547
537
|
source = get_full_attr_trl(everything_device_trl, "float32")
|
|
548
538
|
backend = await make_backend(float, source)
|
|
549
539
|
attr_proxy = backend.proxies[source]
|
|
@@ -556,3 +546,23 @@ async def test_attribute_unsubscribe_callback(everything_device_trl):
|
|
|
556
546
|
attr_proxy.unsubscribe_callback()
|
|
557
547
|
assert not attr_proxy.has_subscription()
|
|
558
548
|
await asyncio.sleep(0.1)
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
@pytest.mark.asyncio
|
|
552
|
+
@pytest.mark.timeout(3.0)
|
|
553
|
+
async def test_parse_precision(everything_device_trl):
|
|
554
|
+
proxy = await DeviceProxy(everything_device_trl)
|
|
555
|
+
for attr in proxy.get_attribute_list():
|
|
556
|
+
config = await proxy.get_attribute_config(attr)
|
|
557
|
+
precision = parse_precision(config)
|
|
558
|
+
if attr in [
|
|
559
|
+
"float32",
|
|
560
|
+
"float32_image",
|
|
561
|
+
"float32_spectrum",
|
|
562
|
+
"float64",
|
|
563
|
+
"float64_image",
|
|
564
|
+
"float64_spectrum",
|
|
565
|
+
]:
|
|
566
|
+
assert precision == 2
|
|
567
|
+
else:
|
|
568
|
+
assert precision is None
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import os
|
|
3
|
+
import shutil
|
|
3
4
|
import sys
|
|
4
5
|
import uuid
|
|
5
6
|
from datetime import date
|
|
@@ -10,6 +11,9 @@ import pytest
|
|
|
10
11
|
from ophyd_async.core import (
|
|
11
12
|
AutoIncrementFilenameProvider,
|
|
12
13
|
AutoIncrementingPathProvider,
|
|
14
|
+
AutoMaxIncrementingPathProvider,
|
|
15
|
+
PathInfo,
|
|
16
|
+
StaticFilenameProvider,
|
|
13
17
|
StaticPathProvider,
|
|
14
18
|
UUIDFilenameProvider,
|
|
15
19
|
YMDPathProvider,
|
|
@@ -75,6 +79,59 @@ def test_auto_increment_path_provider(static_filename_provider, tmp_path):
|
|
|
75
79
|
assert os.path.basename(info.directory_path) == "00002"
|
|
76
80
|
|
|
77
81
|
|
|
82
|
+
def test_auto_max_increment_path_provider(tmp_path: Path):
|
|
83
|
+
def write_file(info: PathInfo):
|
|
84
|
+
os.makedirs(info.directory_path)
|
|
85
|
+
with open(f"{info.directory_path}/{info.filename}", "w"):
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
filename = "capture"
|
|
89
|
+
base_provider = StaticPathProvider(StaticFilenameProvider("capture"), tmp_path)
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
# Test multiple increments
|
|
93
|
+
path_provider = AutoMaxIncrementingPathProvider(base_provider, max_digits=3)
|
|
94
|
+
info = path_provider()
|
|
95
|
+
write_file(info)
|
|
96
|
+
expected_path = tmp_path / f"000_{filename}"
|
|
97
|
+
assert info.directory_path == expected_path
|
|
98
|
+
info = path_provider()
|
|
99
|
+
write_file(info)
|
|
100
|
+
expected_path = tmp_path / f"001_{filename}"
|
|
101
|
+
assert info.directory_path == expected_path
|
|
102
|
+
|
|
103
|
+
# Test fresh path provider continues incrementing
|
|
104
|
+
path_provider = AutoMaxIncrementingPathProvider(base_provider)
|
|
105
|
+
info = path_provider()
|
|
106
|
+
write_file(info)
|
|
107
|
+
expected_path = tmp_path / f"0002_{filename}"
|
|
108
|
+
assert info.directory_path == expected_path
|
|
109
|
+
|
|
110
|
+
# Test path provider in dated mode
|
|
111
|
+
path_provider = AutoMaxIncrementingPathProvider(base_provider, dated=True)
|
|
112
|
+
info = path_provider()
|
|
113
|
+
write_file(info)
|
|
114
|
+
assert (
|
|
115
|
+
info.directory_path
|
|
116
|
+
== tmp_path / date.today().strftime("%Y-%m-%d") / f"0000_{filename}"
|
|
117
|
+
)
|
|
118
|
+
info = path_provider()
|
|
119
|
+
write_file(info)
|
|
120
|
+
assert (
|
|
121
|
+
info.directory_path
|
|
122
|
+
== tmp_path / date.today().strftime("%Y-%m-%d") / f"0001_{filename}"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
finally:
|
|
126
|
+
# Tidy up directory - although they should have been
|
|
127
|
+
# created in a temporary location
|
|
128
|
+
for file in tmp_path.iterdir():
|
|
129
|
+
if file.is_file():
|
|
130
|
+
file.unlink()
|
|
131
|
+
elif file.is_dir():
|
|
132
|
+
shutil.rmtree(file)
|
|
133
|
+
|
|
134
|
+
|
|
78
135
|
def test_ymd_path_provider(static_filename_provider, tmp_path):
|
|
79
136
|
ymd_path_provider = YMDPathProvider(static_filename_provider, tmp_path)
|
|
80
137
|
current_date = date.today()
|