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.
Files changed (329) hide show
  1. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.copier-answers.yml +1 -1
  2. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/CONTRIBUTING.md +1 -1
  3. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_test.yml +0 -5
  4. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/ci.yml +4 -2
  5. ophyd_async-0.14.1/.github/workflows/claude.yml +52 -0
  6. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.pre-commit-config.yaml +1 -1
  7. {ophyd_async-0.14.0/src/ophyd_async.egg-info → ophyd_async-0.14.1}/PKG-INFO +1 -1
  8. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/_version.py +3 -3
  9. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/__init__.py +2 -0
  10. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_providers.py +94 -1
  11. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_trajectory.py +15 -1
  12. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger_io.py +1 -1
  13. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_control.py +2 -1
  14. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/__init__.py +6 -0
  15. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_tango_transport.py +12 -11
  16. {ophyd_async-0.14.0 → ophyd_async-0.14.1/src/ophyd_async.egg-info}/PKG-INFO +1 -1
  17. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/SOURCES.txt +6 -5
  18. {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/conftest.py +20 -8
  19. {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_tango_signals.py +22 -12
  20. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_providers.py +57 -0
  21. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_trajectory.py +35 -16
  22. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.codecov.yml +0 -0
  23. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.devcontainer/devcontainer.json +0 -0
  24. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.git-blame-ignore-revs +0 -0
  25. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  26. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  27. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  28. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/codeql/codeql-config.yml +0 -0
  29. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/pages/index.html +0 -0
  30. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/pages/make_switcher.py +0 -0
  31. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_codeql.yml +0 -0
  32. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_dist.yml +0 -0
  33. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_docs.yml +0 -0
  34. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_pypi.yml +0 -0
  35. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_release.yml +0 -0
  36. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/_tox.yml +0 -0
  37. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.github/workflows/periodic.yml +0 -0
  38. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.gitignore +0 -0
  39. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.gitleaks.toml +0 -0
  40. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.gitmodules +0 -0
  41. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/.python-version +0 -0
  42. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/Dockerfile +0 -0
  43. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/LICENSE +0 -0
  44. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/README.md +0 -0
  45. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/_static/custom.css +0 -0
  46. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/conf.py +0 -0
  47. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  48. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  49. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  50. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  51. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  52. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  53. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
  54. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0008-signal-types.md +0 -0
  55. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
  56. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0010-docstring-format.md +0 -0
  57. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/0011-buffer-updates-camonitor.md +0 -0
  58. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions/COPYME +0 -0
  59. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/decisions.md +0 -0
  60. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/declarative-vs-procedural.md +0 -0
  61. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/design-goals.md +0 -0
  62. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/device-connection-strategies.md +0 -0
  63. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/devices-signals-backends.md +0 -0
  64. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/fly-scanning.md +0 -0
  65. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/plan-stubs.md +0 -0
  66. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/when-to-extend-movable.md +0 -0
  67. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations/where-device-logic.md +0 -0
  68. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/explanations.md +0 -0
  69. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/genindex.rst +0 -0
  70. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/choose-right-baseclass.md +0 -0
  71. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/contribute.md +0 -0
  72. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/derive-one-signal-from-others.md +0 -0
  73. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/implement-ad-detector.md +0 -0
  74. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/interact-with-signals.md +0 -0
  75. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/put-device-back.md +0 -0
  76. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to/store-and-retrieve.md +0 -0
  77. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/how-to.md +0 -0
  78. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
  79. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/ophyd-async-logo.svg +0 -0
  80. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/ophyd-favicon.svg +0 -0
  81. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
  82. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/index.md +0 -0
  83. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/reference.md +0 -0
  84. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/implementing-detectors.md +0 -0
  85. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/implementing-devices.md +0 -0
  86. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/installation.md +0 -0
  87. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/using-devices.md +0 -0
  88. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials/writing-tests-for-devices.md +0 -0
  89. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/docs/tutorials.md +0 -0
  90. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/pyproject.toml +0 -0
  91. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/renovate.json +0 -0
  92. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/setup.cfg +0 -0
  93. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/__init__.py +0 -0
  94. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/__main__.py +0 -0
  95. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/_docs_parser.py +0 -0
  96. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_derived_signal.py +0 -0
  97. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
  98. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_detector.py +0 -0
  99. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_device.py +0 -0
  100. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_device_filler.py +0 -0
  101. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_enums.py +0 -0
  102. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_flyer.py +0 -0
  103. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_hdf_dataset.py +0 -0
  104. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_log.py +0 -0
  105. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
  106. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_mock_signal_utils.py +0 -0
  107. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_protocol.py +0 -0
  108. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_readable.py +0 -0
  109. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_settings.py +0 -0
  110. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_signal.py +0 -0
  111. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_signal_backend.py +0 -0
  112. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
  113. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_status.py +0 -0
  114. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_table.py +0 -0
  115. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_utils.py +0 -0
  116. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/core/_yaml_settings.py +0 -0
  117. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/__init__.py +0 -0
  118. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/__init__.py +0 -0
  119. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor.py +0 -0
  120. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
  121. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
  122. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
  123. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
  124. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
  125. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
  126. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/__init__.py +0 -0
  127. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
  128. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
  129. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_logic.py +0 -0
  130. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_writer.py +0 -0
  131. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_hdf_writer.py +0 -0
  132. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
  133. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
  134. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
  135. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_utils.py +0 -0
  136. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
  137. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
  138. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
  139. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
  140. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
  141. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
  142. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
  143. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
  144. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
  145. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
  146. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
  147. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
  148. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/__init__.py +0 -0
  149. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
  150. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
  151. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
  152. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/__init__.py +0 -0
  153. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_aioca.py +0 -0
  154. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
  155. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_epics_device.py +0 -0
  156. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_p4p.py +0 -0
  157. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
  158. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_signal.py +0 -0
  159. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_util.py +0 -0
  160. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/__init__.py +0 -0
  161. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/__main__.py +0 -0
  162. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_ioc.py +0 -0
  163. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_motor.py +0 -0
  164. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
  165. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
  166. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_stage.py +0 -0
  167. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/motor.db +0 -0
  168. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/point_detector.db +0 -0
  169. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
  170. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/motor.py +0 -0
  171. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/odin/__init__.py +0 -0
  172. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/odin/_odin_io.py +0 -0
  173. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/__init__.py +0 -0
  174. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_io.py +0 -0
  175. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_trajectory_generation.py +0 -0
  176. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_utils.py +0 -0
  177. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/signal.py +0 -0
  178. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/__init__.py +0 -0
  179. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
  180. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/_utils.py +0 -0
  181. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/test_records.db +0 -0
  182. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
  183. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/__init__.py +0 -0
  184. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/core.py +0 -0
  185. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
  186. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
  187. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
  188. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/__init__.py +0 -0
  189. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_controller.py +0 -0
  190. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_jungfrau.py +0 -0
  191. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_signals.py +0 -0
  192. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_utils.py +0 -0
  193. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
  194. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
  195. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_block.py +0 -0
  196. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
  197. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_table.py +0 -0
  198. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
  199. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
  200. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/__init__.py +0 -0
  201. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
  202. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_fly.py +0 -0
  203. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
  204. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_panda.py +0 -0
  205. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_settings.py +0 -0
  206. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_utils.py +0 -0
  207. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
  208. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/py.typed +0 -0
  209. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/__init__.py +0 -0
  210. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/__main__.py +0 -0
  211. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector.py +0 -0
  212. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
  213. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
  214. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
  215. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
  216. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_motor.py +0 -0
  217. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_pattern_generator.py +0 -0
  218. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_point_detector.py +0 -0
  219. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/sim/_stage.py +0 -0
  220. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/__init__.py +0 -0
  221. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_base_device.py +0 -0
  222. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_converters.py +0 -0
  223. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_signal.py +0 -0
  224. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_utils.py +0 -0
  225. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/__init__.py +0 -0
  226. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_counter.py +0 -0
  227. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_detector.py +0 -0
  228. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_mover.py +0 -0
  229. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
  230. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
  231. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/__init__.py +0 -0
  232. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
  233. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/_test_config.py +0 -0
  234. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/__init__.py +0 -0
  235. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
  236. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_assert.py +0 -0
  237. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_one_of_everything.py +0 -0
  238. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_single_derived.py +0 -0
  239. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_utils.py +0 -0
  240. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
  241. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  242. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/requires.txt +0 -0
  243. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/top_level.txt +0 -0
  244. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/README.md +0 -0
  245. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/conftest.py +0 -0
  246. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/__init__.py +0 -0
  247. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/conftest.py +0 -0
  248. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/baseline.yaml +0 -0
  249. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/external_dependencies.sh +0 -0
  250. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/test_adsim_system.py +0 -0
  251. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/README.md +0 -0
  252. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
  253. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/test_eiger_system.py +0 -0
  254. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_signals.py +0 -0
  255. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_yaml_save_ca.yaml +0 -0
  256. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_yaml_save_pva.yaml +0 -0
  257. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/fastcs/panda/test_panda_connect.py +0 -0
  258. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/system_tests/test_tutorials.py +0 -0
  259. {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/context_subprocess.py +0 -0
  260. {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_base_device.py +0 -0
  261. {ophyd_async-0.14.0/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_tango_transport.py +0 -0
  262. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/__init__.py +0 -0
  263. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_auto_init_devices.py +0 -0
  264. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_detector.py +0 -0
  265. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_device.py +0 -0
  266. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_flyer.py +0 -0
  267. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_log.py +0 -0
  268. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_mock_signal_backend.py +0 -0
  269. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_multi_derived_signal.py +0 -0
  270. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_observe.py +0 -0
  271. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_protocol.py +0 -0
  272. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_readable.py +0 -0
  273. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_signal.py +0 -0
  274. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_single_derived_signal.py +0 -0
  275. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_soft_signal_backend.py +0 -0
  276. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_status.py +0 -0
  277. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_subset_enum.py +0 -0
  278. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_table.py +0 -0
  279. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_utils.py +0 -0
  280. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/core/test_watchable_async_status.py +0 -0
  281. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adandor/test_andor.py +0 -0
  282. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adaravis/test_aravis.py +0 -0
  283. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_cont_acq_detector.py +0 -0
  284. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_detectors.py +0 -0
  285. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_drivers.py +0 -0
  286. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_plugins.py +0 -0
  287. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_scans.py +0 -0
  288. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_single_trigger.py +0 -0
  289. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_writers.py +0 -0
  290. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adkinetix/test_kinetix.py +0 -0
  291. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adpilatus/test_pilatus.py +0 -0
  292. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/adsimdetector/test_sim.py +0 -0
  293. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/advimba/test_vimba.py +0 -0
  294. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/conftest.py +0 -0
  295. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/demo/test_epics_demo.py +0 -0
  296. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/eiger/test_odin_io.py +0 -0
  297. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/conftest.py +0 -0
  298. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_io.py +0 -0
  299. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_trajectory_generation.py +0 -0
  300. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_utils.py +0 -0
  301. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/pvi/test_pvi.py +0 -0
  302. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/signal/test_common.py +0 -0
  303. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/test_areadetector_subclass_naming.py +0 -0
  304. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/epics/test_motor.py +0 -0
  305. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/eiger/test_eiger_controller.py +0 -0
  306. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/eiger/test_eiger_detector.py +0 -0
  307. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/__init__.py +0 -0
  308. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/test_controller.py +0 -0
  309. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/test_utils.py +0 -0
  310. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/db/panda.db +0 -0
  311. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_hdf_panda.py +0 -0
  312. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_connect_mock.py +0 -0
  313. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_control.py +0 -0
  314. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_utils.py +0 -0
  315. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_seq_table.py +0 -0
  316. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_trigger.py +0 -0
  317. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_writer.py +0 -0
  318. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_ensure_connected.py +0 -0
  319. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_fly.py +0 -0
  320. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_settings.py +0 -0
  321. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_setup.py +0 -0
  322. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/sim/__init__.py +0 -0
  323. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/sim/test_sim_blob_detector.py +0 -0
  324. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/sim/test_sim_motor.py +0 -0
  325. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_branching.py +0 -0
  326. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_cli.py +0 -0
  327. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_data/test_yaml_config_save.yaml +0 -0
  328. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/tests/unit_tests/test_data/test_yaml_save.yaml +0 -0
  329. {ophyd_async-0.14.0 → ophyd_async-0.14.1}/uv.lock +0 -0
@@ -1,5 +1,5 @@
1
1
  # Changes here will be overwritten by Copier
2
- _commit: 5.0.0a5
2
+ _commit: 5.0.1
3
3
  _src_path: https://github.com/DiamondLightSource/python-copier-template
4
4
  author_email: tom.cobb@diamond.ac.uk
5
5
  author_name: Tom Cobb
@@ -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.0a5/how-to.html).
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:*)"
@@ -3,7 +3,7 @@ repos:
3
3
  rev: v5.0.0
4
4
  hooks:
5
5
  - id: check-added-large-files
6
- args: ["--maxkb=1000"] # uv.lock is more than 500kB
6
+ exclude: ^uv.lock
7
7
  - id: check-yaml
8
8
  - id: check-merge-conflict
9
9
  - id: end-of-file-fixer
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ophyd-async
3
- Version: 0.14.0
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.0'
32
- __version_tuple__ = version_tuple = (0, 14, 0)
31
+ __version__ = version = '0.14.1'
32
+ __version_tuple__ = version_tuple = (0, 14, 1)
33
33
 
34
- __commit_id__ = commit_id = 'g3da44d6fb'
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=10,
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
- pass
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 = None
643
- if config.format:
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.0
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/system_tests/tango/conftest.py
254
- tests/system_tests/tango/context_subprocess.py
255
- tests/system_tests/tango/test_base_device.py
256
- tests/system_tests/tango/test_tango_signals.py
257
- tests/system_tests/tango/test_tango_transport.py
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 os
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 = os.path.join("system_tests", "tango")
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()