Skip to content

Commit

Permalink
Fixed issue CiscoDevNet#1091
Browse files Browse the repository at this point in the history
  • Loading branch information
ygorelik committed Sep 1, 2023
1 parent 67ec6ae commit 26703cf
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#### Resolved GitHub issues
* Segmentation Fault on Python application exit with Python 3.9.5 ([#1050](https://github.com/CiscoDevNet/ydk-gen/issues/1050))
* ydk.io and ciscodevnet.github.io/ydk-py/ not working correctly ([#1088](https://github.com/CiscoDevNet/ydk-gen/issues/1088))
* Incorrect bundle model reference ([#1091](https://github.com/CiscoDevNet/ydk-gen/issues/1091))

### 2023-01-31 version 0.8.6.4

Expand Down
3 changes: 2 additions & 1 deletion sdk/python/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
### 2023-03-31 version 0.8.6.5
### 2023-08-31 version 0.8.6.5

#### Resolved GitHub issues
* Segmentation Fault on Python application exit with Python 3.9.5 ([#1050](https://github.com/CiscoDevNet/ydk-gen/issues/1050))
* Incorrect bundle model reference ([#1091](https://github.com/CiscoDevNet/ydk-gen/issues/1091))


### 2023-01-31 version 0.8.6.4
Expand Down
27 changes: 17 additions & 10 deletions sdk/python/core/ydk/entity_utils/entity_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@ def _datanode_to_entity(data_node):
class_name = name_list[-1]
module_name = entity_entry.split('.'+class_name)[0]
try:
imported_module = importlib.import_module('ydk.models.{}.{}'.format(name, module_name))
imported_module = importlib.import_module('ydk.models.{}.{}'.
format(name, module_name))
entity = getattr(imported_module, class_name)()
except Exception as err:
raise YModelError("Failed instantiate class '{}' from module '{}': {}".format(class_name, module_name, err))
raise YModelError("Failed instantiate class '{}' from module '{}': {}".
format(class_name, module_name, err))

top_entity = entity.clone_ptr()
get_entity_from_data_node(data_node, top_entity)
Expand All @@ -93,7 +95,7 @@ def _datanode_to_entity(data_node):
raise YModelError(_ENTITY_ERROR_MSG.format(node_path))


def _payload_to_top_entity(payload, encoding):
def _payload_to_top_entity(payload, encoding, bundle_name=None):
"""Return top level entity from payload.
Namespace and entity name are extracted from payload. Then we use this
Expand All @@ -119,7 +121,7 @@ def _payload_to_top_entity(payload, encoding):
raise YModelError("Could not retrieve namespace and container name")
ydk_models = importlib.import_module('ydk.models')
for (_, name, ispkg) in pkgutil.iter_modules(ydk_models.__path__):
if ispkg:
if ispkg and (bundle_name is None or bundle_name == name):
yang_ns = importlib.import_module('ydk.models.{}._yang_ns'.format(name))
entity_lookup = yang_ns.__dict__['ENTITY_LOOKUP']
if ns_ename in entity_lookup:
Expand Down Expand Up @@ -244,17 +246,19 @@ def _get_child_entity_from_top(top_entity, filter_entity):
"""Searches for 'filter_entity' in the hierarchy of given top-level entity.
Args:
top_entity (Entity or [Entity ..]): Top-level entity, usually returned from CRUD read operation.
top_entity (Entity or [Entity]): Top-level entity, usually returned from CRUD read operation
filter_entity (Entity or [Entity ..]): Top-level or non-top-level entity, which is expected to be in the 'top_entity' hierarchy.
filter_entity (Entity or [Entity]): Top-level or non-top-level entity,
which is expected to be in the 'top_entity' hierarchy.
Argument type and list size must be matching.
Returns:
Top-level or non-top-level entity, which matches given filter under top-entity hierarchy.
Raises:
YServiceError, if specified argument types are not matching or 'filter_entity' does not belong to 'top_entity' hierarchy.
YServiceError, if specified argument types are not matching or 'filter_entity'
does not belong to 'top_entity' hierarchy.
"""
if filter_entity is None:
return top_entity
Expand All @@ -275,11 +279,13 @@ def _get_child_entity_from_top(top_entity, filter_entity):
if filter_entity.get_absolute_path() == top_entity.get_absolute_path():
return top_entity
else:
raise YServiceError("_get_child_entity_from_top: The filter '%s' points to different top-entity" %
raise YServiceError("_get_child_entity_from_top: "
"The filter '%s' points to different top-entity" %
filter_entity.get_absolute_path())
else:
if not top_entity.is_top_level_class:
raise YServiceError("_get_child_entity_from_top: The '%s' is not a top-level entity" %
raise YServiceError("_get_child_entity_from_top: "
"The '%s' is not a top-level entity" %
top_entity.get_absolute_path())
filter_abs_path = filter_entity.get_absolute_path()
entity = _find_child_entity(top_entity, filter_abs_path)
Expand All @@ -289,7 +295,8 @@ def _get_child_entity_from_top(top_entity, filter_entity):
elif top_entity is None:
return None
else:
raise YServiceError('_get_child_entity_from_top: Invalid arguments. Expected Entity or [Entity ...] for both arguments')
raise YServiceError('_get_child_entity_from_top: '
'Invalid arguments. Expected Entity or [Entity ...] for both arguments')


def _set_nontop_entity_filter(entity, yfilter):
Expand Down
10 changes: 6 additions & 4 deletions sdk/python/core/ydk/providers/codec_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class CodecServiceProvider(object):
def __init__(self, **kwargs):
self.logger = logging.getLogger(__name__)
self._root_schema_table = {}
self.bundle_name = None

repo = kwargs.get('repo', None)
if repo is None:
Expand Down Expand Up @@ -79,6 +80,7 @@ def initialize(self, bundle_name, models_path):
self.logger.log(_TRACE_LEVEL_NUM, "Creating repo in path {}".format(models_path))
repo = _Repository(models_path)
self._initialize_root_schema(bundle_name, repo)
self.bundle_name = bundle_name

def get_root_schema(self, bundle_name):
"""Return root_schema for bundle_name.
Expand All @@ -89,11 +91,11 @@ def get_root_schema(self, bundle_name):
if self._user_provided_repo:
return self._root_schema_table[_USER_PROVIDED_REPO]

if bundle_name not in self._root_schema_table:
self.logger.error("Root schema not created")
raise YServiceProviderError(error_msg="Root schema not created")
if bundle_name in self._root_schema_table:
return self._root_schema_table[bundle_name]

return self._root_schema_table[bundle_name]
self.logger.debug("Root schema yet to be initialized")
return None

def _initialize_root_schema(self, bundle_name, repo, user_provided_repo=False):
"""Update root schema table entry.
Expand Down
22 changes: 13 additions & 9 deletions sdk/python/core/ydk/services/codec_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ def _encode(self, provider, entity, pretty, subtree):
Instance of YServiceError if encoding fails.
"""
bundle_name = _get_bundle_name(entity)
provider.initialize(bundle_name, _get_yang_path(entity))
root_schema = provider.get_root_schema(bundle_name)
if root_schema is None:
provider.initialize(bundle_name, _get_yang_path(entity))
root_schema = provider.get_root_schema(bundle_name)

if subtree:
if provider.encoding == EncodingFormat.XML:
Expand All @@ -122,7 +124,7 @@ def _encode(self, provider, entity, pretty, subtree):
data_node = _get_data_node_from_entity(entity, root_schema)
codec_service = _Codec()
result = codec_service.encode(data_node, provider.encoding, pretty)
self.logger.debug("Performing encode operation, resulting in {}".format(result))
self.logger.debug("Encode operation result:\n{}".format(result))
return result

@_check_argument
Expand All @@ -131,7 +133,8 @@ def decode(self, provider, payload_holder, subtree=False):
Args:
provider: (ydk.providers.CodecServiceProvider): Codec provider.
payload_holder: (str or dict(str, str) or list(str)), which represents payload in XML or JSON format.
payload_holder: (str or dict(str, str) or list(str)),
which represents payload in XML or JSON format.
subtree: (bool) flag, which directs encode to XML subtree; default - False.
Returns:
Expand Down Expand Up @@ -169,7 +172,8 @@ def _decode(self, provider, payload, subtree):
YServiceProviderError with _PAYLOAD_ERROR_MSG, if payload
contains more than one top level containers.
"""
entity = _payload_to_top_entity(payload, provider.encoding)
entity = _payload_to_top_entity(payload, provider.encoding,
bundle_name=provider.bundle_name)

if subtree:
if provider.encoding == EncodingFormat.XML:
Expand All @@ -179,15 +183,14 @@ def _decode(self, provider, payload, subtree):
return codec.decode(payload, entity)

bundle_name = _get_bundle_name(entity)
provider.initialize(bundle_name, _get_yang_path(entity))

root_schema = provider.get_root_schema(bundle_name)

self.logger.debug("Performing decode operation on payload:\n{}".format(payload))
if root_schema is None:
provider.initialize(bundle_name, _get_yang_path(entity))
root_schema = provider.get_root_schema(bundle_name)

codec_service = _Codec()
root_data_node = codec_service.decode(root_schema, payload, provider.encoding)
data_nodes = root_data_node.get_children();
data_nodes = root_data_node.get_children()
if data_nodes is None or len(data_nodes) == 0:
self.logger.debug(_PAYLOAD_ERROR_MSG)
raise YServiceProviderError(_PAYLOAD_ERROR_MSG)
Expand All @@ -200,6 +203,7 @@ def _log_error_and_raise_exception(self, msg, exception_class):
self.logger.error(msg)
raise exception_class(msg)


def _get_yang_path(entity):
"""Return YANG models install location for entity.
Expand Down

0 comments on commit 26703cf

Please sign in to comment.