diff options
author | Brad Bishop <radsquirrel@gmail.com> | 2016-02-11 16:15:40 -0500 |
---|---|---|
committer | Brad Bishop <bradleyb@us.ibm.com> | 2016-04-15 08:44:02 -0400 |
commit | 8ffe1e4424799a58e7f664a982b9417f5555d12d (patch) | |
tree | 93814081ac04e664520fcec1d6e245fe72dd32a7 /obmc/utils | |
parent | c832cb33083d49bd57b1ca19d258dc003b74dcde (diff) | |
download | pyphosphor-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__.py | 0 | ||||
-rw-r--r-- | obmc/utils/misc.py | 63 | ||||
-rw-r--r-- | obmc/utils/pathtree.py | 183 |
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) |