cmd2 2.4.2__py3-none-any.whl → 2.5.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cmd2/__init__.py +2 -6
- cmd2/ansi.py +16 -16
- cmd2/argparse_completer.py +1 -10
- cmd2/argparse_custom.py +29 -83
- cmd2/clipboard.py +3 -22
- cmd2/cmd2.py +658 -361
- cmd2/command_definition.py +43 -8
- cmd2/constants.py +3 -0
- cmd2/decorators.py +135 -128
- cmd2/exceptions.py +0 -1
- cmd2/history.py +52 -23
- cmd2/parsing.py +54 -49
- cmd2/plugin.py +8 -6
- cmd2/py_bridge.py +15 -4
- cmd2/rl_utils.py +57 -23
- cmd2/table_creator.py +1 -0
- cmd2/transcript.py +3 -2
- cmd2/utils.py +75 -35
- {cmd2-2.4.2.dist-info → cmd2-2.5.9.dist-info}/LICENSE +1 -1
- cmd2-2.5.9.dist-info/METADATA +218 -0
- cmd2-2.5.9.dist-info/RECORD +24 -0
- {cmd2-2.4.2.dist-info → cmd2-2.5.9.dist-info}/WHEEL +1 -1
- cmd2-2.4.2.dist-info/METADATA +0 -225
- cmd2-2.4.2.dist-info/RECORD +0 -24
- {cmd2-2.4.2.dist-info → cmd2-2.5.9.dist-info}/top_level.txt +0 -0
cmd2/history.py
CHANGED
@@ -8,6 +8,9 @@ import re
|
|
8
8
|
from collections import (
|
9
9
|
OrderedDict,
|
10
10
|
)
|
11
|
+
from dataclasses import (
|
12
|
+
dataclass,
|
13
|
+
)
|
11
14
|
from typing import (
|
12
15
|
Any,
|
13
16
|
Callable,
|
@@ -19,17 +22,54 @@ from typing import (
|
|
19
22
|
overload,
|
20
23
|
)
|
21
24
|
|
22
|
-
import attr
|
23
|
-
|
24
25
|
from . import (
|
25
26
|
utils,
|
26
27
|
)
|
27
28
|
from .parsing import (
|
28
29
|
Statement,
|
30
|
+
shlex_split,
|
29
31
|
)
|
30
32
|
|
31
33
|
|
32
|
-
|
34
|
+
def single_line_format(statement: Statement) -> str:
|
35
|
+
"""
|
36
|
+
Format a command line to display on a single line.
|
37
|
+
|
38
|
+
Spaces and newlines in quotes are preserved so those strings will span multiple lines.
|
39
|
+
|
40
|
+
:param statement: Statement being formatted.
|
41
|
+
:return: formatted command line
|
42
|
+
"""
|
43
|
+
if not statement.raw:
|
44
|
+
return ""
|
45
|
+
|
46
|
+
lines = statement.raw.splitlines()
|
47
|
+
formatted_command = lines[0]
|
48
|
+
|
49
|
+
# Append any remaining lines to the command.
|
50
|
+
for line in lines[1:]:
|
51
|
+
try:
|
52
|
+
shlex_split(formatted_command)
|
53
|
+
except ValueError:
|
54
|
+
# We are in quotes, so restore the newline.
|
55
|
+
separator = "\n"
|
56
|
+
else:
|
57
|
+
# Don't add a space before line if one already exists or if it begins with the terminator.
|
58
|
+
if (
|
59
|
+
formatted_command.endswith(" ")
|
60
|
+
or line.startswith(" ")
|
61
|
+
or (statement.terminator and line.startswith(statement.terminator))
|
62
|
+
):
|
63
|
+
separator = ""
|
64
|
+
else:
|
65
|
+
separator = " "
|
66
|
+
|
67
|
+
formatted_command += separator + line
|
68
|
+
|
69
|
+
return formatted_command
|
70
|
+
|
71
|
+
|
72
|
+
@dataclass(frozen=True)
|
33
73
|
class HistoryItem:
|
34
74
|
"""Class used to represent one command in the history list"""
|
35
75
|
|
@@ -39,10 +79,10 @@ class HistoryItem:
|
|
39
79
|
# Used in JSON dictionaries
|
40
80
|
_statement_field = 'statement'
|
41
81
|
|
42
|
-
statement: Statement
|
82
|
+
statement: Statement
|
43
83
|
|
44
84
|
def __str__(self) -> str:
|
45
|
-
"""A convenient human
|
85
|
+
"""A convenient human-readable representation of the history item"""
|
46
86
|
return self.statement.raw
|
47
87
|
|
48
88
|
@property
|
@@ -84,15 +124,7 @@ class HistoryItem:
|
|
84
124
|
if expanded:
|
85
125
|
ret_str = self.expanded
|
86
126
|
else:
|
87
|
-
ret_str = self.
|
88
|
-
|
89
|
-
# In non-verbose mode, display raw multiline commands on 1 line
|
90
|
-
if self.statement.multiline_command:
|
91
|
-
# This is an approximation and not meant to be a perfect piecing together of lines.
|
92
|
-
# All newlines will be converted to spaces, including the ones in quoted strings that
|
93
|
-
# are considered literals. Also if the final line starts with a terminator, then the
|
94
|
-
# terminator will have an extra space before it in the 1 line version.
|
95
|
-
ret_str = ret_str.replace('\n', ' ')
|
127
|
+
ret_str = single_line_format(self.statement).rstrip()
|
96
128
|
|
97
129
|
# Display a numbered list if not writing to a script
|
98
130
|
if not script:
|
@@ -118,13 +150,13 @@ class HistoryItem:
|
|
118
150
|
|
119
151
|
|
120
152
|
class History(List[HistoryItem]):
|
121
|
-
"""A list of
|
153
|
+
"""A list of [HistoryItem][cmd2.history.HistoryItem] objects with additional methods
|
122
154
|
for searching and managing the list.
|
123
155
|
|
124
|
-
|
156
|
+
[cmd2.Cmd][] instantiates this class into the `cmd2.Cmd.history`
|
125
157
|
attribute, and adds commands to it as a user enters them.
|
126
158
|
|
127
|
-
See
|
159
|
+
See [History](../features/history.md) for information about the built-in command
|
128
160
|
which allows users to view, search, run, and save previously entered commands.
|
129
161
|
|
130
162
|
Developers interested in accessing previously entered commands can use this
|
@@ -144,7 +176,6 @@ class History(List[HistoryItem]):
|
|
144
176
|
"""Start a new session, thereby setting the next index as the first index in the new session."""
|
145
177
|
self.session_start_index = len(self)
|
146
178
|
|
147
|
-
# noinspection PyMethodMayBeStatic
|
148
179
|
def _zero_based_index(self, onebased: Union[int, str]) -> int:
|
149
180
|
"""Convert a one-based index to a zero-based index."""
|
150
181
|
result = int(onebased)
|
@@ -153,12 +184,10 @@ class History(List[HistoryItem]):
|
|
153
184
|
return result
|
154
185
|
|
155
186
|
@overload
|
156
|
-
def append(self, new: HistoryItem) -> None:
|
157
|
-
... # pragma: no cover
|
187
|
+
def append(self, new: HistoryItem) -> None: ... # pragma: no cover
|
158
188
|
|
159
189
|
@overload
|
160
|
-
def append(self, new: Statement) -> None:
|
161
|
-
... # pragma: no cover
|
190
|
+
def append(self, new: Statement) -> None: ... # pragma: no cover
|
162
191
|
|
163
192
|
def append(self, new: Union[Statement, HistoryItem]) -> None:
|
164
193
|
"""Append a new statement to the end of the History list.
|
@@ -178,7 +207,7 @@ class History(List[HistoryItem]):
|
|
178
207
|
"""Get item from the History list using 1-based indexing.
|
179
208
|
|
180
209
|
:param index: optional item to get
|
181
|
-
:return: a single
|
210
|
+
:return: a single [cmd2.history.HistoryItem][]
|
182
211
|
"""
|
183
212
|
if index == 0:
|
184
213
|
raise IndexError('The first command in history is command 1.')
|
cmd2/parsing.py
CHANGED
@@ -4,6 +4,10 @@
|
|
4
4
|
|
5
5
|
import re
|
6
6
|
import shlex
|
7
|
+
from dataclasses import (
|
8
|
+
dataclass,
|
9
|
+
field,
|
10
|
+
)
|
7
11
|
from typing import (
|
8
12
|
Any,
|
9
13
|
Dict,
|
@@ -14,8 +18,6 @@ from typing import (
|
|
14
18
|
Union,
|
15
19
|
)
|
16
20
|
|
17
|
-
import attr
|
18
|
-
|
19
21
|
from . import (
|
20
22
|
constants,
|
21
23
|
utils,
|
@@ -36,7 +38,7 @@ def shlex_split(str_to_split: str) -> List[str]:
|
|
36
38
|
return shlex.split(str_to_split, comments=False, posix=False)
|
37
39
|
|
38
40
|
|
39
|
-
@
|
41
|
+
@dataclass(frozen=True)
|
40
42
|
class MacroArg:
|
41
43
|
"""
|
42
44
|
Information used to replace or unescape arguments in a macro value when the macro is resolved
|
@@ -45,15 +47,15 @@ class MacroArg:
|
|
45
47
|
"""
|
46
48
|
|
47
49
|
# The starting index of this argument in the macro value
|
48
|
-
start_index: int
|
50
|
+
start_index: int
|
49
51
|
|
50
52
|
# The number string that appears between the braces
|
51
53
|
# This is a string instead of an int because we support unicode digits and must be able
|
52
54
|
# to reproduce this string later
|
53
|
-
number_str: str
|
55
|
+
number_str: str
|
54
56
|
|
55
57
|
# Tells if this argument is escaped and therefore needs to be unescaped
|
56
|
-
is_escaped: bool
|
58
|
+
is_escaped: bool
|
57
59
|
|
58
60
|
# Pattern used to find normal argument
|
59
61
|
# Digits surrounded by exactly 1 brace on a side and 1 or more braces on the opposite side
|
@@ -69,24 +71,24 @@ class MacroArg:
|
|
69
71
|
digit_pattern = re.compile(r'\d+')
|
70
72
|
|
71
73
|
|
72
|
-
@
|
74
|
+
@dataclass(frozen=True)
|
73
75
|
class Macro:
|
74
76
|
"""Defines a cmd2 macro"""
|
75
77
|
|
76
78
|
# Name of the macro
|
77
|
-
name: str
|
79
|
+
name: str
|
78
80
|
|
79
81
|
# The string the macro resolves to
|
80
|
-
value: str
|
82
|
+
value: str
|
81
83
|
|
82
84
|
# The minimum number of args the user has to pass to this macro
|
83
|
-
minimum_arg_count: int
|
85
|
+
minimum_arg_count: int
|
84
86
|
|
85
87
|
# Used to fill in argument placeholders in the macro
|
86
|
-
arg_list: List[MacroArg] =
|
88
|
+
arg_list: List[MacroArg] = field(default_factory=list)
|
87
89
|
|
88
90
|
|
89
|
-
@
|
91
|
+
@dataclass(frozen=True)
|
90
92
|
class Statement(str): # type: ignore[override]
|
91
93
|
"""String subclass with additional attributes to store the results of parsing.
|
92
94
|
|
@@ -96,7 +98,7 @@ class Statement(str): # type: ignore[override]
|
|
96
98
|
we add our own attributes to this subclass.
|
97
99
|
|
98
100
|
Instances of this class should not be created by anything other than the
|
99
|
-
|
101
|
+
[StatementParser.parse][cmd2.parsing.StatementParser.parse] method, nor should any of the
|
100
102
|
attributes be modified once the object is created.
|
101
103
|
|
102
104
|
The string portion of the class contains the arguments, but not the
|
@@ -106,46 +108,46 @@ class Statement(str): # type: ignore[override]
|
|
106
108
|
|
107
109
|
1. `argparse <https://docs.python.org/3/library/argparse.html>`_ is your
|
108
110
|
friend for anything complex. ``cmd2`` has the decorator
|
109
|
-
(
|
111
|
+
([cmd2.decorators.with_argparser][]) which you can
|
110
112
|
use to make your command method receive a namespace of parsed arguments,
|
111
113
|
whether positional or denoted with switches.
|
112
114
|
|
113
115
|
2. For commands with simple positional arguments, use
|
114
|
-
|
116
|
+
[args][cmd2.Statement.args] or [arg_list][cmd2.Statement.arg_list]
|
115
117
|
|
116
118
|
3. If you don't want to have to worry about quoted arguments, see
|
117
|
-
|
119
|
+
[argv][cmd2.Statement.argv] for a trick which strips quotes off for you.
|
118
120
|
"""
|
119
121
|
|
120
122
|
# the arguments, but not the command, nor the output redirection clauses.
|
121
|
-
args: str =
|
123
|
+
args: str = ''
|
122
124
|
|
123
125
|
# string containing exactly what we input by the user
|
124
|
-
raw: str =
|
126
|
+
raw: str = ''
|
125
127
|
|
126
128
|
# the command, i.e. the first whitespace delimited word
|
127
|
-
command: str =
|
129
|
+
command: str = ''
|
128
130
|
|
129
131
|
# list of arguments to the command, not including any output redirection or terminators; quoted args remain quoted
|
130
|
-
arg_list: List[str] =
|
132
|
+
arg_list: List[str] = field(default_factory=list)
|
131
133
|
|
132
134
|
# if the command is a multiline command, the name of the command, otherwise empty
|
133
|
-
multiline_command: str =
|
135
|
+
multiline_command: str = ''
|
134
136
|
|
135
137
|
# the character which terminated the multiline command, if there was one
|
136
|
-
terminator: str =
|
138
|
+
terminator: str = ''
|
137
139
|
|
138
140
|
# characters appearing after the terminator but before output redirection, if any
|
139
|
-
suffix: str =
|
141
|
+
suffix: str = ''
|
140
142
|
|
141
143
|
# if output was piped to a shell command, the shell command as a string
|
142
|
-
pipe_to: str =
|
144
|
+
pipe_to: str = ''
|
143
145
|
|
144
146
|
# if output was redirected, the redirection token, i.e. '>>'
|
145
|
-
output: str =
|
147
|
+
output: str = ''
|
146
148
|
|
147
149
|
# if output was redirected, the destination file token (quotes preserved)
|
148
|
-
output_to: str =
|
150
|
+
output_to: str = ''
|
149
151
|
|
150
152
|
# Used in JSON dictionaries
|
151
153
|
_args_field = 'args'
|
@@ -156,7 +158,7 @@ class Statement(str): # type: ignore[override]
|
|
156
158
|
We must override __new__ because we are subclassing `str` which is
|
157
159
|
immutable and takes a different number of arguments as Statement.
|
158
160
|
|
159
|
-
NOTE:
|
161
|
+
NOTE: @dataclass takes care of initializing other members in the __init__ it
|
160
162
|
generates.
|
161
163
|
"""
|
162
164
|
stmt = super().__new__(cls, value)
|
@@ -200,8 +202,7 @@ class Statement(str): # type: ignore[override]
|
|
200
202
|
|
201
203
|
@property
|
202
204
|
def expanded_command_line(self) -> str:
|
203
|
-
"""Concatenate
|
204
|
-
and :meth:`~cmd2.Statement.post_command`"""
|
205
|
+
"""Concatenate [command_and_args][cmd2.Statement.command_and_args] and [post_command][cmd2.Statement.post_command]"""
|
205
206
|
return self.command_and_args + self.post_command
|
206
207
|
|
207
208
|
@property
|
@@ -348,7 +349,7 @@ class StatementParser:
|
|
348
349
|
return False, 'cannot start with the comment character'
|
349
350
|
|
350
351
|
if not is_subcommand:
|
351
|
-
for
|
352
|
+
for shortcut, _ in self.shortcuts:
|
352
353
|
if word.startswith(shortcut):
|
353
354
|
# Build an error string with all shortcuts listed
|
354
355
|
errmsg = 'cannot start with a shortcut: '
|
@@ -397,12 +398,12 @@ class StatementParser:
|
|
397
398
|
|
398
399
|
def parse(self, line: str) -> Statement:
|
399
400
|
"""
|
400
|
-
Tokenize the input and parse it into a
|
401
|
+
Tokenize the input and parse it into a [cmd2.parsing.Statement][] object,
|
401
402
|
stripping comments, expanding aliases and shortcuts, and extracting output
|
402
403
|
redirection directives.
|
403
404
|
|
404
405
|
:param line: the command line being parsed
|
405
|
-
:return: a new
|
406
|
+
:return: a new [cmd2.parsing.Statement][] object
|
406
407
|
:raises: Cmd2ShlexError if a shlex error occurs (e.g. No closing quotation)
|
407
408
|
"""
|
408
409
|
|
@@ -481,7 +482,6 @@ class StatementParser:
|
|
481
482
|
|
482
483
|
# Check if output should be piped to a shell command
|
483
484
|
if pipe_index < redir_index and pipe_index < append_index:
|
484
|
-
|
485
485
|
# Get the tokens for the pipe command and expand ~ where needed
|
486
486
|
pipe_to_tokens = tokens[pipe_index + 1 :]
|
487
487
|
utils.expand_user_in_tokens(pipe_to_tokens)
|
@@ -543,7 +543,7 @@ class StatementParser:
|
|
543
543
|
return statement
|
544
544
|
|
545
545
|
def parse_command_only(self, rawinput: str) -> Statement:
|
546
|
-
"""Partially parse input into a
|
546
|
+
"""Partially parse input into a [cmd2.Statement][] object.
|
547
547
|
|
548
548
|
The command is identified, and shortcuts and aliases are expanded.
|
549
549
|
Multiline commands are identified, but terminators and output
|
@@ -552,21 +552,21 @@ class StatementParser:
|
|
552
552
|
This method is used by tab completion code and therefore must not
|
553
553
|
generate an exception if there are unclosed quotes.
|
554
554
|
|
555
|
-
The
|
555
|
+
The [cmd2.parsing.Statement][] object returned by this method can at most
|
556
556
|
contain values in the following attributes:
|
557
|
-
|
558
|
-
|
559
|
-
|
557
|
+
[cmd2.parsing.Statement.args][], [cmd2.parsing.Statement.raw][],
|
558
|
+
[cmd2.parsing.Statement.command][],
|
559
|
+
[cmd2.parsing.Statement.multiline_command][]
|
560
560
|
|
561
|
-
|
561
|
+
[cmd2.parsing.Statement.args][] will include all output redirection
|
562
562
|
clauses and command terminators.
|
563
563
|
|
564
|
-
Different from
|
564
|
+
Different from [cmd2.parsing.StatementParser.parse][] this method
|
565
565
|
does not remove redundant whitespace within args. However, it does
|
566
566
|
ensure args has no leading or trailing whitespace.
|
567
567
|
|
568
568
|
:param rawinput: the command line as entered by the user
|
569
|
-
:return: a new
|
569
|
+
:return: a new [cmd2.Statement][] object
|
570
570
|
"""
|
571
571
|
# expand shortcuts and aliases
|
572
572
|
line = self._expand(rawinput)
|
@@ -580,8 +580,15 @@ class StatementParser:
|
|
580
580
|
|
581
581
|
# take everything from the end of the first match group to
|
582
582
|
# the end of the line as the arguments (stripping leading
|
583
|
-
# and trailing
|
584
|
-
args = line[match.end(1) :].
|
583
|
+
# and unquoted trailing whitespace)
|
584
|
+
args = line[match.end(1) :].lstrip()
|
585
|
+
try:
|
586
|
+
shlex_split(args)
|
587
|
+
except ValueError:
|
588
|
+
# Unclosed quote. Leave trailing whitespace.
|
589
|
+
pass
|
590
|
+
else:
|
591
|
+
args = args.rstrip()
|
585
592
|
# if the command is empty that means the input was either empty
|
586
593
|
# or something weird like '>'. args should be empty if we couldn't
|
587
594
|
# parse a command
|
@@ -609,18 +616,18 @@ class StatementParser:
|
|
609
616
|
:param command_name: name of the command being run
|
610
617
|
:param to_parse: what is being passed to the ``do_*`` method. It can be one of two types:
|
611
618
|
|
612
|
-
1. An already parsed
|
619
|
+
1. An already parsed [cmd2.Statement][]
|
613
620
|
2. An argument string in cases where a ``do_*`` method is
|
614
621
|
explicitly called. Calling ``do_help('alias create')`` would
|
615
622
|
cause ``to_parse`` to be 'alias create'.
|
616
623
|
|
617
624
|
In this case, the string will be converted to a
|
618
|
-
|
625
|
+
[cmd2.Statement][] and returned along with
|
619
626
|
the argument list.
|
620
627
|
|
621
628
|
:param preserve_quotes: if ``True``, then quotes will not be stripped from
|
622
629
|
the arguments
|
623
|
-
:return: A tuple containing the
|
630
|
+
:return: A tuple containing the [cmd2.Statement][] and a list of
|
624
631
|
strings representing the arguments
|
625
632
|
"""
|
626
633
|
# Check if to_parse needs to be converted to a Statement
|
@@ -656,7 +663,7 @@ class StatementParser:
|
|
656
663
|
keep_expanding = bool(remaining_aliases)
|
657
664
|
|
658
665
|
# expand shortcuts
|
659
|
-
for
|
666
|
+
for shortcut, expansion in self.shortcuts:
|
660
667
|
if line.startswith(shortcut):
|
661
668
|
# If the next character after the shortcut isn't a space, then insert one
|
662
669
|
shortcut_len = len(shortcut)
|
@@ -701,7 +708,6 @@ class StatementParser:
|
|
701
708
|
punctuated_tokens = []
|
702
709
|
|
703
710
|
for cur_initial_token in tokens:
|
704
|
-
|
705
711
|
# Save tokens up to 1 character in length or quoted tokens. No need to parse these.
|
706
712
|
if len(cur_initial_token) <= 1 or cur_initial_token[0] in constants.QUOTES:
|
707
713
|
punctuated_tokens.append(cur_initial_token)
|
@@ -716,7 +722,6 @@ class StatementParser:
|
|
716
722
|
|
717
723
|
while True:
|
718
724
|
if cur_char not in punctuation:
|
719
|
-
|
720
725
|
# Keep appending to new_token until we hit a punctuation char
|
721
726
|
while cur_char not in punctuation:
|
722
727
|
new_token += cur_char
|
cmd2/plugin.py
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
#
|
2
2
|
# coding=utf-8
|
3
3
|
"""Classes for the cmd2 plugin system"""
|
4
|
+
|
5
|
+
from dataclasses import (
|
6
|
+
dataclass,
|
7
|
+
)
|
4
8
|
from typing import (
|
5
9
|
Optional,
|
6
10
|
)
|
7
11
|
|
8
|
-
import attr
|
9
|
-
|
10
12
|
from .parsing import (
|
11
13
|
Statement,
|
12
14
|
)
|
13
15
|
|
14
16
|
|
15
|
-
@
|
17
|
+
@dataclass
|
16
18
|
class PostparsingData:
|
17
19
|
"""Data class containing information passed to postparsing hook methods"""
|
18
20
|
|
@@ -20,14 +22,14 @@ class PostparsingData:
|
|
20
22
|
statement: Statement
|
21
23
|
|
22
24
|
|
23
|
-
@
|
25
|
+
@dataclass
|
24
26
|
class PrecommandData:
|
25
27
|
"""Data class containing information passed to precommand hook methods"""
|
26
28
|
|
27
29
|
statement: Statement
|
28
30
|
|
29
31
|
|
30
|
-
@
|
32
|
+
@dataclass
|
31
33
|
class PostcommandData:
|
32
34
|
"""Data class containing information passed to postcommand hook methods"""
|
33
35
|
|
@@ -35,7 +37,7 @@ class PostcommandData:
|
|
35
37
|
statement: Statement
|
36
38
|
|
37
39
|
|
38
|
-
@
|
40
|
+
@dataclass
|
39
41
|
class CommandFinalizationData:
|
40
42
|
"""Data class containing information passed to command finalization hook methods"""
|
41
43
|
|
cmd2/py_bridge.py
CHANGED
@@ -57,7 +57,7 @@ class CommandResult(NamedTuple):
|
|
57
57
|
if isinstance(sys.stderr, StdSim):
|
58
58
|
sys.stderr.pause_storage = True
|
59
59
|
|
60
|
-
See
|
60
|
+
See [cmd2.utils.StdSim][] for more information.
|
61
61
|
|
62
62
|
.. note::
|
63
63
|
|
@@ -83,10 +83,17 @@ class CommandResult(NamedTuple):
|
|
83
83
|
|
84
84
|
|
85
85
|
class PyBridge:
|
86
|
-
"""
|
86
|
+
"""
|
87
|
+
Provides a Python API wrapper for application commands.
|
88
|
+
|
89
|
+
:param cmd2_app: app being controlled by this PyBridge.
|
90
|
+
:param add_to_history: If True, then add all commands run by this PyBridge to history.
|
91
|
+
Defaults to True.
|
92
|
+
"""
|
87
93
|
|
88
|
-
def __init__(self, cmd2_app: 'cmd2.Cmd') -> None:
|
94
|
+
def __init__(self, cmd2_app: 'cmd2.Cmd', *, add_to_history: bool = True) -> None:
|
89
95
|
self._cmd2_app = cmd2_app
|
96
|
+
self._add_to_history = add_to_history
|
90
97
|
self.cmd_echo = False
|
91
98
|
|
92
99
|
# Tells if any of the commands run via __call__ returned True for stop
|
@@ -126,7 +133,11 @@ class PyBridge:
|
|
126
133
|
self._cmd2_app.stdout = cast(TextIO, copy_cmd_stdout)
|
127
134
|
with redirect_stdout(cast(IO[str], copy_cmd_stdout)):
|
128
135
|
with redirect_stderr(cast(IO[str], copy_stderr)):
|
129
|
-
stop = self._cmd2_app.onecmd_plus_hooks(
|
136
|
+
stop = self._cmd2_app.onecmd_plus_hooks(
|
137
|
+
command,
|
138
|
+
add_to_history=self._add_to_history,
|
139
|
+
py_bridge_call=True,
|
140
|
+
)
|
130
141
|
finally:
|
131
142
|
with self._cmd2_app.sigint_protection:
|
132
143
|
self._cmd2_app.stdout = cast(IO[str], copy_cmd_stdout.inner_stream)
|