1
|
|
|
"""Run docopt in GOATOOLS.""" |
2
|
|
|
|
3
|
|
|
from __future__ import print_function |
4
|
|
|
|
5
|
|
|
__copyright__ = "Copyright (C) 2016-2018, DV Klopfenstein, H Tang, All rights reserved." |
6
|
|
|
__author__ = "DV Klopfenstein" |
7
|
|
|
|
8
|
|
|
import sys |
9
|
|
|
import re |
10
|
|
|
from docopt import docopt |
11
|
|
|
from goatools.gosubdag.utils import get_kwargs |
12
|
|
|
|
13
|
|
|
|
14
|
|
|
class DocOptParse(object): |
15
|
|
|
"""Run docopt in GOATOOLS.""" |
16
|
|
|
|
17
|
|
|
def __init__(self, doc, exp_keys, exp_elems): |
18
|
|
|
self.doc = doc |
19
|
|
|
self.exp_keys = exp_keys if exp_keys else set() # Expected dictionary keys |
20
|
|
|
self.exp_elems = exp_elems if exp_elems else set() # Expected set elements (True/False) |
21
|
|
|
|
22
|
|
|
def get_docargs(self, args=None, prt=None, **kws): |
23
|
|
|
"""Pare down docopt. Return a minimal dictionary and a set containing runtime arg values.""" |
24
|
|
|
args_user = sys.argv[1:] if args is None else args |
25
|
|
|
arg_kws = self._get_docargs(args_user, prt) |
26
|
|
|
if 'intvals' in kws: |
27
|
|
|
self._set_intvals(arg_kws, kws['intvals']) |
28
|
|
|
return arg_kws |
29
|
|
|
|
30
|
|
|
def _get_docargs(self, args_user, prt): |
31
|
|
|
"""Pare down docopt. Return a minimal dictionary and a set containing runtime arg values.""" |
32
|
|
|
if prt is not None: |
33
|
|
|
print("DocOptParse BEFORE docopt: {}".format(args_user)) |
34
|
|
|
docargs = docopt(self.doc, args_user) |
35
|
|
|
if prt is not None: |
36
|
|
|
print("DocOptParse AFTER docopt: {}".format(docargs)) |
37
|
|
|
kwargs_doc = {re.sub(r'^-{1,2}', '', k):v for k, v in docargs.items()} |
38
|
|
|
self._chk_docopt_kws(kwargs_doc, args_user) |
39
|
|
|
kwargs_usr = get_kwargs(kwargs_doc, self.exp_keys, self.exp_elems) |
40
|
|
|
if prt is not None: |
41
|
|
|
print("DocOptParse AFTER pared: {}".format(kwargs_usr)) |
42
|
|
|
for key in ['taxid']: |
43
|
|
|
if key in kwargs_usr: |
44
|
|
|
kwargs_usr[key] = int(kwargs_usr[key]) |
45
|
|
|
if prt is not None: |
46
|
|
|
print("DocOptParse AFTER edited/checked: {}".format(kwargs_usr)) |
47
|
|
|
return kwargs_usr |
48
|
|
|
|
49
|
|
|
@staticmethod |
50
|
|
|
def _set_intvals(kws, keys): |
51
|
|
|
"""Convert keyword values to int.""" |
52
|
|
|
for key in keys: |
53
|
|
|
if key in kws: |
54
|
|
|
kws[key] = int(kws[key]) |
55
|
|
|
|
56
|
|
|
def _chk_docopt_exit(self, args, exp_letters): |
57
|
|
|
"""Check if docopt exit was for an unknown argument.""" |
58
|
|
|
if args is None: |
59
|
|
|
args = sys.argv[1:] |
60
|
|
|
keys_all = self.exp_keys.union(self.exp_elems) |
61
|
|
|
if exp_letters: |
62
|
|
|
keys_all |= exp_letters |
63
|
|
|
unknown_args = self._chk_docunknown(args, keys_all) |
64
|
|
|
if unknown_args: |
65
|
|
|
raise RuntimeError("{USAGE}\n **FATAL: UNKNOWN ARGS: {UNK}".format( |
66
|
|
|
USAGE=self.doc, UNK=" ".join(unknown_args))) |
67
|
|
|
|
68
|
|
|
def _chk_docopt_kws(self, docdict, exp): |
69
|
|
|
"""Check for common user errors when running from the command-line.""" |
70
|
|
|
for key, val in docdict.items(): |
71
|
|
|
if isinstance(val, str): |
72
|
|
|
assert '=' not in val, self._err("'=' FOUND IN VALUE", key, val, exp) |
73
|
|
|
elif key != 'help' and key not in self.exp_keys and key not in self.exp_elems: |
74
|
|
|
raise RuntimeError(self._err("UNKNOWN KEY", key, val, exp)) |
75
|
|
|
|
76
|
|
|
def _err(self, msg, key, val, exp): |
77
|
|
|
return "{DOC}\n{MSG}: KEY({K}) VAL({V}): {EXP}".format( |
78
|
|
|
DOC=self.doc, MSG=msg, K=key, V=val, EXP=" ".join(exp)) |
79
|
|
|
|
80
|
|
|
@staticmethod |
81
|
|
|
def _chk_docunknown(args, exp): |
82
|
|
|
"""Return any unknown args.""" |
83
|
|
|
unknown = [] |
84
|
|
|
for arg in args: |
85
|
|
|
if arg[:2] == '--': |
86
|
|
|
val = arg[2:] |
87
|
|
|
if val not in exp: |
88
|
|
|
unknown.append(arg) |
89
|
|
|
elif arg[:1] == '-': |
90
|
|
|
val = arg[1:] |
91
|
|
|
if val not in exp: |
92
|
|
|
unknown.append(arg) |
93
|
|
|
if '-h' in unknown or '--help' in unknown: |
94
|
|
|
return [] |
95
|
|
|
return unknown |
96
|
|
|
|
97
|
|
|
|
98
|
|
|
# Copyright (C) 2016-2018, DV Klopfenstein, H Tang, All rights reserved. |
99
|
|
|
|