diff --git a/kittens/hints/main.py b/kittens/hints/main.py index c6b34cbd2..2246b6236 100644 --- a/kittens/hints/main.py +++ b/kittens/hints/main.py @@ -216,7 +216,7 @@ class Hints(Handler): self.write(self.current_text) -def regex_finditer(pat: Pattern, minimum_match_length: int, text: str) -> Generator[Tuple[int, int, Dict], None, None]: +def regex_finditer(pat: 'Pattern[str]', minimum_match_length: int, text: str) -> Generator[Tuple[int, int, Dict[str, str]], None, None]: has_named_groups = bool(pat.groupindex) for m in pat.finditer(text): s, e = m.span(0 if has_named_groups else pat.groups) @@ -444,7 +444,7 @@ def process_hyperlinks(text: str) -> Tuple[str, Tuple[Mark, ...]]: active_hyperlink_start_offset = 0 idx += 1 - def process_hyperlink(m: 're.Match') -> str: + def process_hyperlink(m: 're.Match[str]') -> str: nonlocal removed_size, active_hyperlink_url, active_hyperlink_id, active_hyperlink_start_offset raw = m.group() start = m.start() - removed_size diff --git a/kitty/boss.py b/kitty/boss.py index 6e2d45a6a..8fabd68a1 100755 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -9,8 +9,7 @@ from contextlib import suppress from functools import partial from gettext import gettext as _ from typing import ( - Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, - Union, cast + Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union, cast ) from weakref import WeakValueDictionary @@ -154,7 +153,7 @@ class Boss: set_layout_options(opts) self.cocoa_application_launched = False self.clipboard_buffers: Dict[str, str] = {} - self.update_check_process: Optional[PopenType] = None + self.update_check_process: Optional['PopenType[bytes]'] = None self.window_id_map: WeakValueDictionary[int, Window] = WeakValueDictionary() self.startup_colors = {k: opts[k] for k in opts if isinstance(opts[k], Color)} self.visual_window_select_callback: Optional[Callable[[Tab, Window], None]] = None @@ -946,7 +945,7 @@ class Boss: dispatch_type: str = 'KeyPress' ) -> bool: - def report_match(f: Callable) -> None: + def report_match(f: Callable[..., Any]) -> None: if self.args.debug_keyboard: prefix = '\n' if dispatch_type == 'KeyPress' else '' print(f'{prefix}\x1b[35m{dispatch_type}\x1b[m matched action:', func_name(f), flush=True) @@ -1148,8 +1147,8 @@ class Boss: args: Iterable[str] = (), input_data: Optional[Union[bytes, str]] = None, window: Optional[Window] = None, - custom_callback: Optional[Callable] = None, - action_on_removal: Optional[Callable] = None + custom_callback: Optional[Callable[[Dict[str, Any], int, 'Boss'], None]] = None, + action_on_removal: Optional[Callable[[int, 'Boss'], None]] = None ) -> Any: orig_args, args = list(args), list(args) from kittens.runner import create_kitten_handler @@ -1229,7 +1228,7 @@ class Boss: def run_kitten(self, kitten: str, *args: str) -> None: self._run_kitten(kitten, args) - def on_kitten_finish(self, target_window_id: str, end_kitten: Callable, source_window: Window) -> None: + def on_kitten_finish(self, target_window_id: int, end_kitten: Callable[[Dict[str, Any], int, 'Boss'], None], source_window: Window) -> None: output = self.get_output(source_window, num_lines=None) from kittens.runner import deserialize data = deserialize(output) @@ -1336,7 +1335,7 @@ class Boss: def open_url_with_hints(self) -> None: self._run_kitten('hints') - def drain_actions(self, actions: List) -> None: + def drain_actions(self, actions: List[KeyAction]) -> None: def callback(timer_id: Optional[int]) -> None: self.dispatch_action(actions.pop(0)) @@ -1450,7 +1449,7 @@ class Boss: def process_stdin_source( self, window: Optional[Window] = None, - stdin: Optional[str] = None, copy_pipe_data: Optional[Dict] = None + stdin: Optional[str] = None, copy_pipe_data: Optional[Dict[str, Any]] = None ) -> Tuple[Optional[Dict[str, str]], Optional[bytes]]: w = window or self.active_window if not w: @@ -1763,7 +1762,7 @@ class Boss: with suppress(FileNotFoundError): os.remove(path) - def set_update_check_process(self, process: Optional[PopenType] = None) -> None: + def set_update_check_process(self, process: Optional['PopenType[bytes]'] = None) -> None: if self.update_check_process is not None: with suppress(Exception): if self.update_check_process.poll() is None: diff --git a/kitty/child.py b/kitty/child.py index 6f96fa438..13fcaf2b8 100644 --- a/kitty/child.py +++ b/kitty/child.py @@ -32,7 +32,7 @@ if is_macos: return os.path.realpath(_cwd(pid)) def process_group_map() -> DefaultDict[int, List[int]]: - ans: DefaultDict[int, List] = defaultdict(list) + ans: DefaultDict[int, List[int]] = defaultdict(list) for pid, pgid in _process_group_map(): ans[pgid].append(pid) return ans diff --git a/kitty/cli.py b/kitty/cli.py index e8a33de19..47d75a458 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -226,7 +226,7 @@ def prettify(text: str) -> str: def identity(x: str) -> str: return x - def sub(m: Match) -> str: + def sub(m: 'Match[str]') -> str: role, text = m.group(1, 2) return role_map.get(role, identity)(text) diff --git a/kitty/conf/generate.py b/kitty/conf/generate.py index bcc70d396..80ac3c828 100644 --- a/kitty/conf/generate.py +++ b/kitty/conf/generate.py @@ -173,7 +173,7 @@ def generate_class(defn: Definition, loc: str) -> Tuple[str, str]: if defn.has_color_table: imports.add(('array', 'array')) - a(' color_table: array = array("L", (') + a(' color_table: "array[int]" = array("L", (') for grp in chunks(color_table, 8): a(' ' + ', '.join(grp) + ',') a(' ))') diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 8564fafa4..2800a8e21 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1,13 +1,14 @@ -from ctypes import Array +import termios +from ctypes import Array, c_ubyte from typing import ( Any, AnyStr, Callable, Dict, List, NewType, Optional, Tuple, TypedDict, Union ) -import termios from kitty.boss import Boss from kitty.fonts import FontFeature from kitty.fonts.render import FontObject +from kitty.marks import MarkerFunc from kitty.options.types import Options # Constants {{{ @@ -622,7 +623,7 @@ class ColorProfile: default_bg: int - def as_dict(self) -> Dict: + def as_dict(self) -> Dict[str, int]: pass def as_color(self, val: int) -> Tuple[int, int, int]: @@ -733,7 +734,7 @@ def background_opacity_of(os_window_id: int) -> Optional[float]: pass -def read_command_response(fd: int, timeout: float, list: List) -> None: +def read_command_response(fd: int, timeout: float, list: List[bytes]) -> None: pass @@ -887,10 +888,10 @@ def set_send_sprite_to_gpu( def set_font_data( box_drawing_func: Callable[[int, int, int, float], - Tuple[int, Union[bytearray, bytes, Array]]], + Tuple[int, Union[bytearray, bytes, Array[c_ubyte]]]], prerender_func: Callable[ [int, int, int, int, int, int, int, float, float, float, float], - Tuple[Union[Array, int], ...]], + Tuple[Union[Array[c_ubyte], int], ...]], descriptor_for_idx: Callable[[int], Tuple[FontObject, bool, bool]], bold: int, italic: int, bold_italic: int, num_symbol_fonts: int, symbol_maps: Tuple[Tuple[int, int, int], ...], font_sz_in_pts: float, @@ -1044,7 +1045,7 @@ class Screen: def refresh_sprite_positions(self) -> None: pass - def set_marker(self, marker: Optional[Callable] = None) -> None: + def set_marker(self, marker: Optional[MarkerFunc] = None) -> None: pass def paste_bytes(self, data: bytes) -> None: @@ -1105,7 +1106,7 @@ class ChildMonitor: def __init__( self, death_notify: Callable[[int], None], - dump_callback: Optional[Callable], + dump_callback: Optional[Callable[[bytes], None]], talk_fd: int = -1, listen_fd: int = -1 ): diff --git a/kitty/fonts/render.py b/kitty/fonts/render.py index a77cc8dde..cdbc36567 100644 --- a/kitty/fonts/render.py +++ b/kitty/fonts/render.py @@ -200,10 +200,11 @@ def set_font_family(opts: Optional[Options] = None, override_font_size: Optional ) -UnderlineCallback = Callable[[ctypes.Array, int, int, int, int], None] +CBufType = ctypes.Array[ctypes.c_ubyte] +UnderlineCallback = Callable[[CBufType, int, int, int, int], None] -def add_line(buf: ctypes.Array, cell_width: int, position: int, thickness: int, cell_height: int) -> None: +def add_line(buf: CBufType, cell_width: int, position: int, thickness: int, cell_height: int) -> None: y = position - thickness // 2 while thickness > 0 and -1 < y < cell_height: thickness -= 1 @@ -211,7 +212,7 @@ def add_line(buf: ctypes.Array, cell_width: int, position: int, thickness: int, y += 1 -def add_dline(buf: ctypes.Array, cell_width: int, position: int, thickness: int, cell_height: int) -> None: +def add_dline(buf: CBufType, cell_width: int, position: int, thickness: int, cell_height: int) -> None: a = min(position - thickness, cell_height - 1) b = min(position, cell_height - 1) top, bottom = min(a, b), max(a, b) @@ -231,7 +232,7 @@ def add_dline(buf: ctypes.Array, cell_width: int, position: int, thickness: int, ctypes.memset(ctypes.addressof(buf) + (cell_width * y), 255, cell_width) -def add_curl(buf: ctypes.Array, cell_width: int, position: int, thickness: int, cell_height: int) -> None: +def add_curl(buf: CBufType, cell_width: int, position: int, thickness: int, cell_height: int) -> None: max_x, max_y = cell_width - 1, cell_height - 1 xfactor = 2.0 * pi / max_x thickness = max(1, thickness) @@ -280,7 +281,7 @@ def render_special( strikethrough_thickness: int = 0, dpi_x: float = 96., dpi_y: float = 96., -) -> ctypes.Array: +) -> CBufType: underline_position = min(underline_position, cell_height - underline_thickness) CharTexture = ctypes.c_ubyte * (cell_width * cell_height) @@ -317,7 +318,7 @@ def render_cursor( cell_height: int = 0, dpi_x: float = 0, dpi_y: float = 0 -) -> ctypes.Array: +) -> CBufType: CharTexture = ctypes.c_ubyte * (cell_width * cell_height) ans = CharTexture() @@ -361,7 +362,7 @@ def prerender_function( cursor_underline_thickness: float, dpi_x: float, dpi_y: float -) -> Tuple[Union[int, ctypes.Array], ...]: +) -> Tuple[Union[int, CBufType], ...]: # Pre-render the special underline, strikethrough and missing and cursor cells f = partial( render_special, cell_width=cell_width, cell_height=cell_height, baseline=baseline, @@ -377,7 +378,7 @@ def prerender_function( return tuple(map(ctypes.addressof, cells)) + (cells,) -def render_box_drawing(codepoint: int, cell_width: int, cell_height: int, dpi: float) -> Tuple[int, ctypes.Array]: +def render_box_drawing(codepoint: int, cell_width: int, cell_height: int, dpi: float) -> Tuple[int, CBufType]: CharTexture = ctypes.c_ubyte * (cell_width * cell_height) buf = CharTexture() render_box_char( diff --git a/kitty/layout/interface.py b/kitty/layout/interface.py index f7a6e670c..6c196e3ac 100644 --- a/kitty/layout/interface.py +++ b/kitty/layout/interface.py @@ -20,9 +20,11 @@ all_layouts: Dict[str, Type[Layout]] = { Splits.name: Splits, } +KeyType = Tuple[str, int, int, str] + class CreateLayoutObjectFor: - cache: Dict[Tuple, Layout] = {} + cache: Dict[KeyType, Layout] = {} def __call__( self, diff --git a/kitty/options/types.py b/kitty/options/types.py index 9cdb52160..9bb0917c2 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -585,7 +585,7 @@ class Options: sequence_map: SequenceMap = {} mouse_map: typing.List[kitty.options.utils.MouseMapping] = [] mousemap: MouseMap = {} - color_table: array = array("L", ( + color_table: "array[int]" = array("L", ( 0x000000, 0xcc0403, 0x19cb00, 0xcecb00, 0x0d73cc, 0xcb1ed1, 0x0dcdcd, 0xdddddd, 0x767676, 0xf2201f, 0x23fd00, 0xfffd00, 0x1a8fff, 0xfd28ff, 0x14ffff, 0xffffff, 0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, diff --git a/kitty/utils.py b/kitty/utils.py index 21f70d5cb..f99fba36e 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -37,7 +37,7 @@ def expandvars(val: str, env: Mapping[str, str] = {}, fallback_to_os_env: bool = Expand $VAR and ${VAR} Use $$ for a literal $ ''' - def sub(m: Match) -> str: + def sub(m: 'Match[str]') -> str: key = m.group(1) or m.group(2) result = env.get(key) if result is None and fallback_to_os_env: @@ -216,7 +216,7 @@ def command_for_open(program: Union[str, List[str]] = 'default') -> List[str]: return cmd -def open_cmd(cmd: Union[Iterable[str], List[str]], arg: Union[None, Iterable[str], str] = None, cwd: Optional[str] = None) -> PopenType: +def open_cmd(cmd: Union[Iterable[str], List[str]], arg: Union[None, Iterable[str], str] = None, cwd: Optional[str] = None) -> 'PopenType[bytes]': import subprocess if arg is not None: cmd = list(cmd) @@ -227,7 +227,7 @@ def open_cmd(cmd: Union[Iterable[str], List[str]], arg: Union[None, Iterable[str return subprocess.Popen(tuple(cmd), stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=cwd or None) -def open_url(url: str, program: Union[str, List[str]] = 'default', cwd: Optional[str] = None) -> PopenType: +def open_url(url: str, program: Union[str, List[str]] = 'default', cwd: Optional[str] = None) -> 'PopenType[bytes]': return open_cmd(command_for_open(program), url, cwd=cwd) @@ -302,7 +302,7 @@ def end_startup_notification(ctx: Optional['StartupCtx']) -> None: class startup_notification_handler: - def __init__(self, do_notify: bool = True, startup_id: Optional[str] = None, extra_callback: Optional[Callable] = None): + def __init__(self, do_notify: bool = True, startup_id: Optional[str] = None, extra_callback: Optional[Callable[[int], None]] = None): self.do_notify = do_notify self.startup_id = startup_id self.extra_callback = extra_callback @@ -768,9 +768,9 @@ def reload_conf_in_all_kitties() -> None: @run_once -def control_codes_pat() -> Pattern: +def control_codes_pat() -> 'Pattern[str]': return re.compile('[\x00-\x09\x0b-\x1f\x7f\x80-\x9f]') def sanitize_control_codes(text: str, replace_with: str = '') -> str: - return cast(str, control_codes_pat().sub(replace_with, text)) + return control_codes_pat().sub(replace_with, text) diff --git a/kitty/window.py b/kitty/window.py index 9009628e5..a9888d66a 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -361,8 +361,8 @@ class Window: self.current_mouse_event_button = 0 self.current_clipboard_read_ask: Optional[bool] = None self.prev_osc99_cmd = NotificationCommand() - self.action_on_close: Optional[Callable] = None - self.action_on_removal: Optional[Callable] = None + self.action_on_close: Optional[Callable[['Window'], None]] = None + self.action_on_removal: Optional[Callable[['Window'], None]] = None self.current_marker_spec: Optional[Tuple[str, Union[str, Tuple[Tuple[int, str], ...]]]] = None self.pty_resized_once = False self.last_reported_pty_size = (-1, -1, -1, -1) @@ -495,7 +495,7 @@ class Window: } @property - def current_colors(self) -> Dict: + def current_colors(self) -> Dict[str, int]: return self.screen.color_profile.as_dict() @property