Beispiel #1
0
        def decorate(ruleinfo):
            if ruleinfo.wildcard_constraints:
                rule.set_wildcard_constraints(
                    *ruleinfo.wildcard_constraints[0],
                    **ruleinfo.wildcard_constraints[1])
            if ruleinfo.input:
                rule.set_input(*ruleinfo.input[0], **ruleinfo.input[1])
            if ruleinfo.output:
                rule.set_output(*ruleinfo.output[0], **ruleinfo.output[1])
            if ruleinfo.params:
                rule.set_params(*ruleinfo.params[0], **ruleinfo.params[1])
            # handle default resources
            if self.default_resources is not None:
                rule.resources = copy.deepcopy(self.default_resources.parsed)
            if ruleinfo.threads is not None:
                if (not isinstance(ruleinfo.threads, int)
                        and not isinstance(ruleinfo.threads, float)
                        and not callable(ruleinfo.threads)):
                    raise RuleException(
                        "Threads value has to be an integer, float, or a callable.",
                        rule=rule,
                    )
                if name in self.overwrite_threads:
                    rule.resources["_cores"] = self.overwrite_threads[name]
                else:
                    if isinstance(ruleinfo.threads, float):
                        ruleinfo.threads = int(ruleinfo.threads)
                    rule.resources["_cores"] = ruleinfo.threads
            if ruleinfo.shadow_depth:
                if ruleinfo.shadow_depth not in (True, "shallow", "full",
                                                 "minimal"):
                    raise RuleException(
                        "Shadow must either be 'minimal', 'shallow', 'full', "
                        "or True (equivalent to 'full')",
                        rule=rule,
                    )
                if ruleinfo.shadow_depth is True:
                    rule.shadow_depth = "full"
                    logger.warning(
                        "Shadow is set to True in rule {} (equivalent to 'full'). It's encouraged to use the more explicit options 'minimal|shallow|full' instead."
                        .format(rule))
                else:
                    rule.shadow_depth = ruleinfo.shadow_depth
            if ruleinfo.resources:
                args, resources = ruleinfo.resources
                if args:
                    raise RuleException("Resources have to be named.")
                if not all(
                        map(lambda r: isinstance(r, int) or callable(r),
                            resources.values())):
                    raise RuleException(
                        "Resources values have to be integers or callables",
                        rule=rule)
                rule.resources.update(resources)
            if ruleinfo.priority:
                if not isinstance(ruleinfo.priority, int) and not isinstance(
                        ruleinfo.priority, float):
                    raise RuleException("Priority values have to be numeric.",
                                        rule=rule)
                rule.priority = ruleinfo.priority
            if ruleinfo.version:
                rule.version = ruleinfo.version
            if ruleinfo.log:
                rule.set_log(*ruleinfo.log[0], **ruleinfo.log[1])
            if ruleinfo.message:
                rule.message = ruleinfo.message
            if ruleinfo.benchmark:
                rule.benchmark = ruleinfo.benchmark
            if not self.run_local and ruleinfo.group is not None:
                rule.group = ruleinfo.group
            if ruleinfo.wrapper:
                rule.conda_env = snakemake.wrapper.get_conda_env(
                    ruleinfo.wrapper, prefix=self.wrapper_prefix)
                # TODO retrieve suitable singularity image

            if ruleinfo.env_modules:
                # If using environment modules and they are defined for the rule,
                # ignore conda and singularity directive below.
                # The reason is that this is likely intended in order to use
                # a software stack specifically compiled for a particular
                # HPC cluster.
                invalid_rule = not (ruleinfo.script or ruleinfo.wrapper
                                    or ruleinfo.shellcmd or ruleinfo.notebook)
                if invalid_rule:
                    raise RuleException(
                        "envmodules directive is only allowed with "
                        "shell, script, notebook, or wrapper directives (not with run)",
                        rule=rule,
                    )
                from snakemake.deployment.env_modules import EnvModules

                rule.env_modules = EnvModules(*ruleinfo.env_modules)

            if ruleinfo.conda_env:
                if not (ruleinfo.script or ruleinfo.wrapper
                        or ruleinfo.shellcmd or ruleinfo.notebook):
                    raise RuleException(
                        "Conda environments are only allowed "
                        "with shell, script, notebook, or wrapper directives "
                        "(not with run).",
                        rule=rule,
                    )
                if not (urllib.parse.urlparse(ruleinfo.conda_env).scheme
                        or os.path.isabs(ruleinfo.conda_env)):
                    ruleinfo.conda_env = os.path.join(self.current_basedir,
                                                      ruleinfo.conda_env)
                rule.conda_env = ruleinfo.conda_env

            invalid_rule = not (ruleinfo.script or ruleinfo.wrapper
                                or ruleinfo.shellcmd or ruleinfo.notebook)
            if ruleinfo.container_img:
                if invalid_rule:
                    raise RuleException(
                        "Singularity directive is only allowed "
                        "with shell, script, notebook or wrapper directives "
                        "(not with run).",
                        rule=rule,
                    )
                rule.container_img = ruleinfo.container_img
            elif self.global_container_img:
                if not invalid_rule:
                    # skip rules with run directive
                    rule.container_img = self.global_container_img

            rule.norun = ruleinfo.norun
            rule.docstring = ruleinfo.docstring
            rule.run_func = ruleinfo.func
            rule.shellcmd = ruleinfo.shellcmd
            rule.script = ruleinfo.script
            rule.notebook = ruleinfo.notebook
            rule.wrapper = ruleinfo.wrapper
            rule.cwl = ruleinfo.cwl
            rule.restart_times = self.restart_times
            rule.basedir = self.current_basedir

            if ruleinfo.cache is True:
                if not self.enable_cache:
                    logger.warning(
                        "Workflow defines that rule {} is eligible for caching between workflows "
                        "(use the --cache argument to enable this).".format(
                            rule.name))
                else:
                    self.cache_rules.add(rule.name)
            elif not (ruleinfo.cache is False):
                raise WorkflowError(
                    "Invalid argument for 'cache:' directive. Only true allowed. "
                    "To deactivate caching, remove directive.",
                    rule=rule,
                )

            ruleinfo.func.__name__ = "__{}".format(rule.name)
            self.globals[ruleinfo.func.__name__] = ruleinfo.func
            setattr(rules, rule.name, RuleProxy(rule))
            if checkpoint:
                checkpoints.register(rule)
            return ruleinfo.func
Beispiel #2
0
        def decorate(ruleinfo):
            if ruleinfo.wildcard_constraints:
                rule.set_wildcard_constraints(
                    *ruleinfo.wildcard_constraints[0],
                    **ruleinfo.wildcard_constraints[1])
            if ruleinfo.input:
                rule.set_input(*ruleinfo.input[0], **ruleinfo.input[1])
            if ruleinfo.output:
                rule.set_output(*ruleinfo.output[0], **ruleinfo.output[1])
            if ruleinfo.params:
                rule.set_params(*ruleinfo.params[0], **ruleinfo.params[1])
            # handle default resources
            rule.resources = copy.deepcopy(self.default_resources)
            if ruleinfo.threads:
                if not isinstance(ruleinfo.threads, int) and not callable(
                        ruleinfo.threads):
                    raise RuleException(
                        "Threads value has to be an integer or a callable.",
                        rule=rule)
                rule.resources["_cores"] = ruleinfo.threads
            if ruleinfo.shadow_depth:
                if ruleinfo.shadow_depth not in (True, "shallow", "full",
                                                 "minimal"):
                    raise RuleException(
                        "Shadow must either be 'minimal', 'shallow', 'full', "
                        "or True (equivalent to 'full')",
                        rule=rule)
                if ruleinfo.shadow_depth is True:
                    rule.shadow_depth = 'full'
                    logger.warning(
                        "Shadow is set to True in rule {} (equivalent to 'full'). It's encouraged to use the more explicit options 'minimal|shallow|full' instead."
                        .format(rule))
                else:
                    rule.shadow_depth = ruleinfo.shadow_depth
            if ruleinfo.resources:
                args, resources = ruleinfo.resources
                if args:
                    raise RuleException("Resources have to be named.")
                if not all(
                        map(lambda r: isinstance(r, int) or callable(r),
                            resources.values())):
                    raise RuleException(
                        "Resources values have to be integers or callables",
                        rule=rule)
                rule.resources.update(resources)
            if ruleinfo.priority:
                if (not isinstance(ruleinfo.priority, int)
                        and not isinstance(ruleinfo.priority, float)):
                    raise RuleException("Priority values have to be numeric.",
                                        rule=rule)
                rule.priority = ruleinfo.priority
            if ruleinfo.version:
                rule.version = ruleinfo.version
            if ruleinfo.log:
                rule.set_log(*ruleinfo.log[0], **ruleinfo.log[1])
            if ruleinfo.message:
                rule.message = ruleinfo.message
            if ruleinfo.benchmark:
                rule.benchmark = ruleinfo.benchmark
            if not self.run_local and ruleinfo.group is not None:
                rule.group = ruleinfo.group
            if ruleinfo.wrapper:
                if self.use_conda:
                    rule.conda_env = snakemake.wrapper.get_conda_env(
                        ruleinfo.wrapper, prefix=self.wrapper_prefix)
                # TODO retrieve suitable singularity image

            if ruleinfo.conda_env and self.use_conda:
                if not (ruleinfo.script or ruleinfo.wrapper
                        or ruleinfo.shellcmd):
                    raise RuleException(
                        "Conda environments are only allowed "
                        "with shell, script, or wrapper directives "
                        "(not with run).",
                        rule=rule)
                if not (urllib.parse.urlparse(ruleinfo.conda_env).scheme
                        or os.path.isabs(ruleinfo.conda_env)):
                    ruleinfo.conda_env = os.path.join(self.current_basedir,
                                                      ruleinfo.conda_env)
                rule.conda_env = ruleinfo.conda_env

            if self.use_singularity:
                invalid_rule = not (ruleinfo.script or ruleinfo.wrapper
                                    or ruleinfo.shellcmd)
                if ruleinfo.singularity_img:
                    if invalid_rule:
                        raise RuleException(
                            "Singularity directive is only allowed "
                            "with shell, script or wrapper directives "
                            "(not with run).",
                            rule=rule)
                    rule.singularity_img = ruleinfo.singularity_img
                elif self.global_singularity_img:
                    if not invalid_rule:
                        # skip rules with run directive
                        rule.singularity_img = self.global_singularity_img

            if self.use_docker:
                #invalid_rule = not ruleinfo.shellcmd
                invalid_rule = not (ruleinfo.script or ruleinfo.shellcmd)
                if ruleinfo.docker_img:
                    if invalid_rule:
                        raise RuleException(
                            "docker_img directive is only allowed "
                            "with shell or script directives "
                            "(not with run/wrapper).",
                            rule=rule)
                    rule.docker_img = ruleinfo.docker_img
                #elif self.global_singularity_img:
                #    if not invalid_rule:
                #        # skip rules with run directive
                #        rule.singularity_img = self.global_singularity_img

            rule.norun = ruleinfo.norun
            rule.docstring = ruleinfo.docstring
            rule.run_func = ruleinfo.func
            rule.shellcmd = ruleinfo.shellcmd
            rule.script = ruleinfo.script
            rule.wrapper = ruleinfo.wrapper
            rule.cwl = ruleinfo.cwl
            rule.restart_times = self.restart_times
            rule.basedir = self.current_basedir

            ruleinfo.func.__name__ = "__{}".format(rule.name)
            self.globals[ruleinfo.func.__name__] = ruleinfo.func
            setattr(rules, rule.name, RuleProxy(rule))
            if checkpoint:
                checkpoints.register(rule)
            return ruleinfo.func