def free(self, with_siblings: bool = True) -> None: try: if with_siblings: lib.lyd_free_withsiblings(self.cdata) else: lib.lyd_free(self.cdata) finally: self.cdata = None
def free(self, with_siblings=True): try: if with_siblings: lib.lyd_free_withsiblings(self._node) else: lib.lyd_free(self._node) finally: self._node = None
def dict_to_dnode( dic: Dict[str, Any], module: Module, parent: Optional[DNode] = None, data: bool = False, config: bool = False, get: bool = False, getconfig: bool = False, edit: bool = False, rpc: bool = False, rpcreply: bool = False, strict: bool = False, no_yanglib: bool = False, validate: bool = True, ) -> Optional[DNode]: """ Convert a python dictionary to a DNode object given a YANG module object. The return value is the first created node. If parent is not set, a top-level node is returned. :arg dic: The python dictionary to convert. :arg module: The libyang Module object associated with the dictionary. :arg parent: Optional parent to update. If not specified a new top-level DNode will be created. :arg data: Complete datastore content with configuration as well as state data. To handle possibly missing (but by default required) ietf-yang-library data, use no_yanglib=True. :arg config: Complete datastore without state data. :arg get: Data content from a reply message to the NETCONF <get> operation. :arg getconfig: Data content from a reply message to the NETCONF <get-config> operation. :arg edit: Content of the NETCONF <edit-config> config element. :arg rpc: Data represents RPC or action input parameters. :arg rpcreply: Data represents RPC or action output parameters. :arg strict: Instead of ignoring (with a warning message) data without schema definition, raise an error. :arg no_yanglib: Ignore (possibly) missing ietf-yang-library data. Applicable only with data=True. :arg validate: If False, do not validate the modified tree before returning. The validation is performed on the top of the data tree. """ if not dic: return None if not isinstance(dic, dict): raise TypeError("dic argument must be a python dict") if not isinstance(module, Module): raise TypeError("module argument must be a Module object") if parent is not None and not isinstance(parent, DNode): raise TypeError("parent argument must be a DNode object or None") created = [] def _create_leaf(_parent, module, name, value, in_rpc_output=False): if value is not None: if isinstance(value, bool): value = str(value).lower() elif not isinstance(value, str): value = str(value) if in_rpc_output: n = lib.lyd_new_output_leaf(_parent, module.cdata, str2c(name), str2c(value)) else: n = lib.lyd_new_leaf(_parent, module.cdata, str2c(name), str2c(value)) if not n: if _parent: parent_path = repr(DNode.new(module.context, _parent).path()) else: parent_path = "module %r" % module.name() raise module.context.error( "failed to create leaf %r as a child of %s", name, parent_path) created.append(n) def _create_container(_parent, module, name, in_rpc_output=False): if in_rpc_output: n = lib.lyd_new_output(_parent, module.cdata, str2c(name)) else: n = lib.lyd_new(_parent, module.cdata, str2c(name)) if not n: if _parent: parent_path = repr(DNode.new(module.context, _parent).path()) else: parent_path = "module %r" % module.name() raise module.context.error( "failed to create container/list/rpc %r as a child of %s", name, parent_path, ) created.append(n) return n schema_cache = {} def _find_schema(schema_parent, name, prefix): cache_key = (schema_parent.cdata, name, prefix) snode, module = schema_cache.get(cache_key, (None, None)) if snode is not None: return snode, module if isinstance(schema_parent, SRpc): if rpc: schema_parent = schema_parent.input() elif rpcreply: schema_parent = schema_parent.output() else: raise ValueError("rpc or rpcreply must be specified") if schema_parent is None: # there may not be any input or any output node in the rpc return None, None for s in schema_parent: if s.name() != name: continue mod = s.module() if prefix is not None and mod.name() != prefix: continue snode = s module = mod break schema_cache[cache_key] = (snode, module) return snode, module keys_cache = {} def _dic_keys(_dic, _schema): if isinstance(_schema, SList): # list keys must be first and in the order specified in the schema list_keys = keys_cache.get(_schema.cdata, None) if list_keys is None: list_keys = tuple(k.name() for k in _schema.keys()) keys_cache[_schema.cdata] = list_keys keys = [] for k in list_keys: if k in _dic: keys.append(k) keys.extend(_dic.keys() - list_keys) return keys return _dic.keys() def _to_dnode(_dic, _schema, _parent=ffi.NULL, in_rpc_output=False): for key in _dic_keys(_dic, _schema): if ":" in key: prefix, name = name.split(":") else: prefix, name = None, key s, module = _find_schema(_schema, name, prefix) if not s: if isinstance(_schema, Module): path = _schema.name() elif isinstance(_schema, SNode): path = _schema.schema_path() else: path = str(_schema) if strict: raise LibyangError("%s: unknown element %r" % (path, key)) LOG.warning("%s: skipping unknown element %r", path, key) continue value = _dic[key] if isinstance(s, SLeaf): _create_leaf(_parent, module, name, value, in_rpc_output) elif isinstance(s, SLeafList): if not isinstance(value, (list, tuple)): raise TypeError( "%s: python value is not a list/tuple: %r" % (s.schema_path(), value)) for v in value: _create_leaf(_parent, module, name, v, in_rpc_output) elif isinstance(s, SRpc): n = _create_container(_parent, module, name, in_rpc_output) _to_dnode(value, s, n, rpcreply) elif isinstance(s, SContainer): n = _create_container(_parent, module, name, in_rpc_output) _to_dnode(value, s, n, in_rpc_output) elif isinstance(s, SList): if not isinstance(value, (list, tuple)): raise TypeError( "%s: python value is not a list/tuple: %r" % (s.schema_path(), value)) for v in value: if not isinstance(v, dict): raise TypeError("%s: list element is not a dict: %r" % (_schema.schema_path(), v)) n = _create_container(_parent, module, name, in_rpc_output) _to_dnode(v, s, n, in_rpc_output) result = None try: if parent is not None: _parent = parent.cdata _schema_parent = parent.schema() else: _parent = ffi.NULL _schema_parent = module _to_dnode( dic, _schema_parent, _parent, in_rpc_output=rpcreply and isinstance(parent, DRpc), ) if created: result = DNode.new(module.context, created[0]) if validate: result.root().validate( data=data, config=config, get=get, getconfig=getconfig, edit=edit, rpc=rpc, rpcreply=rpcreply, no_yanglib=no_yanglib, ) except: for c in reversed(created): lib.lyd_free(c) raise return result