Skip to content

Commit

Permalink
fix: rule inheritance within modules (did previously lead to key erro…
Browse files Browse the repository at this point in the history
…rs) (#1292)

* fix: rule inheritance within modules (did previously lead to key errors)

* skip on windows
  • Loading branch information
johanneskoester committed Dec 7, 2021
1 parent 36732bf commit 603e0a8
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 5 deletions.
12 changes: 9 additions & 3 deletions snakemake/modules.py
Expand Up @@ -13,18 +13,24 @@
from snakemake.common import Rules, Scatter, Gather


def get_name_modifier_func(rules=None, name_modifier=None):
def get_name_modifier_func(rules=None, name_modifier=None, parent_modifier=None):
if name_modifier is None:
return None
else:
if parent_modifier is None:
parent_modifier_func = lambda rulename: rulename
else:
parent_modifier_func = parent_modifier.modify_rulename
if "*" in name_modifier:
return lambda rulename: name_modifier.replace("*", rulename)
return lambda rulename: parent_modifier_func(
name_modifier.replace("*", rulename)
)
elif name_modifier is not None:
if len(rules) > 1:
raise SyntaxError(
"Multiple rules in 'use rule' statement but name modification ('as' statement) does not contain a wildcard '*'."
)
return lambda rulename: name_modifier
return lambda rulename: parent_modifier_func(name_modifier)


class ModuleInfo:
Expand Down
6 changes: 4 additions & 2 deletions snakemake/workflow.py
Expand Up @@ -1819,11 +1819,13 @@ def decorate(maybe_ruleinfo):
raise WorkflowError(
"'use rule' statement from rule in the same module must declare a single rule but multiple rules are declared."
)
orig_rule = self._rules[rules[0]]
orig_rule = self._rules[self.modifier.modify_rulename(rules[0])]
ruleinfo = maybe_ruleinfo if not callable(maybe_ruleinfo) else None
with WorkflowModifier(
self,
rulename_modifier=get_name_modifier_func(rules, name_modifier),
rulename_modifier=get_name_modifier_func(
rules, name_modifier, parent_modifier=self.modifier
),
ruleinfo_overwrite=ruleinfo,
):
self.rule(
Expand Down
25 changes: 25 additions & 0 deletions tests/test_modules_ruledeps_inheritance/Snakefile
@@ -0,0 +1,25 @@
rule all:
input:
"test2.txt",
"test3.txt",
"test4.txt",


module somemodule:
snakefile:
"module/Snakefile"
config:
config


use rule * from somemodule as somemodule_*


module someothermodule:
snakefile:
"module2/Snakefile"
config:
config


use rule * from someothermodule as someothermodule_*
@@ -0,0 +1 @@
test
20 changes: 20 additions & 0 deletions tests/test_modules_ruledeps_inheritance/module/Snakefile
@@ -0,0 +1,20 @@
rule a:
output:
"test.txt"
shell:
"echo test > {output}"


rule b:
input:
rules.a.output[0]
output:
"test2.txt"
shell:
"cp {input} {output}"



use rule b as c with:
output:
"test4.txt"
5 changes: 5 additions & 0 deletions tests/test_modules_ruledeps_inheritance/module2/Snakefile
@@ -0,0 +1,5 @@
rule a:
output:
"test3.txt"
shell:
"echo foo > {output}"
5 changes: 5 additions & 0 deletions tests/tests.py
Expand Up @@ -1377,3 +1377,8 @@ def test_ancient_dag():
@skip_on_windows
def test_checkpoint_allowed_rules():
run(dpath("test_checkpoint_allowed_rules"), targets=["c"], cluster="./qsub")


@skip_on_windows
def test_modules_ruledeps_inheritance():
run(dpath("test_modules_ruledeps_inheritance"))

0 comments on commit 603e0a8

Please sign in to comment.