From 2ba5207ed96741c8b56edf23a66f966ea6b44c23 Mon Sep 17 00:00:00 2001
From: John Estabrook <jestabro@vyos.io>
Date: Thu, 25 May 2023 14:22:29 -0500
Subject: xml: T5242: add cli_defined boolean test for node existing under path

If non_local=False (default), cli_defined returns True if the node is a
child of the path in interface-definitions; otherwise True if node is a
descendent of the path.
---
 python/vyos/xml_ref/__init__.py   |  3 +++
 python/vyos/xml_ref/definition.py | 25 +++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

(limited to 'python')

diff --git a/python/vyos/xml_ref/__init__.py b/python/vyos/xml_ref/__init__.py
index ae5184746..2e144ef10 100644
--- a/python/vyos/xml_ref/__init__.py
+++ b/python/vyos/xml_ref/__init__.py
@@ -45,6 +45,9 @@ def is_valueless(path: list) -> bool:
 def is_leaf(path: list) -> bool:
     return load_reference().is_leaf(path)
 
+def cli_defined(path: list, node: str, non_local=False) -> bool:
+    return load_reference().cli_defined(path, node, non_local=non_local)
+
 def component_version() -> dict:
     return load_reference().component_version()
 
diff --git a/python/vyos/xml_ref/definition.py b/python/vyos/xml_ref/definition.py
index 429331577..95ecc01a6 100644
--- a/python/vyos/xml_ref/definition.py
+++ b/python/vyos/xml_ref/definition.py
@@ -92,6 +92,31 @@ class Xml:
         d = self._get_ref_path(path)
         return self._is_leaf_node(d)
 
+    @staticmethod
+    def _dict_get(d: dict, path: list) -> dict:
+        for i in path:
+            d = d.get(i, {})
+            if not isinstance(d, dict):
+                return {}
+            if not d:
+                break
+        return d
+
+    def _dict_find(self, d: dict, key: str, non_local=False) -> bool:
+        for k in list(d):
+            if k in ('node_data', 'component_version'):
+                continue
+            if k == key:
+                return True
+            if non_local and isinstance(d[k], dict):
+                if self._dict_find(d[k], key):
+                    return True
+        return False
+
+    def cli_defined(self, path: list, node: str, non_local=False) -> bool:
+        d = self._dict_get(self.ref, path)
+        return self._dict_find(d, node, non_local=non_local)
+
     def component_version(self) -> dict:
         d = {}
         for k, v in self.ref['component_version']:
-- 
cgit v1.2.3