ophyd-async 0.13.7__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.13.7 → ophyd_async-0.14.1}/.copier-answers.yml +1 -1
  2. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.devcontainer/devcontainer.json +3 -0
  3. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/CONTRIBUTING.md +1 -1
  4. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/_test.yml +0 -5
  5. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/ci.yml +6 -2
  6. ophyd_async-0.14.1/.github/workflows/claude.yml +52 -0
  7. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.pre-commit-config.yaml +1 -1
  8. {ophyd_async-0.13.7/src/ophyd_async.egg-info → ophyd_async-0.14.1}/PKG-INFO +1 -1
  9. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/tutorials/writing-tests-for-devices.md +41 -0
  10. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/pyproject.toml +1 -1
  11. {ophyd_async-0.13.7/.github → ophyd_async-0.14.1}/renovate.json +5 -21
  12. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/_version.py +3 -3
  13. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/__init__.py +30 -2
  14. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_device.py +92 -16
  15. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_mock_signal_backend.py +7 -1
  16. {ophyd_async-0.13.7/src/ophyd_async/testing → ophyd_async-0.14.1/src/ophyd_async/core}/_mock_signal_utils.py +11 -14
  17. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_providers.py +94 -1
  18. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_signal.py +1 -2
  19. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_utils.py +0 -40
  20. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/motor.py +37 -1
  21. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_trajectory.py +15 -1
  22. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger_io.py +1 -1
  23. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_control.py +2 -1
  24. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/__init__.py +6 -0
  25. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_tango_transport.py +12 -11
  26. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/testing/__init__.py +27 -17
  27. {ophyd_async-0.13.7 → ophyd_async-0.14.1/src/ophyd_async.egg-info}/PKG-INFO +1 -1
  28. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/SOURCES.txt +10 -7
  29. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_signals.py +2 -1
  30. {ophyd_async-0.13.7/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/conftest.py +20 -8
  31. {ophyd_async-0.13.7/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_tango_signals.py +22 -12
  32. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_auto_init_devices.py +1 -1
  33. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_flyer.py +7 -10
  34. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_mock_signal_backend.py +10 -12
  35. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_observe.py +2 -1
  36. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_providers.py +57 -0
  37. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_cont_acq_detector.py +1 -2
  38. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_drivers.py +1 -4
  39. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_scans.py +1 -1
  40. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_writers.py +2 -1
  41. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adkinetix/test_kinetix.py +1 -1
  42. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adpilatus/test_pilatus.py +1 -1
  43. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adsimdetector/test_sim.py +2 -1
  44. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/advimba/test_vimba.py +1 -2
  45. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/conftest.py +1 -2
  46. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/eiger/test_odin_io.py +3 -3
  47. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/conftest.py +1 -2
  48. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_trajectory.py +39 -20
  49. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_trajectory_generation.py +1 -1
  50. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_utils.py +1 -1
  51. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/test_motor.py +220 -9
  52. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/eiger/test_eiger_controller.py +2 -4
  53. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/eiger/test_eiger_detector.py +8 -2
  54. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/test_controller.py +7 -5
  55. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_hdf_panda.py +2 -1
  56. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_trigger.py +1 -2
  57. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_writer.py +2 -1
  58. ophyd_async-0.14.1/tests/unit_tests/plan_stubs/test_fly.py +0 -0
  59. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_settings.py +1 -2
  60. ophyd_async-0.14.1/tests/unit_tests/sim/__init__.py +0 -0
  61. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.codecov.yml +0 -0
  62. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.git-blame-ignore-revs +0 -0
  63. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  64. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  65. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  66. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/codeql/codeql-config.yml +0 -0
  67. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/pages/index.html +0 -0
  68. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/pages/make_switcher.py +0 -0
  69. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/_codeql.yml +0 -0
  70. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/_dist.yml +0 -0
  71. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/_docs.yml +0 -0
  72. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/_pypi.yml +0 -0
  73. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/_release.yml +0 -0
  74. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/_tox.yml +0 -0
  75. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.github/workflows/periodic.yml +0 -0
  76. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.gitignore +0 -0
  77. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.gitleaks.toml +0 -0
  78. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.gitmodules +0 -0
  79. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/.python-version +0 -0
  80. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/Dockerfile +0 -0
  81. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/LICENSE +0 -0
  82. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/README.md +0 -0
  83. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/_static/custom.css +0 -0
  84. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/conf.py +0 -0
  85. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  86. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  87. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  88. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  89. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  90. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  91. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
  92. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0008-signal-types.md +0 -0
  93. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
  94. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0010-docstring-format.md +0 -0
  95. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/0011-buffer-updates-camonitor.md +0 -0
  96. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions/COPYME +0 -0
  97. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/decisions.md +0 -0
  98. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/declarative-vs-procedural.md +0 -0
  99. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/design-goals.md +0 -0
  100. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/device-connection-strategies.md +0 -0
  101. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/devices-signals-backends.md +0 -0
  102. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/fly-scanning.md +0 -0
  103. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/plan-stubs.md +0 -0
  104. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/when-to-extend-movable.md +0 -0
  105. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations/where-device-logic.md +0 -0
  106. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/explanations.md +0 -0
  107. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/genindex.rst +0 -0
  108. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to/choose-right-baseclass.md +0 -0
  109. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to/contribute.md +0 -0
  110. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to/derive-one-signal-from-others.md +0 -0
  111. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to/implement-ad-detector.md +0 -0
  112. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to/interact-with-signals.md +0 -0
  113. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to/put-device-back.md +0 -0
  114. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to/store-and-retrieve.md +0 -0
  115. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/how-to.md +0 -0
  116. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/images/fly_scan_collection_windows_and_frames.svg +0 -0
  117. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/images/ophyd-async-logo.svg +0 -0
  118. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/images/ophyd-favicon.svg +0 -0
  119. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
  120. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/index.md +0 -0
  121. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/reference.md +0 -0
  122. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/tutorials/implementing-detectors.md +0 -0
  123. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/tutorials/implementing-devices.md +0 -0
  124. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/tutorials/installation.md +0 -0
  125. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/tutorials/using-devices.md +0 -0
  126. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/docs/tutorials.md +0 -0
  127. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/setup.cfg +0 -0
  128. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/__init__.py +0 -0
  129. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/__main__.py +0 -0
  130. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/_docs_parser.py +0 -0
  131. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_derived_signal.py +0 -0
  132. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_derived_signal_backend.py +0 -0
  133. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_detector.py +0 -0
  134. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_device_filler.py +0 -0
  135. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_enums.py +0 -0
  136. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_flyer.py +0 -0
  137. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_hdf_dataset.py +0 -0
  138. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_log.py +0 -0
  139. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_protocol.py +0 -0
  140. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_readable.py +0 -0
  141. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_settings.py +0 -0
  142. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_signal_backend.py +0 -0
  143. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
  144. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_status.py +0 -0
  145. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_table.py +0 -0
  146. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/core/_yaml_settings.py +0 -0
  147. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/__init__.py +0 -0
  148. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/__init__.py +0 -0
  149. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor.py +0 -0
  150. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
  151. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
  152. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
  153. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
  154. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
  155. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
  156. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/__init__.py +0 -0
  157. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
  158. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
  159. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_logic.py +0 -0
  160. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_core_writer.py +0 -0
  161. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_hdf_writer.py +0 -0
  162. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
  163. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
  164. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
  165. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adcore/_utils.py +0 -0
  166. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
  167. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
  168. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
  169. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
  170. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
  171. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
  172. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
  173. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
  174. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
  175. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
  176. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
  177. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
  178. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/__init__.py +0 -0
  179. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
  180. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
  181. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
  182. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/__init__.py +0 -0
  183. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_aioca.py +0 -0
  184. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
  185. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_epics_device.py +0 -0
  186. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_p4p.py +0 -0
  187. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
  188. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_signal.py +0 -0
  189. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/core/_util.py +0 -0
  190. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/__init__.py +0 -0
  191. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/__main__.py +0 -0
  192. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_ioc.py +0 -0
  193. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_motor.py +0 -0
  194. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
  195. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
  196. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/_stage.py +0 -0
  197. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/motor.db +0 -0
  198. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/point_detector.db +0 -0
  199. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
  200. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/odin/__init__.py +0 -0
  201. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/odin/_odin_io.py +0 -0
  202. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/__init__.py +0 -0
  203. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_io.py +0 -0
  204. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_pmac_trajectory_generation.py +0 -0
  205. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/pmac/_utils.py +0 -0
  206. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/signal.py +0 -0
  207. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/__init__.py +0 -0
  208. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
  209. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/_utils.py +0 -0
  210. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/test_records.db +0 -0
  211. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
  212. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/__init__.py +0 -0
  213. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/core.py +0 -0
  214. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
  215. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
  216. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
  217. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/__init__.py +0 -0
  218. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_controller.py +0 -0
  219. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_jungfrau.py +0 -0
  220. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_signals.py +0 -0
  221. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/jungfrau/_utils.py +0 -0
  222. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
  223. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
  224. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_block.py +0 -0
  225. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
  226. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_table.py +0 -0
  227. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
  228. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
  229. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/__init__.py +0 -0
  230. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
  231. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_fly.py +0 -0
  232. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
  233. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_panda.py +0 -0
  234. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_settings.py +0 -0
  235. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_utils.py +0 -0
  236. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
  237. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/py.typed +0 -0
  238. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/__init__.py +0 -0
  239. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/__main__.py +0 -0
  240. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector.py +0 -0
  241. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
  242. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
  243. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
  244. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
  245. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_motor.py +0 -0
  246. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_pattern_generator.py +0 -0
  247. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_point_detector.py +0 -0
  248. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/sim/_stage.py +0 -0
  249. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/__init__.py +0 -0
  250. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_base_device.py +0 -0
  251. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_converters.py +0 -0
  252. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_signal.py +0 -0
  253. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/core/_utils.py +0 -0
  254. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/__init__.py +0 -0
  255. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_counter.py +0 -0
  256. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_detector.py +0 -0
  257. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_mover.py +0 -0
  258. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
  259. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
  260. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/__init__.py +0 -0
  261. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
  262. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/tango/testing/_test_config.py +0 -0
  263. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
  264. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/testing/_assert.py +0 -0
  265. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/testing/_one_of_everything.py +0 -0
  266. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/testing/_single_derived.py +0 -0
  267. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/testing/_utils.py +0 -0
  268. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
  269. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  270. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/requires.txt +0 -0
  271. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/src/ophyd_async.egg-info/top_level.txt +0 -0
  272. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/README.md +0 -0
  273. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/conftest.py +0 -0
  274. {ophyd_async-0.13.7/tests/unit_tests/fastcs/jungfrau → ophyd_async-0.14.1/tests/system_tests}/__init__.py +0 -0
  275. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/conftest.py +0 -0
  276. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/baseline.yaml +0 -0
  277. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/external_dependencies.sh +0 -0
  278. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/adsim/test_adsim_system.py +0 -0
  279. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/README.md +0 -0
  280. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
  281. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/eiger/test_eiger_system.py +0 -0
  282. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_yaml_save_ca.yaml +0 -0
  283. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/epics/signal/test_yaml_save_pva.yaml +0 -0
  284. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/fastcs/panda/test_panda_connect.py +0 -0
  285. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/system_tests/test_tutorials.py +0 -0
  286. {ophyd_async-0.13.7/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/context_subprocess.py +0 -0
  287. {ophyd_async-0.13.7/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_base_device.py +0 -0
  288. {ophyd_async-0.13.7/tests/system_tests/tango → ophyd_async-0.14.1/tests/system_tests_tango}/test_tango_transport.py +0 -0
  289. {ophyd_async-0.13.7/tests/unit_tests/sim → ophyd_async-0.14.1/tests/unit_tests}/__init__.py +0 -0
  290. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_detector.py +0 -0
  291. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_device.py +0 -0
  292. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_log.py +0 -0
  293. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_multi_derived_signal.py +2 -2
  294. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_protocol.py +0 -0
  295. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_readable.py +0 -0
  296. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_signal.py +3 -3
  297. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_single_derived_signal.py +1 -1
  298. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_soft_signal_backend.py +0 -0
  299. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_status.py +0 -0
  300. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_subset_enum.py +0 -0
  301. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_table.py +0 -0
  302. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_utils.py +0 -0
  303. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/core/test_watchable_async_status.py +0 -0
  304. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adandor/test_andor.py +0 -0
  305. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adaravis/test_aravis.py +0 -0
  306. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_detectors.py +0 -0
  307. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_plugins.py +0 -0
  308. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/adcore/test_single_trigger.py +0 -0
  309. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/demo/test_epics_demo.py +3 -3
  310. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/pmac/test_pmac_io.py +0 -0
  311. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/pvi/test_pvi.py +0 -0
  312. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/signal/test_common.py +0 -0
  313. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/epics/test_areadetector_subclass_naming.py +0 -0
  314. /ophyd_async-0.13.7/tests/unit_tests/plan_stubs/test_fly.py → /ophyd_async-0.14.1/tests/unit_tests/fastcs/jungfrau/__init__.py +0 -0
  315. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/jungfrau/test_utils.py +0 -0
  316. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/db/panda.db +0 -0
  317. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_connect_mock.py +0 -0
  318. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_control.py +0 -0
  319. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_panda_utils.py +0 -0
  320. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/fastcs/panda/test_seq_table.py +0 -0
  321. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_ensure_connected.py +0 -0
  322. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/plan_stubs/test_setup.py +0 -0
  323. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/sim/test_sim_blob_detector.py +0 -0
  324. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/sim/test_sim_motor.py +0 -0
  325. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/test_branching.py +0 -0
  326. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/test_cli.py +0 -0
  327. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/test_data/test_yaml_config_save.yaml +0 -0
  328. {ophyd_async-0.13.7 → ophyd_async-0.14.1}/tests/unit_tests/test_data/test_yaml_save.yaml +0 -0
  329. {ophyd_async-0.13.7 → 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.0a4
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
@@ -34,6 +34,9 @@
34
34
  "python.terminal.shellIntegration.enabled": false,
35
35
  "python.testing.unittestEnabled": false,
36
36
  "python.testing.pytestEnabled": true,
37
+ "python.testing.pytestArgs": [
38
+ "tests"
39
+ ],
37
40
  "editor.formatOnSave": true,
38
41
  "editor.codeActionsOnSave": {
39
42
  "source.organizeImports": "explicit"
@@ -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.0a4/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,17 +20,21 @@ 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
36
+ permissions:
37
+ contents: write
34
38
 
35
39
  dist:
36
40
  uses: ./.github/workflows/_dist.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.13.7
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
@@ -87,6 +87,47 @@ There are a few other things we may wish to do in tests:
87
87
  - [](#set_mock_put_proceeds) to block or unblock `Signal.set(..., wait=True)` from completing
88
88
  - [](#mock_puts_blocked) a context manager that blocks put proceeds at the start, and unblocks at the end
89
89
 
90
+ ### Automatic mock behavior injection
91
+
92
+ If you find yourself repeatedly using [](#callback_on_mock_put) to set up the same mock behavior for a Device type across many tests, you can define a [](#DeviceMock) subclass to automatically inject that behavior when the Device is connected in mock mode. This is especially useful for defining standard mock behavior alongside your Device definitions, making it easier to switch between hardware and mock modes.
93
+
94
+ For example, if you have a device that needs automatic mock behavior, you can define:
95
+
96
+ ```{literalinclude} ../../src/ophyd_async/epics/motor.py
97
+ :language: python
98
+ :pyobject: InstantMotorMock
99
+ ```
100
+
101
+ Then decorate the original class with [](#default_mock_class) so it is automatically used when connected in mock mode:
102
+
103
+ ```{literalinclude} ../../src/ophyd_async/epics/motor.py
104
+ :language: python
105
+ :start-at: default_mock_class(
106
+ :end-at: class Motor
107
+ ```
108
+
109
+ Now whenever a Motor is connected in mock mode using [](#init_devices)`(mock=True)`, it will automatically use `InstantMotorMock` and have this behavior:
110
+
111
+ ```python
112
+ async with init_devices(mock=True):
113
+ motor = Motor("BLxxI-MO-TABLE-01:X")
114
+
115
+ # No manual callback setup needed - the mock behavior is already active
116
+ await motor.user_setpoint.set(50.0)
117
+ assert await motor.user_readback.get_value() == 50.0
118
+ ```
119
+
120
+ You can still override the automatic mock for specific tests by passing an explicit [](#DeviceMock) instance:
121
+
122
+ ```python
123
+ # Use a plain DeviceMock without the automatic behavior
124
+ custom_mock = DeviceMock()
125
+ motor = Motor("TEST:MOTOR")
126
+ await motor.connect(mock=custom_mock)
127
+ ```
128
+
129
+ This approach keeps your mock logic close to your Device definition, reduces duplication across tests, and makes it easier to maintain consistent mock behavior.
130
+
90
131
  ## Tests that execute a bluesky plan
91
132
 
92
133
  If we need to check that our Device performs correctly within a plan that calls multiple verbs, it is best to test it under an actual RunEngine. This allows you to check that when the verbs are called in the order that they are in the plan, the correct behavior occurs.
@@ -96,7 +96,7 @@ addopts = """
96
96
  --ignore=docs/examples --ignore=src/ophyd_async/epics/signal.py
97
97
  """
98
98
  # https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings
99
- filterwarnings = "error"
99
+ filterwarnings = ["error"]
100
100
  # Doctest python code in docs, python code in src docstrings, test functions in tests
101
101
  testpaths = "docs src tests/unit_tests"
102
102
  log_format = "%(asctime)s,%(msecs)03d %(levelname)s (%(threadName)s) %(message)s"
@@ -6,7 +6,7 @@
6
6
  "lockFileMaintenance": {
7
7
  "description": "Keep uv.lock up to date, merging if tests pass",
8
8
  "enabled": true,
9
- "automerge": true
9
+ "automerge": true
10
10
  },
11
11
  "packageRules": [
12
12
  {
@@ -20,34 +20,18 @@
20
20
  "description": "Disable github actions that are managed by python-copier-template",
21
21
  "matchPackageNames": [
22
22
  "actions/checkout",
23
- "actions/download-artifact",
24
- "actions/setup-python",
25
- "actions/upload-artifact",
26
23
  "astral-sh/setup-uv",
24
+ "actions/upload-artifact",
25
+ "actions/download-artifact",
26
+ "softprops/action-gh-release",
27
27
  "codecov/codecov-action",
28
- "docker/build-push-action",
29
- "docker/login-action",
30
- "docker/metadata-action",
31
- "docker/setup-buildx-action",
32
- "peaceiris/actions-gh-pages",
33
28
  "pypa/gh-action-pypi-publish",
34
- "softprops/action-gh-release"
29
+ "peaceiris/actions-gh-pages"
35
30
  ],
36
31
  "matchManagers": [
37
32
  "github-actions"
38
33
  ],
39
34
  "enabled": false
40
- },
41
- {
42
- "description": "Group non-major github action updates",
43
- "groupName": "GitHub Actions",
44
- "matchUpdateTypes": [
45
- "patch",
46
- "minor"
47
- ],
48
- "matchManagers": [
49
- "github-actions"
50
- ]
51
35
  }
52
36
  ]
53
37
  }
@@ -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.13.7'
32
- __version_tuple__ = version_tuple = (0, 13, 7)
31
+ __version__ = version = '0.14.1'
32
+ __version_tuple__ = version_tuple = (0, 14, 1)
33
33
 
34
- __commit_id__ = commit_id = 'g80ae4488a'
34
+ __commit_id__ = commit_id = 'g9b567b214'
@@ -14,7 +14,15 @@ from ._detector import (
14
14
  StandardDetector,
15
15
  TriggerInfo,
16
16
  )
17
- from ._device import Device, DeviceConnector, DeviceVector, init_devices
17
+ from ._device import (
18
+ Device,
19
+ DeviceConnector,
20
+ DeviceMock,
21
+ DeviceVector,
22
+ LazyMock,
23
+ default_mock_class,
24
+ init_devices,
25
+ )
18
26
  from ._device_filler import DeviceFiller
19
27
  from ._enums import (
20
28
  EnabledDisabled,
@@ -27,10 +35,20 @@ from ._flyer import FlyerController, FlyMotorInfo, StandardFlyer
27
35
  from ._hdf_dataset import HDFDatasetDescription, HDFDocumentComposer
28
36
  from ._log import config_ophyd_async_logging
29
37
  from ._mock_signal_backend import MockSignalBackend
38
+ from ._mock_signal_utils import (
39
+ callback_on_mock_put,
40
+ get_mock,
41
+ get_mock_put,
42
+ mock_puts_blocked,
43
+ set_mock_put_proceeds,
44
+ set_mock_value,
45
+ set_mock_values,
46
+ )
30
47
  from ._protocol import AsyncConfigurable, AsyncReadable, AsyncStageable, Watcher
31
48
  from ._providers import (
32
49
  AutoIncrementFilenameProvider,
33
50
  AutoIncrementingPathProvider,
51
+ AutoMaxIncrementingPathProvider,
34
52
  DatasetDescriber,
35
53
  FilenameProvider,
36
54
  PathInfo,
@@ -87,7 +105,6 @@ from ._utils import (
87
105
  Callback,
88
106
  ConfinedModel,
89
107
  EnumTypes,
90
- LazyMock,
91
108
  NotConnectedError,
92
109
  Reference,
93
110
  StrictEnum,
@@ -166,8 +183,18 @@ __all__ = [
166
183
  "soft_signal_r_and_setter",
167
184
  "soft_signal_rw",
168
185
  # Mock signal
186
+ "DeviceMock",
169
187
  "LazyMock",
170
188
  "MockSignalBackend",
189
+ "default_mock_class",
190
+ # Mocking utilities
191
+ "get_mock",
192
+ "set_mock_value",
193
+ "set_mock_values",
194
+ "get_mock_put",
195
+ "callback_on_mock_put",
196
+ "mock_puts_blocked",
197
+ "set_mock_put_proceeds",
171
198
  # Signal utilities
172
199
  "observe_value",
173
200
  "observe_signals_value",
@@ -196,6 +223,7 @@ __all__ = [
196
223
  "FilenameProvider",
197
224
  "StaticFilenameProvider",
198
225
  "AutoIncrementFilenameProvider",
226
+ "AutoMaxIncrementingPathProvider",
199
227
  "UUIDFilenameProvider",
200
228
  # Datatset
201
229
  "DatasetDescriber",
@@ -5,19 +5,71 @@ import sys
5
5
  from collections.abc import Awaitable, Callable, Iterator, Mapping, MutableMapping
6
6
  from functools import cached_property
7
7
  from logging import LoggerAdapter, getLogger
8
- from typing import Any, TypeVar
8
+ from typing import Any, Generic, TypeVar
9
+ from unittest.mock import Mock
9
10
 
10
11
  from bluesky.protocols import HasName
11
12
  from bluesky.run_engine import call_in_bluesky_event_loop, in_bluesky_event_loop
12
13
 
13
14
  from ._utils import (
14
15
  DEFAULT_TIMEOUT,
15
- LazyMock,
16
16
  NotConnectedError,
17
17
  error_if_none,
18
18
  wait_for_connection,
19
19
  )
20
20
 
21
+ DeviceT = TypeVar("DeviceT", bound="Device")
22
+
23
+
24
+ class DeviceMock(Generic[DeviceT]):
25
+ """A lazily created Mock to be used when connecting in mock mode.
26
+
27
+ Creating Mocks is reasonably expensive when each Device (and Signal)
28
+ requires its own, and the tree is only used when ``Signal.set()`` is
29
+ called. This class allows a tree of lazily connected Mocks to be
30
+ constructed so that when the leaf is created, so are its parents.
31
+ Any calls to the child are then accessible from the parent mock.
32
+
33
+ Subclasses can override the `connect()` method to inject custom logic
34
+ when mock devices are connected.
35
+
36
+ ```python
37
+ >>> parent = DeviceMock()
38
+ >>> child = DeviceMock("child", parent)
39
+ >>> child_mock = child()
40
+ >>> child_mock() # doctest: +ELLIPSIS
41
+ <Mock name='mock.child()' id='...'>
42
+ >>> parent_mock = parent()
43
+ >>> parent_mock.mock_calls
44
+ [call.child()]
45
+
46
+ ```
47
+ """
48
+
49
+ def __init__(self, name: str = "", parent: DeviceMock | None = None) -> None:
50
+ self.name = name
51
+ self.parent = parent
52
+ self._mock: Mock | None = None
53
+
54
+ def __call__(self) -> Mock:
55
+ if self._mock is None:
56
+ self._mock = Mock(spec=object)
57
+ if self.parent is not None:
58
+ self.parent().attach_mock(self._mock, self.name)
59
+ return self._mock
60
+
61
+ async def connect(self, device: DeviceT) -> None:
62
+ """Will be called when the device is connected in mock mode.
63
+
64
+ This allows mock values to be set and callbacks to be added
65
+ to the mock device so it behaves more like the real device.
66
+ """
67
+
68
+
69
+ # Keep LazyMock as an alias for backwards compatibility
70
+ # Remove for ophyd-async 1.0
71
+ LazyMock = DeviceMock
72
+
21
73
 
22
74
  class DeviceConnector:
23
75
  """Defines how a `Device` should be connected and type hints processed."""
@@ -40,7 +92,7 @@ class DeviceConnector:
40
92
  during `__init__`.
41
93
  """
42
94
 
43
- async def connect_mock(self, device: Device, mock: LazyMock):
95
+ async def connect_mock(self, device: Device, mock: DeviceMock):
44
96
  """Use during [](#Device.connect) with `mock=True`.
45
97
 
46
98
  This is called when there is no cached connect done in `mock=True`
@@ -50,12 +102,16 @@ class DeviceConnector:
50
102
  exceptions: dict[str, Exception] = {}
51
103
  for name, child_device in device.children():
52
104
  try:
53
- await child_device.connect(mock=mock.child(name))
105
+ child_mock_class = child_device._mock_class # noqa: SLF001
106
+ await child_device.connect(mock=child_mock_class(name, mock))
54
107
  except Exception as exc:
55
108
  exceptions[name] = exc
56
109
  if exceptions:
57
110
  raise NotConnectedError.with_other_exceptions_logged(exceptions)
58
111
 
112
+ # Call the DeviceMock's connect method to inject custom logic
113
+ await mock.connect(device)
114
+
59
115
  async def connect_real(self, device: Device, timeout: float, force_reconnect: bool):
60
116
  """Use during [](#Device.connect) with `mock=False`.
61
117
 
@@ -82,8 +138,10 @@ class Device(HasName):
82
138
  _name: str = ""
83
139
  # None if connect hasn't started, a Task if it has
84
140
  _connect_task: asyncio.Task | None = None
141
+ # The mock class to be used if we connect in mock mode
142
+ _mock_class: type[DeviceMock] = DeviceMock
85
143
  # The mock if we have connected in mock mode
86
- _mock: LazyMock | None = None
144
+ _mock: DeviceMock | None = None
87
145
  # The separator to use when making child names
88
146
  _child_name_separator: str = "-"
89
147
 
@@ -163,7 +221,7 @@ class Device(HasName):
163
221
 
164
222
  async def connect(
165
223
  self,
166
- mock: bool | LazyMock = False,
224
+ mock: bool | DeviceMock = False,
167
225
  timeout: float = DEFAULT_TIMEOUT,
168
226
  force_reconnect: bool = False,
169
227
  ) -> None:
@@ -175,25 +233,26 @@ class Device(HasName):
175
233
 
176
234
  :param mock:
177
235
  If True then use [](#MockSignalBackend) for all Signals. If passed a
178
- [](#LazyMock) then pass this down for use within the Signals,
179
- otherwise create one.
236
+ [](#DeviceMock) then pass this down for use within the Signals,
237
+ otherwise create one using the registered default mock for this device
238
+ type, or a plain [](#DeviceMock) if no default is registered.
180
239
  :param timeout: Time to wait before failing with a TimeoutError.
181
240
  :param force_reconnect:
182
241
  If True, force a reconnect even if the last connect succeeded.
183
242
  """
184
- connector = error_if_none(
243
+ connector: DeviceConnector = error_if_none(
185
244
  getattr(self, "_connector", None),
186
245
  f"{self}: doesn't have attribute `_connector`,"
187
246
  f" did you call `super().__init__` in your `__init__` method?",
188
247
  )
189
248
  if mock:
190
249
  # Always connect in mock mode serially
191
- if isinstance(mock, LazyMock):
192
- # Use the provided mock
250
+ if isinstance(mock, DeviceMock):
251
+ # Use the user supplied mock
193
252
  self._mock = mock
194
253
  elif not self._mock:
195
- # Make one
196
- self._mock = LazyMock()
254
+ # Make a new mock of the registered type
255
+ self._mock = self._mock_class()
197
256
  await connector.connect_mock(self, self._mock)
198
257
  else:
199
258
  # Try to cache the connect in real mode
@@ -223,9 +282,6 @@ _not_device_attrs = {
223
282
  }
224
283
 
225
284
 
226
- DeviceT = TypeVar("DeviceT", bound=Device)
227
-
228
-
229
285
  class DeviceVector(MutableMapping[int, DeviceT], Device):
230
286
  """Defines a dictionary of Device children with arbitrary integer keys.
231
287
 
@@ -396,3 +452,23 @@ def init_devices(
396
452
  await wait_for_connection(**coros)
397
453
 
398
454
  return DeviceProcessor(process_devices)
455
+
456
+
457
+ def default_mock_class(
458
+ mock_cls: type[DeviceMock],
459
+ ) -> Callable[[type[DeviceT]], type[DeviceT]]:
460
+ """Register a DeviceMock subclass as the default mock for a Device class.
461
+
462
+ This decorator allows automatic injection of mock logic when devices are
463
+ connected in mock mode. The decorated DeviceMock class should override
464
+ the `connect()` method to define custom mock behavior.
465
+
466
+ :param mock_cls: A DeviceMock subclass to register.
467
+ :returns: A decorator that registers the mock class for a Device subclass.
468
+ """
469
+
470
+ def wrapper(device_cls: type[DeviceT]) -> type[DeviceT]:
471
+ device_cls._mock_class = mock_cls # noqa: SLF001
472
+ return device_cls
473
+
474
+ return wrapper
@@ -1,6 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  from collections.abc import Callable
3
5
  from functools import cached_property
6
+ from typing import TYPE_CHECKING
4
7
  from unittest.mock import AsyncMock
5
8
 
6
9
  from bluesky.protocols import Reading
@@ -9,7 +12,10 @@ from event_model import DataKey
9
12
  from ._derived_signal_backend import DerivedSignalBackend
10
13
  from ._signal_backend import SignalBackend, SignalDatatypeT
11
14
  from ._soft_signal_backend import SoftSignalBackend
12
- from ._utils import Callback, LazyMock
15
+ from ._utils import Callback
16
+
17
+ if TYPE_CHECKING:
18
+ from ._device import LazyMock
13
19
 
14
20
 
15
21
  class MockSignalBackend(SignalBackend[SignalDatatypeT]):
@@ -2,15 +2,10 @@ from collections.abc import Awaitable, Callable, Iterable, Iterator
2
2
  from contextlib import contextmanager
3
3
  from unittest.mock import AsyncMock, Mock
4
4
 
5
- from ophyd_async.core import (
6
- Device,
7
- LazyMock,
8
- MockSignalBackend,
9
- Signal,
10
- SignalConnector,
11
- SignalDatatypeT,
12
- SignalR,
13
- )
5
+ from ._device import Device, DeviceMock
6
+ from ._mock_signal_backend import MockSignalBackend
7
+ from ._signal import Signal, SignalConnector, SignalR
8
+ from ._signal_backend import SignalDatatypeT
14
9
 
15
10
 
16
11
  def get_mock(device: Device | Signal) -> Mock:
@@ -19,16 +14,18 @@ def get_mock(device: Device | Signal) -> Mock:
19
14
  The device must have been connected in mock mode.
20
15
  """
21
16
  mock = device._mock # noqa: SLF001
22
- assert isinstance(mock, LazyMock), f"Device {device} not connected in mock mode"
17
+ if not isinstance(mock, DeviceMock):
18
+ msg = f"Device {device} not connected in mock mode"
19
+ raise RuntimeError(msg)
23
20
  return mock()
24
21
 
25
22
 
26
23
  def _get_mock_signal_backend(signal: Signal) -> MockSignalBackend:
27
24
  connector = signal._connector # noqa: SLF001
28
- assert isinstance(connector, SignalConnector), f"Expected Signal, got {signal}"
29
- assert isinstance(connector.backend, MockSignalBackend), (
30
- f"Signal {signal} not connected in mock mode"
31
- )
25
+ if not isinstance(connector, SignalConnector):
26
+ raise TypeError(f"Expected Signal, got {signal}")
27
+ if not isinstance(connector.backend, MockSignalBackend):
28
+ raise RuntimeError(f"Signal {signal} not connected in mock mode")
32
29
  return connector.backend
33
30
 
34
31