Skip to content

Commit 504c62d

Browse files
xorrito624mashehu
authored andcommitted
Log subworkflow dependencies on install (#3871)
Mirror remove.py by logging installed components and their dependencies during subworkflow install, and add a test for the dependency log output.
1 parent 7232dd2 commit 504c62d

3 files changed

Lines changed: 45 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
### Subworkflows
2929

30+
- Log subworkflow dependencies on install ([#4357](https://github.com/nf-core/tools/pull/4357))
31+
3032
### Template
3133

3234
- add `process_low_memory` resource label to `base.config` ([#4264](https://github.com/nf-core/tools/pull/4264))

nf_core/components/install.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ def __init__(
5252
else:
5353
self.installed_by = [self.component_type]
5454

55-
def install(self, component: str | dict[str, str], silent: bool = False) -> bool:
55+
def install(
56+
self,
57+
component: str | dict[str, str],
58+
silent: bool = False,
59+
) -> bool:
5660
if isinstance(component, dict):
5761
# Override modules_repo when the component to install is a dependency from a subworkflow.
5862
remote_url = component.get("git_remote", self.current_remote.remote_url)
@@ -167,6 +171,9 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool
167171
self.component_type, self.modules_repo, component, version, self.installed_by, install_track
168172
)
169173

174+
installed_components = []
175+
installed_components.append(component)
176+
170177
if self.component_type == "subworkflows":
171178
# Under --skip-deps, don't propagate --force to transitive deps so
172179
# already-installed ones keep their pinned SHAs and just have
@@ -175,11 +182,17 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool
175182
original_force = self.force
176183
self.force = False
177184
try:
178-
self.install_included_components(component_dir)
185+
self.install_included_components(component_dir, installed_components)
179186
finally:
180187
self.force = original_force
181188
else:
182-
self.install_included_components(component_dir)
189+
self.install_included_components(component_dir, installed_components)
190+
191+
dependencies = set(installed_components) - {component}
192+
if dependencies:
193+
log.info(f"Installed files for '{component}' and its dependencies '{', '.join(sorted(dependencies))}'.")
194+
else:
195+
log.info(f"Installed files for '{component}'.")
183196

184197
# Update container configs for the installed module. Subworkflows have no container entries of their
185198
# own; their included modules each trigger this when installed above.
@@ -207,27 +220,40 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool
207220
Console().print(
208221
Syntax(f"includeConfig '{subworkflow_config}'", "groovy", theme="ansi_dark", padding=1)
209222
)
223+
210224
return True
211225

212-
def install_included_components(self, subworkflow_dir):
226+
def install_included_components(self, subworkflow_dir, installed_components: list[str] | None = None):
213227
"""
214228
Install included modules and subworkflows
215229
"""
230+
if installed_components is None:
231+
installed_components = []
216232
ini_modules_repo = self.modules_repo
217233
modules_to_install, subworkflows_to_install = get_components_to_install(subworkflow_dir)
218-
for s_install in subworkflows_to_install:
234+
for subworkflow_to_install in subworkflows_to_install:
219235
original_installed = self.installed_by
220236
self.installed_by = [Path(subworkflow_dir).parts[-1]]
221-
self.install(s_install, silent=True)
237+
dependency_installed = self.install(subworkflow_to_install, silent=True)
222238
self.installed_by = original_installed
223-
for m_install in modules_to_install:
239+
if dependency_installed:
240+
component_name = (
241+
subworkflow_to_install["name"]
242+
if isinstance(subworkflow_to_install, dict)
243+
else subworkflow_to_install
244+
)
245+
installed_components.append(component_name.replace("/", "_"))
246+
for module_to_install in modules_to_install:
224247
original_component_type = self.component_type
225248
self.component_type = "modules"
226249
original_installed = self.installed_by
227250
self.installed_by = [Path(subworkflow_dir).parts[-1]]
228-
self.install(m_install, silent=True)
251+
dependency_installed = self.install(module_to_install, silent=True)
229252
self.component_type = original_component_type
230253
self.installed_by = original_installed
254+
if dependency_installed:
255+
component_name = module_to_install["name"] if isinstance(module_to_install, dict) else module_to_install
256+
installed_components.append(component_name.replace("/", "_"))
231257
# self.install will have modified self.modules_repo. Restore its original value
232258
self.modules_repo = ini_modules_repo
233259

tests/subworkflows/test_install.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
from pathlib import Path
23

34
import pytest
@@ -65,6 +66,14 @@ def test_subworkflows_install_bam_sort_stats_samtools(self):
6566
assert samtools_idxstats_path.exists()
6667
assert samtools_flagstat_path.exists()
6768

69+
def test_subworkflows_install_logs_dependencies(self):
70+
"""Installing a subworkflow should log its module dependencies (#3871)."""
71+
self.caplog.set_level(logging.INFO)
72+
assert self.subworkflow_install.install("bam_sort_stats_samtools") is not False
73+
assert "Installed files for 'bam_sort_stats_samtools' and its dependencies" in self.caplog.text
74+
assert "samtools_index" in self.caplog.text
75+
assert "bam_stats_samtools" in self.caplog.text
76+
6877
def test_subworkflow_install_nopipeline(self):
6978
"""Test installing a subworkflow - no pipeline given"""
7079
assert self.subworkflow_install.directory is not None

0 commit comments

Comments
 (0)