ophyd-async 0.10.0a4__tar.gz → 0.10.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 (295) hide show
  1. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/PKG-INFO +2 -2
  2. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/pyproject.toml +1 -1
  3. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/_version.py +2 -2
  4. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_derived_signal.py +1 -1
  5. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_derived_signal_backend.py +7 -5
  6. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_hdf_dataset.py +1 -1
  7. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_providers.py +1 -1
  8. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_signal.py +6 -1
  9. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_signal_backend.py +1 -1
  10. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_core_logic.py +34 -10
  11. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_hdf_writer.py +15 -0
  12. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async.egg-info/PKG-INFO +2 -2
  13. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async.egg-info/requires.txt +1 -1
  14. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_multi_derived_signal.py +56 -0
  15. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_signal.py +6 -0
  16. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_single_derived_signal.py +108 -6
  17. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adcore/test_drivers.py +54 -2
  18. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adcore/test_writers.py +16 -0
  19. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.codecov.yml +0 -0
  20. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.copier-answers.yml +0 -0
  21. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.devcontainer/devcontainer.json +0 -0
  22. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.git-blame-ignore-revs +0 -0
  23. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/CONTRIBUTING.md +0 -0
  24. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  25. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  26. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  27. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/actions/install_requirements/action.yml +0 -0
  28. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/codeql/codeql-config.yml +0 -0
  29. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/dependabot.yml +0 -0
  30. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/pages/index.html +0 -0
  31. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/pages/make_switcher.py +0 -0
  32. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_check.yml +0 -0
  33. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_codeql.yml +0 -0
  34. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_dist.yml +0 -0
  35. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_docs.yml +0 -0
  36. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_import_with_no_extras.yml +0 -0
  37. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_pypi.yml +0 -0
  38. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_release.yml +0 -0
  39. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_test.yml +0 -0
  40. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/_tox.yml +0 -0
  41. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/ci.yml +0 -0
  42. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.github/workflows/periodic.yml +0 -0
  43. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.gitignore +0 -0
  44. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/.pre-commit-config.yaml +0 -0
  45. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/Dockerfile +0 -0
  46. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/LICENSE +0 -0
  47. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/README.md +0 -0
  48. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/_static/custom.css +0 -0
  49. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/conf.py +0 -0
  50. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0001-record-architecture-decisions.md +0 -0
  51. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0002-switched-to-python-copier-template.md +0 -0
  52. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0003-ophyd-async-migration.rst +0 -0
  53. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0004-repository-structure.rst +0 -0
  54. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0005-respect-black-line-length.rst +0 -0
  55. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0006-procedural-device-definitions.rst +0 -0
  56. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0007-subpackage-structure.md +0 -0
  57. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0008-signal-types.md +0 -0
  58. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0009-procedural-vs-declarative-devices.md +0 -0
  59. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/0010-docstring-format.md +0 -0
  60. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions/COPYME +0 -0
  61. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/decisions.md +0 -0
  62. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/declarative-vs-procedural.md +0 -0
  63. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/design-goals.md +0 -0
  64. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/device-connection-strategies.md +0 -0
  65. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/devices-signals-backends.md +0 -0
  66. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/flyscanning.md +0 -0
  67. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations/where-device-logic.md +0 -0
  68. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/explanations.md +0 -0
  69. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/genindex.rst +0 -0
  70. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to/choose-right-baseclass.md +0 -0
  71. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to/contribute.md +0 -0
  72. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to/derive-one-signal-from-others.md +0 -0
  73. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to/implement-ad-detector.md +0 -0
  74. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to/interact-with-signals.md +0 -0
  75. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to/put-device-back.md +0 -0
  76. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to/store-and-retrieve.md +0 -0
  77. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/how-to.md +0 -0
  78. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/images/flyscan_collection_windows_and_frames.svg +0 -0
  79. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/images/ophyd-async-logo.svg +0 -0
  80. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/images/ophyd-favicon.svg +0 -0
  81. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/images/set_and_wait_for_other_value.excalidraw.svg +0 -0
  82. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/index.md +0 -0
  83. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/reference.md +0 -0
  84. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/tutorials/implementing-detectors.md +0 -0
  85. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/tutorials/implementing-devices.md +0 -0
  86. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/tutorials/installation.md +0 -0
  87. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/tutorials/using-devices.md +0 -0
  88. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/tutorials/writing-tests-for-devices.md +0 -0
  89. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/docs/tutorials.md +0 -0
  90. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/setup.cfg +0 -0
  91. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/__init__.py +0 -0
  92. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/__main__.py +0 -0
  93. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/_docs_parser.py +0 -0
  94. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/__init__.py +0 -0
  95. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_detector.py +0 -0
  96. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_device.py +0 -0
  97. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_device_filler.py +0 -0
  98. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_flyer.py +0 -0
  99. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_log.py +0 -0
  100. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_mock_signal_backend.py +0 -0
  101. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_protocol.py +0 -0
  102. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_readable.py +0 -0
  103. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_settings.py +0 -0
  104. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_soft_signal_backend.py +0 -0
  105. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_status.py +0 -0
  106. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_table.py +0 -0
  107. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_utils.py +0 -0
  108. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/core/_yaml_settings.py +0 -0
  109. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/__init__.py +0 -0
  110. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adandor/__init__.py +0 -0
  111. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adandor/_andor.py +0 -0
  112. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adandor/_andor_controller.py +0 -0
  113. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adandor/_andor_io.py +0 -0
  114. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adaravis/__init__.py +0 -0
  115. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adaravis/_aravis.py +0 -0
  116. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adaravis/_aravis_controller.py +0 -0
  117. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adaravis/_aravis_io.py +0 -0
  118. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/__init__.py +0 -0
  119. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_core_detector.py +0 -0
  120. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_core_io.py +0 -0
  121. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_core_writer.py +0 -0
  122. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_jpeg_writer.py +0 -0
  123. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_single_trigger.py +0 -0
  124. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_tiff_writer.py +0 -0
  125. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adcore/_utils.py +0 -0
  126. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adkinetix/__init__.py +0 -0
  127. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adkinetix/_kinetix.py +0 -0
  128. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adkinetix/_kinetix_controller.py +0 -0
  129. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adkinetix/_kinetix_io.py +0 -0
  130. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adpilatus/__init__.py +0 -0
  131. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adpilatus/_pilatus.py +0 -0
  132. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adpilatus/_pilatus_controller.py +0 -0
  133. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adpilatus/_pilatus_io.py +0 -0
  134. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adsimdetector/__init__.py +0 -0
  135. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adsimdetector/_sim.py +0 -0
  136. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adsimdetector/_sim_controller.py +0 -0
  137. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/adsimdetector/_sim_io.py +0 -0
  138. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/advimba/__init__.py +0 -0
  139. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/advimba/_vimba.py +0 -0
  140. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/advimba/_vimba_controller.py +0 -0
  141. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/advimba/_vimba_io.py +0 -0
  142. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/__init__.py +0 -0
  143. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/_aioca.py +0 -0
  144. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/_epics_connector.py +0 -0
  145. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/_epics_device.py +0 -0
  146. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/_p4p.py +0 -0
  147. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/_pvi_connector.py +0 -0
  148. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/_signal.py +0 -0
  149. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/core/_util.py +0 -0
  150. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/__init__.py +0 -0
  151. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/__main__.py +0 -0
  152. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/_ioc.py +0 -0
  153. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/_motor.py +0 -0
  154. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/_point_detector.py +0 -0
  155. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/_point_detector_channel.py +0 -0
  156. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/_stage.py +0 -0
  157. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/motor.db +0 -0
  158. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/point_detector.db +0 -0
  159. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/demo/point_detector_channel.db +0 -0
  160. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/eiger/__init__.py +0 -0
  161. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/eiger/_odin_io.py +0 -0
  162. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/motor.py +0 -0
  163. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/signal.py +0 -0
  164. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/testing/__init__.py +0 -0
  165. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/testing/_example_ioc.py +0 -0
  166. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/testing/_utils.py +0 -0
  167. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/testing/test_records.db +0 -0
  168. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/epics/testing/test_records_pva.db +0 -0
  169. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/__init__.py +0 -0
  170. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/core.py +0 -0
  171. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/eiger/__init__.py +0 -0
  172. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/eiger/_eiger.py +0 -0
  173. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/eiger/_eiger_controller.py +0 -0
  174. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/eiger/_eiger_io.py +0 -0
  175. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/odin/__init__.py +0 -0
  176. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/panda/__init__.py +0 -0
  177. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/panda/_block.py +0 -0
  178. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/panda/_control.py +0 -0
  179. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/panda/_hdf_panda.py +0 -0
  180. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/panda/_table.py +0 -0
  181. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/panda/_trigger.py +0 -0
  182. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/fastcs/panda/_writer.py +0 -0
  183. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/__init__.py +0 -0
  184. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/_ensure_connected.py +0 -0
  185. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/_fly.py +0 -0
  186. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/_nd_attributes.py +0 -0
  187. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/_panda.py +0 -0
  188. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/_settings.py +0 -0
  189. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/_utils.py +0 -0
  190. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/plan_stubs/_wait_for_awaitable.py +0 -0
  191. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/py.typed +0 -0
  192. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/__init__.py +0 -0
  193. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/__main__.py +0 -0
  194. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_blob_detector.py +0 -0
  195. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_blob_detector_controller.py +0 -0
  196. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_blob_detector_writer.py +0 -0
  197. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_mirror_horizontal.py +0 -0
  198. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_mirror_vertical.py +0 -0
  199. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_motor.py +0 -0
  200. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_pattern_generator.py +0 -0
  201. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_point_detector.py +0 -0
  202. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/sim/_stage.py +0 -0
  203. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/__init__.py +0 -0
  204. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/core/__init__.py +0 -0
  205. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/core/_base_device.py +0 -0
  206. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/core/_converters.py +0 -0
  207. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/core/_signal.py +0 -0
  208. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/core/_tango_readable.py +0 -0
  209. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/core/_tango_transport.py +0 -0
  210. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/core/_utils.py +0 -0
  211. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/demo/__init__.py +0 -0
  212. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/demo/_counter.py +0 -0
  213. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/demo/_detector.py +0 -0
  214. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/demo/_mover.py +0 -0
  215. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/demo/_tango/__init__.py +0 -0
  216. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/demo/_tango/_servers.py +0 -0
  217. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/testing/__init__.py +0 -0
  218. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/tango/testing/_one_of_everything.py +0 -0
  219. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/__init__.py +0 -0
  220. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/__pytest_assert_rewrite.py +0 -0
  221. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/_assert.py +0 -0
  222. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/_mock_signal_utils.py +0 -0
  223. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/_one_of_everything.py +0 -0
  224. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/_single_derived.py +0 -0
  225. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/_utils.py +0 -0
  226. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async/testing/_wait_for_pending.py +0 -0
  227. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async.egg-info/SOURCES.txt +0 -0
  228. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async.egg-info/dependency_links.txt +0 -0
  229. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/src/ophyd_async.egg-info/top_level.txt +0 -0
  230. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/system_tests/epics/eiger/README.md +0 -0
  231. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/system_tests/epics/eiger/start_iocs_and_run_tests.sh +0 -0
  232. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/system_tests/epics/eiger/test_eiger_system.py +0 -0
  233. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/conftest.py +0 -0
  234. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_auto_init_devices.py +0 -0
  235. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_detector.py +0 -0
  236. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_device.py +0 -0
  237. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_flyer.py +0 -0
  238. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_log.py +0 -0
  239. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_mock_signal_backend.py +0 -0
  240. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_observe.py +0 -0
  241. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_protocol.py +0 -0
  242. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_providers.py +0 -0
  243. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_readable.py +0 -0
  244. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_soft_signal_backend.py +0 -0
  245. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_status.py +0 -0
  246. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_subset_enum.py +0 -0
  247. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_table.py +0 -0
  248. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_utils.py +0 -0
  249. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/core/test_watchable_async_status.py +0 -0
  250. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adandor/test_andor.py +0 -0
  251. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adaravis/test_aravis.py +0 -0
  252. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adcore/test_cont_acq_detector.py +0 -0
  253. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adcore/test_detectors.py +0 -0
  254. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adcore/test_scans.py +0 -0
  255. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adcore/test_single_trigger.py +0 -0
  256. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adkinetix/test_kinetix.py +0 -0
  257. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adpilatus/test_pilatus.py +0 -0
  258. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/adsimdetector/test_sim.py +0 -0
  259. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/advimba/test_vimba.py +0 -0
  260. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/conftest.py +0 -0
  261. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/demo/test_epics_demo.py +0 -0
  262. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/eiger/test_odin_io.py +0 -0
  263. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/pvi/test_pvi.py +0 -0
  264. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/signal/test_common.py +0 -0
  265. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/signal/test_signals.py +0 -0
  266. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/signal/test_yaml_save_ca.yaml +0 -0
  267. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/signal/test_yaml_save_pva.yaml +0 -0
  268. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/test_areadetector_subclass_naming.py +0 -0
  269. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/epics/test_motor.py +0 -0
  270. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/eiger/test_eiger_controller.py +0 -0
  271. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/eiger/test_eiger_detector.py +0 -0
  272. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/db/panda.db +0 -0
  273. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/test_hdf_panda.py +0 -0
  274. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/test_panda_connect.py +0 -0
  275. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/test_panda_control.py +0 -0
  276. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/test_panda_utils.py +0 -0
  277. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/test_seq_table.py +0 -0
  278. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/test_trigger.py +0 -0
  279. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/fastcs/panda/test_writer.py +0 -0
  280. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/plan_stubs/test_ensure_connected.py +0 -0
  281. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/plan_stubs/test_fly.py +0 -0
  282. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/plan_stubs/test_settings.py +0 -0
  283. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/plan_stubs/test_setup.py +0 -0
  284. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/sim/__init__.py +0 -0
  285. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/sim/test_sim_blob_detector.py +0 -0
  286. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/sim/test_sim_motor.py +0 -0
  287. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/tango/conftest.py +0 -0
  288. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/tango/context_subprocess.py +0 -0
  289. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/tango/test_base_device.py +0 -0
  290. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/tango/test_tango_signals.py +0 -0
  291. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/tango/test_tango_transport.py +0 -0
  292. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/test_cli.py +0 -0
  293. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/test_data/test_yaml_config_save.yaml +0 -0
  294. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/test_data/test_yaml_save.yaml +0 -0
  295. {ophyd_async-0.10.0a4 → ophyd_async-0.10.1}/tests/test_tutorials.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ophyd-async
3
- Version: 0.10.0a4
3
+ Version: 0.10.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
@@ -43,7 +43,7 @@ Description-Content-Type: text/markdown
43
43
  License-File: LICENSE
44
44
  Requires-Dist: numpy
45
45
  Requires-Dist: bluesky>=1.13.1rc2
46
- Requires-Dist: event-model>=1.22.1
46
+ Requires-Dist: event-model>=1.23
47
47
  Requires-Dist: pyyaml
48
48
  Requires-Dist: colorlog
49
49
  Requires-Dist: pydantic>=2.0
@@ -15,7 +15,7 @@ description = "Asynchronous Bluesky hardware abstraction code, compatible with c
15
15
  dependencies = [
16
16
  "numpy",
17
17
  "bluesky>=1.13.1rc2",
18
- "event-model>=1.22.1",
18
+ "event-model>=1.23",
19
19
  "pyyaml",
20
20
  "colorlog",
21
21
  "pydantic>=2.0",
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.10.0a4'
21
- __version_tuple__ = version_tuple = (0, 10, 0, 'a4')
20
+ __version__ = version = '0.10.1'
21
+ __version_tuple__ = version_tuple = (0, 10, 1)
@@ -248,7 +248,7 @@ def derived_signal_rw(
248
248
  if raw_to_derived_datatype != set_derived_datatype:
249
249
  msg = (
250
250
  f"{raw_to_derived} has datatype {raw_to_derived_datatype} "
251
- f"!= {set_derived_datatype} dataype {set_derived_datatype}"
251
+ f"!= {set_derived_datatype} datatype {set_derived_datatype}"
252
252
  )
253
253
  raise TypeError(msg)
254
254
 
@@ -61,7 +61,7 @@ class Transform(BaseModel, Generic[RawT, DerivedT]):
61
61
  TransformT = TypeVar("TransformT", bound=Transform)
62
62
 
63
63
 
64
- def filter_by_type(raw_devices: Mapping[str, Any], type_: type[T]) -> dict[str, T]:
64
+ def validate_by_type(raw_devices: Mapping[str, Any], type_: type[T]) -> dict[str, T]:
65
65
  filtered_devices: dict[str, T] = {}
66
66
  for name, device in raw_devices.items():
67
67
  if not isinstance(device, type_):
@@ -91,21 +91,23 @@ class SignalTransformer(Generic[TransformT]):
91
91
 
92
92
  @cached_property
93
93
  def raw_locatables(self) -> dict[str, AsyncLocatable]:
94
- return filter_by_type(self._raw_devices, AsyncLocatable)
94
+ return validate_by_type(self._raw_devices, AsyncLocatable)
95
95
 
96
96
  @cached_property
97
97
  def transform_readables(self) -> dict[str, AsyncReadable]:
98
- return filter_by_type(self._transform_devices, AsyncReadable)
98
+ return validate_by_type(self._transform_devices, AsyncReadable)
99
99
 
100
100
  @cached_property
101
101
  def raw_and_transform_readables(self) -> dict[str, AsyncReadable]:
102
- return filter_by_type(
102
+ return validate_by_type(
103
103
  self._raw_devices | self._transform_devices, AsyncReadable
104
104
  )
105
105
 
106
106
  @cached_property
107
107
  def raw_and_transform_subscribables(self) -> dict[str, Subscribable]:
108
- return filter_by_type(self._raw_devices | self._transform_devices, Subscribable)
108
+ return validate_by_type(
109
+ self._raw_devices | self._transform_devices, Subscribable
110
+ )
109
111
 
110
112
  def _complete_cached_reading(self) -> dict[str, Reading] | None:
111
113
  if self._cached_readings and len(self._cached_readings) == len(
@@ -23,7 +23,7 @@ class HDFDatasetDescription(BaseModel):
23
23
  """The dataset name within the HDF file,
24
24
  e.g. /entry/data/data or /entry/instrument/NDAttributes/sum"""
25
25
 
26
- shape: tuple[int, ...] = Field(default_factory=tuple)
26
+ shape: tuple[int | None, ...] = Field(default_factory=tuple)
27
27
  """The shape of a single event's data in the HDF file,
28
28
  e.g. (1, 768, 1024) for arrays or () for scalars"""
29
29
 
@@ -228,5 +228,5 @@ class DatasetDescriber(Protocol):
228
228
  """Return the numpy datatype for this dataset."""
229
229
 
230
230
  @abstractmethod
231
- async def shape(self) -> tuple[int, ...]:
231
+ async def shape(self) -> tuple[int | None, ...]:
232
232
  """Get the shape of the data collection."""
@@ -163,7 +163,12 @@ class _SignalCache(Generic[SignalDatatypeT]):
163
163
  self._notify(function, want_value)
164
164
 
165
165
  def unsubscribe(self, function: Callback) -> bool:
166
- self._listeners.pop(function)
166
+ _listener = self._listeners.pop(function, None)
167
+ if not _listener:
168
+ self._signal.log.warning(
169
+ f"Unsubscribe failed: subscriber {function} was not found "
170
+ f" in listeners list: {list(self._listeners)}"
171
+ )
167
172
  return self._staged or bool(self._listeners)
168
173
 
169
174
  def set_staged(self, staged: bool) -> bool:
@@ -176,7 +176,7 @@ def _datakey_dtype_numpy(
176
176
  raise TypeError(f"Can't make dtype_numpy for {datatype}")
177
177
 
178
178
 
179
- def _datakey_shape(value: SignalDatatype) -> list[int]:
179
+ def _datakey_shape(value: SignalDatatype) -> list[int | None]:
180
180
  if type(value) in _primitive_dtype or isinstance(value, EnumTypes):
181
181
  return []
182
182
  elif isinstance(value, np.ndarray):
@@ -7,6 +7,7 @@ from ophyd_async.core import (
7
7
  DetectorController,
8
8
  DetectorTrigger,
9
9
  TriggerInfo,
10
+ observe_value,
10
11
  set_and_wait_for_value,
11
12
  )
12
13
 
@@ -89,34 +90,57 @@ class ADBaseController(DetectorController, Generic[ADBaseIOT]):
89
90
  self.driver.acquire_period.set(full_frame_time, timeout=timeout),
90
91
  )
91
92
 
92
- async def start_acquiring_driver_and_ensure_status(self) -> AsyncStatus:
93
+ async def start_acquiring_driver_and_ensure_status(
94
+ self,
95
+ start_timeout: float = DEFAULT_TIMEOUT,
96
+ state_timeout: float = DEFAULT_TIMEOUT,
97
+ ) -> AsyncStatus:
93
98
  """Start acquiring driver, raising ValueError if the detector is in a bad state.
94
99
 
95
100
  This sets driver.acquire to True, and waits for it to be True up to a timeout.
96
101
  Then, it checks that the DetectorState PV is in DEFAULT_GOOD_STATES,
97
102
  and otherwise raises a ValueError.
98
103
 
104
+
105
+ :param start_timeout:
106
+ Timeout used for waiting for the driver to start
107
+ acquiring.
108
+ :param state_timeout:
109
+ Timeout used for waiting for the detector to be in a good
110
+ state after it stops acquiring.
99
111
  :returns AsyncStatus:
100
112
  An AsyncStatus that can be awaited to set driver.acquire to True and perform
101
113
  subsequent raising (if applicable) due to detector state.
114
+
102
115
  """
103
116
  status = await set_and_wait_for_value(
104
117
  self.driver.acquire,
105
118
  True,
106
- timeout=DEFAULT_TIMEOUT,
119
+ timeout=start_timeout,
107
120
  wait_for_set_completion=False,
108
121
  )
109
122
 
110
123
  async def complete_acquisition() -> None:
111
- # NOTE: possible race condition here between the callback from
112
- # set_and_wait_for_value and the detector state updating.
113
124
  await status
114
- state = await self.driver.detector_state.get_value()
115
- if state not in self.good_states:
116
- raise ValueError(
117
- f"Final detector state {state.value} not "
118
- "in valid end states: {self.good_states}"
119
- )
125
+ state = None
126
+ try:
127
+ async for state in observe_value(
128
+ self.driver.detector_state, done_timeout=state_timeout
129
+ ):
130
+ if state in self.good_states:
131
+ return
132
+ except asyncio.TimeoutError as exc:
133
+ if state is not None:
134
+ raise ValueError(
135
+ f"Final detector state {state.value} not in valid end "
136
+ f"states: {self.good_states}"
137
+ ) from exc
138
+ else:
139
+ # No updates from the detector, something else is wrong
140
+ raise asyncio.TimeoutError(
141
+ "Could not monitor detector state: "
142
+ + self.driver.detector_state.source
143
+ ) from exc
120
144
 
121
145
  return AsyncStatus(complete_acquisition())
122
146
 
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  from collections.abc import AsyncIterator
3
3
  from pathlib import Path
4
+ from typing import TypeGuard
4
5
  from xml.etree import ElementTree as ET
5
6
 
6
7
  from bluesky.protocols import StreamAsset
@@ -22,6 +23,10 @@ from ._utils import (
22
23
  )
23
24
 
24
25
 
26
+ def _is_fully_described(shape: tuple[int | None, ...]) -> TypeGuard[tuple[int, ...]]:
27
+ return None not in shape
28
+
29
+
25
30
  class ADHDFWriter(ADWriter[NDFileHDFIO]):
26
31
  """Allow `NDFileHDFIO` to be used within `StandardDetector`."""
27
32
 
@@ -75,6 +80,16 @@ class ADHDFWriter(ADWriter[NDFileHDFIO]):
75
80
  # Determine number of frames that will be saved per HDF chunk
76
81
  frames_per_chunk = await self.fileio.num_frames_chunks.get_value()
77
82
 
83
+ if not _is_fully_described(detector_shape):
84
+ # Questions:
85
+ # - Can AreaDetector support this?
86
+ # - How to deal with chunking?
87
+ # Don't support for now - leave option open to support it later
88
+ raise ValueError(
89
+ "Datasets with partially unknown dimensionality "
90
+ "are not currently supported by ADHDFWriter."
91
+ )
92
+
78
93
  # Add the main data
79
94
  self._datasets = [
80
95
  HDFDatasetDescription(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ophyd-async
3
- Version: 0.10.0a4
3
+ Version: 0.10.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
@@ -43,7 +43,7 @@ Description-Content-Type: text/markdown
43
43
  License-File: LICENSE
44
44
  Requires-Dist: numpy
45
45
  Requires-Dist: bluesky>=1.13.1rc2
46
- Requires-Dist: event-model>=1.22.1
46
+ Requires-Dist: event-model>=1.23
47
47
  Requires-Dist: pyyaml
48
48
  Requires-Dist: colorlog
49
49
  Requires-Dist: pydantic>=2.0
@@ -1,6 +1,6 @@
1
1
  numpy
2
2
  bluesky>=1.13.1rc2
3
- event-model>=1.22.1
3
+ event-model>=1.23
4
4
  pyyaml
5
5
  colorlog
6
6
  pydantic>=2.0
@@ -8,6 +8,9 @@ from bluesky.protocols import Reading
8
8
 
9
9
  from ophyd_async.core import (
10
10
  DerivedSignalFactory,
11
+ SignalRW,
12
+ Table,
13
+ derived_signal_rw,
11
14
  soft_signal_rw,
12
15
  )
13
16
  from ophyd_async.sim import (
@@ -22,6 +25,7 @@ from ophyd_async.testing import (
22
25
  assert_reading,
23
26
  assert_value,
24
27
  get_mock,
28
+ set_mock_value,
25
29
  )
26
30
 
27
31
 
@@ -131,3 +135,55 @@ def test_mismatching_args():
131
135
  jack22=soft_signal_rw(float),
132
136
  distance=soft_signal_rw(float),
133
137
  )
138
+
139
+
140
+ @pytest.fixture
141
+ def derived_signal() -> SignalRW[float]:
142
+ signal_r = soft_signal_rw(int, initial_value=4)
143
+
144
+ def _get(ts: int) -> float:
145
+ return ts
146
+
147
+ async def _put(value: float) -> None:
148
+ pass
149
+
150
+ return derived_signal_rw(_get, _put, ts=signal_r)
151
+
152
+
153
+ async def test_derived_signal_backend_connect_pass(
154
+ derived_signal: SignalRW,
155
+ ):
156
+ result = await derived_signal.connect()
157
+ assert result is None
158
+
159
+
160
+ async def test_derived_signal_backend_set_value(
161
+ derived_signal: SignalRW,
162
+ ) -> None:
163
+ await derived_signal.connect(mock=True)
164
+ with pytest.raises(RuntimeError):
165
+ set_mock_value(derived_signal, 1.0)
166
+
167
+
168
+ async def test_derived_signal_backend_put_wait_fails(
169
+ derived_signal: SignalRW,
170
+ ) -> None:
171
+ with pytest.raises(RuntimeError):
172
+ await derived_signal.set(value=None, wait=False)
173
+ with pytest.raises(RuntimeError):
174
+ await derived_signal.set(value=None, wait=True)
175
+
176
+
177
+ def test_make_rw_signal_type_mismatch():
178
+ factory = DerivedSignalFactory(
179
+ TwoJackTransform,
180
+ set_derived=None,
181
+ distance=soft_signal_rw(float),
182
+ jack1=soft_signal_rw(float),
183
+ jack2=soft_signal_rw(float),
184
+ )
185
+ with pytest.raises(
186
+ ValueError,
187
+ match=re.escape("Must define a set_derived method to support derived"),
188
+ ):
189
+ factory.derived_signal_rw(datatype=Table, name="")
@@ -1013,3 +1013,9 @@ async def test_notify_runtime_error(signal_cache: _SignalCache[Any]) -> None:
1013
1013
  def test_signal_backend_throws_type_error() -> None:
1014
1014
  with pytest.raises(TypeError, match="Unsupported protocol: XYZ"):
1015
1015
  get_signal_backend_type("XYZ") # type: ignore
1016
+
1017
+
1018
+ def test_remove_non_existing_listener():
1019
+ signal_rw = soft_signal_rw(int, initial_value=4)
1020
+ cbs = []
1021
+ assert signal_rw.clear_sub(cbs.append) is None
@@ -1,12 +1,18 @@
1
1
  import asyncio
2
2
  import re
3
- from unittest.mock import call
3
+ from unittest.mock import MagicMock, call, patch
4
4
 
5
5
  import pytest
6
+ from bluesky.protocols import Reading, Subscribable
6
7
 
7
8
  from ophyd_async.core import (
9
+ Callback,
10
+ Signal,
11
+ SignalBackend,
12
+ SignalDatatype,
8
13
  derived_signal_r,
9
14
  derived_signal_rw,
15
+ derived_signal_w,
10
16
  soft_signal_r_and_setter,
11
17
  soft_signal_rw,
12
18
  )
@@ -22,6 +28,16 @@ from ophyd_async.testing import (
22
28
  )
23
29
 
24
30
 
31
+ @pytest.fixture
32
+ def movable_beamstop() -> MovableBeamstop:
33
+ return MovableBeamstop("device")
34
+
35
+
36
+ @pytest.fixture
37
+ def readonly_beamstop() -> ReadOnlyBeamstop:
38
+ return ReadOnlyBeamstop("device")
39
+
40
+
25
41
  def _get_position(foo: float, bar: float) -> BeamstopPosition:
26
42
  if abs(foo) < 1 and abs(bar) < 2:
27
43
  return BeamstopPosition.IN_POSITION
@@ -137,14 +153,100 @@ def test_mismatching_args_and_types(func, expected_msg, args):
137
153
  derived_signal_r(func, **args)
138
154
 
139
155
 
156
+ def _get(ts: int) -> float:
157
+ return ts
158
+
159
+
160
+ async def _put(value: float) -> None:
161
+ pass
162
+
163
+
164
+ @pytest.fixture
165
+ def derived_signal_backend() -> SignalBackend[SignalDatatype]:
166
+ signal_rw = soft_signal_rw(int, initial_value=4)
167
+ derived = derived_signal_rw(_get, _put, ts=signal_rw)
168
+ return derived._connector.backend
169
+
170
+
140
171
  async def test_derived_signal_rw_works_with_signal_r():
141
172
  signal_r, _ = soft_signal_r_and_setter(int, initial_value=4)
173
+ derived = derived_signal_rw(_get, _put, ts=signal_r)
174
+ assert await derived.get_value() == 4
175
+
142
176
 
143
- def _get(ts: int) -> float:
177
+ async def test_validate_by_type(derived_signal_backend: SignalBackend):
178
+ def float_get(ts: float) -> float:
144
179
  return ts
145
180
 
146
- async def _put(value: float) -> None:
147
- pass
181
+ with pytest.raises(TypeError, match=re.escape(" is not an instance of")):
182
+ derived_signal_rw(float_get, _put, ts=Signal(derived_signal_backend))
148
183
 
149
- derived = derived_signal_rw(_get, _put, ts=signal_r)
150
- assert await derived.get_value() == 4
184
+
185
+ async def test_set_derived_not_initialized():
186
+ sig = derived_signal_r(_get, ts=soft_signal_rw(int, initial_value=4))
187
+ with pytest.raises(
188
+ RuntimeError,
189
+ match="Cannot put as no set_derived method given",
190
+ ):
191
+ await sig._connector.backend.put(1.0, True)
192
+
193
+
194
+ async def test_derived_update_cached_reading_not_initialized(
195
+ derived_signal_backend: SignalBackend,
196
+ ):
197
+ class test_cls(Subscribable):
198
+ def subscribe(self, function: Callback) -> None:
199
+ pass
200
+
201
+ def clear_sub(self, function: Callback) -> None:
202
+ function("")
203
+
204
+ @property
205
+ def name(self) -> str:
206
+ return ""
207
+
208
+ with patch.object(
209
+ derived_signal_backend.transformer, # type: ignore
210
+ "raw_and_transform_subscribables",
211
+ {"raw_device": test_cls()},
212
+ ):
213
+ with pytest.raises(
214
+ RuntimeError,
215
+ match=re.escape(
216
+ "Cannot update cached reading as it has not been initialised"
217
+ ),
218
+ ): # noqa: E501
219
+ derived_signal_backend.set_callback(None)
220
+
221
+
222
+ async def test_set_derived_callback_already_set(derived_signal_backend: SignalBackend):
223
+ mock_callback = MagicMock(Callback[Reading])
224
+ derived_signal_backend.set_callback(mock_callback)
225
+ with pytest.raises(RuntimeError, match=re.escape("Callback already set for")):
226
+ derived_signal_backend.set_callback(mock_callback)
227
+
228
+
229
+ @patch("ophyd_async.core._derived_signal.get_type_hints", return_value={})
230
+ def test_get_return_datatype_no_type(movable_beamstop: MovableBeamstop):
231
+ with pytest.raises(
232
+ TypeError, match=re.escape("does not have a type hint for it's return value")
233
+ ):
234
+ derived_signal_r(movable_beamstop._get_position)
235
+
236
+
237
+ @patch("ophyd_async.core._derived_signal.get_type_hints", return_value={})
238
+ def test_get_first_arg_datatype_no_type(movable_beamstop: MovableBeamstop):
239
+ with pytest.raises(
240
+ TypeError, match=re.escape("does not have a type hinted argument")
241
+ ):
242
+ derived_signal_w(movable_beamstop._set_from_position)
243
+
244
+
245
+ def test_derived_signal_rw_type_error(movable_beamstop: MovableBeamstop):
246
+ with patch.object(
247
+ movable_beamstop, "_set_from_position", movable_beamstop._get_position
248
+ ): # noqa: E501
249
+ with pytest.raises(TypeError):
250
+ derived_signal_rw(
251
+ movable_beamstop._get_position, movable_beamstop._set_from_position
252
+ ) # noqa: E501
@@ -68,7 +68,6 @@ async def test_start_acquiring_driver_and_ensure_status_flags_immediate_failure(
68
68
  await acquiring
69
69
 
70
70
 
71
- @patch("ophyd_async.core._detector.DEFAULT_TIMEOUT", 0.2)
72
71
  async def test_start_acquiring_driver_and_ensure_status_fails_after_some_time(
73
72
  controller: adsimdetector.SimController,
74
73
  ):
@@ -87,9 +86,62 @@ async def test_start_acquiring_driver_and_ensure_status_fails_after_some_time(
87
86
 
88
87
  controller.frame_timeout = 0.1
89
88
 
90
- acquiring = await controller.start_acquiring_driver_and_ensure_status()
89
+ acquiring = await controller.start_acquiring_driver_and_ensure_status(
90
+ start_timeout=0.2, state_timeout=0.2
91
+ )
91
92
 
92
93
  with pytest.raises(
93
94
  ValueError, match="Final detector state Disconnected not in valid end states:"
94
95
  ):
95
96
  await acquiring
97
+
98
+
99
+ async def test_start_acquiring_driver_and_ensure_status_timing(
100
+ controller: adsimdetector.SimController,
101
+ ):
102
+ """This test ensures the camera has time to return to a good state.
103
+
104
+ Real world application; there is race condition wherein the
105
+ detector has been asked to complete acquisition, but has not yet
106
+ returned to a known good state before the status check.
107
+
108
+ """
109
+ set_mock_value(controller.driver.detector_state, adcore.ADState.ACQUIRE)
110
+
111
+ acquiring = await controller.start_acquiring_driver_and_ensure_status(
112
+ start_timeout=0.2, state_timeout=0.2
113
+ )
114
+
115
+ async def complete_acquire():
116
+ """Return to idle state, but pretend the detector is slow."""
117
+ await asyncio.sleep(0.05)
118
+ set_mock_value(controller.driver.detector_state, adcore.ADState.IDLE)
119
+
120
+ await asyncio.gather(acquiring, complete_acquire())
121
+
122
+
123
+ async def bad_observe_value(*args, **kwargs):
124
+ "Stub to simulate a disconnected ``observe_value()``."
125
+ if True:
126
+ raise asyncio.TimeoutError()
127
+ yield None # Make it a generator
128
+
129
+
130
+ @patch("ophyd_async.epics.adcore._core_logic.observe_value", bad_observe_value)
131
+ async def test_start_acquiring_driver_and_ensure_status_disconnected(
132
+ controller: adsimdetector.SimController,
133
+ ):
134
+ """This test ensures the function behaves gracefully if no detector
135
+ states are available.
136
+
137
+ """
138
+ acquiring = await controller.start_acquiring_driver_and_ensure_status(
139
+ start_timeout=0.2, state_timeout=0.2
140
+ )
141
+
142
+ with pytest.raises(asyncio.TimeoutError) as exc:
143
+ await acquiring
144
+ assert (
145
+ str(exc.value)
146
+ == "Could not monitor detector state: mock+ca://DRV:DetectorState_RBV"
147
+ )
@@ -296,3 +296,19 @@ async def test_nd_attributes_plan_stub_gives_correct_error(RE, detectors):
296
296
  == f"Invalid type for ndattributes: {type(invalidObjects[0])}. "
297
297
  + "Expected NDAttributePv or NDAttributeParam."
298
298
  )
299
+
300
+
301
+ async def test_hdf_writer_descriptor_shape_contains_none(
302
+ hdf_writer: adcore.ADHDFWriter,
303
+ ):
304
+ async def shape_containing_none():
305
+ return 10, None, 10
306
+
307
+ hdf_writer._dataset_describer.shape = shape_containing_none
308
+
309
+ with pytest.raises(
310
+ ValueError,
311
+ match=r"Datasets with partially unknown dimensionality "
312
+ r"are not currently supported by ADHDFWriter.",
313
+ ):
314
+ await hdf_writer.open(DETECTOR_NAME)
File without changes
File without changes
File without changes
File without changes