Make mypy a bit stricter

This commit is contained in:
Kovid Goyal 2020-03-05 19:57:28 +05:30
parent 81a58186c6
commit 77e9460eea
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
11 changed files with 74 additions and 53 deletions

View File

@ -6,7 +6,6 @@
import importlib
import os
import sys
from contextlib import suppress
from functools import partial
aliases = {'url_hints': 'hints'}
@ -99,9 +98,11 @@ def run_kitten(kitten, run_name='__main__'):
original_kitten_name = kitten
kitten = resolved_kitten(kitten)
set_debug(kitten)
with suppress(ImportError):
try:
runpy.run_module('kittens.{}.main'.format(kitten), run_name=run_name)
return
except ImportError:
pass
# Look for a custom kitten
if not kitten.endswith('.py'):
kitten += '.py'

View File

@ -63,8 +63,8 @@ def beep() -> str:
return '\a'
def set_window_title(value) -> str:
return ('\033]2;' + value.replace('\033', '').replace('\x9c', '') + '\033\\')
def set_window_title(value: str) -> str:
return '\033]2;' + value.replace('\033', '').replace('\x9c', '') + '\033\\'
def set_line_wrapping(yes_or_no: bool) -> str:
@ -134,7 +134,7 @@ def faint(text) -> str:
return colored(text, 'black', True)
def styled(text, fg=None, bg=None, fg_intense=False, bg_intense=False, italic=None, bold=None, underline=None, underline_color=None, reverse=None) -> str:
def styled(text: str, fg=None, bg=None, fg_intense=False, bg_intense=False, italic=None, bold=None, underline=None, underline_color=None, reverse=None) -> str:
start, end = [], []
if fg is not None:
start.append(color_code(fg, fg_intense))
@ -167,7 +167,7 @@ def styled(text, fg=None, bg=None, fg_intense=False, bg_intense=False, italic=No
return '\033[{}m{}\033[{}m'.format(';'.join(start), text, ';'.join(end))
def serialize_gr_command(cmd, payload=None):
def serialize_gr_command(cmd, payload=None) -> bytes:
cmd = ','.join('{}={}'.format(k, v) for k, v in cmd.items())
ans: List[bytes] = []
w = ans.append
@ -180,11 +180,11 @@ def serialize_gr_command(cmd, payload=None):
def gr_command(cmd, payload=None) -> str:
return serialize_gr_command(cmd, payload)
return serialize_gr_command(cmd, payload).decode('ascii')
def clear_images_on_screen(delete_data=False) -> str:
return serialize_gr_command({'a': 'd', 'd': 'A' if delete_data else 'a'})
return serialize_gr_command({'a': 'd', 'd': 'A' if delete_data else 'a'}).decode('ascii')
def init_state(alternate_screen=True):
@ -255,8 +255,9 @@ def write_to_clipboard(data, use_primary=False) -> str:
from base64 import standard_b64encode
fmt = 'p' if use_primary else 'c'
def esc(chunk):
def esc(chunk: str) -> str:
return '\x1b]52;{};{}\x07'.format(fmt, chunk)
ans = esc('!') # clear clipboard buffer
for chunk in (data[i:i+512] for i in range(0, len(data), 512)):
chunk = standard_b64encode(chunk).decode('ascii')

View File

@ -260,11 +260,12 @@ class Table:
self.layout_dirty = True
def is_index(w):
with suppress(Exception):
def is_index(w: str) -> bool:
try:
int(w.lstrip(INDEX_CHAR), 16)
return True
return False
except Exception:
return False
class UnicodeInput(Handler):

View File

@ -674,7 +674,8 @@ type=bool-set
appname=appname, config_help=CONFIG_HELP.format(appname=appname, conf_name=appname)
))
return getattr(options_spec, 'ans')
ans: str = getattr(options_spec, 'ans')
return ans
def options_for_completion() -> OptionSpecSeq:
@ -703,7 +704,7 @@ def parse_args(
usage: Optional[str] = None,
message: Optional[str] = None,
appname: Optional[str] = None,
result_class: Type[T] = None,
result_class: Optional[Type[T]] = None,
) -> Tuple[T, List[str]]:
options = parse_option_spec(ospec())
seq, disabled = options

View File

@ -6,7 +6,10 @@ import os
import re
import shlex
from collections import namedtuple
from typing import Callable, FrozenSet, List, Optional, Union, Dict, Any, Iterator, Type
from typing import (
Any, Callable, Dict, FrozenSet, Iterator, List, Optional, Sequence, Tuple,
Type, Union
)
from ..rgb import Color, to_color as as_color
from ..utils import log_error
@ -56,12 +59,13 @@ def to_cmdline(x: str) -> List[str]:
def python_string(text: str) -> str:
import ast
return ast.literal_eval("'''" + text.replace("'''", "'\\''") + "'''")
ans: str = ast.literal_eval("'''" + text.replace("'''", "'\\''") + "'''")
return ans
def choices(*choices) -> Callable[[str], str]:
defval: str = choices[0]
uc: FrozenSet[str] = frozenset(choices)
def choices(*choices: str) -> Callable[[str], str]:
defval = choices[0]
uc = frozenset(choices)
def choice(x: str) -> str:
x = x.lower()
@ -199,13 +203,13 @@ def create_options_class(all_keys: Iterator[str]) -> Type:
return ans
def merge_dicts(defaults, newvals):
def merge_dicts(defaults: Dict, newvals: Dict) -> Dict:
ans = defaults.copy()
ans.update(newvals)
return ans
def resolve_config(SYSTEM_CONF, defconf, config_files_on_cmd_line):
def resolve_config(SYSTEM_CONF: str, defconf: str, config_files_on_cmd_line: Sequence[str]):
if config_files_on_cmd_line:
if 'NONE' not in config_files_on_cmd_line:
yield SYSTEM_CONF
@ -217,9 +221,14 @@ def resolve_config(SYSTEM_CONF, defconf, config_files_on_cmd_line):
def load_config(
Options, defaults, parse_config, merge_configs, *paths, overrides=None
Options: Type,
defaults: Any,
parse_config: Callable[[Iterator[str]], Dict[str, Any]],
merge_configs: Callable[[Dict, Dict], Dict],
*paths: str,
overrides: Optional[Iterator[str]] = None
):
ans = defaults._asdict()
ans: Dict = defaults._asdict()
for path in paths:
if not path:
continue
@ -235,7 +244,7 @@ def load_config(
return Options(ans)
def init_config(default_config_lines, parse_config):
def init_config(default_config_lines: Iterator[str], parse_config: Callable):
defaults = parse_config(default_config_lines, check_keys=False)
Options = create_options_class(defaults.keys())
defaults = Options(defaults)
@ -260,7 +269,7 @@ def key_func():
return func_with_args, ans
def parse_kittens_shortcut(sc):
def parse_kittens_shortcut(sc: str) -> Tuple[Optional[int], str, bool]:
from ..key_encoding import config_key_map, config_mod_map, text_match
if sc.endswith('+'):
parts = list(filter(None, sc.rstrip('+').split('+') + ['+']))
@ -282,16 +291,17 @@ def parse_kittens_shortcut(sc):
tkey = text_match(rkey)
if tkey is None:
rkey = rkey.upper()
rkey = config_key_map.get(rkey)
if rkey is None:
q = config_key_map.get(rkey)
if q is None:
raise ValueError('Unknown shortcut key: {}'.format(sc))
rkey = q
else:
is_text = True
rkey = tkey
return mods, rkey, is_text
def parse_kittens_func_args(action, args_funcs):
def parse_kittens_func_args(action: str, args_funcs: Dict[str, Callable]) -> Tuple[str, Tuple[str, ...]]:
parts = action.strip().split(' ', 1)
func = parts[0]
if len(parts) == 1:
@ -317,10 +327,12 @@ def parse_kittens_func_args(action, args_funcs):
return func, tuple(args)
def parse_kittens_key(val, funcs_with_args):
def parse_kittens_key(
val: str, funcs_with_args: Dict[str, Callable]
) -> Optional[Tuple[Tuple[str, Tuple[str, ...]], str, Optional[int], bool]]:
sc, action = val.partition(' ')[::2]
if not sc or not action:
return
return None
mods, key, is_text = parse_kittens_shortcut(sc)
action = parse_kittens_func_args(action, funcs_with_args)
return action, key, mods, is_text
ans = parse_kittens_func_args(action, funcs_with_args)
return ans, key, mods, is_text

View File

@ -483,7 +483,7 @@ def handle_symbol_map(key, val, ans):
class FontFeature(str):
def __new__(cls, name, parsed):
ans = str.__new__(cls, name) # type: ignore
ans = str.__new__(cls, name)
ans.parsed = parsed
return ans
@ -624,7 +624,7 @@ actions = frozenset(all_key_actions) | frozenset(
no_op_actions = frozenset({'noop', 'no-op', 'no_op'})
def merge_configs(defaults, vals):
def merge_configs(defaults: Dict, vals: Dict) -> Dict:
ans = {}
for k, v in defaults.items():
if isinstance(v, dict):
@ -777,7 +777,7 @@ def finalize_keys(opts: OptionsStub) -> None:
opts.sequence_map = sequence_map
def load_config(*paths: Tuple[str], overrides: Optional[Iterator[str]] = None, accumulate_bad_lines: Optional[List[BadLine]] = None) -> OptionsStub:
def load_config(*paths: str, overrides: Optional[Iterator[str]] = None, accumulate_bad_lines: Optional[List[BadLine]] = None) -> OptionsStub:
parser = parse_config
if accumulate_bad_lines is not None:
parser = partial(parse_config, accumulate_bad_lines=accumulate_bad_lines)

View File

@ -18,7 +18,7 @@ from .tabs import Tab
try:
from typing import TypedDict
except ImportError:
TypedDict = Dict[str, Any] # type: ignore
TypedDict = Dict[str, Any]
@lru_cache(maxsize=2)
@ -162,7 +162,7 @@ def get_env(opts: LaunchCLIOptions, active_child: Child) -> Dict[str, str]:
def tab_for_window(boss: Boss, opts: LaunchCLIOptions, target_tab: Optional[Tab] = None) -> Tab:
if opts.type == 'tab':
tm = boss.active_tab_manager
tab = tm.new_tab(empty_tab=True, location=opts.location)
tab: Tab = tm.new_tab(empty_tab=True, location=opts.location)
if opts.tab_title:
tab.set_title(opts.tab_title)
elif opts.type == 'os-window':
@ -252,7 +252,7 @@ def launch(boss: Boss, opts: LaunchCLIOptions, args: List[str], target_tab: Opti
func(kw['stdin'])
else:
tab = tab_for_window(boss, opts, target_tab)
new_window = tab.new_window(env=env or None, **kw)
new_window: Window = tab.new_window(env=env or None, **kw)
if opts.keep_focus and active:
boss.set_active_window(active, switch_os_window_if_needed=True)
return new_window

View File

@ -466,7 +466,7 @@ class Layout: # {{{
def window_independent_borders(self, windows, active_windows):
return
yield
yield # type:ignore
def minimal_borders(self, windows, active_window, needs_borders_map):
for w in windows:

9
kitty/rgb.py generated
View File

@ -3,11 +3,14 @@
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
import re
from collections import namedtuple
from contextlib import suppress
from typing import Optional
from typing import Optional, NamedTuple
Color = namedtuple('Color', 'red green blue')
class Color(NamedTuple):
red: int
green: int
blue: int
def alpha_blend_channel(top_color: int, bottom_color: int, alpha: float) -> int:

View File

@ -468,17 +468,17 @@ def func_name(f):
def resolved_shell(opts: Optional[Options] = None) -> List[str]:
ans = getattr(opts, 'shell', '.')
if ans == '.':
q: str = getattr(opts, 'shell', '.')
if q == '.':
ans = [shell_path]
else:
import shlex
ans = shlex.split(ans)
ans = shlex.split(q)
return ans
def read_shell_environment(opts: Optional[Options] = None) -> Dict[str, str]:
ans = getattr(read_shell_environment, 'ans', None)
ans: Optional[Dict[str, str]] = getattr(read_shell_environment, 'ans', None)
if ans is None:
from .child import openpty, remove_blocking
ans = {}
@ -506,7 +506,7 @@ def read_shell_environment(opts: Optional[Options] = None) -> Dict[str, str]:
raw += stdout.read()
if ret is not None:
break
if p.returncode is None:
if cast(Optional[int], p.returncode) is None:
log_error('Timed out waiting for shell to quit while reading shell environment')
p.kill()
elif p.returncode == 0:

View File

@ -15,9 +15,11 @@ multi_line_output = 5
[mypy]
files = kitty,kittens,glfw/glfw.py,*.py
[mypy-kitty.conf.*]
check_untyped_defs = True
[mypy-kitty.cli]
check_untyped_defs = True
no_implicit_optional = True
sqlite_cache = True
cache_fine_grained = True
warn_redundant_casts = True
warn_unused_ignores = True
warn_return_any = True
warn_unreachable = True
# check_untyped_defs = True