helpers: allow to overwrite config in mock_snakemake and allow mock_snakemake to be called from repo root

This commit is contained in:
Fabian 2023-03-09 12:45:44 +01:00
parent abe4df543e
commit 5356feab49

View File

@ -295,7 +295,7 @@ def get_aggregation_strategies(aggregation_strategies):
return bus_strategies, generator_strategies return bus_strategies, generator_strategies
def mock_snakemake(rulename, **wildcards): def mock_snakemake(rulename, configfiles=[], **wildcards):
""" """
This function is expected to be executed from the 'scripts'-directory of ' This function is expected to be executed from the 'scripts'-directory of '
the snakemake project. It returns a snakemake.script.Snakemake object, the snakemake project. It returns a snakemake.script.Snakemake object,
@ -307,6 +307,8 @@ def mock_snakemake(rulename, **wildcards):
---------- ----------
rulename: str rulename: str
name of the rule for which the snakemake object should be generated name of the rule for which the snakemake object should be generated
configfiles: list, str
list of configfiles to be used to update the config
**wildcards: **wildcards:
keyword arguments fixing the wildcards. Only necessary if wildcards are keyword arguments fixing the wildcards. Only necessary if wildcards are
needed. needed.
@ -319,17 +321,35 @@ def mock_snakemake(rulename, **wildcards):
from snakemake.script import Snakemake from snakemake.script import Snakemake
script_dir = Path(__file__).parent.resolve() script_dir = Path(__file__).parent.resolve()
assert ( root_dir = script_dir.parent
Path.cwd().resolve() == script_dir
), f"mock_snakemake has to be run from the repository scripts directory {script_dir}" user_in_script_dir = Path.cwd().resolve() == script_dir
os.chdir(script_dir.parent) if user_in_script_dir:
os.chdir(root_dir)
elif Path.cwd().resolve() != root_dir:
raise RuntimeError(
"mock_snakemake has to be run from the repository root"
f" {root_dir} or scripts directory {script_dir}"
)
try:
for p in sm.SNAKEFILE_CHOICES: for p in sm.SNAKEFILE_CHOICES:
if os.path.exists(p): if os.path.exists(p):
snakefile = p snakefile = p
break break
kwargs = dict(rerun_triggers=[]) if parse(sm.__version__) > Version("7.7.0") else {} kwargs = (
workflow = sm.Workflow(snakefile, overwrite_configfiles=[], **kwargs) dict(rerun_triggers=[]) if parse(sm.__version__) > Version("7.7.0") else {}
)
workflow = sm.Workflow(snakefile, **kwargs)
workflow.include(snakefile) workflow.include(snakefile)
if isinstance(configfiles, str):
configfiles = [configfiles]
if configfiles:
for f in configfiles:
if not os.path.exists(f):
raise FileNotFoundError(f"Config file {f} does not exist.")
workflow.configfile(f)
workflow.global_resources = {} workflow.global_resources = {}
rule = workflow.get_rule(rulename) rule = workflow.get_rule(rulename)
dag = sm.dag.DAG(workflow, rules=[rule]) dag = sm.dag.DAG(workflow, rules=[rule])
@ -358,6 +378,8 @@ def mock_snakemake(rulename, **wildcards):
for path in list(snakemake.log) + list(snakemake.output): for path in list(snakemake.log) + list(snakemake.output):
Path(path).parent.mkdir(parents=True, exist_ok=True) Path(path).parent.mkdir(parents=True, exist_ok=True)
finally:
if user_in_script_dir:
os.chdir(script_dir) os.chdir(script_dir)
return snakemake return snakemake