summaryrefslogtreecommitdiffstats
path: root/obmc/utils
diff options
context:
space:
mode:
authorBrad Bishop <radsquirrel@gmail.com>2016-02-11 16:15:40 -0500
committerBrad Bishop <bradleyb@us.ibm.com>2016-04-15 08:44:02 -0400
commit8ffe1e4424799a58e7f664a982b9417f5555d12d (patch)
tree93814081ac04e664520fcec1d6e245fe72dd32a7 /obmc/utils
parentc832cb33083d49bd57b1ca19d258dc003b74dcde (diff)
downloadpyphosphor-8ffe1e4424799a58e7f664a982b9417f5555d12d.tar.gz
pyphosphor-8ffe1e4424799a58e7f664a982b9417f5555d12d.zip
Introducing pyobmc
We have openbmc python utilities scattered all over the place. To facilitate reuse, bring them together in a single python package. None of this is new code, it was all simply ported and re-arranged from other projects. Ran everything through pep8.
Diffstat (limited to 'obmc/utils')
-rw-r--r--obmc/utils/__init__.py0
-rw-r--r--obmc/utils/misc.py63
-rw-r--r--obmc/utils/pathtree.py183
3 files changed, 246 insertions, 0 deletions
diff --git a/obmc/utils/__init__.py b/obmc/utils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obmc/utils/__init__.py
diff --git a/obmc/utils/misc.py b/obmc/utils/misc.py
new file mode 100644
index 0000000..cfde266
--- /dev/null
+++ b/obmc/utils/misc.py
@@ -0,0 +1,63 @@
+# Contributors Listed Below - COPYRIGHT 2016
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+
+
+class Path:
+ def __init__(self, path):
+ self.parts = filter(bool, path.split('/'))
+
+ def rel(self, first=None, last=None):
+ # relative
+ return self.get('', first, last)
+
+ def fq(self, first=None, last=None):
+ # fully qualified
+ return self.get('/', first, last)
+
+ def depth(self):
+ return len(self.parts)
+
+ def get(self, prefix='/', first=None, last=None):
+ if not first:
+ first = 0
+ if not last:
+ last = self.depth()
+ return prefix + '/'.join(self.parts[first:last])
+
+
+def org_dot_openbmc_match(name):
+ return 'org.openbmc' in name
+
+
+class ListMatch(object):
+ def __init__(self, l):
+ self.l = l
+
+ def __call__(self, match):
+ return match in self.l
+
+
+def find_case_insensitive(value, lst):
+ return next((x for x in lst if x.lower() == value.lower()), None)
+
+
+def makelist(data):
+ if isinstance(data, list):
+ return data
+ elif data:
+ return [data]
+ else:
+ return []
diff --git a/obmc/utils/pathtree.py b/obmc/utils/pathtree.py
new file mode 100644
index 0000000..221495e
--- /dev/null
+++ b/obmc/utils/pathtree.py
@@ -0,0 +1,183 @@
+# Contributors Listed Below - COPYRIGHT 2016
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+
+
+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)
OpenPOWER on IntegriCloud