ophyd-async 0.9.0a2__py3-none-any.whl → 0.10.0a1__py3-none-any.whl

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 (151) hide show
  1. ophyd_async/__init__.py +5 -8
  2. ophyd_async/_docs_parser.py +12 -0
  3. ophyd_async/_version.py +9 -4
  4. ophyd_async/core/__init__.py +97 -62
  5. ophyd_async/core/_derived_signal.py +271 -0
  6. ophyd_async/core/_derived_signal_backend.py +300 -0
  7. ophyd_async/core/_detector.py +106 -125
  8. ophyd_async/core/_device.py +69 -63
  9. ophyd_async/core/_device_filler.py +65 -1
  10. ophyd_async/core/_flyer.py +14 -5
  11. ophyd_async/core/_hdf_dataset.py +29 -22
  12. ophyd_async/core/_log.py +14 -23
  13. ophyd_async/core/_mock_signal_backend.py +11 -3
  14. ophyd_async/core/_protocol.py +65 -45
  15. ophyd_async/core/_providers.py +28 -9
  16. ophyd_async/core/_readable.py +44 -35
  17. ophyd_async/core/_settings.py +36 -27
  18. ophyd_async/core/_signal.py +262 -170
  19. ophyd_async/core/_signal_backend.py +56 -13
  20. ophyd_async/core/_soft_signal_backend.py +16 -11
  21. ophyd_async/core/_status.py +72 -24
  22. ophyd_async/core/_table.py +37 -8
  23. ophyd_async/core/_utils.py +96 -49
  24. ophyd_async/core/_yaml_settings.py +2 -0
  25. ophyd_async/epics/__init__.py +1 -0
  26. ophyd_async/epics/adandor/_andor.py +2 -2
  27. ophyd_async/epics/adandor/_andor_controller.py +4 -2
  28. ophyd_async/epics/adandor/_andor_io.py +2 -4
  29. ophyd_async/epics/adaravis/__init__.py +5 -0
  30. ophyd_async/epics/adaravis/_aravis.py +4 -8
  31. ophyd_async/epics/adaravis/_aravis_controller.py +20 -43
  32. ophyd_async/epics/adaravis/_aravis_io.py +13 -28
  33. ophyd_async/epics/adcore/__init__.py +23 -8
  34. ophyd_async/epics/adcore/_core_detector.py +42 -2
  35. ophyd_async/epics/adcore/_core_io.py +124 -99
  36. ophyd_async/epics/adcore/_core_logic.py +106 -27
  37. ophyd_async/epics/adcore/_core_writer.py +12 -8
  38. ophyd_async/epics/adcore/_hdf_writer.py +21 -38
  39. ophyd_async/epics/adcore/_single_trigger.py +2 -2
  40. ophyd_async/epics/adcore/_utils.py +2 -2
  41. ophyd_async/epics/adkinetix/__init__.py +2 -1
  42. ophyd_async/epics/adkinetix/_kinetix.py +3 -3
  43. ophyd_async/epics/adkinetix/_kinetix_controller.py +4 -2
  44. ophyd_async/epics/adkinetix/_kinetix_io.py +12 -13
  45. ophyd_async/epics/adpilatus/__init__.py +5 -0
  46. ophyd_async/epics/adpilatus/_pilatus.py +1 -1
  47. ophyd_async/epics/adpilatus/_pilatus_controller.py +5 -24
  48. ophyd_async/epics/adpilatus/_pilatus_io.py +11 -9
  49. ophyd_async/epics/adsimdetector/__init__.py +8 -1
  50. ophyd_async/epics/adsimdetector/_sim.py +4 -14
  51. ophyd_async/epics/adsimdetector/_sim_controller.py +17 -0
  52. ophyd_async/epics/adsimdetector/_sim_io.py +10 -0
  53. ophyd_async/epics/advimba/__init__.py +10 -1
  54. ophyd_async/epics/advimba/_vimba.py +3 -2
  55. ophyd_async/epics/advimba/_vimba_controller.py +4 -2
  56. ophyd_async/epics/advimba/_vimba_io.py +23 -28
  57. ophyd_async/epics/core/_aioca.py +35 -16
  58. ophyd_async/epics/core/_epics_connector.py +4 -0
  59. ophyd_async/epics/core/_epics_device.py +2 -0
  60. ophyd_async/epics/core/_p4p.py +10 -2
  61. ophyd_async/epics/core/_pvi_connector.py +65 -8
  62. ophyd_async/epics/core/_signal.py +51 -51
  63. ophyd_async/epics/core/_util.py +4 -4
  64. ophyd_async/epics/demo/__init__.py +16 -0
  65. ophyd_async/epics/demo/__main__.py +31 -0
  66. ophyd_async/epics/demo/_ioc.py +32 -0
  67. ophyd_async/epics/demo/_motor.py +82 -0
  68. ophyd_async/epics/demo/_point_detector.py +42 -0
  69. ophyd_async/epics/demo/_point_detector_channel.py +22 -0
  70. ophyd_async/epics/demo/_stage.py +15 -0
  71. ophyd_async/epics/{sim/mover.db → demo/motor.db} +2 -1
  72. ophyd_async/epics/demo/point_detector.db +59 -0
  73. ophyd_async/epics/demo/point_detector_channel.db +21 -0
  74. ophyd_async/epics/eiger/_eiger.py +1 -3
  75. ophyd_async/epics/eiger/_eiger_controller.py +11 -4
  76. ophyd_async/epics/eiger/_eiger_io.py +2 -0
  77. ophyd_async/epics/eiger/_odin_io.py +1 -2
  78. ophyd_async/epics/motor.py +65 -28
  79. ophyd_async/epics/signal.py +4 -1
  80. ophyd_async/epics/testing/_example_ioc.py +21 -9
  81. ophyd_async/epics/testing/_utils.py +3 -0
  82. ophyd_async/epics/testing/test_records.db +8 -0
  83. ophyd_async/epics/testing/test_records_pva.db +17 -16
  84. ophyd_async/fastcs/__init__.py +1 -0
  85. ophyd_async/fastcs/core.py +6 -0
  86. ophyd_async/fastcs/odin/__init__.py +1 -0
  87. ophyd_async/fastcs/panda/__init__.py +8 -6
  88. ophyd_async/fastcs/panda/_block.py +29 -9
  89. ophyd_async/fastcs/panda/_control.py +5 -0
  90. ophyd_async/fastcs/panda/_hdf_panda.py +2 -0
  91. ophyd_async/fastcs/panda/_table.py +9 -6
  92. ophyd_async/fastcs/panda/_trigger.py +23 -9
  93. ophyd_async/fastcs/panda/_writer.py +27 -30
  94. ophyd_async/plan_stubs/__init__.py +2 -0
  95. ophyd_async/plan_stubs/_ensure_connected.py +1 -0
  96. ophyd_async/plan_stubs/_fly.py +2 -4
  97. ophyd_async/plan_stubs/_nd_attributes.py +2 -0
  98. ophyd_async/plan_stubs/_panda.py +1 -0
  99. ophyd_async/plan_stubs/_settings.py +43 -16
  100. ophyd_async/plan_stubs/_utils.py +3 -0
  101. ophyd_async/plan_stubs/_wait_for_awaitable.py +1 -1
  102. ophyd_async/sim/__init__.py +24 -14
  103. ophyd_async/sim/__main__.py +43 -0
  104. ophyd_async/sim/_blob_detector.py +33 -0
  105. ophyd_async/sim/_blob_detector_controller.py +48 -0
  106. ophyd_async/sim/_blob_detector_writer.py +105 -0
  107. ophyd_async/sim/_mirror_horizontal.py +46 -0
  108. ophyd_async/sim/_mirror_vertical.py +74 -0
  109. ophyd_async/sim/_motor.py +233 -0
  110. ophyd_async/sim/_pattern_generator.py +124 -0
  111. ophyd_async/sim/_point_detector.py +86 -0
  112. ophyd_async/sim/_stage.py +19 -0
  113. ophyd_async/tango/__init__.py +1 -0
  114. ophyd_async/tango/core/__init__.py +6 -1
  115. ophyd_async/tango/core/_base_device.py +41 -33
  116. ophyd_async/tango/core/_converters.py +81 -0
  117. ophyd_async/tango/core/_signal.py +18 -32
  118. ophyd_async/tango/core/_tango_readable.py +2 -19
  119. ophyd_async/tango/core/_tango_transport.py +136 -60
  120. ophyd_async/tango/core/_utils.py +47 -0
  121. ophyd_async/tango/{sim → demo}/_counter.py +2 -0
  122. ophyd_async/tango/{sim → demo}/_detector.py +2 -0
  123. ophyd_async/tango/{sim → demo}/_mover.py +5 -4
  124. ophyd_async/tango/{sim → demo}/_tango/_servers.py +4 -0
  125. ophyd_async/tango/testing/__init__.py +6 -0
  126. ophyd_async/tango/testing/_one_of_everything.py +200 -0
  127. ophyd_async/testing/__init__.py +29 -7
  128. ophyd_async/testing/_assert.py +137 -81
  129. ophyd_async/testing/_mock_signal_utils.py +56 -70
  130. ophyd_async/testing/_one_of_everything.py +41 -21
  131. ophyd_async/testing/_single_derived.py +87 -0
  132. ophyd_async/testing/_utils.py +3 -0
  133. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a1.dist-info}/METADATA +25 -26
  134. ophyd_async-0.10.0a1.dist-info/RECORD +149 -0
  135. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a1.dist-info}/WHEEL +1 -1
  136. ophyd_async/epics/sim/__init__.py +0 -54
  137. ophyd_async/epics/sim/_ioc.py +0 -29
  138. ophyd_async/epics/sim/_mover.py +0 -101
  139. ophyd_async/epics/sim/_sensor.py +0 -37
  140. ophyd_async/epics/sim/sensor.db +0 -19
  141. ophyd_async/sim/_pattern_detector/__init__.py +0 -13
  142. ophyd_async/sim/_pattern_detector/_pattern_detector.py +0 -42
  143. ophyd_async/sim/_pattern_detector/_pattern_detector_controller.py +0 -69
  144. ophyd_async/sim/_pattern_detector/_pattern_detector_writer.py +0 -41
  145. ophyd_async/sim/_pattern_detector/_pattern_generator.py +0 -214
  146. ophyd_async/sim/_sim_motor.py +0 -107
  147. ophyd_async-0.9.0a2.dist-info/RECORD +0 -129
  148. /ophyd_async/tango/{sim → demo}/__init__.py +0 -0
  149. /ophyd_async/tango/{sim → demo}/_tango/__init__.py +0 -0
  150. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a1.dist-info/licenses}/LICENSE +0 -0
  151. {ophyd_async-0.9.0a2.dist-info → ophyd_async-0.10.0a1.dist-info}/top_level.txt +0 -0
@@ -10,8 +10,7 @@ from typing import Protocol
10
10
 
11
11
  @dataclass
12
12
  class PathInfo:
13
- """
14
- Information about where and how to write a file.
13
+ """Information about where and how to write a file.
15
14
 
16
15
  :param directory_path: Directory into which files should be written
17
16
  :param filename: Base filename to use generated by FilenameProvider, w/o extension
@@ -25,18 +24,24 @@ class PathInfo:
25
24
 
26
25
 
27
26
  class FilenameProvider(Protocol):
27
+ """Base class for callable classes providing filenames."""
28
+
28
29
  @abstractmethod
29
30
  def __call__(self, device_name: str | None = None) -> str:
30
- """Get a filename to use for output data, w/o extension"""
31
+ """Get a filename to use for output data, w/o extension."""
31
32
 
32
33
 
33
34
  class PathProvider(Protocol):
35
+ """Abstract class that tells a detector where to write its data."""
36
+
34
37
  @abstractmethod
35
38
  def __call__(self, device_name: str | None = None) -> PathInfo:
36
- """Get the current directory to write files into"""
39
+ """Get the current directory to write files into."""
37
40
 
38
41
 
39
42
  class StaticFilenameProvider(FilenameProvider):
43
+ """Provides a constant filename on every call."""
44
+
40
45
  def __init__(self, filename: str):
41
46
  self._static_filename = filename
42
47
 
@@ -45,6 +50,8 @@ class StaticFilenameProvider(FilenameProvider):
45
50
 
46
51
 
47
52
  class UUIDFilenameProvider(FilenameProvider):
53
+ """Files will have a UUID as a filename."""
54
+
48
55
  def __init__(
49
56
  self,
50
57
  uuid_call_func: Callable = uuid.uuid4,
@@ -68,6 +75,8 @@ class UUIDFilenameProvider(FilenameProvider):
68
75
 
69
76
 
70
77
  class AutoIncrementFilenameProvider(FilenameProvider):
78
+ """Provides a new numerically incremented filename on each call."""
79
+
71
80
  def __init__(
72
81
  self,
73
82
  base_filename: str = "",
@@ -98,14 +107,16 @@ class AutoIncrementFilenameProvider(FilenameProvider):
98
107
 
99
108
 
100
109
  class StaticPathProvider(PathProvider):
110
+ """All files will be within a static directory."""
111
+
101
112
  def __init__(
102
113
  self,
103
114
  filename_provider: FilenameProvider,
104
- directory_path: Path,
115
+ directory_path: Path | str,
105
116
  create_dir_depth: int = 0,
106
117
  ) -> None:
107
118
  self._filename_provider = filename_provider
108
- self._directory_path = directory_path
119
+ self._directory_path = Path(directory_path)
109
120
  self._create_dir_depth = create_dir_depth
110
121
 
111
122
  def __call__(self, device_name: str | None = None) -> PathInfo:
@@ -119,6 +130,8 @@ class StaticPathProvider(PathProvider):
119
130
 
120
131
 
121
132
  class AutoIncrementingPathProvider(PathProvider):
133
+ """Provides a new numerically incremented path on each call."""
134
+
122
135
  def __init__(
123
136
  self,
124
137
  filename_provider: FilenameProvider,
@@ -169,6 +182,8 @@ class AutoIncrementingPathProvider(PathProvider):
169
182
 
170
183
 
171
184
  class YMDPathProvider(PathProvider):
185
+ """Provides a path with the date included in the directory name."""
186
+
172
187
  def __init__(
173
188
  self,
174
189
  filename_provider: FilenameProvider,
@@ -206,16 +221,20 @@ class YMDPathProvider(PathProvider):
206
221
 
207
222
 
208
223
  class NameProvider(Protocol):
224
+ """Base class for callable classes providing data keys."""
225
+
209
226
  @abstractmethod
210
227
  def __call__(self) -> str:
211
- """Get the name to be used as a data_key in the descriptor document"""
228
+ """Get the name to be used as a data_key in the descriptor document."""
212
229
 
213
230
 
214
231
  class DatasetDescriber(Protocol):
232
+ """For describing datasets in file writing."""
233
+
215
234
  @abstractmethod
216
235
  async def np_datatype(self) -> str:
217
- """Represents the numpy datatype"""
236
+ """Return the numpy datatype for this dataset."""
218
237
 
219
238
  @abstractmethod
220
239
  async def shape(self) -> tuple[int, ...]:
221
- """Get the shape of the data collection"""
240
+ """Get the shape of the data collection."""
@@ -17,25 +17,34 @@ from ._utils import merge_gathered_dicts
17
17
  class StandardReadableFormat(Enum):
18
18
  """Declare how a `Device` should contribute to the `StandardReadable` verbs."""
19
19
 
20
- #: Detect which verbs the child supports and contribute to:
21
- #:
22
- #: - ``read()``, ``describe()`` if it is `bluesky.protocols.Readable`
23
- #: - ``read_configuration()``, ``describe_configuration()`` if it is
24
- #: `bluesky.protocols.Configurable`
25
- #: - ``stage()``, ``unstage()`` if it is `bluesky.protocols.Stageable`
26
- #: - ``hints`` if it `bluesky.protocols.HasHints`
27
20
  CHILD = "CHILD"
28
- #: Contribute the `Signal` value to ``read_configuration()`` and
29
- #: ``describe_configuration()``
21
+ """Detect which verbs the child supports and contribute to:
22
+
23
+ - `read()`, `describe()` if it is [](#bluesky.protocols.Readable)
24
+ - `read_configuration()`, `describe_configuration()` if it is
25
+ [](#bluesky.protocols.Configurable)
26
+ - `stage()`, `unstage()` if it is [](#bluesky.protocols.Stageable)
27
+ - `hints` if it [](#bluesky.protocols.HasHints)
28
+ """
29
+
30
30
  CONFIG_SIGNAL = "CONFIG_SIGNAL"
31
- #: Contribute the monitored `Signal` value to ``read()`` and ``describe()``` and
32
- #: put the signal name in ``hints``
31
+ """Contribute the `Signal` value to `read_configuration()` and
32
+ `describe_configuration()`
33
+ """
34
+
33
35
  HINTED_SIGNAL = "HINTED_SIGNAL"
34
- #: Contribute the uncached `Signal` value to ``read()`` and ``describe()```
36
+ """Contribute the monitored `Signal` value to `read()` and `describe()` and
37
+ put the signal name in `hints`
38
+ """
39
+
35
40
  UNCACHED_SIGNAL = "UNCACHED_SIGNAL"
36
- #: Contribute the uncached `Signal` value to ``read()`` and ``describe()``` and
37
- #: put the signal name in ``hints``
41
+ """Contribute the uncached `Signal` value to `read()` and `describe()`
42
+ """
43
+
38
44
  HINTED_UNCACHED_SIGNAL = "HINTED_UNCACHED_SIGNAL"
45
+ """Contribute the uncached `Signal` value to `read()` and `describe()` and
46
+ put the signal name in `hints`
47
+ """
39
48
 
40
49
  def __call__(self, parent: Device, child: Device):
41
50
  if not isinstance(parent, StandardReadable):
@@ -74,11 +83,15 @@ HintedSignal.uncached = _compat_format(
74
83
  class StandardReadable(
75
84
  Device, AsyncReadable, AsyncConfigurable, AsyncStageable, HasHints
76
85
  ):
77
- """Device that owns its children and provides useful default behavior.
86
+ """Device that provides selected child Device values in `read()`.
78
87
 
79
- - When its name is set it renames child Devices
80
- - Signals can be registered for read() and read_configuration()
81
- - These signals will be subscribed for read() between stage() and unstage()
88
+ Provides the ability for children to be registered to:
89
+ - Participate in `stage()` and `unstage()`
90
+ - Provide their value in `read()` and `describe()
91
+ - Provide their value in `read_configuration()` and `describe_configuration()
92
+ - Select a value to appear in `hints`
93
+
94
+ The behavior is customized with a [](#StandardReadableFormat)
82
95
  """
83
96
 
84
97
  # These must be immutable types to avoid accidental sharing between
@@ -119,7 +132,7 @@ class StandardReadable(
119
132
  hints: Hints = {}
120
133
  for new_hint in self._has_hints:
121
134
  # Merge the existing and new hints, based on the type of the value.
122
- # This avoids default dict merge behaviour that overrides the values;
135
+ # This avoids default dict merge behavior that overrides the values;
123
136
  # we want to combine them when they are Sequences, and ensure they are
124
137
  # identical when string values.
125
138
  for key, value in new_hint.hints.items():
@@ -156,13 +169,12 @@ class StandardReadable(
156
169
  self,
157
170
  format: StandardReadableFormat = StandardReadableFormat.CHILD,
158
171
  ) -> Generator[None, None, None]:
159
- """Context manager that calls `add_readables` on child Devices added within.
172
+ """Context manager that calls [](#add_readables) on child Devices added within.
160
173
 
161
- Scans ``self.children()`` on entry and exit to context manager, and calls
162
- `add_readables` on any that are added with the provided
174
+ Scans `self.children()` on entry and exit to context manager, and calls
175
+ `add_readables()` on any that are added with the provided
163
176
  `StandardReadableFormat`.
164
177
  """
165
-
166
178
  dict_copy = dict(self.children())
167
179
 
168
180
  yield
@@ -192,18 +204,15 @@ class StandardReadable(
192
204
  Use output from the given devices to contribute to the verbs of the following
193
205
  interfaces:
194
206
 
195
- - `bluesky.protocols.Readable`
196
- - `bluesky.protocols.Configurable`
197
- - `bluesky.protocols.Stageable`
198
- - `bluesky.protocols.HasHints`
199
-
200
- Parameters
201
- ----------
202
- devices:
203
- The devices to be added
204
- format:
205
- Determines which of the devices functions are added to which verb as per the
206
- `StandardReadableFormat` documentation
207
+ - [](#bluesky.protocols.Readable)
208
+ - [](#bluesky.protocols.Configurable)
209
+ - [](#bluesky.protocols.Stageable)
210
+ - [](#bluesky.protocols.HasHints)
211
+
212
+ :param devices: The devices to be added
213
+ :param format:
214
+ Determines which of the devices functions are added to which verb as
215
+ per the [](#StandardReadableFormat) documentation
207
216
  """
208
217
 
209
218
  def assert_device_is_signalr(device: Device) -> SignalR:
@@ -10,6 +10,28 @@ from ._signal_backend import SignalDatatypeT
10
10
 
11
11
 
12
12
  class Settings(MutableMapping[SignalRW[Any], Any], Generic[DeviceT]):
13
+ """Used for supplying settings to signals.
14
+
15
+ :param device: The device that the settings are for.
16
+ :param settings: A dictionary of settings to start with.
17
+
18
+ :example:
19
+ ```python
20
+ # Settings are created from a dict of signals to values
21
+ settings1 = Settings(device, {device.sig1: 1, device.sig2: 2})
22
+ settings2 = Settings(device, {device.sig1: 10, device.sig3: 3})
23
+ # They act like a dictionaries
24
+ assert settings1[device.sig1] == 1
25
+ # Including the ability to "or" two settings together
26
+ settings = settings1 | settings2
27
+ assert dict(settings) == {
28
+ device.sig1: 10,
29
+ device.sig2: 2,
30
+ device.sig3: 3,
31
+ }
32
+ ```
33
+ """
34
+
13
35
  def __init__(
14
36
  self, device: DeviceT, settings: MutableMapping[SignalRW, Any] | None = None
15
37
  ):
@@ -48,19 +70,7 @@ class Settings(MutableMapping[SignalRW[Any], Any], Generic[DeviceT]):
48
70
  return len(self._settings)
49
71
 
50
72
  def __or__(self, other: MutableMapping[SignalRW, Any]) -> Settings[DeviceT]:
51
- """Create a new Settings that is the union of self overridden by other.
52
-
53
- For example::
54
-
55
- settings1 = Settings(device, {device.sig1: 1, device.sig2: 2})
56
- settings2 = Settings(device, {device.sig1: 10, device.sig3: 3})
57
- settings = settings1 | settings2
58
- assert dict(settings) == {
59
- device.sig1: 10,
60
- device.sig2: 2,
61
- device.sig3: 3,
62
- }
63
- """
73
+ """Create a new Settings that is the union of self overridden by other."""
64
74
  if isinstance(other, Settings) and not self._is_in_device(other.device):
65
75
  raise ValueError(f"{other.device} is not a child of {self.device}")
66
76
  return Settings(self.device, self._settings | dict(other))
@@ -70,20 +80,19 @@ class Settings(MutableMapping[SignalRW[Any], Any], Generic[DeviceT]):
70
80
  ) -> tuple[Settings[DeviceT], Settings[DeviceT]]:
71
81
  """Partition into two Settings based on a predicate.
72
82
 
73
- Parameters
74
- ----------
75
- predicate
83
+ :param predicate:
76
84
  Callable that takes each signal, and returns a boolean to say if it
77
85
  should be in the first returned Settings
78
-
79
- Returns
80
- -------
81
- (where_true, where_false)
82
-
83
- For example::
84
-
85
- settings = Settings(device, {device.special: 1, device.sig: 2})
86
- specials, others = settings.partition(lambda sig: "special" in sig.name)
86
+ :returns:
87
+ `(where_true, where_false)` where each is a Settings object.
88
+ The first contains the signals for which the predicate returned True,
89
+ and the second contains the signals for which the predicate returned False.
90
+
91
+ :example:
92
+ ```python
93
+ settings = Settings(device, {device.special: 1, device.sig: 2})
94
+ specials, others = settings.partition(lambda sig: "special" in sig.name)
95
+ ```
87
96
  """
88
97
  where_true, where_false = Settings(self.device), Settings(self.device)
89
98
  for signal, value in self.items():
@@ -93,12 +102,12 @@ class Settings(MutableMapping[SignalRW[Any], Any], Generic[DeviceT]):
93
102
 
94
103
 
95
104
  class SettingsProvider:
105
+ """Base class for providing settings."""
106
+
96
107
  @abstractmethod
97
108
  async def store(self, name: str, data: dict[str, Any]):
98
109
  """Store the data, associating it with the given name."""
99
- ...
100
110
 
101
111
  @abstractmethod
102
112
  async def retrieve(self, name: str) -> dict[str, Any]:
103
113
  """Retrieve the data associated with the given name."""
104
- ...