1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
Author: Stephen Finucane <sfinucan@redhat.com>
Date: Tue, 03 Mar 2026 12:10:54 +0000
Description: Fix compatibility with cmd2 3.1.0+
cmd2 3.1.0 has removed the dependency on the stdlib cmd library [1]. For
our use cases, the largest change is that we no longer have the
'completenames' helper, which was defined in `cmd.Cmd` rather than
`cmd2.Cmd`. However, upon further inspection is seems this helper was
never actually used. It was not called directly in cmd2 2.x and was only
used in cmd in two locations: `Cmd.complete` [2] and `Cmd.complete_help`
[3]. cmd2 2.x entirely overrode the former [4] and deleted the latter,
meaning we were not actually using any of that code. Therefore we can
just delete the helper and any tests for same and suffer no ill effects.
To be safe though, we bump our cmd2 minimum to 3.0.0.
.
While here, we also need to fix some type hints to account for the cmd2
bump along with a related autopage bump.
.
[1] https://github.com/python-cmd2/cmd2/releases/tag/3.1.0
[2] https://github.com/python/cpython/blob/v3.10.20/Lib/cmd.py#L274
[3] https://github.com/python/cpython/blob/v3.10.20/Lib/cmd.py#L287
[4] https://github.com/python-cmd2/cmd2/blob/2.7.0/cmd2/cmd2.py#L2192-L2294
[5] https://github.com/python-cmd2/cmd2/blob/2.7.0/cmd2/cmd2.py#L3770-L3772
Change-Id: I75933ec1ffc2dc8d57d4105c5683892ddbf50bff
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
Origin: upstream, https://review.opendev.org/c/openstack/cliff/+/978994
Last-Update: 2026-03-27
diff --git a/cliff/formatters/table.py b/cliff/formatters/table.py
index 6546a76..771130f 100644
--- a/cliff/formatters/table.py
+++ b/cliff/formatters/table.py
@@ -51,7 +51,7 @@
class TableFormatter(base.ListFormatter, base.SingleFormatter):
- ALIGNMENTS = {
+ ALIGNMENTS: dict[type[int | str | float], ty.Literal['l', 'c', 'r']] = {
int: 'r',
str: 'l',
float: 'r',
diff --git a/cliff/interactive.py b/cliff/interactive.py
index 607d3f8..0f65abb 100644
--- a/cliff/interactive.py
+++ b/cliff/interactive.py
@@ -73,7 +73,7 @@
parts.insert(0, line.command)
return parts
- def default(self, line: str) -> bool | None: # type: ignore[override]
+ def default(self, line: str) -> bool | None:
# Tie in the default command processor to
# dispatch commands known to the command manager.
# We send the message through our parent app,
@@ -87,17 +87,7 @@
return bool(ret)
return None
- def completenames(self, text: str, *ignored: ty.Any) -> list[str]:
- """Tab-completion for command prefix without completer delimiter.
-
- This method returns cmd style and cliff style commands matching
- provided command prefix (text).
- """
- completions = cmd2.Cmd.completenames(self, text)
- completions += self._complete_prefix(text)
- return completions
-
- def completedefault(
+ def completedefault( # type: ignore[override]
self, text: str, line: str, begidx: int, endidx: int
) -> list[str]:
"""Default tab-completion for command prefix with completer delimiter.
@@ -146,7 +136,7 @@
else:
stdout = self.stdout
try:
- with autopage.argparse.help_pager(stdout) as paged_out: # type: ignore
+ with autopage.argparse.help_pager(stdout) as paged_out:
self.stdout = paged_out
cmd2.Cmd.do_help(self, arg) # type: ignore
diff --git a/cliff/tests/base.py b/cliff/tests/base.py
index cace122..4e55fce 100644
--- a/cliff/tests/base.py
+++ b/cliff/tests/base.py
@@ -11,7 +11,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools # type: ignore
+import testtools
import fixtures
diff --git a/cliff/tests/test_commandmanager.py b/cliff/tests/test_commandmanager.py
index f17b5b7..53ff464 100644
--- a/cliff/tests/test_commandmanager.py
+++ b/cliff/tests/test_commandmanager.py
@@ -30,6 +30,8 @@
('three-words', {'argv': ['three', 'word', 'command']}),
]
+ argv: list[str]
+
def test(self):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
cmd, name, remaining = mgr.find_command(self.argv)
@@ -45,6 +47,8 @@
('three', {'argv': ['three', 'word', 'command', '--opt']}),
]
+ argv: list[str]
+
def test(self):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
cmd, name, remaining = mgr.find_command(self.argv)
@@ -58,6 +62,8 @@
('no-command-given', {'argv': ['-b']}),
]
+ argv: list[str]
+
def test(self):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
try:
@@ -246,6 +252,8 @@
('three-words', {'argv': ['t', 'w', 'c']}),
]
+ argv: list[str]
+
def test(self):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
cmd, name, remaining = mgr.find_command(self.argv)
diff --git a/cliff/tests/test_interactive.py b/cliff/tests/test_interactive.py
index 2936f07..55645bd 100644
--- a/cliff/tests/test_interactive.py
+++ b/cliff/tests/test_interactive.py
@@ -11,7 +11,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import cmd2
from cliff import app
from cliff.interactive import InteractiveApp
@@ -32,33 +31,6 @@
errexit=errexit,
)
- def _test_completenames(self, expecteds, prefix):
- app = self.make_interactive_app(False, 'hips', 'hippo', 'nonmatching')
- self.assertEqual(
- set(app.completenames(prefix, '', 0, 1)), set(expecteds)
- )
-
- def test_cmd2_completenames(self):
- # cmd2.Cmd define do_help method
- self._test_completenames(['help'], 'he')
-
- def test_cliff_completenames(self):
- self._test_completenames(['hips', 'hippo'], 'hip')
-
- def test_no_completenames(self):
- self._test_completenames([], 'taz')
-
- def test_both_completenames(self):
- # cmd2.Cmd define do_history method
- # NOTE(dtroyer): Before release 0.7.0 do_hi was also defined so we need
- # to account for that in the list of possible responses.
- # Remove this check after cmd2 0.7.0 is the minimum
- # requirement.
- if hasattr(cmd2.Cmd, "do_hi"):
- self._test_completenames(['hi', 'history', 'hips', 'hippo'], 'hi')
- else:
- self._test_completenames(['history', 'hips', 'hippo'], 'hi')
-
def _test_completedefault(self, expecteds, line, begidx):
command_names = set(
['show file', 'show folder', 'show long', 'list all']
diff --git a/requirements.txt b/requirements.txt
index 94ac040..bc95ac5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
autopage>=0.4.0 # Apache 2.0
-cmd2>=1.0.0 # MIT
+cmd2>=3.0.0 # MIT
PrettyTable>=0.7.2 # BSD
stevedore>=5.6.0 # Apache-2.0
PyYAML>=3.12 # MIT
|