diff --git a/Snakefile b/Snakefile index 079439205..72242b113 100644 --- a/Snakefile +++ b/Snakefile @@ -8,6 +8,7 @@ from getpass import getuser from snakemake.logging import logger from snakemake.utils import validate from collections import OrderedDict +import textwrap import time # Store the user's configuration prior to loading defaults, so we can check for @@ -132,3 +133,21 @@ if "localrules" in config: if "custom_rules" in config: for rule_file in config["custom_rules"]: include: rule_file + +onerror: + # If the workflow failed and the user isn't using the workflow's Conda + # environment, report the required and installed Augur versions and a + # recommendation to use the `--use-conda` flag. + if not workflow.use_conda: + min_augur_version, actual_augur_version = report_augur_versions(config["conda_environment"]) + + print(f"Required Augur version: {min_augur_version}", file=sys.stderr) + print(f"Installed Augur version: {actual_augur_version}", file=sys.stderr) + print( + textwrap.fill( + "Run this workflow with Snakemake's `--use-conda` flag " + + "or update your Docker image " + + "to ensure you're using the latest versions of the required software." + ), + file=sys.stderr + ) diff --git a/workflow/snakemake_rules/common.smk b/workflow/snakemake_rules/common.smk index 2b2f67926..c1199c5b5 100644 --- a/workflow/snakemake_rules/common.smk +++ b/workflow/snakemake_rules/common.smk @@ -2,6 +2,50 @@ """ import datetime from urllib.parse import urlsplit +import yaml + + +def report_augur_versions(conda_env_file): + """Check the globally available version of Augur against the version required in + the Conda environment file. + + """ + with open(conda_env_file, "r") as fh: + env = yaml.load(fh, yaml.FullLoader) + + # Check for Conda installation of Augur first. + augur_package = [ + package + for package in env["dependencies"] + if not isinstance(package, dict) and package.startswith("augur") + ] or None + + if augur_package is None: + # Check for pip installation of Augur. + pip_packages = [ + package["pip"] + for package in env["dependencies"] + if isinstance(package, dict) and "pip" in package + ] or None + + if pip_packages is not None: + augur_package = [ + package + for package in pip_packages[0] + if package.startswith("nextstrain-augur") + ] or None + + min_augur_version = "unknown" + if augur_package is not None and "=" in augur_package[0]: + min_augur_version = augur_package[0].split("=")[-1] + + try: + from augur.__version__ import __version__ as augur_version + except ModuleNotFoundError: + augur_version = "not installed" + + return min_augur_version, augur_version + def numeric_date(dt=None): """