Skip to content

Commit 57d08e7

Browse files
committed
Merge branch 'master' into 3.0.0
2 parents 374e596 + a61513e commit 57d08e7

File tree

13 files changed

+296
-179
lines changed

13 files changed

+296
-179
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
os: [ubuntu-latest, macos-latest, windows-latest]
13-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
13+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14-dev"]
1414
runs-on: ${{ matrix.os }}
1515
steps:
1616
- uses: actions/checkout@v4 # https://github.com/actions/checkout
@@ -19,7 +19,7 @@ jobs:
1919
# Set fetch-depth: 0 to fetch all history for all branches and tags.
2020
fetch-depth: 0 # Needed for setuptools_scm to work correctly
2121
- name: Install uv
22-
uses: astral-sh/setup-uv@v5
22+
uses: astral-sh/setup-uv@v6
2323

2424
- name: Set up Python ${{ matrix.python-version }}
2525
uses: actions/setup-python@v5

.github/workflows/doc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
# Set fetch-depth: 0 to fetch all history for all branches and tags.
2323
fetch-depth: 0 # Needed for setuptools_scm to work correctly
2424
- name: Install uv and set the python version
25-
uses: astral-sh/setup-uv@v5
25+
uses: astral-sh/setup-uv@v6
2626
with:
2727
python-version: ${{ matrix.python-version }}
2828
- name: Install the project

.github/workflows/mypy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
# Set fetch-depth: 0 to fetch all history for all branches and tags.
1818
fetch-depth: 0 # Needed for setuptools_scm to work correctly
1919
- name: Install uv and set the python version
20-
uses: astral-sh/setup-uv@v5
20+
uses: astral-sh/setup-uv@v6
2121
with:
2222
python-version: 3.13
2323
- name: Install the project

.pre-commit-config.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@ repos:
88
- id: trailing-whitespace
99

1010
- repo: https://github.com/astral-sh/ruff-pre-commit
11-
rev: "v0.9.3"
11+
rev: "v0.11.10"
1212
hooks:
1313
- id: ruff-format
1414
args: [--config=pyproject.toml]
15+
- id: ruff-check
16+
args: [--config=pyproject.toml, --fix]
1517

1618
- repo: https://github.com/pre-commit/mirrors-prettier
1719
rev: "v3.1.0"
1820
hooks:
1921
- id: prettier
2022
additional_dependencies:
21-
- prettier@3.4.2
22-
23+
- prettier@3.5.3
24+

CHANGELOG.md

Lines changed: 118 additions & 52 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,21 @@ when using cmd.
3030
![system schema](https://raw.githubusercontent.com/python-cmd2/cmd2/master/.github/images/graph.drawio.png)
3131

3232
When creating solutions developers have no shortage of tools to create rich and smart user interfaces.
33-
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.
33+
System administrators have long been duct taping together brittle workflows based on a menagerie of simple command line
34+
tools created by strangers on github and the guy down the hall.
3435
Unfortunately, when CLIs become significantly complex the ease of command discoverability tends to fade quickly.
35-
On the other hand, Web and traditional desktop GUIs are first in class when it comes to easily discovering functionality.
36-
The price we pay for beautifully colored displays is complexity required to aggregate disperate applications into larger systems.
37-
`cmd2` fills the niche between high [ease of command discovery](https://clig.dev/#ease-of-discovery) applications and smart workflow automation systems.
38-
39-
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.
40-
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:
36+
On the other hand, Web and traditional desktop GUIs are first in class when it comes to easily discovering
37+
functionality.
38+
The price we pay for beautifully colored displays is complexity required to aggregate disperate applications into larger
39+
systems.
40+
`cmd2` fills the niche between high [ease of command discovery](https://clig.dev/#ease-of-discovery) applications and
41+
smart workflow automation systems.
42+
43+
The `cmd2` framework provides a great mixture of both worlds. Application designers can easily create complex
44+
applications and rely on the cmd2 library to offer effortless user facing help and extensive tab completion.
45+
When users become comfortable with functionality, cmd2 turns into a feature rich library enabling a smooth transition to
46+
full automation. If designed with enough forethought, a well implemented cmd2 application can serve as a boutique
47+
workflow tool. `cmd2` pulls off this flexibility based on two pillars of philosophy:
4148

4249
- Tab Completion
4350
- Automation Transition
@@ -46,7 +53,8 @@ When users become comfortable with functionality, cmd2 turns into a feature rich
4653

4754
<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>
4855

49-
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.
56+
Deep extensive tab completion and help text generation based on the argparse library create the first pillar of 'ease of
57+
command discovery'. The following is a list of features in this category.
5058

5159
- Great tab completion of commands, subcommands, file system paths, and shell commands.
5260
- Custom tab completion for user designed commands via simple function overloading.
@@ -57,7 +65,8 @@ Deep extensive tab completion and help text generation based on the argparse lib
5765

5866
<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>
5967

60-
cmd2 creates the second pillar of 'ease of transition to automation' through alias creation, command line argument parsing and execution of cmd2 scripting.
68+
cmd2 creates the second pillar of 'ease of transition to automation' through alias/macro creation, command line argument
69+
parsing and execution of cmd2 scripting.
6170

6271
- Flexible alias creation for quick abstraction of commands.
6372
- Text file scripting of your application with `run_script` (`@`) and `_relative_run_script` (`@@`)
@@ -94,7 +103,8 @@ The best way to learn the cmd2 api is to delve into the example applications loc
94103
- [example code](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples)
95104
- [Cookiecutter](https://github.com/cookiecutter/cookiecutter) Templates from community
96105
- Basic cookiecutter template for cmd2 application : https://github.com/jayrod/cookiecutter-python-cmd2
97-
- Advanced cookiecutter template with external plugin support : https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug
106+
- Advanced cookiecutter template with external plugin
107+
support : https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug
98108
- [cmd2 example applications](https://github.com/python-cmd2/cmd2/tree/master/examples)
99109
- Basic cmd2 examples to demonstrate how to use various features
100110
- [Advanced Examples](https://github.com/jayrod/cmd2-example-apps)
@@ -111,19 +121,25 @@ import cmd2
111121
class FirstApp(cmd2.Cmd):
112122
"""A simple cmd2 application."""
113123

114-
def do_hello_world(self, _: cmd2.Statement):
124+
125+
def do_hello_world(self, _: cmd2.Statement):
115126
self.poutput('Hello World')
116127

128+
117129
if __name__ == '__main__':
118130
import sys
131+
119132
c = FirstApp()
120133
sys.exit(c.cmdloop())
121134

122135
```
123136

124137
## Found a bug?
125138

126-
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:
139+
If you think you've found a bug, please first read through the
140+
open [Issues](https://github.com/python-cmd2/cmd2/issues). If you're confident it's a new bug, go ahead and create a new
141+
GitHub issue. Be sure to include as much information as possible so we can reproduce the bug. At a minimum, please state
142+
the following:
127143

128144
- `cmd2` version
129145
- Python version

cmd2/argparse_custom.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,9 @@ def __init__(
13431343
conflict_handler: str = 'error',
13441344
add_help: bool = True,
13451345
allow_abbrev: bool = True,
1346+
exit_on_error: bool = True,
1347+
suggest_on_error: bool = False,
1348+
color: bool = False,
13461349
*,
13471350
ap_completer_type: Optional[Type['ArgparseCompleter']] = None,
13481351
) -> None:
@@ -1353,20 +1356,42 @@ def __init__(
13531356
behavior on this parser. If this is None or not present, then cmd2 will use
13541357
argparse_completer.DEFAULT_AP_COMPLETER when tab completing this parser's arguments
13551358
"""
1356-
super(Cmd2ArgumentParser, self).__init__(
1357-
prog=prog,
1358-
usage=usage,
1359-
description=description, # type: ignore[arg-type]
1360-
epilog=epilog, # type: ignore[arg-type]
1361-
parents=parents if parents else [],
1362-
formatter_class=formatter_class,
1363-
prefix_chars=prefix_chars,
1364-
fromfile_prefix_chars=fromfile_prefix_chars,
1365-
argument_default=argument_default,
1366-
conflict_handler=conflict_handler,
1367-
add_help=add_help,
1368-
allow_abbrev=allow_abbrev,
1369-
)
1359+
if sys.version_info[1] >= 14:
1360+
# Python >= 3.14 so pass new arguments to parent argparse.ArgumentParser class
1361+
super(Cmd2ArgumentParser, self).__init__(
1362+
prog=prog,
1363+
usage=usage,
1364+
description=description, # type: ignore[arg-type]
1365+
epilog=epilog, # type: ignore[arg-type]
1366+
parents=parents if parents else [],
1367+
formatter_class=formatter_class,
1368+
prefix_chars=prefix_chars,
1369+
fromfile_prefix_chars=fromfile_prefix_chars,
1370+
argument_default=argument_default,
1371+
conflict_handler=conflict_handler,
1372+
add_help=add_help,
1373+
allow_abbrev=allow_abbrev,
1374+
exit_on_error=exit_on_error,
1375+
suggest_on_error=suggest_on_error,
1376+
color=color,
1377+
)
1378+
else:
1379+
# Python < 3.14, so don't pass new arguments to parent argparse.ArgumentParser class
1380+
super(Cmd2ArgumentParser, self).__init__(
1381+
prog=prog,
1382+
usage=usage,
1383+
description=description, # type: ignore[arg-type]
1384+
epilog=epilog, # type: ignore[arg-type]
1385+
parents=parents if parents else [],
1386+
formatter_class=formatter_class,
1387+
prefix_chars=prefix_chars,
1388+
fromfile_prefix_chars=fromfile_prefix_chars,
1389+
argument_default=argument_default,
1390+
conflict_handler=conflict_handler,
1391+
add_help=add_help,
1392+
allow_abbrev=allow_abbrev,
1393+
exit_on_error=exit_on_error,
1394+
)
13701395

13711396
# Recast to assist type checkers since in a Cmd2HelpFormatter, these can be Rich renderables.
13721397
self.description: Optional[RenderableType] = self.description # type: ignore[assignment]
@@ -1460,7 +1485,7 @@ def format_help(self) -> str:
14601485
# determine help from format above
14611486
return formatter.format_help() + '\n'
14621487

1463-
def _print_message(self, message: str, file: Optional[IO[str]] = None) -> None:
1488+
def _print_message(self, message: str, file: Optional[IO[str]] = None) -> None: # type: ignore[override]
14641489
# Override _print_message to use style_aware_write() since we use ANSI escape characters to support color
14651490
if message:
14661491
if file is None:

docs/overview/installation.md

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Installation Instructions
22

3-
`cmd2` works on Linux, macOS, and Windows. It requires Python 3.8 or higher, [pip](https://pypi.org/project/pip), and [setuptools](https://pypi.org/project/setuptools). If you've got all that, then you can just:
3+
`cmd2` works on Linux, macOS, and Windows. It requires Python 3.9 or higher, [pip](https://pypi.org/project/pip),
4+
and [setuptools](https://pypi.org/project/setuptools). If you've got all that, then you can just:
45

56
```shell
67
$ pip install cmd2
@@ -16,7 +17,9 @@ $ pip install cmd2
1617

1718
## Prerequisites
1819

19-
If you have Python 3 >=3.8 installed from [python.org](https://www.python.org), you will already have [pip](https://pypi.org/project/pip) and [setuptools](https://pypi.org/project/setuptools), but may need to upgrade to the latest versions:
20+
If you have Python 3 >=3.9 installed from [python.org](https://www.python.org), you will already
21+
have [pip](https://pypi.org/project/pip) and [setuptools](https://pypi.org/project/setuptools), but may need to upgrade
22+
to the latest versions:
2023

2124
On Linux or OS X:
2225

@@ -32,7 +35,8 @@ C:\> python -m pip install -U pip setuptools
3235

3336
## Install from PyPI {: #pip_install }
3437

35-
[pip](https://pypi.org/project/pip) is the recommended installer. Installing packages from [PyPI](https://pypi.org) with pip is easy:
38+
[pip](https://pypi.org/project/pip) is the recommended installer. Installing packages from [PyPI](https://pypi.org) with
39+
pip is easy:
3640

3741
```shell
3842
$ pip install cmd2
@@ -42,15 +46,17 @@ This will install the required 3rd-party dependencies, if necessary.
4246

4347
## Install from GitHub {: #github }
4448

45-
The latest version of `cmd2` can be installed directly from the master branch on GitHub using [pip](https://pypi.org/project/pip):
49+
The latest version of `cmd2` can be installed directly from the master branch on GitHub
50+
using [pip](https://pypi.org/project/pip):
4651

4752
```shell
4853
$ pip install -U git+git://github.com/python-cmd2/cmd2.git
4954
```
5055

5156
## Install from Debian or Ubuntu repos
5257

53-
We recommend installing from [pip](https://pypi.org/project/pip), but if you wish to install from Debian or Ubuntu repos this can be done with apt-get.
58+
We recommend installing from [pip](https://pypi.org/project/pip), but if you wish to install from Debian or Ubuntu repos
59+
this can be done with apt-get.
5460

5561
For Python 3:
5662

@@ -78,13 +84,19 @@ If you wish to permanently uninstall `cmd2`, this can also easily be done with [
7884

7985
## readline Considerations
8086

81-
Tab completion for `cmd2` applications is only tested against GNU Readline. It does not work properly with the [libedit](http://thrysoee.dk/editline/) library which is similar, but not identical to GNU Readline. `cmd2` will disable all tab-completion support if an incompatible version of `readline` is found.
87+
Tab completion for `cmd2` applications is only tested against GNU Readline. It does not work properly with
88+
the [libedit](http://thrysoee.dk/editline/) library which is similar, but not identical to GNU Readline. `cmd2` will
89+
disable all tab-completion support if an incompatible version of `readline` is found.
8290

83-
When installed using `pip`, `uv`, or similar Python packaging tool on either `macOS` or `Windows`, `cmd2` will automatically install a compatiable version of readline.
91+
When installed using `pip`, `uv`, or similar Python packaging tool on either `macOS` or `Windows`, `cmd2` will
92+
automatically install a compatiable version of readline.
8493

85-
Most `Linux` OSes come with a compatible version of readline. However, if you are using a tool like `uv` to install Python on your system and configure a virtual environment, `uv` installed versions of Python come with `libEdit`.
94+
Most `Linux` OSes come with a compatible version of readline. However, if you are using a tool like `uv` to install
95+
Python on your system and configure a virtual environment, `uv` installed versions of Python come with `libEdit`.
8696

87-
macOS comes with the [libedit](http://thrysoee.dk/editline/) library which is similar, but not identical, to GNU Readline. Tab completion for `cmd2` applications is only tested against GNU Readline. In this case you just need to install the `gnureadline` Python package which is statically linked against GNU Readline:
97+
macOS comes with the [libedit](http://thrysoee.dk/editline/) library which is similar, but not identical, to GNU
98+
Readline. Tab completion for `cmd2` applications is only tested against GNU Readline. In this case you just need to
99+
install the `gnureadline` Python package which is statically linked against GNU Readline:
88100

89101
```shell
90102
$ pip install -U gnureadline

plugins/ext_test/setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
'Programming Language :: Python :: 3.11',
4949
'Programming Language :: Python :: 3.12',
5050
'Programming Language :: Python :: 3.13',
51+
'Programming Language :: Python :: 3.14',
5152
],
5253
# dependencies for development and testing
5354
# $ pip install -e .[dev]

plugins/template/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@ and an example app which uses the plugin:
5151
import cmd2
5252
import cmd2_myplugin
5353

54+
5455
class Example(cmd2_myplugin.MyPlugin, cmd2.Cmd):
5556
"""An class to show how to use a plugin"""
57+
5658
def __init__(self, *args, **kwargs):
5759
# code placed here runs before cmd2.Cmd or
5860
# any plugins initialize

0 commit comments

Comments
 (0)