cmd2 2.4.3__py3-none-any.whl → 2.5.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cmd2/rl_utils.py CHANGED
@@ -2,6 +2,7 @@
2
2
  """
3
3
  Imports the proper Readline for the platform and provides utility functions for it
4
4
  """
5
+
5
6
  import sys
6
7
  from enum import (
7
8
  Enum,
@@ -28,19 +29,17 @@ from typing import (
28
29
 
29
30
  # Prefer statically linked gnureadline if installed due to compatibility issues with libedit
30
31
  try:
31
- # noinspection PyPackageRequirements
32
32
  import gnureadline as readline # type: ignore[import]
33
33
  except ImportError:
34
34
  # Note: If this actually fails, you should install gnureadline on Linux/Mac or pyreadline3 on Windows.
35
35
  try:
36
- # noinspection PyUnresolvedReferences
37
36
  import readline # type: ignore[no-redef]
38
37
  except ImportError: # pragma: no cover
39
38
  pass
40
39
 
41
40
 
42
41
  class RlType(Enum):
43
- """Readline library types we recognize"""
42
+ """Readline library types we support"""
44
43
 
45
44
  GNU = 1
46
45
  PYREADLINE = 2
@@ -70,8 +69,8 @@ if 'pyreadline3' in sys.modules:
70
69
  )
71
70
 
72
71
  # Check if we are running in a terminal
73
- if sys.stdout.isatty(): # pragma: no cover
74
- # noinspection PyPep8Naming,PyUnresolvedReferences
72
+ if sys.stdout is not None and sys.stdout.isatty(): # pragma: no cover
73
+
75
74
  def enable_win_vt100(handle: HANDLE) -> bool:
76
75
  """
77
76
  Enables VT100 character sequences in a Windows console
@@ -101,27 +100,18 @@ if 'pyreadline3' in sys.modules:
101
100
  # Enable VT100 sequences for stdout and stderr
102
101
  STD_OUT_HANDLE = -11
103
102
  STD_ERROR_HANDLE = -12
104
- # noinspection PyUnresolvedReferences
105
103
  vt100_stdout_support = enable_win_vt100(readline.rl.console.GetStdHandle(STD_OUT_HANDLE))
106
- # noinspection PyUnresolvedReferences
107
104
  vt100_stderr_support = enable_win_vt100(readline.rl.console.GetStdHandle(STD_ERROR_HANDLE))
108
105
  vt100_support = vt100_stdout_support and vt100_stderr_support
109
106
 
110
107
  ############################################################################################################
111
108
  # pyreadline3 is incomplete in terms of the Python readline API. Add the missing functions we need.
112
109
  ############################################################################################################
113
- # readline.redisplay()
114
- try:
115
- getattr(readline, 'redisplay')
116
- except AttributeError:
117
- # noinspection PyProtectedMember,PyUnresolvedReferences
118
- readline.redisplay = readline.rl.mode._update_line
119
-
120
110
  # readline.remove_history_item()
121
111
  try:
122
112
  getattr(readline, 'remove_history_item')
123
113
  except AttributeError:
124
- # noinspection PyProtectedMember,PyUnresolvedReferences
114
+
125
115
  def pyreadline_remove_history_item(pos: int) -> None:
126
116
  """
127
117
  An implementation of remove_history_item() for pyreadline3
@@ -141,7 +131,7 @@ if 'pyreadline3' in sys.modules:
141
131
 
142
132
  elif 'gnureadline' in sys.modules or 'readline' in sys.modules:
143
133
  # We don't support libedit. See top of this file for why.
144
- if 'libedit' not in readline.__doc__:
134
+ if readline.__doc__ is not None and 'libedit' not in readline.__doc__:
145
135
  try:
146
136
  # Load the readline lib so we can access members of it
147
137
  import ctypes
@@ -156,7 +146,7 @@ elif 'gnureadline' in sys.modules or 'readline' in sys.modules:
156
146
  rl_type = RlType.GNU
157
147
  vt100_support = sys.stdout.isatty()
158
148
 
159
- # Check if readline was loaded
149
+ # Check if we loaded a supported version of readline
160
150
  if rl_type == RlType.NONE: # pragma: no cover
161
151
  if not _rl_warn_reason:
162
152
  _rl_warn_reason = (
@@ -168,7 +158,6 @@ else:
168
158
  rl_warning = ''
169
159
 
170
160
 
171
- # noinspection PyProtectedMember,PyUnresolvedReferences
172
161
  def rl_force_redisplay() -> None: # pragma: no cover
173
162
  """
174
163
  Causes readline to display the prompt and input text wherever the cursor is and start
@@ -191,7 +180,6 @@ def rl_force_redisplay() -> None: # pragma: no cover
191
180
  readline.rl.mode._update_line()
192
181
 
193
182
 
194
- # noinspection PyProtectedMember, PyUnresolvedReferences
195
183
  def rl_get_point() -> int: # pragma: no cover
196
184
  """
197
185
  Returns the offset of the current cursor position in rl_line_buffer
@@ -206,9 +194,8 @@ def rl_get_point() -> int: # pragma: no cover
206
194
  return 0
207
195
 
208
196
 
209
- # noinspection PyUnresolvedReferences
210
197
  def rl_get_prompt() -> str: # pragma: no cover
211
- """Gets Readline's current prompt"""
198
+ """Get Readline's prompt"""
212
199
  if rl_type == RlType.GNU:
213
200
  encoded_prompt = ctypes.c_char_p.in_dll(readline_lib, "rl_prompt").value
214
201
  if encoded_prompt is None:
@@ -229,7 +216,24 @@ def rl_get_prompt() -> str: # pragma: no cover
229
216
  return rl_unescape_prompt(prompt)
230
217
 
231
218
 
232
- # noinspection PyUnresolvedReferences
219
+ def rl_get_display_prompt() -> str: # pragma: no cover
220
+ """
221
+ Get Readline's currently displayed prompt.
222
+
223
+ In GNU Readline, the displayed prompt sometimes differs from the prompt.
224
+ This occurs in functions that use the prompt string as a message area, such as incremental search.
225
+ """
226
+ if rl_type == RlType.GNU:
227
+ encoded_prompt = ctypes.c_char_p.in_dll(readline_lib, "rl_display_prompt").value
228
+ if encoded_prompt is None:
229
+ prompt = ''
230
+ else:
231
+ prompt = encoded_prompt.decode(encoding='utf-8')
232
+ return rl_unescape_prompt(prompt)
233
+ else:
234
+ return rl_get_prompt()
235
+
236
+
233
237
  def rl_set_prompt(prompt: str) -> None: # pragma: no cover
234
238
  """
235
239
  Sets Readline's prompt
@@ -246,7 +250,8 @@ def rl_set_prompt(prompt: str) -> None: # pragma: no cover
246
250
 
247
251
 
248
252
  def rl_escape_prompt(prompt: str) -> str:
249
- """Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ANSI escape codes
253
+ """
254
+ Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ANSI escape codes
250
255
 
251
256
  :param prompt: original prompt
252
257
  :return: prompt safe to pass to GNU Readline
@@ -285,3 +290,32 @@ def rl_unescape_prompt(prompt: str) -> str:
285
290
  prompt = prompt.replace(escape_start, "").replace(escape_end, "")
286
291
 
287
292
  return prompt
293
+
294
+
295
+ def rl_in_search_mode() -> bool: # pragma: no cover
296
+ """Check if readline is doing either an incremental (e.g. Ctrl-r) or non-incremental (e.g. Esc-p) search"""
297
+ if rl_type == RlType.GNU:
298
+ # GNU Readline defines constants that we can use to determine if in search mode.
299
+ # RL_STATE_ISEARCH 0x0000080
300
+ # RL_STATE_NSEARCH 0x0000100
301
+ IN_SEARCH_MODE = 0x0000180
302
+
303
+ readline_state = ctypes.c_int.in_dll(readline_lib, "rl_readline_state").value
304
+ return bool(IN_SEARCH_MODE & readline_state)
305
+ elif rl_type == RlType.PYREADLINE:
306
+ from pyreadline3.modes.emacs import ( # type: ignore[import]
307
+ EmacsMode,
308
+ )
309
+
310
+ # These search modes only apply to Emacs mode, which is the default.
311
+ if not isinstance(readline.rl.mode, EmacsMode):
312
+ return False
313
+
314
+ # While in search mode, the current keyevent function is set one of the following.
315
+ search_funcs = (
316
+ readline.rl.mode._process_incremental_search_keyevent,
317
+ readline.rl.mode._process_non_incremental_search_keyevent,
318
+ )
319
+ return readline.rl.mode.process_keyevent_queue[-1] in search_funcs
320
+ else:
321
+ return False
cmd2/table_creator.py CHANGED
@@ -5,6 +5,7 @@ This API is built upon two core classes: Column and TableCreator
5
5
  The general use case is to inherit from TableCreator to create a table class with custom formatting options.
6
6
  There are already implemented and ready-to-use examples of this below TableCreator's code.
7
7
  """
8
+
8
9
  import copy
9
10
  import io
10
11
  from collections import (
cmd2/transcript.py CHANGED
@@ -9,6 +9,7 @@ a unit test, comparing the expected output to the actual output.
9
9
  This file contains the class necessary to make that work. This
10
10
  class is used in cmd2.py::run_transcript_tests()
11
11
  """
12
+
12
13
  import re
13
14
  import unittest
14
15
  from typing import (
@@ -60,7 +61,7 @@ class Cmd2TestCase(unittest.TestCase):
60
61
  def runTest(self) -> None: # was testall
61
62
  if self.cmdapp:
62
63
  its = sorted(self.transcripts.items())
63
- for (fname, transcript) in its:
64
+ for fname, transcript in its:
64
65
  self._test_transcript(fname, transcript)
65
66
 
66
67
  def _fetchTranscripts(self) -> None:
@@ -204,7 +205,7 @@ class Cmd2TestCase(unittest.TestCase):
204
205
  # escaped. We found it.
205
206
  break
206
207
  else:
207
- # check if the slash is preceeded by a backslash
208
+ # check if the slash is preceded by a backslash
208
209
  if s[pos - 1 : pos] == '\\':
209
210
  # it is.
210
211
  if in_regex:
cmd2/utils.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # coding=utf-8
2
2
  """Shared utility functions"""
3
+
3
4
  import argparse
4
5
  import collections
5
6
  import functools
@@ -12,6 +13,9 @@ import subprocess
12
13
  import sys
13
14
  import threading
14
15
  import unicodedata
16
+ from difflib import (
17
+ SequenceMatcher,
18
+ )
15
19
  from enum import (
16
20
  Enum,
17
21
  )
@@ -154,7 +158,7 @@ class Settable:
154
158
  :param choices_provider: function that provides choices for this argument
155
159
  :param completer: tab completion function that provides choices for this argument
156
160
  """
157
- if val_type == bool:
161
+ if val_type is bool:
158
162
 
159
163
  def get_bool_choices(_) -> List[str]: # type: ignore[no-untyped-def]
160
164
  """Used to tab complete lowercase boolean values"""
@@ -174,17 +178,14 @@ class Settable:
174
178
  self.completer = completer
175
179
 
176
180
  def get_value(self) -> Any:
177
- """
178
- Get the value of the settable attribute
179
- :return:
180
- """
181
+ """Get the value of the settable attribute."""
181
182
  return getattr(self.settable_obj, self.settable_attrib_name)
182
183
 
183
- def set_value(self, value: Any) -> Any:
184
+ def set_value(self, value: Any) -> None:
184
185
  """
185
- Set the settable attribute on the specified destination object
186
- :param value: New value to set
187
- :return: New value that the attribute was set to
186
+ Set the settable attribute on the specified destination object.
187
+
188
+ :param value: new value to set
188
189
  """
189
190
  # Run the value through its type function to handle any conversion or validation
190
191
  new_value = self.val_type(value)
@@ -201,7 +202,6 @@ class Settable:
201
202
  # Check if we need to call an onchange callback
202
203
  if orig_value != new_value and self.onchange_cb:
203
204
  self.onchange_cb(self.name, orig_value, new_value)
204
- return new_value
205
205
 
206
206
 
207
207
  def is_text_file(file_path: str) -> bool:
@@ -668,7 +668,6 @@ class ProcReader:
668
668
 
669
669
  # Run until process completes
670
670
  while self._proc.poll() is None:
671
- # noinspection PyUnresolvedReferences
672
671
  available = read_stream.peek() # type: ignore[attr-defined]
673
672
  if available:
674
673
  read_stream.read(len(available))
@@ -871,7 +870,8 @@ def align_text(
871
870
  )
872
871
 
873
872
  if width is None:
874
- width = shutil.get_terminal_size().columns
873
+ # Prior to Python 3.11 this can return 0, so use a fallback if needed.
874
+ width = shutil.get_terminal_size().columns or constants.DEFAULT_TERMINAL_WIDTH
875
875
 
876
876
  if width < 1:
877
877
  raise ValueError("width must be at least 1")
@@ -1152,17 +1152,18 @@ def categorize(func: Union[Callable[..., Any], Iterable[Callable[..., Any]]], ca
1152
1152
  :param func: function or list of functions to categorize
1153
1153
  :param category: category to put it in
1154
1154
 
1155
- :Example:
1155
+ Example:
1156
+
1157
+ ```py
1158
+ import cmd2
1159
+ class MyApp(cmd2.Cmd):
1160
+ def do_echo(self, arglist):
1161
+ self.poutput(' '.join(arglist)
1156
1162
 
1157
- >>> import cmd2
1158
- >>> class MyApp(cmd2.Cmd):
1159
- >>> def do_echo(self, arglist):
1160
- >>> self.poutput(' '.join(arglist)
1161
- >>>
1162
- >>> cmd2.utils.categorize(do_echo, "Text Processing")
1163
+ cmd2.utils.categorize(do_echo, "Text Processing")
1164
+ ```
1163
1165
 
1164
- For an alternative approach to categorizing commands using a decorator, see
1165
- :func:`~cmd2.decorators.with_category`
1166
+ For an alternative approach to categorizing commands using a decorator, see [cmd2.decorators.with_category][]
1166
1167
  """
1167
1168
  if isinstance(func, Iterable):
1168
1169
  for item in func:
@@ -1187,9 +1188,7 @@ def get_defining_class(meth: Callable[..., Any]) -> Optional[Type[Any]]:
1187
1188
  if isinstance(meth, functools.partial):
1188
1189
  return get_defining_class(meth.func)
1189
1190
  if inspect.ismethod(meth) or (
1190
- inspect.isbuiltin(meth)
1191
- and getattr(meth, '__self__') is not None
1192
- and getattr(meth.__self__, '__class__') # type: ignore[attr-defined]
1191
+ inspect.isbuiltin(meth) and getattr(meth, '__self__') is not None and getattr(meth.__self__, '__class__')
1193
1192
  ):
1194
1193
  for cls in inspect.getmro(meth.__self__.__class__): # type: ignore[attr-defined]
1195
1194
  if meth.__name__ in cls.__dict__:
@@ -1262,3 +1261,36 @@ def strip_doc_annotations(doc: str) -> str:
1262
1261
  elif found_first:
1263
1262
  break
1264
1263
  return cmd_desc
1264
+
1265
+
1266
+ def similarity_function(s1: str, s2: str) -> float:
1267
+ # The ratio from s1,s2 may be different to s2,s1. We keep the max.
1268
+ # See https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.ratio
1269
+ return max(SequenceMatcher(None, s1, s2).ratio(), SequenceMatcher(None, s2, s1).ratio())
1270
+
1271
+
1272
+ MIN_SIMIL_TO_CONSIDER = 0.7
1273
+
1274
+
1275
+ def suggest_similar(
1276
+ requested_command: str, options: Iterable[str], similarity_function_to_use: Optional[Callable[[str, str], float]] = None
1277
+ ) -> Optional[str]:
1278
+ """
1279
+ Given a requested command and an iterable of possible options returns the most similar (if any is similar)
1280
+
1281
+ :param requested_command: The command entered by the user
1282
+ :param options: The list of available commands to search for the most similar
1283
+ :param similarity_function_to_use: An optional callable to use to compare commands
1284
+ :return: The most similar command or None if no one is similar
1285
+ """
1286
+
1287
+ proposed_command = None
1288
+ best_simil = MIN_SIMIL_TO_CONSIDER
1289
+ requested_command_to_compare = requested_command.lower()
1290
+ similarity_function_to_use = similarity_function_to_use or similarity_function
1291
+ for each in options:
1292
+ simil = similarity_function_to_use(each.lower(), requested_command_to_compare)
1293
+ if best_simil < simil:
1294
+ best_simil = simil
1295
+ proposed_command = each
1296
+ return proposed_command
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2008-2023 Catherine Devlin and others
3
+ Copyright (c) 2008-2024 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
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.2
2
+ Name: cmd2
3
+ Version: 2.5.9
4
+ Summary: cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python
5
+ Author: cmd2 Contributors
6
+ License: The MIT License (MIT)
7
+
8
+ Copyright (c) 2008-2024 Catherine Devlin and others
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in
18
+ all copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
+ THE SOFTWARE.
27
+
28
+ Keywords: CLI,cmd,command,interactive,prompt,Python
29
+ Classifier: Development Status :: 5 - Production/Stable
30
+ Classifier: Environment :: Console
31
+ Classifier: Operating System :: OS Independent
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: Intended Audience :: System Administrators
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Programming Language :: Python :: 3 :: Only
36
+ Classifier: Programming Language :: Python :: 3.8
37
+ Classifier: Programming Language :: Python :: 3.9
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
43
+ Requires-Python: >=3.8
44
+ Description-Content-Type: text/markdown
45
+ License-File: LICENSE
46
+ Requires-Dist: gnureadline>=8; platform_system == "Darwin"
47
+ Requires-Dist: pyperclip>=1.8
48
+ Requires-Dist: pyreadline3>=3.4; platform_system == "Windows"
49
+ Requires-Dist: wcwidth>=0.2.10
50
+
51
+ <h1 align="center">cmd2 : immersive interactive command line applications</h1>
52
+
53
+ [![Latest Version](https://img.shields.io/pypi/v/cmd2.svg?style=flat-square&label=latest%20stable%20version)](https://pypi.python.org/pypi/cmd2/)
54
+ [![GitHub Actions](https://github.com/python-cmd2/cmd2/workflows/CI/badge.svg)](https://github.com/python-cmd2/cmd2/actions?query=workflow%3ACI)
55
+ [![codecov](https://codecov.io/gh/python-cmd2/cmd2/branch/master/graph/badge.svg)](https://codecov.io/gh/python-cmd2/cmd2)
56
+ [![Documentation Status](https://readthedocs.org/projects/cmd2/badge/?version=latest)](http://cmd2.readthedocs.io/en/latest/?badge=latest)
57
+ <a href="https://discord.gg/RpVG6tk"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat"></a>
58
+
59
+ <p align="center">
60
+ <a href="#the-developers-toolbox">Developer's Toolbox</a> •
61
+ <a href="#philosophy">Philosophy</a> •
62
+ <a href="#installation">Installation</a> •
63
+ <a href="#documentation">Documentation</a> •
64
+ <a href="#tutorials">Tutorials</a> •
65
+ <a href="#hello-world">Hello World</a> •
66
+ <a href="#projects-using-cmd2">Projects using cmd2</a> •
67
+ </p>
68
+
69
+ [![Screenshot](https://raw.githubusercontent.com/python-cmd2/cmd2/master/cmd2.png)](https://youtu.be/DDU_JH6cFsA)
70
+
71
+ cmd2 is a tool for building interactive command line applications in Python. Its goal is to make it
72
+ quick and easy for developers to build feature-rich and user-friendly interactive command line
73
+ applications. It provides a simple API which is an extension of Python's built-in
74
+ [cmd](https://docs.python.org/3/library/cmd.html) module. cmd2 provides a wealth of features on top
75
+ of cmd to make your life easier and eliminates much of the boilerplate code which would be necessary
76
+ when using cmd.
77
+
78
+ ## The developers toolbox
79
+
80
+ ![system schema](https://raw.githubusercontent.com/python-cmd2/cmd2/master/.github/images/graph.drawio.png)
81
+
82
+ When creating solutions developers have no shortage of tools to create rich and smart user interfaces.
83
+ System administrators have long been duct taping together brittle workflows based on a menagerie of simple command line tools created by strangers on github and the guy down the hall.
84
+ Unfortunately, when CLIs become significantly complex the ease of command discoverability tends to fade quickly.
85
+ On the other hand, Web and traditional desktop GUIs are first in class when it comes to easily discovering functionality.
86
+ The price we pay for beautifully colored displays is complexity required to aggregate disperate applications into larger systems.
87
+ `cmd2` fills the niche between high [ease of command discovery](https://clig.dev/#ease-of-discovery) applications and smart workflow automation systems.
88
+
89
+ The `cmd2` framework provides a great mixture of both worlds. Application designers can easily create complex applications and rely on the cmd2 library to offer effortless user facing help and extensive tab completion.
90
+ When users become comfortable with functionality, cmd2 turns into a feature rich library enabling a smooth transition to full automation. If designed with enough forethought, a well implemented cmd2 application can serve as a boutique workflow tool. `cmd2` pulls off this flexibility based on two pillars of philosophy:
91
+
92
+ - Tab Completion
93
+ - Automation Transition
94
+
95
+ ## Philosophy
96
+
97
+ <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>
98
+
99
+ Deep extensive tab completion and help text generation based on the argparse library create the first pillar of 'ease of command discovery'. The following is a list of features in this category.
100
+
101
+ - Great tab completion of commands, subcommands, file system paths, and shell commands.
102
+ - Custom tab completion for user designed commands via simple function overloading.
103
+ - Tab completion from `persistent_history_file` sources added with very little friction.
104
+ - Automatic tab completion of `argparse` flags and optional arguments.
105
+ - Path completion easily enabled.
106
+ - When all else fails, custom tab completion based on `choices_provider` can fill any gaps.
107
+
108
+ <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>
109
+
110
+ cmd2 creates the second pillar of 'ease of transition to automation' through alias/macro creation, command line argument parsing and execution of cmd2 scripting.
111
+
112
+ - Flexible alias and macro creation for quick abstraction of commands.
113
+ - Text file scripting of your application with `run_script` (`@`) and `_relative_run_script` (`@@`)
114
+ - Powerful and flexible built-in Python scripting of your application using the `run_pyscript` command
115
+ - Transcripts for use with built-in regression can be automatically generated from `history -t` or `run_script -t`
116
+
117
+ ## Installation
118
+
119
+ On all operating systems, the latest stable version of `cmd2` can be installed using pip:
120
+
121
+ ```bash
122
+ pip install -U cmd2
123
+ ```
124
+
125
+ cmd2 works with Python 3.8+ on Windows, macOS, and Linux. It is pure Python code with few 3rd-party dependencies.
126
+
127
+ For information on other installation options, see
128
+ [Installation Instructions](https://cmd2.readthedocs.io/en/latest/overview/installation.html) in the cmd2
129
+ documentation.
130
+
131
+ ## Documentation
132
+
133
+ The latest documentation for cmd2 can be read online here: https://cmd2.readthedocs.io/en/latest/
134
+
135
+ It is available in HTML, PDF, and ePub formats.
136
+
137
+ The best way to learn the cmd2 api is to delve into the example applications located in source under examples.
138
+
139
+ ## Tutorials
140
+
141
+ - PyOhio 2019 presentation:
142
+ - [video](https://www.youtube.com/watch?v=pebeWrTqIIw)
143
+ - [slides](https://github.com/python-cmd2/talks/blob/master/PyOhio_2019/cmd2-PyOhio_2019.pdf)
144
+ - [example code](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples)
145
+ - [Cookiecutter](https://github.com/cookiecutter/cookiecutter) Templates from community
146
+ - Basic cookiecutter template for cmd2 application : https://github.com/jayrod/cookiecutter-python-cmd2
147
+ - Advanced cookiecutter template with external plugin support : https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug
148
+ - [cmd2 example applications](https://github.com/python-cmd2/cmd2/tree/master/examples)
149
+ - Basic cmd2 examples to demonstrate how to use various features
150
+ - [Advanced Examples](https://github.com/jayrod/cmd2-example-apps)
151
+ - More complex examples that demonstrate more featuers about how to put together a complete application
152
+
153
+ ## Hello World
154
+
155
+ ```python
156
+ #!/usr/bin/env python
157
+ """A simple cmd2 application."""
158
+ import cmd2
159
+
160
+
161
+ class FirstApp(cmd2.Cmd):
162
+ """A simple cmd2 application."""
163
+
164
+ def do_hello_world(self, _: cmd2.Statement):
165
+ self.poutput('Hello World')
166
+
167
+ if __name__ == '__main__':
168
+ import sys
169
+ c = FirstApp()
170
+ sys.exit(c.cmdloop())
171
+
172
+ ```
173
+
174
+ ## Found a bug?
175
+
176
+ If you think you've found a bug, please first read through the open [Issues](https://github.com/python-cmd2/cmd2/issues). If you're confident it's a new bug, go ahead and create a new GitHub issue. Be sure to include as much information as possible so we can reproduce the bug. At a minimum, please state the following:
177
+
178
+ - `cmd2` version
179
+ - Python version
180
+ - OS name and version
181
+ - What you did to cause the bug to occur
182
+ - Include any traceback or error message associated with the bug
183
+
184
+ ## Projects using cmd2
185
+
186
+ | Application Name | Description | Organization or Author |
187
+ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
188
+ | [CephFS Shell](https://github.com/ceph/ceph) | The Ceph File System, or CephFS, is a POSIX-compliant file system built on top of Ceph’s distributed object store | [ceph](https://ceph.com/) |
189
+ | [garak](https://github.com/NVIDIA/garak) | LLM vulnerability scanner that checks if an LLM can be made to fail in a way we don't want | [NVIDIA](https://github.com/NVIDIA) |
190
+ | [medusa](https://github.com/Ch0pin/medusa) | Binary instrumentation framework that that automates processes for the dynamic analysis of Android and iOS Applications | [Ch0pin](https://github.com/Ch0pin) |
191
+ | [InternalBlue](https://github.com/seemoo-lab/internalblue) | Bluetooth experimentation framework for Broadcom and Cypress chips | [Secure Mobile Networking Lab](https://github.com/seemoo-lab) |
192
+ | [SCCMHunter](https://github.com/garrettfoster13/sccmhunter) | A post-ex tool built to streamline identifying, profiling, and attacking SCCM related assets in an Active Directory domain | [Garret Foster](https://github.com/garrettfoster13) |
193
+ | [Unipacker](https://github.com/unipacker/unipacker) | Automatic and platform-independent unpacker for Windows binaries based on emulation | [unipacker](https://github.com/unipacker) |
194
+ | [Frankenstein](https://github.com/seemoo-lab/frankenstein) | Broadcom and Cypress firmware emulation for fuzzing and further full-stack debugging | [Secure Mobile Networking Lab](https://github.com/seemoo-lab) |
195
+ | [Poseidon](https://github.com/faucetsdn/poseidon) | Leverages software-defined networks (SDNs) to acquire and then feed network traffic to a number of machine learning techniques. | [Faucet SDN](https://github.com/faucetsdn) |
196
+ | [DFTimewolf](https://github.com/log2timeline/dftimewolf) | A framework for orchestrating forensic collection, processing and data export | [log2timeline](https://github.com/log2timeline) |
197
+ | [GAP SDK](https://github.com/GreenWaves-Technologies/gap_sdk) | SDK for Greenwaves Technologies' GAP8 IoT Application Processor | [GreenWaves Technologies](https://github.com/GreenWaves-Technologies) |
198
+ | [REW Sploit](https://github.com/REW-sploit/REW-sploit) | Emulate and Dissect Metasploit Framework (MSF) and other attacks | [REW-sploit](https://github.com/REW-sploit) |
199
+ | [tomcatmanager](https://github.com/tomcatmanager/tomcatmanager) | A command line tool and python library for managing a tomcat server | [tomcatmanager](https://github.com/tomcatmanager) |
200
+ | [Falcon Toolkit](https://github.com/CrowdStrike/Falcon-Toolkit) | Unleash the power of the CrowdStrike Falcon Platform at the CLI | [CrowdStrike](https://github.com/CrowdStrike) |
201
+ | [EXPLIoT](https://gitlab.com/expliot_framework/expliot) | Internet of Things Security Testing and Exploitation framework | [expliot_framework](https://gitlab.com/expliot_framework/) |
202
+
203
+ Possibly defunct but still good examples
204
+
205
+ | Application Name | Description | Organization or Author |
206
+ | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
207
+ | [Katana](https://github.com/JohnHammond/katana) | Automatic CTF Challenge Solver | [John Hammond](https://github.com/JohnHammond) |
208
+ | [SatanSword](https://github.com/Lucifer1993/SatanSword) (in Chinese) | Comprehensive Penetration Framework for Red Teaming | [Lucifer1993](https://github.com/Lucifer1993) |
209
+ | [Jok3r](http://www.jok3r-framework.com) | Network & Web Pentest Automation Framework | [Koutto](https://github.com/koutto) |
210
+ | [Counterfit](https://github.com/Azure/counterfit) | a CLI that provides a generic automation layer for assessing the security of ML models | [Microsoft Azure](https://github.com/Azure) |
211
+ | [Overlord](https://github.com/qsecure-labs/overlord) | Red Teaming Infrastructure Automation | [QSecure Labs](https://github.com/qsecure-labs) |
212
+ | [Automated Reconnaissance Pipeline](https://github.com/epi052/recon-pipeline) | An automated target reconnaissance pipeline | [epi052](https://github.com/epi052) |
213
+ | [JSShell](https://github.com/Den1al/JSShell) | An interactive multi-user web JavaScript (JS) shell | [Den1al](https://github.com/Den1al) |
214
+ | [RedShell](https://github.com/Verizon/redshell) | An interactive command prompt for red teaming and pentesting | [Verizon](https://github.com/Verizon) |
215
+ | [FLASHMINGO](https://github.com/mandiant/flashmingo) | Automatic analysis of SWF files based on some heuristics. Extensible via plugins. | [Mandiant](https://github.com/mandiant) |
216
+ | [psiTurk](https://github.com/NYUCCL/psiTurk) | An open platform for science on Amazon Mechanical Turk | [NYU Computation and Cognition Lab](https://github.com/NYUCCL) |
217
+
218
+ Note: If you have created an application based on `cmd2` that you would like us to mention here, please get in touch.
@@ -0,0 +1,24 @@
1
+ cmd2/__init__.py,sha256=C6IHJ_uHgkqejuRwA10IK0-OzPxHKyZbPn82nMUwn-A,2602
2
+ cmd2/ansi.py,sha256=_3gAbMgqh8ksg43N2xQLp2u8uoB81BUl3CFoBN0990I,32036
3
+ cmd2/argparse_completer.py,sha256=6z0zmODqM7vhQhI0c6JUvCmR2V4qfdWQEyTZeNIea8c,36505
4
+ cmd2/argparse_custom.py,sha256=eZS-PodcF-UqhclKr61Wy0KXLRHM382Tk4T7mzlaWko,57689
5
+ cmd2/clipboard.py,sha256=7EISono76d7djj17hbvR9cCTB7jVGSBkUjgVQiMyUjE,549
6
+ cmd2/cmd2.py,sha256=GRIBAdRtDs2fXcUkE-IMaKIRLHV2slNbKTyPFq8QMHw,261090
7
+ cmd2/command_definition.py,sha256=OscFEk-O2N20fb8_fhkczqclaCxOwYyxNTnXWXOlngg,7655
8
+ cmd2/constants.py,sha256=DioxETv-_HzcMUnjuPyz7Cqw4YEt_MTrzOMotiHj-Jo,1981
9
+ cmd2/decorators.py,sha256=QVRyGQmAM6YBUhlZHqEVAvt9Tn1NqKGeSjDrLoUHvJg,20261
10
+ cmd2/exceptions.py,sha256=DwX7rQmon4eRyX1ZK4yne4lObdPO1j5Agg3Bav6pXwU,3600
11
+ cmd2/history.py,sha256=4iFi0Bny1CTjMx0ByQplrElvlZcus3lUgj2IyBfvAf0,14988
12
+ cmd2/parsing.py,sha256=58gD8hSvSV3nCliyoEZXJbvbzbnJ_5mSnwhTQhMM0BI,28297
13
+ cmd2/plugin.py,sha256=CCzzuHeBQbxH7YuG3UCdQ0uArnKYbodjhj-sYCbXSa0,814
14
+ cmd2/py.typed,sha256=qrkHrYJvGoZpU2BpVLNxJB44LlhqVSKyYOwD_L_1m3s,10
15
+ cmd2/py_bridge.py,sha256=DJCa7ff-XLwcz7Ij47nrwxgDDVUIVS5bRReLmayok1Q,5016
16
+ cmd2/rl_utils.py,sha256=HVPdNjuYyU67-XerPUJArmzhohzI1ABrZhU9cLc-EIs,11538
17
+ cmd2/table_creator.py,sha256=qoxt9s3MxQkfSkp4cIPFMlVzC7kRjUU55p0ow7pFQus,47544
18
+ cmd2/transcript.py,sha256=I0sD38RbG79Qz9GXIlfh1pHSNmWBTY2SLZAKEdSLWI4,9182
19
+ cmd2/utils.py,sha256=TElD9YnN5yT7BNuUcKSLpqRLcxrVmx_etkKHETFxRWU,49366
20
+ cmd2-2.5.9.dist-info/LICENSE,sha256=QXrW0Z0merk9mncyUkn-sgRxhT8_o1dL5HEaBNH47Q4,1099
21
+ cmd2-2.5.9.dist-info/METADATA,sha256=l1ODgTmFJO7C1Lgro-FIdGMldbIOCHrvmilsRCSUml8,17103
22
+ cmd2-2.5.9.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
23
+ cmd2-2.5.9.dist-info/top_level.txt,sha256=gJbOJmyrARwLhm5diXAtzlNQdxbDZ8iRJ8HJi65_5hg,5
24
+ cmd2-2.5.9.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5