Skip to content

Commit

Permalink
fix: fix bugs in --summary and --list-input-changes. Removed outdated…
Browse files Browse the repository at this point in the history
… statement in tutorial. (#2735)

Thanks to @Horstage!


### QC
<!-- Make sure that you can tick the boxes below. -->

* [x] The PR contains a test case for the changes or the changes are
already covered by an existing test case.
* [x] The documentation (`docs/`) is updated to reflect the changes or
this is not necessary (e.g. if the change does neither modify the
language nor the behavior or functionalities of Snakemake).
  • Loading branch information
johanneskoester committed Mar 6, 2024
1 parent 6420428 commit 55c06d8
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 23 deletions.
11 changes: 0 additions & 11 deletions docs/tutorial/advanced.rst
Expand Up @@ -156,17 +156,6 @@ For the rule ``bwa_map`` this works as follows:
shell:
"bwa mem -t {threads} {input} | samtools view -Sb - > {output}"
.. sidebar:: Note

Snakemake does not automatically rerun jobs when new input files are added as
in the exercise below. However, you can get a list of output files that
are affected by such changes with ``snakemake --list-input-changes``.
To trigger a rerun, this bit of bash magic helps:

.. code:: console
snakemake -n --forcerun $(snakemake --list-input-changes)
Any normal function would work as well.
Input functions take as **single argument** a ``wildcards`` object, that allows to access the wildcards values via attributes (here ``wildcards.sample``).
They have to **return a string or a list of strings**, that are interpreted as paths to input files (here, we return the path that is stored for the sample in the config file).
Expand Down
8 changes: 6 additions & 2 deletions snakemake/cli.py
Expand Up @@ -1081,8 +1081,8 @@ def get_argument_parser(profiles=None):
"--lc",
choices=ChangeType.all(),
type=ChangeType.parse_choice,
help="List all output files for which the rule body (run or shell) have "
"changed in the Snakefile.",
help="List all output files for which the given items (code, input, params) "
"have changed since creation.",
)
group_utils.add_argument(
"--list-input-changes",
Expand Down Expand Up @@ -1994,6 +1994,10 @@ def args_to_api(args, parser):
dag_api.container_cleanup_images()
elif args.list_changes:
dag_api.list_changes(args.list_changes)
elif args.list_input_changes:
dag_api.list_changes(ChangeType.INPUT)
elif args.list_params_changes:
dag_api.list_changes(ChangeType.PARAMS)
elif args.list_untracked:
dag_api.list_untracked()
elif args.summary:
Expand Down
13 changes: 4 additions & 9 deletions snakemake/dag.py
Expand Up @@ -2357,18 +2357,15 @@ def html_node(node_id, node, color):

async def summary(self, detailed=False):
if detailed:
yield "output_file\tdate\trule\tversion\tlog-file(s)\tinput-file(s)\tshellcmd\tstatus\tplan"
yield "output_file\tdate\trule\tlog-file(s)\tinput-file(s)\tshellcmd\tstatus\tplan"
else:
yield "output_file\tdate\trule\tversion\tlog-file(s)\tstatus\tplan"
yield "output_file\tdate\trule\tlog-file(s)\tstatus\tplan"

for job in self.jobs:
output = job.output
for f in output:
rule = job.rule.name

version = self.workflow.persistence.version(f)
version = "-" if version is None else str(version)

date = (
time.ctime((await f.mtime()).local_or_storage())
if await f.exists()
Expand Down Expand Up @@ -2400,8 +2397,6 @@ async def summary(self, detailed=False):
status = "missing"
elif self.reason(job).updated_input:
status = "updated input files"
elif self.workflow.persistence.version_changed(job, file=f):
status = f"version changed to {job.rule.version}"
elif self.workflow.persistence.code_changed(job, file=f):
status = "rule implementation changed"
elif self.workflow.persistence.input_changed(job, file=f):
Expand All @@ -2410,10 +2405,10 @@ async def summary(self, detailed=False):
status = "params changed"
if detailed:
yield "\t".join(
(f, date, rule, version, log, input, shellcmd, status, pending)
(f, date, rule, log, input, shellcmd, status, pending)
)
else:
yield "\t".join((f, date, rule, version, log, status, pending))
yield "\t".join((f, date, rule, log, status, pending))

def archive(self, path: Path):
"""Archives workflow such that it can be re-run on a different system.
Expand Down
7 changes: 6 additions & 1 deletion snakemake/workflow.py
Expand Up @@ -878,7 +878,12 @@ def summary(self, detailed: bool = False):
)
self._build_dag()

print("\n".join(async_run(self.dag.summary(detailed=detailed))))
async def join_summary(detailed):
return "\n".join(
[line async for line in self.dag.summary(detailed=detailed)]
)

print(async_run(join_summary(detailed)))

def conda_cleanup_envs(self):
self._prepare_dag(forceall=True, ignore_incomplete=True, lock_warn_only=False)
Expand Down
10 changes: 10 additions & 0 deletions tests/tests.py
Expand Up @@ -2033,3 +2033,13 @@ def test_set_resources_human_readable():
@skip_on_windows
def test_call_inner():
run(dpath("test_inner_call"))


@skip_on_windows
def test_list_input_changes():
run(dpath("test01"), shellcmd="snakemake --list-input-changes", check_results=False)


@skip_on_windows
def test_summary():
run(dpath("test01"), shellcmd="snakemake --summary", check_results=False)

0 comments on commit 55c06d8

Please sign in to comment.