diff --git a/sdk/python/core/ydk/types/__init__.py b/sdk/python/core/ydk/types/__init__.py index 5d37b176f..1d900830a 100644 --- a/sdk/python/core/ydk/types/__init__.py +++ b/sdk/python/core/ydk/types/__init__.py @@ -15,6 +15,8 @@ # ------------------------------------------------------------------ from .py_types import Entity, EntityCollection, Config, Filter, YList, YLeafList +from .py_types import entity_to_dict, entity_diff + from ydk.ext.types import Bits from ydk.ext.types import ChildrenMap from ydk.ext.types import ModelCachingOption @@ -48,4 +50,6 @@ "YLeaf", "YLeafList", "YType", + "entity_to_dict", + "entity_diff", ] diff --git a/sdk/python/core/ydk/types/py_types.py b/sdk/python/core/ydk/types/py_types.py index 7c6c02915..a1bad83bb 100644 --- a/sdk/python/core/ydk/types/py_types.py +++ b/sdk/python/core/ydk/types/py_types.py @@ -20,14 +20,15 @@ - YList - YLeafList - Entity + - EntityCollection """ from collections import OrderedDict from functools import reduce import importlib import logging - import sys + if sys.version_info > (3,): long = int unicode = str @@ -43,11 +44,13 @@ from ydk.ext.types import Decimal64 # Do not remove. Used in eval() from ydk.ext.types import Entity as _Entity from ydk.ext.types import LeafDataList + from ydk.filters import YFilter as _YFilter from ydk.errors import YModelError as _YModelError from ydk.errors import YInvalidArgumentError from ydk.errors.error_handler import handle_type_error as _handle_type_error + class YLeafList(_YLeafList): """ Wrapper class for YLeafList, add __repr__ and get list slice functionalities. @@ -326,11 +329,11 @@ def path(self): return self.get_segment_path() def get_absolute_path(self): - path = self._absolute_path() - if len(path) == 0 and self.is_top_level_class: - path = self.get_segment_path() - if '[' in path: - path = path.split('[')[0] + path = self.get_segment_path() + if not self.is_top_level_class: + path = self.parent.get_absolute_path() + '/' + path + # elif '[' in path: + # path = path.split('[')[0] return path def _get_child_by_seg_name(self, segs): @@ -345,8 +348,8 @@ def _perform_setattr(self, clazz, leaf_names, name, value): if name != 'yfilter' and name != 'parent' and name != 'ignore_validation' \ and hasattr(self, '_is_frozen') and self._is_frozen \ and name not in self.__dict__: - raise _YModelError("Attempt to assign unknown attribute '{0}' to '{1}'.".format(name, - self.__class__.__name__)) + raise _YModelError("Attempt to assign unknown attribute '{0}' to '{1}'.". + format(name, self.__class__.__name__)) if name in self.__dict__ and isinstance(self.__dict__[name], YList): raise _YModelError("Attempt to assign value of '{}' to YList ldata. " "Please use list append or extend method." @@ -399,6 +402,60 @@ def _assign_yleaflist(self, name, value, v): def __str__(self): return "{}.{}".format(self.__class__.__module__, self.__class__.__name__) + + +def entity_to_dict(entity): + edict = {} + abs_path = entity.get_absolute_path() + if (hasattr(entity, 'is_presence_container') and entity.is_presence_container) or \ + abs_path.endswith(']'): + edict[abs_path] = '' + leaf_name_data = entity.get_name_leaf_data() + for l in leaf_name_data: + leaf_name = l[0] + leaf_value = l[1].value + if leaf_name not in entity.ylist_key_names: + edict["%s/%s" % (abs_path, leaf_name)] = leaf_value + for name, child in entity.get_children().items(): + child_dict = entity_to_dict(child) + for n, v in child_dict.items(): + edict[n] = v + return edict + + +def entity_diff(ent1, ent2): + if ent1 is None or ent2 is None or type(ent1) != type(ent2): + logger = logging.getLogger("ydk.types.Entity") + logger.error("entity_diff: Incompatible arguments provided.") + raise YInvalidArgumentError("entity_diff: Incompatible arguments provided.") + + diffs = {} + ent1_dict = entity_to_dict(ent1) + ent2_dict = entity_to_dict(ent2) + ent1_keys = sorted(ent1_dict.keys()) + ent2_keys = sorted(ent2_dict.keys()) + ent1_skip_keys = [] + for key in ent1_keys: + if key in ent1_skip_keys: + continue + if key in ent2_keys: + if ent1_dict[key] != ent2_dict[key]: + diffs[key] = (ent1_dict[key], ent2_dict[key]) + ent2_keys.remove(key) + else: + diffs[key] = (ent1_dict[key], None) + for dup_key in ent1_keys: + if dup_key.startswith(key): + ent1_skip_keys.append(dup_key) + ent2_skip_keys = [] + for key in ent2_keys: + if key in ent2_skip_keys: + continue + diffs[key] = (None, ent2_dict[key]) + for dup_key in ent2_keys: + if dup_key.startswith(key): + ent2_skip_keys.append(dup_key) + return diffs def _name_matches_yang_name(name, yang_name):