cmd2 2.6.0__py3-none-any.whl → 2.6.2__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/cmd2.py +71 -59
- cmd2/decorators.py +8 -0
- cmd2/utils.py +30 -23
- {cmd2-2.6.0.dist-info → cmd2-2.6.2.dist-info}/METADATA +45 -37
- {cmd2-2.6.0.dist-info → cmd2-2.6.2.dist-info}/RECORD +8 -8
- {cmd2-2.6.0.dist-info → cmd2-2.6.2.dist-info}/licenses/LICENSE +1 -1
- {cmd2-2.6.0.dist-info → cmd2-2.6.2.dist-info}/WHEEL +0 -0
- {cmd2-2.6.0.dist-info → cmd2-2.6.2.dist-info}/top_level.txt +0 -0
cmd2/cmd2.py
CHANGED
@@ -144,6 +144,7 @@ from .table_creator import (
|
|
144
144
|
from .utils import (
|
145
145
|
Settable,
|
146
146
|
get_defining_class,
|
147
|
+
get_types,
|
147
148
|
strip_doc_annotations,
|
148
149
|
suggest_similar,
|
149
150
|
)
|
@@ -253,17 +254,11 @@ class _CommandParsers:
|
|
253
254
|
command = command_method.__name__[len(COMMAND_FUNC_PREFIX) :]
|
254
255
|
|
255
256
|
parser_builder = getattr(command_method, constants.CMD_ATTR_ARGPARSER, None)
|
256
|
-
|
257
|
-
parser = self._cmd._build_parser(parent, parser_builder)
|
258
|
-
if parser is None:
|
257
|
+
if parser_builder is None:
|
259
258
|
return None
|
260
259
|
|
261
|
-
|
262
|
-
|
263
|
-
_set_parser_prog,
|
264
|
-
)
|
265
|
-
|
266
|
-
_set_parser_prog(parser, command)
|
260
|
+
parent = self._cmd.find_commandset_for_command(command) or self._cmd
|
261
|
+
parser = self._cmd._build_parser(parent, parser_builder, command)
|
267
262
|
|
268
263
|
# If the description has not been set, then use the method docstring if one exists
|
269
264
|
if parser.description is None and hasattr(command_method, '__wrapped__') and command_method.__wrapped__.__doc__:
|
@@ -757,24 +752,41 @@ class Cmd(cmd.Cmd):
|
|
757
752
|
def _build_parser(
|
758
753
|
self,
|
759
754
|
parent: CommandParent,
|
760
|
-
parser_builder:
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
ClassArgParseBuilder,
|
766
|
-
]
|
755
|
+
parser_builder: Union[
|
756
|
+
argparse.ArgumentParser,
|
757
|
+
Callable[[], argparse.ArgumentParser],
|
758
|
+
StaticArgParseBuilder,
|
759
|
+
ClassArgParseBuilder,
|
767
760
|
],
|
768
|
-
|
769
|
-
|
761
|
+
prog: str,
|
762
|
+
) -> argparse.ArgumentParser:
|
763
|
+
"""Build argument parser for a command/subcommand.
|
764
|
+
|
765
|
+
:param parent: CommandParent object which owns the command using the parser.
|
766
|
+
This function assumes that parent is where parser_builder
|
767
|
+
is defined when parser_builder is a classmethod.
|
768
|
+
:param parser_builder: means used to build the parser
|
769
|
+
:param prog: prog value to set in new parser
|
770
|
+
:return: new parser
|
771
|
+
:raises TypeError: if parser_builder is invalid type
|
772
|
+
"""
|
770
773
|
if isinstance(parser_builder, staticmethod):
|
771
774
|
parser = parser_builder.__func__()
|
772
775
|
elif isinstance(parser_builder, classmethod):
|
773
|
-
parser = parser_builder.__func__(parent
|
776
|
+
parser = parser_builder.__func__(parent.__class__)
|
774
777
|
elif callable(parser_builder):
|
775
778
|
parser = parser_builder()
|
776
779
|
elif isinstance(parser_builder, argparse.ArgumentParser):
|
777
780
|
parser = copy.deepcopy(parser_builder)
|
781
|
+
else:
|
782
|
+
raise TypeError(f"Invalid type for parser_builder: {type(parser_builder)}")
|
783
|
+
|
784
|
+
from .decorators import (
|
785
|
+
_set_parser_prog,
|
786
|
+
)
|
787
|
+
|
788
|
+
_set_parser_prog(parser, prog)
|
789
|
+
|
778
790
|
return parser
|
779
791
|
|
780
792
|
def _install_command_function(self, command_func_name: str, command_method: CommandFunc, context: str = '') -> None:
|
@@ -962,12 +974,7 @@ class Cmd(cmd.Cmd):
|
|
962
974
|
|
963
975
|
target_parser = find_subcommand(command_parser, subcommand_names)
|
964
976
|
|
965
|
-
subcmd_parser =
|
966
|
-
from .decorators import (
|
967
|
-
_set_parser_prog,
|
968
|
-
)
|
969
|
-
|
970
|
-
_set_parser_prog(subcmd_parser, f'{command_name} {subcommand_name}')
|
977
|
+
subcmd_parser = self._build_parser(cmdset, subcmd_parser_builder, f'{command_name} {subcommand_name}')
|
971
978
|
if subcmd_parser.description is None and method.__doc__:
|
972
979
|
subcmd_parser.description = strip_doc_annotations(method.__doc__)
|
973
980
|
|
@@ -2609,7 +2616,7 @@ class Cmd(cmd.Cmd):
|
|
2609
2616
|
# caused by certain binary characters having been printed to it.
|
2610
2617
|
import subprocess
|
2611
2618
|
|
2612
|
-
proc = subprocess.Popen(['stty', 'sane']) # noqa:
|
2619
|
+
proc = subprocess.Popen(['stty', 'sane']) # noqa: S607
|
2613
2620
|
proc.communicate()
|
2614
2621
|
|
2615
2622
|
data = plugin.CommandFinalizationData(stop, statement)
|
@@ -3597,8 +3604,8 @@ class Cmd(cmd.Cmd):
|
|
3597
3604
|
max_arg_num = 0
|
3598
3605
|
arg_nums = set()
|
3599
3606
|
|
3600
|
-
|
3601
|
-
|
3607
|
+
try:
|
3608
|
+
while True:
|
3602
3609
|
cur_match = normal_matches.__next__()
|
3603
3610
|
|
3604
3611
|
# Get the number string between the braces
|
@@ -3612,9 +3619,8 @@ class Cmd(cmd.Cmd):
|
|
3612
3619
|
max_arg_num = max(max_arg_num, cur_num)
|
3613
3620
|
|
3614
3621
|
arg_list.append(MacroArg(start_index=cur_match.start(), number_str=cur_num_str, is_escaped=False))
|
3615
|
-
|
3616
|
-
|
3617
|
-
break
|
3622
|
+
except StopIteration:
|
3623
|
+
pass
|
3618
3624
|
|
3619
3625
|
# Make sure the argument numbers are continuous
|
3620
3626
|
if len(arg_nums) != max_arg_num:
|
@@ -3624,16 +3630,16 @@ class Cmd(cmd.Cmd):
|
|
3624
3630
|
# Find all escaped arguments
|
3625
3631
|
escaped_matches = re.finditer(MacroArg.macro_escaped_arg_pattern, value)
|
3626
3632
|
|
3627
|
-
|
3628
|
-
|
3633
|
+
try:
|
3634
|
+
while True:
|
3629
3635
|
cur_match = escaped_matches.__next__()
|
3630
3636
|
|
3631
3637
|
# Get the number string between the braces
|
3632
3638
|
cur_num_str = re.findall(MacroArg.digit_pattern, cur_match.group())[0]
|
3633
3639
|
|
3634
3640
|
arg_list.append(MacroArg(start_index=cur_match.start(), number_str=cur_num_str, is_escaped=True))
|
3635
|
-
|
3636
|
-
|
3641
|
+
except StopIteration:
|
3642
|
+
pass
|
3637
3643
|
|
3638
3644
|
# Set the macro
|
3639
3645
|
result = "overwritten" if args.name in self.macros else "created"
|
@@ -5545,10 +5551,10 @@ class Cmd(cmd.Cmd):
|
|
5545
5551
|
def _validate_prepostloop_callable(cls, func: Callable[[], None]) -> None:
|
5546
5552
|
"""Check parameter and return types for preloop and postloop hooks."""
|
5547
5553
|
cls._validate_callable_param_count(func, 0)
|
5548
|
-
# make sure there is no return
|
5549
|
-
|
5550
|
-
if
|
5551
|
-
raise TypeError(f"{func.__name__} must
|
5554
|
+
# make sure there is no return annotation or the return is specified as None
|
5555
|
+
_, ret_ann = get_types(func)
|
5556
|
+
if ret_ann is not None:
|
5557
|
+
raise TypeError(f"{func.__name__} must have a return type of 'None', got: {ret_ann}")
|
5552
5558
|
|
5553
5559
|
def register_preloop_hook(self, func: Callable[[], None]) -> None:
|
5554
5560
|
"""Register a function to be called at the beginning of the command loop."""
|
@@ -5564,11 +5570,13 @@ class Cmd(cmd.Cmd):
|
|
5564
5570
|
def _validate_postparsing_callable(cls, func: Callable[[plugin.PostparsingData], plugin.PostparsingData]) -> None:
|
5565
5571
|
"""Check parameter and return types for postparsing hooks."""
|
5566
5572
|
cls._validate_callable_param_count(cast(Callable[..., Any], func), 1)
|
5567
|
-
|
5568
|
-
|
5569
|
-
|
5573
|
+
type_hints, ret_ann = get_types(func)
|
5574
|
+
if not type_hints:
|
5575
|
+
raise TypeError(f"{func.__name__} parameter is missing a type hint, expected: 'cmd2.plugin.PostparsingData'")
|
5576
|
+
par_ann = next(iter(type_hints.values()))
|
5577
|
+
if par_ann != plugin.PostparsingData:
|
5570
5578
|
raise TypeError(f"{func.__name__} must have one parameter declared with type 'cmd2.plugin.PostparsingData'")
|
5571
|
-
if
|
5579
|
+
if ret_ann != plugin.PostparsingData:
|
5572
5580
|
raise TypeError(f"{func.__name__} must declare return a return type of 'cmd2.plugin.PostparsingData'")
|
5573
5581
|
|
5574
5582
|
def register_postparsing_hook(self, func: Callable[[plugin.PostparsingData], plugin.PostparsingData]) -> None:
|
@@ -5583,21 +5591,21 @@ class Cmd(cmd.Cmd):
|
|
5583
5591
|
cls, func: Callable[[CommandDataType], CommandDataType], data_type: type[CommandDataType]
|
5584
5592
|
) -> None:
|
5585
5593
|
"""Check parameter and return types for pre and post command hooks."""
|
5586
|
-
signature = inspect.signature(func)
|
5587
5594
|
# validate that the callable has the right number of parameters
|
5588
5595
|
cls._validate_callable_param_count(cast(Callable[..., Any], func), 1)
|
5596
|
+
|
5597
|
+
type_hints, ret_ann = get_types(func)
|
5598
|
+
if not type_hints:
|
5599
|
+
raise TypeError(f"{func.__name__} parameter is missing a type hint, expected: {data_type}")
|
5600
|
+
param_name, par_ann = next(iter(type_hints.items()))
|
5589
5601
|
# validate the parameter has the right annotation
|
5590
|
-
|
5591
|
-
|
5592
|
-
if param.annotation != data_type:
|
5593
|
-
raise TypeError(f'argument 1 of {func.__name__} has incompatible type {param.annotation}, expected {data_type}')
|
5602
|
+
if par_ann != data_type:
|
5603
|
+
raise TypeError(f'argument 1 of {func.__name__} has incompatible type {par_ann}, expected {data_type}')
|
5594
5604
|
# validate the return value has the right annotation
|
5595
|
-
if
|
5605
|
+
if ret_ann is None:
|
5596
5606
|
raise TypeError(f'{func.__name__} does not have a declared return type, expected {data_type}')
|
5597
|
-
if
|
5598
|
-
raise TypeError(
|
5599
|
-
f'{func.__name__} has incompatible return type {signature.return_annotation}, expected {data_type}'
|
5600
|
-
)
|
5607
|
+
if ret_ann != data_type:
|
5608
|
+
raise TypeError(f'{func.__name__} has incompatible return type {ret_ann}, expected {data_type}')
|
5601
5609
|
|
5602
5610
|
def register_precmd_hook(self, func: Callable[[plugin.PrecommandData], plugin.PrecommandData]) -> None:
|
5603
5611
|
"""Register a hook to be called before the command function."""
|
@@ -5615,12 +5623,16 @@ class Cmd(cmd.Cmd):
|
|
5615
5623
|
) -> None:
|
5616
5624
|
"""Check parameter and return types for command finalization hooks."""
|
5617
5625
|
cls._validate_callable_param_count(func, 1)
|
5618
|
-
|
5619
|
-
|
5620
|
-
|
5621
|
-
|
5622
|
-
if
|
5623
|
-
raise TypeError(
|
5626
|
+
type_hints, ret_ann = get_types(func)
|
5627
|
+
if not type_hints:
|
5628
|
+
raise TypeError(f"{func.__name__} parameter is missing a type hint, expected: {plugin.CommandFinalizationData}")
|
5629
|
+
_, par_ann = next(iter(type_hints.items()))
|
5630
|
+
if par_ann != plugin.CommandFinalizationData:
|
5631
|
+
raise TypeError(
|
5632
|
+
f"{func.__name__} must have one parameter declared with type {plugin.CommandFinalizationData}, got: {par_ann}"
|
5633
|
+
)
|
5634
|
+
if ret_ann != plugin.CommandFinalizationData:
|
5635
|
+
raise TypeError(f"{func.__name__} must declare return a return type of {plugin.CommandFinalizationData}")
|
5624
5636
|
|
5625
5637
|
def register_cmdfinalization_hook(
|
5626
5638
|
self, func: Callable[[plugin.CommandFinalizationData], plugin.CommandFinalizationData]
|
cmd2/decorators.py
CHANGED
@@ -393,6 +393,14 @@ def with_argparser(
|
|
393
393
|
|
394
394
|
command_name = func.__name__[len(constants.COMMAND_FUNC_PREFIX) :]
|
395
395
|
|
396
|
+
if isinstance(parser, argparse.ArgumentParser):
|
397
|
+
# Set parser's prog value for backward compatibility within the cmd2 2.0 family.
|
398
|
+
# This will be removed in cmd2 3.0 since we never reference this parser object's prog value.
|
399
|
+
# Since it's possible for the same parser object to be passed into multiple with_argparser()
|
400
|
+
# calls, we only set prog on the deep copies of this parser based on the specific do_xxxx
|
401
|
+
# instance method they are associated with.
|
402
|
+
_set_parser_prog(parser, command_name)
|
403
|
+
|
396
404
|
# Set some custom attributes for this command
|
397
405
|
setattr(cmd_wrapper, constants.CMD_ATTR_ARGPARSER, parser)
|
398
406
|
setattr(cmd_wrapper, constants.CMD_ATTR_PRESERVE_QUOTES, preserve_quotes)
|
cmd2/utils.py
CHANGED
@@ -14,29 +14,12 @@ import sys
|
|
14
14
|
import threading
|
15
15
|
import unicodedata
|
16
16
|
from collections.abc import Callable, Iterable
|
17
|
-
from difflib import
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
from typing import (
|
24
|
-
TYPE_CHECKING,
|
25
|
-
Any,
|
26
|
-
Optional,
|
27
|
-
TextIO,
|
28
|
-
TypeVar,
|
29
|
-
Union,
|
30
|
-
cast,
|
31
|
-
)
|
32
|
-
|
33
|
-
from . import (
|
34
|
-
constants,
|
35
|
-
)
|
36
|
-
from .argparse_custom import (
|
37
|
-
ChoicesProviderFunc,
|
38
|
-
CompleterFunc,
|
39
|
-
)
|
17
|
+
from difflib import SequenceMatcher
|
18
|
+
from enum import Enum
|
19
|
+
from typing import TYPE_CHECKING, Any, Optional, TextIO, TypeVar, Union, cast, get_type_hints
|
20
|
+
|
21
|
+
from . import constants
|
22
|
+
from .argparse_custom import ChoicesProviderFunc, CompleterFunc
|
40
23
|
|
41
24
|
if TYPE_CHECKING: # pragma: no cover
|
42
25
|
import cmd2 # noqa: F401
|
@@ -1261,3 +1244,27 @@ def suggest_similar(
|
|
1261
1244
|
best_simil = simil
|
1262
1245
|
proposed_command = each
|
1263
1246
|
return proposed_command
|
1247
|
+
|
1248
|
+
|
1249
|
+
def get_types(func_or_method: Callable[..., Any]) -> tuple[dict[str, Any], Any]:
|
1250
|
+
"""Use typing.get_type_hints() to extract type hints for parameters and return value.
|
1251
|
+
|
1252
|
+
This exists because the inspect module doesn't have a safe way of doing this that works
|
1253
|
+
both with and without importing annotations from __future__ until Python 3.10.
|
1254
|
+
|
1255
|
+
TODO: Once cmd2 only supports Python 3.10+, change to use inspect.get_annotations(eval_str=True)
|
1256
|
+
|
1257
|
+
:param func_or_method: Function or method to return the type hints for
|
1258
|
+
:return tuple with first element being dictionary mapping param names to type hints
|
1259
|
+
and second element being return type hint, unspecified, returns None
|
1260
|
+
"""
|
1261
|
+
try:
|
1262
|
+
type_hints = get_type_hints(func_or_method) # Get dictionary of type hints
|
1263
|
+
except TypeError as exc:
|
1264
|
+
raise ValueError("Argument passed to get_types should be a function or method") from exc
|
1265
|
+
ret_ann = type_hints.pop('return', None) # Pop off the return annotation if it exists
|
1266
|
+
if inspect.ismethod(func_or_method):
|
1267
|
+
type_hints.pop('self', None) # Pop off `self` hint for methods
|
1268
|
+
if ret_ann is type(None):
|
1269
|
+
ret_ann = None # Simplify logic to just return None instead of NoneType
|
1270
|
+
return type_hints, ret_ann
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cmd2
|
3
|
-
Version: 2.6.
|
3
|
+
Version: 2.6.2
|
4
4
|
Summary: cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python
|
5
5
|
Author: cmd2 Contributors
|
6
6
|
License: The MIT License (MIT)
|
7
7
|
|
8
|
-
Copyright (c) 2008-
|
8
|
+
Copyright (c) 2008-2025 Catherine Devlin and others
|
9
9
|
|
10
10
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
11
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -39,6 +39,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.12
|
40
40
|
Classifier: Programming Language :: Python :: 3.13
|
41
41
|
Classifier: Programming Language :: Python :: 3.14
|
42
|
+
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
|
42
43
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
43
44
|
Requires-Python: >=3.9
|
44
45
|
Description-Content-Type: text/markdown
|
@@ -80,22 +81,22 @@ when using cmd.
|
|
80
81
|
|
81
82
|

|
82
83
|
|
83
|
-
When creating solutions developers have no shortage of tools to create rich and smart user
|
84
|
-
System administrators have long been duct taping together brittle workflows based on a
|
85
|
-
tools created by strangers on github and the guy down the hall.
|
86
|
-
Unfortunately, when CLIs become significantly complex the ease of command discoverability tends to
|
87
|
-
On the other hand, Web and traditional desktop GUIs are first in class when it comes
|
88
|
-
functionality.
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
84
|
+
When creating solutions developers have no shortage of tools to create rich and smart user
|
85
|
+
interfaces. System administrators have long been duct taping together brittle workflows based on a
|
86
|
+
menagerie of simple command line tools created by strangers on github and the guy down the hall.
|
87
|
+
Unfortunately, when CLIs become significantly complex the ease of command discoverability tends to
|
88
|
+
fade quickly. On the other hand, Web and traditional desktop GUIs are first in class when it comes
|
89
|
+
to easily discovering functionality. The price we pay for beautifully colored displays is complexity
|
90
|
+
required to aggregate disperate applications into larger systems. `cmd2` fills the niche between
|
91
|
+
high [ease of command discovery](https://clig.dev/#ease-of-discovery) applications and smart
|
92
|
+
workflow automation systems.
|
93
|
+
|
94
|
+
The `cmd2` framework provides a great mixture of both worlds. Application designers can easily
|
95
|
+
create complex applications and rely on the cmd2 library to offer effortless user facing help and
|
96
|
+
extensive tab completion. When users become comfortable with functionality, cmd2 turns into a
|
97
|
+
feature rich library enabling a smooth transition to full automation. If designed with enough
|
98
|
+
forethought, a well implemented cmd2 application can serve as a boutique workflow tool. `cmd2` pulls
|
99
|
+
off this flexibility based on two pillars of philosophy:
|
99
100
|
|
100
101
|
- Tab Completion
|
101
102
|
- Automation Transition
|
@@ -104,8 +105,8 @@ workflow tool. `cmd2` pulls off this flexibility based on two pillars of philoso
|
|
104
105
|
|
105
106
|
<a href="https://imgflip.com/i/63h03x"><img src="https://i.imgflip.com/63h03x.jpg" title="made at imgflip.com" width="70%" height="%70"/></a>
|
106
107
|
|
107
|
-
Deep extensive tab completion and help text generation based on the argparse library create the
|
108
|
-
command discovery'. The following is a list of features in this category.
|
108
|
+
Deep extensive tab completion and help text generation based on the argparse library create the
|
109
|
+
first pillar of 'ease of command discovery'. The following is a list of features in this category.
|
109
110
|
|
110
111
|
- Great tab completion of commands, subcommands, file system paths, and shell commands.
|
111
112
|
- Custom tab completion for user designed commands via simple function overloading.
|
@@ -116,13 +117,15 @@ command discovery'. The following is a list of features in this category.
|
|
116
117
|
|
117
118
|
<a href="https://imgflip.com/i/66t0y0"><img src="https://i.imgflip.com/66t0y0.jpg" title="made at imgflip.com" width="70%" height="70%"/></a>
|
118
119
|
|
119
|
-
cmd2 creates the second pillar of 'ease of transition to automation' through alias/macro creation,
|
120
|
-
parsing and execution of cmd2 scripting.
|
120
|
+
cmd2 creates the second pillar of 'ease of transition to automation' through alias/macro creation,
|
121
|
+
command line argument parsing and execution of cmd2 scripting.
|
121
122
|
|
122
123
|
- Flexible alias and macro creation for quick abstraction of commands.
|
123
124
|
- Text file scripting of your application with `run_script` (`@`) and `_relative_run_script` (`@@`)
|
124
|
-
- Powerful and flexible built-in Python scripting of your application using the `run_pyscript`
|
125
|
-
|
125
|
+
- Powerful and flexible built-in Python scripting of your application using the `run_pyscript`
|
126
|
+
command
|
127
|
+
- Transcripts for use with built-in regression can be automatically generated from `history -t` or
|
128
|
+
`run_script -t`
|
126
129
|
|
127
130
|
## Installation
|
128
131
|
|
@@ -132,11 +135,12 @@ On all operating systems, the latest stable version of `cmd2` can be installed u
|
|
132
135
|
pip install -U cmd2
|
133
136
|
```
|
134
137
|
|
135
|
-
cmd2 works with Python 3.9+ on Windows, macOS, and Linux. It is pure Python code with few 3rd-party
|
138
|
+
cmd2 works with Python 3.9+ on Windows, macOS, and Linux. It is pure Python code with few 3rd-party
|
139
|
+
dependencies. It works with both conventional CPython and free-threaded variants.
|
136
140
|
|
137
141
|
For information on other installation options, see
|
138
|
-
[Installation Instructions](https://cmd2.readthedocs.io/en/latest/overview/installation.html) in the
|
139
|
-
documentation.
|
142
|
+
[Installation Instructions](https://cmd2.readthedocs.io/en/latest/overview/installation.html) in the
|
143
|
+
cmd2 documentation.
|
140
144
|
|
141
145
|
## Documentation
|
142
146
|
|
@@ -144,7 +148,8 @@ The latest documentation for cmd2 can be read online here: https://cmd2.readthed
|
|
144
148
|
|
145
149
|
It is available in HTML, PDF, and ePub formats.
|
146
150
|
|
147
|
-
The best way to learn the cmd2 api is to delve into the example applications located in source under
|
151
|
+
The best way to learn the cmd2 api is to delve into the example applications located in source under
|
152
|
+
examples.
|
148
153
|
|
149
154
|
## Tutorials
|
150
155
|
|
@@ -153,13 +158,15 @@ The best way to learn the cmd2 api is to delve into the example applications loc
|
|
153
158
|
- [slides](https://github.com/python-cmd2/talks/blob/master/PyOhio_2019/cmd2-PyOhio_2019.pdf)
|
154
159
|
- [example code](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples)
|
155
160
|
- [Cookiecutter](https://github.com/cookiecutter/cookiecutter) Templates from community
|
156
|
-
- Basic cookiecutter template for cmd2 application :
|
157
|
-
|
158
|
-
|
161
|
+
- Basic cookiecutter template for cmd2 application :
|
162
|
+
https://github.com/jayrod/cookiecutter-python-cmd2
|
163
|
+
- Advanced cookiecutter template with external plugin support :
|
164
|
+
https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug
|
159
165
|
- [cmd2 example applications](https://github.com/python-cmd2/cmd2/tree/master/examples)
|
160
166
|
- Basic cmd2 examples to demonstrate how to use various features
|
161
167
|
- [Advanced Examples](https://github.com/jayrod/cmd2-example-apps)
|
162
|
-
- More complex examples that demonstrate more featuers about how to put together a complete
|
168
|
+
- More complex examples that demonstrate more featuers about how to put together a complete
|
169
|
+
application
|
163
170
|
|
164
171
|
## Hello World
|
165
172
|
|
@@ -187,10 +194,10 @@ if __name__ == '__main__':
|
|
187
194
|
|
188
195
|
## Found a bug?
|
189
196
|
|
190
|
-
If you think you've found a bug, please first read through the
|
191
|
-
|
192
|
-
GitHub issue. Be sure to include as much information as possible so we can
|
193
|
-
the following:
|
197
|
+
If you think you've found a bug, please first read through the open
|
198
|
+
[Issues](https://github.com/python-cmd2/cmd2/issues). If you're confident it's a new bug, go ahead
|
199
|
+
and create a new GitHub issue. Be sure to include as much information as possible so we can
|
200
|
+
reproduce the bug. At a minimum, please state the following:
|
194
201
|
|
195
202
|
- `cmd2` version
|
196
203
|
- Python version
|
@@ -232,4 +239,5 @@ Possibly defunct but still good examples
|
|
232
239
|
| [FLASHMINGO](https://github.com/mandiant/flashmingo) | Automatic analysis of SWF files based on some heuristics. Extensible via plugins. | [Mandiant](https://github.com/mandiant) |
|
233
240
|
| [psiTurk](https://github.com/NYUCCL/psiTurk) | An open platform for science on Amazon Mechanical Turk | [NYU Computation and Cognition Lab](https://github.com/NYUCCL) |
|
234
241
|
|
235
|
-
Note: If you have created an application based on `cmd2` that you would like us to mention here,
|
242
|
+
Note: If you have created an application based on `cmd2` that you would like us to mention here,
|
243
|
+
please get in touch.
|
@@ -3,10 +3,10 @@ cmd2/ansi.py,sha256=XwBvFnB51LYYjIpfEge6mcr5X63dUxiV0aJlOOJ_2tQ,31965
|
|
3
3
|
cmd2/argparse_completer.py,sha256=F_5hiX9fYpEhV42mz7v7qeS7KuInAS6xU6KekLxYzsQ,35863
|
4
4
|
cmd2/argparse_custom.py,sha256=Q7N-2TSctfjn3TEZezQNaT5y0w8sdGpmUA5_DCPa_Pk,59131
|
5
5
|
cmd2/clipboard.py,sha256=HLZWY-W3mkpF_OqQet-F8pS3rlXpiE5vxUyPV_yHvIU,507
|
6
|
-
cmd2/cmd2.py,sha256
|
6
|
+
cmd2/cmd2.py,sha256=-LkAwuakQGF_oZTUsmtQfPTILtCT-F7LNE7Ej2l9PVc,261740
|
7
7
|
cmd2/command_definition.py,sha256=_wF39nig5MP0grSOZ1hFehP5fCGusUNHMn9PIs6pmcU,7648
|
8
8
|
cmd2/constants.py,sha256=duEqGhhvdUV7AYxE8VGZ4wyFBcN2y2bLPd5iefW4tSU,1943
|
9
|
-
cmd2/decorators.py,sha256=
|
9
|
+
cmd2/decorators.py,sha256=t0gBy3aRz5ke0jHyP5YOszdQ61t5aV8j0eNyLPX6hmg,20644
|
10
10
|
cmd2/exceptions.py,sha256=fYciAnLCpvPYkXCtmADhxtcvjbxVagRjhp41eYwAQo8,3444
|
11
11
|
cmd2/history.py,sha256=elJPuvV7BnUEgpWnixNyl2yGtR6sz3nwvpyFwaeFqRA,14800
|
12
12
|
cmd2/parsing.py,sha256=BsyQTTkuEg4FiQP9o2O28KjXodFgXkXmvk_VkAe-Ryw,28057
|
@@ -16,9 +16,9 @@ cmd2/py_bridge.py,sha256=TKl2d7sgptDdccuO1PWG8m83Nww2bGCzsY4_wqjKTjg,4935
|
|
16
16
|
cmd2/rl_utils.py,sha256=sWapqwDR_GvOgy5NJ7c-i6nUU4dqpKpGQ8-Olwi3tuU,11335
|
17
17
|
cmd2/table_creator.py,sha256=nF3VEgGHvfhHBh_yoMAiV1WaDdR8hIareIAogzIPq5M,47177
|
18
18
|
cmd2/transcript.py,sha256=Ws0lW_oBFxCQCKSwvnDUS1x3ya163YXnV-O5aTU0z7k,9207
|
19
|
-
cmd2/utils.py,sha256=
|
20
|
-
cmd2-2.6.
|
21
|
-
cmd2-2.6.
|
22
|
-
cmd2-2.6.
|
23
|
-
cmd2-2.6.
|
24
|
-
cmd2-2.6.
|
19
|
+
cmd2/utils.py,sha256=NqDIkY4LiAlnv_Un7MFHxszoH2KgEWQ7NJOwQurIn_E,50698
|
20
|
+
cmd2-2.6.2.dist-info/licenses/LICENSE,sha256=9qPeHY4u2fkSz0JQGT-P4T3QqTWTqnQJ_8LkZUhSdFY,1099
|
21
|
+
cmd2-2.6.2.dist-info/METADATA,sha256=PXmEeU5Cspekoxefr9LjKqHJ44zXV4hUdwGUrBTeygs,17292
|
22
|
+
cmd2-2.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
cmd2-2.6.2.dist-info/top_level.txt,sha256=gJbOJmyrARwLhm5diXAtzlNQdxbDZ8iRJ8HJi65_5hg,5
|
24
|
+
cmd2-2.6.2.dist-info/RECORD,,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2008-
|
3
|
+
Copyright (c) 2008-2025 Catherine Devlin and others
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
File without changes
|
File without changes
|