diff --git a/CHANGELOG.md b/CHANGELOG.md index 23d42cab9a..db3ac967f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### General - Update pre-commit hook astral-sh/ruff-pre-commit to v0.1.15 ([#2705](https://github.com/nf-core/tools/pull/2705)) +- handle float values correctly in default value comparison ([#2711](https://github.com/nf-core/tools/pull/2711)) - fix changelog titles ([#2708](https://github.com/nf-core/tools/pull/2708)) - Print relative path not absolute path in logo cmd log output ([#2709](https://github.com/nf-core/tools/pull/2709)) diff --git a/nf_core/lint/nextflow_config.py b/nf_core/lint/nextflow_config.py index 15794ef677..40c42b17e4 100644 --- a/nf_core/lint/nextflow_config.py +++ b/nf_core/lint/nextflow_config.py @@ -388,18 +388,27 @@ def nextflow_config(self): ignored.append(f"Config default ignored: {param}") elif param in self.nf_config.keys(): if str(self.nf_config[param]) == schema_default: - passed.append(f"Config default value correct: {param}") + passed.append(f"Config default value correct: {param}= {schema_default}") else: # Handle "number" type if schema_default.endswith(".0") and str(self.nf_config[param]) == schema_default[:-2]: - passed.append(f"Config default value correct: {param}") + passed.append(f"Config default value correct: {param}= {schema_default}") else: - failed.append( - f"Config default value incorrect: `{param}` is set as {self._wrap_quotes(schema_default)} in `nextflow_schema.json` but is {self._wrap_quotes(self.nf_config[param])} in `nextflow.config`." - ) + # try to convert to float + try: + if float(self.nf_config[param]) == float(schema_default): + passed.append(f"Config default value correct: {param}= {schema_default}") + else: + failed.append( + f"Config default value incorrect: `{param}` is set as {self._wrap_quotes(schema_default)} in `nextflow_schema.json` but is {self._wrap_quotes(self.nf_config[param])} in `nextflow.config`." + ) + except ValueError: + failed.append( + f"Config default value incorrect: `{param}` is set as {self._wrap_quotes(schema_default)} in `nextflow_schema.json` but is {self._wrap_quotes(self.nf_config[param])} in `nextflow.config`." + ) else: failed.append( - f"Default value from the Nextflow schema '{param} = {self._wrap_quotes(schema_default)}' not found in `nextflow.config`." + f"Default value from the Nextflow schema `{param} = {self._wrap_quotes(schema_default)}` not found in `nextflow.config`." ) return {"passed": passed, "warned": warned, "failed": failed, "ignored": ignored} diff --git a/nf_core/list.py b/nf_core/list.py index d0b59319a3..b22ca56163 100644 --- a/nf_core/list.py +++ b/nf_core/list.py @@ -39,7 +39,7 @@ def list_workflows(filter_by=None, sort_by="release", as_json=False, show_archiv return wfs.print_summary() -def get_local_wf(workflow, revision=None): +def get_local_wf(workflow, revision=None) -> str: """ Check if this workflow has a local copy and use nextflow to pull it if not """ diff --git a/tests/lint/nextflow_config.py b/tests/lint/nextflow_config.py index 60aaee5243..4330dffbfd 100644 --- a/tests/lint/nextflow_config.py +++ b/tests/lint/nextflow_config.py @@ -64,8 +64,8 @@ def test_default_values_match(self): result = lint_obj.nextflow_config() assert len(result["failed"]) == 0 assert len(result["warned"]) == 0 - assert "Config default value correct: params.max_cpus" in result["passed"] - assert "Config default value correct: params.validate_params" in result["passed"] + assert "Config default value correct: params.max_cpus" in str(result["passed"]) + assert "Config default value correct: params.validate_params" in str(result["passed"]) def test_default_values_fail(self): @@ -75,7 +75,7 @@ def test_default_values_fail(self): nf_conf_file = Path(new_pipeline) / "nextflow.config" with open(nf_conf_file) as f: content = f.read() - fail_content = re.sub(r"\bmax_cpus = 16\b", "max_cpus = 0", content) + fail_content = re.sub(r"\bmax_cpus\s*=\s*16\b", "max_cpus = 0", content) with open(nf_conf_file, "w") as f: f.write(fail_content) # Change the default value of max_memory in nextflow_schema.json @@ -115,5 +115,68 @@ def test_default_values_ignored(self): result = lint_obj.nextflow_config() assert len(result["failed"]) == 0 assert len(result["ignored"]) == 1 - assert "Config default value correct: params.max_cpus" not in result["passed"] - assert "Config default ignored: params.max_cpus" in result["ignored"] + assert "Config default value correct: params.max_cpu" not in str(result["passed"]) + assert "Config default ignored: params.max_cpus" in str(result["ignored"]) + + +def test_default_values_float(self): + """Test comparing two float values.""" + new_pipeline = self._make_pipeline_copy() + # Add a float value `dummy=0.0001` to the nextflow.config below `validate_params` + nf_conf_file = Path(new_pipeline) / "nextflow.config" + with open(nf_conf_file) as f: + content = f.read() + fail_content = re.sub( + r"validate_params\s*=\s*true", "params.validate_params = true\ndummy = 0.000000001", content + ) + with open(nf_conf_file, "w") as f: + f.write(fail_content) + # Add a float value `dummy` to the nextflow_schema.json + nf_schema_file = Path(new_pipeline) / "nextflow_schema.json" + with open(nf_schema_file) as f: + content = f.read() + fail_content = re.sub( + r'"validate_params": {', + ' "dummy": {"type": "float","default":0.000000001},\n"validate_params": {', + content, + ) + with open(nf_schema_file, "w") as f: + f.write(fail_content) + + lint_obj = nf_core.lint.PipelineLint(new_pipeline) + lint_obj._load_pipeline_config() + result = lint_obj.nextflow_config() + assert len(result["failed"]) == 0 + assert len(result["warned"]) == 0 + assert "Config default value correct: params.dummy" in str(result["passed"]) + + +def test_default_values_float_fail(self): + """Test comparing two float values.""" + new_pipeline = self._make_pipeline_copy() + # Add a float value `dummy=0.0001` to the nextflow.config below `validate_params` + nf_conf_file = Path(new_pipeline) / "nextflow.config" + with open(nf_conf_file) as f: + content = f.read() + fail_content = re.sub( + r"validate_params\s*=\s*true", "params.validate_params = true\ndummy = 0.000000001", content + ) + with open(nf_conf_file, "w") as f: + f.write(fail_content) + # Add a float value `dummy` to the nextflow_schema.json + nf_schema_file = Path(new_pipeline) / "nextflow_schema.json" + with open(nf_schema_file) as f: + content = f.read() + fail_content = re.sub( + r'"validate_params": {', ' "dummy": {"type": "float","default":0.000001},\n"validate_params": {', content + ) + with open(nf_schema_file, "w") as f: + f.write(fail_content) + + lint_obj = nf_core.lint.PipelineLint(new_pipeline) + lint_obj._load_pipeline_config() + result = lint_obj.nextflow_config() + + assert len(result["failed"]) == 1 + assert len(result["warned"]) == 0 + assert "Config default value incorrect: `params.dummy" in str(result["failed"]) diff --git a/tests/test_lint.py b/tests/test_lint.py index 2f989aeffb..9839265892 100644 --- a/tests/test_lint.py +++ b/tests/test_lint.py @@ -222,6 +222,8 @@ def test_sphinx_md_files(self): ) from .lint.nextflow_config import ( # type: ignore[misc] test_default_values_fail, + test_default_values_float, + test_default_values_float_fail, test_default_values_ignored, test_default_values_match, test_nextflow_config_bad_name_fail,