Skip to content

Commit 2385a35

Browse files
committed
ENH: implementation for 'structure_path_get' and 'structure_path_nodes' API
1 parent 629801c commit 2385a35

File tree

4 files changed

+113
-2
lines changed

4 files changed

+113
-2
lines changed

src/save_and_restore_api/_api_async.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,16 @@ async def structure_copy(self, nodeIds, newParentNodeId, *, auth=None):
249249
)
250250
return await self.send_request(method, url, params=params, url_params=url_params, auth=auth)
251251

252+
async def structure_path_get(self, uniqueNodeId):
253+
# Reusing docstrings from the threaded version
254+
method, url = self._prepare_structure_path_get(uniqueNodeId=uniqueNodeId)
255+
return await self.send_request(method, url)
256+
257+
async def structure_path_nodes(self, path):
258+
# Reusing docstrings from the threaded version
259+
method, url, url_params = self._prepare_structure_path_nodes(path=path)
260+
return await self.send_request(method, url, url_params=url_params)
261+
252262

253263
SaveRestoreAPI.info_get.__doc__ = _SaveRestoreAPI_Threads.info_get.__doc__
254264
SaveRestoreAPI.version_get.__doc__ = _SaveRestoreAPI_Threads.version_get.__doc__
@@ -278,3 +288,5 @@ async def structure_copy(self, nodeIds, newParentNodeId, *, auth=None):
278288
SaveRestoreAPI.compare.__doc__ = _SaveRestoreAPI_Threads.compare.__doc__
279289
SaveRestoreAPI.structure_move.__doc__ = _SaveRestoreAPI_Threads.structure_move.__doc__
280290
SaveRestoreAPI.structure_copy.__doc__ = _SaveRestoreAPI_Threads.structure_copy.__doc__
291+
SaveRestoreAPI.structure_path_get.__doc__ = _SaveRestoreAPI_Threads.structure_path_get.__doc__
292+
SaveRestoreAPI.structure_path_nodes.__doc__ = _SaveRestoreAPI_Threads.structure_path_nodes.__doc__

src/save_and_restore_api/_api_base.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,15 @@ def _prepare_structure_copy(self, *, nodeIds, newParentNodeId):
361361
params = nodeIds
362362
return method, url, params, url_params
363363

364+
def _prepare_structure_path_get(self, *, uniqueNodeId):
365+
method, url = "GET", f"/path/{uniqueNodeId}"
366+
return method, url
367+
368+
def _prepare_structure_path_nodes(self, *, path):
369+
method, url = "GET", "/path"
370+
url_params = {"path": path}
371+
return method, url, url_params
372+
364373
# =============================================================================================
365374

366375
# def create_config(self, parent_node_uid, name, pv_list):

src/save_and_restore_api/_api_threads.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ def structure_move(self, nodeIds, *, newParentNodeId, auth=None):
385385
Move nodes specified by a list of UIDs ``nodeIds`` to a new parent node specified
386386
by ``newParentNodeId``. The API requires 'admin' priviledges.
387387
388-
API: POST /structure/move
388+
API: POST /move
389389
"""
390390
method, url, params, url_params = self._prepare_structure_move(
391391
nodeIds=nodeIds, newParentNodeId=newParentNodeId
@@ -397,9 +397,29 @@ def structure_copy(self, nodeIds, *, newParentNodeId, auth=None):
397397
Copy nodes specified by a list of UIDs ``nodeIds`` to a new parent node specified
398398
by ``newParentNodeId``. The API requires 'admin' priviledges.
399399
400-
API: POST /structure/copy
400+
API: POST /copy
401401
"""
402402
method, url, params, url_params = self._prepare_structure_copy(
403403
nodeIds=nodeIds, newParentNodeId=newParentNodeId
404404
)
405405
return self.send_request(method, url, params=params, url_params=url_params, auth=auth)
406+
407+
def structure_path_get(self, uniqueNodeId):
408+
"""
409+
Get path for the node with specified uniqueNodeId.
410+
411+
API: GET /path/{uniqueNodeId}
412+
"""
413+
method, url = self._prepare_structure_path_get(uniqueNodeId=uniqueNodeId)
414+
return self.send_request(method, url)
415+
416+
def structure_path_nodes(self, path):
417+
"""
418+
Get a list of nodes that match the specified path. The path can point to multiple
419+
nodes as long as node type is different (e.g. a folder and a configuration may have
420+
the same name).
421+
422+
API: GET /path
423+
"""
424+
method, url, url_params = self._prepare_structure_path_nodes(path=path)
425+
return self.send_request(method, url, url_params=url_params)

tests/test_structure_control.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
base_url,
1414
clear_sar, # noqa: F401
1515
create_root_folder,
16+
root_folder_node_name,
1617
)
1718

1819
# =============================================================================================
@@ -129,3 +130,72 @@ async def testing():
129130
assert len(response) == n_folder2
130131

131132
asyncio.run(testing())
133+
134+
135+
136+
# fmt: off
137+
@pytest.mark.parametrize("usesetauth", [True, False])
138+
@pytest.mark.parametrize("library", ["THREADS", "ASYNC"])
139+
# fmt: on
140+
def test_structure_path_01(clear_sar, library, usesetauth): # noqa: F811
141+
"""
142+
Basic tests for the 'path_get' and 'path_nodes' API.
143+
"""
144+
root_folder_uid = create_root_folder()
145+
146+
if not _is_async(library):
147+
with SaveRestoreAPI_Threads(base_url=base_url, timeout=10) as SR:
148+
auth = _select_auth(SR=SR, usesetauth=usesetauth)
149+
150+
# Create two folders
151+
folder1_name = "Folder1"
152+
response = SR.node_add(root_folder_uid, name=folder1_name, nodeType="FOLDER", **auth)
153+
folder1_uid = response["uniqueId"]
154+
155+
node_name = "Node Name"
156+
response = SR.node_add(folder1_uid, name=node_name, nodeType="FOLDER", **auth)
157+
folder2_uid = response["uniqueId"]
158+
159+
# Create two configurations in folder1
160+
response = SR.config_create(
161+
folder1_uid,
162+
configurationNode={"name": node_name},
163+
configurationData={"pvList": []},
164+
**auth
165+
)
166+
167+
folder1_path = SR.structure_path_get(folder2_uid)
168+
assert folder1_path == "/" + root_folder_node_name + "/" + folder1_name + "/" + node_name
169+
170+
response = SR.structure_path_nodes(folder1_path)
171+
assert len(response) == 2
172+
173+
else:
174+
async def testing():
175+
async with SaveRestoreAPI_Async(base_url=base_url, timeout=2) as SR:
176+
auth = _select_auth(SR=SR, usesetauth=usesetauth)
177+
178+
# Create two folders
179+
folder1_name = "Folder1"
180+
response = await SR.node_add(root_folder_uid, name=folder1_name, nodeType="FOLDER", **auth)
181+
folder1_uid = response["uniqueId"]
182+
183+
node_name = "Node Name"
184+
response = await SR.node_add(folder1_uid, name=node_name, nodeType="FOLDER", **auth)
185+
folder2_uid = response["uniqueId"]
186+
187+
# Create two configurations in folder1
188+
response = await SR.config_create(
189+
folder1_uid,
190+
configurationNode={"name": node_name},
191+
configurationData={"pvList": []},
192+
**auth
193+
)
194+
195+
folder1_path = await SR.structure_path_get(folder2_uid)
196+
assert folder1_path == "/" + root_folder_node_name + "/" + folder1_name + "/" + node_name
197+
198+
response = await SR.structure_path_nodes(folder1_path)
199+
assert len(response) == 2
200+
201+
asyncio.run(testing())

0 commit comments

Comments
 (0)