def _add_found_extension(self, obj, ext): """ :obj: Found extension class :ext: matching extension item. """ self.logger.debug('\tAdding %s %s', ext.name, obj.name) key = identifier(obj.name.lower()) obj.kind = ext.name if key in self.extensions or key in self.aliases: raise LoaderError('{} {} already exists.'.format( ext.name, obj.name)) # Extensions are tracked both, in a common extensions # dict, and in per-extension kind dict (as retrieving # extensions by kind is a common use case. self.extensions[key] = obj store = self._get_store(ext) store[key] = obj for alias in obj.aliases: alias_id = identifier(alias.name) if alias_id in self.extensions or alias_id in self.aliases: raise LoaderError('{} {} already exists.'.format( ext.name, obj.name)) self.aliases[alias_id] = alias # Update global aliases list. If a global alias is already in the list, # then make sure this extension is in the same parent/child hierarchy # as the one already found. for param in obj.parameters: if param.global_alias: if param.global_alias not in self.global_param_aliases: ga = GlobalParameterAlias(param.global_alias) ga.update(obj) self.global_param_aliases[ga.name] = ga else: # global alias already exists. self.global_param_aliases[param.global_alias].update(obj)
def _load_from_paths(self, paths, ignore_paths): self.logger.debug('Loading from paths.') for path in paths: self.logger.debug('Checking path %s', path) for root, _, files in os.walk(path): should_skip = False for igpath in ignore_paths: if root.startswith(igpath): should_skip = True break if should_skip: continue for fname in files: if not os.path.splitext(fname)[1].lower() == '.py': continue filepath = os.path.join(root, fname) try: modname = os.path.splitext( filepath[1:])[0].translate(MODNAME_TRANS) module = imp.load_source(modname, filepath) self._load_module(module) except (SystemExit, ImportError), e: if self.keep_going: self.logger.warn( 'Failed to load {}'.format(filepath)) self.logger.warn('Got: {}'.format(e)) else: raise LoaderError( 'Failed to load {}'.format(filepath), sys.exc_info()) except Exception as e: message = 'Problem loading extensions from {}: {}' raise LoaderError(message.format(filepath, e))
def _validate_ext(self, other_ext): other_param = self.get_param(other_ext) for param, ext in self.iteritems(): if ((not (issubclass(ext, other_ext) or issubclass(other_ext, ext))) and other_param.kind != param.kind): message = 'Duplicate global alias {} declared in {} and {} extensions with different types' raise LoaderError(message.format(self.name, ext.name, other_ext.name)) if not param.name == other_param.name: message = 'Two params {} in {} and {} in {} both declare global alias {}' raise LoaderError(message.format(param.name, ext.name, other_param.name, other_ext.name, self.name))
def _instantiate(cls, args=None, kwargs=None): args = [] if args is None else args kwargs = {} if kwargs is None else kwargs try: return cls(*args, **kwargs) except Exception: raise LoaderError('Could not load {}'.format(cls), sys.exc_info())
def _load_from_packages(self, packages): try: for package in packages: for module in walk_modules(package): self._load_module(module) except ImportError as e: message = 'Problem loading extensions from package {}: {}' raise LoaderError(message.format(package, e.message))
def _load_module(self, module): # NOQA pylint: disable=too-many-branches self.logger.debug('Checking module %s', module.__name__) for obj in vars(module).itervalues(): if inspect.isclass(obj): if not issubclass(obj, Extension) or not hasattr(obj, 'name') or not obj.name: continue try: for ext in self.extension_kinds.values(): if issubclass(obj, ext.cls): self._add_found_extension(obj, ext) break else: # did not find a matching Extension type message = 'Unknown extension type for {} (type: {})' raise LoaderError(message.format(obj.name, obj.__class__.__name__)) except LoaderError as e: if self.keep_going: self.logger.warning(e) else: raise e