ophyd-async 0.3a4__tar.gz → 0.3a6__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 (209) hide show
  1. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.codecov.yml +1 -1
  2. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/_release.yml +1 -1
  3. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/PKG-INFO +1 -1
  4. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/design-goals.rst +1 -1
  5. ophyd_async-0.3a6/docs/explanations/flyscanning.rst +29 -0
  6. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/_version.py +1 -1
  7. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/__init__.py +6 -1
  8. ophyd_async-0.3a6/src/ophyd_async/core/async_status.py +142 -0
  9. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/detector.py +23 -29
  10. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/device.py +32 -11
  11. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/flyer.py +1 -1
  12. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/mock_signal_backend.py +14 -15
  13. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/mock_signal_utils.py +9 -13
  14. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/signal.py +71 -21
  15. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/utils.py +30 -0
  16. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/aravis.py +1 -5
  17. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/controllers/aravis_controller.py +6 -1
  18. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/drivers/ad_base.py +1 -7
  19. ophyd_async-0.3a6/src/ophyd_async/epics/areadetector/drivers/aravis_driver.py +38 -0
  20. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/writers/hdf_writer.py +3 -2
  21. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/writers/nd_file_hdf.py +0 -2
  22. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/writers/nd_plugin.py +9 -0
  23. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/demo/__init__.py +33 -34
  24. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/motion/motor.py +47 -42
  25. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/pvi/pvi.py +2 -2
  26. ophyd_async-0.3a6/src/ophyd_async/epics/signal/__init__.py +15 -0
  27. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/__init__.py +2 -0
  28. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/writers/_hdf_writer.py +4 -4
  29. ophyd_async-0.3a6/src/ophyd_async/plan_stubs/__init__.py +13 -0
  30. ophyd_async-0.3a6/src/ophyd_async/plan_stubs/ensure_connected.py +22 -0
  31. ophyd_async-0.3a6/src/ophyd_async/plan_stubs/fly.py +149 -0
  32. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/protocols.py +32 -2
  33. ophyd_async-0.3a6/src/ophyd_async/sim/demo/sim_motor.py +103 -0
  34. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async.egg-info/PKG-INFO +1 -1
  35. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async.egg-info/SOURCES.txt +5 -6
  36. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_async_status.py +44 -1
  37. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_device.py +104 -1
  38. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_device_collector.py +4 -1
  39. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_flyer.py +12 -12
  40. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_mock_signal_backend.py +16 -5
  41. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_signal.py +9 -0
  42. ophyd_async-0.3a6/tests/core/test_watchable_async_status.py +196 -0
  43. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_aravis.py +4 -52
  44. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/demo/test_demo.py +27 -16
  45. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/demo/test_demo_ad_sim_detector.py +28 -0
  46. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/motion/test_motor.py +81 -13
  47. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/test_hdf_panda.py +4 -8
  48. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/test_trigger.py +1 -2
  49. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/test_writer.py +2 -2
  50. ophyd_async-0.3a4/tests/test_flyer_with_panda.py → ophyd_async-0.3a6/tests/plan_stubs/test_fly.py +157 -13
  51. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/demo/test_sim_motor.py +4 -35
  52. ophyd_async-0.3a4/docs/explanations/flyscanning.rst +0 -63
  53. ophyd_async-0.3a4/docs/images/hardware-triggered-scan.png +0 -0
  54. ophyd_async-0.3a4/docs/images/outer-scan.png +0 -0
  55. ophyd_async-0.3a4/docs/images/simple-hardware-scan.png +0 -0
  56. ophyd_async-0.3a4/src/ophyd_async/core/async_status.py +0 -98
  57. ophyd_async-0.3a4/src/ophyd_async/epics/areadetector/drivers/aravis_driver.py +0 -156
  58. ophyd_async-0.3a4/src/ophyd_async/epics/signal/__init__.py +0 -8
  59. ophyd_async-0.3a4/src/ophyd_async/planstubs/__init__.py +0 -5
  60. ophyd_async-0.3a4/src/ophyd_async/planstubs/prepare_trigger_and_dets.py +0 -57
  61. ophyd_async-0.3a4/src/ophyd_async/sim/demo/sim_motor.py +0 -118
  62. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.copier-answers.yml +0 -0
  63. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.devcontainer/devcontainer.json +0 -0
  64. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.git-blame-ignore-revs +0 -0
  65. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/CONTRIBUTING.md +0 -0
  66. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/actions/install_requirements/action.yml +0 -0
  67. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/dependabot.yml +0 -0
  68. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/pages/index.html +0 -0
  69. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/pages/make_switcher.py +0 -0
  70. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/_check.yml +0 -0
  71. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/_dist.yml +0 -0
  72. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/_docs.yml +0 -0
  73. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/_pypi.yml +0 -0
  74. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/_test.yml +0 -0
  75. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/_tox.yml +0 -0
  76. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/ci.yml +0 -0
  77. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.github/workflows/periodic.yml +0 -0
  78. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.gitignore +0 -0
  79. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.mailmap +0 -0
  80. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/.pre-commit-config.yaml +0 -0
  81. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/Dockerfile +0 -0
  82. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/LICENSE +0 -0
  83. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/README.md +0 -0
  84. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/_templates/README +0 -0
  85. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/_templates/custom-class-template.rst +0 -0
  86. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/_templates/custom-module-template.rst +0 -0
  87. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/conf.py +0 -0
  88. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/examples/epics_demo.py +0 -0
  89. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/examples/foo_detector.py +0 -0
  90. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  91. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  92. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  93. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  94. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  95. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  96. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions/COPYME +0 -0
  97. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/decisions.md +0 -0
  98. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations/event-loop-choice.rst +0 -0
  99. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/explanations.md +0 -0
  100. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/genindex.rst +0 -0
  101. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/how-to/choose-interfaces-for-devices.md +0 -0
  102. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/how-to/compound-devices.rst +0 -0
  103. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/how-to/contribute.md +0 -0
  104. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/how-to/make-a-simple-device.rst +0 -0
  105. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/how-to/make-a-standard-detector.rst +0 -0
  106. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/how-to/write-tests-for-devices.rst +0 -0
  107. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/how-to.md +0 -0
  108. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/images/bluesky_ophyd_epics_devices_logo.svg +0 -0
  109. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/images/bluesky_ophyd_logo.svg +0 -0
  110. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/images/ophyd_favicon.svg +0 -0
  111. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/index.md +0 -0
  112. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/reference/api.rst +0 -0
  113. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/reference.md +0 -0
  114. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/tutorials/installation.md +0 -0
  115. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/tutorials/using-existing-devices.rst +0 -0
  116. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/docs/tutorials.md +0 -0
  117. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/pyproject.toml +0 -0
  118. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/setup.cfg +0 -0
  119. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/__init__.py +0 -0
  120. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/__main__.py +0 -0
  121. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/_providers.py +0 -0
  122. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/device_save_loader.py +0 -0
  123. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/signal_backend.py +0 -0
  124. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/soft_signal_backend.py +0 -0
  125. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/core/standard_readable.py +0 -0
  126. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/__init__.py +0 -0
  127. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/_backend/__init__.py +0 -0
  128. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/_backend/_aioca.py +0 -0
  129. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/_backend/_p4p.py +0 -0
  130. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/_backend/common.py +0 -0
  131. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/__init__.py +0 -0
  132. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/controllers/__init__.py +0 -0
  133. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/controllers/ad_sim_controller.py +0 -0
  134. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/controllers/kinetix_controller.py +0 -0
  135. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/controllers/pilatus_controller.py +0 -0
  136. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/controllers/vimba_controller.py +0 -0
  137. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/drivers/__init__.py +0 -0
  138. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/drivers/kinetix_driver.py +0 -0
  139. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/drivers/pilatus_driver.py +0 -0
  140. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/drivers/vimba_driver.py +0 -0
  141. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/kinetix.py +0 -0
  142. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/pilatus.py +0 -0
  143. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/single_trigger_det.py +0 -0
  144. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/utils.py +0 -0
  145. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/vimba.py +0 -0
  146. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/writers/__init__.py +0 -0
  147. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/writers/_hdfdataset.py +0 -0
  148. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/areadetector/writers/_hdffile.py +0 -0
  149. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/demo/demo_ad_sim_detector.py +0 -0
  150. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/demo/mover.db +0 -0
  151. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/demo/sensor.db +0 -0
  152. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/motion/__init__.py +0 -0
  153. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/pvi/__init__.py +0 -0
  154. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/signal/_epics_transport.py +0 -0
  155. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/epics/signal/signal.py +0 -0
  156. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/log.py +0 -0
  157. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/_common_blocks.py +0 -0
  158. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/_hdf_panda.py +0 -0
  159. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/_panda_controller.py +0 -0
  160. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/_table.py +0 -0
  161. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/_trigger.py +0 -0
  162. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/_utils.py +0 -0
  163. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/writers/__init__.py +0 -0
  164. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/panda/writers/_panda_hdf_file.py +0 -0
  165. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/sim/__init__.py +0 -0
  166. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/sim/demo/__init__.py +0 -0
  167. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/sim/pattern_generator.py +0 -0
  168. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/sim/sim_pattern_detector_control.py +0 -0
  169. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/sim/sim_pattern_detector_writer.py +0 -0
  170. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async/sim/sim_pattern_generator.py +0 -0
  171. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  172. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async.egg-info/entry_points.txt +0 -0
  173. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async.egg-info/requires.txt +0 -0
  174. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/src/ophyd_async.egg-info/top_level.txt +0 -0
  175. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/conftest.py +0 -0
  176. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_device_save_loader.py +0 -0
  177. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_soft_signal_backend.py +0 -0
  178. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_standard_readable.py +0 -0
  179. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/core/test_utils.py +0 -0
  180. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/_backend/test_common.py +0 -0
  181. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/__init__.py +0 -0
  182. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_controllers.py +0 -0
  183. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_drivers.py +0 -0
  184. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_kinetix.py +0 -0
  185. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_pilatus.py +0 -0
  186. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_scans.py +0 -0
  187. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_single_trigger_det.py +0 -0
  188. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_utils.py +0 -0
  189. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_vimba.py +0 -0
  190. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/areadetector/test_writers.py +0 -0
  191. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/motion/__init__.py +0 -0
  192. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/test_pvi.py +0 -0
  193. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/test_records.db +0 -0
  194. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/epics/test_signals.py +0 -0
  195. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/db/panda.db +0 -0
  196. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/test_panda_connect.py +0 -0
  197. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/test_panda_controller.py +0 -0
  198. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/test_panda_utils.py +0 -0
  199. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/panda/test_table.py +0 -0
  200. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/protocols/test_protocols.py +0 -0
  201. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/__init__.py +0 -0
  202. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/conftest.py +0 -0
  203. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/demo/__init__.py +0 -0
  204. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/test_pattern_generator.py +0 -0
  205. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/test_sim_detector.py +0 -0
  206. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/test_sim_writer.py +0 -0
  207. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/sim/test_streaming_plan.py +0 -0
  208. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/test_cli.py +0 -0
  209. {ophyd_async-0.3a4 → ophyd_async-0.3a6}/tests/test_log.py +0 -0
@@ -8,7 +8,7 @@ coverage:
8
8
  threshold: 1%
9
9
  patch:
10
10
  default:
11
- target: auto
11
+ target: 90
12
12
  threshold: 1%
13
13
  github_checks:
14
14
  annotations: false
@@ -23,7 +23,7 @@ jobs:
23
23
  - name: Create GitHub Release
24
24
  # We pin to the SHA, not the tag, for security reasons.
25
25
  # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
26
- uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2.0.4
26
+ uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5
27
27
  with:
28
28
  prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
29
29
  files: "*"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ophyd-async
3
- Version: 0.3a4
3
+ Version: 0.3a6
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
@@ -32,7 +32,7 @@ Parity with Malcolm
32
32
 
33
33
  Ophyd-async should provide the same building blocks for defining flyscans scans as malcolm_. It should support PandA and Zebra as timing masters by default, but also provide easy helpers for developers to write support for their own devices.
34
34
 
35
- It should enable `motor trajectory scanning <motortraj_>` and `multiple triggering rates<detectorsync_>` based around a base rate, and pausing/resuming scans. Scans should be modelled using scanspec_, which serves as a universal language for defining trajectory and time-resolved scans, and converted to the underlying format of the given motion controller. It should also be possible to define an `outer scan <outerscan_>`.
35
+ It should enable motor trajectory scanning and multiple triggering rates based around a base rate, and pausing/resuming scans. Scans should be modelled using scanspec_, which serves as a universal language for defining trajectory and time-resolved scans, and converted to the underlying format of the given motion controller. It should also be possible to define an outer scan .
36
36
 
37
37
 
38
38
  Improved Trajectory Calculation
@@ -0,0 +1,29 @@
1
+ Flyscanning
2
+ ===========
3
+
4
+ See the documents in the [bluesky cookbook](http://blueskyproject.io/bluesky-cookbook/glossary/flyscanning.html)
5
+
6
+ Hardware
7
+ --------
8
+
9
+ Ophyd-async ships with support for Quantum Detectors' PandA_ and Zebra_ as triggering mechanisms.
10
+
11
+ These are very modular and can be used to trigger a variety of detectors and handle readback signals from a variety of sample control devices. See full specs for more information.
12
+
13
+ It is possible to write support for additional systems/devices.
14
+
15
+
16
+ Role of Ophyd-Async
17
+ -------------------
18
+
19
+ Bluesky supports devices that configure acquisition and then hand over control to an external system via the ``Flyer`` protocol.
20
+
21
+ Ophyd-async's job is to provide devices that implement ``Flyer`` and can:
22
+
23
+ - Configure all necessary hardware for a scan
24
+ - Kickoff a scan and monitor progress until complete
25
+ - Produce documents representing the progress of the scan
26
+ - Allow handing control back and forth to enable outer scanning
27
+
28
+ .. _PandA: https://quantumdetectors.com/products/pandabox/
29
+ .. _Zebra: https://quantumdetectors.com/products/zebra/
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.3a4'
15
+ __version__ = version = '0.3a6'
16
16
  __version_tuple__ = version_tuple = (0, 3)
@@ -5,7 +5,7 @@ from ._providers import (
5
5
  ShapeProvider,
6
6
  StaticDirectoryProvider,
7
7
  )
8
- from .async_status import AsyncStatus
8
+ from .async_status import AsyncStatus, WatchableAsyncStatus
9
9
  from .detector import (
10
10
  DetectorControl,
11
11
  DetectorTrigger,
@@ -57,6 +57,8 @@ from .soft_signal_backend import SoftSignalBackend
57
57
  from .standard_readable import ConfigSignal, HintedSignal, StandardReadable
58
58
  from .utils import (
59
59
  DEFAULT_TIMEOUT,
60
+ CalculatableTimeout,
61
+ CalculateTimeout,
60
62
  Callback,
61
63
  NotConnected,
62
64
  ReadingValueCallback,
@@ -96,6 +98,7 @@ __all__ = [
96
98
  "set_mock_value",
97
99
  "wait_for_value",
98
100
  "AsyncStatus",
101
+ "WatchableAsyncStatus",
99
102
  "DirectoryInfo",
100
103
  "DirectoryProvider",
101
104
  "NameProvider",
@@ -107,6 +110,8 @@ __all__ = [
107
110
  "TriggerInfo",
108
111
  "TriggerLogic",
109
112
  "HardwareTriggeredFlyable",
113
+ "CalculateTimeout",
114
+ "CalculatableTimeout",
110
115
  "DEFAULT_TIMEOUT",
111
116
  "Callback",
112
117
  "NotConnected",
@@ -0,0 +1,142 @@
1
+ """Equivalent of bluesky.protocols.Status for asynchronous tasks."""
2
+
3
+ import asyncio
4
+ import functools
5
+ import time
6
+ from dataclasses import asdict, replace
7
+ from typing import (
8
+ AsyncIterator,
9
+ Awaitable,
10
+ Callable,
11
+ Generic,
12
+ Type,
13
+ TypeVar,
14
+ cast,
15
+ )
16
+
17
+ from bluesky.protocols import Status
18
+
19
+ from ..protocols import Watcher
20
+ from .utils import Callback, P, T, WatcherUpdate
21
+
22
+ AS = TypeVar("AS", bound="AsyncStatus")
23
+ WAS = TypeVar("WAS", bound="WatchableAsyncStatus")
24
+
25
+
26
+ class AsyncStatusBase(Status):
27
+ """Convert asyncio awaitable to bluesky Status interface"""
28
+
29
+ def __init__(self, awaitable: Awaitable):
30
+ if isinstance(awaitable, asyncio.Task):
31
+ self.task = awaitable
32
+ else:
33
+ self.task = asyncio.create_task(awaitable)
34
+ self.task.add_done_callback(self._run_callbacks)
35
+ self._callbacks: list[Callback[Status]] = []
36
+
37
+ def __await__(self):
38
+ return self.task.__await__()
39
+
40
+ def add_callback(self, callback: Callback[Status]):
41
+ if self.done:
42
+ callback(self)
43
+ else:
44
+ self._callbacks.append(callback)
45
+
46
+ def _run_callbacks(self, task: asyncio.Task):
47
+ for callback in self._callbacks:
48
+ callback(self)
49
+
50
+ def exception(self, timeout: float | None = 0.0) -> BaseException | None:
51
+ if timeout != 0.0:
52
+ raise ValueError(
53
+ "cannot honour any timeout other than 0 in an asynchronous function"
54
+ )
55
+ if self.task.done():
56
+ try:
57
+ return self.task.exception()
58
+ except asyncio.CancelledError as e:
59
+ return e
60
+ return None
61
+
62
+ @property
63
+ def done(self) -> bool:
64
+ return self.task.done()
65
+
66
+ @property
67
+ def success(self) -> bool:
68
+ return (
69
+ self.task.done()
70
+ and not self.task.cancelled()
71
+ and self.task.exception() is None
72
+ )
73
+
74
+ def __repr__(self) -> str:
75
+ if self.done:
76
+ if e := self.exception():
77
+ status = f"errored: {repr(e)}"
78
+ else:
79
+ status = "done"
80
+ else:
81
+ status = "pending"
82
+ return f"<{type(self).__name__}, task: {self.task.get_coro()}, {status}>"
83
+
84
+ __str__ = __repr__
85
+
86
+
87
+ class AsyncStatus(AsyncStatusBase):
88
+ @classmethod
89
+ def wrap(cls: Type[AS], f: Callable[P, Awaitable]) -> Callable[P, AS]:
90
+ """Wrap an async function in an AsyncStatus."""
91
+
92
+ @functools.wraps(f)
93
+ def wrap_f(*args: P.args, **kwargs: P.kwargs) -> AS:
94
+ return cls(f(*args, **kwargs))
95
+
96
+ # type is actually functools._Wrapped[P, Awaitable, P, AS]
97
+ # but functools._Wrapped is not necessarily available
98
+ return cast(Callable[P, AS], wrap_f)
99
+
100
+
101
+ class WatchableAsyncStatus(AsyncStatusBase, Generic[T]):
102
+ """Convert AsyncIterator of WatcherUpdates to bluesky Status interface."""
103
+
104
+ def __init__(self, iterator: AsyncIterator[WatcherUpdate[T]]):
105
+ self._watchers: list[Watcher] = []
106
+ self._start = time.monotonic()
107
+ self._last_update: WatcherUpdate[T] | None = None
108
+ super().__init__(self._notify_watchers_from(iterator))
109
+
110
+ async def _notify_watchers_from(self, iterator: AsyncIterator[WatcherUpdate[T]]):
111
+ async for update in iterator:
112
+ self._last_update = (
113
+ update
114
+ if update.time_elapsed is not None
115
+ else replace(update, time_elapsed=time.monotonic() - self._start)
116
+ )
117
+ for watcher in self._watchers:
118
+ self._update_watcher(watcher, self._last_update)
119
+
120
+ def _update_watcher(self, watcher: Watcher, update: WatcherUpdate[T]):
121
+ vals = asdict(
122
+ update, dict_factory=lambda d: {k: v for k, v in d if v is not None}
123
+ )
124
+ watcher(**vals)
125
+
126
+ def watch(self, watcher: Watcher):
127
+ self._watchers.append(watcher)
128
+ if self._last_update:
129
+ self._update_watcher(watcher, self._last_update)
130
+
131
+ @classmethod
132
+ def wrap(
133
+ cls: Type[WAS],
134
+ f: Callable[P, AsyncIterator[WatcherUpdate[T]]],
135
+ ) -> Callable[P, WAS]:
136
+ """Wrap an AsyncIterator in a WatchableAsyncStatus."""
137
+
138
+ @functools.wraps(f)
139
+ def wrap_f(*args: P.args, **kwargs: P.kwargs) -> WAS:
140
+ return cls(f(*args, **kwargs))
141
+
142
+ return cast(Callable[P, WAS], wrap_f)
@@ -31,9 +31,9 @@ from bluesky.protocols import (
31
31
 
32
32
  from ophyd_async.protocols import AsyncConfigurable, AsyncReadable
33
33
 
34
- from .async_status import AsyncStatus
34
+ from .async_status import AsyncStatus, WatchableAsyncStatus
35
35
  from .device import Device
36
- from .utils import DEFAULT_TIMEOUT, merge_gathered_dicts
36
+ from .utils import DEFAULT_TIMEOUT, WatcherUpdate, merge_gathered_dicts
37
37
 
38
38
  T = TypeVar("T")
39
39
 
@@ -188,7 +188,7 @@ class StandardDetector(
188
188
  self._trigger_info: Optional[TriggerInfo] = None
189
189
  # For kickoff
190
190
  self._watchers: List[Callable] = []
191
- self._fly_status: Optional[AsyncStatus] = None
191
+ self._fly_status: Optional[WatchableAsyncStatus] = None
192
192
  self._fly_start: float
193
193
 
194
194
  self._intial_frame: int
@@ -292,43 +292,37 @@ class StandardDetector(
292
292
  f"Detector {self.controller} needs at least {required}s deadtime, "
293
293
  f"but trigger logic provides only {self._trigger_info.deadtime}s"
294
294
  )
295
-
296
295
  self._arm_status = await self.controller.arm(
297
296
  num=self._trigger_info.num,
298
297
  trigger=self._trigger_info.trigger,
299
298
  exposure=self._trigger_info.livetime,
300
299
  )
301
-
302
- @AsyncStatus.wrap
303
- async def kickoff(self) -> None:
304
- self._fly_status = AsyncStatus(self._fly(), self._watchers)
305
300
  self._fly_start = time.monotonic()
306
301
 
307
- async def _fly(self) -> None:
308
- await self._observe_writer_indicies(self._last_frame)
309
-
310
- async def _observe_writer_indicies(self, end_observation: int):
302
+ @AsyncStatus.wrap
303
+ async def kickoff(self):
304
+ if not self._arm_status:
305
+ raise Exception("Detector not armed!")
306
+
307
+ @WatchableAsyncStatus.wrap
308
+ async def complete(self):
309
+ assert self._arm_status, "Prepare not run"
310
+ assert self._trigger_info
311
311
  async for index in self.writer.observe_indices_written(
312
312
  self._frame_writing_timeout
313
313
  ):
314
- for watcher in self._watchers:
315
- watcher(
316
- name=self.name,
317
- current=index,
318
- initial=self._initial_frame,
319
- target=end_observation,
320
- unit="",
321
- precision=0,
322
- time_elapsed=time.monotonic() - self._fly_start,
323
- )
324
- if index >= end_observation:
314
+ yield WatcherUpdate(
315
+ name=self.name,
316
+ current=index,
317
+ initial=self._initial_frame,
318
+ target=self._trigger_info.num,
319
+ unit="",
320
+ precision=0,
321
+ time_elapsed=time.monotonic() - self._fly_start,
322
+ )
323
+ if index >= self._trigger_info.num:
325
324
  break
326
325
 
327
- @AsyncStatus.wrap
328
- async def complete(self) -> AsyncStatus:
329
- assert self._fly_status, "Kickoff not run"
330
- return await self._fly_status
331
-
332
326
  async def describe_collect(self) -> Dict[str, DataKey]:
333
327
  return self._describe
334
328
 
@@ -338,7 +332,7 @@ class StandardDetector(
338
332
  # Collect stream datum documents for all indices written.
339
333
  # The index is optional, and provided for fly scans, however this needs to be
340
334
  # retrieved for step scans.
341
- if not index:
335
+ if index is None:
342
336
  index = await self.writer.get_indices_written()
343
337
  async for doc in self.writer.collect_stream_docs(index):
344
338
  yield doc
@@ -1,7 +1,6 @@
1
1
  """Base device"""
2
2
 
3
- from __future__ import annotations
4
-
3
+ import asyncio
5
4
  import sys
6
5
  from functools import cached_property
7
6
  from logging import LoggerAdapter, getLogger
@@ -31,7 +30,10 @@ class Device(HasName):
31
30
 
32
31
  _name: str = ""
33
32
  #: The parent Device if it exists
34
- parent: Optional[Device] = None
33
+ parent: Optional["Device"] = None
34
+ # None if connect hasn't started, a Task if it has
35
+ _connect_task: Optional[asyncio.Task] = None
36
+ _connect_mock_arg: bool = False
35
37
 
36
38
  def __init__(self, name: str = "") -> None:
37
39
  self.set_name(name)
@@ -47,7 +49,7 @@ class Device(HasName):
47
49
  getLogger("ophyd_async.devices"), {"ophyd_async_device_name": self.name}
48
50
  )
49
51
 
50
- def children(self) -> Iterator[Tuple[str, Device]]:
52
+ def children(self) -> Iterator[Tuple[str, "Device"]]:
51
53
  for attr_name, attr in self.__dict__.items():
52
54
  if attr_name != "parent" and isinstance(attr, Device):
53
55
  yield attr_name, attr
@@ -71,7 +73,12 @@ class Device(HasName):
71
73
  child.set_name(child_name)
72
74
  child.parent = self
73
75
 
74
- async def connect(self, mock: bool = False, timeout: float = DEFAULT_TIMEOUT):
76
+ async def connect(
77
+ self,
78
+ mock: bool = False,
79
+ timeout: float = DEFAULT_TIMEOUT,
80
+ force_reconnect: bool = False,
81
+ ):
75
82
  """Connect self and all child Devices.
76
83
 
77
84
  Contains a timeout that gets propagated to child.connect methods.
@@ -83,12 +90,26 @@ class Device(HasName):
83
90
  timeout:
84
91
  Time to wait before failing with a TimeoutError.
85
92
  """
86
- coros = {
87
- name: child_device.connect(mock=mock, timeout=timeout)
88
- for name, child_device in self.children()
89
- }
90
- if coros:
91
- await wait_for_connection(**coros)
93
+ # If previous connect with same args has started and not errored, can use it
94
+ can_use_previous_connect = (
95
+ self._connect_task
96
+ and not (self._connect_task.done() and self._connect_task.exception())
97
+ and self._connect_mock_arg == mock
98
+ )
99
+ if force_reconnect or not can_use_previous_connect:
100
+ # Kick off a connection
101
+ coros = {
102
+ name: child_device.connect(
103
+ mock, timeout=timeout, force_reconnect=force_reconnect
104
+ )
105
+ for name, child_device in self.children()
106
+ }
107
+ self._connect_task = asyncio.create_task(wait_for_connection(**coros))
108
+ self._connect_mock_arg = mock
109
+
110
+ assert self._connect_task, "Connect task not created, this shouldn't happen"
111
+ # Wait for it to complete
112
+ await self._connect_task
92
113
 
93
114
 
94
115
  VT = TypeVar("VT", bound=Device)
@@ -39,7 +39,7 @@ class HardwareTriggeredFlyable(
39
39
  def __init__(
40
40
  self,
41
41
  trigger_logic: TriggerLogic[T],
42
- configuration_signals: Sequence[SignalR],
42
+ configuration_signals: Sequence[SignalR] = (),
43
43
  name: str = "",
44
44
  ):
45
45
  self._trigger_logic = trigger_logic
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
+ from functools import cached_property
2
3
  from typing import Optional, Type
3
- from unittest.mock import MagicMock
4
+ from unittest.mock import Mock
4
5
 
5
6
  from bluesky.protocols import Descriptor, Reading
6
7
 
@@ -36,51 +37,49 @@ class MockSignalBackend(SignalBackend):
36
37
  else:
37
38
  self.soft_backend = initial_backend
38
39
 
39
- self.mock = MagicMock()
40
-
41
- self.put_proceeds = asyncio.Event()
42
- self.put_proceeds.set()
43
-
44
40
  def source(self, name: str) -> str:
45
- self.mock.source(name)
46
41
  if self.initial_backend:
47
42
  return f"mock+{self.initial_backend.source(name)}"
48
43
  return f"mock+{name}"
49
44
 
50
45
  async def connect(self, timeout: float = DEFAULT_TIMEOUT) -> None:
51
- self.mock.connect(timeout=timeout)
46
+ pass
47
+
48
+ @cached_property
49
+ def put_mock(self) -> Mock:
50
+ return Mock(name="put")
51
+
52
+ @cached_property
53
+ def put_proceeds(self) -> asyncio.Event:
54
+ put_proceeds = asyncio.Event()
55
+ put_proceeds.set()
56
+ return put_proceeds
52
57
 
53
58
  async def put(self, value: Optional[T], wait=True, timeout=None):
54
- self.mock.put(value, wait=wait, timeout=timeout)
59
+ self.put_mock(value, wait=wait, timeout=timeout)
55
60
  await self.soft_backend.put(value, wait=wait, timeout=timeout)
56
61
 
57
62
  if wait:
58
63
  await asyncio.wait_for(self.put_proceeds.wait(), timeout=timeout)
59
64
 
60
65
  def set_value(self, value: T):
61
- self.mock.set_value(value)
62
66
  self.soft_backend.set_value(value)
63
67
 
64
68
  async def get_descriptor(self, source: str) -> Descriptor:
65
- self.mock.get_descriptor(source)
66
69
  return await self.soft_backend.get_descriptor(source)
67
70
 
68
71
  async def get_reading(self) -> Reading:
69
- self.mock.get_reading()
70
72
  return await self.soft_backend.get_reading()
71
73
 
72
74
  async def get_value(self) -> T:
73
- self.mock.get_value()
74
75
  return await self.soft_backend.get_value()
75
76
 
76
77
  async def get_setpoint(self) -> T:
77
78
  """For a soft signal, the setpoint and readback values are the same."""
78
- self.mock.get_setpoint()
79
79
  return await self.soft_backend.get_setpoint()
80
80
 
81
81
  async def get_datakey(self, source: str) -> Descriptor:
82
82
  return await self.soft_backend.get_datakey(source)
83
83
 
84
84
  def set_callback(self, callback: Optional[ReadingValueCallback[T]]) -> None:
85
- self.mock.set_callback(callback)
86
85
  self.soft_backend.set_callback(callback)
@@ -1,6 +1,6 @@
1
1
  from contextlib import asynccontextmanager, contextmanager
2
- from typing import Any, Callable, Generator, Iterable, Iterator, List
3
- from unittest.mock import ANY
2
+ from typing import Any, Callable, Iterable, Iterator, List
3
+ from unittest.mock import ANY, Mock
4
4
 
5
5
  from ophyd_async.core.signal import Signal
6
6
  from ophyd_async.core.utils import T
@@ -43,12 +43,12 @@ async def mock_puts_blocked(*signals: List[Signal]):
43
43
 
44
44
  def assert_mock_put_called_with(signal: Signal, value: Any, wait=ANY, timeout=ANY):
45
45
  backend = _get_mock_signal_backend(signal)
46
- backend.mock.put.assert_called_with(value, wait=wait, timeout=timeout)
46
+ backend.put_mock.assert_called_with(value, wait=wait, timeout=timeout)
47
47
 
48
48
 
49
49
  def reset_mock_put_calls(signal: Signal):
50
50
  backend = _get_mock_signal_backend(signal)
51
- backend.mock.put.reset_mock()
51
+ backend.put_mock.reset_mock()
52
52
 
53
53
 
54
54
  class _SetValuesIterator:
@@ -122,16 +122,12 @@ def set_mock_values(
122
122
 
123
123
 
124
124
  @contextmanager
125
- def _unset_side_effect_cm(mock):
125
+ def _unset_side_effect_cm(put_mock: Mock):
126
126
  yield
127
- mock.put.side_effect = None
127
+ put_mock.side_effect = None
128
128
 
129
129
 
130
- # linting isn't smart enought to realize @contextmanager will give use a
131
- # ContextManager[None]
132
- def callback_on_mock_put(
133
- signal: Signal, callback: Callable[[T], None]
134
- ) -> Generator[None, None, None]:
130
+ def callback_on_mock_put(signal: Signal, callback: Callable[[T], None]):
135
131
  """For setting a callback when a backend is put to.
136
132
 
137
133
  Can either be used in a context, with the callback being
@@ -145,5 +141,5 @@ def callback_on_mock_put(
145
141
  The callback to call when the backend is put to during the context.
146
142
  """
147
143
  backend = _get_mock_signal_backend(signal)
148
- backend.mock.put.side_effect = callback
149
- return _unset_side_effect_cm(backend.mock)
144
+ backend.put_mock.side_effect = callback
145
+ return _unset_side_effect_cm(backend.put_mock)