Skip to content
Snippets Groups Projects
Commit 46126c95 authored by Ladislav Lhotka's avatar Ladislav Lhotka
Browse files

Implement submodule handling.

parent 01e34dec
No related branches found
No related tags found
No related merge requests found
......@@ -10,7 +10,7 @@ def contents(*filenames):
setup(
name = "yangson",
packages = ["yangson"],
version = "0.1.19",
version = "0.1.20",
description = "Library for working with YANG schemas and data",
author = "Ladislav Lhotka",
author_email = "lhotka@nic.cz",
......
......@@ -17,6 +17,9 @@ class Context:
prefix_map = {} # type: Dict[ModuleId, Dict[YangIdentifier, ModuleId]]
"""Per-module prefix assignments."""
ns_map = {} # type: Dict[YangIdentifier, YangIdentifier]
"""Map of module and submodule names to namespaces."""
@classmethod
def resolve_qname(cls, mid: ModuleId,
qname: QName) -> Tuple[ModuleId, YangIdentifier]:
......@@ -29,7 +32,7 @@ class Context:
try:
return (cls.prefix_map[mid][p], loc) if s else (mid, p)
except KeyError:
raise BadQName(qname)
raise BadQName(qname) from None
@classmethod
def translate_qname(cls, mid: ModuleId, qname: QName) -> NodeName:
......
......@@ -5,6 +5,7 @@ from .exception import YangsonException
from .instance import Crumb, Instance, InstanceIdentifier, MemberName
from .modparser import from_file
from .schema import InternalNode, NonexistentSchemaNode, RawObject
from .statement import Statement
from .typealiases import *
from .regex import *
......@@ -27,16 +28,27 @@ class DataModel:
yl = json.loads(txt)
for item in yl["ietf-yang-library:modules-state"]["module"]:
name = item["name"]
Context.ns_map[name] = name
rev = item["revision"] if item["revision"] else None
mid = (name, rev)
ct = item["conformance-type"]
if ct == "implement": implement.append(mid)
revisions.setdefault(name, []).append(rev)
cls.load_module(name, rev, mod_dir)
mod = cls.load_module(name, rev, mod_dir)
locpref = mod.find1("prefix", required=True).argument
Context.prefix_map[mid] = { locpref: mid }
if "submodules" in item and "submodule" in item["submodules"]:
for s in item["submodules"]["submodule"]:
sname = s["name"]
Context.ns_map[sname] = name
rev = s["revision"] if s["revision"] else None
cls.load_module(s["name"], rev, mod_dir)
smid = (sname, rev)
if ct == "implement": implement.append(smid)
revisions.setdefault(sname, []).append(rev)
submod = cls.load_module(sname, rev, mod_dir)
bt = submod.find1("belongs-to", name, required=True)
locpref = bt.find1("prefix", required=True).argument
Context.prefix_map[smid] = { locpref: mid }
except (json.JSONDecodeError, KeyError, AttributeError):
raise BadYangLibraryData()
res = cls(revisions, implement)
......@@ -45,7 +57,7 @@ class DataModel:
@classmethod
def load_module(cls, name: YangIdentifier, rev: RevisionDate,
mod_dir: str = ".") -> None:
mod_dir: str = ".") -> Statement:
"""Read, parse and register YANG module or submodule.
:param name: module or submodule name
......@@ -55,7 +67,8 @@ class DataModel:
"""
fn = "{}/{}".format(mod_dir, name)
if rev: fn += "@" + rev
Context.modules[(name, rev)] = from_file(fn + ".yang")
Context.modules[(name, rev)] = res = from_file(fn + ".yang")
return res
def __init__(self,
revisions: Dict[YangIdentifier, List[RevisionDate]],
......@@ -90,8 +103,6 @@ class DataModel:
mods = Context.modules
for mid in mods:
mod = mods[mid]
locpref = mod.find1("prefix", required=True).argument
Context.prefix_map[mid] = pmap = { locpref: mid }
try:
pos = self.implement.index(mid)
except ValueError: # mod not implemented
......@@ -108,8 +119,8 @@ class DataModel:
break
if imid is None and rev is None: # use last revision in the list
imid = (iname, self.revisions[iname][-1])
pmap[prefix] = imid
if pos is None: return
Context.prefix_map[mid][prefix] = imid
if pos is None: continue
i = pos
while i < len(self.implement):
if self.implement[i] == imid:
......
......@@ -80,6 +80,7 @@ class SchemaNode:
"default": "default_stmt",
"ietf-netconf-acm:default-deny-all": "nacm_default_deny_stmt",
"ietf-netconf-acm:default-deny-write": "nacm_default_deny_stmt",
"include": "include_stmt",
"leaf": "leaf_stmt",
"leaf-list": "leaf_list_stmt",
"list": "list_stmt",
......@@ -160,7 +161,7 @@ class InternalNode(SchemaNode):
:param mid: module context
"""
node.name = stmt.argument
node.ns = mid[0] if self._nsswitch else self.ns
node.ns = Context.ns_map[mid[0]] if self._nsswitch else self.ns
self.add_child(node)
node.handle_substatements(stmt, mid)
......@@ -171,6 +172,12 @@ class InternalNode(SchemaNode):
target._nsswitch = nsswitch
target.handle_substatements(stmt, mid)
def include_stmt(self, stmt: Statement, mid: ModuleId) -> None:
name = stmt.argument
revst = stmt.find1("revision-date")
smid = (name, revst.argument if revst else None)
self.handle_substatements(Context.modules[smid], smid)
def uses_stmt(self, stmt: Statement, mid: ModuleId) -> None:
"""Handle uses statement."""
grp, gid = Context.get_definition(stmt, mid)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment