1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
"""Bridges calls made inside of pyscript with the Cmd2 host app while maintaining a reasonable
degree of isolation between the two"""
import argparse
class ArgparseFunctor:
def __init__(self, cmd2_app, item, parser):
self._cmd2_app = cmd2_app
self._item = item
self._parser = parser
self._args = {}
self.__current_subcommand_parser = parser
def __getattr__(self, item):
# look for sub-command
for action in self.__current_subcommand_parser._actions:
if not action.option_strings and isinstance(action, argparse._SubParsersAction):
if item in action.choices:
# item matches the a sub-command, save our position in argparse,
# save the sub-command, return self to allow next level of traversal
self.__current_subcommand_parser = action.choices[item]
self._args[action.dest] = item
return self
return super().__getatttr__(item)
def __call__(self, *args, **kwargs):
next_pos_index = 0
has_subcommand = False
consumed_kw = []
for action in self.__current_subcommand_parser._actions:
# is this a flag option?
if action.option_strings:
if action.dest in kwargs:
self._args[action.dest] = kwargs[action.dest]
consumed_kw.append(action.dest)
else:
if not isinstance(action, argparse._SubParsersAction):
if next_pos_index < len(args):
self._args[action.dest] = args[next_pos_index]
next_pos_index += 1
else:
has_subcommand = True
for kw in kwargs:
if kw not in consumed_kw:
raise TypeError('{}() got an unexpected keyword argument \'{}\''.format(
self.__current_subcommand_parser.prog, kw))
if has_subcommand:
return self
else:
return self._run()
def _run(self):
# look up command function
func = getattr(self._cmd2_app, 'do_' + self._item)
# reconstruct the cmd2 command from the python call
cmd_str = ['']
def traverse_parser(parser):
for action in parser._actions:
# was something provided for the argument
if action.dest in self._args:
if isinstance(action, argparse._SubParsersAction):
traverse_parser(action.choices[self._args[action.dest]])
else:
# was the argument a flag?
if action.option_strings:
cmd_str[0] += '{} '.format(action.option_strings[0])
# TODO: Handle 'narg' and 'append' options
cmd_str[0] += '"{}" '.format(self._args[action.dest])
traverse_parser(self._parser)
func(cmd_str[0])
return self._cmd2_app._last_result
class PyscriptBridge(object):
def __init__(self, cmd2_app):
self._cmd2_app = cmd2_app
self._last_result = None
def __getattr__(self, item: str):
commands = self._cmd2_app.get_all_commands()
if item in commands:
func = getattr(self._cmd2_app, 'do_' + item)
try:
parser = getattr(func, 'argparser')
except AttributeError:
def wrap_func(args=''):
func(args)
return self._cmd2_app._last_result
return wrap_func
else:
return ArgparseFunctor(self._cmd2_app, item, parser)
return super().__getattr__(item)
def __call__(self, args):
self._cmd2_app.onecmd_plus_hooks(args + '\n')
self._last_result = self._cmd2_app._last_result
return self._cmd2_app._last_result
|