Skip to content

Commit 4eb067a

Browse files
committed
ENH: implementation of composite snapshot APIs
1 parent 86aad32 commit 4eb067a

File tree

6 files changed

+346
-7
lines changed

6 files changed

+346
-7
lines changed

src/save_and_restore_api/_api_async.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@ async def snapshot_get(self, uniqueId):
191191

192192
async def snapshot_add(self, parentNodeId, *, snapshotNode, snapshotData, auth=None):
193193
# Reusing docstrings from the threaded version
194-
method, url, params = self._prepare_snapshot_add(
194+
method, url, url_params, params = self._prepare_snapshot_add(
195195
parentNodeId=parentNodeId, snapshotNode=snapshotNode, snapshotData=snapshotData
196196
)
197-
return await self.send_request(method, url, params=params, auth=auth)
197+
return await self.send_request(method, url, params=params, url_params=url_params, auth=auth)
198198

199199
async def snapshot_update(self, *, snapshotNode, snapshotData, auth=None):
200200
# Reusing docstrings from the threaded version
@@ -206,6 +206,49 @@ async def snapshots_get(self):
206206
method, url = self._prepare_snapshots_get()
207207
return await self.send_request(method, url)
208208

209+
# =============================================================================================
210+
# COMPOSITE-SNAPSHOT-CONTROLLER API METHODS
211+
# =============================================================================================
212+
213+
async def composite_snapshot_get(self, uniqueId):
214+
# Reusing docstrings from the threaded version
215+
method, url = self._prepare_composite_snapshot_get(uniqueId=uniqueId)
216+
return await self.send_request(method, url)
217+
218+
async def composite_snapshot_get_nodes(self, uniqueId):
219+
# Reusing docstrings from the threaded version
220+
method, url = self._prepare_composite_snapshot_get_nodes(uniqueId=uniqueId)
221+
return await self.send_request(method, url)
222+
223+
async def composite_snapshot_get_items(self, uniqueId):
224+
# Reusing docstrings from the threaded version
225+
method, url = self._prepare_composite_snapshot_get_items(uniqueId=uniqueId)
226+
return await self.send_request(method, url)
227+
228+
async def composite_snapshot_add(
229+
self, parentNodeId, *, compositeSnapshotNode, compositeSnapshotData, auth=None
230+
):
231+
# Reusing docstrings from the threaded version
232+
method, url, url_params, params = self._prepare_composite_snapshot_add(
233+
parentNodeId=parentNodeId,
234+
compositeSnapshotNode=compositeSnapshotNode,
235+
compositeSnapshotData=compositeSnapshotData,
236+
)
237+
return await self.send_request(method, url, url_params=url_params, params=params, auth=auth)
238+
239+
async def composite_snapshot_update(self, *, compositeSnapshotNode, compositeSnapshotData, auth=None):
240+
# Reusing docstrings from the threaded version
241+
method, url, params = self._prepare_composite_snapshot_update(
242+
compositeSnapshotNode=compositeSnapshotNode,
243+
compositeSnapshotData=compositeSnapshotData,
244+
)
245+
return await self.send_request(method, url, params=params, auth=auth)
246+
247+
async def composite_snapshot_consistency_check(self, uniqueNodeIds, *, auth=None):
248+
# Reusing docstrings from the threaded version
249+
method, url, params = self._prepare_composite_snapshot_consistency_check(uniqueNodeIds=uniqueNodeIds)
250+
return await self.send_request(method, url, params=params, auth=auth)
251+
209252
# =============================================================================================
210253
# SNAPSHOT-RESTORE-CONTROLLER API METHODS
211254
# =============================================================================================
@@ -302,6 +345,16 @@ async def structure_path_nodes(self, path):
302345
SaveRestoreAPI.snapshot_add.__doc__ = _SaveRestoreAPI_Threads.snapshot_add.__doc__
303346
SaveRestoreAPI.snapshot_update.__doc__ = _SaveRestoreAPI_Threads.snapshot_update.__doc__
304347
SaveRestoreAPI.snapshots_get.__doc__ = _SaveRestoreAPI_Threads.snapshots_get.__doc__
348+
349+
SaveRestoreAPI.composite_snapshot_get.__doc__ = _SaveRestoreAPI_Threads.composite_snapshot_get.__doc__
350+
SaveRestoreAPI.composite_snapshot_get_nodes.__doc__ = _SaveRestoreAPI_Threads.composite_snapshot_get_nodes.__doc__
351+
SaveRestoreAPI.composite_snapshot_get_items.__doc__ = _SaveRestoreAPI_Threads.composite_snapshot_get_items.__doc__
352+
SaveRestoreAPI.composite_snapshot_add.__doc__ = _SaveRestoreAPI_Threads.composite_snapshot_add.__doc__
353+
SaveRestoreAPI.composite_snapshot_update.__doc__ = _SaveRestoreAPI_Threads.composite_snapshot_update.__doc__
354+
SaveRestoreAPI.composite_snapshot_consistency_check.__doc__ = (
355+
_SaveRestoreAPI_Threads.composite_snapshot_consistency_check.__doc__
356+
)
357+
305358
SaveRestoreAPI.restore_node.__doc__ = _SaveRestoreAPI_Threads.restore_node.__doc__
306359
SaveRestoreAPI.restore_items.__doc__ = _SaveRestoreAPI_Threads.restore_items.__doc__
307360
SaveRestoreAPI.compare.__doc__ = _SaveRestoreAPI_Threads.compare.__doc__

src/save_and_restore_api/_api_base.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,10 @@ def _prepare_snapshot_get(self, *, uniqueId):
302302
return method, url
303303

304304
def _prepare_snapshot_add(self, *, parentNodeId, snapshotNode, snapshotData):
305-
method, url = "PUT", f"/snapshot?parentNodeId={parentNodeId}"
305+
method, url = "PUT", "/snapshot"
306306
params = {"snapshotNode": snapshotNode, "snapshotData": snapshotData}
307-
return method, url, params
307+
url_params = {"parentNodeId": parentNodeId}
308+
return method, url, url_params, params
308309

309310
def _prepare_snapshot_update(self, *, snapshotNode, snapshotData):
310311
method, url = "POST", "/snapshot"
@@ -315,6 +316,38 @@ def _prepare_snapshots_get(self):
315316
method, url = "GET", "/snapshots"
316317
return method, url
317318

319+
# =============================================================================================
320+
# COMPOSITE-SNAPSHOT-CONTROLLER API METHODS
321+
# =============================================================================================
322+
323+
def _prepare_composite_snapshot_get(self, *, uniqueId):
324+
method, url = "GET", f"/composite-snapshot/{uniqueId}"
325+
return method, url
326+
327+
def _prepare_composite_snapshot_get_nodes(self, *, uniqueId):
328+
method, url = "GET", f"/composite-snapshot/{uniqueId}/nodes"
329+
return method, url
330+
331+
def _prepare_composite_snapshot_get_items(self, *, uniqueId):
332+
method, url = "GET", f"/composite-snapshot/{uniqueId}/items"
333+
return method, url
334+
335+
def _prepare_composite_snapshot_add(self, *, parentNodeId, compositeSnapshotNode, compositeSnapshotData):
336+
method, url = "PUT", "/composite-snapshot"
337+
params = {"compositeSnapshotNode": compositeSnapshotNode, "compositeSnapshotData": compositeSnapshotData}
338+
url_params = {"parentNodeId": parentNodeId}
339+
return method, url, url_params, params
340+
341+
def _prepare_composite_snapshot_update(self, *, compositeSnapshotNode, compositeSnapshotData):
342+
method, url = "POST", "/composite-snapshot"
343+
params = {"compositeSnapshotNode": compositeSnapshotNode, "compositeSnapshotData": compositeSnapshotData}
344+
return method, url, params
345+
346+
def _prepare_composite_snapshot_consistency_check(self, *, uniqueNodeIds):
347+
method, url = "POST", "/composite-snapshot-consistency-check"
348+
params = uniqueNodeIds
349+
return method, url, params
350+
318351
# =============================================================================================
319352
# SNAPSHOT-RESTORE-CONTROLLER API METHODS
320353
# =============================================================================================

src/save_and_restore_api/_api_threads.py

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,10 @@ def snapshot_add(self, parentNodeId, *, snapshotNode, snapshotData, auth=None):
308308
309309
API: PUT /snapshot?parentNodeId={parentNodeId}
310310
"""
311-
method, url, params = self._prepare_snapshot_add(
311+
method, url, url_params, params = self._prepare_snapshot_add(
312312
parentNodeId=parentNodeId, snapshotNode=snapshotNode, snapshotData=snapshotData
313313
)
314-
return self.send_request(method, url, params=params, auth=auth)
314+
return self.send_request(method, url, params=params, url_params=url_params, auth=auth)
315315

316316
def snapshot_update(self, *, snapshotNode, snapshotData, auth=None):
317317
"""
@@ -332,6 +332,77 @@ def snapshots_get(self):
332332
method, url = self._prepare_snapshots_get()
333333
return self.send_request(method, url)
334334

335+
# =============================================================================================
336+
# COMPOSITE-SNAPSHOT-CONTROLLER API METHODS
337+
# =============================================================================================
338+
339+
def composite_snapshot_get(self, uniqueId):
340+
"""
341+
Returns composite snapshot data (``compositeSnapshotData``). The composite snapshot is
342+
specified by ``uniqueId``. The data includes uniqueId and the list of referencedSnapshotNodes
343+
(no PV information).
344+
345+
API: GET /composite-snapshot/{uniqueId}
346+
"""
347+
method, url = self._prepare_composite_snapshot_get(uniqueId=uniqueId)
348+
return self.send_request(method, url)
349+
350+
def composite_snapshot_get_nodes(self, uniqueId):
351+
"""
352+
Returns a list of nodes referenced by the composite snapshot. The composite snapshot is
353+
specified by ``uniqueId``.
354+
355+
API: GET /composite-snapshot/{uniqueId}/nodes
356+
"""
357+
method, url = self._prepare_composite_snapshot_get_nodes(uniqueId=uniqueId)
358+
return self.send_request(method, url)
359+
360+
def composite_snapshot_get_items(self, uniqueId):
361+
"""
362+
Returns a list of restorable items referenced by the composite snapshot. The composite snapshot is
363+
specified by ``uniqueId``.
364+
365+
API: GET /composite-snapshot/{uniqueId}/items
366+
"""
367+
method, url = self._prepare_composite_snapshot_get_items(uniqueId=uniqueId)
368+
return self.send_request(method, url)
369+
370+
def composite_snapshot_add(self, parentNodeId, *, compositeSnapshotNode, compositeSnapshotData, auth=None):
371+
"""
372+
Create a new composite snapshot node. The new node is created under the existing configuration node
373+
specified by ``parentNodeId``.
374+
375+
API: PUT /composite-snapshot?parentNodeId={parentNodeId}
376+
"""
377+
method, url, url_params, params = self._prepare_composite_snapshot_add(
378+
parentNodeId=parentNodeId,
379+
compositeSnapshotNode=compositeSnapshotNode,
380+
compositeSnapshotData=compositeSnapshotData,
381+
)
382+
return self.send_request(method, url, url_params=url_params, params=params, auth=auth)
383+
384+
def composite_snapshot_update(self, *, compositeSnapshotNode, compositeSnapshotData, auth=None):
385+
"""
386+
Update the existing snapshot. Both ``compositeSnapshotNode`` and ``compositeSnapshotNode``
387+
must have valid ``uniqueId`` fields pointing to an existing node.
388+
389+
API: POST /composite-snapshot
390+
"""
391+
method, url, params = self._prepare_composite_snapshot_update(
392+
compositeSnapshotNode=compositeSnapshotNode,
393+
compositeSnapshotData=compositeSnapshotData,
394+
)
395+
return self.send_request(method, url, params=params, auth=auth)
396+
397+
def composite_snapshot_consistency_check(self, uniqueNodeIds, *, auth=None):
398+
"""
399+
Check consistency of the composite snapshots.
400+
401+
API: POST /composite-snapshot-consistency-check
402+
"""
403+
method, url, params = self._prepare_composite_snapshot_consistency_check(uniqueNodeIds=uniqueNodeIds)
404+
return self.send_request(method, url, params=params, auth=auth)
405+
335406
# =============================================================================================
336407
# SNAPSHOT-RESTORE-CONTROLLER API METHODS
337408
# =============================================================================================

tests/common.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,17 @@ def _clear():
102102
n_uid += 1
103103

104104
# Delete all nodes starting with children, including the root folder
105+
# First delete all composite snapshots
106+
uids_remaining = []
105107
for uid in reversed(uids):
108+
resp = SR.node_get(uid)
109+
if resp["nodeType"] == "COMPOSITE_SNAPSHOT":
110+
SR.nodes_delete([uid])
111+
else:
112+
uids_remaining.append(uid)
113+
# Then delete all other nodes
114+
uids = uids_remaining
115+
for uid in uids:
106116
SR.nodes_delete([uid])
107117

108118
# Delete all filters

tests/test_filter_control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
@pytest.mark.parametrize("usesetauth", [True, False])
2525
@pytest.mark.parametrize("library", ["THREADS", "ASYNC"])
2626
# fmt: on
27-
def test_filter_add_01(clear_sar, ioc, library, usesetauth): # noqa: F811
27+
def test_filter_add_01(clear_sar, library, usesetauth): # noqa: F811
2828
"""
2929
Basic tests for the 'filter_add', 'filters_get' and 'filter_delete' API.
3030
"""

0 commit comments

Comments
 (0)