Skip to content

Commit 7919bae

Browse files
committed
Add types to input.py, console.pu, and commands.py
1 parent 6c188fb commit 7919bae

9 files changed

Lines changed: 198 additions & 143 deletions

File tree

Lib/_pyrepl/commands.py

Lines changed: 69 additions & 95 deletions
Large diffs are not rendered by default.

Lib/_pyrepl/console.py

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1818
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1919

20+
from abc import ABC, abstractmethod
2021
import dataclasses
2122

2223

@@ -27,66 +28,87 @@ class Event:
2728
raw: bytes = b""
2829

2930

30-
class Console:
31+
class Console(ABC):
3132
"""Attributes:
3233
3334
screen,
3435
height,
3536
width,
3637
"""
3738

38-
def refresh(self, screen, xy):
39-
pass
39+
@abstractmethod
40+
def refresh(self, screen: list[str], xy: tuple[int, int]) -> None:
41+
...
4042

41-
def prepare(self):
42-
pass
43+
@abstractmethod
44+
def prepare(self) -> None:
45+
...
4346

44-
def restore(self):
45-
pass
47+
@abstractmethod
48+
def restore(self) -> None:
49+
...
4650

47-
def move_cursor(self, x, y):
48-
pass
51+
@abstractmethod
52+
def move_cursor(self, x: int, y: int) -> None:
53+
...
4954

50-
def set_cursor_vis(self, vis):
51-
pass
55+
@abstractmethod
56+
def set_cursor_vis(self, visible: bool) -> None:
57+
...
5258

53-
def getheightwidth(self):
59+
@abstractmethod
60+
def getheightwidth(self) -> tuple[int, int]:
5461
"""Return (height, width) where height and width are the height
5562
and width of the terminal window in characters."""
56-
pass
63+
...
5764

58-
def get_event(self, block=1):
65+
@abstractmethod
66+
def get_event(self, block: bool = True) -> Event:
5967
"""Return an Event instance. Returns None if |block| is false
6068
and there is no event pending, otherwise waits for the
6169
completion of an event."""
62-
pass
70+
...
6371

64-
def beep(self):
65-
pass
72+
@abstractmethod
73+
def push_char(self, char: str) -> None:
74+
"""
75+
Push a character to the console event queue.
76+
"""
77+
...
6678

67-
def clear(self):
79+
@abstractmethod
80+
def beep(self) -> None:
81+
...
82+
83+
@abstractmethod
84+
def clear(self) -> None:
6885
"""Wipe the screen"""
69-
pass
86+
...
7087

71-
def finish(self):
88+
@abstractmethod
89+
def finish(self) -> None:
7290
"""Move the cursor to the end of the display and otherwise get
7391
ready for end. XXX could be merged with restore? Hmm."""
74-
pass
92+
...
7593

76-
def flushoutput(self):
94+
@abstractmethod
95+
def flushoutput(self) -> None:
7796
"""Flush all output to the screen (assuming there's some
7897
buffering going on somewhere)."""
79-
pass
98+
...
8099

81-
def forgetinput(self):
100+
@abstractmethod
101+
def forgetinput(self) -> None:
82102
"""Forget all pending, but not yet processed input."""
83-
pass
103+
...
84104

85-
def getpending(self):
105+
@abstractmethod
106+
def getpending(self) -> Event:
86107
"""Return the characters that have been typed but not yet
87108
processed."""
88-
pass
109+
...
89110

90-
def wait(self):
111+
@abstractmethod
112+
def wait(self) -> None:
91113
"""Wait for an event."""
92-
pass
114+
...

Lib/_pyrepl/historical_reader.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@
1717
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1818
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1919

20+
from __future__ import annotations
21+
2022
from contextlib import contextmanager
2123

2224
from . import commands, input
23-
from .reader import Reader as R
25+
from .reader import Reader
26+
27+
28+
if False:
29+
from .types import Callback, SimpleContextManager, KeySpec, CommandName
2430

25-
isearch_keymap = tuple(
31+
32+
isearch_keymap: tuple[tuple[KeySpec, CommandName], ...] = tuple(
2633
[("\\%03o" % c, "isearch-end") for c in range(256) if chr(c) != "\\"]
2734
+ [(c, "isearch-add-character") for c in map(chr, range(32, 127)) if c != "\\"]
2835
+ [
@@ -46,7 +53,7 @@
4653

4754

4855
class next_history(commands.Command):
49-
def do(self):
56+
def do(self) -> None:
5057
r = self.reader
5158
if r.historyi == len(r.history):
5259
r.error("end of history list")
@@ -190,7 +197,7 @@ def do(self):
190197
r.dirty = 1
191198

192199

193-
class HistoricalReader(R):
200+
class HistoricalReader(Reader):
194201
"""Adds history support (with incremental history searching) to the
195202
Reader class.
196203

Lib/_pyrepl/input.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,32 @@
3232
# executive, temporary decision: [tab] and [C-i] are distinct, but
3333
# [meta-key] is identified with [esc key]. We demand that any console
3434
# class does quite a lot towards emulating a unix terminal.
35+
36+
from __future__ import annotations
37+
38+
from abc import ABC, abstractmethod
3539
import unicodedata
3640
from collections import deque
3741

3842

39-
class InputTranslator:
40-
def push(self, evt):
41-
pass
43+
# types
44+
if False:
45+
from .types import EventTuple
4246

43-
def get(self):
44-
pass
4547

46-
def empty(self):
48+
class InputTranslator(ABC):
49+
@abstractmethod
50+
def push(self, evt: EventTuple) -> None:
4751
pass
4852

53+
@abstractmethod
54+
def get(self) -> EventTuple | None:
55+
return None
56+
57+
@abstractmethod
58+
def empty(self) -> bool:
59+
return True
60+
4961

5062
class KeymapTranslator(InputTranslator):
5163
def __init__(self, keymap, verbose=0, invalid_cls=None, character_cls=None):

Lib/_pyrepl/reader.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,8 @@ def make_default_commands() -> dict[CommandName, type[Command]]:
105105
(r"\C-k", "kill-line"),
106106
(r"\C-l", "clear-screen"),
107107
(r"\C-m", "accept"),
108-
(r"\C-q", "quoted-insert"),
109108
(r"\C-t", "transpose-characters"),
110109
(r"\C-u", "unix-line-discard"),
111-
(r"\C-v", "quoted-insert"),
112110
(r"\C-w", "unix-word-rubout"),
113111
(r"\C-x\C-u", "upcase-region"),
114112
(r"\C-y", "yank"),
@@ -142,7 +140,6 @@ def make_default_commands() -> dict[CommandName, type[Command]]:
142140
(r"\<down>", "down"),
143141
(r"\<left>", "left"),
144142
(r"\<right>", "right"),
145-
(r"\<insert>", "quoted-insert"),
146143
(r"\<delete>", "delete"),
147144
(r"\<backspace>", "backspace"),
148145
(r"\M-\<backspace>", "backward-kill-word"),
@@ -464,9 +461,9 @@ def update_cursor(self) -> None:
464461
self.cxy = self.pos2xy(self.pos)
465462
self.console.move_cursor(*self.cxy)
466463

467-
def after_command(self, cmd) -> None:
464+
def after_command(self, cmd: Command) -> None:
468465
"""This function is called to allow post command cleanup."""
469-
if getattr(cmd, "kills_digit_arg", 1):
466+
if getattr(cmd, "kills_digit_arg", True):
470467
if self.arg is not None:
471468
self.dirty = True
472469
self.arg = None
@@ -537,7 +534,7 @@ def refresh(self) -> None:
537534
def do_cmd(self, cmd) -> None:
538535
if isinstance(cmd[0], str):
539536
cmd = self.commands.get(cmd[0], commands.invalid_command)(self, *cmd)
540-
elif isinstance(cmd[0], type):
537+
elif isinstance(cmd[0], type) and issubclass(cmd[0], commands.Command):
541538
cmd = cmd[0](self, *cmd)
542539
else:
543540
return # nothing to do

Lib/_pyrepl/readline.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
import os
3030
import readline
31-
from site import gethistoryfile
31+
from site import gethistoryfile # type: ignore[attr-defined]
3232
import sys
3333

3434
from . import commands, historical_reader

Lib/_pyrepl/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
SimpleContextManager = Iterator[None]
55
KeySpec = str # like r"\C-c"
66
CommandName = str # like "interrupt"
7+
EventTuple = tuple[CommandName, str]

Lib/_pyrepl/unix_console.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ def push_char(self, char):
349349
trace("push char {char!r}", char=char)
350350
self.event_queue.push(char)
351351

352-
def get_event(self, block=True):
352+
def get_event(self, block: bool = True) -> Event:
353353
"""
354354
Get an event from the console event queue.
355355

Lib/test/test_pyrepl.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,51 @@ def __init__(self, events, encoding="utf-8"):
5555
self.height = 100
5656
self.width = 80
5757

58-
def get_event(self, block=True):
58+
def get_event(self, block: bool = True) -> Event:
5959
return next(self.events)
6060

61+
def getpending(self) -> Event:
62+
return self.get_event(block=False)
63+
64+
def getheightwidth(self) -> tuple[int, int]:
65+
return self.height, self.width
66+
67+
def refresh(self, screen: list[str], xy: tuple[int, int]) -> None:
68+
pass
69+
70+
def prepare(self) -> None:
71+
pass
72+
73+
def restore(self) -> None:
74+
pass
75+
76+
def move_cursor(self, x: int, y: int) -> None:
77+
pass
78+
79+
def set_cursor_vis(self, visible: bool) -> None:
80+
pass
81+
82+
def push_char(self, char: str) -> None:
83+
pass
84+
85+
def beep(self) -> None:
86+
pass
87+
88+
def clear(self) -> None:
89+
pass
90+
91+
def finish(self) -> None:
92+
pass
93+
94+
def flushoutput(self) -> None:
95+
pass
96+
97+
def forgetinput(self) -> None:
98+
pass
99+
100+
def wait(self) -> None:
101+
pass
102+
61103

62104
class TestPyReplDriver(TestCase):
63105
def prepare_reader(self, events):

0 commit comments

Comments
 (0)