@@ -45,8 +45,14 @@ def __bool__(self) -> bool:
45
45
return not self .stderr
46
46
47
47
48
- def _exec_cmd (cmd2_app , func : Callable , echo : bool ) -> CommandResult :
49
- """Helper to encapsulate executing a command and capturing the results"""
48
+ def _exec_cmd (cmd2_app , command : str , echo : bool ) -> CommandResult :
49
+ """
50
+ Helper to encapsulate executing a command and capturing the results
51
+ :param cmd2_app: cmd2 app that will run the command
52
+ :param command: command line being run
53
+ :param echo: if True, output will be echoed to stdout/stderr while the command runs
54
+ :return: result of the command
55
+ """
50
56
copy_stdout = StdSim (sys .stdout , echo )
51
57
copy_stderr = StdSim (sys .stderr , echo )
52
58
@@ -58,7 +64,8 @@ def _exec_cmd(cmd2_app, func: Callable, echo: bool) -> CommandResult:
58
64
cmd2_app .stdout = copy_cmd_stdout
59
65
with redirect_stdout (copy_stdout ):
60
66
with redirect_stderr (copy_stderr ):
61
- func ()
67
+ # Include a newline in case it's a multiline command
68
+ cmd2_app .onecmd_plus_hooks (command + '\n ' )
62
69
finally :
63
70
cmd2_app .stdout = copy_cmd_stdout .inner_stream
64
71
@@ -199,28 +206,29 @@ def _run(self):
199
206
self ._command_name ))
200
207
201
208
# reconstruct the cmd2 command from the python call
202
- cmd_str = [ '' ]
209
+ command = self . _command_name
203
210
204
211
def process_argument (action , value ):
212
+ nonlocal command
205
213
if isinstance (action , argparse ._CountAction ):
206
214
if isinstance (value , int ):
207
215
for _ in range (value ):
208
- cmd_str [ 0 ] += '{} ' .format (action .option_strings [0 ])
216
+ command += ' {} ' .format (action .option_strings [0 ])
209
217
return
210
218
else :
211
219
raise TypeError ('Expected int for ' + action .dest )
212
220
if isinstance (action , argparse ._StoreConstAction ) or isinstance (action , argparse ._AppendConstAction ):
213
221
if value :
214
222
# Nothing else to append to the command string, just the flag is enough.
215
- cmd_str [ 0 ] += '{} ' .format (action .option_strings [0 ])
223
+ command += ' {} ' .format (action .option_strings [0 ])
216
224
return
217
225
else :
218
226
# value is not True so we default to false, which means don't include the flag
219
227
return
220
228
221
229
# was the argument a flag?
222
230
if action .option_strings :
223
- cmd_str [ 0 ] += '{} ' .format (action .option_strings [0 ])
231
+ command += ' {} ' .format (action .option_strings [0 ])
224
232
225
233
is_remainder_arg = action .dest == self ._remainder_arg
226
234
@@ -231,33 +239,34 @@ def process_argument(action, value):
231
239
raise ValueError ('{} appears to be a flag and should be supplied as a keyword argument '
232
240
'to the function.' .format (item ))
233
241
item = quote_string_if_needed (item )
234
- cmd_str [ 0 ] += '{} ' .format (item )
242
+ command += ' {} ' .format (item )
235
243
236
244
# If this is a flag parameter that can accept a variable number of arguments and we have not
237
245
# reached the max number, add a list completion suffix to tell argparse to move to the next
238
246
# parameter
239
247
if action .option_strings and isinstance (action , _RangeAction ) and action .nargs_max is not None and \
240
248
action .nargs_max > len (value ):
241
- cmd_str [ 0 ] += '{0}{0} ' .format (self ._parser .prefix_chars [0 ])
249
+ command += ' {0}{0}' .format (self ._parser .prefix_chars [0 ])
242
250
243
251
else :
244
252
value = str (value ).strip ()
245
253
if not is_remainder_arg and is_potential_flag (value , self ._parser ):
246
254
raise ValueError ('{} appears to be a flag and should be supplied as a keyword argument '
247
255
'to the function.' .format (value ))
248
256
value = quote_string_if_needed (value )
249
- cmd_str [ 0 ] += '{} ' .format (value )
257
+ command += ' {} ' .format (value )
250
258
251
259
# If this is a flag parameter that can accept a variable number of arguments and we have not
252
260
# reached the max number, add a list completion suffix to tell argparse to move to the next
253
261
# parameter
254
262
if action .option_strings and isinstance (action , _RangeAction ) and action .nargs_max is not None and \
255
263
action .nargs_max > 1 :
256
- cmd_str [ 0 ] += '{0}{0} ' .format (self ._parser .prefix_chars [0 ])
264
+ command += ' {0}{0}' .format (self ._parser .prefix_chars [0 ])
257
265
258
266
def process_action (action ):
267
+ nonlocal command
259
268
if isinstance (action , argparse ._SubParsersAction ):
260
- cmd_str [ 0 ] += '{} ' .format (self ._args [action .dest ])
269
+ command += ' {} ' .format (self ._args [action .dest ])
261
270
traverse_parser (action .choices [self ._args [action .dest ]])
262
271
elif isinstance (action , argparse ._AppendAction ):
263
272
if isinstance (self ._args [action .dest ], list ) or isinstance (self ._args [action .dest ], tuple ):
@@ -284,8 +293,7 @@ def traverse_parser(parser):
284
293
process_action (action )
285
294
286
295
traverse_parser (self ._parser )
287
-
288
- return _exec_cmd (self ._cmd2_app , functools .partial (func , cmd_str [0 ]), self ._echo )
296
+ return _exec_cmd (self ._cmd2_app , command , self ._echo )
289
297
290
298
291
299
class PyscriptBridge (object ):
@@ -310,7 +318,10 @@ def __getattr__(self, item: str):
310
318
else :
311
319
# Command doesn't use argparse, we will accept parameters in the form of a command string
312
320
def wrap_func (args = '' ):
313
- return _exec_cmd (self ._cmd2_app , functools .partial (func , args ), self .cmd_echo )
321
+ command = item
322
+ if args :
323
+ command += ' ' + args
324
+ return _exec_cmd (self ._cmd2_app , command , self .cmd_echo )
314
325
315
326
return wrap_func
316
327
else :
@@ -323,17 +334,15 @@ def __dir__(self):
323
334
attributes .insert (0 , 'cmd_echo' )
324
335
return attributes
325
336
326
- def __call__ (self , args : str , echo : Optional [bool ]= None ) -> CommandResult :
337
+ def __call__ (self , command : str , echo : Optional [bool ]= None ) -> CommandResult :
327
338
"""
328
339
Provide functionality to call application commands by calling PyscriptBridge
329
340
ex: app('help')
330
- :param args: The string being passed to the command
331
- :param echo: If True, output will be echoed while the command runs
332
- This temporarily overrides the value of self.cmd_echo
341
+ :param command: command line being run
342
+ :param echo: if True, output will be echoed to stdout/stderr while the command runs
343
+ this temporarily overrides the value of self.cmd_echo
333
344
"""
334
345
if echo is None :
335
346
echo = self .cmd_echo
336
347
337
- return _exec_cmd (self ._cmd2_app ,
338
- functools .partial (self ._cmd2_app .onecmd_plus_hooks , args + '\n ' ),
339
- echo )
348
+ return _exec_cmd (self ._cmd2_app , command , echo )
0 commit comments