#! /usr/bin/env python """This program is designed to check if a tool that is advertised as supporting NEXUS will accept a file without an error. Initially this is judged simply by the exit code of the process.""" import os import subprocess import sys import time from optparse import OptionParser from nexus_tools_util import * g_script_name = os.path.basename(sys.argv[0]) g_script_dir = os.path.dirname(sys.argv[0]) g_verbose = False def tool_path_check(name, tool): "*Exits* with an informative error if the path field is not valid." if not os.path.exists(tool.path): exit("%s not found at\n %s\ncheck the %s property of %s" % ( name, tool.path, tool.prop_name, g_user_prop_file)) def exit(m): em = "%s: %s" % (g_script_name, m) sys.exit(em) def debug(m): if g_verbose: sys.stderr.write("%s: %s\n" % (g_script_name, m)) def warn(m): sys.stderr.write("%s: %s\n" % (g_script_name, m)) def run_generic_check(cmd, tool, stdin=None, env=None): debug("Executing: %s " %str(cmd)) p = subprocess.Popen(cmd, shell=False, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) st = time.time() (o, e) = p.communicate(stdin) et = time.time() tool.stdout = o tool.stderr = e tool.return_code = p.returncode tool.running_time = et - st def check_generic_acceptance(name, fp, tool): debug("Checking acceptability of %s according to %s" % (fp, tool.name_version())) tool_path_check(name, tool) cmd = [tool.path, fp] return run_generic_check(cmd, tool) def check_bio_nexus_acceptance(fp, tool): debug("Checking acceptability of %s according to %s" % (fp, tool.name_version())) e = dict(os.environ) p5 = os.environ.get("PERL5LIB", "") if p5: e["PERL5LIB"] = "%s%s%s" % (tool.path, os.pathsep, p5) else: e["PERL5LIB"] = tool.path cmd = ["/usr/bin/env", "perl", "-MBio::NEXUS", "-e", "new Bio::NEXUS('%s')" % fp] return run_generic_check(cmd, tool, env=e) def check_cipres_acceptance(fp, tool): return check_generic_acceptance("CIPRES", fp, tool) def check_mb_acceptance(fp, tool): return check_generic_acceptance("MrBayes", fp, tool) def check_mesquite_acceptance(fp, tool): debug("Checking acceptability of %s according to %s" % (fp, tool.name_version())) def check_paup_acceptance(fp, tool): debug("Checking acceptability of %s according to %s" % (fp, tool.name_version())) tool_path_check("PAUP*", tool) cmd = [tool.path, "-n", fp] return run_generic_check(cmd, tool) check_func = { "bio_nexus": check_bio_nexus_acceptance, "cipres_nexus_check": check_cipres_acceptance, "mb": check_mb_acceptance, "mesquite": check_mesquite_acceptance, "paup": check_paup_acceptance, } def check_acceptance(fp, tool): global check_func n = tool.name f = check_func.get(n) if f is None: warn("No checking function available for %s" % n) else: return f(fp, tool) if __name__ == '__main__': parser = OptionParser() parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true", help="Verbose output",) parser.add_option("-t", "--tool", dest="tool", default="", help="tool to check") (options, args) = parser.parse_args() g_verbose = options.verbose tool_info = read_tool_info(g_script_dir, g_script_name, warn=True) if not tool_info: sys.exit(1) # read_tool_info will have given an error message if options.tool: t = options.tool.lower() if not t in g_known_tools: exit("The requested tool (%s) is not known" % options.tool) tl = tool_info.get(t) if tl is None: m = "The selected tool (%s) is not configured. " % t if g_user_prop_file: m = m + " Its path must be listed in the properties file:\n%s" % g_user_prop_file exit(m) tool_info = {t:tl} if g_verbose: write_tool_list(tool_info, sys.stderr) if not args: exit("Expecting an argument specifying a NEXUS file to check.") for file in args: fn = os.path.basename(file) fp = os.path.abspath(file) if not os.path.exists(fp): exit("The file %s does not exist" % fp) if os.path.isdir(fp): exit("%s is a directory, a file was expected" % fp) print '\n' % ( xml_quoteattr("file:%s" % os.path.join(os.path.abspath(g_script_dir), "nexus_accept_test.xsd")), xml_quoteattr(fn), xml_quoteattr(os.path.dirname(fp)) ) for tool_name in g_known_tools: ti_list = tool_info.get(tool_name, []) for tool in ti_list: check_acceptance(fp, tool) print tool.to_xml() print "\n"