def get_instrument(inst): if isinstance(inst, Instrument): return inst for installed_inst in installed: if identifier(installed_inst.name) == identifier(inst): return installed_inst raise ValueError('Instrument {} is not installed'.format(inst))
def is_installed(instrument): if isinstance(instrument, Instrument): if instrument in installed: return True if instrument.name in [i.name for i in installed]: return True elif isinstance(instrument, type): if instrument in [i.__class__ for i in installed]: return True else: # assume string if identifier(instrument) in [identifier(i.name) for i in installed]: return True return False
def get_output_processor(self, processor): if isinstance(processor, OutputProcessor): return processor processor = identifier(processor) for p in self.processors: if processor == p.name: return p raise ValueError('Output processor {} is not installed'.format(processor))
def get_output_processor(self, processor): if isinstance(processor, OutputProcessor): return processor processor = identifier(processor) for p in self.processors: if processor == p.name: return p raise ValueError( 'Output processor {} is not installed'.format(processor))
def _discover_cooling_module(self): cooling_module = None for module in self.active_cooling_modules: if self.target.has(module): if not cooling_module: cooling_module = getattr(self.target, identifier(module)) else: msg = 'Multiple cooling modules found "{}" "{}".' raise InstrumentError( msg.format(cooling_module.name, module)) return cooling_module
def execute(self, state, args): name = identifier(args.plugin) rst_output = None if name == caseless_string('settings'): rst_output = get_rst_for_global_config() rst_output += get_rst_for_envars() plugin_name = name.lower() kind = 'global:' else: try: plugin = pluginloader.get_plugin_class(name) except NotFoundError: plugin = None if plugin: rst_output = get_rst_from_plugin(plugin) plugin_name = plugin.name kind = '{}:'.format(plugin.kind) else: target = get_target_description(name) if target: rst_output = get_rst_from_target(target) plugin_name = target.name kind = 'target:' if not rst_output: raise NotFoundError( 'Could not find plugin or alias "{}"'.format(name)) if which('pandoc'): p = Popen(['pandoc', '-f', 'rst', '-t', 'man'], stdin=PIPE, stdout=PIPE, stderr=PIPE) if sys.version_info[0] == 3: output, _ = p.communicate(rst_output.encode( sys.stdin.encoding)) output = output.decode(sys.stdout.encoding) else: output, _ = p.communicate(rst_output) # Make sure to double escape back slashes output = output.replace('\\', '\\\\\\') # Correctly format the title and page number of the man page title, body = output.split('\n', 1) title = '.TH {}{} 7'.format(kind, plugin_name) output = '\n'.join([title, body]) call('echo "{}" | man -l -'.format(escape_double_quotes(output)), shell=True) else: print(rst_output) # pylint: disable=superfluous-parens
def _add_found_plugin(self, obj): """ :obj: Found plugin class :ext: matching plugin item. """ self.logger.debug('Adding %s %s', obj.kind, obj.name) key = identifier(obj.name.lower()) if key in self.plugins or key in self.aliases: msg = '{} "{}" already exists.' raise PluginLoaderError(msg.format(obj.kind, obj.name)) # plugins are tracked both, in a common plugins # dict, and in per-plugin kind dict (as retrieving # plugins by kind is a common use case. self.plugins[key] = obj self.kind_map[obj.kind][key] = obj for alias in obj.aliases: alias_id = identifier(alias.name.lower()) if alias_id in self.plugins or alias_id in self.aliases: msg = '{} "{}" already exists.' raise PluginLoaderError(msg.format(obj.kind, obj.name)) self.aliases[alias_id] = alias
def resolve_alias(self, alias_name): """ Try to resolve the specified name as an plugin alias. Returns a two-tuple, the first value of which is actual plugin name, and the iisecond is a dict of parameter values for this alias. If the name passed is already an plugin name, then the result is ``(alias_name, {})``. """ alias_name = identifier(alias_name.lower()) if alias_name in self.plugins: return (alias_name, {}) if alias_name in self.aliases: alias = self.aliases[alias_name] return (alias.plugin_name, copy(alias.params)) raise NotFoundError('Could not find plugin or alias "{}"'.format(alias_name))
def execute(self, state, args): name = identifier(args.plugin) rst_output = None if name == caseless_string('settings'): rst_output = get_rst_for_global_config() rst_output += get_rst_for_envars() plugin_name = name.lower() kind = 'global:' else: try: plugin = pluginloader.get_plugin_class(name) except NotFoundError: plugin = None if plugin: rst_output = get_rst_from_plugin(plugin) plugin_name = plugin.name kind = '{}:'.format(plugin.kind) else: target = get_target_description(name) if target: rst_output = get_rst_from_target(target) plugin_name = target.name kind = 'target:' if not rst_output: raise NotFoundError('Could not find plugin or alias "{}"'.format(name)) if which('pandoc'): p = Popen(['pandoc', '-f', 'rst', '-t', 'man'], stdin=PIPE, stdout=PIPE, stderr=PIPE) if sys.version_info[0] == 3: output, _ = p.communicate(rst_output.encode(sys.stdin.encoding)) output = output.decode(sys.stdout.encoding) else: output, _ = p.communicate(rst_output) # Make sure to double escape back slashes output = output.replace('\\', '\\\\\\') # Correctly format the title and page number of the man page title, body = output.split('\n', 1) title = '.TH {}{} 7'.format(kind, plugin_name) output = '\n'.join([title, body]) call('echo "{}" | man -l -'.format(escape_double_quotes(output)), shell=True) else: print(rst_output) # pylint: disable=superfluous-parens
def __init__(self, config=None): dict.__init__(self) if isinstance(config, dict): config = {identifier(k.lower()): v for k, v in config.items()} self['regular_format'] = config.pop('regular_format', self.defaults['regular_format']) self['verbose_format'] = config.pop('verbose_format', self.defaults['verbose_format']) self['file_format'] = config.pop('file_format', self.defaults['file_format']) self['color'] = config.pop('colour_enabled', self.defaults['color']) # legacy self['color'] = config.pop('color', self.defaults['color']) if config: message = 'Unexpected logging configuration parameters: {}' raise ValueError(message.format(bad_vals=', '.join(list(config.keys())))) elif config is None: for k, v in self.defaults.items(): self[k] = v else: raise ValueError(config)
def __init__(self, target, loader=pluginloader, **kwargs): super(EnergyMeasurement, self).__init__(target, **kwargs) self.instruments = None self.measurement_csvs = {} self.loader = loader self.backend = self.loader.get_plugin(self.instrument) self.params = obj_dict() instrument_parameters = {identifier(k): v for k, v in self.instrument_parameters.items()} supported_params = self.backend.get_parameters() for name, param in supported_params.items(): value = instrument_parameters.pop(name, None) param.set_value(self.params, value) if instrument_parameters: msg = 'Unexpected parameters for backend "{}": {}' raise ConfigError(msg.format(self.instrument, instrument_parameters)) self.backend.validate_parameters(self.params)
def __init__(self, target, loader=pluginloader, **kwargs): super(EnergyMeasurement, self).__init__(target, **kwargs) self.instruments = None self.measurement_csvs = {} self.loader = loader self.backend = self.loader.get_plugin(self.instrument) self.params = obj_dict() instrument_parameters = {identifier(k): v for k, v in self.instrument_parameters.items()} supported_params = self.backend.get_parameters() for name, param in supported_params.items(): value = instrument_parameters.pop(name, None) param.set_value(self.params, value) if instrument_parameters: msg = 'Unexpected parameters for backend "{}": {}' raise ConfigError(msg.format(self.instrument, instrument_parameters)) self.backend.validate_parameters(self.params)
def create_target_description(name, *args, **kwargs): name = identifier(name) for td in _adhoc_target_descriptions: if caseless_string(name) == td.name: msg = 'Target with name "{}" already exists (from source: {})' raise ValueError(msg.format(name, td.source)) stack = inspect.stack() # inspect.stack() returns a list of call frame records for the current thread # in reverse call order. So the first entry is for the current frame and next one # for the immediate caller. Each entry is a tuple in the format # (frame_object, module_path, line_no, function_name, source_lines, source_lines_index) # # Here we assign the path of the calling module as the "source" for this description. # because this might be invoked via the add_scription_for_target wrapper, we need to # check for that, and make sure that we get the info for *its* caller in that case. if stack[1][3] == 'add_description_for_target': source = stack[2][1] else: source = stack[1][1] _adhoc_target_descriptions.append(TargetDescription(name, source, *args, **kwargs))
def create_target_description(name, *args, **kwargs): name = identifier(name) for td in _adhoc_target_descriptions: if caseless_string(name) == td.name: msg = 'Target with name "{}" already exists (from source: {})' raise ValueError(msg.format(name, td.source)) stack = inspect.stack() # inspect.stack() returns a list of call frame records for the current thread # in reverse call order. So the first entry is for the current frame and next one # for the immediate caller. Each entry is a tuple in the format # (frame_object, module_path, line_no, function_name, source_lines, source_lines_index) # # Here we assign the path of the calling module as the "source" for this description. # because this might be invoked via the add_scription_for_target wrapper, we need to # check for that, and make sure that we get the info for *its* caller in that case. if stack[1][3] == 'add_description_for_target': source = stack[2][1] else: source = stack[1][1] _adhoc_target_descriptions.append( TargetDescription(name, source, *args, **kwargs))
def get_target_description(name): targets = list_target_descriptions() for target in targets: if name == identifier(target.name): return target
def __init__(self, name, kind=None, mandatory=None, default=None, override=False, allowed_values=None, description=None, constraint=None, merge=False, aliases=None, global_alias=None): """ Create a new Parameter object. :param name: The name of the parameter. This will become an instance member of the plugin object to which the parameter is applied, so it must be a valid python identifier. This is the only mandatory parameter. :param kind: The type of parameter this is. This must be a callable that takes an arbitrary object and converts it to the expected type, or raised ``ValueError`` if such conversion is not possible. Most Python standard types -- ``str``, ``int``, ``bool``, etc. -- can be used here. This defaults to ``str`` if not specified. :param mandatory: If set to ``True``, then a non-``None`` value for this parameter *must* be provided on plugin object construction, otherwise ``ConfigError`` will be raised. :param default: The default value for this parameter. If no value is specified on plugin construction, this value will be used instead. (Note: if this is specified and is not ``None``, then ``mandatory`` parameter will be ignored). :param override: A ``bool`` that specifies whether a parameter of the same name further up the hierarchy should be overridden. If this is ``False`` (the default), an exception will be raised by the ``AttributeCollection`` instead. :param allowed_values: This should be the complete list of allowed values for this parameter. Note: ``None`` value will always be allowed, even if it is not in this list. If you want to disallow ``None``, set ``mandatory`` to ``True``. :param constraint: If specified, this must be a callable that takes the parameter value as an argument and return a boolean indicating whether the constraint has been satisfied. Alternatively, can be a two-tuple with said callable as the first element and a string describing the constraint as the second. :param merge: The default behaviour when setting a value on an object that already has that attribute is to overrided with the new value. If this is set to ``True`` then the two values will be merged instead. The rules by which the values are merged will be determined by the types of the existing and new values -- see ``merge_config_values`` documentation for details. :param aliases: Alternative names for the same configuration point. These are largely for backwards compatibility. :param global_alias: An alias for this parameter that can be specified at the global level. A global_alias can map onto many ConfigurationPoints. """ self.name = identifier(name) if kind in KIND_MAP: kind = KIND_MAP[kind] if kind is not None and not callable(kind): raise ValueError('Kind must be callable.') self.kind = kind self.mandatory = mandatory if not is_pod(default): msg = "The default for '{}' must be a Plain Old Data type, but it is of type '{}' instead." raise TypeError(msg.format(self.name, type(default))) self.default = default self.override = override self.allowed_values = allowed_values self.description = description if self.kind is None and not self.override: self.kind = str if constraint is not None and not callable(constraint) and not isinstance(constraint, tuple): raise ValueError('Constraint must be callable or a (callable, str) tuple.') self.constraint = constraint self.merge = merge self.aliases = aliases or [] self.global_alias = global_alias if self.default is not None: try: self.validate_value("init", self.default) except ConfigError: raise ValueError('Default value "{}" is not valid'.format(self.default))
def format_parameter(param): if isinstance(param, dict): return {identifier(k): v for k, v in param.items()} else: return param
def format_parameter(param): if isinstance(param, dict): return {identifier(k): v for k, v in param.items()} else: return param
def __init__(self, name, kind=None, mandatory=None, default=None, override=False, allowed_values=None, description=None, constraint=None, merge=False, aliases=None, global_alias=None, deprecated=False): """ Create a new Parameter object. :param name: The name of the parameter. This will become an instance member of the plugin object to which the parameter is applied, so it must be a valid python identifier. This is the only mandatory parameter. :param kind: The type of parameter this is. This must be a callable that takes an arbitrary object and converts it to the expected type, or raised ``ValueError`` if such conversion is not possible. Most Python standard types -- ``str``, ``int``, ``bool``, etc. -- can be used here. This defaults to ``str`` if not specified. :param mandatory: If set to ``True``, then a non-``None`` value for this parameter *must* be provided on plugin object construction, otherwise ``ConfigError`` will be raised. :param default: The default value for this parameter. If no value is specified on plugin construction, this value will be used instead. (Note: if this is specified and is not ``None``, then ``mandatory`` parameter will be ignored). :param override: A ``bool`` that specifies whether a parameter of the same name further up the hierarchy should be overridden. If this is ``False`` (the default), an exception will be raised by the ``AttributeCollection`` instead. :param allowed_values: This should be the complete list of allowed values for this parameter. Note: ``None`` value will always be allowed, even if it is not in this list. If you want to disallow ``None``, set ``mandatory`` to ``True``. :param constraint: If specified, this must be a callable that takes the parameter value as an argument and return a boolean indicating whether the constraint has been satisfied. Alternatively, can be a two-tuple with said callable as the first element and a string describing the constraint as the second. :param merge: The default behaviour when setting a value on an object that already has that attribute is to overrided with the new value. If this is set to ``True`` then the two values will be merged instead. The rules by which the values are merged will be determined by the types of the existing and new values -- see ``merge_config_values`` documentation for details. :param aliases: Alternative names for the same configuration point. These are largely for backwards compatibility. :param global_alias: An alias for this parameter that can be specified at the global level. A global_alias can map onto many ConfigurationPoints. :param deprecated: Specify that this parameter is deprecated and its config should be ignored. If supplied WA will display a warning to the user however will continue execution. """ self.name = identifier(name) kind = KIND_MAP.get(kind, kind) if kind is not None and not callable(kind): raise ValueError('Kind must be callable.') self.kind = kind self.mandatory = mandatory if not is_pod(default): msg = "The default for '{}' must be a Plain Old Data type, but it is of type '{}' instead." raise TypeError(msg.format(self.name, type(default))) self.default = default self.override = override self.allowed_values = allowed_values self.description = description if self.kind is None and not self.override: self.kind = str if constraint is not None and not callable(constraint) and not isinstance(constraint, tuple): raise ValueError('Constraint must be callable or a (callable, str) tuple.') self.constraint = constraint self.merge = merge self.aliases = aliases or [] self.global_alias = global_alias self.deprecated = deprecated if self.default is not None: try: self.validate_value("init", self.default) except ConfigError: raise ValueError('Default value "{}" is not valid'.format(self.default))
def get_target_description(name): targets = list_target_descriptions() for target in targets: if name == identifier(target.name): return target