ophyd-async 0.8.0a5__tar.gz → 0.9.0a1__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 (255) hide show
  1. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.copier-answers.yml +1 -1
  2. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.devcontainer/devcontainer.json +4 -4
  3. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/CONTRIBUTING.md +1 -1
  4. ophyd_async-0.9.0a1/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +10 -0
  5. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/_test.yml +1 -0
  6. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/ci.yml +1 -1
  7. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.pre-commit-config.yaml +8 -0
  8. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/PKG-INFO +3 -1
  9. ophyd_async-0.9.0a1/docs/how-to/use_set_and_wait_for_other_value.md +45 -0
  10. ophyd_async-0.9.0a1/docs/images/set_and_wait_for_other_value.svg +10 -0
  11. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/pyproject.toml +52 -0
  12. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/_version.py +2 -2
  13. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/__init__.py +4 -26
  14. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_detector.py +9 -9
  15. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_device.py +27 -8
  16. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_protocol.py +0 -28
  17. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_signal.py +111 -136
  18. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_table.py +9 -4
  19. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_utils.py +11 -2
  20. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adaravis/_aravis_controller.py +8 -8
  21. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adaravis/_aravis_io.py +4 -4
  22. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adcore/_core_io.py +21 -21
  23. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adcore/_core_logic.py +6 -3
  24. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adcore/_hdf_writer.py +6 -3
  25. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adcore/_single_trigger.py +1 -1
  26. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adcore/_utils.py +35 -35
  27. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +7 -7
  28. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +7 -7
  29. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adpilatus/_pilatus.py +3 -3
  30. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +4 -4
  31. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +5 -5
  32. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +2 -2
  33. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/advimba/_vimba_controller.py +14 -14
  34. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/advimba/_vimba_io.py +23 -23
  35. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/_p4p.py +19 -0
  36. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/_pvi_connector.py +4 -2
  37. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/_signal.py +9 -2
  38. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/_util.py +9 -0
  39. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/demo/_mover.py +2 -2
  40. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/demo/_sensor.py +2 -2
  41. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/eiger/_eiger_controller.py +10 -5
  42. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/eiger/_eiger_io.py +3 -3
  43. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/motor.py +8 -5
  44. ophyd_async-0.9.0a1/src/ophyd_async/epics/testing/__init__.py +24 -0
  45. ophyd_async-0.9.0a1/src/ophyd_async/epics/testing/_example_ioc.py +107 -0
  46. ophyd_async-0.9.0a1/src/ophyd_async/epics/testing/_utils.py +78 -0
  47. ophyd_async-0.9.0a1/src/ophyd_async/epics/testing/test_records.db +158 -0
  48. ophyd_async-0.9.0a1/src/ophyd_async/epics/testing/test_records_pva.db +177 -0
  49. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/core.py +2 -2
  50. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/_block.py +9 -9
  51. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/_control.py +2 -2
  52. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/_hdf_panda.py +4 -1
  53. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/_trigger.py +7 -7
  54. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/plan_stubs/_fly.py +1 -1
  55. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/demo/_sim_motor.py +34 -32
  56. {ophyd_async-0.8.0a5/src/ophyd_async/tango/signal → ophyd_async-0.9.0a1/src/ophyd_async/tango/core}/__init__.py +7 -2
  57. {ophyd_async-0.8.0a5/src/ophyd_async/tango/base_devices → ophyd_async-0.9.0a1/src/ophyd_async/tango/core}/_base_device.py +38 -64
  58. {ophyd_async-0.8.0a5/src/ophyd_async/tango/signal → ophyd_async-0.9.0a1/src/ophyd_async/tango/core}/_signal.py +13 -3
  59. {ophyd_async-0.8.0a5/src/ophyd_async/tango/base_devices → ophyd_async-0.9.0a1/src/ophyd_async/tango/core}/_tango_readable.py +3 -4
  60. {ophyd_async-0.8.0a5/src/ophyd_async/tango/signal → ophyd_async-0.9.0a1/src/ophyd_async/tango/core}/_tango_transport.py +1 -1
  61. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/tango/demo/_counter.py +6 -7
  62. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/tango/demo/_mover.py +8 -7
  63. ophyd_async-0.9.0a1/src/ophyd_async/testing/__init__.py +33 -0
  64. ophyd_async-0.9.0a1/src/ophyd_async/testing/_assert.py +128 -0
  65. {ophyd_async-0.8.0a5/src/ophyd_async/core → ophyd_async-0.9.0a1/src/ophyd_async/testing}/_mock_signal_utils.py +12 -8
  66. ophyd_async-0.9.0a1/src/ophyd_async/testing/_wait_for_pending.py +22 -0
  67. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async.egg-info/PKG-INFO +3 -1
  68. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async.egg-info/SOURCES.txt +16 -9
  69. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async.egg-info/requires.txt +1 -0
  70. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/system_tests/epics/eiger/test_eiger_system.py +1 -1
  71. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/conftest.py +26 -10
  72. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_device.py +16 -2
  73. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_device_collector.py +1 -1
  74. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_device_save_loader.py +32 -59
  75. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_flyer.py +23 -28
  76. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_mock_signal_backend.py +8 -5
  77. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_observe.py +54 -8
  78. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_readable.py +8 -8
  79. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_signal.py +61 -18
  80. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_soft_signal_backend.py +7 -7
  81. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_subset_enum.py +6 -6
  82. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_table.py +5 -1
  83. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adaravis/test_aravis.py +3 -3
  84. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adcore/test_drivers.py +12 -11
  85. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adcore/test_scans.py +2 -2
  86. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adcore/test_single_trigger.py +2 -2
  87. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adcore/test_writers.py +1 -1
  88. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adkinetix/test_kinetix.py +6 -6
  89. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adpilatus/test_pilatus.py +13 -13
  90. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/adsimdetector/test_sim.py +8 -8
  91. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/advimba/test_vimba.py +8 -8
  92. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/conftest.py +1 -2
  93. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/demo/test_demo.py +11 -14
  94. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/eiger/test_eiger_controller.py +1 -3
  95. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/eiger/test_eiger_detector.py +3 -2
  96. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/eiger/test_odin_io.py +2 -1
  97. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/signal/test_signals.py +357 -299
  98. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/test_motor.py +19 -21
  99. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/test_hdf_panda.py +4 -11
  100. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/test_panda_connect.py +4 -2
  101. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/test_panda_control.py +3 -3
  102. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/test_trigger.py +4 -3
  103. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/test_writer.py +1 -2
  104. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/plan_stubs/test_fly.py +1 -1
  105. ophyd_async-0.9.0a1/tests/sim/demo/__init__.py +0 -0
  106. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/sim/demo/test_sim_motor.py +41 -2
  107. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/sim/test_sim_detector.py +3 -5
  108. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/sim/test_streaming_plan.py +3 -2
  109. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/tango/test_base_device.py +1 -1
  110. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/tango/test_tango_signals.py +215 -356
  111. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/tango/test_tango_transport.py +1 -3
  112. ophyd_async-0.9.0a1/tests/test_data/test_yaml_save.yml +42 -0
  113. ophyd_async-0.8.0a5/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -8
  114. ophyd_async-0.8.0a5/.mailmap +0 -18
  115. ophyd_async-0.8.0a5/src/ophyd_async/tango/__init__.py +0 -43
  116. ophyd_async-0.8.0a5/src/ophyd_async/tango/base_devices/__init__.py +0 -4
  117. ophyd_async-0.8.0a5/tests/epics/signal/test_records.db +0 -330
  118. ophyd_async-0.8.0a5/tests/test_data/test_yaml_save.yml +0 -46
  119. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.codecov.yml +0 -0
  120. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.git-blame-ignore-revs +0 -0
  121. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  122. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  123. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/actions/install_requirements/action.yml +0 -0
  124. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/dependabot.yml +0 -0
  125. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/pages/index.html +0 -0
  126. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/pages/make_switcher.py +0 -0
  127. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/_check.yml +0 -0
  128. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/_dist.yml +0 -0
  129. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/_docs.yml +0 -0
  130. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/_pypi.yml +0 -0
  131. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/_release.yml +0 -0
  132. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/_tox.yml +0 -0
  133. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.github/workflows/periodic.yml +0 -0
  134. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/.gitignore +0 -0
  135. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/Dockerfile +0 -0
  136. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/LICENSE +0 -0
  137. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/README.md +0 -0
  138. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/_api.rst +0 -0
  139. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/_templates/custom-module-template.rst +0 -0
  140. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/conf.py +0 -0
  141. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/examples/epics_demo.py +0 -0
  142. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/examples/foo_detector.py +0 -0
  143. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/examples/tango_demo.py +0 -0
  144. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  145. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  146. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  147. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  148. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  149. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  150. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
  151. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0008-signal-types.md +0 -0
  152. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
  153. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions/COPYME +0 -0
  154. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/decisions.md +0 -0
  155. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/design-goals.rst +0 -0
  156. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/event-loop-choice.rst +0 -0
  157. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations/flyscanning.rst +0 -0
  158. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/explanations.md +0 -0
  159. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/genindex.rst +0 -0
  160. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/how-to/choose-interfaces-for-devices.md +0 -0
  161. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/how-to/compound-devices.rst +0 -0
  162. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/how-to/contribute.md +0 -0
  163. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/how-to/make-a-simple-device.rst +0 -0
  164. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/how-to/make-a-standard-detector.rst +0 -0
  165. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/how-to/write-tests-for-devices.rst +0 -0
  166. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/how-to.md +0 -0
  167. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/images/ophyd-async-logo.svg +0 -0
  168. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/images/ophyd-favicon.svg +0 -0
  169. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/index.md +0 -0
  170. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/reference.md +0 -0
  171. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/tutorials/installation.md +0 -0
  172. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/tutorials/using-existing-devices.rst +0 -0
  173. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/docs/tutorials.md +0 -0
  174. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/setup.cfg +0 -0
  175. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/__init__.py +0 -0
  176. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/__main__.py +0 -0
  177. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_device_filler.py +0 -0
  178. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_device_save_loader.py +0 -0
  179. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_flyer.py +0 -0
  180. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_hdf_dataset.py +0 -0
  181. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_log.py +0 -0
  182. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
  183. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_providers.py +0 -0
  184. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_readable.py +0 -0
  185. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_signal_backend.py +0 -0
  186. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
  187. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/core/_status.py +0 -0
  188. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/__init__.py +0 -0
  189. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
  190. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
  191. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adcore/__init__.py +0 -0
  192. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
  193. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
  194. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
  195. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
  196. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
  197. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/advimba/__init__.py +0 -0
  198. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
  199. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/__init__.py +0 -0
  200. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/_aioca.py +0 -0
  201. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
  202. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/core/_epics_device.py +0 -0
  203. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/demo/__init__.py +0 -0
  204. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/demo/mover.db +0 -0
  205. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/demo/sensor.db +0 -0
  206. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/eiger/__init__.py +0 -0
  207. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/eiger/_eiger.py +0 -0
  208. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/eiger/_odin_io.py +0 -0
  209. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/epics/signal.py +0 -0
  210. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/__init__.py +0 -0
  211. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
  212. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
  213. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/_table.py +0 -0
  214. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/_utils.py +0 -0
  215. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
  216. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/plan_stubs/__init__.py +0 -0
  217. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
  218. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
  219. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/py.typed +0 -0
  220. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/__init__.py +0 -0
  221. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/demo/__init__.py +0 -0
  222. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/demo/_pattern_detector/__init__.py +0 -0
  223. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_detector.py +0 -0
  224. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_detector_controller.py +0 -0
  225. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_detector_writer.py +0 -0
  226. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/demo/_pattern_detector/_pattern_generator.py +0 -0
  227. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/sim/testing/__init__.py +0 -0
  228. {ophyd_async-0.8.0a5/tests/sim → ophyd_async-0.9.0a1/src/ophyd_async/tango}/__init__.py +0 -0
  229. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/tango/demo/__init__.py +0 -0
  230. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/tango/demo/_detector.py +0 -0
  231. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
  232. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
  233. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  234. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async.egg-info/entry_points.txt +0 -0
  235. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/src/ophyd_async.egg-info/top_level.txt +0 -0
  236. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/system_tests/epics/eiger/README.md +0 -0
  237. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
  238. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_log.py +0 -0
  239. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_protocol.py +0 -0
  240. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_providers.py +0 -0
  241. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_status.py +0 -0
  242. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_utils.py +0 -0
  243. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/core/test_watchable_async_status.py +0 -0
  244. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/pvi/test_pvi.py +0 -0
  245. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/signal/test_common.py +0 -0
  246. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/epics/test_areadetector_subclass_naming.py +0 -0
  247. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/db/panda.db +0 -0
  248. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/test_panda_utils.py +0 -0
  249. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/fastcs/panda/test_seq_table.py +0 -0
  250. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/plan_stubs/test_ensure_connected.py +0 -0
  251. {ophyd_async-0.8.0a5/tests/sim/demo → ophyd_async-0.9.0a1/tests/sim}/__init__.py +0 -0
  252. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/sim/conftest.py +0 -0
  253. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/sim/test_pattern_generator.py +0 -0
  254. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/sim/test_sim_writer.py +0 -0
  255. {ophyd_async-0.8.0a5 → ophyd_async-0.9.0a1}/tests/test_cli.py +0 -0
@@ -1,5 +1,5 @@
1
1
  # Changes here will be overwritten by Copier
2
- _commit: 2.5.0
2
+ _commit: 2.6.0
3
3
  _src_path: gh:DiamondLightSource/python-copier-template
4
4
  author_email: tom.cobb@diamond.ac.uk
5
5
  author_name: Tom Cobb
@@ -37,11 +37,11 @@
37
37
  }
38
38
  },
39
39
  "features": {
40
- // Some default things like git config
41
- "ghcr.io/devcontainers/features/common-utils:2": {
42
- "upgradePackages": false
43
- }
40
+ // add in eternal history and other bash features
41
+ "ghcr.io/diamondlightsource/devcontainer-features/bash-config:1.0.0": {}
44
42
  },
43
+ // Create the config folder for the bash-config feature
44
+ "initializeCommand": "mkdir -p ${localEnv:HOME}/.config/bash-config",
45
45
  "runArgs": [
46
46
  // Allow the container to access the host X11 display and EPICS CA
47
47
  "--net=host",
@@ -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/2.5.0/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/2.6.0/how-to.html).
@@ -0,0 +1,10 @@
1
+ Fixes #ISSUE
2
+
3
+ ### Instructions to reviewer on how to test:
4
+ 1. Do thing x
5
+ 2. Confirm thing y happens
6
+
7
+ ### Checks for reviewer
8
+ - [ ] Would the PR title make sense to a user on a set of release notes
9
+ - [ ] If the change requires a bump in an IOC version, is that specified in a `##Changes` section in the body of the PR
10
+ - [ ] If the change requires a bump in the PandABlocks-ioc version, is the `ophyd_async.fastcs.panda._hdf_panda.MINIMUM_PANDA_IOC` variable updated to match
@@ -49,6 +49,7 @@ jobs:
49
49
  with:
50
50
  python-version: ${{ inputs.python-version }}
51
51
  pip-install: ".[dev]"
52
+
52
53
  - name: Run tests
53
54
  run: tox -e tests
54
55
 
@@ -21,7 +21,7 @@ jobs:
21
21
  strategy:
22
22
  matrix:
23
23
  runs-on: ["ubuntu-latest", "windows-latest"] # can add macos-latest
24
- python-version: ["3.10","3.11"] # 3.12 should be added when p4p is updated
24
+ python-version: ["3.10","3.11","3.12"]
25
25
  include:
26
26
  # Include one that runs in the dev environment
27
27
  - runs-on: "ubuntu-latest"
@@ -22,3 +22,11 @@ repos:
22
22
  entry: ruff format --force-exclude
23
23
  types: [python]
24
24
  require_serial: true
25
+
26
+ - id: import-contracts
27
+ name: Ensure import directionality
28
+ pass_filenames: false
29
+ language: system
30
+ entry: lint-imports
31
+ types: [python]
32
+ require_serial: false
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ophyd-async
3
- Version: 0.8.0a5
3
+ Version: 0.9.0a1
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
@@ -37,6 +37,7 @@ Classifier: Development Status :: 3 - Alpha
37
37
  Classifier: License :: OSI Approved :: BSD License
38
38
  Classifier: Programming Language :: Python :: 3.10
39
39
  Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
40
41
  Requires-Python: >=3.10
41
42
  Description-Content-Type: text/markdown
42
43
  License-File: LICENSE
@@ -67,6 +68,7 @@ Requires-Dist: ophyd_async[tango]; extra == "dev"
67
68
  Requires-Dist: inflection; extra == "dev"
68
69
  Requires-Dist: ipython; extra == "dev"
69
70
  Requires-Dist: ipywidgets; extra == "dev"
71
+ Requires-Dist: import-linter; extra == "dev"
70
72
  Requires-Dist: matplotlib; extra == "dev"
71
73
  Requires-Dist: myst-parser; extra == "dev"
72
74
  Requires-Dist: numpydoc; extra == "dev"
@@ -0,0 +1,45 @@
1
+ # `set_and_wait_for_other_value`
2
+
3
+ The `set_and_wait_for_other_value` function (defined in `_signal.py`) is a utility designed to:
4
+
5
+ 1. **Set a signal**.
6
+ 2. **Wait for another signal to reach a specified value (`match_value`)**.
7
+
8
+ The behavior of the function depends on the value of the `wait_for_set_completion` parameter:
9
+
10
+ - **If `wait_for_set_completion = True`:**
11
+ The function returns at **1** (see diagram below), which occurs when the "set operation" is complete.
12
+
13
+ - **If `wait_for_set_completion = False`:**
14
+ The function returns at **2**, which occurs when the `match_signal` reaches the `match_value`.
15
+
16
+ In **AreaDetector**, the `wait_for_set_completion` parameter should generally be set to **`False`**, as the preferred behavior is to return when the `match_signal` achieves the `match_value`.
17
+
18
+ ---
19
+
20
+ ## Behavior Diagram:
21
+
22
+ ![wait_for_set_completion](../images/set_and_wait_for_other_value.svg)
23
+
24
+ ---
25
+
26
+ ## Example Usage
27
+
28
+ ```python
29
+ # Example code snippet for using set_and_wait_for_other_value in an AreaDetector driver
30
+ self._arm_status = set_and_wait_for_other_value(
31
+ self._drv.arm,
32
+ 1,
33
+ self._drv.state,
34
+ "ready",
35
+ timeout=DEFAULT_TIMEOUT,
36
+ wait_for_set_completion=False,
37
+ )
38
+ ```
39
+
40
+ In this **AreaDetector driver**, the function ensures that the detector's `arm_status` reaches `"ready"` before capturing data. To achieve this:
41
+
42
+ - The detector is instructed to transition to the "armed" state by setting the driver's `arm` signal to `1`.
43
+ - The function waits until the driver's `state` signal equals `"ready"`.
44
+
45
+ This approach ensures that data capture is only initiated once the detector is fully prepared.
@@ -0,0 +1,10 @@
1
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1187.8240472771774 784.5838303364346" width="1187.8240472771774" height="784.5838303364346">
2
+ <!-- svg-source:excalidraw -->
3
+
4
+ <defs>
5
+ <style class="style-fonts">
6
+ @font-face { font-family: Excalifont; src: url(data:font/woff2;base64,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); }
7
+ </style>
8
+
9
+ </defs>
10
+ <rect x="0" y="0" width="1187.8240472771774" height="784.5838303364346" fill="#ffffff"></rect><g stroke-linecap="round"><g transform="translate(43.84248105120804 302.75444427692025) rotate(0 109.31598350459507 0)"><path d="M-0.45 -0.7 C35.76 -0.86, 180.92 -1.39, 217.58 -1.19 M1.51 1.54 C38.06 1.51, 183.45 0.24, 219.75 -0.28" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(262.4744480603982 302.8253415087969) rotate(0 0 -82.9293667965893)"><path d="M0.64 0.3 C0.59 -27.08, -0.08 -137.51, -0.32 -165.29 M-0.48 -0.59 C-0.72 -28.23, -1.79 -139.66, -1.44 -167.12" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(258.8706526177911 134.14839879518058) rotate(0 332.5798441252804 -1.9202069522244898)"><path d="M-0.18 0.98 C110.67 0.28, 554.82 -2.97, 665.76 -3.76 M-1.73 0.45 C108.95 -0.07, 554.04 -1.71, 665.12 -2.18" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(925.5665064301318 131.8441504525112) rotate(0 1.1521241713346626 80.10711520276767)"><path d="M0.54 0.53 C0.98 27.16, 1.63 133.33, 2.07 159.95 M-0.63 -0.24 C-0.32 26.56, 0.42 134.38, 1 161.35" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(926.3345892110212 293.1415344393678) rotate(0 68.92542750440384 -1.152124171334691)"><path d="M1.09 -0.33 C24.12 -0.33, 115.62 -0.86, 138.29 -1.2 M0.21 -1.54 C23.1 -1.75, 114.33 -2.82, 137.57 -2.74" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(154.08449781789392 67.15748673767692) rotate(0 52.98975332972128 33.34186726364484)"><path d="M-1.06 0.7 C16.59 11.86, 88.97 56.89, 106.91 67.72 M0.58 0.03 C18.07 10.8, 88.85 55.06, 106.45 66.14" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(154.08449781789392 67.15748673767692) rotate(0 52.98975332972128 33.34186726364484)"><path d="M82 60.91 C92.6 64.68, 102.53 66.17, 106.45 66.14 M82 60.91 C86.56 61.38, 93.31 62.59, 106.45 66.14" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(154.08449781789392 67.15748673767692) rotate(0 52.98975332972128 33.34186726364484)"><path d="M91.08 46.42 C98.28 55.67, 104.73 62.72, 106.45 66.14 M91.08 46.42 C93.64 50.1, 98.42 54.45, 106.45 66.14" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(73.11139160618495 10) rotate(0 47.0625 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">set called</text></g><g stroke-linecap="round"><g transform="translate(931.6644736450401 312.4583673202069) rotate(0 4.167733407955666 192.31112725280877)"><path d="M-0.34 -0.98 C1.13 63.35, 6.73 321.09, 8.05 385.17 M1.68 1.12 C3.03 65.16, 5.56 319.49, 6.94 383.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(931.6644736450401 312.4583673202069) rotate(0 4.167733407955666 192.31112725280877)"><path d="M-1.96 359.97 C-1.66 365.01, 2.98 369.66, 6.94 383.33 M-1.96 359.97 C0.77 365.61, 2.46 369.39, 6.94 383.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(931.6644736450401 312.4583673202069) rotate(0 4.167733407955666 192.31112725280877)"><path d="M15.14 359.71 C11.41 364.76, 12.02 369.48, 6.94 383.33 M15.14 359.71 C14.41 365.37, 12.64 369.21, 6.94 383.33" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(889.4853986759654 715.0686100052003) rotate(0 66.3862760711362 24.140464025867686)"><text x="0" y="17.014199045431567" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="19.312371220694175px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Set completed</text><text x="0" y="41.15466307129928" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="19.312371220694175px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"></text></g><g stroke-linecap="round"><g transform="translate(45.723429211048085 551.6184165698157) rotate(0 208.3866703977804 -2.9769524342540308)"><path d="M1.15 -0.09 C70.36 -1.4, 346.52 -5.76, 415.96 -6.64 M0.29 -1.19 C69.83 -1.84, 348.7 -4.42, 418.24 -5.46" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(462.49677000660887 545.6645117013077) rotate(0 -1.190780973701635 -80.97310621170891)"><path d="M-0.62 -0.09 C-1.05 -26.87, -1.53 -134.53, -1.9 -161.39 M1.25 -1.18 C0.65 -28.26, -1.74 -136.22, -2.59 -163.22" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(460.1152080592056 380.14595635678495) rotate(0 105.3841161725918 -1.1907809737016066)"><path d="M0.98 -0.93 C36.1 -1.01, 176.54 -1, 211.51 -1.27 M0.04 1.2 C34.99 0.88, 175.96 -2.39, 210.95 -2.82" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(669.6926594306876 376.57361343568016) rotate(0 0.5953904868507607 82.75927767226133)"><path d="M-0.99 -0.41 C-0.54 27.2, 1.55 136.9, 1.72 164.64 M0.7 -1.68 C1.12 26.16, 0.78 138.12, 1.04 165.72" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(672.0742213780909 542.0921687802029) rotate(0 191.12034627910714 -2.976952434253974)"><path d="M0.95 0.4 C64.42 -0.86, 317.63 -5.42, 381.15 -6.62 M0 -0.44 C63.78 -1.63, 319.76 -4.51, 383.29 -5.43" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g stroke-linecap="round"><g transform="translate(672.1152080592055 548.1907594909206) rotate(0 0.5953904868508175 65.49295355358805)"><path d="M-0.92 1.14 C-0.95 23.33, -0.16 110.39, 0.31 131.92 M0.8 0.7 C1.09 22.66, 2.45 108.52, 2.56 130.29" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(672.1152080592055 548.1907594909206) rotate(0 0.5953904868508175 65.49295355358805)"><path d="M-6.25 106.9 C-1.55 113.53, 1.13 124.19, 2.56 130.29 M-6.25 106.9 C-4.64 113.13, -2.21 118.07, 2.56 130.29" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g><g transform="translate(672.1152080592055 548.1907594909206) rotate(0 0.5953904868508175 65.49295355358805)"><path d="M10.85 106.7 C9.68 113.27, 6.5 123.99, 2.56 130.29 M10.85 106.7 C8.22 113.14, 6.41 118.12, 2.56 130.29" stroke="#1e1e1e" stroke-width="2" fill="none"></path></g></g><mask></mask><g transform="translate(616.1485022952302 694.6568192562175) rotate(0 69.97916412353516 25)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">RBV Matched </text><text x="0" y="42.62" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Return here</text></g><g transform="translate(10 264.6402019077296) rotate(0 47.8125 12.500000000000014)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Set signal</text></g><g transform="translate(869.5323806105109 749.2654514964912) rotate(0 154.14583333333326 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">wait_for_set_completion= True</text></g><g transform="translate(521.8463297153439 749.5838303364346) rotate(0 160.32291666666663 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">wait_for_set_completion = False</text></g><g transform="translate(20.535767711378583 514.1120161220821) rotate(0 59.5625 12.5)"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">match signal</text></g><g transform="translate(957.8616550664754 651.6440183607504) rotate(0 7.677083492279053 22.5)"><text x="0" y="31.716" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="36px" fill="#e03131" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">1</text></g><g transform="translate(691.1677036384312 638.6901134922423) rotate(0 12.583333015441895 22.5)"><text x="0" y="31.716" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="36px" fill="#e03131" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">2</text></g></svg>
@@ -9,6 +9,7 @@ classifiers = [
9
9
  "License :: OSI Approved :: BSD License",
10
10
  "Programming Language :: Python :: 3.10",
11
11
  "Programming Language :: Python :: 3.11",
12
+ "Programming Language :: Python :: 3.12",
12
13
  ]
13
14
  description = "Asynchronous Bluesky hardware abstraction code, compatible with control systems like EPICS and Tango"
14
15
  dependencies = [
@@ -42,6 +43,7 @@ dev = [
42
43
  "inflection",
43
44
  "ipython",
44
45
  "ipywidgets",
46
+ "import-linter",
45
47
  "matplotlib",
46
48
  "myst-parser",
47
49
  "numpydoc",
@@ -164,3 +166,53 @@ lint.preview = true # so that preview mode PLC2701 is enabled
164
166
  # See https://github.com/DiamondLightSource/python-copier-template/issues/154
165
167
  # Remove this line to forbid private member access in tests
166
168
  "tests/**/*" = ["SLF001"]
169
+
170
+
171
+ [tool.importlinter]
172
+ root_package = "ophyd_async"
173
+
174
+ [[tool.importlinter.contracts]]
175
+ name = "Core is independent"
176
+ type = "independence"
177
+ modules = "ophyd_async.core"
178
+
179
+ [[tool.importlinter.contracts]]
180
+ name = "Epics depends only on core"
181
+ type = "forbidden"
182
+ source_modules = "ophyd_async.epics"
183
+ forbidden_modules = [
184
+ "ophyd_async.fastcs",
185
+ "ophyd_async.plan_stubs",
186
+ "ophyd_async.sim",
187
+ "ophyd_async.tango",
188
+ ]
189
+
190
+ [[tool.importlinter.contracts]]
191
+ name = "tango depends only on core"
192
+ type = "forbidden"
193
+ source_modules = "ophyd_async.tango"
194
+ forbidden_modules = [
195
+ "ophyd_async.epics",
196
+ "ophyd_async.fastcs",
197
+ "ophyd_async.plan_stubs",
198
+ "ophyd_async.sim",
199
+ ]
200
+
201
+
202
+ [[tool.importlinter.contracts]]
203
+ name = "sim depends only on core"
204
+ type = "forbidden"
205
+ source_modules = "ophyd_async.sim"
206
+ forbidden_modules = [
207
+ "ophyd_async.epics",
208
+ "ophyd_async.fastcs",
209
+ "ophyd_async.plan_stubs",
210
+ "ophyd_async.tango",
211
+ ]
212
+
213
+
214
+ [[tool.importlinter.contracts]]
215
+ name = "Fastcs depends only on core, epics, tango"
216
+ type = "forbidden"
217
+ source_modules = "ophyd_async.fastcs"
218
+ forbidden_modules = ["ophyd_async.plan_stubs", "ophyd_async.sim"]
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.8.0a5'
16
- __version_tuple__ = version_tuple = (0, 8, 0)
15
+ __version__ = version = '0.9.0a1'
16
+ __version_tuple__ = version_tuple = (0, 9, 0)
@@ -21,16 +21,6 @@ from ._flyer import FlyerController, StandardFlyer
21
21
  from ._hdf_dataset import HDFDataset, HDFFile
22
22
  from ._log import config_ophyd_async_logging
23
23
  from ._mock_signal_backend import MockSignalBackend
24
- from ._mock_signal_utils import (
25
- callback_on_mock_put,
26
- get_mock,
27
- get_mock_put,
28
- mock_puts_blocked,
29
- reset_mock_put_calls,
30
- set_mock_put_proceeds,
31
- set_mock_value,
32
- set_mock_values,
33
- )
34
24
  from ._protocol import AsyncConfigurable, AsyncReadable, AsyncStageable
35
25
  from ._providers import (
36
26
  AutoIncrementFilenameProvider,
@@ -53,14 +43,12 @@ from ._readable import (
53
43
  )
54
44
  from ._signal import (
55
45
  Signal,
46
+ SignalConnector,
56
47
  SignalR,
57
48
  SignalRW,
58
49
  SignalW,
59
50
  SignalX,
60
- assert_configuration,
61
- assert_emitted,
62
- assert_reading,
63
- assert_value,
51
+ observe_signals_value,
64
52
  observe_value,
65
53
  set_and_wait_for_other_value,
66
54
  set_and_wait_for_value,
@@ -122,14 +110,6 @@ __all__ = [
122
110
  "HDFFile",
123
111
  "config_ophyd_async_logging",
124
112
  "MockSignalBackend",
125
- "callback_on_mock_put",
126
- "get_mock",
127
- "get_mock_put",
128
- "mock_puts_blocked",
129
- "reset_mock_put_calls",
130
- "set_mock_put_proceeds",
131
- "set_mock_value",
132
- "set_mock_values",
133
113
  "AsyncConfigurable",
134
114
  "AsyncReadable",
135
115
  "AsyncStageable",
@@ -149,15 +129,13 @@ __all__ = [
149
129
  "StandardReadable",
150
130
  "StandardReadableFormat",
151
131
  "Signal",
132
+ "SignalConnector",
152
133
  "SignalR",
153
134
  "SignalRW",
154
135
  "SignalW",
155
136
  "SignalX",
156
- "assert_configuration",
157
- "assert_emitted",
158
- "assert_reading",
159
- "assert_value",
160
137
  "observe_value",
138
+ "observe_signals_value",
161
139
  "set_and_wait_for_value",
162
140
  "set_and_wait_for_other_value",
163
141
  "soft_signal_r_and_setter",
@@ -30,13 +30,13 @@ class DetectorTrigger(StrictEnum):
30
30
  """Type of mechanism for triggering a detector to take frames"""
31
31
 
32
32
  #: Detector generates internal trigger for given rate
33
- internal = "internal"
33
+ INTERNAL = "internal"
34
34
  #: Expect a series of arbitrary length trigger signals
35
- edge_trigger = "edge_trigger"
35
+ EDGE_TRIGGER = "edge_trigger"
36
36
  #: Expect a series of constant width external gate signals
37
- constant_gate = "constant_gate"
37
+ CONSTANT_GATE = "constant_gate"
38
38
  #: Expect a series of variable width external gate signals
39
- variable_gate = "variable_gate"
39
+ VARIABLE_GATE = "variable_gate"
40
40
 
41
41
 
42
42
  class TriggerInfo(BaseModel):
@@ -53,7 +53,7 @@ class TriggerInfo(BaseModel):
53
53
  #: - 3 times for final flat field images
54
54
  number_of_triggers: NonNegativeInt | list[NonNegativeInt]
55
55
  #: Sort of triggers that will be sent
56
- trigger: DetectorTrigger = Field(default=DetectorTrigger.internal)
56
+ trigger: DetectorTrigger = Field(default=DetectorTrigger.INTERNAL)
57
57
  #: What is the minimum deadtime between triggers
58
58
  deadtime: float | None = Field(default=None, ge=0)
59
59
  #: What is the maximum high time of the triggers
@@ -265,14 +265,14 @@ class StandardDetector(
265
265
  await self.prepare(
266
266
  TriggerInfo(
267
267
  number_of_triggers=1,
268
- trigger=DetectorTrigger.internal,
268
+ trigger=DetectorTrigger.INTERNAL,
269
269
  deadtime=None,
270
270
  livetime=None,
271
271
  frame_timeout=None,
272
272
  )
273
273
  )
274
274
  assert self._trigger_info
275
- assert self._trigger_info.trigger is DetectorTrigger.internal
275
+ assert self._trigger_info.trigger is DetectorTrigger.INTERNAL
276
276
  # Arm the detector and wait for it to finish.
277
277
  indices_written = await self.writer.get_indices_written()
278
278
  await self.controller.arm()
@@ -303,7 +303,7 @@ class StandardDetector(
303
303
  Args:
304
304
  value: TriggerInfo describing how to trigger the detector
305
305
  """
306
- if value.trigger != DetectorTrigger.internal:
306
+ if value.trigger != DetectorTrigger.INTERNAL:
307
307
  assert (
308
308
  value.deadtime
309
309
  ), "Deadtime must be supplied when in externally triggered mode"
@@ -323,7 +323,7 @@ class StandardDetector(
323
323
  self._describe, _ = await asyncio.gather(
324
324
  self.writer.open(value.multiplier), self.controller.prepare(value)
325
325
  )
326
- if value.trigger != DetectorTrigger.internal:
326
+ if value.trigger != DetectorTrigger.INTERNAL:
327
327
  await self.controller.arm()
328
328
  self._fly_start = time.monotonic()
329
329
 
@@ -10,7 +10,6 @@ from typing import Any, TypeVar
10
10
  from bluesky.protocols import HasName
11
11
  from bluesky.run_engine import call_in_bluesky_event_loop, in_bluesky_event_loop
12
12
 
13
- from ._protocol import Connectable
14
13
  from ._utils import DEFAULT_TIMEOUT, LazyMock, NotConnected, wait_for_connection
15
14
 
16
15
 
@@ -61,7 +60,7 @@ class DeviceConnector:
61
60
  await wait_for_connection(**coros)
62
61
 
63
62
 
64
- class Device(HasName, Connectable):
63
+ class Device(HasName):
65
64
  """Common base class for all Ophyd Async Devices."""
66
65
 
67
66
  _name: str = ""
@@ -71,13 +70,16 @@ class Device(HasName, Connectable):
71
70
  _connect_task: asyncio.Task | None = None
72
71
  # The mock if we have connected in mock mode
73
72
  _mock: LazyMock | None = None
73
+ # The separator to use when making child names
74
+ _child_name_separator: str = "-"
74
75
 
75
76
  def __init__(
76
77
  self, name: str = "", connector: DeviceConnector | None = None
77
78
  ) -> None:
78
79
  self._connector = connector or DeviceConnector()
79
80
  self._connector.create_children_from_annotations(self)
80
- self.set_name(name)
81
+ if name:
82
+ self.set_name(name)
81
83
 
82
84
  @property
83
85
  def name(self) -> str:
@@ -97,21 +99,30 @@ class Device(HasName, Connectable):
97
99
  getLogger("ophyd_async.devices"), {"ophyd_async_device_name": self.name}
98
100
  )
99
101
 
100
- def set_name(self, name: str):
102
+ def set_name(self, name: str, *, child_name_separator: str | None = None) -> None:
101
103
  """Set ``self.name=name`` and each ``self.child.name=name+"-child"``.
102
104
 
103
105
  Parameters
104
106
  ----------
105
107
  name:
106
108
  New name to set
109
+ child_name_separator:
110
+ Use this as a separator instead of "-". Use "_" instead to make the same
111
+ names as the equivalent ophyd sync device.
107
112
  """
108
113
  self._name = name
114
+ if child_name_separator:
115
+ self._child_name_separator = child_name_separator
109
116
  # Ensure logger is recreated after a name change
110
117
  if "log" in self.__dict__:
111
118
  del self.log
112
- for child_name, child in self.children():
113
- child_name = f"{self.name}-{child_name.strip('_')}" if self.name else ""
114
- child.set_name(child_name)
119
+ for attr_name, child in self.children():
120
+ child_name = (
121
+ f"{self.name}{self._child_name_separator}{attr_name}"
122
+ if self.name
123
+ else ""
124
+ )
125
+ child.set_name(child_name, child_name_separator=self._child_name_separator)
115
126
 
116
127
  def __setattr__(self, name: str, value: Any) -> None:
117
128
  # Bear in mind that this function is called *a lot*, so
@@ -147,6 +158,10 @@ class Device(HasName, Connectable):
147
158
  timeout:
148
159
  Time to wait before failing with a TimeoutError.
149
160
  """
161
+ assert hasattr(self, "_connector"), (
162
+ f"{self}: doesn't have attribute `_connector`,"
163
+ " did you call `super().__init__` in your `__init__` method?"
164
+ )
150
165
  if mock:
151
166
  # Always connect in mock mode serially
152
167
  if isinstance(mock, LazyMock):
@@ -247,6 +262,8 @@ class DeviceCollector:
247
262
  set_name:
248
263
  If True, call ``device.set_name(variable_name)`` on all collected
249
264
  Devices
265
+ child_name_separator:
266
+ Use this as a separator if we call ``set_name``.
250
267
  connect:
251
268
  If True, call ``device.connect(mock)`` in parallel on all
252
269
  collected Devices
@@ -271,11 +288,13 @@ class DeviceCollector:
271
288
  def __init__(
272
289
  self,
273
290
  set_name=True,
291
+ child_name_separator: str = "-",
274
292
  connect=True,
275
293
  mock=False,
276
294
  timeout: float = 10.0,
277
295
  ):
278
296
  self._set_name = set_name
297
+ self._child_name_separator = child_name_separator
279
298
  self._connect = connect
280
299
  self._mock = mock
281
300
  self._timeout = timeout
@@ -311,7 +330,7 @@ class DeviceCollector:
311
330
  for name, obj in self._objects_on_exit.items():
312
331
  if name not in self._names_on_enter and isinstance(obj, Device):
313
332
  if self._set_name and not obj.name:
314
- obj.set_name(name)
333
+ obj.set_name(name, child_name_separator=self._child_name_separator)
315
334
  if self._connect:
316
335
  connect_coroutines[name] = obj.connect(
317
336
  self._mock, timeout=self._timeout
@@ -13,38 +13,10 @@ from typing import (
13
13
  from bluesky.protocols import HasName, Reading
14
14
  from event_model import DataKey
15
15
 
16
- from ._utils import DEFAULT_TIMEOUT
17
-
18
16
  if TYPE_CHECKING:
19
- from unittest.mock import Mock
20
-
21
17
  from ._status import AsyncStatus
22
18
 
23
19
 
24
- @runtime_checkable
25
- class Connectable(Protocol):
26
- @abstractmethod
27
- async def connect(
28
- self,
29
- mock: bool | Mock = False,
30
- timeout: float = DEFAULT_TIMEOUT,
31
- force_reconnect: bool = False,
32
- ):
33
- """Connect self and all child Devices.
34
-
35
- Contains a timeout that gets propagated to child.connect methods.
36
-
37
- Parameters
38
- ----------
39
- mock:
40
- If True then use ``MockSignalBackend`` for all Signals
41
- timeout:
42
- Time to wait before failing with a TimeoutError.
43
- force_reconnect:
44
- Reconnect even if previous connect was successful.
45
- """
46
-
47
-
48
20
  @runtime_checkable
49
21
  class AsyncReadable(HasName, Protocol):
50
22
  @abstractmethod