Skip to content
This repository has been archived by the owner on Jul 3, 2020. It is now read-only.

Commit

Permalink
all: use standard python arguments instead of C flags
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Jarry <robin@jarry.cc>
  • Loading branch information
rjarry committed Apr 29, 2020
1 parent ac2d7a9 commit d09f1c2
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 60 deletions.
4 changes: 4 additions & 0 deletions cffi/cdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,11 @@ typedef enum {
...
} LYD_ANYDATA_VALUETYPE;

#define LYP_WITHSIBLINGS ...
#define LYP_FORMAT ...
#define LYP_WD_TRIM ...
#define LYP_WD_ALL ...
#define LYP_KEEPEMPTYCONT ...

#define LYD_ANYDATA_CONSTSTRING ...

Expand Down
40 changes: 29 additions & 11 deletions libyang/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
from _libyang import lib

from .data import DNode
from .data import PathOpt
from .data import data_format
from .data import parser_flags
from .data import path_flags
from .schema import Module
from .schema import SNode
from .schema import schema_in_format
from .util import LibyangError
from .util import c2str
from .util import str2c
Expand All @@ -35,13 +38,15 @@
#------------------------------------------------------------------------------
class Context(object):

def __init__(self, search_path=None,
options=lib.LY_CTX_DISABLE_SEARCHDIR_CWD,
pointer=None):
def __init__(self, search_path=None, disable_searchdir_cwd=True, pointer=None):
if pointer is not None:
self._ctx = ffi.cast('struct ly_ctx *', pointer)
return # already initialized

options = 0
if disable_searchdir_cwd:
options |= lib.LY_CTX_DISABLE_SEARCHDIR_CWD

self._ctx = ffi.gc(lib.ly_ctx_new(ffi.NULL, options),
lambda c: lib.ly_ctx_destroy(c, ffi.NULL))
if not self._ctx:
Expand Down Expand Up @@ -76,14 +81,16 @@ def error(self, msg, *args):

return LibyangError(msg)

def parse_module_file(self, fileobj, fmt=lib.LYS_IN_YANG):
def parse_module_file(self, fileobj, fmt='yang'):
fmt = schema_in_format(fmt)
mod = lib.lys_parse_fd(self._ctx, fileobj.fileno(), fmt)
if not mod:
raise self.error('cannot parse module')

return Module(self, mod)

def parse_module_str(self, s, fmt=lib.LYS_IN_YANG):
def parse_module_str(self, s, fmt='yang'):
fmt = schema_in_format(fmt)
mod = lib.lys_parse_mem(self._ctx, str2c(s), fmt)
if not mod:
raise self.error('cannot parse module')
Expand Down Expand Up @@ -114,17 +121,18 @@ def find_path(self, path):
finally:
lib.ly_set_free(node_set)

def create_data_path(self, path, parent=None, value=None, flags=0):
def create_data_path(self, path, parent=None, value=None, rpc_output=False):
lib.lypy_set_errno(0)
if value is not None:
if isinstance(value, bool):
value = str(value).lower()
elif not isinstance(value, str):
value = str(value)
flags = path_flags(
update=True, no_parent_ret=True, rpc_output=rpc_output)
dnode = lib.lyd_new_path(
parent._node if parent else ffi.NULL,
self._ctx, str2c(path), str2c(value), 0,
PathOpt.UPDATE | PathOpt.NOPARENTRET | flags)
self._ctx, str2c(path), str2c(value), 0, flags)
if lib.lypy_get_errno() != 0:
raise self.error('cannot create data path: %s', path)

Expand All @@ -145,13 +153,23 @@ def create_data_path(self, path, parent=None, value=None, flags=0):

return DNode.new(self, dnode)

def parse_data_str(self, s, fmt, flags=0):
def parse_data_str(self, s, fmt, data=False, config=False, strict=False,
trusted=False, no_yanglib=False):
flags = parser_flags(
data=data, config=config, strict=strict, trusted=trusted,
no_yanglib=no_yanglib)
fmt = data_format(fmt)
dnode = lib.lyd_parse_mem(self._ctx, str2c(s), fmt, flags)
if not dnode:
raise self.error('failed to parse data tree')
return DNode.new(self, dnode)

def parse_data_file(self, fileobj, fmt, flags=0):
def parse_data_file(self, fileobj, fmt, data=False, config=False,
strict=False, trusted=False, no_yanglib=False):
flags = parser_flags(
data=data, config=config, strict=strict, trusted=trusted,
no_yanglib=no_yanglib)
fmt = data_format(fmt)
dnode = lib.lyd_parse_fd(self._ctx, fileobj.fileno(), fmt, flags)
if not dnode:
raise self.error('failed to parse data tree')
Expand Down
109 changes: 81 additions & 28 deletions libyang/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,60 @@


#------------------------------------------------------------------------------
class PrintFmt: # TODO: use enum when dropping python2 support
XML = lib.LYD_XML
JSON = lib.LYD_JSON
LYB = lib.LYD_LYB
def printer_flags(with_siblings=False, pretty=False, keep_empty_containers=False,
trim_default_values=False, include_implicit_defaults=False):
flags = 0
if with_siblings:
flags |= lib.LYP_WITHSIBLINGS
if pretty:
flags |= lib.LYP_FORMAT
if keep_empty_containers:
flags |= lib.LYP_KEEPEMPTYCONT
if trim_default_values:
flags |= lib.LYP_WD_TRIM
if include_implicit_defaults:
flags |= lib.LYP_WD_ALL
return flags


#------------------------------------------------------------------------------
class PrintOpt: # TODO: use enum when dropping python2 support
PRETTY = lib.LYP_FORMAT
def data_format(fmt_string):
if fmt_string == 'json':
return lib.LYD_JSON
if fmt_string == 'xml':
return lib.LYD_XML
if fmt_string == 'lyb':
return lib.LYD_LYB
raise ValueError('unknown data format: %r' % fmt_string)


#------------------------------------------------------------------------------
class PathOpt: # TODO: use enum when dropping python2 support
UPDATE = lib.LYD_PATH_OPT_UPDATE
OUTPUT = lib.LYD_PATH_OPT_OUTPUT
NOPARENTRET = lib.LYD_PATH_OPT_NOPARENTRET
def path_flags(update=False, rpc_output=False, no_parent_ret=False):
flags = 0
if update:
flags |= lib.LYD_PATH_OPT_UPDATE
if rpc_output:
flags |= lib.LYD_PATH_OPT_OUTPUT
if no_parent_ret:
flags |= lib.LYD_PATH_OPT_NOPARENTRET
return flags


#------------------------------------------------------------------------------
class ParserOpt: # TODO: use enum when dropping python2 support
DATA = lib.LYD_OPT_DATA
CONFIG = lib.LYD_OPT_CONFIG
STRICT = lib.LYD_OPT_STRICT
TRUSTED = lib.LYD_OPT_TRUSTED
NO_YANGLIB = lib.LYD_OPT_DATA_NO_YANGLIB
def parser_flags(data=False, config=False, strict=False, trusted=False,
no_yanglib=False):
flags = 0
if data:
flags |= lib.LYD_OPT_DATA
if config:
flags |= lib.LYD_OPT_CONFIG
if strict:
flags |= lib.LYD_OPT_STRICT
if trusted:
flags |= lib.LYD_OPT_TRUSTED
if no_yanglib:
flags |= lib.LYD_OPT_DATA_NO_YANGLIB
return flags


#------------------------------------------------------------------------------
Expand Down Expand Up @@ -99,15 +128,30 @@ def path(self):
finally:
lib.free(path)

def validate(self, flags=0):
def validate(self, data=False, config=False, strict=False, trusted=False,
no_yanglib=False):
flags = parser_flags(
data=data, config=config, strict=strict, trusted=trusted,
no_yanglib=no_yanglib)
node_p = ffi.new('struct lyd_node **')
node_p[0] = self._node
ret = lib.lyd_validate(node_p, flags, ffi.NULL)
if ret != 0:
self.context.error('validation failed')

def dump_str(self, fmt=PrintFmt.JSON, flags=0):
def dump_str(self, fmt,
with_siblings=False,
pretty=False,
include_implicit_defaults=False,
trim_default_values=False,
keep_empty_containers=False):
flags = printer_flags(
with_siblings=with_siblings, pretty=pretty,
include_implicit_defaults=include_implicit_defaults,
trim_default_values=trim_default_values,
keep_empty_containers=keep_empty_containers)
buf = ffi.new('char **')
fmt = data_format(fmt)
ret = lib.lyd_print_mem(buf, self._node, fmt, flags)
if ret != 0:
raise self.context.error('cannot print node')
Expand All @@ -116,7 +160,18 @@ def dump_str(self, fmt=PrintFmt.JSON, flags=0):
finally:
lib.free(buf[0])

def dump_file(self, fileobj, fmt=PrintFmt.JSON, flags=0):
def dump_file(self, fileobj, fmt,
with_siblings=False,
pretty=False,
include_implicit_defaults=False,
trim_default_values=False,
keep_empty_containers=False):
flags = printer_flags(
with_siblings=with_siblings, pretty=pretty,
include_implicit_defaults=include_implicit_defaults,
trim_default_values=trim_default_values,
keep_empty_containers=keep_empty_containers)
fmt = data_format(fmt)
ret = lib.lyd_print_fd(fileobj.fileno(), self._node, fmt, flags)
if ret != 0:
raise self.context.error('cannot print node')
Expand Down Expand Up @@ -158,9 +213,9 @@ def new(cls, context, node_p):
@DNode.register(SNode.CONTAINER)
class DContainer(DNode):

def create_path(self, path, value=None, flags=0):
def create_path(self, path, value=None, rpc_output=False):
return self.context.create_data_path(
path, parent=self, value=value, flags=flags)
path, parent=self, value=value, rpc_output=rpc_output)

def children(self):
child = self._node.child
Expand Down Expand Up @@ -279,10 +334,6 @@ def dict_to_dnode(dic, schema, parent=None, rpc_input=False, rpc_output=False):
if not isinstance(dic, dict):
raise TypeError('dic argument must be a python dict')

flags = 0
if rpc_output:
flags |= PathOpt.OUTPUT

# XXX: ugly, required for python2. Cannot use nonlocal keyword
_parent = [parent]

Expand All @@ -309,7 +360,8 @@ def _to_dnode(_dic, _schema, key=()):
% (s.schema_path(), d))
if s.presence():
dnode = s.context.create_data_path(
s.data_path() % key, parent=_parent[0], flags=flags)
s.data_path() % key, parent=_parent[0],
rpc_output=rpc_output)
if _parent[0] is None:
_parent[0] = dnode
_to_dnode(d, s, key)
Expand Down Expand Up @@ -343,12 +395,13 @@ def _to_dnode(_dic, _schema, key=()):
for element in d:
dnode = s.context.create_data_path(
s.data_path() % key, parent=_parent[0],
value=element, flags=flags)
value=element, rpc_output=rpc_output)
if _parent[0] is None:
_parent[0] = dnode
elif isinstance(s, SLeaf):
dnode = s.context.create_data_path(
s.data_path() % key, parent=_parent[0], value=d, flags=flags)
s.data_path() % key, parent=_parent[0], value=d,
rpc_output=rpc_output)
if _parent[0] is None:
_parent[0] = dnode

Expand Down
30 changes: 28 additions & 2 deletions libyang/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,30 @@
from .util import str2c


#------------------------------------------------------------------------------
def schema_in_format(fmt_string):
if fmt_string == 'yang':
return lib.LYS_IN_YANG
if fmt_string == 'yin':
return lib.LYS_IN_YIN
raise ValueError('unknown schema input format: %r' % fmt_string)


#------------------------------------------------------------------------------
def schema_out_format(fmt_string):
if fmt_string == 'yang':
return lib.LYS_OUT_YANG
if fmt_string == 'yin':
return lib.LYS_OUT_YIN
if fmt_string == 'tree':
return lib.LYS_OUT_TREE
if fmt_string == 'info':
return lib.LYS_OUT_INFO
if fmt_string == 'json':
return lib.LYS_OUT_JSON
raise ValueError('unknown schema output format: %r' % fmt_string)


#------------------------------------------------------------------------------
class Module(object):

Expand Down Expand Up @@ -72,7 +96,8 @@ def children(self, types=None):
def __str__(self):
return self.dump_str()

def dump_str(self, fmt=lib.LYS_OUT_TREE, path=None):
def dump_str(self, fmt='tree', path=None):
fmt = schema_out_format(fmt)
buf = ffi.new('char **')
ret = lib.lys_print_mem(buf, self._module, fmt, str2c(path), 0, 0)
if ret != 0:
Expand All @@ -82,7 +107,8 @@ def dump_str(self, fmt=lib.LYS_OUT_TREE, path=None):
finally:
lib.free(buf[0])

def dump_file(self, fileobj, fmt=lib.LYS_OUT_TREE, path=None):
def dump_file(self, fileobj, fmt='tree', path=None):
fmt = schema_out_format(fmt)
ret = lib.lys_print_fd(
fileobj.fileno(), self._module, fmt, str2c(path), 0, 0)
if ret != 0:
Expand Down
Loading

0 comments on commit d09f1c2

Please sign in to comment.