# -*- coding: utf-8 -*- """Module that handles argument parsing and stores default program options""" import argparse from os import getcwd from os.path import abspath, join, isfile import json import re from . import logger from pkg_resources import resource_filename _name = "AggParser" _shorts = { 'i': 'protein', 'm': 'mutate', 'd': 'dynamic', 'D': 'distance', 'w': 'work_dir', 'O': 'overwrite', 'v': 'verbose', 'C': 'chain', 'f': 'foldx', 'M': 'movie', 'n': 'naccess', 'o': 'output', 'r': 'remote', 'cabs': "cabs_dir", 'cabs_config': 'cabs_config', 'n_models': 'n_models', 'am': 'auto_mutation', 'ph': 'ph' } class ExtendAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): items = getattr(namespace, self.dest) or [] items.extend(values) setattr(namespace, self.dest, items) def ph_range(ph): try: ph_value = float(ph) except ValueError: raise argparse.ArgumentTypeError("pH should be provided as a non-zero number value") if ph_value <= 0 or ph_value > 14: raise argparse.ArgumentTypeError("pH should be take values between (0,14]") else: return ph_value def parse(options): parser = get_parser_object() read = parser.parse_args(options) data, mut = [], [] if read.config_file: data, mut = parse_config_file(read.config_file) data.extend(options) read = parser.parse_args(data) auto_mutation = _parse_auto_mut(read.auto_mutation) # This is a safety measure in case a path is changed inside the program and the relative would be no longer valid cabs_config, foldx, naccess = '', '', '' if read.cabs_config: cabs_config = abspath(read.cabs_config) if read.foldx != "argument_not_used" and read.foldx is not None: # Prevent assiging a path to not-used argument read.foldx = abspath(read.foldx) if read.naccess: naccess = abspath(read.naccess) foldx = _handle_foldx(read.foldx) work_dir = abspath(read.work_dir) tmp_dir = join(work_dir, "tmp") new_mut = _parse_mut(read.mutate) if new_mut: mut.extend(new_mut) # Catch some of the unwanted option combinations here. if new_mut and auto_mutation: raise logger.InputError("Both manual and automated mutations selected. Please select just one of those as they are exclusive.") if auto_mutation and read.dynamic: raise logger.InputError("Automated mutations are not (yet?) supported with dynamic mode.") if auto_mutation and not foldx: raise logger.InputError("Automated mutations require FoldX to work. Please specify a path with -f.") options = { 'protein': read.protein, 'dynamic': read.dynamic, 'mutate': mut, 'distance': read.distance, 'work_dir': work_dir, 'overwrite': read.overwrite, 'verbose': read.verbose, 'chain': read.chain, 'movie': read.movie, 'naccess': naccess, "foldx": foldx, 'auto_mutation': auto_mutation, 'remote': read.remote, "cabs_dir": read.cabs_dir, "cabs_config": cabs_config, "n_models": read.n_models, "tmp_dir": tmp_dir, "subprocess": read.subprocess, "ph": read.ph } return options def parse_config_file(filename): parsed = [] option_pattern = re.compile( r'(?P