Skip to content

Commit f6de384

Browse files
committed
subscription: return parent node to oper_state callback
The only way to differentiate two calls when there is a subscription on an internal element of a list is by using the parent node. Moreover, in these cases, it is on this parent node that the data structure to be returned must be built.
1 parent ab825a9 commit f6de384

File tree

3 files changed

+16
-5
lines changed

3 files changed

+16
-5
lines changed

sysrepo/session.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -372,13 +372,17 @@ def subscribe_module_change(
372372

373373
self.subscriptions.append(sub)
374374

375-
OperDataCallbackType = Callable[[str, Any], Optional[Dict]]
375+
OperDataCallbackType = Callable[[str, Optional[libyang.DNode], Any], Optional[Dict]]
376376
"""
377377
Callback to be called when the operational data are requested.
378378
379379
:arg xpath:
380380
The XPath requested by a client. Can be None if the client requested for all the
381381
module operational data.
382+
:arg parent:
383+
Pointer to an existing parent of the requested nodes. It is None for top-level
384+
nodes. Caller is supposed to append the requested nodes to this data subtree
385+
and return either the original parent or a top-level node.
382386
:arg private_data:
383387
Private context opaque to sysrepo used when subscribing.
384388
:arg kwargs (optional):

sysrepo/subscription.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -367,12 +367,17 @@ def oper_data_callback(session, sub_id, module, xpath, req_xpath, req_id, parent
367367
else:
368368
extra_info = {}
369369

370+
parent_node = None
371+
if parent[0]:
372+
with session.get_ly_ctx() as ly_ctx:
373+
parent_node = DNode.new(ly_ctx, parent[0])
374+
370375
if is_async_func(callback):
371376
task_id = req_id
372377

373378
if task_id not in subscription.tasks:
374379
task = subscription.loop.create_task(
375-
callback(req_xpath, private_data, **extra_info)
380+
callback(req_xpath, parent_node, private_data, **extra_info)
376381
)
377382
task.add_done_callback(
378383
functools.partial(subscription.task_done, task_id, "oper")
@@ -389,7 +394,7 @@ def oper_data_callback(session, sub_id, module, xpath, req_xpath, req_id, parent
389394
oper_data = task.result()
390395

391396
else:
392-
oper_data = callback(req_xpath, private_data, **extra_info)
397+
oper_data = callback(req_xpath, parent_node, private_data, **extra_info)
393398

394399
if isinstance(oper_data, dict):
395400
# convert oper_data to a libyang.DNode object

tests/test_subs_oper.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ def test_oper_sub(self):
3939
priv = object()
4040
state = None
4141

42-
def oper_data_cb(xpath, private_data):
42+
def oper_data_cb(xpath, path, private_data):
4343
self.assertEqual(xpath, "/sysrepo-example:state")
44+
self.assertIsNone(path)
4445
self.assertEqual(private_data, priv)
4546
return state
4647

@@ -77,8 +78,9 @@ def test_oper_sub_with_extra_info(self):
7778
priv = object()
7879
calls = []
7980

80-
def oper_data_cb(xpath, private_data, **kwargs):
81+
def oper_data_cb(xpath, path, private_data, **kwargs):
8182
self.assertEqual(xpath, "/sysrepo-example:state")
83+
self.assertIsNone(path)
8284
self.assertEqual(private_data, priv)
8385
self.assertIn("user", kwargs)
8486
self.assertEqual(getpass.getuser(), kwargs["user"])

0 commit comments

Comments
 (0)