Skip to content

Commit 2b16cc2

Browse files
joverlee521tsibley
andcommitted
pathogens: Workflows are registered independent of their nextstrain run compatibility
Workflows are now registered under a top level "workflows" key in the nextstrain-pathogen.yaml file, and each workflow has its own "compatibility" declarations. The only current "compatibility" declaration remains "nextstrain run". This allows for more meta information about each workflow to be registered in one place not under the banner of compatibility. The nextstrain-pathogen.yaml schema changes to a workflow-first structure like: workflows: ingest: compatibility: nextstrain run: yes phylogenetic: compatibility: nextstrain run: no instead of a compatibility-first structure like: compatibility: nextstrain run: ingest: yes phylogenetic: no as previously introduced¹ (but not yet released). As it was never released, don't bother supporting the latter schema at all anymore. Change first arose out of discussion started by @victorlin in a related PR.² Subsequent discussion with @tsibley³ led to dropping support for the unreleased schema. ¹ <#461> ² <#462 (comment)> ³ <#472 (comment)> Co-authored-by: Thomas Sibley <tsibley@fredhutch.org>
1 parent 172b072 commit 2b16cc2

5 files changed

Lines changed: 49 additions & 28 deletions

File tree

CHANGES.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ development source code and as such may not be routinely kept up to date.
1616
## Improvements
1717

1818
* `nextstrain setup <pathogen>` and `nextstrain version --pathogens` now list
19-
the available workflows for a pathogen if the pathogen lists the workflows
20-
in the top-level `nextstrain-pathogen.yaml` file.
21-
([#461](https://github.com/nextstrain/cli/pull/461))
19+
the available workflows (e.g. `ingest`, `phylogenetic`) for a pathogen if the
20+
workflows are registered as compatible with `nextstrain run` in the
21+
pathogen's `nextstrain-pathogen.yaml` file.
22+
([#461](https://github.com/nextstrain/cli/pull/461), [#472](https://github.com/nextstrain/cli/pull/472))
2223

2324
* Snakemake's storage support downloaded files (stored in `.snakemake/storage/`)
2425
are now downloaded from AWS Batch builds by default.

doc/changes.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ development source code and as such may not be routinely kept up to date.
2020
### Improvements
2121

2222
* `nextstrain setup <pathogen>` and `nextstrain version --pathogens` now list
23-
the available workflows for a pathogen if the pathogen lists the workflows
24-
in the top-level `nextstrain-pathogen.yaml` file.
25-
([#461](https://github.com/nextstrain/cli/pull/461))
23+
the available workflows (e.g. `ingest`, `phylogenetic`) for a pathogen if the
24+
workflows are registered as compatible with `nextstrain run` in the
25+
pathogen's `nextstrain-pathogen.yaml` file.
26+
([#461](https://github.com/nextstrain/cli/pull/461), [#472](https://github.com/nextstrain/cli/pull/472))
2627

2728
* Snakemake's storage support downloaded files (stored in `.snakemake/storage/`)
2829
are now downloaded from AWS Batch builds by default.

nextstrain/cli/command/run.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from ..errors import UserError
3333
from ..pathogens import PathogenVersion
3434
from ..runner import aws_batch, docker, singularity
35-
from ..util import byte_quantity, split_image_name
35+
from ..util import byte_quantity, split_image_name, warn
3636
from ..volume import NamedVolume
3737
from . import build
3838

@@ -229,7 +229,21 @@ def run(opts):
229229
pathogen = PathogenVersion(opts.pathogen)
230230

231231
if opts.workflow not in pathogen.registered_workflows():
232-
print(f"The {opts.workflow!r} workflow is not registered as a compatible workflow, but trying to run anyways.")
232+
warn(cleandoc(f"""
233+
The {opts.workflow!r} workflow is not registered by pathogen {opts.pathogen!r}!
234+
235+
Trying to run it anyways (but it likely won't work)…
236+
"""))
237+
warn()
238+
239+
elif opts.workflow not in pathogen.compatible_workflows("nextstrain run"):
240+
warn(cleandoc(f"""
241+
The {opts.workflow!r} workflow is registered by pathogen {opts.pathogen!r}
242+
but not marked as compatible with `nextstrain run`!
243+
244+
Trying to run it anyways (but it likely won't work)…
245+
"""))
246+
warn()
233247

234248
workflow_directory = pathogen.workflow_path(opts.workflow)
235249

nextstrain/cli/command/version.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ def run(opts):
7272
if opts.verbose:
7373
print(" " + str(version.path))
7474

75-
if registered_workflows := version.registered_workflows():
76-
print(" " + "Available workflows:")
77-
for workflow in registered_workflows:
75+
if compatible_workflows := version.compatible_workflows("nextstrain run"):
76+
print(" " + "Compatible workflows:")
77+
for workflow in compatible_workflows:
7878
print(" " + workflow)
7979
else:
8080
print(" " + "No workflows listed, please refer to pathogen docs.")

nextstrain/cli/pathogens.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -307,21 +307,33 @@ def __init__(self, name_version_url: str, new_setup: bool = False):
307307

308308
def registered_workflows(self) -> Dict[str, Dict]:
309309
"""
310-
Parses :attr:`.registration` to return a dict of registered
311-
compatible workflows, where the keys are workflow names.
310+
Parses :attr:`.registration` to return a dict of registered workflows,
311+
where the keys are workflow names.
312312
"""
313313
if self.registration is None:
314314
debug("pathogen does not have a registration")
315315
return {}
316316

317-
workflows = self.registration.get("compatibility", {}).get("nextstrain run")
317+
workflows = self.registration.get("workflows")
318318
if not isinstance(workflows, dict):
319-
debug(f"pathogen registration.compatibility['nextstrain runs'] is not a dict (got a {type(workflows).__name__})")
319+
debug(f"pathogen registration.workflows is not a dict (got a {type(workflows).__name__})")
320320
return {}
321321

322322
return workflows
323323

324324

325+
def compatible_workflows(self, feature: str) -> Dict[str, Dict]:
326+
"""
327+
Filters registered workflows to return a subset of workflows that are
328+
compatible with the provided *feature*.
329+
"""
330+
return {
331+
name: info
332+
for name, info in self.registered_workflows().items()
333+
if isinstance(info, dict) and info.get("compatibility", {}).get(feature)
334+
}
335+
336+
325337
def workflow_path(self, workflow: str) -> Path:
326338
return self.path / workflow
327339

@@ -481,20 +493,13 @@ def test_compatibility() -> SetupTestResult:
481493
if self.registration is None:
482494
return msg + "\n(couldn't read registration)", False
483495

484-
try:
485-
compatibility = self.registration["compatibility"]["nextstrain run"]
486-
except (KeyError, IndexError, TypeError):
487-
if DEBUGGING:
488-
traceback.print_exc()
489-
return msg + "\n(couldn't find 'compatibility: nextstrain run: …' field)", False
490-
491-
if compatibility:
492-
if workflows := self.registered_workflows():
493-
msg += f"\nAvailable workflows: {list(workflows.keys())}"
494-
else:
495-
msg += f"\nNo workflows listed, please refer to pathogen docs."
496+
if not self.registered_workflows():
497+
return msg + "\n(no workflows registered)", False
498+
499+
if not (compatible_workflows := self.compatible_workflows("nextstrain run")):
500+
return msg + "\n(no workflows registered as compatible)", False
496501

497-
return msg, bool(compatibility)
502+
return msg + f"\nCompatible workflows: {list(compatible_workflows.keys())}", True
498503

499504
return [
500505
('downloaded',

0 commit comments

Comments
 (0)