[PATCH phosphor-objmgr v2 02/10] Add PathTree to mapper library
OpenBMC Patches
patches at stwcx.xyz
Fri Nov 6 00:21:42 AEDT 2015
From: Brad Bishop <bradleyb at us.ibm.com>
PathTree is a somewhat generic structure for associating
data with a path, internally managed as a tree. It emulates
built in python containers and supports iteration.
---
OpenBMCMapper.py | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 165 insertions(+), 3 deletions(-)
diff --git a/OpenBMCMapper.py b/OpenBMCMapper.py
index cefed52..3b6fe00 100644
--- a/OpenBMCMapper.py
+++ b/OpenBMCMapper.py
@@ -169,7 +169,169 @@ class IntrospectionParser:
continue
items.update(callback(path + k, parser))
- if path == '/':
- print items
-
return items
+
+class PathTreeItemIterator(object):
+ def __init__(self, path_tree, subtree, depth):
+ self.path_tree = path_tree
+ self.path = []
+ self.itlist = []
+ self.subtree = ['/'] + filter(bool, subtree.split('/'))
+ self.depth = depth
+ d = path_tree.root
+ for k in self.subtree:
+ try:
+ d = d[k]['children']
+ except KeyError:
+ raise KeyError(subtree)
+ self.it = d.iteritems()
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ return super(PathTreeItemIterator, self).next()
+
+ def next(self):
+ key, value = self._next()
+ path = self.subtree[0] + '/'.join(self.subtree[1:] + self.path)
+ return path, value.get('data')
+
+ def _next(self):
+ try:
+ while True:
+ x = self.it.next()
+ depth_exceeded = len(self.path) +1 > self.depth
+ if self.depth and depth_exceeded:
+ continue
+ self.itlist.append(self.it)
+ self.path.append(x[0])
+ self.it = x[1]['children'].iteritems()
+ break;
+
+ except StopIteration:
+ if not self.itlist:
+ raise StopIteration
+
+ self.it = self.itlist.pop()
+ self.path.pop()
+ x = self._next()
+
+ return x
+
+class PathTreeKeyIterator(PathTreeItemIterator):
+ def __init__(self, path_tree, subtree, depth):
+ super(PathTreeKeyIterator, self).__init__(path_tree, subtree, depth)
+
+ def next(self):
+ return super(PathTreeKeyIterator, self).next()[0]
+
+class PathTree:
+ def __init__(self):
+ self.root = {}
+
+ def _try_delete_parent(self, elements):
+ if len(elements) == 1:
+ return False
+
+ kids = 'children'
+ elements.pop()
+ d = self.root
+ for k in elements[:-1]:
+ d = d[k][kids]
+
+ if 'data' not in d[elements[-1]] and not d[elements[-1]][kids]:
+ del d[elements[-1]]
+ self._try_delete_parent(elements)
+
+ def _get_node(self, key):
+ kids = 'children'
+ elements = ['/'] + filter(bool, key.split('/'))
+ d = self.root
+ for k in elements[:-1]:
+ try:
+ d = d[k][kids]
+ except KeyError:
+ raise KeyError(key)
+
+ return d[elements[-1]]
+
+ def __iter__(self):
+ return self
+
+ def __missing__(self, key):
+ for x in self.iterkeys():
+ if key == x:
+ return False
+ return True
+
+ def __delitem__(self, key):
+ kids = 'children'
+ elements = ['/'] + filter(bool, key.split('/'))
+ d = self.root
+ for k in elements[:-1]:
+ try:
+ d = d[k][kids]
+ except KeyError:
+ raise KeyError(key)
+
+ del d[elements[-1]]
+ self._try_delete_parent(elements)
+
+ def __setitem__(self, key, value):
+ kids = 'children'
+ elements = ['/'] + filter(bool, key.split('/'))
+ d = self.root
+ for k in elements[:-1]:
+ d = d.setdefault(k, {kids: {}})[kids]
+
+ children = d.setdefault(elements[-1], {kids: {}})[kids]
+ d[elements[-1]].update({kids: children, 'data': value})
+
+ def __getitem__(self, key):
+ return self._get_node(key).get('data')
+
+ def setdefault(self, key, default):
+ if not self.get(key):
+ self.__setitem__(key, default)
+
+ return self.__getitem__(key)
+
+ def get(self, key, default = None):
+ try:
+ x = self.__getitem__(key)
+ except KeyError:
+ x = default
+
+ return x
+
+ def get_children(self, key):
+ return [ x for x in self._get_node(key)['children'].iterkeys() ]
+
+ def demote(self, key):
+ n = self._get_node(key)
+ if 'data' in n:
+ del n['data']
+
+ def keys(self, subtree = '/', depth = None):
+ return [ x for x in self.iterkeys(subtree, depth) ]
+
+ def values(self, subtree = '/', depth = None):
+ return [ x[1] for x in self.iteritems(subtree, depth) ]
+
+ def items(self, subtree = '/', depth = None):
+ return [ x for x in self.iteritems(subtree, depth) ]
+
+ def dataitems(self, subtree = '/', depth = None):
+ return [ x for x in self.iteritems(subtree, depth) \
+ if x[1] is not None ]
+
+ def iterkeys(self, subtree = '/', depth = None):
+ if not self.root:
+ return {}.iterkeys()
+ return PathTreeKeyIterator(self, subtree, depth)
+
+ def iteritems(self, subtree = '/', depth = None):
+ if not self.root:
+ return {}.iteritems()
+ return PathTreeItemIterator(self, subtree, depth)
--
2.6.0
More information about the openbmc
mailing list