From 033f5c87f1f876088701d1ae078dc39c41177d4a Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 17 May 2024 06:13:24 -0400 Subject: [PATCH] Improve `pyrepl` type-annotation coverage (#119081) --- Lib/_pyrepl/_minimal_curses.py | 2 +- Lib/_pyrepl/input.py | 4 ++-- Lib/_pyrepl/keymap.py | 2 +- Lib/_pyrepl/pager.py | 8 ++++++-- Lib/_pyrepl/readline.py | 7 +++++-- Lib/_pyrepl/unix_console.py | 22 ++++++++++++++++------ 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Lib/_pyrepl/_minimal_curses.py b/Lib/_pyrepl/_minimal_curses.py index 0757fb2c664..849617bf758 100644 --- a/Lib/_pyrepl/_minimal_curses.py +++ b/Lib/_pyrepl/_minimal_curses.py @@ -17,7 +17,7 @@ class error(Exception): pass -def _find_clib(): +def _find_clib() -> str: trylibs = ["ncursesw", "ncurses", "curses"] for lib in trylibs: diff --git a/Lib/_pyrepl/input.py b/Lib/_pyrepl/input.py index 300e16d1d25..21c24eb5cde 100644 --- a/Lib/_pyrepl/input.py +++ b/Lib/_pyrepl/input.py @@ -60,7 +60,7 @@ class InputTranslator(ABC): class KeymapTranslator(InputTranslator): - def __init__(self, keymap, verbose=0, invalid_cls=None, character_cls=None): + def __init__(self, keymap, verbose=False, invalid_cls=None, character_cls=None): self.verbose = verbose from .keymap import compile_keymap, parse_keys @@ -110,5 +110,5 @@ class KeymapTranslator(InputTranslator): else: return None - def empty(self): + def empty(self) -> bool: return not self.results diff --git a/Lib/_pyrepl/keymap.py b/Lib/_pyrepl/keymap.py index 31a02642ce8..e1421730e75 100644 --- a/Lib/_pyrepl/keymap.py +++ b/Lib/_pyrepl/keymap.py @@ -187,7 +187,7 @@ def _parse_key1(key, s): return ret, s -def parse_keys(key): +def parse_keys(key: str) -> list[str]: s = 0 r = [] while s < len(key): diff --git a/Lib/_pyrepl/pager.py b/Lib/_pyrepl/pager.py index af0409c4523..6a076b5181d 100644 --- a/Lib/_pyrepl/pager.py +++ b/Lib/_pyrepl/pager.py @@ -76,10 +76,14 @@ def tty_pager(text: str, title: str = '') -> None: fd = sys.stdin.fileno() old = termios.tcgetattr(fd) tty.setcbreak(fd) - getchar = lambda: sys.stdin.read(1) has_tty = True + + def getchar() -> str: + return sys.stdin.read(1) + except (ImportError, AttributeError, io.UnsupportedOperation): - getchar = lambda: sys.stdin.readline()[:-1][:1] + def getchar() -> str: + return sys.stdin.readline()[:-1][:1] try: try: diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index d28a7f3779f..0adecf235a4 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -48,6 +48,9 @@ from collections.abc import Callable, Collection from .types import Callback, Completer, KeySpec, CommandName +MoreLinesCallable = Callable[[str], bool] + + __all__ = [ "add_history", "clear_history", @@ -94,7 +97,7 @@ class ReadlineAlikeReader(historical_reader.HistoricalReader, CompletingReader): # Instance fields config: ReadlineConfig - more_lines: Callable[[str], bool] | None = None + more_lines: MoreLinesCallable | None = None def __post_init__(self) -> None: super().__post_init__() @@ -287,7 +290,7 @@ class _ReadlineWrapper: reader.ps1 = str(prompt) return reader.readline(startup_hook=self.startup_hook) - def multiline_input(self, more_lines, ps1, ps2): + def multiline_input(self, more_lines: MoreLinesCallable, ps1: str, ps2: str) -> tuple[str, bool]: """Read an input on possibly multiple lines, asking for more lines as long as 'more_lines(unicodetext)' returns an object whose boolean value is true. diff --git a/Lib/_pyrepl/unix_console.py b/Lib/_pyrepl/unix_console.py index 605318c82ae..7c59f48df40 100644 --- a/Lib/_pyrepl/unix_console.py +++ b/Lib/_pyrepl/unix_console.py @@ -40,9 +40,13 @@ from .unix_eventqueue import EventQueue from .utils import wlen +TYPE_CHECKING = False + # types -if False: - from typing import IO +if TYPE_CHECKING: + from typing import IO, Literal, overload +else: + overload = lambda func: None class InvalidTerminal(RuntimeError): @@ -157,7 +161,13 @@ class UnixConsole(Console): curses.setupterm(term or None, self.output_fd) self.term = term - def _my_getstr(cap, optional=0): + @overload + def _my_getstr(cap: str, optional: Literal[False] = False) -> bytes: ... + + @overload + def _my_getstr(cap: str, optional: bool) -> bytes | None: ... + + def _my_getstr(cap: str, optional: bool = False) -> bytes | None: r = curses.tigetstr(cap) if not optional and r is None: raise InvalidTerminal( @@ -672,18 +682,18 @@ class UnixConsole(Console): elif dy < 0: self.__write_code(self._cuu, -dy) - def __move_x_hpa(self, x): + def __move_x_hpa(self, x: int) -> None: if x != self.__posxy[0]: self.__write_code(self._hpa, x) - def __move_x_cub1_cuf1(self, x): + def __move_x_cub1_cuf1(self, x: int) -> None: dx = x - self.__posxy[0] if dx > 0: self.__write_code(self._cuf1 * dx) elif dx < 0: self.__write_code(self._cub1 * (-dx)) - def __move_x_cub_cuf(self, x): + def __move_x_cub_cuf(self, x: int) -> None: dx = x - self.__posxy[0] if dx > 0: self.__write_code(self._cuf, dx)