Beispiel #1
0
class EnvironmentConfig(Plugin):
    """A plugin that supports configuration of environment options."""

    implements(IEnvironmentConfig)
    implements(IPluginLoadPath)

    def __init__(self, namespace):
        self.namespace = namespace
        self.p = re.compile(namespace)
        declare_option("options", cls=DictOption, section=namespace)

    def get_option(self, option):
        try:
            return getattr(self.options, option)
        except AttributeError:
            return None

    def matches(self, namespace):
        if self.p.match(namespace) is None:
            return (False, 0)
        return (True, namespace.count('.') + 1)

    def get_load_path(self):
        ans = []
        #
        # Look for load_path in the environment
        #
        try:
            ans.append(
                os.path.normcase(os.path.realpath(self.options.load_path)))
        except OptionError:
            pass
        except AttributeError:
            pass
        #
        # Look for the $HOME/.$name/plugin directory
        #
        if "HOME" in os.environ:
            dir = os.path.normcase(
                os.path.realpath(
                    os.path.join(os.environ["HOME"], "." + self.namespace,
                                 "plugins")))
            if os.path.exists(dir):
                ans.append(dir)
        #
        # Look for the $PLUGINPATH environment
        #
        if "PLUGINPATH" in os.environ:
            tmp = os.environ["PLUGINPATH"]
            if ';' in tmp:
                ans += tmp.split(';')
            elif ':' in tmp:
                ans += tmp.split(':')
            else:
                ans += re.split('[ \t]+', tmp)
        if __debug__ and logger.isEnabledFor(logging.DEBUG):
            logger.debug("Created load path: %s" % ans)
        return ans
class DefaultTestDriver(Plugin):
    """
    This is the 'default' test driver, which simply prints the
    arguments being passed into a test.
    """

    implements(plugins.ITestDriver)
    alias('default')

    def setUpClass(self, cls, options):
        """Set-up the class that defines the suite of tests"""

    def tearDownClass(self, cls, options):
        """Tear-down the class that defines the suite of tests"""

    def setUp(self, testcase, options):
        """Set-up a single test in the suite"""

    def tearDown(self, testcase, options):
        """Tear-down a single test in the suite"""
        sys.stdout.flush()

    def run_test(self, testcase, name, options):
        """Execute a single test in the suite"""
        print('run_test ' + name)
        print(options)
Beispiel #3
0
class YamlTestParser(SingletonPlugin):

    implements(plugins.ITestParser)

    def __init__(self, **kwds):
        SingletonPlugin.__init__(self, **kwds)
        self.name = 'yml'

    def load_test_config(self, filename):
        if using_yaml:
            INPUT = open(filename, 'r')
            repn = yaml.load(INPUT, yaml.SafeLoader)
            INPUT.close()
            return repn
        #
        # If PyYaml is not available, then we use a simple yaml parser
        #
        INPUT = open(filename, 'r')
        repn = pyutilib.misc.simple_yaml_parser(INPUT)
        INPUT.close()
        return repn

    def print_test_config(self, repn):
        print(repn)  #pragma:nocover

    def enabled(self):
        return True
Beispiel #4
0
class DragonflySystemParticipant(SingletonPlugin):

    implements(ISystemParticipant)
    declare_option("engine", section="Dragonfly", default="auto")

    def __init__(self):
        self._engine = None
        self._loaded_engine_name = None

    #-----------------------------------------------------------------------
    # ISystemParticipant methods.

    def startup(self):
        self.shutdown()
        self._connect_engine()

    def shutdown(self):
        if self._engine:
            self._engine.disconnect()
        self._engine = None
        self._loaded_engine_name = None

    def config_changed(self):
        if self.engine == self._loaded_engine_name:
            # No change, return immediately.
            log.info("No change.")
            return

        self.shutdown()
        self.startup()

    #-----------------------------------------------------------------------
    # Internal methods.

    def _resolve_engine_name(self, engine_name):
        if not engine_name or engine_name == "auto":
            return None
        return engine_name

    def _connect_engine(self):
        engine_name = self._resolve_engine_name(self.engine)

        try:
            log.info("Importing Dragonfly library.")
            import dragonfly

            log.info("Locating SR engine {0}."
                     "".format(engine_name or "(automatic selection)"))
            self._engine = dragonfly.get_engine(engine_name)

            log.info("Connecting to SR engine {0}.".format(self._engine))
            self._engine.connect()
        except Exception, e:
            log.exception("Error during Dragonfly setup: {0}".format(e))
            raise

        self._loaded_engine_name = self.engine
Beispiel #5
0
class WorkflowPlugin(Plugin, workflow.Workflow):

    implements(IWorkflowTask)

    def __init__(self, *args, **kwds):  #pragma:nocover
        Plugin.__init__(self, *args, **kwds)
        workflow.Workflow.__init__(self, *args, **kwds)

    def __repr__(self):  #pragma:nocover
        return workflow.Workflow.__repr__(self)
Beispiel #6
0
class TaskPlugin(Plugin, task.Task):

    implements(IWorkflowTask)

    def __init__(self, *args, **kwds):  #pragma:nocover
        Plugin.__init__(self, *args, **kwds)
        task.Task.__init__(self, *args, **kwds)

    def __repr__(self):
        return task.Task.__repr__(self)  #pragma:nocover
Beispiel #7
0
class FileOption(Option):
    """A class that converts option data into a path.  Relative paths are
    converted using the path for the configuration file."""

    implements(IFileOption, service=True)
    implements(IUpdatedOptionsAction, service=True)

    def __init__(self, name, **kwds):
        """
        Constructor.  By default, the current working directory is the
        path used in this data.
        """
        self.dir = None
        Option.__init__(self, name, **kwds)

    def _parse_option(self, k, v):
        """Parse options that are specific to the FileOption class"""
        if k == "directory":
            self.dir = v
        else:
            Option._parse_option(self, k, v)

    def convert(self, value, default):
        """Conversion routine."""
        val = value[-1]
        if not val:
            if default is None:
                return None
            return os.path.normcase(os.path.realpath(default))
        if not os.path.isabs(val):
            val = os.path.join(self.dir, val)
            return os.path.normcase(os.path.realpath(val))
        else:
            return os.path.normcase(os.path.realpath(val))

    def set_dir(self, path):
        """Sets the path of the configuration data file."""
        self.dir = path

    def reset_after_updates(self):
        if self.dir is None:  #pragma:nocover
            raise OptionError("FileOption must have a directory specified.")
Beispiel #8
0
class OptionData(Plugin):
    """
    A class that is used to share option data between Option objects.
    This data in this class represents option data as

        section -> option -> data

    Note: this class does not currentl support the situation where an
    option is removed.  This would require a backwards map from option
    names to the Option classes that declare them.
    """

    implements(IOptionDataProvider, service=True)

    def __init__(self):
        """Constructor"""
        self.ignore_missing = False
        self.data = {}

    def get_data(self):
        """Get the class data"""
        return self.data

    def set(self, section, name, value):
        """Set the value of an option in a specified section"""
        if section not in self.data:
            self.data[section] = {}
        self.data[section][name] = value

    def get(self, section, name):
        """Get the value of an option in a specified section"""
        try:
            return self.data[section][name]
        except Exception:
            if self.ignore_missing:
                return None
            if section in self.data:
                raise OptionError(
                    "Problem retrieving the value of option %r from section %r. Valid keys are %s"
                    % (name, section, self.data[section].keys()))
            else:
                raise OptionError(
                    "Problem retrieving the value of option %r from section %r. Undefined section."
                    % (name, section))

    def clear(self, keys=None):
        """Clears the data"""
        if keys is None:
            self.data = {}
        else:
            for key in keys:
                if not key in self.data:
                    continue
                del self.data[key]
Beispiel #9
0
class CommandSetBase(Plugin):

    implements(ICommandSet)
    observers = ExtensionPoint(ICommandSetObserver)

    def after_load(self):
        for observer in self.observers:
            observer.loaded_command_set(self)

    def after_unload(self):
        self.deactivate()
        for observer in self.observers:
            observer.unloaded_command_set(self)
Beispiel #10
0
class ExternalExecutable(Plugin):

    implements(IExternalExecutable, service=True)

    def __init__(self, **kwds):
        if 'doc' in kwds:
            self.exec_doc = kwds["doc"]
        else:
            self.exec_doc = ""
        if 'name' in kwds:
            self.name = kwds['name']
            declare_option(
                kwds['name'],
                local_name="executable",
                section="executables",
                default=None,
                doc=self.exec_doc,
                cls=ExecutableOption)
        else:
            raise PluginError("An ExternalExectuable requires a name")
        if 'path' in kwds:
            self.path = kwds['path']
        else:
            self.path = None
        if 'validate' in kwds:
            self.validate = kwds['validate']
        else:
            self.validate = None
        self.find_executable()

    def find_executable(self):
        if not self.path is None:
            self.exec_default = self.path
        else:
            self.exec_default = pyutilib.misc.search_file(
                self.name,
                implicitExt=pyutilib.misc.executable_extension,
                executable=True,
                validate=self.validate)

    def enabled(self):
        return self._enable and ((self.executable is not None) or
                                 (self.exec_default is not None))

    def get_path(self):
        if not self.enabled():
            return None
        tmp = self.executable
        if tmp is None:
            return self.exec_default
        return tmp
Beispiel #11
0
class GrammarTreeUpdater(Plugin):

    implements(ICommandSetObserver)

    def __init__(self, grammar_tree):
        self._grammar_tree = grammar_tree

    def loaded_command_set(self, command_set):
        self.update()

    def unloaded_command_set(self, command_set):
        self.update()

    def update(self):
        command_sets = pyutilib.component.core.ExtensionPoint(ICommandSet)
        self._grammar_tree.update(tuple(command_sets))
Beispiel #12
0
class DummyOption1(Option):
    """A test class that converts option data into float values."""

    implements(IDummyOption)

    def convert(self, value, default):
        """Conversion routine."""
        val = value[-1]
        if not val:
            return 0
        try:
            return float(val)
        except ValueError:
            raise OptionError('Expected float, got %s' % repr(value))
        except TypeError:
            raise OptionError('Expected string or float type, got %s' %
                              repr(value))
Beispiel #13
0
class TestDriverBase(Plugin):

    implements(ITestDriver)

    def setUpClass(self, cls, options):
        """Set-up the class that defines the suite of tests"""

    def tearDownClass(self, cls, options):
        """Tear-down the class that defines the suite of tests"""

    def setUp(self, testcase, options):
        """Set-up a single test in the suite"""

    def tearDown(self, testcase, options):
        """Tear-down a single test in the suite"""

    def run_test(self, testcase, name, options):
        """Execute a single test in the suite"""
Beispiel #14
0
class JsonTestParser(SingletonPlugin):

    implements(plugins.ITestParser)

    def __init__(self, **kwds):
        SingletonPlugin.__init__(self, **kwds)
        self.name = 'json'

    def load_test_config(self, filename):
        INPUT = open(filename, 'r')
        repn = json.load(INPUT)
        INPUT.close()
        return repn

    def print_test_config(self, repn):
        print(repn)  #pragma:nocover

    def enabled(self):
        return json_available
class Configuration_ConfigParser(ManagedSingletonPlugin):
    """A configuration parser that uses the ConfigParser package."""

    implements(IConfiguration)

    def __init__(self, **kwds):
        kwds['name'] = 'Configuration_ConfigParser'
        ManagedSingletonPlugin.__init__(self, **kwds)

    def load(self, filename):
        """Returns a list of tuples: [ (section,option,value) ]"""
        parser = ConfigParser.ConfigParser()
        if not os.path.exists(filename):
            raise ConfigurationError("File " + filename + " does not exist!")
        parser.read(filename)
        #
        # Collect data
        #
        data = []
        for section in parser.sections():
            for (option, value) in parser.items(section):
                data.append((section, option, value))
        return data

    def save(self, filename, config, header=None):
        """Save configuration information to the specified file."""
        if sys.version_info[:2] == (2, 6):
            parser = ConfigParser.ConfigParser(dict_type=OrderedDict)
        else:
            parser = ConfigParser.ConfigParser()
        for (section, option, value) in config:
            if not parser.has_section(section):
                parser.add_section(section)
            parser.set(section, option, str(value))
        OUTPUT = open(filename, "w")
        if not header is None:
            for line in header.split("\n"):
                OUTPUT.write("; " + line + '\n')
        parser.write(OUTPUT)
        OUTPUT.close()
Beispiel #16
0
class EggLoader(ManagedPlugin):
    """
    Loader that looks for Python egg files in the plugins directories.
    These files get exampled with the pkg_resources package, and
    Plugin classes are loaded.

    Note: this plugin should not be directly constructed.  Instead,
    the user should employ the PluginFactory_EggLoader function.
    """

    implements(IPluginLoader, service=True)

    def __init__(self, **kwds):
        """EggLoader constructor.  The 'namespace' keyword option is
        required."""
        if 'name' not in kwds:
            kwds['name'] = "EggLoader." + kwds['namespace']
        super(EggLoader, self).__init__(**kwds)
        self.entry_point_name = kwds['namespace'] + ".plugins"
        if pkg_resources_avail is None:
            _check_pkg_resources()
        if not pkg_resources_avail:
            logger.warning(
                'A dummy EggLoader service is being constructed, because the pkg_resources package is not available on this machine.'
            )

    def load(self, env, search_path, disable_re, name_re):
        generate_debug_messages = __debug__ and env.log.isEnabledFor(
            logging.DEBUG)
        if not pkg_resources_avail:
            if generate_debug_messages:
                env.log.debug(
                    'The EggLoader service is terminating early because the pkg_resources package is not available on this machine.'
                )
            return

        working_set = pkg_resources.working_set

        env.log.info('BEGIN -  Loading plugins with an EggLoader service')
        distributions, errors = working_set.find_plugins(
            pkg_resources.Environment(search_path))
        for dist in distributions:
            if name_re.match(str(dist)):
                if generate_debug_messages:
                    env.log.debug('Adding plugin %r from %r', dist,
                                  dist.location)
                working_set.add(dist)
            else:
                if generate_debug_messages:
                    env.log.debug('Ignoring plugin %r from %r', dist,
                                  dist.location)

        def _log_error(item, e):
            gen_debug = __debug__ and env.log.isEnabledFor(logging.DEBUG)
            if isinstance(e, pkg_resources.DistributionNotFound):
                if gen_debug:
                    env.log.debug('Skipping "%s": ("%s" not found)', item, e)
            elif isinstance(e, pkg_resources.VersionConflict):
                if gen_debug:
                    env.log.debug('Skipping "%s": (version conflict "%s")',
                                  item, e)
            elif isinstance(e, pkg_resources.UnknownExtra):
                env.log.error('Skipping "%s": (unknown extra "%s")', item, e)
            elif isinstance(e, ImportError):
                env.log.error('Skipping "%s": (can\'t import "%s")', item, e)
            else:
                env.log.error('Skipping "%s": (error "%s")', item, e)

        for dist, e in errors.items():
            _log_error(dist, e)

        for entry in working_set.iter_entry_points(self.entry_point_name):
            if generate_debug_messages:
                env.log.debug('Loading %r from %r', entry.name,
                              entry.dist.location)
            try:
                entry.load(require=True)
            except (ImportError, pkg_resources.DistributionNotFound,
                    pkg_resources.VersionConflict, pkg_resources.UnknownExtra):
                e = sys.exc_info()[1]
                _log_error(entry, e)
            else:
                if not disable_re.match(os.path.dirname(
                        entry.module_name)) is None:
                    #_enable_plugin(env, entry.module_name)
                    pass

        env.log.info('END -    Loading plugins with an EggLoader service')
Beispiel #17
0
class LegacyDirectoryLoader(SingletonPlugin):

    implements(ICommandSetLoader)
    declare_option("directories", section="LegacyLoader")

    def __init__(self):
        self._modules = {}
        self._directories = []
        self._directories_config = None

    def _parse_directories_config(self):
        # If config has not changed, return immediately.
        if self._directories_config == self.directories:
            return self._directories

        log.info("Config option directories has changed:"
                 " {0!r}".format(self.directories))

        directories = []
        for line in self.directories.splitlines():
            line = line.strip()

            # Skip blank lines and comments.
            if not line or line.startswith("#"):
                continue

            directory = os.path.abspath(line)
            if not os.path.isdir(directory):
                log.error("Not a directory: {0}".format(directory))
                continue

            directories.append(directory)

        self._directories_config = self.directories
        self._directories = directories
        log.debug("Loading command modules from these directories:")
        for directory in directories:
            log.debug(" - {0}".format(directory))
        return directories

    def update(self):
        # Parse directories configuration.
        directories = self._parse_directories_config()

        valid_paths = []
        for directory in directories:
            valid_paths.extend(self._get_valid_paths(directory))

        # Remove any deleted modules.
        for path, module in self._modules.items():
            if path not in valid_paths:
                del self._modules[path]
                module.unload()

        # Add any new modules.
        for path in valid_paths:
            if path not in self._modules:
                module = LegacyCommandSet(path)
                module.load()
                self._modules[path] = module
            # Should check module freshness here.
            #else:
            #    module = self._modules[path]

    def _get_valid_paths(self, directory):
        valid_paths = []
        for filename in os.listdir(directory):
            path = os.path.abspath(os.path.join(directory, filename))
            if not os.path.isfile(path):
                continue
            if not os.path.splitext(path)[1] == ".py":
                continue
            valid_paths.append(path)
        return valid_paths
class LoggingConfig(Plugin):
    """A plugin that supports global configuration of logging options."""

    implements(IUpdatedOptionsAction)

    def __init__(self, namespace):
        """Initialize logging information for a specified namespace"""
        self._hdlr = None
        self.namespace = namespace
        self.env_plugins = ExtensionPoint(IEnvironmentConfig)
        if self.namespace == "":
            section = "logging"
            section_re = None
        else:
            section = "logging." + namespace
            section_re = "^logging$"
        #
        declare_option("timestamp",
                       section=section,
                       section_re=section_re,
                       default=False,
                       doc="""Add timestamp to logging information.""")
        #
        declare_option("log_dir",
                       section=section,
                       section_re=section_re,
                       default=None,
                       doc="""The logging directory.

        The default directory is the application directory plus 'log'.""")
        #
        declare_option("log_type",
                       section=section,
                       section_re=section_re,
                       default='none',
                       doc="""Logging facility to use.

        Should be one of (`none`, `file`, `stderr`, `syslog`, `winlog`).""")
        #
        declare_option(
            "log_file",
            section=section,
            section_re=section_re,
            default=namespace + '.log',
            doc=
            """If `log_type` is `file`, this should be a path to the log-file."""
        )
        #
        declare_option("log_level",
                       section=section,
                       section_re=section_re,
                       default='WARN',
                       doc="""Level of verbosity in log.

        Should be one of (`CRITICAL`, `ERROR`, `WARN`, `INFO`, `DEBUG`).""")
        #
        declare_option("log_format",
                       section=section,
                       section_re=section_re,
                       default=None,
                       doc="""Custom logging format.

        If nothing is set, the following will be used:

        $(project)[$(env) $(module)] $(levelname): $(message)

        In addition to regular key names supported by the Python logger library
        library (see http://docs.python.org/lib/node422.html), one could use:
         - $(path)s     the path for the current environment
         - $(basename)s the last path component of the current environment
         - $(app)s      the name of the current application

        Note the usage of `$(...)s` instead of `%(...)s` as the latter form
        would be interpreted by the ConfigParser itself.
        """)

    def reset_after_updates(self):
        """
        Configure the pyutilib.component logging facility.  This will
        implicitly configure all of the environment-specific logging
        objects.
        """
        sys.stdout.flush()
        logger = logging.getLogger('pyutilib.component.core.' + self.namespace)
        if not self._hdlr is None:
            logger.removeHandler(self._hdlr)
        #
        # Set logging level
        #
        level = self.log_level
        level = level.upper()
        if level in ('DEBUG', 'ALL'):
            logger.setLevel(logging.DEBUG)
        elif level == 'INFO':
            logger.setLevel(logging.INFO)
        elif level == 'ERROR':
            logger.setLevel(logging.ERROR)
        elif level == 'CRITICAL':
            logger.setLevel(logging.CRITICAL)
        else:
            logger.setLevel(logging.WARNING)
        #
        # Initialize the current path.  Is there a rule to use for whic
        # environment will be used???  In practice, there is likely to be
        # only one environment.
        #
        if self.log_dir is None:
            path = None
            for plugin in self.env_plugins:
                (flag, count) = plugin.matches(self.namespace)
                tmp = plugin.get_option("path")
                if flag and not tmp is None:
                    path = tmp
                    break
            if path is None:
                path = os.getcwd()
        else:
            path = self.log_dir
        #
        # Setup the logging file
        #
        logtype = self.log_type.lower()
        if self.log_file is None:
            logfile = os.path.join(path, 'log')
        else:
            logfile = self.log_file
            if not os.path.isabs(logfile):
                logfile = os.path.join(path, logfile)
        #
        # Define the format
        #
        format = self.log_format
        if format is None:
            format = '[env=%(env)s where=%(module)s] %(levelname)s - %(message)s'
            if self.timestamp and logtype in ('file', 'stderr'):
                format = '%(asctime)s ' + format
            format = format.replace('$(', '%(') \
                    .replace('%(env)s', PluginGlobals.get_env().name)
        datefmt = ''
        if self.timestamp and self.log_type == 'stderr':
            datefmt = '%X'
        formatter = logging.Formatter(format, datefmt)
        #
        #  Define the handler
        #
        if logtype == 'file':
            hdlr = logging.FileHandler(logfile)
        elif logtype in ('winlog', 'eventlog', 'nteventlog'):
            # Requires win32 extensions
            hdlr = handlers.NTEventLogHandler(logid, logtype='Application')
        elif logtype in ('syslog', 'unix'):
            hdlr = handlers.SysLogHandler('/dev/log')
        elif logtype in ('stderr'):
            hdlr = logging.StreamHandler(sys.stderr)
        else:
            hdlr = handlers.BufferingHandler(0)
            # Note: this _really_ throws away log events, as a `MemoryHandler`
            # would keep _all_ records in case there's no target handler (a bug?)
        self._hdlr = hdlr
        self._logtype = logtype
        self._logfile = logfile
        hdlr.setFormatter(formatter)
        logger.addHandler(hdlr)
        self._log = logger

    def flush(self):
        """Flush logging I/O"""
        self._hdlr.flush()

    def shutdown(self):
        #
        # Q: should this shutdown _all_ logging?
        #
        logging.shutdown()

    def log(self, message):
        self._log.info(message)
Beispiel #19
0
class TempfileManagerPlugin(ManagedSingletonPlugin):
    """A plugin that manages temporary files."""

    implements(ITempfileManager)

    def __init__(self, **kwds):
        if getattr(self, '_initialized', False) is True:
            return
        self._initialized = True
        #
        kwds['name'] = 'TempfileManager'
        ManagedSingletonPlugin.__init__(self, **kwds)
        self._tempfiles = [[]]
        declare_option("tempdir", default=None)
        self._ctr = -1

    def create_tempfile(self, suffix=None, prefix=None, text=False, dir=None):
        """
        Return the absolute path of a temporary filename that is
        guaranteed to be unique.  This function generates the file and returns
        the filename.
        """
        if suffix is None:
            suffix = ''
        if prefix is None:
            prefix = 'tmp'
        if dir is None:
            dir = self.tempdir

        ans = tempfile.mkstemp(suffix=suffix, prefix=prefix, text=text, dir=dir)
        ans = list(ans)
        if not os.path.isabs(ans[1]):  #pragma:nocover
            fname = os.path.join(dir, ans[1])
        else:
            fname = ans[1]
        os.close(ans[0])
        if self._ctr >= 0:
            new_fname = os.path.join(dir, prefix + str(self._ctr) + suffix)
            # Delete any file having the sequential name and then
            # rename
            if os.path.exists(new_fname):
                os.remove(new_fname)
            shutil.move(fname, new_fname)
            fname = new_fname
            self._ctr += 1
        self._tempfiles[-1].append(fname)
        return fname

    def create_tempdir(self, suffix=None, prefix=None, dir=None):
        """
        Return the absolute path of a temporary directory that is
        guaranteed to be unique.  This function generates the directory and returns
        the directory name.
        """
        if suffix is None:
            suffix = ''
        if prefix is None:
            prefix = 'tmp'
        if dir is None:
            dir = self.tempdir
        dirname = tempfile.mkdtemp(suffix=suffix, prefix=prefix, dir=dir)
        if self._ctr >= 0:
            new_dirname = os.path.join(dir, prefix + str(self._ctr) + suffix)
            # Delete any directory having the sequential name and then
            # rename
            if os.path.exists(new_dirname):
                shutil.rmtree(new_dirname)
            shutil.move(dirname, new_dirname)
            dirname = new_dirname
            self._ctr += 1

        self._tempfiles[-1].append(dirname)
        return dirname

    def add_tempfile(self, filename, exists=True):
        """Declare this file to be temporary."""
        tmp = os.path.abspath(filename)
        if exists and not os.path.exists(tmp):
            raise IOError("Temporary file does not exist: " + tmp)
        self._tempfiles[-1].append(tmp)

    def clear_tempfiles(self, remove=True):
        """Delete all temporary files."""
        while len(self._tempfiles) > 1:
            self.pop(remove)
        self.pop(remove)

    def sequential_files(self, ctr=0):
        """Start generating sequential files, using the specified counter"""
        self._ctr = ctr

    def unique_files(self):
        """Stop generating sequential files, using the specified counter"""
        self._ctr = -1

    #
    # Support "with" statements, where the pop automatically
    # takes place on exit.
    #
    def push(self):
        self._tempfiles.append([])
        return self

    def __exit__(self, type, value, traceback):
        self.pop(remove=True)

    def pop(self, remove=True):
        files = self._tempfiles.pop()
        if remove:
            for filename in files:
                if os.path.exists(filename):
                    if os.path.isdir(filename):
                        shutil.rmtree(
                            filename,
                            ignore_errors=not deletion_errors_are_fatal)
                    else:
                        try:
                            os.remove(filename)
                        except WindowsError:
                            # Sometimes Windows doesn't release the
                            # file lock immediately when the process
                            # terminates.  If we get an error, wait a
                            # second and try again.
                            try:
                                time.sleep(1)
                                os.remove(filename)
                            except WindowsError:
                                if deletion_errors_are_fatal:
                                    raise
                                else:
                                    # Failure to delete a tempfile
                                    # should NOT be fatal
                                    logger = logging.getLogger(
                                        'pyutilib.component.config')
                                    logger.warning("Unable to delete temporary "
                                                   "file %s" % (filename,))

        if len(self._tempfiles) == 0:
            self._tempfiles = [[]]
Beispiel #20
0
class OptionPlugin(Plugin):
    """Manages the initialization of an Option."""

    implements(IOption, service=True)

    def __init__(self):
        """
        Declare an extension point for a data provider, and
        construct one if one hasn't already been provided.
        """
        self.data = ExtensionPoint(IOptionDataProvider)
        if PluginGlobals._default_OptionData is None:
            PluginGlobals._default_OptionData = OptionData()
        #
        # This is a hack.  We shouldn't need to test if len(self.data) is zero.
        # Somewhere in our tests, the weakref to the OptionData object is being
        # corrupted.  Perhaps this is caused by 'nose' or 'import' logic?
        #
        if True and len(self.data) == 0:
            PluginGlobals.interface_services[IOptionDataProvider].add(
                PluginGlobals._default_OptionData._id)
            PluginGlobals.plugin_instances[
                PluginGlobals._default_OptionData._id] = weakref.ref(
                    PluginGlobals._default_OptionData)
        #
        if len(self.data) == 0:
            #if False:
            #print "ZZZ", ep.Xextensions()
            #print "HERE", PluginGlobals._default_OptionData._id, PluginGlobals._default_OptionData.ctr
            #print "HERE", PluginGlobals._default_OptionData
            #print "HERE - id", id(PluginGlobals._default_OptionData)
            #print "HERE", getattr(PluginGlobals._default_OptionData, '_HERE_', None)
            #print "HERE", PluginGlobals._default_OptionData.__interfaces__
            #print ""
            #print "HERE", PluginGlobals.interface_services
            #print "HERE", PluginGlobals.plugin_instances.keys()
            #for exe_ in PluginGlobals._executables:
            #print exe_._id, exe_
            #print "LEN", len(PluginGlobals.env)
            #for name_ in PluginGlobals.env:
            #env_ = PluginGlobals.env[name_]
            #print env_.name
            #print env_.nonsingleton_plugins
            #print [env_.singleton_services[cls_] for cls_ in env_.singleton_services]
            raise PluginError(
                "Problem constructing a global OptionData object %s" %
                self.name)

    def matches_section(self, section):
        """
        This method returns true if the section name matches the option
        section, or if the option's section regular expression matches the
        section name.
        """
        return (section == self.section) or (
            self.section_re != None and
            (not self.section_p.match(section) is None))

    def matches_name(self, name):
        """
        This method returns true if the name matches the options' name.
        """
        return (self.name == "") or (name == self.name)

    def convert(self, value, default):
        """Convert a value into a specific type.  The default behavior is to
        take the list of values, and simply return the last one defined in the
        configuration."""
        return value[-1]

    def get_value(self):
        """
        Get the option value.
        """
        return self.data.service().get(self.section, self.name)

    def set_value(self, _value_, raw=False):
        """
        Set the option value.  By default, the option is converted using
        the option-specific `convert` method, but the `raw` option can be
        specified to force the raw value to be inserted.
        """
        if raw:
            self.data.service().set(self.section, self.name, _value_)
        else:
            if not type(_value_) is list or len(_value_) == 0:
                _value_ = [_value_]
            self.data.service().set(self.section, self.name,
                                    self.convert(_value_, self.default))

    def load(self, _option_, _value_):
        """
        Load an option value.  This method assumes that the option value is
        provided in a list, which is the format used when interfacing with
        the Configure class.
        """
        if type(_value_) is list and len(_value_) == 0:
            raise OptionError("Attempting to load option %r with empty data" %
                              (self.name))
        try:
            self.set_value(_value_)
        except OptionError:
            err = sys.exc_info()[1]
            raise OptionError("Error loading option %r: %s" %
                              (str(_option_), str(err)))
        return True

    def reset(self):
        """Set option to its default value"""
        self.set_value(self.default, raw=True)

    def default_str(self):
        """Return a string value that describes the default option value"""
        return str(self.default)
Beispiel #21
0
class ImportLoader(ManagedSingletonPlugin):
    """Loader that looks for Python source files in the plugins directories,
    which simply get imported, thereby registering them with the component
    manager if they define any components.
    """

    ep_services = ExtensionPoint(IIgnorePluginWhenLoading)

    implements(IPluginLoader)

    def load(self, env, search_path, disable_re, name_re):
        generate_debug_messages = __debug__ and env.log.isEnabledFor(
            logging.DEBUG)
        env.log.info('Loading plugins with ImportLoader')
        for path in search_path:
            plugin_files = glob(os.path.join(path, '*.py'))
            #
            # Note: for reproducibility, this fixes the order that
            # files are loaded
            #
            for plugin_file in sorted(plugin_files):
                #print("ImportLoader:",plugin_file)
                #
                # Load the module
                #
                module = None
                plugin_name = os.path.basename(plugin_file[:-3])
                if plugin_name not in sys.modules and name_re.match(
                        plugin_name):
                    try:
                        module = imp.load_source(plugin_name, plugin_file)
                        if generate_debug_messages:
                            env.log.debug('Loading file plugin %s from %s' % \
                                  (plugin_name, plugin_file))
                    except Exception:
                        e = sys.exc_info()[1]
                        env.log.error('Failed to load plugin from %s',
                                      plugin_file,
                                      exc_info=True)
                        env.log.error('Load error: %r' % str(e))
                #
                # Disable singleton plugins that match
                #
                if not module is None:
                    if not disable_re.match(plugin_name) is None:
                        if generate_debug_messages:
                            env.log.debug('Disabling services in module %s' %
                                          plugin_name)
                        for item in dir(module):
                            #
                            # This seems like a hack, but
                            # without this we can disable pyutilib
                            # functionality!
                            #
                            flag = False
                            for service in ImportLoader.ep_services:
                                if service.ignore(item):
                                    flag = True
                                    break
                            if flag:
                                continue

                            cls = getattr(module, item)
                            try:
                                is_instance = isinstance(cls, Plugin)
                            except TypeError:  #pragma:nocover
                                is_instance = False
                            try:
                                is_plugin = issubclass(cls, Plugin)
                            except TypeError:
                                is_plugin = False
                            try:
                                is_singleton = not (cls.__instance__ is None)
                            except AttributeError:  #pragma:nocover
                                is_singleton = False
                            if is_singleton and is_plugin:
                                if generate_debug_messages:
                                    env.log.debug('Disabling service %s' %
                                                  item)
                                cls.__instance__._enable = False
                            if is_instance:
                                if generate_debug_messages:
                                    env.log.debug('Disabling service %s' %
                                                  item)
                                cls._enable = False
                    elif generate_debug_messages:
                        env.log.debug('All services in module %s are enabled' %
                                      plugin_name)