Skip to content

Commit

Permalink
Added support for lists without a key using an auto-generated uuid key
Browse files Browse the repository at this point in the history
	* (M)	as per #3 - a config false list can now be created without
			a key value. A UUID is generated for the key which is
			returned to the user to be used when referring to the entry
			in question.
  • Loading branch information
Rob Shakir committed May 24, 2015
1 parent cded63b commit 4fa7f47
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 28 deletions.
63 changes: 39 additions & 24 deletions pybind.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ def build_pybind(ctx, modules, fd):
fd.write("from operator import attrgetter\n")
fd.write("import numpy as np\n")
fd.write("from decimal import Decimal\n")
fd.write("""import collections, re
fd.write("import uuid\n")
fd.write("""import collections
import re
NUMPY_INTEGER_TYPES = [np.uint8, np.uint16, np.uint32, np.uint64,
np.int8, np.int16, np.int32, np.int64]
Expand Down Expand Up @@ -420,26 +422,34 @@ def __getitem__(self, k):
def __setitem__(self, k, v):
self.__set(k,v)
def __set(self, k, v=False):
def __set(self, k=False, v=False):
if v and not self.__check__(v):
raise ValueError, "value must be set to an instance of %s" % \
(self._contained_class)
try:
tmp = YANGDynClass(base=self._contained_class, parent=parent, yang_name=yang_name, is_container=is_container)
if " " in self._keyval:
keys = self._keyval.split(" ")
keyparts = k.split(" ")
if not len(keyparts) == len(keys):
raise KeyError, "YANGList key must contain all key elements (%s)" % (self._keyval.split(" "))
else:
keys = [self._keyval,]
keyparts = [k,]
for i in range(0,len(keys)):
key = getattr(tmp, "_set_%s" % keys[i])
key(keyparts[i])
self._members[k] = tmp
except TypeError, m:
raise ValueError, "key value must be valid, %s" % m
if self._keyval:
try:
tmp = YANGDynClass(base=self._contained_class, parent=parent, yang_name=yang_name, is_container=is_container)
if " " in self._keyval:
keys = self._keyval.split(" ")
keyparts = k.split(" ")
if not len(keyparts) == len(keys):
raise KeyError, "YANGList key must contain all key elements (%s)" % (self._keyval.split(" "))
else:
keys = [self._keyval,]
keyparts = [k,]
for i in range(0,len(keys)):
key = getattr(tmp, "_set_%s" % keys[i])
key(keyparts[i])
self._members[k] = tmp
except TypeError, m:
raise ValueError, "key value must be valid, %s" % m
else:
# this is a list that does not have a key specified, and hence
# we generate a uuid that is used as the key, the method then
# returns the uuid for the upstream process to use
k = str(uuid.uuid1())
self._members[k] = YANGDynClass(base=self._contained_class, parent=parent, yang_name=yang_name, is_container=is_container)
return k
def __delitem__(self, k):
del self._members[k]
Expand All @@ -448,9 +458,14 @@ def __len__(self): return len(self._members)
def keys(self): return self._members.keys()
def add(self, k):
self.__set(k)
#self.set()
def add(self, k=False):
if self._keyval:
if not k:
raise KeyError, "a list with a key value must have a key specified"
self.__set(k)
else:
k = self.__set()
return k
def delete(self, k):
try:
Expand Down Expand Up @@ -843,7 +858,7 @@ def get_children(fd, i_children, module, parent, path=str(), parent_cfg=True, ch

keyval = False
if parent.keyword == "list":
keyval = parent.search_one('key').arg
keyval = parent.search_one('key').arg if parent.search_one('key') is not None else False

parent_descr = parent.search_one('description')
if parent_descr is not None:
Expand Down Expand Up @@ -895,7 +910,7 @@ def get_children(fd, i_children, module, parent, path=str(), parent_cfg=True, ch
elif i["class"] == "list":
class_str = "__%s" % (i["name"])
class_str += " = YANGDynClass(base=YANGListType("
class_str += "\"%s\",%s" % (i["key"], i["type"])
class_str += "%s,%s" % ("\"%s\"" % i["key"] if i["key"] else False, i["type"])
class_str += ", yang_name=\"%s\", parent=self, is_container=True" % (i["yang_name"])
class_str += ", user_ordered=%s" % i["user_ordered"]
if i["choice"]:
Expand Down Expand Up @@ -1251,7 +1266,7 @@ def get_element(fd, element, module, parent, path, parent_cfg=True,choice=False)
"choice": choice,
}
if element.keyword == "list":
elemdict["key"] = safe_name(element.search_one("key").arg)
elemdict["key"] = safe_name(element.search_one("key").arg) if element.search_one("key") is not None else False
user_ordered = element.search_one('ordered-by')
elemdict["user_ordered"] = True if user_ordered is not None \
and user_ordered.arg.upper() == "USER" else False
Expand Down
12 changes: 10 additions & 2 deletions tests/list/list.yang
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,16 @@ module list {
list list-five {
key "val";
ordered-by user;

leaf val {

leaf val {
type uint8;
}
}

list list-six {
config false;

leaf val {
type uint8;
}
}
Expand Down
18 changes: 16 additions & 2 deletions tests/list/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def main():
test_instance.list_container.list_element[2].another_value == "aSecondDefaultValue"

assert test_instance.get() == \
{'list-container': {'list-five': {}, 'list-two': {}, 'list-three': {}, 'list-four': {},
{'list-container': {'list-six': {}, 'list-five': {}, 'list-two': {}, 'list-three': {}, 'list-four': {},
'list-element': {1: {'keyval': 1, 'another-value': 'defaultValue'},
2: {'keyval': 2, 'another-value': 'defaultValue'}}}}, \
"incorrect get() output returned: %s" % test_instance.get()
Expand Down Expand Up @@ -117,9 +117,23 @@ def main():
for i,j in zip(test_instance.list_container.list_five.keys(), range(1,10)):
assert i == j, "ordered list had incorret key ordering (%d != %d)" % (i,j)

passed = False
try:
test_instance.list_container.list_five.add()
except KeyError:
passed = True
assert passed == True, "a list with a key value allowed an key-less value to be set"

x = test_instance.list_container.list_six.add()
test_instance.list_container.list_six[x]._set_val(10)

assert test_instance.list_container.list_six[x].val == 10, \
"a key-less list did not have the correct value set (%s %d != 10)" % \
(x,test_instance.list_container.list_six[x].val)

if not k:
os.system("/bin/rm %s/bindings.py" % this_dir)
os.system("/bin/rm %s/bindings.pyc" % this_dir)

if __name__ == '__main__':
main()
main()

0 comments on commit 4fa7f47

Please sign in to comment.