22# Copyright (c) 2021 RACOM s.r.o.
33# SPDX-License-Identifier: MIT
44
5+ import json
56import logging
67from typing import IO , Any , Dict , Iterator , Optional , Tuple , Union
78
89from _libyang import ffi , lib
910from .keyed_list import KeyedList
1011from .schema import (
1112 Module ,
13+ SAnydata ,
1214 SContainer ,
1315 SLeaf ,
1416 SLeafList ,
@@ -107,6 +109,21 @@ def newval_flags(
107109 return flags
108110
109111
112+ # -------------------------------------------------------------------------------------
113+ def anydata_format (fmt_string : str ) -> int :
114+ if fmt_string == "datatree" :
115+ return lib .LYD_ANYDATA_DATATREE
116+ if fmt_string == "string" :
117+ return lib .LYD_ANYDATA_STRING
118+ if fmt_string == "xml" :
119+ return lib .LYD_ANYDATA_XML
120+ if fmt_string == "json" :
121+ return lib .LYD_ANYDATA_JSON
122+ if fmt_string == "lyb" :
123+ return lib .LYD_ANYDATA_LYB
124+ raise ValueError ("unknown anydata format: %r" % fmt_string )
125+
126+
110127# -------------------------------------------------------------------------------------
111128def parser_flags (
112129 lyb_mod_update : bool = False ,
@@ -1207,6 +1224,8 @@ def dict_to_dnode(
12071224 rpcreply : bool = False ,
12081225 notification : bool = False ,
12091226 store_only : bool = False ,
1227+ types : Optional [Tuple [int , ...]] = None ,
1228+ anydata_fmt : str = "json" ,
12101229) -> Optional [DNode ]:
12111230 """
12121231 Convert a python dictionary to a DNode object given a YANG module object. The return
@@ -1316,6 +1335,34 @@ def _create_list(_parent, module, name, key_values, in_rpc_output=False):
13161335 created .append (n [0 ])
13171336 return n [0 ]
13181337
1338+ def _create_anydata (_parent , module , name , value , in_rpc_output = False ):
1339+ if value is not None :
1340+ if isinstance (value , dict ) and anydata_fmt == "json" :
1341+ value = json .dumps (value )
1342+ elif not isinstance (value , str ):
1343+ value = str (value )
1344+
1345+ n = ffi .new ("struct lyd_node **" )
1346+ flags = newval_flags (rpc_output = in_rpc_output , store_only = store_only )
1347+ ret = lib .lyd_new_any (
1348+ _parent ,
1349+ module .cdata ,
1350+ str2c (name ),
1351+ str2c (value ),
1352+ anydata_format (anydata_fmt ),
1353+ flags ,
1354+ n ,
1355+ )
1356+ if ret != lib .LY_SUCCESS :
1357+ if _parent :
1358+ parent_path = repr (DNode .new (module .context , _parent ).path ())
1359+ else :
1360+ parent_path = "module %r" % module .name ()
1361+ raise module .context .error (
1362+ "failed to create leaf %r as a child of %s" , name , parent_path
1363+ )
1364+ created .append (n [0 ])
1365+
13191366 schema_cache = {}
13201367
13211368 def _find_schema (schema_parent , name , prefix ):
@@ -1332,7 +1379,7 @@ def _find_schema(schema_parent, name, prefix):
13321379 if schema_parent is None :
13331380 # there may not be any input or any output node in the rpc
13341381 return None , None
1335- for s in schema_parent :
1382+ for s in schema_parent . children ( types = types ) :
13361383 if s .name () != name :
13371384 continue
13381385 mod = s .module ()
@@ -1432,6 +1479,9 @@ def _to_dnode(_dic, _schema, _parent=ffi.NULL, in_rpc_output=False):
14321479 n = _create_container (_parent , module , name , in_rpc_output )
14331480 _to_dnode (value , s , n , in_rpc_output )
14341481
1482+ elif isinstance (s , SAnydata ):
1483+ _create_anydata (_parent , module , name , value , in_rpc_output )
1484+
14351485 result = None
14361486
14371487 try :
0 commit comments