Esempio n. 1
0
    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
        )
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
    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
                ],
            )
Esempio n. 5
0
    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
        )