Skip to content

Commit

Permalink
data: introduce store_only flags
Browse files Browse the repository at this point in the history
This patch introduces store_only flag, which allows user to only store
value without performing any sort of additional type checks as length,
range, pattern, etc.

Closes: #107
Signed-off-by: Stefan Gula <steweg@gmail.com>
Signed-off-by: Samuel Gauthier <samuel.gauthier@6wind.com>
  • Loading branch information
steweg authored and samuel-gauthier committed Sep 27, 2024
1 parent 0c43437 commit 5330a3f
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 7 deletions.
2 changes: 2 additions & 0 deletions cffi/cdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ...
Expand Down Expand Up @@ -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 ...
Expand Down
11 changes: 10 additions & 1 deletion libyang/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand All @@ -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,
Expand Down Expand Up @@ -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")
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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(
Expand All @@ -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,
Expand All @@ -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]:
Expand Down
24 changes: 19 additions & 5 deletions libyang/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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


Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -391,13 +399,15 @@ 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,
rpc_output=opt_output,
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
Expand Down Expand Up @@ -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]:
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 8 additions & 0 deletions tests/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
4 changes: 3 additions & 1 deletion tests/yang/yolo/yolo-nodetypes.yang
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ module yolo-nodetypes {
}

leaf test1 {
type uint8;
type uint8 {
range "2..20";
}
}

grouping grp1 {
Expand Down

0 comments on commit 5330a3f

Please sign in to comment.