cmd2 2.4.3__py3-none-any.whl → 2.5.1__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 -13
- cmd2/argparse_completer.py +1 -10
- cmd2/argparse_custom.py +12 -53
- cmd2/clipboard.py +3 -22
- cmd2/cmd2.py +543 -236
- cmd2/command_definition.py +10 -0
- cmd2/decorators.py +90 -64
- cmd2/exceptions.py +0 -1
- cmd2/history.py +48 -19
- cmd2/parsing.py +36 -30
- cmd2/plugin.py +8 -6
- cmd2/py_bridge.py +14 -3
- cmd2/rl_utils.py +57 -23
- cmd2/table_creator.py +1 -0
- cmd2/transcript.py +3 -2
- cmd2/utils.py +39 -5
- {cmd2-2.4.3.dist-info → cmd2-2.5.1.dist-info}/LICENSE +1 -1
- {cmd2-2.4.3.dist-info → cmd2-2.5.1.dist-info}/METADATA +29 -27
- cmd2-2.5.1.dist-info/RECORD +24 -0
- {cmd2-2.4.3.dist-info → cmd2-2.5.1.dist-info}/WHEEL +1 -1
- cmd2-2.4.3.dist-info/RECORD +0 -24
- {cmd2-2.4.3.dist-info → cmd2-2.5.1.dist-info}/top_level.txt +0 -0
cmd2/__init__.py
CHANGED
@@ -5,12 +5,8 @@
|
|
5
5
|
|
6
6
|
import sys
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
import importlib.metadata as importlib_metadata
|
11
|
-
else:
|
12
|
-
# For everyone else
|
13
|
-
import importlib_metadata
|
8
|
+
import importlib.metadata as importlib_metadata
|
9
|
+
|
14
10
|
try:
|
15
11
|
__version__ = importlib_metadata.version(__name__)
|
16
12
|
except importlib_metadata.PackageNotFoundError: # pragma: no cover
|
cmd2/ansi.py
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
"""
|
3
3
|
Support for ANSI escape sequences which are used for things like applying style to text,
|
4
4
|
setting the window title, and asynchronous alerts.
|
5
|
-
|
5
|
+
"""
|
6
|
+
|
6
7
|
import functools
|
7
8
|
import re
|
8
9
|
from enum import (
|
@@ -62,25 +63,25 @@ The default is ``AllowStyle.TERMINAL``.
|
|
62
63
|
"""
|
63
64
|
|
64
65
|
# Regular expression to match ANSI style sequence
|
65
|
-
ANSI_STYLE_RE = re.compile(
|
66
|
+
ANSI_STYLE_RE = re.compile(rf'{ESC}\[[^m]*m')
|
66
67
|
|
67
68
|
# Matches standard foreground colors: CSI(30-37|90-97|39)m
|
68
|
-
STD_FG_RE = re.compile(
|
69
|
+
STD_FG_RE = re.compile(rf'{ESC}\[(?:[39][0-7]|39)m')
|
69
70
|
|
70
71
|
# Matches standard background colors: CSI(40-47|100-107|49)m
|
71
|
-
STD_BG_RE = re.compile(
|
72
|
+
STD_BG_RE = re.compile(rf'{ESC}\[(?:(?:4|10)[0-7]|49)m')
|
72
73
|
|
73
74
|
# Matches eight-bit foreground colors: CSI38;5;(0-255)m
|
74
|
-
EIGHT_BIT_FG_RE = re.compile(
|
75
|
+
EIGHT_BIT_FG_RE = re.compile(rf'{ESC}\[38;5;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])m')
|
75
76
|
|
76
77
|
# Matches eight-bit background colors: CSI48;5;(0-255)m
|
77
|
-
EIGHT_BIT_BG_RE = re.compile(
|
78
|
+
EIGHT_BIT_BG_RE = re.compile(rf'{ESC}\[48;5;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])m')
|
78
79
|
|
79
80
|
# Matches RGB foreground colors: CSI38;2;(0-255);(0-255);(0-255)m
|
80
|
-
RGB_FG_RE = re.compile(
|
81
|
+
RGB_FG_RE = re.compile(rf'{ESC}\[38;2(?:;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])){{3}}m')
|
81
82
|
|
82
83
|
# Matches RGB background colors: CSI48;2;(0-255);(0-255);(0-255)m
|
83
|
-
RGB_BG_RE = re.compile(
|
84
|
+
RGB_BG_RE = re.compile(rf'{ESC}\[48;2(?:;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])){{3}}m')
|
84
85
|
|
85
86
|
|
86
87
|
def strip_style(text: str) -> str:
|
@@ -224,7 +225,6 @@ class BgColor(AnsiSequence):
|
|
224
225
|
####################################################################################
|
225
226
|
# Implementations intended for direct use
|
226
227
|
####################################################################################
|
227
|
-
# noinspection PyPep8Naming
|
228
228
|
class Cursor:
|
229
229
|
"""Create ANSI sequences to alter the cursor position"""
|
230
230
|
|
@@ -1042,6 +1042,9 @@ def style(
|
|
1042
1042
|
# Default styles for printing strings of various types.
|
1043
1043
|
# These can be altered to suit an application's needs and only need to be a
|
1044
1044
|
# function with the following structure: func(str) -> str
|
1045
|
+
style_output = functools.partial(style)
|
1046
|
+
"""Partial function supplying arguments to :meth:`cmd2.ansi.style()` which colors text for normal output"""
|
1047
|
+
|
1045
1048
|
style_success = functools.partial(style, fg=Fg.GREEN)
|
1046
1049
|
"""Partial function supplying arguments to :meth:`cmd2.ansi.style()` which colors text to signify success"""
|
1047
1050
|
|
@@ -1056,7 +1059,7 @@ def async_alert_str(*, terminal_columns: int, prompt: str, line: str, cursor_off
|
|
1056
1059
|
"""Calculate the desired string, including ANSI escape codes, for displaying an asynchronous alert message.
|
1057
1060
|
|
1058
1061
|
:param terminal_columns: terminal width (number of columns)
|
1059
|
-
:param prompt:
|
1062
|
+
:param prompt: current onscreen prompt
|
1060
1063
|
:param line: current contents of the Readline line buffer
|
1061
1064
|
:param cursor_offset: the offset of the current cursor position within line
|
1062
1065
|
:param alert_msg: the message to display to the user
|
@@ -1069,9 +1072,9 @@ def async_alert_str(*, terminal_columns: int, prompt: str, line: str, cursor_off
|
|
1069
1072
|
# Calculate how many terminal lines are taken up by all prompt lines except for the last one.
|
1070
1073
|
# That will be included in the input lines calculations since that is where the cursor is.
|
1071
1074
|
num_prompt_terminal_lines = 0
|
1072
|
-
for
|
1073
|
-
|
1074
|
-
num_prompt_terminal_lines += int(
|
1075
|
+
for prompt_line in prompt_lines[:-1]:
|
1076
|
+
prompt_line_width = style_aware_wcswidth(prompt_line)
|
1077
|
+
num_prompt_terminal_lines += int(prompt_line_width / terminal_columns) + 1
|
1075
1078
|
|
1076
1079
|
# Now calculate how many terminal lines are take up by the input
|
1077
1080
|
last_prompt_line = prompt_lines[-1]
|
cmd2/argparse_completer.py
CHANGED
@@ -61,7 +61,6 @@ DEFAULT_DESCRIPTIVE_HEADER = 'Description'
|
|
61
61
|
ARG_TOKENS = 'arg_tokens'
|
62
62
|
|
63
63
|
|
64
|
-
# noinspection PyProtectedMember
|
65
64
|
def _build_hint(parser: argparse.ArgumentParser, arg_action: argparse.Action) -> str:
|
66
65
|
"""Build tab completion hint for a given argument"""
|
67
66
|
# Check if hinting is disabled for this argument
|
@@ -82,7 +81,6 @@ def _single_prefix_char(token: str, parser: argparse.ArgumentParser) -> bool:
|
|
82
81
|
return len(token) == 1 and token[0] in parser.prefix_chars
|
83
82
|
|
84
83
|
|
85
|
-
# noinspection PyProtectedMember
|
86
84
|
def _looks_like_flag(token: str, parser: argparse.ArgumentParser) -> bool:
|
87
85
|
"""
|
88
86
|
Determine if a token looks like a flag. Unless an argument has nargs set to argparse.REMAINDER,
|
@@ -94,7 +92,7 @@ def _looks_like_flag(token: str, parser: argparse.ArgumentParser) -> bool:
|
|
94
92
|
return False
|
95
93
|
|
96
94
|
# Flags have to start with a prefix character
|
97
|
-
if
|
95
|
+
if token[0] not in parser.prefix_chars:
|
98
96
|
return False
|
99
97
|
|
100
98
|
# If it looks like a negative number, it is not a flag unless there are negative-number-like flags
|
@@ -144,7 +142,6 @@ class _ArgumentState:
|
|
144
142
|
self.max = self.action.nargs
|
145
143
|
|
146
144
|
|
147
|
-
# noinspection PyProtectedMember
|
148
145
|
class _UnfinishedFlagError(CompletionError):
|
149
146
|
def __init__(self, flag_arg_state: _ArgumentState) -> None:
|
150
147
|
"""
|
@@ -171,7 +168,6 @@ class _NoResultsError(CompletionError):
|
|
171
168
|
super().__init__(_build_hint(parser, arg_action), apply_style=False)
|
172
169
|
|
173
170
|
|
174
|
-
# noinspection PyProtectedMember
|
175
171
|
class ArgparseCompleter:
|
176
172
|
"""Automatic command line tab completion based on argparse parameters"""
|
177
173
|
|
@@ -273,10 +269,8 @@ class ArgparseCompleter:
|
|
273
269
|
# Check if this action is in a mutually exclusive group
|
274
270
|
for group in self._parser._mutually_exclusive_groups:
|
275
271
|
if arg_action in group._group_actions:
|
276
|
-
|
277
272
|
# Check if the group this action belongs to has already been completed
|
278
273
|
if group in completed_mutex_groups:
|
279
|
-
|
280
274
|
# If this is the action that completed the group, then there is no error
|
281
275
|
# since it's allowed to appear on the command line more than once.
|
282
276
|
completer_action = completed_mutex_groups[group]
|
@@ -307,7 +301,6 @@ class ArgparseCompleter:
|
|
307
301
|
# Parse all but the last token
|
308
302
|
#############################################################################################
|
309
303
|
for token_index, token in enumerate(tokens[:-1]):
|
310
|
-
|
311
304
|
# If we're in a positional REMAINDER arg, force all future tokens to go to that
|
312
305
|
if pos_arg_state is not None and pos_arg_state.is_remainder:
|
313
306
|
consume_argument(pos_arg_state)
|
@@ -339,7 +332,6 @@ class ArgparseCompleter:
|
|
339
332
|
|
340
333
|
# Check the format of the current token to see if it can be an argument's value
|
341
334
|
if _looks_like_flag(token, self._parser) and not skip_remaining_flags:
|
342
|
-
|
343
335
|
# Check if there is an unfinished flag
|
344
336
|
if (
|
345
337
|
flag_arg_state is not None
|
@@ -484,7 +476,6 @@ class ArgparseCompleter:
|
|
484
476
|
|
485
477
|
# Otherwise check if we have a positional to complete
|
486
478
|
elif pos_arg_state is not None or remaining_positionals:
|
487
|
-
|
488
479
|
# If we aren't current tracking a positional, then get the next positional arg to handle this token
|
489
480
|
if pos_arg_state is None:
|
490
481
|
action = remaining_positionals.popleft()
|
cmd2/argparse_custom.py
CHANGED
@@ -101,7 +101,7 @@ dynamic. Therefore it is up to the developer to validate if the user has typed
|
|
101
101
|
an acceptable value for these arguments.
|
102
102
|
|
103
103
|
There are times when what's being tab completed is determined by a previous
|
104
|
-
argument on the command line. In
|
104
|
+
argument on the command line. In these cases, ArgparseCompleter can pass a
|
105
105
|
dictionary that maps the command line tokens up through the one being completed
|
106
106
|
to their argparse argument name. To receive this dictionary, your
|
107
107
|
choices/completer function should have an argument called arg_tokens.
|
@@ -237,8 +237,6 @@ sub-parser from a sub-parsers group. See
|
|
237
237
|
import argparse
|
238
238
|
import re
|
239
239
|
import sys
|
240
|
-
|
241
|
-
# noinspection PyUnresolvedReferences,PyProtectedMember
|
242
240
|
from argparse import (
|
243
241
|
ONE_OR_MORE,
|
244
242
|
ZERO_OR_MORE,
|
@@ -257,12 +255,14 @@ from typing import (
|
|
257
255
|
List,
|
258
256
|
NoReturn,
|
259
257
|
Optional,
|
258
|
+
Protocol,
|
260
259
|
Sequence,
|
261
260
|
Set,
|
262
261
|
Tuple,
|
263
262
|
Type,
|
264
263
|
Union,
|
265
264
|
cast,
|
265
|
+
runtime_checkable,
|
266
266
|
)
|
267
267
|
|
268
268
|
from . import (
|
@@ -270,18 +270,6 @@ from . import (
|
|
270
270
|
constants,
|
271
271
|
)
|
272
272
|
|
273
|
-
try:
|
274
|
-
from typing import (
|
275
|
-
Protocol,
|
276
|
-
runtime_checkable,
|
277
|
-
)
|
278
|
-
except ImportError:
|
279
|
-
from typing_extensions import ( # type: ignore[assignment]
|
280
|
-
Protocol,
|
281
|
-
runtime_checkable,
|
282
|
-
)
|
283
|
-
|
284
|
-
|
285
273
|
if TYPE_CHECKING: # pragma: no cover
|
286
274
|
from .argparse_completer import (
|
287
275
|
ArgparseCompleter,
|
@@ -317,7 +305,6 @@ class CompletionItem(str):
|
|
317
305
|
def __new__(cls, value: object, *args: Any, **kwargs: Any) -> 'CompletionItem':
|
318
306
|
return super(CompletionItem, cls).__new__(cls, value)
|
319
307
|
|
320
|
-
# noinspection PyUnusedLocal
|
321
308
|
def __init__(self, value: object, description: str = '', *args: Any) -> None:
|
322
309
|
"""
|
323
310
|
CompletionItem Initializer
|
@@ -351,8 +338,7 @@ class ChoicesProviderFuncBase(Protocol):
|
|
351
338
|
Function that returns a list of choices in support of tab completion
|
352
339
|
"""
|
353
340
|
|
354
|
-
def __call__(self) -> List[str]:
|
355
|
-
... # pragma: no cover
|
341
|
+
def __call__(self) -> List[str]: ... # pragma: no cover
|
356
342
|
|
357
343
|
|
358
344
|
@runtime_checkable
|
@@ -361,8 +347,7 @@ class ChoicesProviderFuncWithTokens(Protocol):
|
|
361
347
|
Function that returns a list of choices in support of tab completion and accepts a dictionary of prior arguments.
|
362
348
|
"""
|
363
349
|
|
364
|
-
def __call__(self, *, arg_tokens: Dict[str, List[str]] = {}) -> List[str]:
|
365
|
-
... # pragma: no cover
|
350
|
+
def __call__(self, *, arg_tokens: Dict[str, List[str]] = {}) -> List[str]: ... # pragma: no cover
|
366
351
|
|
367
352
|
|
368
353
|
ChoicesProviderFunc = Union[ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens]
|
@@ -380,8 +365,7 @@ class CompleterFuncBase(Protocol):
|
|
380
365
|
line: str,
|
381
366
|
begidx: int,
|
382
367
|
endidx: int,
|
383
|
-
) -> List[str]:
|
384
|
-
... # pragma: no cover
|
368
|
+
) -> List[str]: ... # pragma: no cover
|
385
369
|
|
386
370
|
|
387
371
|
@runtime_checkable
|
@@ -399,8 +383,7 @@ class CompleterFuncWithTokens(Protocol):
|
|
399
383
|
endidx: int,
|
400
384
|
*,
|
401
385
|
arg_tokens: Dict[str, List[str]] = {},
|
402
|
-
) -> List[str]:
|
403
|
-
... # pragma: no cover
|
386
|
+
) -> List[str]: ... # pragma: no cover
|
404
387
|
|
405
388
|
|
406
389
|
CompleterFunc = Union[CompleterFuncBase, CompleterFuncWithTokens]
|
@@ -745,11 +728,9 @@ def register_argparse_argument_parameter(param_name: str, param_type: Optional[T
|
|
745
728
|
|
746
729
|
|
747
730
|
# Save original _ActionsContainer.add_argument so we can call it in our wrapper
|
748
|
-
# noinspection PyProtectedMember
|
749
731
|
orig_actions_container_add_argument = argparse._ActionsContainer.add_argument
|
750
732
|
|
751
733
|
|
752
|
-
# noinspection PyProtectedMember
|
753
734
|
def _add_argument_wrapper(
|
754
735
|
self: argparse._ActionsContainer,
|
755
736
|
*args: Any,
|
@@ -807,7 +788,6 @@ def _add_argument_wrapper(
|
|
807
788
|
nargs_adjusted: Union[int, str, Tuple[int], Tuple[int, int], Tuple[int, float], None]
|
808
789
|
# Check if nargs was given as a range
|
809
790
|
if isinstance(nargs, tuple):
|
810
|
-
|
811
791
|
# Handle 1-item tuple by setting max to INFINITY
|
812
792
|
if len(nargs) == 1:
|
813
793
|
nargs = (nargs[0], constants.INFINITY)
|
@@ -885,7 +865,6 @@ def _add_argument_wrapper(
|
|
885
865
|
|
886
866
|
|
887
867
|
# Overwrite _ActionsContainer.add_argument with our wrapper
|
888
|
-
# noinspection PyProtectedMember
|
889
868
|
setattr(argparse._ActionsContainer, 'add_argument', _add_argument_wrapper)
|
890
869
|
|
891
870
|
############################################################################################################
|
@@ -893,11 +872,9 @@ setattr(argparse._ActionsContainer, 'add_argument', _add_argument_wrapper)
|
|
893
872
|
############################################################################################################
|
894
873
|
|
895
874
|
# Save original ArgumentParser._get_nargs_pattern so we can call it in our wrapper
|
896
|
-
# noinspection PyProtectedMember
|
897
875
|
orig_argument_parser_get_nargs_pattern = argparse.ArgumentParser._get_nargs_pattern
|
898
876
|
|
899
877
|
|
900
|
-
# noinspection PyProtectedMember
|
901
878
|
def _get_nargs_pattern_wrapper(self: argparse.ArgumentParser, action: argparse.Action) -> str:
|
902
879
|
# Wrapper around ArgumentParser._get_nargs_pattern behavior to support nargs ranges
|
903
880
|
nargs_range = action.get_nargs_range() # type: ignore[attr-defined]
|
@@ -919,18 +896,15 @@ def _get_nargs_pattern_wrapper(self: argparse.ArgumentParser, action: argparse.A
|
|
919
896
|
|
920
897
|
|
921
898
|
# Overwrite ArgumentParser._get_nargs_pattern with our wrapper
|
922
|
-
# noinspection PyProtectedMember
|
923
899
|
setattr(argparse.ArgumentParser, '_get_nargs_pattern', _get_nargs_pattern_wrapper)
|
924
900
|
|
925
901
|
|
926
902
|
############################################################################################################
|
927
903
|
# Patch ArgumentParser._match_argument with our wrapper to support nargs ranges
|
928
904
|
############################################################################################################
|
929
|
-
# noinspection PyProtectedMember
|
930
905
|
orig_argument_parser_match_argument = argparse.ArgumentParser._match_argument
|
931
906
|
|
932
907
|
|
933
|
-
# noinspection PyProtectedMember
|
934
908
|
def _match_argument_wrapper(self: argparse.ArgumentParser, action: argparse.Action, arg_strings_pattern: str) -> int:
|
935
909
|
# Wrapper around ArgumentParser._match_argument behavior to support nargs ranges
|
936
910
|
nargs_pattern = self._get_nargs_pattern(action)
|
@@ -946,7 +920,6 @@ def _match_argument_wrapper(self: argparse.ArgumentParser, action: argparse.Acti
|
|
946
920
|
|
947
921
|
|
948
922
|
# Overwrite ArgumentParser._match_argument with our wrapper
|
949
|
-
# noinspection PyProtectedMember
|
950
923
|
setattr(argparse.ArgumentParser, '_match_argument', _match_argument_wrapper)
|
951
924
|
|
952
925
|
|
@@ -960,7 +933,6 @@ setattr(argparse.ArgumentParser, '_match_argument', _match_argument_wrapper)
|
|
960
933
|
ATTR_AP_COMPLETER_TYPE = 'ap_completer_type'
|
961
934
|
|
962
935
|
|
963
|
-
# noinspection PyPep8Naming
|
964
936
|
def _ArgumentParser_get_ap_completer_type(self: argparse.ArgumentParser) -> Optional[Type['ArgparseCompleter']]:
|
965
937
|
"""
|
966
938
|
Get the ap_completer_type attribute of an argparse ArgumentParser.
|
@@ -978,7 +950,6 @@ def _ArgumentParser_get_ap_completer_type(self: argparse.ArgumentParser) -> Opti
|
|
978
950
|
setattr(argparse.ArgumentParser, 'get_ap_completer_type', _ArgumentParser_get_ap_completer_type)
|
979
951
|
|
980
952
|
|
981
|
-
# noinspection PyPep8Naming
|
982
953
|
def _ArgumentParser_set_ap_completer_type(self: argparse.ArgumentParser, ap_completer_type: Type['ArgparseCompleter']) -> None:
|
983
954
|
"""
|
984
955
|
Set the ap_completer_type attribute of an argparse ArgumentParser.
|
@@ -999,7 +970,6 @@ setattr(argparse.ArgumentParser, 'set_ap_completer_type', _ArgumentParser_set_ap
|
|
999
970
|
############################################################################################################
|
1000
971
|
# Patch ArgumentParser._check_value to support CompletionItems as choices
|
1001
972
|
############################################################################################################
|
1002
|
-
# noinspection PyPep8Naming
|
1003
973
|
def _ArgumentParser_check_value(self: argparse.ArgumentParser, action: argparse.Action, value: Any) -> None:
|
1004
974
|
"""
|
1005
975
|
Custom override of ArgumentParser._check_value that supports CompletionItems as choices.
|
@@ -1032,7 +1002,7 @@ setattr(argparse.ArgumentParser, '_check_value', _ArgumentParser_check_value)
|
|
1032
1002
|
# Patch argparse._SubParsersAction to add remove_parser function
|
1033
1003
|
############################################################################################################
|
1034
1004
|
|
1035
|
-
|
1005
|
+
|
1036
1006
|
def _SubParsersAction_remove_parser(self: argparse._SubParsersAction, name: str) -> None: # type: ignore
|
1037
1007
|
"""
|
1038
1008
|
Removes a sub-parser from a sub-parsers group. Used to remove subcommands from a parser.
|
@@ -1061,7 +1031,6 @@ def _SubParsersAction_remove_parser(self: argparse._SubParsersAction, name: str)
|
|
1061
1031
|
del self._name_parser_map[cur_name]
|
1062
1032
|
|
1063
1033
|
|
1064
|
-
# noinspection PyProtectedMember
|
1065
1034
|
setattr(argparse._SubParsersAction, 'remove_parser', _SubParsersAction_remove_parser)
|
1066
1035
|
|
1067
1036
|
|
@@ -1073,11 +1042,9 @@ setattr(argparse._SubParsersAction, 'remove_parser', _SubParsersAction_remove_pa
|
|
1073
1042
|
############################################################################################################
|
1074
1043
|
|
1075
1044
|
|
1076
|
-
# noinspection PyCompatibility,PyShadowingBuiltins
|
1077
1045
|
class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
1078
1046
|
"""Custom help formatter to configure ordering of help text"""
|
1079
1047
|
|
1080
|
-
# noinspection PyProtectedMember
|
1081
1048
|
def _format_usage(
|
1082
1049
|
self,
|
1083
1050
|
usage: Optional[str],
|
@@ -1117,20 +1084,19 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1117
1084
|
|
1118
1085
|
# build full usage string
|
1119
1086
|
format = self._format_actions_usage
|
1120
|
-
action_usage = format(required_options + optionals + positionals, groups)
|
1087
|
+
action_usage = format(required_options + optionals + positionals, groups) # type: ignore[arg-type]
|
1121
1088
|
usage = ' '.join([s for s in [prog, action_usage] if s])
|
1122
1089
|
|
1123
1090
|
# wrap the usage parts if it's too long
|
1124
1091
|
text_width = self._width - self._current_indent
|
1125
1092
|
if len(prefix) + len(usage) > text_width:
|
1126
|
-
|
1127
1093
|
# Begin cmd2 customization
|
1128
1094
|
|
1129
1095
|
# break usage into wrappable parts
|
1130
1096
|
part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
|
1131
|
-
req_usage = format(required_options, groups)
|
1132
|
-
opt_usage = format(optionals, groups)
|
1133
|
-
pos_usage = format(positionals, groups)
|
1097
|
+
req_usage = format(required_options, groups) # type: ignore[arg-type]
|
1098
|
+
opt_usage = format(optionals, groups) # type: ignore[arg-type]
|
1099
|
+
pos_usage = format(positionals, groups) # type: ignore[arg-type]
|
1134
1100
|
req_parts = re.findall(part_regexp, req_usage)
|
1135
1101
|
opt_parts = re.findall(part_regexp, opt_usage)
|
1136
1102
|
pos_parts = re.findall(part_regexp, pos_usage)
|
@@ -1141,7 +1107,6 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1141
1107
|
# End cmd2 customization
|
1142
1108
|
|
1143
1109
|
# helper for wrapping lines
|
1144
|
-
# noinspection PyMissingOrEmptyDocstring,PyShadowingNames
|
1145
1110
|
def get_lines(parts: List[str], indent: str, prefix: Optional[str] = None) -> List[str]:
|
1146
1111
|
lines: List[str] = []
|
1147
1112
|
line: List[str] = []
|
@@ -1224,7 +1189,6 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1224
1189
|
return ', '.join(action.option_strings) + ' ' + args_string
|
1225
1190
|
# End cmd2 customization
|
1226
1191
|
|
1227
|
-
# noinspection PyMethodMayBeStatic
|
1228
1192
|
def _determine_metavar(
|
1229
1193
|
self,
|
1230
1194
|
action: argparse.Action,
|
@@ -1249,7 +1213,6 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1249
1213
|
) -> Callable[[int], Tuple[str, ...]]:
|
1250
1214
|
metavar = self._determine_metavar(action, default_metavar)
|
1251
1215
|
|
1252
|
-
# noinspection PyMissingOrEmptyDocstring
|
1253
1216
|
def format(tuple_size: int) -> Tuple[str, ...]:
|
1254
1217
|
if isinstance(metavar, tuple):
|
1255
1218
|
return metavar
|
@@ -1258,7 +1221,6 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1258
1221
|
|
1259
1222
|
return format
|
1260
1223
|
|
1261
|
-
# noinspection PyProtectedMember
|
1262
1224
|
def _format_args(self, action: argparse.Action, default_metavar: Union[str, Tuple[str, ...]]) -> str:
|
1263
1225
|
"""Customized to handle ranged nargs and make other output less verbose"""
|
1264
1226
|
metavar = self._determine_metavar(action, default_metavar)
|
@@ -1287,7 +1249,6 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1287
1249
|
return super()._format_args(action, default_metavar) # type: ignore[arg-type]
|
1288
1250
|
|
1289
1251
|
|
1290
|
-
# noinspection PyCompatibility
|
1291
1252
|
class Cmd2ArgumentParser(argparse.ArgumentParser):
|
1292
1253
|
"""Custom ArgumentParser class that improves error and help output"""
|
1293
1254
|
|
@@ -1332,7 +1293,6 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
1332
1293
|
|
1333
1294
|
self.set_ap_completer_type(ap_completer_type) # type: ignore[attr-defined]
|
1334
1295
|
|
1335
|
-
# noinspection PyProtectedMember
|
1336
1296
|
def add_subparsers(self, **kwargs: Any) -> argparse._SubParsersAction: # type: ignore
|
1337
1297
|
"""
|
1338
1298
|
Custom override. Sets a default title if one was not given.
|
@@ -1361,7 +1321,6 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
1361
1321
|
formatted_message = ansi.style_error(formatted_message)
|
1362
1322
|
self.exit(2, f'{formatted_message}\n\n')
|
1363
1323
|
|
1364
|
-
# noinspection PyProtectedMember
|
1365
1324
|
def format_help(self) -> str:
|
1366
1325
|
"""Copy of format_help() from argparse.ArgumentParser with tweaks to separately display required parameters"""
|
1367
1326
|
formatter = self._get_formatter()
|
cmd2/clipboard.py
CHANGED
@@ -2,29 +2,10 @@
|
|
2
2
|
"""
|
3
3
|
This module provides basic ability to copy from and paste to the clipboard/pastebuffer.
|
4
4
|
"""
|
5
|
-
from typing import (
|
6
|
-
cast,
|
7
|
-
)
|
8
5
|
|
9
|
-
import
|
10
|
-
|
11
|
-
# noinspection PyProtectedMember
|
6
|
+
import typing
|
12
7
|
|
13
|
-
|
14
|
-
# noinspection PyBroadException
|
15
|
-
try:
|
16
|
-
# Try getting the contents of the clipboard
|
17
|
-
_ = pyperclip.paste()
|
18
|
-
|
19
|
-
# pyperclip raises at least the following types of exceptions. To be safe, just catch all Exceptions.
|
20
|
-
# FileNotFoundError on Windows Subsystem for Linux (WSL) when Windows paths are removed from $PATH
|
21
|
-
# ValueError for headless Linux systems without Gtk installed
|
22
|
-
# AssertionError can be raised by paste_klipper().
|
23
|
-
# PyperclipException for pyperclip-specific exceptions
|
24
|
-
except Exception:
|
25
|
-
can_clip = False
|
26
|
-
else:
|
27
|
-
can_clip = True
|
8
|
+
import pyperclip # type: ignore[import]
|
28
9
|
|
29
10
|
|
30
11
|
def get_paste_buffer() -> str:
|
@@ -32,7 +13,7 @@ def get_paste_buffer() -> str:
|
|
32
13
|
|
33
14
|
:return: contents of the clipboard
|
34
15
|
"""
|
35
|
-
pb_str = cast(str, pyperclip.paste())
|
16
|
+
pb_str = typing.cast(str, pyperclip.paste())
|
36
17
|
return pb_str
|
37
18
|
|
38
19
|
|