[Python-modules-commits] [python-scruffy] 01/08: Imported Upstream version 0.3.3

ChangZhuo Chen czchen at moszumanska.debian.org
Wed May 11 12:01:49 UTC 2016


This is an automated email from the git hooks/post-receive script.

czchen pushed a commit to branch master
in repository python-scruffy.

commit 1fd2b430076baeabffc6aa22eb531358a70ec728
Author: ChangZhuo Chen (陳昌倬) <czchen at debian.org>
Date:   Wed May 11 19:53:46 2016 +0800

    Imported Upstream version 0.3.3
---
 PKG-INFO                                   |  11 +
 scruffington.egg-info/PKG-INFO             |  11 +
 scruffington.egg-info/SOURCES.txt          |  13 +
 scruffington.egg-info/dependency_links.txt |   1 +
 scruffington.egg-info/requires.txt         |   2 +
 scruffington.egg-info/top_level.txt        |   1 +
 scruffy/__init__.py                        |  14 +
 scruffy/config.py                          | 400 +++++++++++++++++++++++++
 scruffy/env.py                             | 116 ++++++++
 scruffy/file.py                            | 460 +++++++++++++++++++++++++++++
 scruffy/plugin.py                          |  63 ++++
 scruffy/state.py                           | 114 +++++++
 setup.cfg                                  |   8 +
 setup.py                                   |  14 +
 14 files changed, 1228 insertions(+)

diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..b62b00d
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,11 @@
+Metadata-Version: 1.0
+Name: scruffington
+Version: 0.3.3
+Summary: The janitor
+Home-page: https://github.com/snare/scruffy
+Author: snare
+Author-email: snare at ho.ax
+License: MIT
+Description: UNKNOWN
+Keywords: scruffy
+Platform: UNKNOWN
diff --git a/scruffington.egg-info/PKG-INFO b/scruffington.egg-info/PKG-INFO
new file mode 100644
index 0000000..b62b00d
--- /dev/null
+++ b/scruffington.egg-info/PKG-INFO
@@ -0,0 +1,11 @@
+Metadata-Version: 1.0
+Name: scruffington
+Version: 0.3.3
+Summary: The janitor
+Home-page: https://github.com/snare/scruffy
+Author: snare
+Author-email: snare at ho.ax
+License: MIT
+Description: UNKNOWN
+Keywords: scruffy
+Platform: UNKNOWN
diff --git a/scruffington.egg-info/SOURCES.txt b/scruffington.egg-info/SOURCES.txt
new file mode 100644
index 0000000..b147ef5
--- /dev/null
+++ b/scruffington.egg-info/SOURCES.txt
@@ -0,0 +1,13 @@
+setup.cfg
+setup.py
+scruffington.egg-info/PKG-INFO
+scruffington.egg-info/SOURCES.txt
+scruffington.egg-info/dependency_links.txt
+scruffington.egg-info/requires.txt
+scruffington.egg-info/top_level.txt
+scruffy/__init__.py
+scruffy/config.py
+scruffy/env.py
+scruffy/file.py
+scruffy/plugin.py
+scruffy/state.py
\ No newline at end of file
diff --git a/scruffington.egg-info/dependency_links.txt b/scruffington.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/scruffington.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/scruffington.egg-info/requires.txt b/scruffington.egg-info/requires.txt
new file mode 100644
index 0000000..4f1e759
--- /dev/null
+++ b/scruffington.egg-info/requires.txt
@@ -0,0 +1,2 @@
+pyyaml
+six
\ No newline at end of file
diff --git a/scruffington.egg-info/top_level.txt b/scruffington.egg-info/top_level.txt
new file mode 100644
index 0000000..f502ec4
--- /dev/null
+++ b/scruffington.egg-info/top_level.txt
@@ -0,0 +1 @@
+scruffy
diff --git a/scruffy/__init__.py b/scruffy/__init__.py
new file mode 100644
index 0000000..299f591
--- /dev/null
+++ b/scruffy/__init__.py
@@ -0,0 +1,14 @@
+from .env import Environment
+from .file import File, LogFile, LockFile, Directory, PluginDirectory, PackageDirectory, PackageFile
+from .plugin import PluginRegistry, Plugin, PluginManager
+from .config import ConfigNode, Config, ConfigEnv, ConfigFile, ConfigApplicator
+from .state import State
+
+__all__ = [
+    "Environment",
+    "Directory", "PluginDirectory", "PackageDirectory", "PackageFile",
+    "File", "LogFile", "LockFile",
+    "PluginRegistry", "Plugin", "PluginManager",
+    "ConfigNode", "Config", "ConfigEnv", "ConfigFile", "ConfigApplicator",
+    "State"
+]
diff --git a/scruffy/config.py b/scruffy/config.py
new file mode 100644
index 0000000..1177430
--- /dev/null
+++ b/scruffy/config.py
@@ -0,0 +1,400 @@
+import copy
+import os
+import ast
+import yaml
+import re
+
+from .file import File
+
+
+class ConfigNode(object):
+    """
+    Represents a Scruffy config object.
+
+    Can be accessed as a dictionary, like this:
+
+        config['top-level-section']['second-level-property']
+
+    Or as a dictionary with a key path, like this:
+
+        config['top_level_section.second_level_property']
+
+    Or as an object, like this:
+
+        config.top_level_section.second_level_property
+    """
+    def __init__(self, data={}, defaults={}, root=None, path=None):
+        super(ConfigNode, self).__init__()
+        self._root = root
+        if not self._root:
+            self._root = self
+        self._path = path
+        self._defaults = defaults
+        self._data = copy.deepcopy(self._defaults)
+        self.update(data)
+
+    def __getitem__(self, key):
+        c = self._child(key)
+        v = c._get_value()
+        if type(v) in [dict, list, type(None)]:
+            return c
+        else:
+            return v
+
+    def __setitem__(self, key, value):
+        container, last = self._child(key)._resolve_path(create=True)
+        container[last] = value
+
+    def __getattr__(self, key):
+        return self[key]
+
+    def __setattr__(self, key, value):
+        if key.startswith("_"):
+            super(ConfigNode, self).__setattr__(key, value)
+        else:
+            self[key] = value
+
+    def __str__(self):
+        return str(self._get_value())
+
+    def __repr__(self):
+        return str(self._get_value())
+
+    def __int__(self):
+        return int(self._get_value())
+
+    def __float__(self):
+        return float(self._get_value())
+
+    def __lt__(self, other):
+        return self._get_value() < other
+
+    def __le__(self, other):
+        return self._get_value() <= other
+
+    def __le__(self, other):
+        return self._get_value() <= other
+
+    def __eq__(self, other):
+        return self._get_value() == other
+
+    def __ne__(self, other):
+        return self._get_value() != other
+
+    def __gt__(self, other):
+        return self._get_value() > other
+
+    def __ge__(self, other):
+        return self._get_value() >= other
+
+    def __contains__(self, key):
+        return key in self._get_value()
+
+    def items(self):
+        return self._get_value().items()
+
+    def keys(self):
+        return self._get_value().keys()
+
+    def __iter__(self):
+        return self._get_value().__iter__()
+
+    def _child(self, path):
+        """
+        Return a ConfigNode object representing a child node with the specified
+        relative path.
+        """
+        if self._path:
+            path = '{}.{}'.format(self._path, path)
+        return ConfigNode(root=self._root, path=path)
+
+    def _resolve_path(self, create=False):
+        """
+        Returns a tuple of a reference to the last container in the path, and
+        the last component in the key path.
+
+        For example, with a self._value like this:
+
+        {
+            'thing': {
+                'another': {
+                    'some_leaf': 5,
+                    'one_more': {
+                        'other_leaf': 'x'
+                    }
+                }
+            }
+        }
+
+        And a self._path of: 'thing.another.some_leaf'
+
+        This will return a tuple of a reference to the 'another' dict, and
+        'some_leaf', allowing the setter and casting methods to directly access
+        the item referred to by the key path.
+        """
+        # Split up the key path
+        if type(self._path) == str:
+            key_path = self._path.split('.')
+        else:
+            key_path = [self._path]
+
+        # Start at the root node
+        node = self._root._data
+        nodes = [self._root._data]
+
+        # Traverse along key path
+        while len(key_path):
+            # Get the next key in the key path
+            key = key_path.pop(0)
+
+            # See if the test could be an int for array access, if so assume it is
+            try:
+                key = int(key)
+            except:
+                pass
+
+            # If the next level doesn't exist, create it
+            if create:
+                if type(node) == dict and key not in node:
+                    node[key] = {}
+                elif type(node) == list and type(key) == int and len(node) < key:
+                    node.append([None for i in range(key-len(node))])
+
+            # Store the last node and traverse down the hierarchy
+            nodes.append(node)
+            try:
+                node = node[key]
+            except TypeError:
+                if type(key) == int:
+                    raise IndexError(key)
+                else:
+                    raise KeyError(key)
+
+        return (nodes[-1], key)
+
+    def _get_value(self):
+        """
+        Get the value represented by this node.
+        """
+        if self._path:
+            try:
+                container, last = self._resolve_path()
+                return container[last]
+            except KeyError:
+                return None
+            except IndexError:
+                return None
+        else:
+            return self._data
+
+    def update(self, data={}, options={}):
+        """
+        Update the configuration with new data.
+
+        This can be passed either or both `data` and `options`.
+
+        `options` is a dict of keypath/value pairs like this (similar to
+        CherryPy's config mechanism:
+        {
+            'server.port': 8080,
+            'server.host': 'localhost',
+            'admin.email': 'admin at lol'
+        }
+
+        `data` is a dict of actual config data, like this:
+        {
+            'server': {
+                'port': 8080,
+                'host': 'localhost'
+            },
+            'admin': {
+                'email': 'admin at lol'
+            }
+        }
+        """
+        # Handle an update with a set of options like CherryPy does
+        for key in options:
+            self[key] = options[key]
+
+        # Merge in any data in `data`
+        if isinstance(data, ConfigNode):
+            data = data._get_value()
+        update_dict(self._get_value(), data)
+
+    def reset(self):
+        """
+        Reset the config to defaults.
+        """
+        self._data = copy.deepcopy(self._defaults)
+
+    def to_dict(self):
+        """
+        Generate a plain dictionary.
+        """
+        return self._get_value()
+
+
+class Config(ConfigNode):
+    """
+    Config root node class. Just for convenience.
+    """
+
+
+class ConfigEnv(ConfigNode):
+    """
+    Config based on based on environment variables.
+    """
+    def __init__(self, *args, **kwargs):
+        super(ConfigEnv, self).__init__(*args, **kwargs)
+
+        # build options dictionary from environment variables starting with __SC_
+        options = {}
+        for key in filter(lambda x: x.startswith('__SC_'), os.environ):
+            try:
+                val = ast.literal_eval(os.environ[key])
+            except:
+                val = os.environ[key]
+            options[key.replace('__SC_', '').lower()] = val
+
+        # update config with the values we've found
+        self.update(options=options)
+
+
+class ConfigFile(Config, File):
+    """
+    Config based on a loaded YAML or JSON file.
+    """
+    def __init__(self, path=None, defaults=None, load=False, apply_env=False, *args, **kwargs):
+        self._loaded = False
+        self._defaults_file = defaults
+        self._apply_env = apply_env
+        Config.__init__(self)
+        File.__init__(self, path=path, *args, **kwargs)
+
+        if load:
+            self.load()
+
+    def load(self, reload=False):
+        """
+        Load the config and defaults from files.
+        """
+        if reload or not self._loaded:
+            # load defaults
+            if self._defaults_file and type(self._defaults_file) == str:
+                self._defaults_file = File(self._defaults_file, parent=self._parent)
+            defaults = {}
+            if self._defaults_file:
+                defaults = yaml.safe_load(self._defaults_file.read().replace('\t', '    '))
+
+            # load data
+            data = {}
+            if self.exists:
+                data = yaml.safe_load(self.read().replace('\t', '    '))
+
+            # initialise with the loaded data
+            self._defaults = defaults
+            self._data = copy.deepcopy(self._defaults)
+            self.update(data=data)
+
+            # if specified, apply environment variables
+            if self._apply_env:
+                self.update(ConfigEnv())
+
+            self._loaded = True
+
+        return self
+
+    def save(self):
+        """
+        Save the config back to the config file.
+        """
+        self.write(yaml.safe_dump(self._data))
+
+    def prepare(self):
+        """
+        Load the file when the Directory/Environment prepares us.
+        """
+        self.load()
+
+
+class ConfigApplicator(object):
+    """
+    Applies configs to other objects.
+    """
+    def __init__(self, config):
+        self.config = config
+
+    def apply(self, obj):
+        """
+        Apply the config to an object.
+        """
+        if type(obj) == str:
+            return self.apply_to_str(obj)
+
+    def apply_to_str(self, obj):
+        """
+        Apply the config to a string.
+        """
+        toks = re.split('({config:|})', obj)
+        newtoks = []
+        try:
+            while len(toks):
+                tok = toks.pop(0)
+                if tok == '{config:':
+                    # pop the config variable, look it up
+                    var = toks.pop(0)
+                    val = self.config[var]
+
+                    # if we got an empty node, then it didn't exist
+                    if type(val) == ConfigNode and val == None:
+                        raise KeyError("No such config variable '{}'".format(var))
+
+                    # add the value to the list
+                    newtoks.append(str(val))
+
+                    # pop the '}'
+                    toks.pop(0)
+                else:
+                    # not the start of a config block, just append it to the list
+                    newtoks.append(tok)
+            return ''.join(newtoks)
+        except IndexError:
+            pass
+
+        return obj
+
+
+def update_dict(target, source):
+    """
+    Recursively merge values from a nested dictionary into another nested
+    dictionary.
+
+    For example:
+    target before = {
+        'thing': 123,
+        'thang': {
+            'a': 1,
+            'b': 2
+        }
+    }
+    source = {
+        'thang': {
+            'a': 666,
+            'c': 777
+        }
+    }
+    target after = {
+        'thing': 123,
+        'thang': {
+            'a': 666,
+            'b': 2,
+            'c': 777
+        }
+    }
+    """
+    for k,v in source.items():
+        if isinstance(v, dict) and k in target and isinstance(source[k], dict):
+            update_dict(target[k], v)
+        else:
+            target[k] = v
+
diff --git a/scruffy/env.py b/scruffy/env.py
new file mode 100644
index 0000000..826493b
--- /dev/null
+++ b/scruffy/env.py
@@ -0,0 +1,116 @@
+import os
+import yaml
+import itertools
+import errno
+import logging
+import logging.config
+
+from .file import Directory
+from .plugin import PluginManager
+from .config import ConfigNode, Config, ConfigEnv, ConfigApplicator
+
+
+class Environment(object):
+    """
+    An environment in which to run a program
+    """
+    def __init__(self, setup_logging=True, *args, **kwargs):
+        self._pm = PluginManager()
+        self._children = {}
+        self.config = None
+
+        # find a config if we have one and load it
+        self.config = self.find_config(kwargs)
+        if self.config:
+            self.config.load()
+
+        # setup logging
+        if setup_logging:
+            if self.config != None and self.config.logging.dict_config != None:
+                # configure logging from the configuration
+                logging.config.dictConfig(self.config.logging.dict_config.to_dict())
+            else:
+                # no dict config, set up a basic config so we at least get messages logged to stdout
+                log = logging.getLogger()
+                log.setLevel(logging.INFO)
+                if len(list(filter(lambda h: isinstance(h, logging.StreamHandler), log.handlers))) == 0:
+                    log.addHandler(logging.StreamHandler())
+
+        # add children
+        self.add(**kwargs)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.cleanup()
+
+    def __getitem__(self, key):
+        return self._children[key]
+
+    def __getattr__(self, key):
+        return self._children[key]
+
+    def find_config(self, children):
+        """
+        Find a config in our children so we can fill in variables in our other
+        children with its data.
+        """
+        named_config = None
+        found_config = None
+
+        # first see if we got a kwarg named 'config', as this guy is special
+        if 'config' in children:
+            if type(children['config']) == str:
+                children['config'] = ConfigFile(children['config'])
+            elif isinstance(children['config'], Config):
+                children['config'] = children['config']
+            elif type(children['config']) == dict:
+                children['config'] = Config(data=children['config'])
+            else:
+                raise TypeError("Don't know how to turn {} into a Config".format(type(children['config'])))
+
+            named_config = children['config']
+
+        # next check the other kwargs
+        for k in children:
+            if isinstance(children[k], Config):
+                found_config = children[k]
+
+        # if we still don't have a config, see if there's a directory with one
+        for k in children:
+            if isinstance(children[k], Directory):
+                for j in children[k]._children:
+                    if j == 'config' and not named_config:
+                        named_config = children[k]._children[j]
+                    if isinstance(children[k]._children[j], Config):
+                        found_config = children[k]._children[j]
+
+        if named_config:
+            return named_config
+        else:
+            return found_config
+
+    def add(self, **kwargs):
+        """
+        Add objects to the environment.
+        """
+        for key in kwargs:
+            if type(kwargs[key]) == str:
+                self._children[key] = Directory(kwargs[key])
+            else:
+                self._children[key] = kwargs[key]
+            self._children[key]._env = self
+            self._children[key].apply_config(ConfigApplicator(self.config))
+            self._children[key].prepare()
+
+    def cleanup(self):
+        """
+        Clean up the environment
+        """
+        for key in self._children:
+            self._children[key].cleanup()
+
+    @property
+    def plugins(self):
+        return self._pm.plugins
diff --git a/scruffy/file.py b/scruffy/file.py
new file mode 100644
index 0000000..cd913f7
--- /dev/null
+++ b/scruffy/file.py
@@ -0,0 +1,460 @@
+import os
+import yaml
+import copy
+import logging
+import logging.config
+import inspect
+import pkg_resources
+import shutil
+
+from .plugin import PluginManager
+
+
+class File(object):
+    """
+    Represents a file that may or may not exist on the filesystem.
+
+    Usually encapsulated by a Directory or an Environment.
+    """
+    def __init__(self, path=None, create=False, cleanup=False, parent=None):
+        super(File, self).__init__()
+        self._parent = parent
+        self._fpath = path
+        self._create = create
+        self._cleanup = cleanup
+
+        if self._fpath:
+            self._fpath = os.path.expanduser(self._fpath)
+
+    def __enter__(self):
+        self.prepare()
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.cleanup()
+
+    def __str__(self):
+        return self.path
+
+    def apply_config(self, applicator):
+        """
+        Replace any config tokens with values from the config.
+        """
+        if type(self._fpath) == str:
+            self._fpath = applicator.apply(self._fpath)
+
+    def create(self):
+        """
+        Create the file if it doesn't already exist.
+        """
+        open(self.path, 'a').close()
+
+    def remove(self):
+        """
+        Remove the file.
+        """
+        if self.exists:
+            os.unlink(self.path)
+
+    def prepare(self):
+        """
+        Prepare the file for use in an Environment or Directory.
+
+        This will create the file if the create flag is set.
+        """
+        if self._create:
+            self.create()
+
+    def cleanup(self):
+        """
+        Clean up the file after use in an Environment or Directory.
+
+        This will remove the file if the cleanup flag is set.
+        """
+        if self._cleanup:
+            self.remove()
+
+    @property
+    def path(self):
+        """
+        Get the path to the file relative to its parent.
+        """
+        if self._parent:
+            return os.path.join(self._parent.path, self._fpath)
+        else:
+            return self._fpath
+
+    @property
+    def name(self):
+        """
+        Get the file name.
+        """
+        return os.path.basename(self.path)
+
+    @property
+    def ext(self):
+        """
+        Get the file's extension.
+        """
+        return os.path.splitext(self.path)[1]
+
+    @property
+    def content(self):
+        """
+        Property for the content of the file.
+        """
+        return self.read()
+
+    @property
+    def exists(self):
+        """
+        Whether or not the file exists.
+        """
+        return self.path and os.path.exists(self.path)
+
+    def read(self):
+        """
+        Read and return the contents of the file.
+        """
+        with open(self.path) as f:
+            d = f.read()
+        return d
+
+    def write(self, data, mode='w'):
+        """
+        Write data to the file.
+
+        `data` is the data to write
+        `mode` is the mode argument to pass to `open()`
+        """
+        with open(self.path, mode) as f:
+            f.write(data)
+
+
+class LogFile(File):
+    """
+    A log file to configure with Python's logging module.
+    """
+    def __init__(self, path=None, logger=None, loggers=[], formatter={}, format=None, *args, **kwargs):
+        super(LogFile, self).__init__(path=path, *args, **kwargs)
+        self._create = True
+        self._cleanup = True
+        self._formatter = formatter
+        self._format = format
+
+        if logger:
+            self._loggers = [logger]
+        else:
+            self._loggers = loggers
+
+    def prepare(self):
+        """
+        Configure the log file.
+        """
+        self.configure()
+
+    def configure(self):
+        """
+        Configure the Python logging module for this file.
+        """
+        # build a file handler for this file
+        handler = logging.FileHandler(self.path, delay=True)
+
+        # if we got a format string, create a formatter with it
+        if self._format:
+            handler.setFormatter(logging.Formatter(self._format))
+
+        # if we got a string for the formatter, assume it's the name of a
+        # formatter in the environment's config
+        if type(self._formatter) == str:
+            if self._env and self._env.config.logging.dict_config.formatters[self._formatter]:
+                d = self._env.config.logging.dict_config.formatters[self._formatter].to_dict()
+                handler.setFormatter(logging.Formatter(**d))
+        elif type(self._formatter) == dict:
+            # if it's a dict it must be the actual formatter params
+            handler.setFormatter(logging.Formatter(**self._formatter))
+
+        # add the file handler to whatever loggers were specified
+        if len(self._loggers):
+            for name in self._loggers:
+                logging.getLogger(name).addHandler(handler)
+        else:
+            # none specified, just add it to the root logger
+            logging.getLogger().addHandler(handler)
+
+
+class LockFile(File):
+    """
+    A file that is automatically created and cleaned up.
+    """
+    def __init__(self, *args, **kwargs):
+        super(LockFile, self).__init__(*args, **kwargs)
+        self._create = True
+        self._cleanup = True
+
+    def create(self):
+        """
+        Create the file.
+
+        If the file already exists an exception will be raised
+        """
+        if not os.path.exists(self.path):
+            open(self.path, 'a').close()
+        else:
+            raise Exception("File exists: {}".format(self.path))
+
+
+class YamlFile(File):
+    """
+    A yaml file that is parsed into a dictionary.
+    """
+    @property
+    def content(self):
+        """
+        Parse the file contents into a dictionary.
+        """
+        return yaml.safe_load(self.read())
+
+
+class JsonFile(YamlFile):
+    """
+    A json file that is parsed into a dictionary.
+    """
+
+
+class PackageFile(File):
+    """
+    A file whose path is relative to a Python package.
+    """
+    def __init__(self, path=None, create=False, cleanup=False, parent=None, package=None):
+        super(PackageFile, self).__init__(path=path, create=create, cleanup=cleanup, parent=PackageDirectory(package=package))
+
+
+class Directory(object):
+    """
+    A filesystem directory.
+
+    A Scruffy Environment usually encompasses a number of these. For example,
+    the main Directory object may represent `~/.myproject`.
+
+    d = Directory({
+        path='~/.myproject',
+        create=True,
+        cleanup=False,
+        children=[
+        ...
+        ]
+    })
+
+    `path` can be either a string representing the path to the directory, or
+    a nested Directory object. If a Directory object is passed as the `path`
+    its path will be requested instead. This is so Directory objects can be
+    wrapped in others to inherit their properties.
+    """
+    def __init__(self, path=None, base=None, create=True, cleanup=False, parent=None, **kwargs):
+        self._path = path
+        self._base = base
+        self._create = create
+        self._cleanup = cleanup
+        self._pm = PluginManager()
+        self._children = {}
+        self._env = None
+        self._parent = parent
+
+        if self._path and type(self._path) == str:
+            self._path = os.path.expanduser(self._path)
+
+        self.add(**kwargs)
+
+    def __enter__(self):
+        self.create()
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.cleanup()
+
+    def __getitem__(self, key):
+        return self._children[key]
+
+    def __getattr__(self, key):
+        return self._children[key]
+
+    def apply_config(self, applicator):
+        """
+        Replace any config tokens with values from the config.
+        """
+        if type(self._path) == str:
+            self._path = applicator.apply(self._path)
+
+        for key in self._children:
+            self._children[key].apply_config(applicator)
+
+    @property
+    def path(self):
+        """
+        Return the path to this directory.
+        """
+        p = ''
+
+        if self._parent and self._parent.path:
+            p = os.path.join(p, self._parent.path)
+        if self._base:
+            p = os.path.join(p, self._base)
+        if self._path:
+            p = os.path.join(p, self._path)
+
+        return p
+
+    def create(self):
+        """
+        Create the directory.
+
+        Directory will only be created if the create flag is set.
+        """
+        if not self.exists:
+            os.mkdir(self.path)
+
+    def remove(self, recursive=True, ignore_error=True):
+        """
+        Remove the directory.
+        """
+        try:
+            if recursive or self._cleanup == 'recursive':
+                shutil.rmtree(self.path)
+            else:
+                os.rmdir(self.path)
+        except Exception as e:
+            if not ignore_error:
+                raise e
+
+    def prepare(self):
+        """
+        Prepare the Directory for use in an Environment.
+
+        This will create the directory if the create flag is set.
+        """
+        if self._create:
+            self.create()
+        for k in self._children:
+            self._children[k]._env = self._env
+            self._children[k].prepare()
+
+    def cleanup(self):
+        """
+        Clean up children and remove the directory.
+
+        Directory will only be removed if the cleanup flag is set.
+        """
... 337 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-scruffy.git



More information about the Python-modules-commits mailing list