diff --git a/docs/snakefiles/reporting.rst b/docs/snakefiles/reporting.rst index 16e7de925..8b367bac9 100644 --- a/docs/snakefiles/reporting.rst +++ b/docs/snakefiles/reporting.rst @@ -5,7 +5,7 @@ Reports ------- From Snakemake 5.1 on, it is possible to automatically generate detailed self-contained HTML reports that encompass runtime statistics, provenance information, workflow topology and results. -**A realistic example report from a real workflow can be found** `here `_. +**As an example, the report of the Snakemake rolling paper can be found** `here `_. For including results into the report, the Snakefile has to be annotated with additional information. Each output file that shall be part of the report has to be marked with the ``report`` flag, which optionally points to a caption in `restructured text format `_ and allows to define a ``category`` for grouping purposes. diff --git a/snakemake/workflow.py b/snakemake/workflow.py index d69ac8332..0844ddb30 100644 --- a/snakemake/workflow.py +++ b/snakemake/workflow.py @@ -1109,7 +1109,7 @@ def files(items): success = self.scheduler.schedule() - if not immediate_submit and not dryrun: + if not immediate_submit and not dryrun and self.mode == Mode.default: dag.cleanup_workdir() if success: diff --git a/tests/common.py b/tests/common.py index ef1532eaf..41f22e4ef 100644 --- a/tests/common.py +++ b/tests/common.py @@ -99,9 +99,9 @@ def run( subpath=None, no_tmpdir=False, check_md5=True, - check_results=True, + check_results=None, cores=3, - nodes=1, + nodes=None, set_pythonpath=True, cleanup=True, conda_frontend="mamba", @@ -119,6 +119,12 @@ def run( directory to the calling test for inspection, and the test should clean it up. """ + if check_results is None: + if not shouldfail: + check_results = True + else: + check_results = False + if set_pythonpath: # Enforce current workdir (the snakemake source dir) to also be in PYTHONPATH # when subprocesses are invoked in the tempdir defined below. @@ -204,43 +210,44 @@ def run( assert not success, "expected error on execution" else: assert success, "expected successful execution" - if check_results: - for resultfile in get_expected_files(results_dir): - if resultfile in [".gitignore", ".gitkeep"] or not os.path.isfile( - os.path.join(results_dir, resultfile) - ): - # this means tests cannot use directories as output files - continue - targetfile = join(tmpdir, resultfile) - expectedfile = join(results_dir, resultfile) - - if ON_WINDOWS: - if os.path.exists(join(results_dir, resultfile + "_WIN")): - continue # Skip test if a Windows specific file exists - if resultfile.endswith("_WIN"): - targetfile = join(tmpdir, resultfile[:-4]) - elif resultfile.endswith("_WIN"): - # Skip win specific result files on Posix platforms - continue - - assert os.path.exists( - targetfile - ), 'expected file "{}" not produced'.format(resultfile) - if check_md5: - md5expected = md5sum(expectedfile, ignore_newlines=ON_WINDOWS) - md5target = md5sum(targetfile, ignore_newlines=ON_WINDOWS) - if md5target != md5expected: - with open(expectedfile) as expected: - expected_content = expected.read() - with open(targetfile) as target: - content = target.read() - assert ( - False - ), "wrong result produced for file '{resultfile}':\n------found------\n{content}\n-----expected-----\n{expected_content}\n-----------------".format( - resultfile=resultfile, - content=content, - expected_content=expected_content, - ) + + if check_results: + for resultfile in get_expected_files(results_dir): + if resultfile in [".gitignore", ".gitkeep"] or not os.path.isfile( + os.path.join(results_dir, resultfile) + ): + # this means tests cannot use directories as output files + continue + targetfile = join(tmpdir, resultfile) + expectedfile = join(results_dir, resultfile) + + if ON_WINDOWS: + if os.path.exists(join(results_dir, resultfile + "_WIN")): + continue # Skip test if a Windows specific file exists + if resultfile.endswith("_WIN"): + targetfile = join(tmpdir, resultfile[:-4]) + elif resultfile.endswith("_WIN"): + # Skip win specific result files on Posix platforms + continue + + assert os.path.exists(targetfile), 'expected file "{}" not produced'.format( + resultfile + ) + if check_md5: + md5expected = md5sum(expectedfile, ignore_newlines=ON_WINDOWS) + md5target = md5sum(targetfile, ignore_newlines=ON_WINDOWS) + if md5target != md5expected: + with open(expectedfile) as expected: + expected_content = expected.read() + with open(targetfile) as target: + content = target.read() + assert ( + False + ), "wrong result produced for file '{resultfile}':\n------found------\n{content}\n-----expected-----\n{expected_content}\n-----------------".format( + resultfile=resultfile, + content=content, + expected_content=expected_content, + ) if not cleanup: return tmpdir diff --git a/tests/test_github_issue1261/Snakefile b/tests/test_github_issue1261/Snakefile new file mode 100644 index 000000000..95a296ffd --- /dev/null +++ b/tests/test_github_issue1261/Snakefile @@ -0,0 +1,20 @@ +import time + +rule all: + input: + ['out/A.txt', 'out/B.txt'], + +rule A: + output: + out= 'out/A.txt', + run: + time.sleep(10) + with open(output.out, 'w') as fout: + fout.write('done') + +rule B: + output: + 'out/B.txt', + run: + time.sleep(5) + raise Exception("Artificially failing rule B, A should go on and finalize properly.") diff --git a/tests/test_github_issue1261/expected-results/out/A.txt b/tests/test_github_issue1261/expected-results/out/A.txt new file mode 100644 index 000000000..348ebd949 --- /dev/null +++ b/tests/test_github_issue1261/expected-results/out/A.txt @@ -0,0 +1 @@ +done \ No newline at end of file diff --git a/tests/tests.py b/tests/tests.py index 855051ab5..7a415055a 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1616,6 +1616,11 @@ def test_github_issue1389(): run(dpath("test_github_issue1389"), resources={"foo": 4}, shouldfail=True) +@skip_on_windows +def test_github_issue1261(): + run(dpath("test_github_issue1261"), shouldfail=True, check_results=True) + + def test_rule_inheritance_globals(): run( dpath("test_rule_inheritance_globals"),