/
usr
/
lib
/
python3
/
dist-packages
/
landscape
/
lib
/
/usr/lib/python3/dist-packages/landscape/lib
mkdir
upload
Name
Size
Mode
Actions
apt/
-
0755
rm
__pycache__/
-
0755
rm
amp.py
21745
0644
edit
dl
rm
backoff.py
1683
0644
edit
dl
rm
base64.py
196
0644
edit
dl
rm
bootstrap.py
1416
0644
edit
dl
rm
bpickle.py
6471
0644
edit
dl
rm
cli.py
440
0644
edit
dl
rm
cloud.py
1715
0644
edit
dl
rm
compat.py
616
0644
edit
dl
rm
config.py
12484
0644
edit
dl
rm
disk.py
5027
0644
edit
dl
rm
encoding.py
545
0644
edit
dl
rm
fd.py
751
0644
edit
dl
rm
fetch.py
6647
0644
edit
dl
rm
format.py
959
0644
edit
dl
rm
fs.py
3889
0644
edit
dl
rm
gpg.py
1796
0644
edit
dl
rm
hashlib.py
264
0644
edit
dl
rm
jiffies.py
1621
0644
edit
dl
rm
juju.py
860
0644
edit
dl
rm
lock.py
705
0644
edit
dl
rm
log.py
484
0644
edit
dl
rm
logging.py
2528
0644
edit
dl
rm
message.py
2638
0644
edit
dl
rm
monitor.py
6281
0644
edit
dl
rm
network.py
9821
0644
edit
dl
rm
os_release.py
1324
0644
edit
dl
rm
persist.py
20995
0644
edit
dl
rm
plugin.py
1787
0644
edit
dl
rm
process.py
6603
0644
edit
dl
rm
reactor.py
8812
0644
edit
dl
rm
schema.py
6457
0644
edit
dl
rm
scriptcontent.py
522
0644
edit
dl
rm
sequenceranges.py
5724
0644
edit
dl
rm
store.py
1408
0644
edit
dl
rm
sysstats.py
7920
0644
edit
dl
rm
tag.py
506
0644
edit
dl
rm
testing.py
24662
0644
edit
dl
rm
timestamp.py
233
0644
edit
dl
rm
twisted_util.py
4476
0644
edit
dl
rm
user.py
1476
0644
edit
dl
rm
versioning.py
1265
0644
edit
dl
rm
vm_info.py
3172
0644
edit
dl
rm
warning.py
394
0644
edit
dl
rm
__init__.py
198
0644
edit
dl
rm
Edit:
/usr/lib/python3/dist-packages/landscape/lib/persist.py
(20995B)
# # Copyright (c) 2006 Canonical # Copyright (c) 2004 Conectiva, Inc. # # Written by Gustavo Niemeyer <gustavo@niemeyer.net> # # This Python module is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2 of the License, or (at # your option) any later version. # # This Python module is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this Python module; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # import os import sys import copy import re from twisted.python.compat import StringType # Py2: basestring, Py3: str __all__ = ["Persist", "PickleBackend", "BPickleBackend", "path_string_to_tuple", "path_tuple_to_string", "RootedPersist", "PersistError", "PersistReadOnlyError"] NOTHING = object() class PersistError(Exception): pass class PersistReadOnlyError(PersistError): pass class Persist(object): """Persist a hierarchical database of key=>value pairs. There are three different kinds of option maps, regarding the persistence and priority that maps are queried. - hard - Options are persistent. - soft - Options are not persistent, and have a higher priority than persistent options. - weak - Options are not persistent, and have a lower priority than persistent options. @ivar filename: The name of the file where persist data is saved or None if no filename is available. """ def __init__(self, backend=None, filename=None): """ @param backend: The backend to use. If none is specified, L{BPickleBackend} will be used. @param filename: The default filename to save to and load from. If specified, and the file exists, it will be immediately loaded. Specifying this will also allow L{save} to be called without any arguments to save the persist. """ if backend is None: backend = BPickleBackend() self._backend = backend self._hardmap = backend.new() self._softmap = {} self._weakmap = {} self._readonly = False self._modified = False self._config = self self.filename = filename if filename is not None and os.path.exists(filename): self.load(filename) def _get_readonly(self): return self._readonly def _set_readonly(self, flag): self._readonly = bool(flag) def _get_modified(self): return self._modified readonly = property(_get_readonly, _set_readonly) modified = property(_get_modified) def reset_modified(self): """Set the database status as non-modified.""" self._modified = False def assert_writable(self): """Assert if the object is writable @raise: L{PersistReadOnlyError} """ if self._readonly: raise PersistReadOnlyError("Configuration is in readonly mode.") def load(self, filepath): """Load a persisted database.""" def load_old(): filepathold = filepath + ".old" if (os.path.isfile(filepathold) and os.path.getsize(filepathold) > 0 ): # warning("Broken configuration file at %s" % filepath) # warning("Trying backup at %s" % filepathold) try: self._hardmap = self._backend.load(filepathold) except Exception: raise PersistError("Broken configuration file at %s" % filepathold) return True return False filepath = os.path.expanduser(filepath) if not os.path.isfile(filepath): if load_old(): return raise PersistError("File not found: %s" % filepath) if os.path.getsize(filepath) == 0: load_old() return try: self._hardmap = self._backend.load(filepath) except Exception: if load_old(): return raise PersistError("Broken configuration file at %s" % filepath) def save(self, filepath=None): """Save the persist to the given C{filepath}. If None is specified, then the filename passed during construction will be used. If the destination file already exists, it will be renamed to C{<filepath>.old}. """ if filepath is None: if self.filename is None: raise PersistError("Need a filename!") filepath = self.filename filepath = os.path.expanduser(filepath) if os.path.isfile(filepath): os.rename(filepath, filepath + ".old") dirname = os.path.dirname(filepath) if dirname and not os.path.isdir(dirname): os.makedirs(dirname) self._backend.save(filepath, self._hardmap) def _traverse(self, obj, path, default=NOTHING, setvalue=NOTHING): if setvalue is not NOTHING: setvalue = self._backend.copy(setvalue) queue = list(path) marker = NOTHING newobj = obj while queue: obj = newobj elem = queue.pop(0) newobj = self._backend.get(obj, elem) if newobj is NotImplemented: if queue: path = path[:-len(queue)] raise PersistError("Can't traverse %r (%r): %r" % (type(obj), path_tuple_to_string(path), str(obj))) if newobj is marker: break if newobj is not marker: if setvalue is not marker: newobj = self._backend.set(obj, elem, setvalue) else: if setvalue is marker: newobj = default else: while True: if len(queue) > 0: if type(queue[0]) is int: newvalue = [] else: newvalue = {} else: newvalue = setvalue newobj = self._backend.set(obj, elem, newvalue) if newobj is NotImplemented: raise PersistError("Can't traverse %r with %r" % (type(obj), type(elem))) if not queue: break obj = newobj elem = queue.pop(0) return newobj def _getvalue(self, path, soft=False, hard=False, weak=False): if isinstance(path, StringType): path = path_string_to_tuple(path) marker = NOTHING if soft: value = self._traverse(self._softmap, path, marker) elif hard: value = self._traverse(self._hardmap, path, marker) elif weak: value = self._traverse(self._weakmap, path, marker) else: value = self._traverse(self._softmap, path, marker) if value is marker: value = self._traverse(self._hardmap, path, marker) if value is marker: value = self._traverse(self._weakmap, path, marker) return value def has(self, path, value=NOTHING, soft=False, hard=False, weak=False): obj = self._getvalue(path, soft, hard, weak) marker = NOTHING if obj is marker: return False elif value is marker: return True result = self._backend.has(obj, value) if result is NotImplemented: raise PersistError("Can't check %r for containment" % type(obj)) return result def keys(self, path, soft=False, hard=False, weak=False): obj = self._getvalue(path, soft, hard, weak) if obj is NOTHING: return [] result = self._backend.keys(obj) if result is NotImplemented: raise PersistError("Can't return keys for %s" % type(obj)) return result def get(self, path, default=None, soft=False, hard=False, weak=False): value = self._getvalue(path, soft, hard, weak) if value is NOTHING: return default return self._backend.copy(value) def set(self, path, value, soft=False, weak=False): assert path if isinstance(path, StringType): path = path_string_to_tuple(path) if soft: map = self._softmap elif weak: map = self._weakmap else: self.assert_writable() self._modified = True map = self._hardmap self._traverse(map, path, setvalue=value) def add(self, path, value, unique=False, soft=False, weak=False): assert path if isinstance(path, StringType): path = path_string_to_tuple(path) if soft: map = self._softmap elif weak: map = self._weakmap else: self.assert_writable() self._modified = True map = self._hardmap if unique: current = self._traverse(map, path) if type(current) is list and value in current: return path = path + (sys.maxsize,) self._traverse(map, path, setvalue=value) def remove(self, path, value=NOTHING, soft=False, weak=False): assert path if isinstance(path, StringType): path = path_string_to_tuple(path) if soft: map = self._softmap elif weak: map = self._weakmap else: self.assert_writable() self._modified = True map = self._hardmap marker = NOTHING while path: if value is marker: obj = self._traverse(map, path[:-1]) elem = path[-1] isvalue = False else: obj = self._traverse(map, path) elem = value isvalue = True result = False if obj is not marker: result = self._backend.remove(obj, elem, isvalue) if result is NotImplemented: raise PersistError("Can't remove %r from %r" % (elem, type(obj))) if self._backend.empty(obj): if value is not marker: value = marker else: path = path[:-1] else: break return result def move(self, oldpath, newpath, soft=False, weak=False): if not (soft or weak): self.assert_writable() if isinstance(oldpath, StringType): oldpath = path_string_to_tuple(oldpath) if isinstance(newpath, StringType): newpath = path_string_to_tuple(newpath) result = False marker = NOTHING value = self._getvalue(oldpath, soft, not (soft or weak), weak) if value is not marker: self.remove(oldpath, soft=soft, weak=weak) self.set(newpath, value, weak, soft) result = True return result def root_at(self, path): """ Rebase the database hierarchy. @return: A L{RootedPersist} using this L{Persist} as parent. """ return RootedPersist(self, path) class RootedPersist(object): """Root a L{Persist}'s tree at a particular branch. This class shares the same interface of L{Persist} and provides a shortcut to access the nodes of a particular branch in a L{Persist}'s tree. The chosen branch will be viewed as the root of the tree of the L{RootedPersist} and all operations will be forwarded to the parent L{Persist} as appropriate. """ def __init__(self, parent, root): """ @param parent: the parent L{Persist}. @param root: a branch of the parent L{Persist}'s tree, that will be used as root of this L{RootedPersist}. """ self.parent = parent if isinstance(root, StringType): self.root = path_string_to_tuple(root) else: self.root = root readonly = property(lambda self: self.parent.readonly) modified = property(lambda self: self.parent.modified) def assert_writable(self): self.parent.assert_writable() def has(self, path, value=NOTHING, soft=False, hard=False, weak=False): if isinstance(path, StringType): path = path_string_to_tuple(path) return self.parent.has(self.root + path, value, soft, hard, weak) def keys(self, path, soft=False, hard=False, weak=False): if isinstance(path, StringType): path = path_string_to_tuple(path) return self.parent.keys(self.root + path, soft, hard, weak) def get(self, path, default=None, soft=False, hard=False, weak=False): if isinstance(path, StringType): path = path_string_to_tuple(path) return self.parent.get(self.root + path, default, soft, hard, weak) def set(self, path, value, soft=False, weak=False): if isinstance(path, StringType): path = path_string_to_tuple(path) return self.parent.set(self.root + path, value, soft, weak) def add(self, path, value, unique=False, soft=False, weak=False): if isinstance(path, StringType): path = path_string_to_tuple(path) return self.parent.add(self.root + path, value, unique, soft, weak) def remove(self, path, value=NOTHING, soft=False, weak=False): if isinstance(path, StringType): path = path_string_to_tuple(path) return self.parent.remove(self.root + path, value, soft, weak) def move(self, oldpath, newpath, soft=False, weak=False): if isinstance(oldpath, StringType): oldpath = path_string_to_tuple(oldpath) if isinstance(newpath, StringType): newpath = path_string_to_tuple(newpath) return self.parent.move(self.root + oldpath, self.root + newpath, soft, weak) def root_at(self, path): if isinstance(path, StringType): path = path_string_to_tuple(path) return self.parent.root_at(self.root + path) _splitpath = re.compile(r"(\[-?\d+\])|(?<!\\)\.").split def path_string_to_tuple(path): """Convert a L{Persist} path string to a path tuple. Examples: >>> path_string_to_tuple("ab") ("ab",) >>> path_string_to_tuple("ab.cd") ("ab", "cd")) >>> path_string_to_tuple("ab[0][1]") ("ab", 0, 1) >>> path_string_to_tuple("ab[0].cd[1]") ("ab", 0, "cd", 1) Raises L{PersistError} if the given path string is invalid. """ if "." not in path and "[" not in path: return (path,) result = [] tokens = _splitpath(path) for token in tokens: if token: if token[0] == "[" and token[-1] == "]": try: result.append(int(token[1:-1])) except ValueError: raise PersistError("Invalid path index: %r" % token) else: result.append(token.replace(r"\.", ".")) return tuple(result) def path_tuple_to_string(path): result = [] for elem in path: if type(elem) is int: result[-1] += "[%d]" % elem else: result.append(str(elem).replace(".", r"\.")) return ".".join(result) class Backend(object): """ Base class for L{Persist} backends implementing hierarchical storage functionality. Each node of the hierarchy is an object of type C{dict}, C{list} or C{tuple}. A node can have zero or more children, each child can be another node or a leaf value compatible with the backend's serialization mechanism. Each child element is associated with a unique key, that can be used to get, set or remove the child itself from its containing node. If the node object is of type C{dict}, then the child keys will be the keys of the dictionary, otherwise if the node object is of type C{list} or C{tuple} the child element keys are the indexes of the available items, or the value of items theselves. The root node object is always a C{dict}. For example: >>> backend = Backend() >>> root = backend.new() >>> backend.set(root, "foo", "bar") 'bar' >>> egg = backend.set(root, "egg", [1, 2, 3]) >>> backend.set(egg, 0, 10) 10 >>> root {'foo': 'bar', 'egg': [10, 2, 3]} """ def new(self): raise NotImplementedError def load(self, filepath): raise NotImplementedError def save(self, filepath, map): raise NotImplementedError def get(self, obj, elem, _marker=NOTHING): """Lookup a child in the given node object.""" if type(obj) is dict: newobj = obj.get(elem, _marker) elif type(obj) in (tuple, list): if type(elem) is int: try: newobj = obj[elem] except IndexError: newobj = _marker elif elem in obj: newobj = elem else: newobj = _marker else: newobj = NotImplemented return newobj def set(self, obj, elem, value): """Set the value of the given child in the given node object.""" if type(obj) is dict: newobj = obj[elem] = value elif type(obj) is list and type(elem) is int: lenobj = len(obj) if lenobj <= elem: obj.append(None) elem = lenobj elif elem < 0 and abs(elem) > lenobj: obj.insert(0, None) elem = 0 newobj = obj[elem] = value else: newobj = NotImplemented return newobj def remove(self, obj, elem, isvalue): """Remove a the given child in the given node object. @param isvalue: In case the node object is a C{list}, a boolean indicating if C{elem} is the index of the child or the value of the child itself. """ result = False if type(obj) is dict: if elem in obj: del obj[elem] result = True elif type(obj) is list: if not isvalue and type(elem) is int: try: del obj[elem] result = True except IndexError: pass elif elem in obj: obj[:] = [x for x in obj if x != elem] result = True else: result = NotImplemented return result def copy(self, value): """Copy a node or a value.""" if type(value) in (dict, list): return copy.deepcopy(value) return value def empty(self, obj): """Whether the given node object has no children.""" return (not obj) def has(self, obj, elem): """Whether the given node object contains the given child element.""" contains = getattr(obj, "__contains__", None) if contains: return contains(elem) return NotImplemented def keys(self, obj): """Return the keys of the child elements of the given node object.""" keys = getattr(obj, "keys", None) if keys: return keys() elif type(obj) is list: return range(len(obj)) return NotImplemented class PickleBackend(Backend): def __init__(self): from landscape.lib.compat import cPickle self._pickle = cPickle def new(self): return {} def load(self, filepath): with open(filepath, 'rb') as fd: return self._pickle.load(fd) def save(self, filepath, map): with open(filepath, "wb") as fd: self._pickle.dump(map, fd, 2) class BPickleBackend(Backend): def __init__(self): from landscape.lib import bpickle self._bpickle = bpickle def new(self): return {} def load(self, filepath): with open(filepath, "rb") as fd: return self._bpickle.loads(fd.read()) def save(self, filepath, map): with open(filepath, "wb") as fd: fd.write(self._bpickle.dumps(map)) # vim:ts=4:sw=4:et
Save
cmd:
run