Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add module linting for when condition #1397

Merged
merged 3 commits into from
Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* Allow for containers from other biocontainers resource as defined [here](https://github.com/nf-core/modules/blob/cde237e7cec07798e5754b72aeca44efe89fc6db/modules/cat/fastq/main.nf#L7-L8)
* Fixed traceback when using `stageAs` syntax as defined [here](https://github.com/nf-core/modules/blob/cde237e7cec07798e5754b72aeca44efe89fc6db/modules/cat/fastq/main.nf#L11)
* Allow conditional process execution from the configuration file ([#1393](https://github.com/nf-core/tools/pull/1393))
* Add linting for when condition([#1397](https://github.com/nf-core/tools/pull/1397))

## [v2.2 - Lead Liger](https://github.com/nf-core/tools/releases/tag/2.2) - [2021-12-14]

Expand Down
35 changes: 33 additions & 2 deletions nf_core/modules/lint/main_nf.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def main_nf(module_lint_object, module):
state = "module"
process_lines = []
script_lines = []
when_lines = []
for l in lines:
if re.search("^\s*process\s*\w*\s*{", l) and state == "module":
state = "process"
Expand All @@ -52,7 +53,10 @@ def main_nf(module_lint_object, module):
if re.search("output\s*:", l) and state in ["input", "process"]:
state = "output"
continue
if re.search("script\s*:", l) and state in ["input", "output", "process"]:
if re.search("when\s*:", l) and state in ["input", "output", "process"]:
state = "when"
continue
if re.search("script\s*:", l) and state in ["input", "output", "when", "process"]:
state = "script"
continue

Expand All @@ -64,6 +68,8 @@ def main_nf(module_lint_object, module):
if state == "output" and not _is_empty(module, l):
outputs += _parse_output(module, l)
outputs = list(set(outputs)) # remove duplicate 'meta's
if state == "when" and not _is_empty(module, l):
when_lines.append(l)
if state == "script" and not _is_empty(module, l):
script_lines.append(l)

Expand All @@ -73,6 +79,9 @@ def main_nf(module_lint_object, module):
else:
module.warned.append(("main_nf_container", "Container versions do not match", module.main_nf))

# Check the when statement
check_when_section(module, when_lines)

# Check the script definition
check_script_section(module, script_lines)

Expand Down Expand Up @@ -121,6 +130,28 @@ def check_script_section(self, lines):
self.failed.append(("main_nf_meta_prefix", "'prefix' unspecified in script section", self.main_nf))


def check_when_section(self, lines):
"""
Lint the when section
Checks whether the line is modified from 'task.ext.when == null || task.ext.when'
"""
if len(lines) == 0:
self.failed.append(("when_exist", "When condition has been removed", self.main_nf))
return
elif len(lines) > 1:
self.failed.append(("when_exist", "When condition has too many lines", self.main_nf))
return
else:
self.passed.append(("when_exist", "When condition is present", self.main_nf))

# Check the condition hasn't been changed.
if lines[0].strip() != "task.ext.when == null || task.ext.when":
self.failed.append(("when_condition", "When condition has been altered", self.main_nf))
return
else:
self.passed.append(("when_condition", "When condition is unchanged", self.main_nf))


def check_process_section(self, lines):
"""
Lint the section of a module between the process definition
Expand All @@ -146,7 +177,7 @@ def check_process_section(self, lines):
if all([x.upper() for x in self.process_name]):
self.passed.append(("process_capitals", "Process name is in capital letters", self.main_nf))
else:
self.failed.append(("process_capitals", "Process name is not in captial letters", self.main_nf))
self.failed.append(("process_capitals", "Process name is not in capital letters", self.main_nf))

# Check that process labels are correct
correct_process_labels = ["process_low", "process_medium", "process_high", "process_long"]
Expand Down