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
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)
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)
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
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)
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
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
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")
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")
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")
def registered_executable(name=None): ep = ExtensionPoint(IExternalExecutable) if name is None: return filter(lambda x: x.name, ep.extensions()) return ep.service(name)
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("")
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")
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)
def __init__(self, section, ignore_missing=False): self._section_ = section ep = ExtensionPoint(IOptionDataProvider) ep.service().ignore_missing = ignore_missing self.__dict__["data"] = ep
def registered_executable(name=None): ep = ExtensionPoint(IExternalExecutable) if name is None: return filter(lambda x: x.name, ep.extensions()) return ep.service(name)
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("")
def __init__(self, section, ignore_missing=False): self._section_ = section ep = ExtensionPoint(IOptionDataProvider) ep.service().ignore_missing = ignore_missing self.__dict__["data"] = ep
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)