Skip to content

Commit d309493

Browse files
committed
history, py_bridge, transcript now passs mypy
1 parent 295ec39 commit d309493

File tree

4 files changed

+48
-37
lines changed

4 files changed

+48
-37
lines changed

cmd2/cmd2.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3635,7 +3635,7 @@ def _print_topics(self, header: str, cmds: List[str], verbose: bool) -> None:
36353635
stdout_orig = self.stdout
36363636
try:
36373637
# redirect our internal stdout
3638-
self.stdout = result
3638+
self.stdout = cast(TextIO, result)
36393639
help_func()
36403640
finally:
36413641
# restore internal stdout
@@ -3883,7 +3883,7 @@ def do_shell(self, args: argparse.Namespace) -> None:
38833883
shell=True,
38843884
)
38853885

3886-
proc_reader = utils.ProcReader(proc, self.stdout, sys.stderr)
3886+
proc_reader = utils.ProcReader(proc, cast(TextIO, self.stdout), sys.stderr)
38873887
proc_reader.wait()
38883888

38893889
# Save the return code of the application for use in a pyscript
@@ -4563,7 +4563,7 @@ def _generate_transcript(self, history: Union[List[HistoryItem], List[str]], tra
45634563
with self.sigint_protection:
45644564
# Restore altered attributes to their original state
45654565
self.echo = saved_echo
4566-
self.stdout = saved_stdout
4566+
self.stdout = cast(TextIO, saved_stdout)
45674567

45684568
# Check if all commands ran
45694569
if commands_run < len(history):

cmd2/history.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from typing import (
1111
Callable,
1212
Optional,
13-
Union,
13+
Union, List, Iterable, overload,
1414
)
1515

1616
import attr
@@ -23,16 +23,16 @@
2323
)
2424

2525

26-
@attr.s(frozen=True)
26+
@attr.s(auto_attribs=True, frozen=True)
2727
class HistoryItem:
2828
"""Class used to represent one command in the history list"""
2929

3030
_listformat = ' {:>4} {}'
3131
_ex_listformat = ' {:>4}x {}'
3232

33-
statement = attr.ib(default=None, validator=attr.validators.instance_of(Statement))
33+
statement: Statement = attr.ib(default=None, validator=attr.validators.instance_of(Statement))
3434

35-
def __str__(self):
35+
def __str__(self) -> str:
3636
"""A convenient human readable representation of the history item"""
3737
return self.statement.raw
3838

@@ -66,11 +66,11 @@ def pr(self, idx: int, script: bool = False, expanded: bool = False, verbose: bo
6666
"""
6767
if verbose:
6868
raw = self.raw.rstrip()
69-
expanded = self.expanded
69+
expanded_command = self.expanded
7070

7171
ret_str = self._listformat.format(idx, raw)
72-
if raw != expanded:
73-
ret_str += '\n' + self._ex_listformat.format(idx, expanded)
72+
if raw != expanded_command:
73+
ret_str += '\n' + self._ex_listformat.format(idx, expanded_command)
7474
else:
7575
if expanded:
7676
ret_str = self.expanded
@@ -92,7 +92,7 @@ def pr(self, idx: int, script: bool = False, expanded: bool = False, verbose: bo
9292
return ret_str
9393

9494

95-
class History(list):
95+
class History(List[HistoryItem]):
9696
"""A list of :class:`~cmd2.history.HistoryItem` objects with additional methods
9797
for searching and managing the list.
9898
@@ -106,8 +106,8 @@ class History(list):
106106
class to gain access to the historical record.
107107
"""
108108

109-
def __init__(self, seq=()) -> None:
110-
super().__init__(seq)
109+
def __init__(self, seq: Iterable[HistoryItem] = ()) -> None:
110+
super(History, self).__init__(seq)
111111
self.session_start_index = 0
112112

113113
def start_session(self) -> None:
@@ -122,14 +122,25 @@ def _zero_based_index(self, onebased: Union[int, str]) -> int:
122122
result -= 1
123123
return result
124124

125+
@overload
126+
def append(self, new: HistoryItem) -> None:
127+
...
128+
129+
@overload
125130
def append(self, new: Statement) -> None:
131+
...
132+
133+
def append(self, new: Union[Statement, HistoryItem]) -> None:
126134
"""Append a new statement to the end of the History list.
127135
128136
:param new: Statement object which will be composed into a HistoryItem
129137
and added to the end of the list
130138
"""
131-
history_item = HistoryItem(new)
132-
super().append(history_item)
139+
if isinstance(new, Statement):
140+
history_item = HistoryItem(new)
141+
else:
142+
history_item = new
143+
super(History, self).append(history_item)
133144

134145
def clear(self) -> None:
135146
"""Remove all items from the History list."""
@@ -206,17 +217,17 @@ def span(self, span: str, include_persisted: bool = False) -> 'OrderedDict[int,
206217
# our regex doesn't match the input, bail out
207218
raise ValueError('History indices must be positive or negative integers, and may not be zero.')
208219

209-
start = results.group('start')
210-
if start:
211-
start = min(self._zero_based_index(start), len(self) - 1)
220+
start_token = results.group('start')
221+
if start_token:
222+
start = min(self._zero_based_index(start_token), len(self) - 1)
212223
if start < 0:
213224
start = max(0, len(self) + start)
214225
else:
215226
start = 0 if include_persisted else self.session_start_index
216227

217-
end = results.group('end')
218-
if end:
219-
end = min(int(end), len(self))
228+
end_token = results.group('end')
229+
if end_token:
230+
end = min(int(end_token), len(self))
220231
if end < 0:
221232
end = max(0, len(self) + end + 1)
222233
else:

cmd2/py_bridge.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
NamedTuple,
1818
Optional,
1919
TextIO,
20-
cast,
20+
cast, Union,
2121
)
2222

2323
from .utils import ( # namedtuple_with_defaults,
@@ -110,7 +110,7 @@ def __call__(self, command: str, *, echo: Optional[bool] = None) -> CommandResul
110110
echo = self.cmd_echo
111111

112112
# This will be used to capture _cmd2_app.stdout and sys.stdout
113-
copy_cmd_stdout = StdSim(self._cmd2_app.stdout, echo=echo)
113+
copy_cmd_stdout = StdSim(cast(Union[TextIO, StdSim], self._cmd2_app.stdout), echo=echo)
114114

115115
# Pause the storing of stdout until onecmd_plus_hooks enables it
116116
copy_cmd_stdout.pause_storage = True

cmd2/transcript.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class is used in cmd2.py::run_transcript_tests()
1616
List,
1717
Optional,
1818
Tuple,
19-
cast,
19+
cast, Iterator, IO, TextIO,
2020
)
2121

2222
from . import (
@@ -42,34 +42,34 @@ class Cmd2TestCase(unittest.TestCase):
4242

4343
cmdapp: Optional['Cmd'] = None
4444

45-
def setUp(self):
45+
def setUp(self) -> None:
4646
if self.cmdapp:
4747
self._fetchTranscripts()
4848

4949
# Trap stdout
5050
self._orig_stdout = self.cmdapp.stdout
51-
self.cmdapp.stdout = utils.StdSim(self.cmdapp.stdout)
51+
self.cmdapp.stdout = cast(TextIO, utils.StdSim(cast(TextIO, self.cmdapp.stdout)))
5252

53-
def tearDown(self):
53+
def tearDown(self) -> None:
5454
if self.cmdapp:
5555
# Restore stdout
5656
self.cmdapp.stdout = self._orig_stdout
5757

58-
def runTest(self): # was testall
58+
def runTest(self) -> None: # was testall
5959
if self.cmdapp:
6060
its = sorted(self.transcripts.items())
6161
for (fname, transcript) in its:
6262
self._test_transcript(fname, transcript)
6363

64-
def _fetchTranscripts(self):
64+
def _fetchTranscripts(self) -> None:
6565
self.transcripts = {}
6666
testfiles = cast(List[str], getattr(self.cmdapp, 'testfiles', []))
6767
for fname in testfiles:
6868
tfile = open(fname)
6969
self.transcripts[fname] = iter(tfile.readlines())
7070
tfile.close()
7171

72-
def _test_transcript(self, fname: str, transcript):
72+
def _test_transcript(self, fname: str, transcript: Iterator[str]) -> None:
7373
if self.cmdapp is None:
7474
return
7575

@@ -86,24 +86,24 @@ def _test_transcript(self, fname: str, transcript):
8686
finished = True
8787
break
8888
line_num += 1
89-
command = [line[len(self.cmdapp.visible_prompt) :]]
89+
command_parts = [line[len(self.cmdapp.visible_prompt) :]]
9090
try:
9191
line = next(transcript)
9292
except StopIteration:
9393
line = ''
9494
line_num += 1
9595
# Read the entirety of a multi-line command
9696
while line.startswith(self.cmdapp.continuation_prompt):
97-
command.append(line[len(self.cmdapp.continuation_prompt) :])
97+
command_parts.append(line[len(self.cmdapp.continuation_prompt) :])
9898
try:
9999
line = next(transcript)
100100
except StopIteration as exc:
101101
msg = 'Transcript broke off while reading command beginning at line {} with\n{}'.format(
102-
line_num, command[0]
102+
line_num, command_parts[0]
103103
)
104104
raise StopIteration(msg) from exc
105105
line_num += 1
106-
command = ''.join(command)
106+
command = ''.join(command_parts)
107107
# Send the command into the application and capture the resulting output
108108
stop = self.cmdapp.onecmd_plus_hooks(command)
109109
result = self.cmdapp.stdout.read()
@@ -117,9 +117,9 @@ def _test_transcript(self, fname: str, transcript):
117117
# If the command signaled the application to quit there should be no more commands
118118
self.assertFalse(stop, stop_msg)
119119
continue
120-
expected = []
120+
expected_parts = []
121121
while not ansi.strip_style(line).startswith(self.cmdapp.visible_prompt):
122-
expected.append(line)
122+
expected_parts.append(line)
123123
try:
124124
line = next(transcript)
125125
except StopIteration:
@@ -132,7 +132,7 @@ def _test_transcript(self, fname: str, transcript):
132132
self.assertTrue(finished, stop_msg)
133133

134134
# transform the expected text into a valid regular expression
135-
expected = ''.join(expected)
135+
expected = ''.join(expected_parts)
136136
expected = self._transform_transcript_expected(expected)
137137
message = '\nFile {}, line {}\nCommand was:\n{}\nExpected:\n{}\nGot:\n{}\n'.format(
138138
fname, line_num, command, expected, result

0 commit comments

Comments
 (0)