Skip to content

Commit 3a4ee8e

Browse files
committed
data: introduce store_only flags
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. Signed-off-by: Stefan Gula <[email protected]>
1 parent f14116c commit 3a4ee8e

File tree

5 files changed

+41
-7
lines changed

5 files changed

+41
-7
lines changed

cffi/cdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ struct lyd_node {
264264
LY_ERR lys_set_implemented(struct lys_module *, const char **);
265265

266266
#define LYD_NEW_VAL_OUTPUT ...
267+
#define LYD_NEW_VAL_STORE_ONLY ...
267268
#define LYD_NEW_VAL_BIN ...
268269
#define LYD_NEW_VAL_CANON ...
269270
#define LYD_NEW_META_CLEAR_DFLT ...

libyang/context.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ def create_data_path(
244244
parent: Optional[DNode] = None,
245245
value: Any = None,
246246
update: bool = True,
247+
store_only: bool = False,
247248
rpc_output: bool = False,
248249
force_return_value: bool = True,
249250
) -> Optional[DNode]:
@@ -254,7 +255,9 @@ def create_data_path(
254255
value = str(value).lower()
255256
elif not isinstance(value, str):
256257
value = str(value)
257-
flags = newval_flags(update=update, rpc_output=rpc_output)
258+
flags = newval_flags(
259+
update=update, store_only=store_only, rpc_output=rpc_output
260+
)
258261
dnode = ffi.new("struct lyd_node **")
259262
ret = lib.lyd_new_path(
260263
parent.cdata if parent else ffi.NULL,
@@ -348,6 +351,7 @@ def parse_data(
348351
strict: bool = False,
349352
validate_present: bool = False,
350353
validate_multi_error: bool = False,
354+
store_only: bool = False,
351355
) -> Optional[DNode]:
352356
if self.cdata is None:
353357
raise RuntimeError("context already destroyed")
@@ -358,6 +362,7 @@ def parse_data(
358362
opaq=opaq,
359363
ordered=ordered,
360364
strict=strict,
365+
store_only=store_only,
361366
)
362367
validation_flgs = validation_flags(
363368
no_state=no_state,
@@ -415,6 +420,7 @@ def parse_data_mem(
415420
strict: bool = False,
416421
validate_present: bool = False,
417422
validate_multi_error: bool = False,
423+
store_only: bool = False,
418424
) -> Optional[DNode]:
419425
return self.parse_data(
420426
fmt,
@@ -429,6 +435,7 @@ def parse_data_mem(
429435
strict=strict,
430436
validate_present=validate_present,
431437
validate_multi_error=validate_multi_error,
438+
store_only=store_only,
432439
)
433440

434441
def parse_data_file(
@@ -444,6 +451,7 @@ def parse_data_file(
444451
strict: bool = False,
445452
validate_present: bool = False,
446453
validate_multi_error: bool = False,
454+
store_only: bool = False,
447455
) -> Optional[DNode]:
448456
return self.parse_data(
449457
fmt,
@@ -458,6 +466,7 @@ def parse_data_file(
458466
strict=strict,
459467
validate_present=validate_present,
460468
validate_multi_error=validate_multi_error,
469+
store_only=store_only,
461470
)
462471

463472
def __iter__(self) -> Iterator[Module]:

libyang/data.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def data_format(fmt_string: str) -> int:
7979
# -------------------------------------------------------------------------------------
8080
def newval_flags(
8181
rpc_output: bool = False,
82+
store_only: bool = False,
8283
bin_value: bool = False,
8384
canon_value: bool = False,
8485
meta_clear_default: bool = False,
@@ -91,6 +92,8 @@ def newval_flags(
9192
flags = 0
9293
if rpc_output:
9394
flags |= lib.LYD_NEW_VAL_OUTPUT
95+
if store_only:
96+
flags |= lib.LYD_NEW_VAL_STORE_ONLY
9497
if bin_value:
9598
flags |= lib.LYD_NEW_VAL_BIN
9699
if canon_value:
@@ -112,6 +115,7 @@ def parser_flags(
112115
opaq: bool = False,
113116
ordered: bool = False,
114117
strict: bool = False,
118+
store_only: bool = False,
115119
) -> int:
116120
flags = 0
117121
if lyb_mod_update:
@@ -126,6 +130,8 @@ def parser_flags(
126130
flags |= lib.LYD_PARSE_ORDERED
127131
if strict:
128132
flags |= lib.LYD_PARSE_STRICT
133+
if store_only:
134+
flags |= lib.LYD_PARSE_STORE_ONLY
129135
return flags
130136

131137

@@ -314,8 +320,10 @@ def meta_free(self, name):
314320
break
315321
item = item.next
316322

317-
def new_meta(self, name: str, value: str, clear_dflt: bool = False):
318-
flags = newval_flags(meta_clear_default=clear_dflt)
323+
def new_meta(
324+
self, name: str, value: str, clear_dflt: bool = False, store_only: bool = False
325+
):
326+
flags = newval_flags(meta_clear_default=clear_dflt, store_only=store_only)
319327
ret = lib.lyd_new_meta(
320328
ffi.NULL,
321329
self.cdata,
@@ -391,13 +399,15 @@ def new_path(
391399
opt_opaq: bool = False,
392400
opt_bin_value: bool = False,
393401
opt_canon_value: bool = False,
402+
opt_store_only: bool = False,
394403
):
395404
flags = newval_flags(
396405
update=opt_update,
397406
rpc_output=opt_output,
398407
opaq=opt_opaq,
399408
bin_value=opt_bin_value,
400409
canon_value=opt_canon_value,
410+
store_only=opt_store_only,
401411
)
402412
ret = lib.lyd_new_path(
403413
self.cdata, ffi.NULL, str2c(path), str2c(value), flags, ffi.NULL
@@ -1062,9 +1072,10 @@ def create_path(
10621072
path: str,
10631073
value: Any = None,
10641074
rpc_output: bool = False,
1075+
store_only: bool = False,
10651076
) -> Optional[DNode]:
10661077
return self.context.create_data_path(
1067-
path, parent=self, value=value, rpc_output=rpc_output
1078+
path, parent=self, value=value, rpc_output=rpc_output, store_only=store_only
10681079
)
10691080

10701081
def children(self, no_keys=False) -> Iterator[DNode]:
@@ -1188,6 +1199,7 @@ def dict_to_dnode(
11881199
rpc: bool = False,
11891200
rpcreply: bool = False,
11901201
notification: bool = False,
1202+
store_only: bool = False,
11911203
) -> Optional[DNode]:
11921204
"""
11931205
Convert a python dictionary to a DNode object given a YANG module object. The return
@@ -1214,6 +1226,8 @@ def dict_to_dnode(
12141226
Data represents RPC or action output parameters.
12151227
:arg notification:
12161228
Data represents notification parameters.
1229+
:arg store_only:
1230+
Data are being stored regardless of type validation (length, range, pattern, etc.)
12171231
"""
12181232
if not dic:
12191233
return None
@@ -1235,7 +1249,7 @@ def _create_leaf(_parent, module, name, value, in_rpc_output=False):
12351249
value = str(value)
12361250

12371251
n = ffi.new("struct lyd_node **")
1238-
flags = newval_flags(rpc_output=in_rpc_output)
1252+
flags = newval_flags(rpc_output=in_rpc_output, store_only=store_only)
12391253
ret = lib.lyd_new_term(
12401254
_parent,
12411255
module.cdata,
@@ -1273,7 +1287,7 @@ def _create_container(_parent, module, name, in_rpc_output=False):
12731287

12741288
def _create_list(_parent, module, name, key_values, in_rpc_output=False):
12751289
n = ffi.new("struct lyd_node **")
1276-
flags = newval_flags(rpc_output=in_rpc_output)
1290+
flags = newval_flags(rpc_output=in_rpc_output, store_only=store_only)
12771291
ret = lib.lyd_new_list(
12781292
_parent,
12791293
module.cdata,

tests/test_data.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,3 +1092,11 @@ def test_dnode_leafref_linking(self):
10921092
self.assertIsInstance(dnode4, DLeaf)
10931093
self.assertEqual(dnode4.cdata, dnode2.cdata)
10941094
dnode1.free()
1095+
1096+
def test_dnode_store_only(self):
1097+
MAIN = {"yolo-nodetypes:test1": 50}
1098+
module = self.ctx.load_module("yolo-nodetypes")
1099+
dnode = dict_to_dnode(MAIN, module, None, validate=False, store_only=True)
1100+
self.assertIsInstance(dnode, DLeaf)
1101+
self.assertEqual(dnode.value(), 50)
1102+
dnode.free()

tests/yang/yolo/yolo-nodetypes.yang

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ module yolo-nodetypes {
9191
}
9292

9393
leaf test1 {
94-
type uint8;
94+
type uint8 {
95+
range "2..20";
96+
}
9597
}
9698

9799
grouping grp1 {

0 commit comments

Comments
 (0)