diff --git a/rna-seek b/rna-seek index 77ca193..ab8f54b 100755 --- a/rna-seek +++ b/rna-seek @@ -21,7 +21,7 @@ import argparse # potential python3 3rd party package, added in python/3.5 # Pipeline Metadata and globals __author__ = 'Skyler Kuhn' -__version__ = 'v1.9.4' +__version__ = 'v1.9.5' __email__ = 'kuhnsa@nih.gov' __home__ = os.path.dirname(os.path.abspath(__file__)) _name = os.path.basename(sys.argv[0]) @@ -122,6 +122,34 @@ def exe_in_path(cmd, path=None): return False +def require(cmds, suggestions, path=None): + """Enforces an executable is in $PATH + @param cmds list[]: + List of executable names to check + @param suggestions list[]: + Name of module to suggest loading for a given index + in param cmd. + @param path list[]]: + Optional list of PATHs to check [default: $PATH] + @return None + """ + error = False + + for i in range(len(cmds)): + available = exe_in_path(cmds[i]) + if not available: + c = Colors + error = True + err( + "\n{0}{1}Fatal: {2} is not in $PATH and is required during runtime!{3}".format(c.bg_red, c.white, cmds[i], c.end), + "\n └── Possible solution: please 'module load {0}' and run again!".format(suggestions[i]) + ) + + if error: fatal() + + return + + def permissions(parser, filename, *args, **kwargs): """Checks permissions using os.access() to see the user is authorized to access a file/directory. Checks for existence, readability, writability and executability via: @@ -653,7 +681,6 @@ def dryrun(outdir, config='config.json', snakefile=os.path.join('workflow', 'Sna '--configfile={}'.format(config) ], cwd = outdir, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: # Singularity is NOT in $PATH # Tell user to load both main dependencies to avoid the OSError below @@ -841,6 +868,11 @@ def run(sub_args): @param sub_args : Parsed arguments for run sub-command """ + # Check for required dependencies + # The pipelines has only two requirements: + # snakemake and singularity + require(['snakemake', 'singularity'], ['snakemake', 'singularity']) + # Get PATH to RNA-seek git repository for copying over pipeline resources git_repo = os.path.dirname(os.path.abspath(__file__)) @@ -911,6 +943,9 @@ def unlock(sub_args): print("Unlocking the pipeline's output directory...") outdir = sub_args.output + # Check for required dependencies: snakemake + require(['snakemake'], ['snakemake']) + try: unlock_output = subprocess.check_output([ 'snakemake', '--unlock', @@ -1037,8 +1072,13 @@ def build(sub_args): """Builds the reference files for the RNA-seek pipeline from a genomic FASTA file and a GTF file. Disclaimer: hybrid genomes not supported. @param sub_args : - Parsed arguments for unlock sub-command + Parsed arguments for build sub-command """ + # Check for required dependencies + # The pipelines has only two requirements: + # snakemake and singularity + require(['snakemake', 'singularity'], ['snakemake', 'singularity']) + # Get PATH to RNA-seek git repository # for copying over pipeline resources git_repo = os.path.dirname(os.path.abspath(__file__)) @@ -1115,14 +1155,16 @@ def cache(sub_args): Local SIFs will be created from images defined in 'config/containers/images.json'. @TODO: add option to cache other shared S3 resources (i.e. kraken db and fqscreen indices) @param sub_args : - Parsed arguments for unlock sub-command + Parsed arguments for cache sub-command """ + # Check for required dependencies: singularity + require(['singularity'], ['singularity']) + sif_cache = sub_args.sif_cache # Get absolute PATH to templates in rna-seek git repo repo_path = os.path.dirname(os.path.abspath(__file__)) images = os.path.join(repo_path, 'config','containers', 'images.json') - # Create image cache if not exists(sif_cache): # Pipeline output directory does not exist on filesystem