404

[ Avaa Bypassed ]




Upload:

Command:

botdev@3.14.135.249: ~ $
#
# 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(".", "\."))
    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

Filemanager

Name Type Size Permission Actions
__pycache__ Folder 0755
apt Folder 0755
__init__.py File 198 B 0644
amp.py File 21.24 KB 0644
bootstrap.py File 1.38 KB 0644
bpickle.py File 6.31 KB 0644
cli.py File 440 B 0644
cloud.py File 1.67 KB 0644
compat.py File 564 B 0644
config.py File 12.15 KB 0644
disk.py File 4.97 KB 0644
encoding.py File 545 B 0644
fd.py File 751 B 0644
fetch.py File 6.49 KB 0644
format.py File 959 B 0644
fs.py File 3.55 KB 0644
gpg.py File 1.75 KB 0644
hashlib.py File 264 B 0644
jiffies.py File 1.58 KB 0644
juju.py File 860 B 0644
lock.py File 705 B 0644
log.py File 484 B 0644
logging.py File 2.47 KB 0644
lsb_release.py File 893 B 0644
message.py File 1.91 KB 0644
monitor.py File 6.13 KB 0644
network.py File 8.91 KB 0644
persist.py File 20.5 KB 0644
plugin.py File 1.75 KB 0644
process.py File 6.45 KB 0644
reactor.py File 8.61 KB 0644
schema.py File 5.97 KB 0644
scriptcontent.py File 522 B 0644
sequenceranges.py File 5.59 KB 0644
store.py File 1.38 KB 0644
sysstats.py File 6.94 KB 0644
tag.py File 505 B 0644
testing.py File 24.08 KB 0644
timestamp.py File 233 B 0644
twisted_util.py File 4.37 KB 0644
user.py File 1.44 KB 0644
versioning.py File 1.24 KB 0644
vm_info.py File 3.2 KB 0644
warning.py File 394 B 0644