Schema lint: Handle exceptions for `TypeError`s
Open
Nobody has claimed this yet.
bug
- Dominant language
- Python
- Stars
- 322
- Forks
- 255
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 5
Description
Description of the bug
See this actions run for example, where an integer field had null set as default.
This should fail, but it should be handled nicely with an error message pointing to the relevant field. Rather than an unhandled traceback.
Command used and terminal output
$ nf-core lint
,--./,-.
___ __ __ __ ___ /,-._.--~\
|\ | |__ __ / ` / \ |__) |__ } {
| \| | \__, \__/ | \ |___ \`-._,-`-,
`._,._,'
nf-core/tools version 2.13.1 - https://nf-co.re
INFO Testing pipeline: /home/runner/work/pangenome/pangenome
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /opt/hostedtoolcache/Python/3.11.8/x64/bin/nf-core:8 in <module> │
│ │
│ 5 from nf_core.__main__ import run_nf_core │
│ 6 if __name__ == '__main__': │
│ 7 │ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) │
│ ❱ 8 │ sys.exit(run_nf_core()) │
│ 9 │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/nf_core/ │
│ __main__.py:141 in run_nf_core │
│ │
│ 138 │ │ │ log.debug(f"Could not check latest version: {e}") │
│ 139 │ │ stderr.print("\n") │
│ 140 │ # Launch the click cli │
│ ❱ 141 │ nf_core_cli(auto_envvar_prefix="NFCORE") │
│ 142 │
│ 143 │
│ 144 @tui() │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/click/co │
│ re.py:1157 in __call__ │
│ │
│ 1154 │ │
│ 1155 │ def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: │
│ 1156 │ │ """Alias for :meth:`main`.""" │
│ ❱ 1157 │ │ return self.main(*args, **kwargs) │
│ 1158 │
│ 1159 │
│ 1160 class Command(BaseCommand): │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/rich_cli │
│ ck/rich_command.py:126 in main │
│ │
│ 123 │ │ try: │
│ 124 │ │ │ try: │
│ 125 │ │ │ │ with self.make_context(prog_name, args, **extra) as ct │
│ ❱ 126 │ │ │ │ │ rv = self.invoke(ctx) │
│ 127 │ │ │ │ │ if not standalone_mode: │
│ 128 │ │ │ │ │ │ return rv │
│ 129 │ │ │ │ │ # it's not safe to `ctx.exit(rv)` here! │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/click/co │
│ re.py:1688 in invoke │
│ │
│ 1685 │ │ │ │ super().invoke(ctx) │
│ 1686 │ │ │ │ sub_ctx = cmd.make_context(cmd_name, args, parent=ctx │
│ 1687 │ │ │ │ with sub_ctx: │
│ ❱ 1688 │ │ │ │ │ return _process_result(sub_ctx.command.invoke(sub │
│ 1689 │ │ │
│ 1690 │ │ # In chain mode we create the contexts step by step, but afte │
│ 1691 │ │ # base command has been invoked. Because at that point we do │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/click/co │
│ re.py:1434 in invoke │
│ │
│ 1431 │ │ │ echo(style(message, fg="red"), err=True) │
│ 1432 │ │ │
│ 1433 │ │ if self.callback is not None: │
│ ❱ 1434 │ │ │ return ctx.invoke(self.callback, **ctx.params) │
│ 1435 │ │
│ 1436 │ def shell_complete(self, ctx: Context, incomplete: str) -> t.List │
│ 1437 │ │ """Return a list of completions for the incomplete value. Loo │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/click/co │
│ re.py:783 in invoke │
│ │
│ 780 │ │ │
│ 781 │ │ with augment_usage_errors(__self): │
│ 782 │ │ │ with ctx: │
│ ❱ 783 │ │ │ │ return __callback(*args, **kwargs) │
│ 784 │ │
│ 785 │ def forward( │
│ 786 │ │ __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # no │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/click/de │
│ corators.py:33 in new_func │
│ │
│ 30 │ """ │
│ 31 │ │
│ 32 │ def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": │
│ ❱ 33 │ │ return f(get_current_context(), *args, **kwargs) │
│ 34 │ │
│ 35 │ return update_wrapper(new_func, f) │
│ 36 │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/nf_core/ │
│ __main__.py:607 in lint │
│ │
│ 604 │ │
│ 605 │ # Run the lint tests! │
│ 606 │ try: │
│ ❱ 607 │ │ lint_obj, module_lint_obj, subworkflow_lint_obj = run_linting │
│ 608 │ │ │ dir, │
│ 609 │ │ │ release, │
│ 610 │ │ │ fix, │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/nf_core/ │
│ lint/__init__.py:132 in run_linting │
│ │
│ 129 │ │
│ 130 │ # Run the pipeline linting tests │
│ 131 │ try: │
│ ❱ 132 │ │ lint_obj._lint_pipeline() │
│ 133 │ except AssertionError as e: │
│ 134 │ │ log.critical(f"Critical error: {e}") │
│ 135 │ │ log.info("Stopping tests...") │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/nf_core/ │
│ lint/__init__.py:364 in _lint_pipeline │
│ │
│ 361 │ │ │ │ │ continue │
│ 362 │ │ │ │ self.progress_bar.update(lint_progress, advance=1, tes │
│ 363 │ │ │ │ log.debug(f"Running lint test: {test_name}") │
│ ❱ 364 │ │ │ │ test_results = getattr(self, test_name)() │
│ 365 │ │ │ │ for test in test_results.get("passed", []): │
│ 366 │ │ │ │ │ self.passed.append((test_name, test)) │
│ 367 │ │ │ │ for test in test_results.get("ignored", []): │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/nf_core/ │
│ lint/nextflow_config.py:376 in nextflow_config │
│ │
│ 373 │ schema.schema_filename = schema_path │
│ 374 │ schema.no_prompts = True │
│ 375 │ schema.load_schema() │
│ ❱ 376 │ schema.get_schema_defaults() # Get default values from schema │
│ 377 │ schema.get_schema_types() # Get types from schema │
│ 378 │ self.nf_config.keys() # Params in nextflow.config │
│ 379 │ for param_name in schema.schema_defaults.keys(): │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/nf_core/ │
│ schema.py:174 in get_schema_defaults │
│ │
│ 171 │ │ │ for p_key, param in definition.get("properties", {}).items │
│ 172 │ │ │ │ self.schema_params[p_key] = ("definitions", defn_name, │
│ 173 │ │ │ │ if "default" in param: │
│ ❱ 174 │ │ │ │ │ param = self.sanitise_param_default(param) │
│ 175 │ │ │ │ │ if param["default"] is not None: │
│ 176 │ │ │ │ │ │ self.schema_defaults[p_key] = param["default"] │
│ 177 │
│ │
│ /opt/hostedtoolcache/Python/3.11.8/x64/lib/python3.11/site-packages/nf_core/ │
│ schema.py:139 in sanitise_param_default │
│ │
│ 136 │ │ │
│ 137 │ │ # Integers │
│ 138 │ │ if param["type"] == "integer": │
│ ❱ 139 │ │ │ param["default"] = int(param["default"]) │
│ 140 │ │ │ return param │
│ 141 │ │ │
│ 142 │ │ # Numbers │
╰──────────────────────────────────────────────────────────────────────────────╯
TypeError: int() argument must be a string, a bytes-like object or a real
number, not 'NoneType'
System information
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with nf_core/schema.py around get_schema_defaults(), then follow its call from nf_core/lint/nextflow_config.py. Reproduce the integer field with a null default using nf-core lint and ensure the invalid field produces a useful error message instead of an unhandled traceback.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100