[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