[med-svn] [snakemake] 01/03: Imported Upstream version 3.5.5
Kevin Murray
daube-guest at moszumanska.debian.org
Fri Jan 29 15:23:14 UTC 2016
This is an automated email from the git hooks/post-receive script.
daube-guest pushed a commit to branch master
in repository snakemake.
commit 14aba72c911da3298a0180e5510e6503dcd8e879
Author: Kevin Murray <spam at kdmurray.id.au>
Date: Fri Jan 29 17:17:35 2016 +0200
Imported Upstream version 3.5.5
---
docker/Dockerfile | 7 --
snakemake/__init__.py | 26 ++++-
snakemake/dag.py | 75 ++++++++++++-
snakemake/executors.py | 11 +-
snakemake/jobs.py | 10 +-
snakemake/parser.py | 14 ++-
snakemake/remote/FTP.py | 2 +-
snakemake/remote/GS.py | 1 +
snakemake/remote/HTTP.py | 2 +-
snakemake/remote/SFTP.py | 2 +-
snakemake/remote/dropbox.py | 2 +-
snakemake/script.py | 122 +++++++++++----------
snakemake/shell.py | 2 +-
snakemake/version.py | 2 +-
snakemake/workflow.py | 28 ++++-
snakemake/wrapper.py | 22 ++++
tests/test_omitfrom/Snakefile | 54 +++++++++
.../test_omitfrom/expected-results/independent.txt | 0
tests/test_omitfrom/expected-results/levelone.txt | 0
.../expected-results/leveltwo_first.txt | 0
.../expected-results/leveltwo_second.txt | 0
tests/test_omitfrom/expected-results/test1.second | 0
tests/test_omitfrom/expected-results/test2.second | 0
tests/test_until/Snakefile | 54 +++++++++
tests/test_until/expected-results/levelone.txt | 0
.../test_until/expected-results/leveltwo_first.txt | 0
.../expected-results/leveltwo_second.txt | 0
tests/test_until/expected-results/test1.second | 0
tests/test_until/expected-results/test2.second | 0
tests/tests.py | 11 ++
30 files changed, 357 insertions(+), 90 deletions(-)
diff --git a/docker/Dockerfile b/docker/Dockerfile
deleted file mode 100644
index 9792c7a..0000000
--- a/docker/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-# a docker image based on Ubuntu with snakemake installed
-FROM ubuntu:14.04
-MAINTAINER Johannes Köster <johannes.koester at tu-dortmund.de>
-RUN apt-get -qq update
-RUN apt-get install -qqy python3-setuptools python3-docutils python3-flask
-RUN easy_install3 snakemake
-ENTRYPOINT ["snakemake"]
diff --git a/snakemake/__init__.py b/snakemake/__init__.py
index 566e443..33ba87c 100644
--- a/snakemake/__init__.py
+++ b/snakemake/__init__.py
@@ -42,6 +42,8 @@ def snakemake(snakefile,
forcetargets=False,
forceall=False,
forcerun=[],
+ until=[],
+ omit_from=[],
prioritytargets=[],
stats=None,
printreason=False,
@@ -272,6 +274,7 @@ def snakemake(snakefile,
overwrite_config=overwrite_config,
overwrite_workdir=workdir,
overwrite_configfile=configfile,
+ overwrite_clusterconfig=cluster_config,
config_args=config_args,
debug=debug)
@@ -313,7 +316,6 @@ def snakemake(snakefile,
quiet=quiet,
keepgoing=keepgoing,
cluster=cluster,
- cluster_config=cluster_config,
cluster_sync=cluster_sync,
drmaa=drmaa,
jobname=jobname,
@@ -351,6 +353,8 @@ def snakemake(snakefile,
forceall=forceall,
forcerun=forcerun,
prioritytargets=prioritytargets,
+ until=until,
+ omit_from=omit_from,
quiet=quiet,
keepgoing=keepgoing,
printshellcmds=printshellcmds,
@@ -358,7 +362,6 @@ def snakemake(snakefile,
printrulegraph=printrulegraph,
printdag=printdag,
cluster=cluster,
- cluster_config=cluster_config,
cluster_sync=cluster_sync,
jobname=jobname,
drmaa=drmaa,
@@ -512,7 +515,7 @@ def get_argument_parser():
"resources: gpu=1. If now two rules require 1 of the resource "
"'gpu' they won't be run in parallel by the scheduler."))
parser.add_argument(
- "--config",
+ "--config", "-C",
nargs="*",
metavar="KEY=VALUE",
help=
@@ -625,6 +628,21 @@ def get_argument_parser():
help=("Tell the scheduler to assign creation of given targets "
"(and all their dependencies) highest priority. (EXPERIMENTAL)"))
parser.add_argument(
+ "--until", "-U",
+ nargs="+",
+ metavar="TARGET",
+ help=("Runs the pipeline until it reaches the specified rules or "
+ "files. Only runs jobs that are dependencies of the specified "
+ "rule or files, does not run sibling DAGs. "))
+ parser.add_argument(
+ "--omit-from", "-O",
+ nargs="+",
+ metavar="TARGET",
+ help=("Prevent the execution or creation of the given rules or files "
+ "as well as any rules or files that are downstream of these targets "
+ "in the DAG. Also runs jobs in sibling DAGs that are independent of the "
+ "rules or files specified here."))
+ parser.add_argument(
"--allow-ambiguity", "-a",
action="store_true",
help=("Don't check for ambiguous rules and simply use the first if "
@@ -945,6 +963,8 @@ def main():
forceall=args.forceall,
forcerun=args.forcerun,
prioritytargets=args.prioritize,
+ until=args.until,
+ omit_from=args.omit_from,
stats=args.stats,
nocolor=args.nocolor,
quiet=args.quiet,
diff --git a/snakemake/dag.py b/snakemake/dag.py
index a767bf1..eb2e8b5 100644
--- a/snakemake/dag.py
+++ b/snakemake/dag.py
@@ -37,6 +37,10 @@ class DAG:
forcefiles=None,
priorityfiles=None,
priorityrules=None,
+ untilfiles=None,
+ untilrules=None,
+ omitfiles=None,
+ omitrules=None,
ignore_ambiguity=False,
force_incomplete=False,
ignore_incomplete=False,
@@ -68,6 +72,10 @@ class DAG:
self.forcerules = set()
self.forcefiles = set()
+ self.untilrules = set()
+ self.untilfiles = set()
+ self.omitrules = set()
+ self.omitfiles = set()
self.updated_subworkflow_files = set()
if forceall:
self.forcerules.update(self.rules)
@@ -75,6 +83,15 @@ class DAG:
self.forcerules.update(forcerules)
if forcefiles:
self.forcefiles.update(forcefiles)
+ if untilrules: # keep only the rule names
+ self.untilrules.update(set(rule.name for rule in untilrules))
+ if untilfiles:
+ self.untilfiles.update(untilfiles)
+ if omitrules:
+ self.omitrules.update(set(rule.name for rule in omitrules))
+ if omitfiles:
+ self.omitfiles.update(omitfiles)
+
self.omitforce = set()
self.force_incomplete = force_incomplete
@@ -95,6 +112,9 @@ class DAG:
self.targetjobs.add(job)
self.update_needrun()
+ self.set_until_jobs()
+ self.delete_omitfrom_jobs()
+
def update_output_index(self):
self.output_index = OutputIndex(self.rules)
@@ -522,6 +542,45 @@ class DAG:
self._len = len(_needrun)
+
+ def in_until(self, job):
+ return (job.rule.name in self.untilrules or
+ not self.untilfiles.isdisjoint(job.output))
+
+
+ def in_omitfrom(self, job):
+ return (job.rule.name in self.omitrules or
+ not self.omitfiles.isdisjoint(job.output))
+
+ def until_jobs(self):
+ 'Returns a generator of jobs specified by untiljobs'
+ return (job for job in self.jobs if self.in_until(job))
+
+ def omitfrom_jobs(self):
+ 'Returns a generator of jobs specified by omitfromjobs'
+ return (job for job in self.jobs if self.in_omitfrom(job))
+
+ def downstream_of_omitfrom(self):
+ "Returns the downstream of --omit-from rules or files."
+ return filter(lambda job: not self.in_omitfrom(job),
+ self.bfs(self.depending, *self.omitfrom_jobs()))
+
+ def delete_omitfrom_jobs(self):
+ "Removes jobs downstream of jobs specified by --omit-from."
+ if not self.omitrules and not self.omitfiles:
+ return
+ downstream_jobs = list(self.downstream_of_omitfrom()) # need to cast as list before deleting jobs
+ for job in downstream_jobs:
+ self.delete_job(job,
+ recursive=False,
+ add_dependencies=True)
+
+ def set_until_jobs(self):
+ "Removes jobs downstream of jobs specified by --omit-from."
+ if not self.untilrules and not self.untilfiles:
+ return
+ self.targetjobs = set(self.until_jobs())
+
def update_priority(self):
""" Update job priorities. """
prioritized = (lambda job: job.rule in self.priorityrules or
@@ -624,7 +683,14 @@ class DAG:
self.replace_job(job_, newjob_)
return newjob
- def delete_job(self, job, recursive=True):
+ def delete_job(self, job,
+ recursive=True,
+ add_dependencies=False):
+ if job in self.targetjobs:
+ self.targetjobs.remove(job)
+ if add_dependencies:
+ for _job in self.dependencies[job]:
+ self.targetjobs.add(_job)
for job_ in self.depending[job]:
del self.dependencies[job_][job]
del self.depending[job]
@@ -646,6 +712,9 @@ class DAG:
self._ready_jobs.remove(job)
def replace_job(self, job, newjob):
+ if job in self.targetjobs:
+ self.targetjobs.remove(job)
+ self.targetjobs.add(newjob)
depending = list(self.depending[job].items())
if self.finished(job):
self._finished.add(newjob)
@@ -657,9 +726,6 @@ class DAG:
if not job_.dynamic_input:
self.dependencies[job_][newjob].update(files)
self.depending[newjob][job_].update(files)
- if job in self.targetjobs:
- self.targetjobs.remove(job)
- self.targetjobs.add(newjob)
def specialize_rule(self, rule, newrule):
assert newrule is not None
@@ -735,6 +801,7 @@ class DAG:
if post:
yield job
+
def is_isomorph(self, job1, job2):
if job1.rule != job2.rule:
return False
diff --git a/snakemake/executors.py b/snakemake/executors.py
index 7bb145e..42931ae 100644
--- a/snakemake/executors.py
+++ b/snakemake/executors.py
@@ -299,7 +299,7 @@ class ClusterExecutor(RealExecutor):
'cd {workflow.workdir_init} && '
'{workflow.snakemakepath} --snakefile {workflow.snakefile} '
'--force -j{cores} --keep-target-files --keep-shadow '
- '--wait-for-files {local_input} --latency-wait {latency_wait} '
+ '--wait-for-files {wait_for_files} --latency-wait {latency_wait} '
'--benchmark-repeats {benchmark_repeats} '
'{overwrite_workdir} {overwrite_config} --nocolor '
'--notemp --quiet --no-hooks --nolock {target}')
@@ -368,7 +368,9 @@ class ClusterExecutor(RealExecutor):
" ".join(self.workflow.config_args))
target = job.output if job.output else job.rule.name
- local_input = " ".join(job.local_input)
+ wait_for_files = list(job.local_input) + [self.tmpdir]
+ if job.shadow_dir:
+ wait_for_files.append(job.shadow_dir)
format = partial(str.format,
job=job,
overwrite_workdir=overwrite_workdir,
@@ -378,7 +380,8 @@ class ClusterExecutor(RealExecutor):
properties=job.json(),
latency_wait=self.latency_wait,
benchmark_repeats=self.benchmark_repeats,
- target=target, local_input=local_input, **kwargs)
+ target=target, wait_for_files=" ".join(wait_for_files),
+ **kwargs)
try:
exec_job = format(self.exec_job)
with open(jobscript, "w") as f:
@@ -578,7 +581,7 @@ class SynchronousClusterExecutor(ClusterExecutor):
os.remove(active_job.jobscript)
self.print_job_error(active_job.job)
print_exception(ClusterJobException(active_job.job, self.dag.jobid(active_job.job),
- jobscript),
+ active_job.jobscript),
self.workflow.linemaps)
active_job.error_callback(active_job.job)
time.sleep(1)
diff --git a/snakemake/jobs.py b/snakemake/jobs.py
index 7c548aa..e8f0433 100644
--- a/snakemake/jobs.py
+++ b/snakemake/jobs.py
@@ -146,9 +146,10 @@ class Job:
def expanded_shadowed_output(self):
""" Get the paths of output files, resolving shadow directory. """
if not self.shadow_dir:
- return self.expanded_output
- for f in self.expanded_output:
- yield os.path.join(self.shadow_dir, f)
+ yield from self.expanded_output
+ else:
+ for f in self.expanded_output:
+ yield os.path.join(self.shadow_dir, f)
@property
def dynamic_wildcards(self):
@@ -463,8 +464,9 @@ class Job:
def __eq__(self, other):
if other is None:
return False
- return self.rule == other.rule and (
+ return (self.rule == other.rule and (
self.dynamic_output or self.wildcards_dict == other.wildcards_dict)
+ and (self.dynamic_input or self.input == other.input))
def __lt__(self, other):
return self.rule.__lt__(other.rule)
diff --git a/snakemake/parser.py b/snakemake/parser.py
index e1eccf9..7fda2be 100644
--- a/snakemake/parser.py
+++ b/snakemake/parser.py
@@ -520,6 +520,15 @@ class Script(Run):
yield token.string, token
+class Wrapper(Script):
+ def start(self):
+ for t in super(Script, self).start():
+ yield t
+ yield "\n"
+ yield INDENT * (self.effective_indent + 1)
+ yield 'wrapper('
+
+
class Rule(GlobalKeywordState):
subautomata = dict(input=Input,
output=Output,
@@ -534,7 +543,8 @@ class Rule(GlobalKeywordState):
shadow=Shadow,
run=Run,
shell=Shell,
- script=Script)
+ script=Script,
+ wrapper=Wrapper)
def __init__(self, snakefile, base_indent=0, dedent=0, root=True):
super().__init__(snakefile,
@@ -582,7 +592,7 @@ class Rule(GlobalKeywordState):
def block_content(self, token):
if is_name(token):
try:
- if token.string == "run" or token.string == "shell" or token.string == "script":
+ if token.string == "run" or token.string == "shell" or token.string == "script" or token.string == "wrapper":
if self.run:
raise self.error(
"Multiple run or shell keywords in rule {}.".format(
diff --git a/snakemake/remote/FTP.py b/snakemake/remote/FTP.py
index 8ce6153..da268d9 100644
--- a/snakemake/remote/FTP.py
+++ b/snakemake/remote/FTP.py
@@ -9,7 +9,7 @@ from contextlib import contextmanager
# module-specific
from snakemake.remote import AbstractRemoteProvider, DomainObject
-from snakemake.exceptions import FTPFileException
+from snakemake.exceptions import FTPFileException, WorkflowError
import snakemake.io
try:
diff --git a/snakemake/remote/GS.py b/snakemake/remote/GS.py
index d7febbe..fb9c3e5 100644
--- a/snakemake/remote/GS.py
+++ b/snakemake/remote/GS.py
@@ -5,6 +5,7 @@ __license__ = "MIT"
# module-specific
from snakemake.remote.S3 import RemoteObject, RemoteProvider as S3RemoteProvider
+from snakemake.exceptions import WorkflowError
try:
# third-party modules
diff --git a/snakemake/remote/HTTP.py b/snakemake/remote/HTTP.py
index b529763..11959f6 100644
--- a/snakemake/remote/HTTP.py
+++ b/snakemake/remote/HTTP.py
@@ -10,7 +10,7 @@ from contextlib import contextmanager
# module-specific
from snakemake.remote import AbstractRemoteProvider, DomainObject
-from snakemake.exceptions import HTTPFileException
+from snakemake.exceptions import HTTPFileException, WorkflowError
import snakemake.io
try:
diff --git a/snakemake/remote/SFTP.py b/snakemake/remote/SFTP.py
index d16b354..bdfff0e 100644
--- a/snakemake/remote/SFTP.py
+++ b/snakemake/remote/SFTP.py
@@ -8,7 +8,7 @@ from contextlib import contextmanager
# module-specific
from snakemake.remote import AbstractRemoteProvider, DomainObject
-from snakemake.exceptions import SFTPFileException
+from snakemake.exceptions import SFTPFileException, WorkflowError
import snakemake.io
try:
diff --git a/snakemake/remote/dropbox.py b/snakemake/remote/dropbox.py
index 258b6a5..bf3a0de 100644
--- a/snakemake/remote/dropbox.py
+++ b/snakemake/remote/dropbox.py
@@ -8,7 +8,7 @@ from contextlib import contextmanager
# module-specific
from snakemake.remote import AbstractRemoteProvider, AbstractRemoteObject
-from snakemake.exceptions import DropboxFileException
+from snakemake.exceptions import DropboxFileException, WorkflowError
import snakemake.io
try:
diff --git a/snakemake/script.py b/snakemake/script.py
index faedbe1..f059b66 100644
--- a/snakemake/script.py
+++ b/snakemake/script.py
@@ -6,6 +6,8 @@ __license__ = "MIT"
import inspect
import os
import traceback
+from urllib.request import urlopen
+from urllib.error import URLError
from snakemake.utils import format
from snakemake.logging import logger
@@ -79,61 +81,67 @@ def script(basedir, path, input, output, params, wildcards, threads, resources,
Load a script from the given basedir + path and execute it.
Supports Python 3 and R.
"""
- path = format(os.path.join(basedir, path), stepout=1)
+ if not path.startswith("http"):
+ path = path.lstrip("file://")
+ path = "file://" + os.path.abspath(os.path.join(basedir, path))
+ path = format(path, stepout=1)
- if path.endswith(".py"):
- with open(path) as source:
- try:
- exec(compile(source.read(), path, "exec"), {
- "snakemake": Snakemake(input, output, params, wildcards,
- threads, resources, log, config)
- })
- except (Exception, BaseException) as ex:
- raise WorkflowError("".join(traceback.format_exception(type(ex), ex, ex.__traceback__)))
- elif path.endswith(".R"):
- try:
- import rpy2.robjects as robjects
- except ImportError:
- raise ValueError(
- "Python 3 package rpy2 needs to be installed to use the R function.")
- with open(path) as source:
- preamble = """
- Snakemake <- setClass(
- "Snakemake",
- slots = c(
- input = "list",
- output = "list",
- params = "list",
- wildcards = "list",
- threads = "numeric",
- log = "list",
- resources = "list",
- config = "list"
- )
- )
- snakemake <- Snakemake(
- input = {},
- output = {},
- params = {},
- wildcards = {},
- threads = {},
- log = {},
- resources = {},
- config = {}
- )
- """.format(REncoder.encode_namedlist(input),
- REncoder.encode_namedlist(output),
- REncoder.encode_namedlist(params),
- REncoder.encode_namedlist(wildcards), threads,
- REncoder.encode_namedlist(log),
- REncoder.encode_namedlist({
- name: value
- for name, value in resources.items()
- if name != "_cores" and name != "_nodes"
- }), REncoder.encode_dict(config))
- logger.debug(preamble)
- source = preamble + source.read()
- robjects.r(source)
- else:
- raise ValueError(
- "Unsupported script: Expecting either Python (.py) or R (.R) script.")
+ try:
+ with urlopen(path) as source:
+ if path.endswith(".py"):
+ try:
+ exec(compile(source.read().decode(), path, "exec"), {
+ "snakemake": Snakemake(input, output, params, wildcards,
+ threads, resources, log, config)
+ })
+ except (Exception, BaseException) as ex:
+ raise WorkflowError("".join(traceback.format_exception(type(ex), ex, ex.__traceback__)))
+ elif path.endswith(".R"):
+ try:
+ import rpy2.robjects as robjects
+ except ImportError:
+ raise ValueError(
+ "Python 3 package rpy2 needs to be installed to use the R function.")
+ with urlopen(path) as source:
+ preamble = """
+ Snakemake <- setClass(
+ "Snakemake",
+ slots = c(
+ input = "list",
+ output = "list",
+ params = "list",
+ wildcards = "list",
+ threads = "numeric",
+ log = "list",
+ resources = "list",
+ config = "list"
+ )
+ )
+ snakemake <- Snakemake(
+ input = {},
+ output = {},
+ params = {},
+ wildcards = {},
+ threads = {},
+ log = {},
+ resources = {},
+ config = {}
+ )
+ """.format(REncoder.encode_namedlist(input),
+ REncoder.encode_namedlist(output),
+ REncoder.encode_namedlist(params),
+ REncoder.encode_namedlist(wildcards), threads,
+ REncoder.encode_namedlist(log),
+ REncoder.encode_namedlist({
+ name: value
+ for name, value in resources.items()
+ if name != "_cores" and name != "_nodes"
+ }), REncoder.encode_dict(config))
+ logger.debug(preamble)
+ source = preamble + source.read().decode()
+ robjects.r(source)
+ else:
+ raise ValueError(
+ "Unsupported script: Expecting either Python (.py) or R (.R) script.")
+ except URLError as e:
+ raise WorkflowError(e)
diff --git a/snakemake/shell.py b/snakemake/shell.py
index bf59350..2c2a2c2 100644
--- a/snakemake/shell.py
+++ b/snakemake/shell.py
@@ -28,7 +28,7 @@ class shell:
@classmethod
def executable(cls, cmd):
if os.path.split(cmd)[-1] == "bash":
- cls._process_prefix = "set -e -o pipefail; "
+ cls._process_prefix = "set -euo pipefail; "
cls._process_args["executable"] = cmd
@classmethod
diff --git a/snakemake/version.py b/snakemake/version.py
index 7a82992..4c5818f 100644
--- a/snakemake/version.py
+++ b/snakemake/version.py
@@ -1 +1 @@
-__version__ = "3.5.4"
+__version__ = "3.5.5"
diff --git a/snakemake/workflow.py b/snakemake/workflow.py
index a222fc0..42490a3 100644
--- a/snakemake/workflow.py
+++ b/snakemake/workflow.py
@@ -27,6 +27,7 @@ from snakemake.io import protected, temp, temporary, expand, dynamic, glob_wildc
from snakemake.persistence import Persistence
from snakemake.utils import update_config
from snakemake.script import script
+from snakemake.wrapper import wrapper
class Workflow:
def __init__(self,
@@ -37,6 +38,7 @@ class Workflow:
overwrite_config=dict(),
overwrite_workdir=None,
overwrite_configfile=None,
+ overwrite_clusterconfig=dict(),
config_args=None,
debug=False):
"""
@@ -64,6 +66,7 @@ class Workflow:
self.overwrite_shellcmd = overwrite_shellcmd
self.overwrite_config = overwrite_config
self.overwrite_configfile = overwrite_configfile
+ self.overwrite_clusterconfig = overwrite_clusterconfig
self.config_args = config_args
self._onsuccess = lambda log: None
self._onerror = lambda log: None
@@ -74,6 +77,10 @@ class Workflow:
config = dict()
config.update(self.overwrite_config)
+ global cluster_config
+ cluster_config = dict()
+ cluster_config.update(self.overwrite_clusterconfig)
+
global rules
rules = Rules()
@@ -165,6 +172,8 @@ class Workflow:
forcetargets=False,
forceall=False,
forcerun=None,
+ until=[],
+ omit_from=[],
prioritytargets=None,
quiet=False,
keepgoing=False,
@@ -172,7 +181,6 @@ class Workflow:
printreason=False,
printdag=False,
cluster=None,
- cluster_config=None,
cluster_sync=None,
jobname=None,
immediate_submit=False,
@@ -225,19 +233,29 @@ class Workflow:
if not targets:
targets = [self.first_rule
] if self.first_rule is not None else list()
+
if prioritytargets is None:
prioritytargets = list()
if forcerun is None:
forcerun = list()
+ if until is None:
+ until = list()
+ if omit_from is None:
+ omit_from = list()
priorityrules = set(rules(prioritytargets))
priorityfiles = set(files(prioritytargets))
forcerules = set(rules(forcerun))
forcefiles = set(files(forcerun))
+ untilrules = set(rules(until))
+ untilfiles = set(files(until))
+ omitrules = set(rules(omit_from))
+ omitfiles = set(files(omit_from))
targetrules = set(chain(rules(targets),
filterfalse(Rule.has_wildcards, priorityrules),
- filterfalse(Rule.has_wildcards, forcerules)))
- targetfiles = set(chain(files(targets), priorityfiles, forcefiles))
+ filterfalse(Rule.has_wildcards, forcerules),
+ filterfalse(Rule.has_wildcards, untilrules)))
+ targetfiles = set(chain(files(targets), priorityfiles, forcefiles, untilfiles))
if forcetargets:
forcefiles.update(targetfiles)
forcerules.update(targetrules)
@@ -264,6 +282,10 @@ class Workflow:
forcerules=forcerules,
priorityfiles=priorityfiles,
priorityrules=priorityrules,
+ untilfiles=untilfiles,
+ untilrules=untilrules,
+ omitfiles=omitfiles,
+ omitrules=omitrules,
ignore_ambiguity=ignore_ambiguity,
force_incomplete=force_incomplete,
ignore_incomplete=ignore_incomplete or printdag or printrulegraph,
diff --git a/snakemake/wrapper.py b/snakemake/wrapper.py
new file mode 100644
index 0000000..e6cc2ec
--- /dev/null
+++ b/snakemake/wrapper.py
@@ -0,0 +1,22 @@
+__author__ = "Johannes Köster"
+__copyright__ = "Copyright 2016, Johannes Köster"
+__email__ = "koester at jimmy.harvard.edu"
+__license__ = "MIT"
+
+
+import os
+
+from snakemake.script import script
+
+
+def wrapper(path, input, output, params, wildcards, threads, resources, log, config):
+ """
+ Load a wrapper from https://bitbucket.org/snakemake/snakemake-wrappers under
+ the given path + wrapper.py and execute it.
+ """
+ # TODO handle requirements.txt
+ if not (path.startswith("http") or path.startswith("file:")):
+ path = os.path.join("https://bitbucket.org/snakemake/snakemake-wrappers/raw", path)
+ if not (path.endswith("wrapper.py") or path.endswith("wrapper.R")):
+ path = os.path.join(path, "wrapper.py")
+ script("", path, input, output, params, wildcards, threads, resources, log, config)
diff --git a/tests/test_omitfrom/Snakefile b/tests/test_omitfrom/Snakefile
new file mode 100644
index 0000000..fcabec1
--- /dev/null
+++ b/tests/test_omitfrom/Snakefile
@@ -0,0 +1,54 @@
+
+rule all:
+ input:
+ "levelthree.txt",
+ "independent.txt",
+ expand("test{num}.final", num=[1, 2])
+
+rule levelone:
+ output: "levelone.txt"
+ shell: "touch {output}"
+
+rule leveltwo_first:
+ input: rules.levelone.output
+ output: "leveltwo_first.txt"
+ shell: "cp -f {input} {output}"
+
+rule leveltwo_second:
+ input: rules.levelone.output
+ output: "leveltwo_second.txt"
+ shell: "cp -f {input} {output}"
+
+rule levelthree: # should not be created
+ input:
+ rules.leveltwo_first.output,
+ rules.leveltwo_second.output
+ output: "levelthree.txt"
+ shell: "cat {input} > {output}"
+
+rule independent: # should be created in --omit-from but not --until
+ output: "independent.txt"
+ shell: "touch {output}"
+
+###### Wildcard Rules #######
+
+rule zeroth_wildcard:
+ output: "test{num}.txt"
+ shell: "touch {output}"
+
+rule first_wildcard:
+ input: 'test{num}.txt'
+ output: 'test{num}.first'
+ shell: 'cp -f {input} {output}'
+
+rule second_wildcard:
+ input: 'test{num}.first'
+ output: 'test{num}.second'
+ shell: 'cp -f {input} {output}'
+
+rule final_wildcard:
+ input: 'test{num}.second'
+ output: 'test{num}.final'
+ shell: 'cp -f {input} {output}'
+
+
diff --git a/tests/test_omitfrom/expected-results/independent.txt b/tests/test_omitfrom/expected-results/independent.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_omitfrom/expected-results/levelone.txt b/tests/test_omitfrom/expected-results/levelone.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_omitfrom/expected-results/leveltwo_first.txt b/tests/test_omitfrom/expected-results/leveltwo_first.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_omitfrom/expected-results/leveltwo_second.txt b/tests/test_omitfrom/expected-results/leveltwo_second.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_omitfrom/expected-results/test1.second b/tests/test_omitfrom/expected-results/test1.second
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_omitfrom/expected-results/test2.second b/tests/test_omitfrom/expected-results/test2.second
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_until/Snakefile b/tests/test_until/Snakefile
new file mode 100644
index 0000000..fcabec1
--- /dev/null
+++ b/tests/test_until/Snakefile
@@ -0,0 +1,54 @@
+
+rule all:
+ input:
+ "levelthree.txt",
+ "independent.txt",
+ expand("test{num}.final", num=[1, 2])
+
+rule levelone:
+ output: "levelone.txt"
+ shell: "touch {output}"
+
+rule leveltwo_first:
+ input: rules.levelone.output
+ output: "leveltwo_first.txt"
+ shell: "cp -f {input} {output}"
+
+rule leveltwo_second:
+ input: rules.levelone.output
+ output: "leveltwo_second.txt"
+ shell: "cp -f {input} {output}"
+
+rule levelthree: # should not be created
+ input:
+ rules.leveltwo_first.output,
+ rules.leveltwo_second.output
+ output: "levelthree.txt"
+ shell: "cat {input} > {output}"
+
+rule independent: # should be created in --omit-from but not --until
+ output: "independent.txt"
+ shell: "touch {output}"
+
+###### Wildcard Rules #######
+
+rule zeroth_wildcard:
+ output: "test{num}.txt"
+ shell: "touch {output}"
+
+rule first_wildcard:
+ input: 'test{num}.txt'
+ output: 'test{num}.first'
+ shell: 'cp -f {input} {output}'
+
+rule second_wildcard:
+ input: 'test{num}.first'
+ output: 'test{num}.second'
+ shell: 'cp -f {input} {output}'
+
+rule final_wildcard:
+ input: 'test{num}.second'
+ output: 'test{num}.final'
+ shell: 'cp -f {input} {output}'
+
+
diff --git a/tests/test_until/expected-results/levelone.txt b/tests/test_until/expected-results/levelone.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_until/expected-results/leveltwo_first.txt b/tests/test_until/expected-results/leveltwo_first.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_until/expected-results/leveltwo_second.txt b/tests/test_until/expected-results/leveltwo_second.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_until/expected-results/test1.second b/tests/test_until/expected-results/test1.second
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_until/expected-results/test2.second b/tests/test_until/expected-results/test2.second
new file mode 100644
index 0000000..e69de29
diff --git a/tests/tests.py b/tests/tests.py
index 011ddc4..e428e23 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -300,6 +300,17 @@ def test_script():
def test_shadow():
run(dpath("test_shadow"))
+def test_until():
+ run(dpath("test_until"),
+ until=["leveltwo_first", # rule name
+ "leveltwo_second.txt", # file name
+ "second_wildcard"]) # wildcard rule
+
+def test_omitfrom():
+ run(dpath("test_omitfrom"),
+ omit_from=["leveltwo_first", # rule name
+ "leveltwo_second.txt", # file name
+ "second_wildcard"]) # wildcard rule
def test_nonstr_params():
run(dpath("test_nonstr_params"))
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/snakemake.git
More information about the debian-med-commit
mailing list