From 449da48076d0b9ca525dfd1b46edc5e8ae157ea8 Mon Sep 17 00:00:00 2001 From: Matthew Wells Date: Thu, 4 Jul 2024 15:17:57 -0500 Subject: [PATCH] added check for required utilities --- locidex/constants.py | 8 ++++++++ locidex/main.py | 9 +++++++-- locidex/utils.py | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/locidex/constants.py b/locidex/constants.py index d04074f..37b6b29 100644 --- a/locidex/constants.py +++ b/locidex/constants.py @@ -192,3 +192,11 @@ class LocidexDBHeader(NamedTuple): count_int_stops: int dna_ambig_count: int +UTILITIES_CHECK = [ + "makeblastdb", + BlastCommands.tblastn, + BlastCommands.blastn, + BlastCommands.blastp, + "mafft", + "blastdbcheck" +] \ No newline at end of file diff --git a/locidex/main.py b/locidex/main.py index 963995d..ce2f635 100644 --- a/locidex/main.py +++ b/locidex/main.py @@ -4,7 +4,7 @@ import argparse import traceback import logging -from . import format, extract, report, merge, search, build, manifest +from . import format, extract, report, merge, search, build, manifest, utils, constants logger = logging.getLogger(__name__) logging.basicConfig(filemode=sys.stderr, level=logging.DEBUG) @@ -28,14 +28,19 @@ def main(argv=None): for k, v in tasks.items(): format_parser = sub_parsers.add_parser(k, description=v[help_msg], help=v[help_msg]) v[module_idx].add_args(format_parser) - + args = parser.parse_args(argv) if args.command is None: parser.print_help() + try: + utils.check_utilities(logger, constants.UTILITIES_CHECK) + except FileNotFoundError: + pass sys.exit() error_file = "errors.txt" try: + utils.check_utilities(logger, constants.UTILITIES_CHECK) logger.info("Running {}".format(args.command)) tasks[args.command][module_idx].run(args) logger.info("Finished: {}".format(args.command)) diff --git a/locidex/utils.py b/locidex/utils.py index df06ee9..318dd4c 100644 --- a/locidex/utils.py +++ b/locidex/utils.py @@ -1,15 +1,19 @@ import hashlib import json import os +import shutil import argparse +import logging +import errno from collections import Counter from pathlib import Path from locidex.manifest import ManifestItem from Bio.Seq import Seq from typing import Dict, FrozenSet, Optional, List -from locidex.constants import NT_SUB, PROTEIN_ALPHA, DNA_ALPHA, OPTION_GROUPS, FILE_TYPES +from locidex.constants import NT_SUB, PROTEIN_ALPHA, DNA_ALPHA, OPTION_GROUPS, FILE_TYPES, raise_file_not_found_e import locidex.manifest as manifest + def slots(annotations: Dict[str, object]) -> FrozenSet[str]: """ Thank you for this: https://stackoverflow.com/a/63658478 @@ -161,4 +165,30 @@ def get_format(file: Path) -> Optional[str]: if ext in extensions: format = k break - return format \ No newline at end of file + return format + +def check_utility_installed(utility: str) -> Optional[str]: + """ + utility str: The name of an executable to verify installation of + return None if the utility is installed | Message if utility is not installed + """ + out_string: Optional[str] = None + utility_path: Optional[str] = shutil.which(utility) + if utility_path is None: + out_string = f"Utility {utility} is not installed or is not executable." + return out_string + + +def check_utilities(logger: logging.Logger, utilities: List[str]): + """ + Check all utilites are installed + """ + missing_utilities: List[str] = [] + for i in utilities: + output = check_utility_installed(i) + if output is not None: + missing_utilities.append(i) + logger.critical("Missing: {}".format(output)) + + if missing_utilities: + raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), ",".join(missing_utilities)) \ No newline at end of file