diff --git a/cffi/cdefs.h b/cffi/cdefs.h index 499a1b3..6f20187 100644 --- a/cffi/cdefs.h +++ b/cffi/cdefs.h @@ -264,6 +264,7 @@ struct lyd_node { LY_ERR lys_set_implemented(struct lys_module *, const char **); #define LYD_NEW_VAL_OUTPUT ... +#define LYD_NEW_VAL_STORE_ONLY ... #define LYD_NEW_VAL_BIN ... #define LYD_NEW_VAL_CANON ... #define LYD_NEW_META_CLEAR_DFLT ... @@ -308,6 +309,7 @@ LY_ERR lyd_print_all(struct ly_out *, const struct lyd_node *, LYD_FORMAT, uint3 #define LYD_PARSE_LYB_MOD_UPDATE ... #define LYD_PARSE_NO_STATE ... +#define LYD_PARSE_STORE_ONLY ... #define LYD_PARSE_ONLY ... #define LYD_PARSE_OPAQ ... #define LYD_PARSE_OPTS_MASK ... diff --git a/libyang/context.py b/libyang/context.py index b457e7b..b08df0c 100644 --- a/libyang/context.py +++ b/libyang/context.py @@ -409,6 +409,7 @@ def create_data_path( parent: Optional[DNode] = None, value: Any = None, update: bool = True, + store_only: bool = False, rpc_output: bool = False, force_return_value: bool = True, ) -> Optional[DNode]: @@ -419,7 +420,9 @@ def create_data_path( value = str(value).lower() elif not isinstance(value, str): value = str(value) - flags = newval_flags(update=update, rpc_output=rpc_output) + flags = newval_flags( + update=update, store_only=store_only, rpc_output=rpc_output + ) dnode = ffi.new("struct lyd_node **") ret = lib.lyd_new_path( parent.cdata if parent else ffi.NULL, @@ -513,6 +516,7 @@ def parse_data( strict: bool = False, validate_present: bool = False, validate_multi_error: bool = False, + store_only: bool = False, ) -> Optional[DNode]: if self.cdata is None: raise RuntimeError("context already destroyed") @@ -523,6 +527,7 @@ def parse_data( opaq=opaq, ordered=ordered, strict=strict, + store_only=store_only, ) validation_flgs = validation_flags( no_state=no_state, @@ -580,6 +585,7 @@ def parse_data_mem( strict: bool = False, validate_present: bool = False, validate_multi_error: bool = False, + store_only: bool = False, ) -> Optional[DNode]: return self.parse_data( fmt, @@ -594,6 +600,7 @@ def parse_data_mem( strict=strict, validate_present=validate_present, validate_multi_error=validate_multi_error, + store_only=store_only, ) def parse_data_file( @@ -609,6 +616,7 @@ def parse_data_file( strict: bool = False, validate_present: bool = False, validate_multi_error: bool = False, + store_only: bool = False, ) -> Optional[DNode]: return self.parse_data( fmt, @@ -623,6 +631,7 @@ def parse_data_file( strict=strict, validate_present=validate_present, validate_multi_error=validate_multi_error, + store_only=store_only, ) def __iter__(self) -> Iterator[Module]: diff --git a/libyang/data.py b/libyang/data.py index 00490db..288303d 100644 --- a/libyang/data.py +++ b/libyang/data.py @@ -79,6 +79,7 @@ def data_format(fmt_string: str) -> int: # ------------------------------------------------------------------------------------- def newval_flags( rpc_output: bool = False, + store_only: bool = False, bin_value: bool = False, canon_value: bool = False, meta_clear_default: bool = False, @@ -91,6 +92,8 @@ def newval_flags( flags = 0 if rpc_output: flags |= lib.LYD_NEW_VAL_OUTPUT + if store_only: + flags |= lib.LYD_NEW_VAL_STORE_ONLY if bin_value: flags |= lib.LYD_NEW_VAL_BIN if canon_value: @@ -112,6 +115,7 @@ def parser_flags( opaq: bool = False, ordered: bool = False, strict: bool = False, + store_only: bool = False, ) -> int: flags = 0 if lyb_mod_update: @@ -126,6 +130,8 @@ def parser_flags( flags |= lib.LYD_PARSE_ORDERED if strict: flags |= lib.LYD_PARSE_STRICT + if store_only: + flags |= lib.LYD_PARSE_STORE_ONLY return flags @@ -314,8 +320,10 @@ def meta_free(self, name): break item = item.next - def new_meta(self, name: str, value: str, clear_dflt: bool = False): - flags = newval_flags(meta_clear_default=clear_dflt) + def new_meta( + self, name: str, value: str, clear_dflt: bool = False, store_only: bool = False + ): + flags = newval_flags(meta_clear_default=clear_dflt, store_only=store_only) ret = lib.lyd_new_meta( ffi.NULL, self.cdata, @@ -391,6 +399,7 @@ def new_path( opt_opaq: bool = False, opt_bin_value: bool = False, opt_canon_value: bool = False, + opt_store_only: bool = False, ): flags = newval_flags( update=opt_update, @@ -398,6 +407,7 @@ def new_path( opaq=opt_opaq, bin_value=opt_bin_value, canon_value=opt_canon_value, + store_only=opt_store_only, ) ret = lib.lyd_new_path( self.cdata, ffi.NULL, str2c(path), str2c(value), flags, ffi.NULL @@ -1062,9 +1072,10 @@ def create_path( path: str, value: Any = None, rpc_output: bool = False, + store_only: bool = False, ) -> Optional[DNode]: return self.context.create_data_path( - path, parent=self, value=value, rpc_output=rpc_output + path, parent=self, value=value, rpc_output=rpc_output, store_only=store_only ) def children(self, no_keys=False) -> Iterator[DNode]: @@ -1188,6 +1199,7 @@ def dict_to_dnode( rpc: bool = False, rpcreply: bool = False, notification: bool = False, + store_only: bool = False, ) -> Optional[DNode]: """ Convert a python dictionary to a DNode object given a YANG module object. The return @@ -1214,6 +1226,8 @@ def dict_to_dnode( Data represents RPC or action output parameters. :arg notification: Data represents notification parameters. + :arg store_only: + Data are being stored regardless of type validation (length, range, pattern, etc.) """ if not dic: return None @@ -1235,7 +1249,7 @@ def _create_leaf(_parent, module, name, value, in_rpc_output=False): value = str(value) n = ffi.new("struct lyd_node **") - flags = newval_flags(rpc_output=in_rpc_output) + flags = newval_flags(rpc_output=in_rpc_output, store_only=store_only) ret = lib.lyd_new_term( _parent, module.cdata, @@ -1273,7 +1287,7 @@ def _create_container(_parent, module, name, in_rpc_output=False): def _create_list(_parent, module, name, key_values, in_rpc_output=False): n = ffi.new("struct lyd_node **") - flags = newval_flags(rpc_output=in_rpc_output) + flags = newval_flags(rpc_output=in_rpc_output, store_only=store_only) ret = lib.lyd_new_list( _parent, module.cdata, diff --git a/tests/test_data.py b/tests/test_data.py index 9ed35dc..9515a58 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -1092,3 +1092,11 @@ def test_dnode_leafref_linking(self): self.assertIsInstance(dnode4, DLeaf) self.assertEqual(dnode4.cdata, dnode2.cdata) dnode1.free() + + def test_dnode_store_only(self): + MAIN = {"yolo-nodetypes:test1": 50} + module = self.ctx.load_module("yolo-nodetypes") + dnode = dict_to_dnode(MAIN, module, None, validate=False, store_only=True) + self.assertIsInstance(dnode, DLeaf) + self.assertEqual(dnode.value(), 50) + dnode.free() diff --git a/tests/yang/yolo/yolo-nodetypes.yang b/tests/yang/yolo/yolo-nodetypes.yang index 0732ee7..de4656b 100644 --- a/tests/yang/yolo/yolo-nodetypes.yang +++ b/tests/yang/yolo/yolo-nodetypes.yang @@ -91,7 +91,9 @@ module yolo-nodetypes { } leaf test1 { - type uint8; + type uint8 { + range "2..20"; + } } grouping grp1 {