cmd2 2.5.10__py3-none-any.whl → 2.6.0__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 +11 -22
- cmd2/ansi.py +78 -91
- cmd2/argparse_completer.py +109 -132
- cmd2/argparse_custom.py +199 -217
- cmd2/clipboard.py +2 -6
- cmd2/cmd2.py +447 -521
- cmd2/command_definition.py +34 -44
- cmd2/constants.py +1 -3
- cmd2/decorators.py +47 -58
- cmd2/exceptions.py +23 -46
- cmd2/history.py +29 -43
- cmd2/parsing.py +59 -84
- cmd2/plugin.py +6 -10
- cmd2/py_bridge.py +20 -26
- cmd2/rl_utils.py +45 -69
- cmd2/table_creator.py +83 -106
- cmd2/transcript.py +55 -59
- cmd2/utils.py +143 -176
- {cmd2-2.5.10.dist-info → cmd2-2.6.0.dist-info}/METADATA +34 -17
- cmd2-2.6.0.dist-info/RECORD +24 -0
- {cmd2-2.5.10.dist-info → cmd2-2.6.0.dist-info}/WHEEL +1 -1
- cmd2-2.5.10.dist-info/RECORD +0 -24
- {cmd2-2.5.10.dist-info → cmd2-2.6.0.dist-info/licenses}/LICENSE +0 -0
- {cmd2-2.5.10.dist-info → cmd2-2.6.0.dist-info}/top_level.txt +0 -0
cmd2/argparse_custom.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
This module adds capabilities to argparse by patching a few of its functions.
|
1
|
+
"""Module adds capabilities to argparse by patching a few of its functions.
|
2
|
+
|
4
3
|
It also defines a parser class called Cmd2ArgumentParser which improves error
|
5
4
|
and help output over normal argparse. All cmd2 code uses this parser and it is
|
6
5
|
recommended that developers of cmd2-based apps either use it or write their own
|
@@ -230,6 +229,7 @@ from argparse import (
|
|
230
229
|
ZERO_OR_MORE,
|
231
230
|
ArgumentError,
|
232
231
|
)
|
232
|
+
from collections.abc import Callable, Iterable, Sequence
|
233
233
|
from gettext import (
|
234
234
|
gettext,
|
235
235
|
)
|
@@ -237,17 +237,9 @@ from typing import (
|
|
237
237
|
IO,
|
238
238
|
TYPE_CHECKING,
|
239
239
|
Any,
|
240
|
-
Callable,
|
241
|
-
Dict,
|
242
|
-
Iterable,
|
243
|
-
List,
|
244
240
|
NoReturn,
|
245
241
|
Optional,
|
246
242
|
Protocol,
|
247
|
-
Sequence,
|
248
|
-
Set,
|
249
|
-
Tuple,
|
250
|
-
Type,
|
251
243
|
Union,
|
252
244
|
cast,
|
253
245
|
runtime_checkable,
|
@@ -264,8 +256,8 @@ if TYPE_CHECKING: # pragma: no cover
|
|
264
256
|
)
|
265
257
|
|
266
258
|
|
267
|
-
def generate_range_error(range_min: int, range_max:
|
268
|
-
"""Generate an error message when the the number of arguments provided is not within the expected range"""
|
259
|
+
def generate_range_error(range_min: int, range_max: float) -> str:
|
260
|
+
"""Generate an error message when the the number of arguments provided is not within the expected range."""
|
269
261
|
err_str = "expected "
|
270
262
|
|
271
263
|
if range_max == constants.INFINITY:
|
@@ -283,19 +275,18 @@ def generate_range_error(range_min: int, range_max: Union[int, float]) -> str:
|
|
283
275
|
return err_str
|
284
276
|
|
285
277
|
|
286
|
-
class CompletionItem(str):
|
287
|
-
"""
|
288
|
-
Completion item with descriptive text attached
|
278
|
+
class CompletionItem(str): # noqa: SLOT000
|
279
|
+
"""Completion item with descriptive text attached.
|
289
280
|
|
290
281
|
See header of this file for more information
|
291
282
|
"""
|
292
283
|
|
293
|
-
def __new__(cls, value: object, *
|
294
|
-
|
284
|
+
def __new__(cls, value: object, *_args: Any, **_kwargs: Any) -> 'CompletionItem':
|
285
|
+
"""Responsible for creating and returning a new instance, called before __init__ when an object is instantiated."""
|
286
|
+
return super().__new__(cls, value)
|
295
287
|
|
296
288
|
def __init__(self, value: object, description: str = '', *args: Any) -> None:
|
297
|
-
"""
|
298
|
-
CompletionItem Initializer
|
289
|
+
"""CompletionItem Initializer.
|
299
290
|
|
300
291
|
:param value: the value being tab completed
|
301
292
|
:param description: description text to display
|
@@ -310,7 +301,7 @@ class CompletionItem(str):
|
|
310
301
|
|
311
302
|
@property
|
312
303
|
def orig_value(self) -> Any:
|
313
|
-
"""Read-only property for _orig_value"""
|
304
|
+
"""Read-only property for _orig_value."""
|
314
305
|
return self._orig_value
|
315
306
|
|
316
307
|
|
@@ -321,20 +312,18 @@ class CompletionItem(str):
|
|
321
312
|
|
322
313
|
@runtime_checkable
|
323
314
|
class ChoicesProviderFuncBase(Protocol):
|
324
|
-
"""
|
325
|
-
Function that returns a list of choices in support of tab completion
|
326
|
-
"""
|
315
|
+
"""Function that returns a list of choices in support of tab completion."""
|
327
316
|
|
328
|
-
def __call__(self) ->
|
317
|
+
def __call__(self) -> list[str]: # pragma: no cover
|
318
|
+
"""Enable instances to be called like functions."""
|
329
319
|
|
330
320
|
|
331
321
|
@runtime_checkable
|
332
322
|
class ChoicesProviderFuncWithTokens(Protocol):
|
333
|
-
"""
|
334
|
-
Function that returns a list of choices in support of tab completion and accepts a dictionary of prior arguments.
|
335
|
-
"""
|
323
|
+
"""Function that returns a list of choices in support of tab completion and accepts a dictionary of prior arguments."""
|
336
324
|
|
337
|
-
def __call__(self, *, arg_tokens:
|
325
|
+
def __call__(self, *, arg_tokens: dict[str, list[str]] = {}) -> list[str]: # pragma: no cover # noqa: B006
|
326
|
+
"""Enable instances to be called like functions."""
|
338
327
|
|
339
328
|
|
340
329
|
ChoicesProviderFunc = Union[ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens]
|
@@ -342,9 +331,7 @@ ChoicesProviderFunc = Union[ChoicesProviderFuncBase, ChoicesProviderFuncWithToke
|
|
342
331
|
|
343
332
|
@runtime_checkable
|
344
333
|
class CompleterFuncBase(Protocol):
|
345
|
-
"""
|
346
|
-
Function to support tab completion with the provided state of the user prompt
|
347
|
-
"""
|
334
|
+
"""Function to support tab completion with the provided state of the user prompt."""
|
348
335
|
|
349
336
|
def __call__(
|
350
337
|
self,
|
@@ -352,15 +339,13 @@ class CompleterFuncBase(Protocol):
|
|
352
339
|
line: str,
|
353
340
|
begidx: int,
|
354
341
|
endidx: int,
|
355
|
-
) ->
|
342
|
+
) -> list[str]: # pragma: no cover
|
343
|
+
"""Enable instances to be called like functions."""
|
356
344
|
|
357
345
|
|
358
346
|
@runtime_checkable
|
359
347
|
class CompleterFuncWithTokens(Protocol):
|
360
|
-
"""
|
361
|
-
Function to support tab completion with the provided state of the user prompt and accepts a dictionary of prior
|
362
|
-
arguments.
|
363
|
-
"""
|
348
|
+
"""Function to support tab completion with the provided state of the user prompt, accepts a dictionary of prior args."""
|
364
349
|
|
365
350
|
def __call__(
|
366
351
|
self,
|
@@ -369,16 +354,17 @@ class CompleterFuncWithTokens(Protocol):
|
|
369
354
|
begidx: int,
|
370
355
|
endidx: int,
|
371
356
|
*,
|
372
|
-
arg_tokens:
|
373
|
-
) ->
|
357
|
+
arg_tokens: dict[str, list[str]] = {}, # noqa: B006
|
358
|
+
) -> list[str]: # pragma: no cover
|
359
|
+
"""Enable instances to be called like functions."""
|
374
360
|
|
375
361
|
|
376
362
|
CompleterFunc = Union[CompleterFuncBase, CompleterFuncWithTokens]
|
377
363
|
|
378
364
|
|
379
365
|
class ChoicesCallable:
|
380
|
-
"""
|
381
|
-
|
366
|
+
"""Enables using a callable as the choices provider for an argparse argument.
|
367
|
+
|
382
368
|
While argparse has the built-in choices attribute, it is limited to an iterable.
|
383
369
|
"""
|
384
370
|
|
@@ -387,11 +373,11 @@ class ChoicesCallable:
|
|
387
373
|
is_completer: bool,
|
388
374
|
to_call: Union[CompleterFunc, ChoicesProviderFunc],
|
389
375
|
) -> None:
|
390
|
-
"""
|
391
|
-
|
376
|
+
"""Initialize the ChoiceCallable instance.
|
377
|
+
|
392
378
|
:param is_completer: True if to_call is a tab completion routine which expects
|
393
379
|
the args: text, line, begidx, endidx
|
394
|
-
:param to_call: the callable object that will be called to provide choices for the argument
|
380
|
+
:param to_call: the callable object that will be called to provide choices for the argument.
|
395
381
|
"""
|
396
382
|
self.is_completer = is_completer
|
397
383
|
if is_completer:
|
@@ -400,27 +386,28 @@ class ChoicesCallable:
|
|
400
386
|
raise ValueError(
|
401
387
|
'With is_completer set to true, to_call must be either CompleterFunc, CompleterFuncWithTokens'
|
402
388
|
)
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
)
|
389
|
+
elif not isinstance(to_call, (ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens)): # pragma: no cover
|
390
|
+
# runtime checking of Protocols do not currently check the parameters of a function.
|
391
|
+
raise ValueError(
|
392
|
+
'With is_completer set to false, to_call must be either: '
|
393
|
+
'ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens'
|
394
|
+
)
|
410
395
|
self.to_call = to_call
|
411
396
|
|
412
397
|
@property
|
413
398
|
def completer(self) -> CompleterFunc:
|
399
|
+
"""Retreive the internal Completer function, first type checking to ensure it is the right type."""
|
414
400
|
if not isinstance(self.to_call, (CompleterFuncBase, CompleterFuncWithTokens)): # pragma: no cover
|
415
401
|
# this should've been caught in the constructor, just a backup check
|
416
|
-
raise
|
402
|
+
raise TypeError('Function is not a CompleterFunc')
|
417
403
|
return self.to_call
|
418
404
|
|
419
405
|
@property
|
420
406
|
def choices_provider(self) -> ChoicesProviderFunc:
|
407
|
+
"""Retreive the internal ChoicesProvider function, first type checking to ensure it is the right type."""
|
421
408
|
if not isinstance(self.to_call, (ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens)): # pragma: no cover
|
422
409
|
# this should've been caught in the constructor, just a backup check
|
423
|
-
raise
|
410
|
+
raise TypeError('Function is not a ChoicesProviderFunc')
|
424
411
|
return self.to_call
|
425
412
|
|
426
413
|
|
@@ -446,8 +433,7 @@ ATTR_SUPPRESS_TAB_HINT = 'suppress_tab_hint'
|
|
446
433
|
# Patch argparse.Action with accessors for choice_callable attribute
|
447
434
|
############################################################################################################
|
448
435
|
def _action_get_choices_callable(self: argparse.Action) -> Optional[ChoicesCallable]:
|
449
|
-
"""
|
450
|
-
Get the choices_callable attribute of an argparse Action.
|
436
|
+
"""Get the choices_callable attribute of an argparse Action.
|
451
437
|
|
452
438
|
This function is added by cmd2 as a method called ``get_choices_callable()`` to ``argparse.Action`` class.
|
453
439
|
|
@@ -463,8 +449,7 @@ setattr(argparse.Action, 'get_choices_callable', _action_get_choices_callable)
|
|
463
449
|
|
464
450
|
|
465
451
|
def _action_set_choices_callable(self: argparse.Action, choices_callable: ChoicesCallable) -> None:
|
466
|
-
"""
|
467
|
-
Set the choices_callable attribute of an argparse Action.
|
452
|
+
"""Set the choices_callable attribute of an argparse Action.
|
468
453
|
|
469
454
|
This function is added by cmd2 as a method called ``_set_choices_callable()`` to ``argparse.Action`` class.
|
470
455
|
|
@@ -478,7 +463,7 @@ def _action_set_choices_callable(self: argparse.Action, choices_callable: Choice
|
|
478
463
|
if self.choices is not None:
|
479
464
|
err_msg = "None of the following parameters can be used alongside a choices parameter:\nchoices_provider, completer"
|
480
465
|
raise (TypeError(err_msg))
|
481
|
-
|
466
|
+
if self.nargs == 0:
|
482
467
|
err_msg = (
|
483
468
|
"None of the following parameters can be used on an action that takes no arguments:\nchoices_provider, completer"
|
484
469
|
)
|
@@ -494,8 +479,7 @@ def _action_set_choices_provider(
|
|
494
479
|
self: argparse.Action,
|
495
480
|
choices_provider: ChoicesProviderFunc,
|
496
481
|
) -> None:
|
497
|
-
"""
|
498
|
-
Set choices_provider of an argparse Action.
|
482
|
+
"""Set choices_provider of an argparse Action.
|
499
483
|
|
500
484
|
This function is added by cmd2 as a method called ``set_choices_callable()`` to ``argparse.Action`` class.
|
501
485
|
|
@@ -515,8 +499,7 @@ def _action_set_completer(
|
|
515
499
|
self: argparse.Action,
|
516
500
|
completer: CompleterFunc,
|
517
501
|
) -> None:
|
518
|
-
"""
|
519
|
-
Set completer of an argparse Action.
|
502
|
+
"""Set completer of an argparse Action.
|
520
503
|
|
521
504
|
This function is added by cmd2 as a method called ``set_completer()`` to ``argparse.Action`` class.
|
522
505
|
|
@@ -536,8 +519,7 @@ setattr(argparse.Action, 'set_completer', _action_set_completer)
|
|
536
519
|
# Patch argparse.Action with accessors for descriptive_header attribute
|
537
520
|
############################################################################################################
|
538
521
|
def _action_get_descriptive_header(self: argparse.Action) -> Optional[str]:
|
539
|
-
"""
|
540
|
-
Get the descriptive_header attribute of an argparse Action.
|
522
|
+
"""Get the descriptive_header attribute of an argparse Action.
|
541
523
|
|
542
524
|
This function is added by cmd2 as a method called ``get_descriptive_header()`` to ``argparse.Action`` class.
|
543
525
|
|
@@ -553,8 +535,7 @@ setattr(argparse.Action, 'get_descriptive_header', _action_get_descriptive_heade
|
|
553
535
|
|
554
536
|
|
555
537
|
def _action_set_descriptive_header(self: argparse.Action, descriptive_header: Optional[str]) -> None:
|
556
|
-
"""
|
557
|
-
Set the descriptive_header attribute of an argparse Action.
|
538
|
+
"""Set the descriptive_header attribute of an argparse Action.
|
558
539
|
|
559
540
|
This function is added by cmd2 as a method called ``set_descriptive_header()`` to ``argparse.Action`` class.
|
560
541
|
|
@@ -572,9 +553,8 @@ setattr(argparse.Action, 'set_descriptive_header', _action_set_descriptive_heade
|
|
572
553
|
############################################################################################################
|
573
554
|
# Patch argparse.Action with accessors for nargs_range attribute
|
574
555
|
############################################################################################################
|
575
|
-
def _action_get_nargs_range(self: argparse.Action) -> Optional[
|
576
|
-
"""
|
577
|
-
Get the nargs_range attribute of an argparse Action.
|
556
|
+
def _action_get_nargs_range(self: argparse.Action) -> Optional[tuple[int, Union[int, float]]]:
|
557
|
+
"""Get the nargs_range attribute of an argparse Action.
|
578
558
|
|
579
559
|
This function is added by cmd2 as a method called ``get_nargs_range()`` to ``argparse.Action`` class.
|
580
560
|
|
@@ -583,15 +563,14 @@ def _action_get_nargs_range(self: argparse.Action) -> Optional[Tuple[int, Union[
|
|
583
563
|
:param self: argparse Action being queried
|
584
564
|
:return: The value of nargs_range or None if attribute does not exist
|
585
565
|
"""
|
586
|
-
return cast(Optional[
|
566
|
+
return cast(Optional[tuple[int, Union[int, float]]], getattr(self, ATTR_NARGS_RANGE, None))
|
587
567
|
|
588
568
|
|
589
569
|
setattr(argparse.Action, 'get_nargs_range', _action_get_nargs_range)
|
590
570
|
|
591
571
|
|
592
|
-
def _action_set_nargs_range(self: argparse.Action, nargs_range: Optional[
|
593
|
-
"""
|
594
|
-
Set the nargs_range attribute of an argparse Action.
|
572
|
+
def _action_set_nargs_range(self: argparse.Action, nargs_range: Optional[tuple[int, Union[int, float]]]) -> None:
|
573
|
+
"""Set the nargs_range attribute of an argparse Action.
|
595
574
|
|
596
575
|
This function is added by cmd2 as a method called ``set_nargs_range()`` to ``argparse.Action`` class.
|
597
576
|
|
@@ -610,8 +589,7 @@ setattr(argparse.Action, 'set_nargs_range', _action_set_nargs_range)
|
|
610
589
|
# Patch argparse.Action with accessors for suppress_tab_hint attribute
|
611
590
|
############################################################################################################
|
612
591
|
def _action_get_suppress_tab_hint(self: argparse.Action) -> bool:
|
613
|
-
"""
|
614
|
-
Get the suppress_tab_hint attribute of an argparse Action.
|
592
|
+
"""Get the suppress_tab_hint attribute of an argparse Action.
|
615
593
|
|
616
594
|
This function is added by cmd2 as a method called ``get_suppress_tab_hint()`` to ``argparse.Action`` class.
|
617
595
|
|
@@ -627,8 +605,7 @@ setattr(argparse.Action, 'get_suppress_tab_hint', _action_get_suppress_tab_hint)
|
|
627
605
|
|
628
606
|
|
629
607
|
def _action_set_suppress_tab_hint(self: argparse.Action, suppress_tab_hint: bool) -> None:
|
630
|
-
"""
|
631
|
-
Set the suppress_tab_hint attribute of an argparse Action.
|
608
|
+
"""Set the suppress_tab_hint attribute of an argparse Action.
|
632
609
|
|
633
610
|
This function is added by cmd2 as a method called ``set_suppress_tab_hint()`` to ``argparse.Action`` class.
|
634
611
|
|
@@ -647,13 +624,12 @@ setattr(argparse.Action, 'set_suppress_tab_hint', _action_set_suppress_tab_hint)
|
|
647
624
|
# Allow developers to add custom action attributes
|
648
625
|
############################################################################################################
|
649
626
|
|
650
|
-
CUSTOM_ACTION_ATTRIBS:
|
627
|
+
CUSTOM_ACTION_ATTRIBS: set[str] = set()
|
651
628
|
_CUSTOM_ATTRIB_PFX = '_attr_'
|
652
629
|
|
653
630
|
|
654
|
-
def register_argparse_argument_parameter(param_name: str, param_type: Optional[
|
655
|
-
"""
|
656
|
-
Registers a custom argparse argument parameter.
|
631
|
+
def register_argparse_argument_parameter(param_name: str, param_type: Optional[type[Any]]) -> None:
|
632
|
+
"""Register a custom argparse argument parameter.
|
657
633
|
|
658
634
|
The registered name will then be a recognized keyword parameter to the parser's `add_argument()` function.
|
659
635
|
|
@@ -672,15 +648,14 @@ def register_argparse_argument_parameter(param_name: str, param_type: Optional[T
|
|
672
648
|
getter_name = f'get_{param_name}'
|
673
649
|
|
674
650
|
def _action_get_custom_parameter(self: argparse.Action) -> Any:
|
675
|
-
|
676
|
-
Get the custom {param_name} attribute of an argparse Action.
|
651
|
+
"""Get the custom attribute of an argparse Action.
|
677
652
|
|
678
|
-
This function is added by cmd2 as a method called ``
|
653
|
+
This function is added by cmd2 as a method called ``get_<param_name>()`` to ``argparse.Action`` class.
|
679
654
|
|
680
|
-
To call: ``action.
|
655
|
+
To call: ``action.get_<param_name>()``
|
681
656
|
|
682
657
|
:param self: argparse Action being queried
|
683
|
-
:return: The value of
|
658
|
+
:return: The value of the custom attribute or None if attribute does not exist
|
684
659
|
"""
|
685
660
|
return getattr(self, attr_name, None)
|
686
661
|
|
@@ -689,12 +664,11 @@ def register_argparse_argument_parameter(param_name: str, param_type: Optional[T
|
|
689
664
|
setter_name = f'set_{param_name}'
|
690
665
|
|
691
666
|
def _action_set_custom_parameter(self: argparse.Action, value: Any) -> None:
|
692
|
-
|
693
|
-
Set the custom {param_name} attribute of an argparse Action.
|
667
|
+
"""Set the custom attribute of an argparse Action.
|
694
668
|
|
695
|
-
This function is added by cmd2 as a method called ``
|
669
|
+
This function is added by cmd2 as a method called ``set_<param_name>()`` to ``argparse.Action`` class.
|
696
670
|
|
697
|
-
To call: ``action.
|
671
|
+
To call: ``action.set_<param_name>(<param_value>)``
|
698
672
|
|
699
673
|
:param self: argparse Action being updated
|
700
674
|
:param value: value being assigned
|
@@ -720,15 +694,14 @@ orig_actions_container_add_argument = argparse._ActionsContainer.add_argument
|
|
720
694
|
def _add_argument_wrapper(
|
721
695
|
self: argparse._ActionsContainer,
|
722
696
|
*args: Any,
|
723
|
-
nargs: Union[int, str,
|
697
|
+
nargs: Union[int, str, tuple[int], tuple[int, int], tuple[int, float], None] = None,
|
724
698
|
choices_provider: Optional[ChoicesProviderFunc] = None,
|
725
699
|
completer: Optional[CompleterFunc] = None,
|
726
700
|
suppress_tab_hint: bool = False,
|
727
701
|
descriptive_header: Optional[str] = None,
|
728
702
|
**kwargs: Any,
|
729
703
|
) -> argparse.Action:
|
730
|
-
"""
|
731
|
-
Wrapper around _ActionsContainer.add_argument() which supports more settings used by cmd2
|
704
|
+
"""Wrap ActionsContainer.add_argument() which supports more settings used by cmd2.
|
732
705
|
|
733
706
|
# Args from original function
|
734
707
|
:param self: instance of the _ActionsContainer being added to
|
@@ -771,7 +744,7 @@ def _add_argument_wrapper(
|
|
771
744
|
nargs_range = None
|
772
745
|
|
773
746
|
if nargs is not None:
|
774
|
-
nargs_adjusted: Union[int, str,
|
747
|
+
nargs_adjusted: Union[int, str, tuple[int], tuple[int, int], tuple[int, float], None]
|
775
748
|
# Check if nargs was given as a range
|
776
749
|
if isinstance(nargs, tuple):
|
777
750
|
# Handle 1-item tuple by setting max to INFINITY
|
@@ -821,10 +794,7 @@ def _add_argument_wrapper(
|
|
821
794
|
kwargs['nargs'] = nargs_adjusted
|
822
795
|
|
823
796
|
# Extract registered custom keyword arguments
|
824
|
-
custom_attribs:
|
825
|
-
for keyword, value in kwargs.items():
|
826
|
-
if keyword in CUSTOM_ACTION_ATTRIBS:
|
827
|
-
custom_attribs[keyword] = value
|
797
|
+
custom_attribs = {keyword: value for keyword, value in kwargs.items() if keyword in CUSTOM_ACTION_ATTRIBS}
|
828
798
|
for keyword in custom_attribs:
|
829
799
|
del kwargs[keyword]
|
830
800
|
|
@@ -864,12 +834,8 @@ orig_argument_parser_get_nargs_pattern = argparse.ArgumentParser._get_nargs_patt
|
|
864
834
|
def _get_nargs_pattern_wrapper(self: argparse.ArgumentParser, action: argparse.Action) -> str:
|
865
835
|
# Wrapper around ArgumentParser._get_nargs_pattern behavior to support nargs ranges
|
866
836
|
nargs_range = action.get_nargs_range() # type: ignore[attr-defined]
|
867
|
-
if nargs_range
|
868
|
-
if nargs_range[1] == constants.INFINITY
|
869
|
-
range_max = ''
|
870
|
-
else:
|
871
|
-
range_max = nargs_range[1] # type: ignore[assignment]
|
872
|
-
|
837
|
+
if nargs_range:
|
838
|
+
range_max = '' if nargs_range[1] == constants.INFINITY else nargs_range[1]
|
873
839
|
nargs_pattern = f'(-*A{{{nargs_range[0]},{range_max}}}-*)'
|
874
840
|
|
875
841
|
# if this is an optional action, -- is not allowed
|
@@ -919,9 +885,8 @@ setattr(argparse.ArgumentParser, '_match_argument', _match_argument_wrapper)
|
|
919
885
|
ATTR_AP_COMPLETER_TYPE = 'ap_completer_type'
|
920
886
|
|
921
887
|
|
922
|
-
def _ArgumentParser_get_ap_completer_type(self: argparse.ArgumentParser) -> Optional[
|
923
|
-
"""
|
924
|
-
Get the ap_completer_type attribute of an argparse ArgumentParser.
|
888
|
+
def _ArgumentParser_get_ap_completer_type(self: argparse.ArgumentParser) -> Optional[type['ArgparseCompleter']]: # noqa: N802
|
889
|
+
"""Get the ap_completer_type attribute of an argparse ArgumentParser.
|
925
890
|
|
926
891
|
This function is added by cmd2 as a method called ``get_ap_completer_type()`` to ``argparse.ArgumentParser`` class.
|
927
892
|
|
@@ -930,15 +895,14 @@ def _ArgumentParser_get_ap_completer_type(self: argparse.ArgumentParser) -> Opti
|
|
930
895
|
:param self: ArgumentParser being queried
|
931
896
|
:return: An ArgparseCompleter-based class or None if attribute does not exist
|
932
897
|
"""
|
933
|
-
return cast(Optional[
|
898
|
+
return cast(Optional[type['ArgparseCompleter']], getattr(self, ATTR_AP_COMPLETER_TYPE, None))
|
934
899
|
|
935
900
|
|
936
901
|
setattr(argparse.ArgumentParser, 'get_ap_completer_type', _ArgumentParser_get_ap_completer_type)
|
937
902
|
|
938
903
|
|
939
|
-
def _ArgumentParser_set_ap_completer_type(self: argparse.ArgumentParser, ap_completer_type:
|
940
|
-
"""
|
941
|
-
Set the ap_completer_type attribute of an argparse ArgumentParser.
|
904
|
+
def _ArgumentParser_set_ap_completer_type(self: argparse.ArgumentParser, ap_completer_type: type['ArgparseCompleter']) -> None: # noqa: N802
|
905
|
+
"""Set the ap_completer_type attribute of an argparse ArgumentParser.
|
942
906
|
|
943
907
|
This function is added by cmd2 as a method called ``set_ap_completer_type()`` to ``argparse.ArgumentParser`` class.
|
944
908
|
|
@@ -956,9 +920,9 @@ setattr(argparse.ArgumentParser, 'set_ap_completer_type', _ArgumentParser_set_ap
|
|
956
920
|
############################################################################################################
|
957
921
|
# Patch ArgumentParser._check_value to support CompletionItems as choices
|
958
922
|
############################################################################################################
|
959
|
-
def _ArgumentParser_check_value(
|
960
|
-
"""
|
961
|
-
|
923
|
+
def _ArgumentParser_check_value(_self: argparse.ArgumentParser, action: argparse.Action, value: Any) -> None: # noqa: N802
|
924
|
+
"""Check_value that supports CompletionItems as choices (Custom override of ArgumentParser._check_value).
|
925
|
+
|
962
926
|
When evaluating choices, input is compared to CompletionItem.orig_value instead of the
|
963
927
|
CompletionItem instance.
|
964
928
|
|
@@ -989,9 +953,8 @@ setattr(argparse.ArgumentParser, '_check_value', _ArgumentParser_check_value)
|
|
989
953
|
############################################################################################################
|
990
954
|
|
991
955
|
|
992
|
-
def _SubParsersAction_remove_parser(self: argparse._SubParsersAction, name: str) -> None: # type: ignore
|
993
|
-
"""
|
994
|
-
Removes a sub-parser from a sub-parsers group. Used to remove subcommands from a parser.
|
956
|
+
def _SubParsersAction_remove_parser(self: argparse._SubParsersAction, name: str) -> None: # type: ignore[type-arg] # noqa: N802
|
957
|
+
"""Remove a sub-parser from a sub-parsers group. Used to remove subcommands from a parser.
|
995
958
|
|
996
959
|
This function is added by cmd2 as a method called ``remove_parser()`` to ``argparse._SubParsersAction`` class.
|
997
960
|
|
@@ -1029,7 +992,7 @@ setattr(argparse._SubParsersAction, 'remove_parser', _SubParsersAction_remove_pa
|
|
1029
992
|
|
1030
993
|
|
1031
994
|
class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
1032
|
-
"""Custom help formatter to configure ordering of help text"""
|
995
|
+
"""Custom help formatter to configure ordering of help text."""
|
1033
996
|
|
1034
997
|
def _format_usage(
|
1035
998
|
self,
|
@@ -1043,15 +1006,15 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1043
1006
|
|
1044
1007
|
# if usage is specified, use that
|
1045
1008
|
if usage is not None:
|
1046
|
-
usage %=
|
1009
|
+
usage %= {"prog": self._prog}
|
1047
1010
|
|
1048
1011
|
# if no optionals or positionals are available, usage is just prog
|
1049
1012
|
elif not actions:
|
1050
|
-
usage = '
|
1013
|
+
usage = f'{self._prog}'
|
1051
1014
|
|
1052
1015
|
# if optionals and positionals are available, calculate usage
|
1053
1016
|
else:
|
1054
|
-
prog = '
|
1017
|
+
prog = f'{self._prog}'
|
1055
1018
|
|
1056
1019
|
# split optionals from positionals
|
1057
1020
|
optionals = []
|
@@ -1069,8 +1032,8 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1069
1032
|
# End cmd2 customization
|
1070
1033
|
|
1071
1034
|
# build full usage string
|
1072
|
-
|
1073
|
-
action_usage =
|
1035
|
+
format_actions = self._format_actions_usage
|
1036
|
+
action_usage = format_actions(required_options + optionals + positionals, groups) # type: ignore[arg-type]
|
1074
1037
|
usage = ' '.join([s for s in [prog, action_usage] if s])
|
1075
1038
|
|
1076
1039
|
# wrap the usage parts if it's too long
|
@@ -1080,26 +1043,20 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1080
1043
|
|
1081
1044
|
# break usage into wrappable parts
|
1082
1045
|
part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
|
1083
|
-
req_usage =
|
1084
|
-
opt_usage =
|
1085
|
-
pos_usage =
|
1046
|
+
req_usage = format_actions(required_options, groups) # type: ignore[arg-type]
|
1047
|
+
opt_usage = format_actions(optionals, groups) # type: ignore[arg-type]
|
1048
|
+
pos_usage = format_actions(positionals, groups) # type: ignore[arg-type]
|
1086
1049
|
req_parts = re.findall(part_regexp, req_usage)
|
1087
1050
|
opt_parts = re.findall(part_regexp, opt_usage)
|
1088
1051
|
pos_parts = re.findall(part_regexp, pos_usage)
|
1089
|
-
assert ' '.join(req_parts) == req_usage
|
1090
|
-
assert ' '.join(opt_parts) == opt_usage
|
1091
|
-
assert ' '.join(pos_parts) == pos_usage
|
1092
1052
|
|
1093
1053
|
# End cmd2 customization
|
1094
1054
|
|
1095
1055
|
# helper for wrapping lines
|
1096
|
-
def get_lines(parts:
|
1097
|
-
lines:
|
1098
|
-
line:
|
1099
|
-
if prefix is not None
|
1100
|
-
line_len = len(prefix) - 1
|
1101
|
-
else:
|
1102
|
-
line_len = len(indent) - 1
|
1056
|
+
def get_lines(parts: list[str], indent: str, prefix: Optional[str] = None) -> list[str]:
|
1057
|
+
lines: list[str] = []
|
1058
|
+
line: list[str] = []
|
1059
|
+
line_len = len(prefix) - 1 if prefix is not None else len(indent) - 1
|
1103
1060
|
for part in parts:
|
1104
1061
|
if line_len + 1 + len(part) > text_width and line:
|
1105
1062
|
lines.append(indent + ' '.join(line))
|
@@ -1118,14 +1075,14 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1118
1075
|
indent = ' ' * (len(prefix) + len(prog) + 1)
|
1119
1076
|
# Begin cmd2 customization
|
1120
1077
|
if req_parts:
|
1121
|
-
lines = get_lines([prog
|
1078
|
+
lines = get_lines([prog, *req_parts], indent, prefix)
|
1122
1079
|
lines.extend(get_lines(opt_parts, indent))
|
1123
1080
|
lines.extend(get_lines(pos_parts, indent))
|
1124
1081
|
elif opt_parts:
|
1125
|
-
lines = get_lines([prog
|
1082
|
+
lines = get_lines([prog, *opt_parts], indent, prefix)
|
1126
1083
|
lines.extend(get_lines(pos_parts, indent))
|
1127
1084
|
elif pos_parts:
|
1128
|
-
lines = get_lines([prog
|
1085
|
+
lines = get_lines([prog, *pos_parts], indent, prefix)
|
1129
1086
|
else:
|
1130
1087
|
lines = [prog]
|
1131
1088
|
# End cmd2 customization
|
@@ -1142,13 +1099,13 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1142
1099
|
lines.extend(get_lines(opt_parts, indent))
|
1143
1100
|
lines.extend(get_lines(pos_parts, indent))
|
1144
1101
|
# End cmd2 customization
|
1145
|
-
lines = [prog
|
1102
|
+
lines = [prog, *lines]
|
1146
1103
|
|
1147
1104
|
# join lines into usage
|
1148
1105
|
usage = '\n'.join(lines)
|
1149
1106
|
|
1150
1107
|
# prefix with 'Usage:'
|
1151
|
-
return '
|
1108
|
+
return f'{prefix}{usage}\n\n'
|
1152
1109
|
|
1153
1110
|
def _format_action_invocation(self, action: argparse.Action) -> str:
|
1154
1111
|
if not action.option_strings:
|
@@ -1156,37 +1113,35 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1156
1113
|
(metavar,) = self._metavar_formatter(action, default)(1)
|
1157
1114
|
return metavar
|
1158
1115
|
|
1159
|
-
|
1160
|
-
parts: List[str] = []
|
1116
|
+
parts: list[str] = []
|
1161
1117
|
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1118
|
+
# if the Optional doesn't take a value, format is:
|
1119
|
+
# -s, --long
|
1120
|
+
if action.nargs == 0:
|
1121
|
+
parts.extend(action.option_strings)
|
1122
|
+
return ', '.join(parts)
|
1167
1123
|
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
args_string = self._format_args(action, default)
|
1124
|
+
# Begin cmd2 customization (less verbose)
|
1125
|
+
# if the Optional takes a value, format is:
|
1126
|
+
# -s, --long ARGS
|
1127
|
+
default = self._get_default_metavar_for_optional(action)
|
1128
|
+
args_string = self._format_args(action, default)
|
1174
1129
|
|
1175
|
-
|
1176
|
-
|
1130
|
+
return ', '.join(action.option_strings) + ' ' + args_string
|
1131
|
+
# End cmd2 customization
|
1177
1132
|
|
1178
1133
|
def _determine_metavar(
|
1179
1134
|
self,
|
1180
1135
|
action: argparse.Action,
|
1181
|
-
default_metavar: Union[str,
|
1182
|
-
) -> Union[str,
|
1183
|
-
"""
|
1136
|
+
default_metavar: Union[str, tuple[str, ...]],
|
1137
|
+
) -> Union[str, tuple[str, ...]]:
|
1138
|
+
"""Determine what to use as the metavar value of an action."""
|
1184
1139
|
if action.metavar is not None:
|
1185
1140
|
result = action.metavar
|
1186
1141
|
elif action.choices is not None:
|
1187
1142
|
choice_strs = [str(choice) for choice in action.choices]
|
1188
1143
|
# Begin cmd2 customization (added space after comma)
|
1189
|
-
result = '{
|
1144
|
+
result = f'{", ".join(choice_strs)}'
|
1190
1145
|
# End cmd2 customization
|
1191
1146
|
else:
|
1192
1147
|
result = default_metavar
|
@@ -1195,48 +1150,44 @@ class Cmd2HelpFormatter(argparse.RawTextHelpFormatter):
|
|
1195
1150
|
def _metavar_formatter(
|
1196
1151
|
self,
|
1197
1152
|
action: argparse.Action,
|
1198
|
-
default_metavar: Union[str,
|
1199
|
-
) -> Callable[[int],
|
1153
|
+
default_metavar: Union[str, tuple[str, ...]],
|
1154
|
+
) -> Callable[[int], tuple[str, ...]]:
|
1200
1155
|
metavar = self._determine_metavar(action, default_metavar)
|
1201
1156
|
|
1202
|
-
def
|
1157
|
+
def format_tuple(tuple_size: int) -> tuple[str, ...]:
|
1203
1158
|
if isinstance(metavar, tuple):
|
1204
1159
|
return metavar
|
1205
|
-
|
1206
|
-
return (metavar,) * tuple_size
|
1160
|
+
return (metavar,) * tuple_size
|
1207
1161
|
|
1208
|
-
return
|
1162
|
+
return format_tuple
|
1209
1163
|
|
1210
|
-
def _format_args(self, action: argparse.Action, default_metavar: Union[str,
|
1211
|
-
"""
|
1164
|
+
def _format_args(self, action: argparse.Action, default_metavar: Union[str, tuple[str, ...]]) -> str:
|
1165
|
+
"""Handle ranged nargs and make other output less verbose."""
|
1212
1166
|
metavar = self._determine_metavar(action, default_metavar)
|
1213
1167
|
metavar_formatter = self._metavar_formatter(action, default_metavar)
|
1214
1168
|
|
1215
1169
|
# Handle nargs specified as a range
|
1216
1170
|
nargs_range = action.get_nargs_range() # type: ignore[attr-defined]
|
1217
1171
|
if nargs_range is not None:
|
1218
|
-
if nargs_range[1] == constants.INFINITY
|
1219
|
-
range_str = f'{nargs_range[0]}+'
|
1220
|
-
else:
|
1221
|
-
range_str = f'{nargs_range[0]}..{nargs_range[1]}'
|
1172
|
+
range_str = f'{nargs_range[0]}+' if nargs_range[1] == constants.INFINITY else f'{nargs_range[0]}..{nargs_range[1]}'
|
1222
1173
|
|
1223
|
-
return '{}{{{}}}'.format('%s' % metavar_formatter(1), range_str)
|
1174
|
+
return '{}{{{}}}'.format('%s' % metavar_formatter(1), range_str) # noqa: UP031
|
1224
1175
|
|
1225
1176
|
# Make this output less verbose. Do not customize the output when metavar is a
|
1226
1177
|
# tuple of strings. Allow argparse's formatter to handle that instead.
|
1227
|
-
|
1178
|
+
if isinstance(metavar, str):
|
1228
1179
|
if action.nargs == ZERO_OR_MORE:
|
1229
|
-
return '[%s [...]]' % metavar_formatter(1)
|
1230
|
-
|
1231
|
-
return '%s [...]' % metavar_formatter(1)
|
1232
|
-
|
1233
|
-
return '{}{{{}}}'.format('%s' % metavar_formatter(1), action.nargs)
|
1180
|
+
return '[%s [...]]' % metavar_formatter(1) # noqa: UP031
|
1181
|
+
if action.nargs == ONE_OR_MORE:
|
1182
|
+
return '%s [...]' % metavar_formatter(1) # noqa: UP031
|
1183
|
+
if isinstance(action.nargs, int) and action.nargs > 1:
|
1184
|
+
return '{}{{{}}}'.format('%s' % metavar_formatter(1), action.nargs) # noqa: UP031
|
1234
1185
|
|
1235
1186
|
return super()._format_args(action, default_metavar) # type: ignore[arg-type]
|
1236
1187
|
|
1237
1188
|
|
1238
1189
|
class Cmd2ArgumentParser(argparse.ArgumentParser):
|
1239
|
-
"""Custom ArgumentParser class that improves error and help output"""
|
1190
|
+
"""Custom ArgumentParser class that improves error and help output."""
|
1240
1191
|
|
1241
1192
|
def __init__(
|
1242
1193
|
self,
|
@@ -1245,43 +1196,68 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
1245
1196
|
description: Optional[str] = None,
|
1246
1197
|
epilog: Optional[str] = None,
|
1247
1198
|
parents: Sequence[argparse.ArgumentParser] = (),
|
1248
|
-
formatter_class:
|
1199
|
+
formatter_class: type[argparse.HelpFormatter] = Cmd2HelpFormatter,
|
1249
1200
|
prefix_chars: str = '-',
|
1250
1201
|
fromfile_prefix_chars: Optional[str] = None,
|
1251
1202
|
argument_default: Optional[str] = None,
|
1252
1203
|
conflict_handler: str = 'error',
|
1253
1204
|
add_help: bool = True,
|
1254
1205
|
allow_abbrev: bool = True,
|
1206
|
+
exit_on_error: bool = True,
|
1207
|
+
suggest_on_error: bool = False,
|
1208
|
+
color: bool = False,
|
1255
1209
|
*,
|
1256
|
-
ap_completer_type: Optional[
|
1210
|
+
ap_completer_type: Optional[type['ArgparseCompleter']] = None,
|
1257
1211
|
) -> None:
|
1258
|
-
"""
|
1259
|
-
# Custom parameter added by cmd2
|
1212
|
+
"""Initialize the Cmd2ArgumentParser instance, a custom ArgumentParser added by cmd2.
|
1260
1213
|
|
1261
1214
|
:param ap_completer_type: optional parameter which specifies a subclass of ArgparseCompleter for custom tab completion
|
1262
1215
|
behavior on this parser. If this is None or not present, then cmd2 will use
|
1263
1216
|
argparse_completer.DEFAULT_AP_COMPLETER when tab completing this parser's arguments
|
1264
1217
|
"""
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1218
|
+
if sys.version_info >= (3, 14):
|
1219
|
+
# Python >= 3.14 so pass new arguments to parent argparse.ArgumentParser class
|
1220
|
+
super().__init__(
|
1221
|
+
prog=prog,
|
1222
|
+
usage=usage,
|
1223
|
+
description=description,
|
1224
|
+
epilog=epilog,
|
1225
|
+
parents=parents if parents else [],
|
1226
|
+
formatter_class=formatter_class, # type: ignore[arg-type]
|
1227
|
+
prefix_chars=prefix_chars,
|
1228
|
+
fromfile_prefix_chars=fromfile_prefix_chars,
|
1229
|
+
argument_default=argument_default,
|
1230
|
+
conflict_handler=conflict_handler,
|
1231
|
+
add_help=add_help,
|
1232
|
+
allow_abbrev=allow_abbrev,
|
1233
|
+
exit_on_error=exit_on_error, # added in Python 3.9
|
1234
|
+
suggest_on_error=suggest_on_error, # added in Python 3.14
|
1235
|
+
color=color, # added in Python 3.14
|
1236
|
+
)
|
1237
|
+
else:
|
1238
|
+
# Python < 3.14, so don't pass new arguments to parent argparse.ArgumentParser class
|
1239
|
+
super().__init__(
|
1240
|
+
prog=prog,
|
1241
|
+
usage=usage,
|
1242
|
+
description=description,
|
1243
|
+
epilog=epilog,
|
1244
|
+
parents=parents if parents else [],
|
1245
|
+
formatter_class=formatter_class, # type: ignore[arg-type]
|
1246
|
+
prefix_chars=prefix_chars,
|
1247
|
+
fromfile_prefix_chars=fromfile_prefix_chars,
|
1248
|
+
argument_default=argument_default,
|
1249
|
+
conflict_handler=conflict_handler,
|
1250
|
+
add_help=add_help,
|
1251
|
+
allow_abbrev=allow_abbrev,
|
1252
|
+
exit_on_error=exit_on_error, # added in Python 3.9
|
1253
|
+
)
|
1279
1254
|
|
1280
1255
|
self.set_ap_completer_type(ap_completer_type) # type: ignore[attr-defined]
|
1281
1256
|
|
1282
|
-
def add_subparsers(self, **kwargs: Any) -> argparse._SubParsersAction: # type: ignore
|
1283
|
-
"""
|
1284
|
-
|
1257
|
+
def add_subparsers(self, **kwargs: Any) -> argparse._SubParsersAction: # type: ignore[type-arg]
|
1258
|
+
"""Add a subcommand parser.
|
1259
|
+
|
1260
|
+
Set a default title if one was not given.f
|
1285
1261
|
|
1286
1262
|
:param kwargs: additional keyword arguments
|
1287
1263
|
:return: argparse Subparser Action
|
@@ -1292,23 +1268,27 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
1292
1268
|
return super().add_subparsers(**kwargs)
|
1293
1269
|
|
1294
1270
|
def error(self, message: str) -> NoReturn:
|
1295
|
-
"""
|
1271
|
+
"""Print a usage message, including the message, to sys.stderr and terminates the program with a status code of 2.
|
1272
|
+
|
1273
|
+
Custom override that applies custom formatting to the error message.
|
1274
|
+
"""
|
1296
1275
|
lines = message.split('\n')
|
1297
|
-
linum = 0
|
1298
1276
|
formatted_message = ''
|
1299
|
-
for line in lines:
|
1277
|
+
for linum, line in enumerate(lines):
|
1300
1278
|
if linum == 0:
|
1301
1279
|
formatted_message = 'Error: ' + line
|
1302
1280
|
else:
|
1303
1281
|
formatted_message += '\n ' + line
|
1304
|
-
linum += 1
|
1305
1282
|
|
1306
1283
|
self.print_usage(sys.stderr)
|
1307
1284
|
formatted_message = ansi.style_error(formatted_message)
|
1308
1285
|
self.exit(2, f'{formatted_message}\n\n')
|
1309
1286
|
|
1310
1287
|
def format_help(self) -> str:
|
1311
|
-
"""
|
1288
|
+
"""Return a string containing a help message, including the program usage and information about the arguments.
|
1289
|
+
|
1290
|
+
Copy of format_help() from argparse.ArgumentParser with tweaks to separately display required parameters.
|
1291
|
+
"""
|
1312
1292
|
formatter = self._get_formatter()
|
1313
1293
|
|
1314
1294
|
# usage
|
@@ -1361,7 +1341,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
1361
1341
|
# determine help from format above
|
1362
1342
|
return formatter.format_help() + '\n'
|
1363
1343
|
|
1364
|
-
def _print_message(self, message: str, file: Optional[IO[str]] = None) -> None:
|
1344
|
+
def _print_message(self, message: str, file: Optional[IO[str]] = None) -> None: # type: ignore[override]
|
1365
1345
|
# Override _print_message to use style_aware_write() since we use ANSI escape characters to support color
|
1366
1346
|
if message:
|
1367
1347
|
if file is None:
|
@@ -1370,32 +1350,34 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
|
|
1370
1350
|
|
1371
1351
|
|
1372
1352
|
class Cmd2AttributeWrapper:
|
1373
|
-
"""
|
1374
|
-
|
1353
|
+
"""Wraps a cmd2-specific attribute added to an argparse Namespace.
|
1354
|
+
|
1375
1355
|
This makes it easy to know which attributes in a Namespace are
|
1376
1356
|
arguments from a parser and which were added by cmd2.
|
1377
1357
|
"""
|
1378
1358
|
|
1379
1359
|
def __init__(self, attribute: Any) -> None:
|
1360
|
+
"""Initialize Cmd2AttributeWrapper instances."""
|
1380
1361
|
self.__attribute = attribute
|
1381
1362
|
|
1382
1363
|
def get(self) -> Any:
|
1383
|
-
"""Get the value of the attribute"""
|
1364
|
+
"""Get the value of the attribute."""
|
1384
1365
|
return self.__attribute
|
1385
1366
|
|
1386
1367
|
def set(self, new_val: Any) -> None:
|
1387
|
-
"""Set the value of the attribute"""
|
1368
|
+
"""Set the value of the attribute."""
|
1388
1369
|
self.__attribute = new_val
|
1389
1370
|
|
1390
1371
|
|
1391
1372
|
# The default ArgumentParser class for a cmd2 app
|
1392
|
-
DEFAULT_ARGUMENT_PARSER:
|
1373
|
+
DEFAULT_ARGUMENT_PARSER: type[argparse.ArgumentParser] = Cmd2ArgumentParser
|
1393
1374
|
|
1394
1375
|
|
1395
|
-
def set_default_argument_parser_type(parser_type:
|
1396
|
-
"""
|
1397
|
-
|
1398
|
-
you want to override the parser for cmd2's built-in commands.
|
1376
|
+
def set_default_argument_parser_type(parser_type: type[argparse.ArgumentParser]) -> None:
|
1377
|
+
"""Set the default ArgumentParser class for a cmd2 app.
|
1378
|
+
|
1379
|
+
This must be called prior to loading cmd2.py if you want to override the parser for cmd2's built-in commands.
|
1380
|
+
See examples/override_parser.py.
|
1399
1381
|
"""
|
1400
|
-
global DEFAULT_ARGUMENT_PARSER
|
1382
|
+
global DEFAULT_ARGUMENT_PARSER # noqa: PLW0603
|
1401
1383
|
DEFAULT_ARGUMENT_PARSER = parser_type
|