Example #1
0
    def test_float(self):
        """Test float"""
        ep = ExtensionPoint(IOption)

        class TMP_float(Plugin):
            declare_option("o1", cls=FloatOption)

        obj = TMP_float()
        pt = ep.service("o1")

        pt.load("o1", [-1.5])
        self.assertEqual(pt.get_value(), -1.5)

        pt.load("o1", ["-1.5"])
        self.assertEqual(pt.get_value(), -1.5)

        pt.load("o1", [[]])
        self.assertEqual(pt.get_value(), 0)

        try:
            pt.load("o1", [['a']])
            self.fail("expected error")
        except OptionError:
            pass

        try:
            pt.load("o1", ['a'])
            self.fail("expected error")
        except OptionError:
            pass
Example #2
0
    def test_bool(self):
        """Test boolean"""
        ep = ExtensionPoint(IOption)

        class TMP_bool(Plugin):
            declare_option("o1", cls=BoolOption)

        obj = TMP_bool()
        pt = ep.service("o1")

        pt.load("o1", [True])
        self.assertEqual(pt.get_value(), True)

        pt.load("o1", [False])
        self.assertEqual(pt.get_value(), False)

        pt.load("o1", [1])
        self.assertEqual(pt.get_value(), True)

        pt.load("o1", [0])
        self.assertEqual(pt.get_value(), False)

        pt.load("o1", ['YES'])
        self.assertEqual(pt.get_value(), True)

        pt.load("o1", ['no'])
        self.assertEqual(pt.get_value(), False)
Example #3
0
    def test_bool(self):
        """Test boolean"""
        ep = ExtensionPoint(IOption)

        class TMP_bool(Plugin):
            declare_option("o1", cls=BoolOption)

        obj = TMP_bool()
        pt = ep.service("o1")

        pt.load("o1", [True])
        self.assertEqual(pt.get_value(), True)

        pt.load("o1", [False])
        self.assertEqual(pt.get_value(), False)

        pt.load("o1", [1])
        self.assertEqual(pt.get_value(), True)

        pt.load("o1", [0])
        self.assertEqual(pt.get_value(), False)

        pt.load("o1", ['YES'])
        self.assertEqual(pt.get_value(), True)

        pt.load("o1", ['no'])
        self.assertEqual(pt.get_value(), False)
Example #4
0
    def test_float(self):
        """Test float"""
        ep = ExtensionPoint(IOption)

        class TMP_float(Plugin):
            declare_option("o1", cls=FloatOption)

        obj = TMP_float()
        pt = ep.service("o1")

        pt.load("o1", [-1.5])
        self.assertEqual(pt.get_value(), -1.5)

        pt.load("o1", ["-1.5"])
        self.assertEqual(pt.get_value(), -1.5)

        pt.load("o1", [[]])
        self.assertEqual(pt.get_value(), 0)

        try:
            pt.load("o1", [['a']])
            self.fail("expected error")
        except OptionError:
            pass

        try:
            pt.load("o1", ['a'])
            self.fail("expected error")
        except OptionError:
            pass
Example #5
0
def create_test_suites(filename=None, config=None, _globals=None, options=None):
    if options is None:  #pragma:nocover
        options = Options()
    #
    # Add categories specified by the PYUTILIB_AUTOTEST_CATEGORIES
    # or PYUTILIB_UNITTEST_CATEGORIES environments
    #
    if options is None or options.categories is None or len(
            options.categories) == 0:
        options.categories = set()
        if 'PYUTILIB_AUTOTEST_CATEGORIES' in os.environ:
            for cat in re.split(',',
                                os.environ['PYUTILIB_AUTOTEST_CATEGORIES']):
                if cat != '':
                    options.categories.add(cat.strip())
        elif 'PYUTILIB_UNITTEST_CATEGORIES' in os.environ:
            for cat in re.split(',',
                                os.environ['PYUTILIB_UNITTEST_CATEGORIES']):
                if cat != '':
                    options.categories.add(cat.strip())
    #
    if not filename is None:
        if options.currdir is None:
            options.currdir = dirname(abspath(filename)) + os.sep
        #
        ep = ExtensionPoint(plugins.ITestParser)
        ftype = os.path.splitext(filename)[1]
        if not ftype == '':
            ftype = ftype[1:]
        service = ep.service(ftype)
        if service is None:
            raise IOError(
                "Unknown file type.  Cannot load test configuration from file '%s'"
                % filename)
        config = service.load_test_config(filename)
    #service.print_test_config(config)
    validate_test_config(config)
    #
    # Evaluate Python expressions
    #
    for item in config.get('python', []):
        try:
            exec(item, _globals)
        except Exception:
            err = sys.exc_info()[1]
            print("ERROR executing '%s'" % item)
            print("  Exception: %s" % str(err))
    #
    # Create test driver, which is put in the global namespace
    #
    driver = plugins.TestDriverFactory(config['driver'])
    if driver is None:
        raise IOError("Unexpected test driver '%s'" % config['driver'])
    _globals["test_driver"] = driver
    #
    # Generate suite
    #
    for suite in config.get('suites', {}):
        create_test_suite(suite, config, _globals, options)
Example #6
0
    def test_OptionPlugin(self):
        """Test OptionPlugin"""
        ep = ExtensionPoint(IOption)

        class TMP_OptionPlugin(Plugin):
            declare_option("o1")

        obj = TMP_OptionPlugin()
        pt = ep.service("o1")

        try:
            pt.load("o1", [])
            self.fail("expected error")
        except OptionError:
            pass
Example #7
0
    def test_OptionPlugin(self):
        """Test OptionPlugin"""
        ep = ExtensionPoint(IOption)

        class TMP_OptionPlugin(Plugin):
            declare_option("o1")

        obj = TMP_OptionPlugin()
        pt = ep.service("o1")

        try:
            pt.load("o1", [])
            self.fail("expected error")
        except OptionError:
            pass
Example #8
0
    def test_path(self):
        """Test path"""
        ep = ExtensionPoint(IOption)
        if sys.platform == "win32":
            o1_default = "C:/default"
        else:
            o1_default = "/dev//default"

        class TMP_path(Plugin):
            declare_option("o1",
                           cls=FileOption,
                           default=o1_default,
                           directory="/dev/null")

        obj = TMP_path()
        pt = ep.service("o1")

        pt.load("o1", [None])
        if sys.platform == "win32":
            self.assertEqual(pt.get_value(), "c:\\default")
        else:
            self.assertEqual(pt.get_value(), "/dev/default")

        if sys.platform == "win32":
            pt.load("o1", ["C:/load1"])
        else:
            pt.load("o1", ["/dev/load1"])
        if sys.platform == "win32":
            self.assertEqual(pt.get_value(), "c:\\load1")
        else:
            self.assertEqual(pt.get_value(), "/dev/load1")

        if sys.platform == "win32":
            pt.set_dir("D:/foo")
        else:
            pt.set_dir("/dev/foo")
        pt.load("o1", ["bar"])
        if sys.platform == "win32":
            self.assertEqual(pt.get_value(), "d:\\foo\\bar")
        else:
            self.assertEqual(pt.get_value(), "/dev/foo/bar")
Example #9
0
    def test_path(self):
        """Test path"""
        ep = ExtensionPoint(IOption)
        if sys.platform == "win32":
            o1_default = "C:/default"
        else:
            o1_default = "/dev//default"

        class TMP_path(Plugin):
            declare_option(
                "o1", cls=FileOption, default=o1_default, directory="/dev/null")

        obj = TMP_path()
        pt = ep.service("o1")

        pt.load("o1", [None])
        if sys.platform == "win32":
            self.assertEqual(pt.get_value(), "c:\\default")
        else:
            self.assertEqual(pt.get_value(), "/dev/default")

        if sys.platform == "win32":
            pt.load("o1", ["C:/load1"])
        else:
            pt.load("o1", ["/dev/load1"])
        if sys.platform == "win32":
            self.assertEqual(pt.get_value(), "c:\\load1")
        else:
            self.assertEqual(pt.get_value(), "/dev/load1")

        if sys.platform == "win32":
            pt.set_dir("D:/foo")
        else:
            pt.set_dir("/dev/foo")
        pt.load("o1", ["bar"])
        if sys.platform == "win32":
            self.assertEqual(pt.get_value(), "d:\\foo\\bar")
        else:
            self.assertEqual(pt.get_value(), "/dev/foo/bar")
Example #10
0
    def test_repr(self):
        """Test string repn"""
        ep = ExtensionPoint(IOption)

        class TMP_repr(Plugin):
            declare_option("o1", default=4)
            declare_option("o2", section="foo", default=4)

        obj = TMP_repr()
        if re.match("\<Option \[globals\] 'o1'\>", str(
                ep.service("o1"))) is None:
            self.fail("Expected globals:o1, but this option is %s" %
                      str(ep.service("o1")))
        self.assertFalse(
            re.match("\<Option \[globals\] 'o1'\>", str(ep.service("o1"))) is
            None)
        self.assertFalse(
            re.match("\<Option \[foo\] 'o2'\>", str(ep.service("o2"))) is None)
        self.assertEqual(ep.service("o1").get_value(), 4)
        ep.service("o1").load("o1", ["new"])
        self.assertEqual(ep.service("o1").get_value(), "new")
        ep.service("o1").load("o1", "old")
        self.assertEqual(ep.service("o1").get_value(), "old")
Example #11
0
def registered_executable(name=None):
    ep = ExtensionPoint(IExternalExecutable)
    if name is None:
        return filter(lambda x: x.name, ep.extensions())
    return ep.service(name)
Example #12
0
class Configuration(Plugin):
    """This class manages configuration data.  Further, this configuration
    I/O is coordinated with Option objects.  When configuration data is read
    in, associated Option plugins are populated.  Similarly, when
    configuration data is writen, the configuration data is taken from
    Option data."""

    def __init__(self, filename=None, parser="ConfigParser"):
        """Constructor.
            @param filename - The associated configuration file.
            @param parser   - Specify the name of the parser used to
                read/write configuration files.
        """
        self.parser_type = "Configuration_ConfigParser"
        self.filename = filename
        #
        # Define extension points
        #
        self.parsers = ExtensionPoint(IConfiguration)
        self.option_plugins = ExtensionPoint(IOption)
        self.option_data_plugin = ExtensionPoint(IOptionDataProvider)
        self.pathoption_plugins = ExtensionPoint(IFileOption)
        self.postconfig_actions = ExtensionPoint(IUpdatedOptionsAction)
        self.clear()

    def clear(self):
        """Clear local data."""
        self.config = []
        self.data = {}
        self.section = []

    def __contains__(self, name):
        """Return whether the configuration contains a section of the given
        name.
        """
        return name in self.data

    def __getitem__(self, name):
        """Return the configuration section with the specified name."""
        if name not in self.data:
            raise ConfigurationError("No section " + name + " in data")
        return self.data[name]

    def sections(self):
        """Returns the names of all sections in the configuration data."""
        return list(self.data.keys())

    def load(self, filename=None):
        """Load configuration from a file."""
        if len(self.parsers) == 0:  #pragma:nocover
            raise ConfigurationError("No IConfiguration parsers are registered")
        if not filename is None:
            self.filename = filename
        if self.filename is None:
            raise ConfigurationError("Cannot load without a filename")
        for option in self.pathoption_plugins:
            option.set_dir(os.path.dirname(self.filename))
        #
        # By default, we simply take the first parser
        #
        self.config = self.parsers.service(self.parser_type).load(self.filename)
        self.data = {}
        self.section = []
        for (s, o, v) in self.config:
            if not s in self.data:
                self.section.append(s)
                self.data[s] = {}
            if not o in self.data[s]:
                self.data[s][o] = []
            self.data[s][o].append(v)
        #
        # Iterate through all sections, in the order they were
        # loaded.  Load data for extensions that match each section name.
        #
        for sec in self.section:
            #
            # Find the option_plugins that match this section
            #
            plugins = []
            for plugin in self.option_plugins:
                if plugin.matches_section(sec):
                    plugins.append(plugin)
            for option in self.data[sec]:
                flag = False
                for plugin in plugins:
                    if plugin.matches_name(option):
                        flag = plugin.load(option,
                                           self.data[sec][option]) or flag
                if not flag:
                    raise ConfigurationError(
                        "Problem loading file %r. Option %r in section %r is not recognized!"
                        % (self.filename, option, sec))
        #
        # Finalize the configuration process
        #
        for plugin in self.postconfig_actions:
            plugin.reset_after_updates()

    def save(self, filename=None):
        """Save configuration to a file."""
        if not filename is None:
            self.filename = filename
        if self.filename is None:
            raise ConfigurationError("Cannot save without a filename")
        #
        # Setup the list of tuples
        #
        self.clear()
        self.data = self.option_data_plugin.service().get_data()
        self.section = list(self.data.keys())
        self.section.sort()
        flag = False
        header = "\nNote: the following configuration options have been omitted because their\nvalue is 'None':\n"
        for sec in self.section:
            plugins = []
            for plugin in self.option_plugins:
                if plugin.matches_section(sec):
                    plugins.append(plugin)
            #
            options = list(self.data[sec].keys())
            options.sort()
            for option in options:
                for plugin in plugins:
                    if plugin.matches_name(option):
                        if not self.data[sec][option] is None:
                            val = self.data[sec][option]
                            self.config.append((sec, option, val))
                        else:
                            flag = True
                            header = header + "  section=%r option=%r\n" % (
                                sec, option)
                        break
        if flag:
            header = header + "\n"
        else:
            header = None
        #
        # Write config file
        #
        self.parsers.service(self.parser_type).save(self.filename, self.config,
                                                    header)

    def pprint(self):
        """Print a simple summary of the configuration data."""
        text = ""
        for (s, o, v) in self.config:
            text += "[%s] %s = %s\n" % (s, o, v)
        print(text)

    def summarize(self):
        """Summarize options"""
        tmp = {}
        for option in self.option_plugins:
            tmp.setdefault(option.section, {})[option.name] = option
        keys = list(tmp.keys())
        keys.sort()
        for key in keys:
            print("[" + key + "]")
            print("")
            okeys = list(tmp[key].keys())
            okeys.sort()
            for okey in okeys:
                print("  Option:    " + tmp[key][okey].name)
                print("  Type:      " + tmp[key][okey].__class__.__name__)
                print("  Default:   " + tmp[key][okey].default_str())
                print("  Doc:       " + tmp[key][okey].__doc__)
                print("")
            print("")
Example #13
0
    def test_repr(self):
        """Test string repn"""
        ep = ExtensionPoint(IOption)

        class TMP_repr(Plugin):
            declare_option("o1", default=4)
            declare_option("o2", section="foo", default=4)

        obj = TMP_repr()
        if re.match("\<Option \[globals\] 'o1'\>",
                    str(ep.service("o1"))) is None:
            self.fail("Expected globals:o1, but this option is %s" %
                      str(ep.service("o1")))
        self.assertFalse(
            re.match("\<Option \[globals\] 'o1'\>", str(ep.service("o1"))) is
            None)
        self.assertFalse(
            re.match("\<Option \[foo\] 'o2'\>", str(ep.service("o2"))) is None)
        self.assertEqual(ep.service("o1").get_value(), 4)
        ep.service("o1").load("o1", ["new"])
        self.assertEqual(ep.service("o1").get_value(), "new")
        ep.service("o1").load("o1", "old")
        self.assertEqual(ep.service("o1").get_value(), "old")
Example #14
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)
Example #15
0
 def __init__(self, section, ignore_missing=False):
     self._section_ = section
     ep = ExtensionPoint(IOptionDataProvider)
     ep.service().ignore_missing = ignore_missing
     self.__dict__["data"] = ep
Example #16
0
def registered_executable(name=None):
    ep = ExtensionPoint(IExternalExecutable)
    if name is None:
        return filter(lambda x: x.name, ep.extensions())
    return ep.service(name)
Example #17
0
class Configuration(Plugin):
    """This class manages configuration data.  Further, this configuration
    I/O is coordinated with Option objects.  When configuration data is read
    in, associated Option plugins are populated.  Similarly, when
    configuration data is writen, the configuration data is taken from
    Option data."""
    def __init__(self, filename=None, parser="ConfigParser"):
        """Constructor.
            @param filename - The associated configuration file.
            @param parser   - Specify the name of the parser used to
                read/write configuration files.
        """
        self.parser_type = "Configuration_ConfigParser"
        self.filename = filename
        #
        # Define extension points
        #
        self.parsers = ExtensionPoint(IConfiguration)
        self.option_plugins = ExtensionPoint(IOption)
        self.option_data_plugin = ExtensionPoint(IOptionDataProvider)
        self.pathoption_plugins = ExtensionPoint(IFileOption)
        self.postconfig_actions = ExtensionPoint(IUpdatedOptionsAction)
        self.clear()

    def clear(self):
        """Clear local data."""
        self.config = []
        self.data = {}
        self.section = []

    def __contains__(self, name):
        """Return whether the configuration contains a section of the given
        name.
        """
        return name in self.data

    def __getitem__(self, name):
        """Return the configuration section with the specified name."""
        if name not in self.data:
            raise ConfigurationError("No section " + name + " in data")
        return self.data[name]

    def sections(self):
        """Returns the names of all sections in the configuration data."""
        return list(self.data.keys())

    def load(self, filename=None):
        """Load configuration from a file."""
        if len(self.parsers) == 0:  #pragma:nocover
            raise ConfigurationError(
                "No IConfiguration parsers are registered")
        if not filename is None:
            self.filename = filename
        if self.filename is None:
            raise ConfigurationError("Cannot load without a filename")
        for option in self.pathoption_plugins:
            option.set_dir(os.path.dirname(self.filename))
        #
        # By default, we simply take the first parser
        #
        self.config = self.parsers.service(self.parser_type).load(
            self.filename)
        self.data = {}
        self.section = []
        for (s, o, v) in self.config:
            if not s in self.data:
                self.section.append(s)
                self.data[s] = {}
            if not o in self.data[s]:
                self.data[s][o] = []
            self.data[s][o].append(v)
        #
        # Iterate through all sections, in the order they were
        # loaded.  Load data for extensions that match each section name.
        #
        for sec in self.section:
            #
            # Find the option_plugins that match this section
            #
            plugins = []
            for plugin in self.option_plugins:
                if plugin.matches_section(sec):
                    plugins.append(plugin)
            for option in self.data[sec]:
                flag = False
                for plugin in plugins:
                    if plugin.matches_name(option):
                        flag = plugin.load(option,
                                           self.data[sec][option]) or flag
                if not flag:
                    raise ConfigurationError(
                        "Problem loading file %r. Option %r in section %r is not recognized!"
                        % (self.filename, option, sec))
        #
        # Finalize the configuration process
        #
        for plugin in self.postconfig_actions:
            plugin.reset_after_updates()

    def save(self, filename=None):
        """Save configuration to a file."""
        if not filename is None:
            self.filename = filename
        if self.filename is None:
            raise ConfigurationError("Cannot save without a filename")
        #
        # Setup the list of tuples
        #
        self.clear()
        self.data = self.option_data_plugin.service().get_data()
        self.section = list(self.data.keys())
        self.section.sort()
        flag = False
        header = "\nNote: the following configuration options have been omitted because their\nvalue is 'None':\n"
        for sec in self.section:
            plugins = []
            for plugin in self.option_plugins:
                if plugin.matches_section(sec):
                    plugins.append(plugin)
            #
            options = list(self.data[sec].keys())
            options.sort()
            for option in options:
                for plugin in plugins:
                    if plugin.matches_name(option):
                        if not self.data[sec][option] is None:
                            val = self.data[sec][option]
                            self.config.append((sec, option, val))
                        else:
                            flag = True
                            header = header + "  section=%r option=%r\n" % (
                                sec, option)
                        break
        if flag:
            header = header + "\n"
        else:
            header = None
        #
        # Write config file
        #
        self.parsers.service(self.parser_type).save(self.filename, self.config,
                                                    header)

    def pprint(self):
        """Print a simple summary of the configuration data."""
        text = ""
        for (s, o, v) in self.config:
            text += "[%s] %s = %s\n" % (s, o, v)
        print(text)

    def summarize(self):
        """Summarize options"""
        tmp = {}
        for option in self.option_plugins:
            tmp.setdefault(option.section, {})[option.name] = option
        keys = list(tmp.keys())
        keys.sort()
        for key in keys:
            print("[" + key + "]")
            print("")
            okeys = list(tmp[key].keys())
            okeys.sort()
            for okey in okeys:
                print("  Option:    " + tmp[key][okey].name)
                print("  Type:      " + tmp[key][okey].__class__.__name__)
                print("  Default:   " + tmp[key][okey].default_str())
                print("  Doc:       " + tmp[key][okey].__doc__)
                print("")
            print("")
Example #18
0
 def __init__(self, section, ignore_missing=False):
     self._section_ = section
     ep = ExtensionPoint(IOptionDataProvider)
     ep.service().ignore_missing = ignore_missing
     self.__dict__["data"] = ep
Example #19
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)