| 0 | 1 import os | 
|  | 2 import sys | 
|  | 3 from optparse import OptionParser | 
|  | 4 from ConfigParser import SafeConfigParser | 
|  | 5 from xml.etree import ElementTree | 
|  | 6 import subprocess | 
| 2 | 7 from re import compile | 
| 0 | 8 | 
|  | 9 DEBUG = False | 
|  | 10 | 
|  | 11 | 
|  | 12 def main(): | 
|  | 13     (options, args) = _parse_args() | 
|  | 14     for executable, config_path in zip(options.executables, options.configs): | 
| 2 | 15         command_handler = COMMAND_HANDLERS.get(executable, _run_openms) | 
|  | 16         command_handler(executable, config_path) | 
|  | 17 | 
|  | 18 | 
|  | 19 def _run_shell(executable, config_path): | 
|  | 20     command = open(config_path, "r").read().strip() | 
|  | 21     if DEBUG: | 
|  | 22         print "Running shell command %s" % command | 
|  | 23     _exec(command) | 
| 0 | 24 | 
|  | 25 | 
|  | 26 def _run_openms(executable, config_path): | 
|  | 27     _exec("%s -write_ini openms.ini" % executable) | 
|  | 28     tree = ElementTree.parse("openms.ini") | 
|  | 29     options = _load_options(config_path) | 
|  | 30     _set_options(tree, executable, options) | 
|  | 31     tree.write("openms.ini") | 
|  | 32     if DEBUG: | 
|  | 33         print 'With openms.ini as:\n%s\n, calling: %s -ini openms.ini' % (open("openms.ini", "r").read(), executable) | 
|  | 34     _exec("%s -ini openms.ini" % executable) | 
|  | 35 | 
| 2 | 36 COMMAND_HANDLERS = { | 
|  | 37     "__SHELL__": _run_shell, | 
|  | 38 } | 
|  | 39 | 
|  | 40 | 
|  | 41 def _fail(message, return_code=1): | 
|  | 42     print message | 
|  | 43     sys.exit(return_code) | 
|  | 44 | 
| 0 | 45 | 
|  | 46 def _exec(command): | 
|  | 47     proc = subprocess.Popen(args=command, shell=True) | 
|  | 48     return_code = proc.wait() | 
|  | 49     if return_code != 0: | 
| 2 | 50         _fail("Error executing command [%s], return code is %d" % (command, return_code), return_code) | 
| 0 | 51 | 
|  | 52 | 
|  | 53 def _set_options(tree, executable, options): | 
|  | 54     executable_node = tree.find("./NODE[@name='%s']" % executable) | 
| 2 | 55     if executable_node is None: | 
|  | 56         _fail("Could not find options for executable %s" % executable) | 
| 0 | 57     options_node = executable_node.find("./NODE[@name='1']") | 
|  | 58     for key, raw_value in options.items("simple_options"): | 
| 2 | 59         if raw_value is None: | 
|  | 60             _fail("No value found key %s" % key) | 
| 0 | 61         value = _parse_value(raw_value) | 
|  | 62         _set_option(options_node, key.split("!"), value) | 
|  | 63     _set_option(options_node, ["no_progress"], "true", required=False) | 
|  | 64 | 
|  | 65 | 
|  | 66 def _set_option(node, key_parts, value, required=True): | 
|  | 67     key = key_parts[0] | 
|  | 68     if len(key_parts) == 1: | 
| 2 | 69         if not _set_item_value(node, key, value) and \ | 
|  | 70            not _set_list_item_value(node, key, value) and \ | 
|  | 71            required: | 
|  | 72             _fail("Failed to find specific OpenMS option [%s] in node [%s]" % (key, node)) | 
| 0 | 73     else: | 
| 2 | 74         if not node: | 
|  | 75             _fail("Failed to find specific OpenMS option [%s] in node [%s]" % (key, node)) | 
| 0 | 76         sub_node = node.find("./NODE[@name='%s']" % key) | 
| 2 | 77         if not sub_node: | 
|  | 78             _fail("Failed to find node for key %s" % key) | 
| 0 | 79         _set_option(sub_node, key_parts[1:], value, required) | 
|  | 80 | 
|  | 81 | 
| 2 | 82 def _set_item_value(node, key, value): | 
|  | 83     item = node.find("./ITEM[@name='%s']" % key) | 
|  | 84     if item is not None: | 
|  | 85         item.set("value", value) | 
|  | 86     return item is not None | 
|  | 87 | 
|  | 88 | 
|  | 89 def _set_list_item_value(node, key, values): | 
|  | 90     item = node.find("./ITEMLIST[@name='%s']" % key) | 
|  | 91     if item is not None: | 
|  | 92         for value in values.split(","): | 
|  | 93             ElementTree.SubElement(item, "LISTITEM", {"value": value}) | 
|  | 94     return item is not None | 
|  | 95 | 
|  | 96 | 
| 0 | 97 def _parse_value(raw_value): | 
|  | 98     value = raw_value | 
| 2 | 99     for pattern, function in VALUE_FUNCTIONS.iteritems(): | 
|  | 100         try: | 
|  | 101             match = pattern.match(value) | 
|  | 102         except TypeError: | 
|  | 103             print "Invalid value found config file %s" % value | 
|  | 104             sys.exit(1) | 
|  | 105         if match: | 
|  | 106             value = function(*match.groups()) | 
|  | 107     if value is None: | 
|  | 108         print "Failed to properly parse raw value %s" % raw_value | 
|  | 109         sys.exit(1) | 
| 0 | 110     return value | 
|  | 111 | 
|  | 112 | 
|  | 113 ## Special value parser for various OpenMS components | 
| 2 | 114 def _get_pepnovo_models_path(): | 
|  | 115     pepnovo_path = _which('PepNovo') | 
| 0 | 116     pepnovo_dir = os.path.split(pepnovo_path)[0] | 
|  | 117     guesses = [os.path.join(pepnovo_dir, 'Models'), | 
|  | 118                os.path.join(pepnovo_dir, '..', 'Models'), | 
|  | 119                os.path.join(pepnovo_dir, '..', 'share', 'pepnovo', 'Models')] | 
|  | 120     models_dir = None | 
|  | 121     for guess in guesses: | 
|  | 122         if os.path.isdir(guess): | 
|  | 123             models_dir = guess | 
|  | 124             break | 
|  | 125     return models_dir | 
|  | 126 | 
|  | 127 | 
|  | 128 # http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python | 
|  | 129 def _which(program): | 
|  | 130 | 
|  | 131     def is_exe(fpath): | 
|  | 132         return os.path.isfile(fpath) and os.access(fpath, os.X_OK) | 
|  | 133 | 
|  | 134     fpath, fname = os.path.split(program) | 
|  | 135     if fpath: | 
|  | 136         if is_exe(program): | 
|  | 137             return program | 
|  | 138     else: | 
|  | 139         for path in os.environ["PATH"].split(os.pathsep): | 
|  | 140             exe_file = os.path.join(path, program) | 
| 2 | 141             print path | 
| 0 | 142             if is_exe(exe_file): | 
|  | 143                 return exe_file | 
|  | 144 | 
|  | 145     return None | 
|  | 146 | 
|  | 147 | 
| 2 | 148 VALUE_FUNCTIONS = {compile(r"\@WHICH\((.*)\)\@"): _which, | 
|  | 149                    compile(r"\@PEPNOVO_MODELS_PATH\@"): _get_pepnovo_models_path, | 
|  | 150                   } | 
|  | 151 | 
|  | 152 | 
| 0 | 153 def _parse_args(): | 
|  | 154     parser = OptionParser() | 
|  | 155     parser.add_option("-e", "--executable", dest="executables", default=[], action="append") | 
|  | 156     parser.add_option("-c", "--config", dest="configs", default=[], action="append") | 
|  | 157     return parser.parse_args() | 
|  | 158 | 
|  | 159 | 
|  | 160 def _load_options(config_path): | 
|  | 161     config_parser = SafeConfigParser() | 
| 2 | 162     config_parser.optionxform = str | 
| 0 | 163     config_parser.read(config_path) | 
|  | 164     return config_parser | 
|  | 165 | 
|  | 166 if __name__ == "__main__": | 
|  | 167     main() |