def action_options(self, identifier: str) -> List[Action.Options]: """ Return all action configs of type 'identifier'. :param identifier: Action type, such as 'run' or 'compile'. :return: List of action options of that type. """ return utils.cast_to_list( # type: ignore self.action_block.get(identifier, {}), # type: ignore )
def valid_module( name: str, config: ModuleConfigDict, requires_timeout: Union[int, float], requires_working_directory: Path, ) -> bool: """ Check if the given dict represents a valid enabled module. The method determines this by inspecting any requires items the module might have specified. :param name: Name of module, used for logging purposes. :param config: Configuration dictionary of the module. :param requires_timeout: Time to wait for shell command requirements. :param requires_working_directory: CWD for shell commands. :return: True if module should be enabled. """ if not config.get('enabled', True): return False # The module is enabled, now check if all requirements are satisfied requires: List[RequirementDict] = cast_to_list( config.get( 'requires', {}, ), ) requirements = [ Requirement( requirements=requirements_dict, directory=requires_working_directory, timeout=requires_timeout, ) for requirements_dict in requires ] if all(requirements): return True else: logger.warning( f'[module/{name}] ' + ', '.join([ repr(requirement) for requirement in requirements ]) + '!', ) return False
def valid_class_section( section: ModuleConfig, requires_timeout: Union[int, float], requires_working_directory: Path, ) -> bool: """Check if the given dict represents a valid enabled module.""" if not len(section) == 1: raise RuntimeError( 'Tried to check module section with dict ' 'which does not have exactly one item.', ) try: module_name = next(iter(section.keys())) valid_module_name = \ module_name.split('/')[0].lower() == 'module' # type: ignore enabled = section[module_name].get('enabled', True) if not (valid_module_name and enabled): return False except KeyError: return False # The module is enabled, now check if all requirements are satisfied requires: List[RequirementDict] = cast_to_list( section[module_name].get( 'requires', {}, ), ) requirements = [ Requirement( requirements=requirements_dict, directory=requires_working_directory, timeout=requires_timeout, ) for requirements_dict in requires ] if all(requirements): return True else: logger.warning( f'[{module_name}] ' + ", ".join([repr(requirement) for requirement in requirements]) + '!', ) return False
def __init__( self, action_block: ActionBlockDict, directory: Path, replacer: Replacer, context_store: compiler.Context, ) -> None: """ Construct ActionBlock object. Instantiates action types and appends to: self._run_actions: List[RunAction], and so on... """ assert directory.is_absolute() self.action_block = action_block for identifier, action_type in ( ('import_context', ImportContextAction), ('compile', CompileAction), ('run', RunAction), ('trigger', TriggerAction), ): # Create and persist a list of all ImportContextAction objects action_configs = utils.cast_to_list( # type: ignore self.action_block.get(identifier, {}), # type: ignore ) setattr( self, f'_{identifier}_actions', [action_type( # type: ignore options=action_config, directory=directory, replacer=replacer, context_store=context_store, ) for action_config in action_configs ], )
def __init__( self, name: str, module_config: ModuleConfigDict, module_directory: Path, replacer: Callable[[str], str] = lambda string: string, context_store: Context = Context(), global_modules_config: Optional[GlobalModulesConfig] = None, dry_run: bool = False, ) -> None: """ Initialize Module object with a section from a config dictionary. Section name must be [module/*], where * is the module name. In addition, the enabled option must be set to "true", or not set at all. module_config example: {'name': 'enabled': True, 'event_listener': {'type': 'weekday'}, 'on_startup': {'run': ['echo weekday is {event}']}, } """ self.name = name # The source directory for the module, determining how to interpret # relative paths in the module config self.directory = module_directory # All user string options should be processed by the replacer self.replace = replacer # Use static event_listener if no event_listener is specified self.event_listener: EventListener = \ event_listener_factory( module_config.get( 'event_listener', {'type': 'static'}, ), ) self.context_store = context_store # Move root actions to 'on_startup' block module_config = self.prepare_on_startup_block( module_name=self.name, module_config=module_config, ) # Create action block object for each available action block type action_blocks: ModuleActionBlocks = {'on_modified': {}} # type: ignore params = { 'module_name': self.name, 'directory': self.directory, 'replacer': self.interpolate_string, 'context_store': self.context_store, 'global_modules_config': global_modules_config, } # Create special case setup action block, it removes any action already # performed. action_blocks['on_setup'] = SetupActionBlock( action_block=module_config.get('on_setup', {}), **params, ) # Create normal action blocks for block_name in ('on_startup', 'on_event', 'on_exit'): action_blocks[block_name] = ActionBlock( # type: ignore action_block=module_config.get( # type: ignore block_name, {}, ), **params, ) for path_string, action_block_dict in module_config.get( 'on_modified', {}, ).items(): modified_path = expand_path( path=Path(path_string), config_directory=self.directory, ) action_blocks['on_modified'][modified_path] = \ ActionBlock( action_block=action_block_dict, **params, ) self.action_blocks = action_blocks requirements = cast_to_list(module_config.get('requires', [])) self.depends_on = tuple( # type: ignore requirement['module'] for requirement in requirements if 'module' in requirement )