Skip to content
Draft
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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ development source code and as such may not be routinely kept up to date.

## Improvements

* `nextstrain setup --list` now lists the available pathogens for setup.
([#502](https://github.com/nextstrain/cli/issues/502)
* Added the following to the list of "well-known" environment variables that are
automatically passed thru to runtimes:

Expand Down
2 changes: 2 additions & 0 deletions doc/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ development source code and as such may not be routinely kept up to date.
(v-next-improvements)=
### Improvements

* `nextstrain setup --list` now lists the available pathogens for setup.
([#502](https://github.com/nextstrain/cli/issues/502)
* Added the following to the list of "well-known" environment variables that are
automatically passed thru to runtimes:

Expand Down
5 changes: 5 additions & 0 deletions doc/commands/setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ nextstrain setup

usage: nextstrain setup [--dry-run] [--force] [--set-default] <pathogen-name>[@<version>[=<url>]]
nextstrain setup [--dry-run] [--force] [--set-default] <runtime-name>
nextstrain setup --list
nextstrain setup --help


Expand Down Expand Up @@ -78,3 +79,7 @@ options

Use this pathogen version or runtime as the default if set up is successful.

.. option:: --list

List available pathogens.

44 changes: 42 additions & 2 deletions nextstrain/cli/command/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from ..errors import UserError
from ..util import colored, runner_module, runner_name, print_and_check_setup_tests
from ..types import Options, RunnerModule, SetupTestResults
from ..pathogens import PathogenVersion, pathogen_defaults
from ..pathogens import PathogenVersion, pathogen_defaults, fetch_nextstrain_run_pathogens
from ..runner import all_runners_by_name, runner_defaults


Expand All @@ -33,10 +33,35 @@
failure = partial(colored, "red")


def list_available_pathogens():
"""
Fetches and displays available pathogens with workflow compatibility details.
"""
print("Fetching available pathogens…")
print()

pathogens = fetch_nextstrain_run_pathogens()
pathogens = sorted(pathogens, key=lambda p: p["name"].lower())

for pathogen in pathogens:
print(pathogen["name"])

compatible_workflows = [
workflow
for workflow, workflow_info in pathogen.get("registration", {}).get("workflows", {}).items()
if isinstance(workflow_info, dict) and workflow_info.get("compatibility", {}).get("nextstrain run")
]
if compatible_workflows:
print(" Workflows compatible with nextstrain run:")
for workflow in compatible_workflows:
print(f" - {workflow}")


def register_parser(subparser):
"""
%(prog)s [--dry-run] [--force] [--set-default] <pathogen-name>[@<version>[=<url>]]
%(prog)s [--dry-run] [--force] [--set-default] <runtime-name>
%(prog)s --list
%(prog)s --help
"""
parser = subparser.add_parser("setup", help = "Set up a pathogen or runtime")
Expand All @@ -60,7 +85,9 @@ def register_parser(subparser):

A runtime is one of {{{', '.join(all_runners_by_name)}}}.
"""),
metavar = "<pathogen>|<runtime>")
metavar = "<pathogen>|<runtime>",
nargs = "?",
default = None)

parser.add_argument(
"--dry-run",
Expand All @@ -78,11 +105,24 @@ def register_parser(subparser):
help = "Use this pathogen version or runtime as the default if set up is successful.",
action = "store_true")

parser.add_argument(
"--list",
help = "List available pathogens.",
action = "store_true")

return parser


@console.auto_dry_run_indicator()
def run(opts: Options) -> int:
if opts.list:
list_available_pathogens()
return 0

if not opts.arg:
print("No pathogen or runtime specified. Run with --list to see available pathogens.")
return 1

try:
runner = runner_module(opts.arg)
except ValueError as e1:
Expand Down
30 changes: 30 additions & 0 deletions nextstrain/cli/pathogens.py
Original file line number Diff line number Diff line change
Expand Up @@ -1198,3 +1198,33 @@ def nextstrain_repo_zip_url(name: str, version: str) -> URL:
return URL(urlquote(revision), version_url)
else:
return version_url


def fetch_nextstrain_run_pathogens() -> List[Dict]:
"""
Fetches all pathogen repos from nextstrain.org, filtered to only those
with at least one `nextstrain run` compatible workflow.

Returns a list of dicts with "name" and optionally "registration" keys.
"""
url = URL("/pathogen-repos", NEXTSTRAIN_DOT_ORG)

with requests.Session() as http:
response = http.get(str(url), headers={"Accept": "application/json"})
response.raise_for_status()
return [repo for repo in response.json() if has_nextstrain_run_compatibility(repo)]


def has_nextstrain_run_compatibility(repo: Dict) -> bool:
"""
Returns True if the pathogen repo has at least one workflow with `nextstrain run` compatibility.
"""
workflows = repo.get("registration", {}).get("workflows", {})

for workflow in workflows.values():
if isinstance(workflow, dict):
compatibility = workflow.get("compatibility", {})
if compatibility.get("nextstrain run"):
return True

return False
Loading