more typing work
This commit is contained in:
parent
cda1e28b32
commit
b27f6d5957
65
docs/conf.py
65
docs/conf.py
@ -13,7 +13,9 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Optional, Dict, Tuple
|
from typing import (
|
||||||
|
Any, Callable, Dict, Iterable, List, Match, Optional, Tuple, Union
|
||||||
|
)
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst.roles import set_classes
|
from docutils.parsers.rst.roles import set_classes
|
||||||
@ -28,7 +30,10 @@ from sphinx.util.logging import getLogger # type: ignore
|
|||||||
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
if kitty_src not in sys.path:
|
if kitty_src not in sys.path:
|
||||||
sys.path.insert(0, kitty_src)
|
sys.path.insert(0, kitty_src)
|
||||||
|
|
||||||
from kitty.constants import str_version # noqa
|
from kitty.constants import str_version # noqa
|
||||||
|
from kitty.conf.definition import Option, Sequence, Shortcut # noqa
|
||||||
|
|
||||||
|
|
||||||
# config {{{
|
# config {{{
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
@ -184,7 +189,7 @@ texinfo_documents = [
|
|||||||
|
|
||||||
# GitHub linking inline roles {{{
|
# GitHub linking inline roles {{{
|
||||||
|
|
||||||
def num_role(which, name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def num_role(which: str, name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
||||||
' Link to a github issue '
|
' Link to a github issue '
|
||||||
try:
|
try:
|
||||||
issue_num = int(text)
|
issue_num = int(text)
|
||||||
@ -202,7 +207,7 @@ def num_role(which, name, rawtext, text, lineno, inliner, options={}, content=[]
|
|||||||
return [node], []
|
return [node], []
|
||||||
|
|
||||||
|
|
||||||
def commit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def commit_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
||||||
' Link to a github commit '
|
' Link to a github commit '
|
||||||
try:
|
try:
|
||||||
commit_id = subprocess.check_output(
|
commit_id = subprocess.check_output(
|
||||||
@ -222,14 +227,14 @@ def commit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
|
|
||||||
|
|
||||||
# Sidebar ToC {{{
|
# Sidebar ToC {{{
|
||||||
def create_toc(app, pagename):
|
def create_toc(app: Any, pagename: str) -> Optional[Any]:
|
||||||
tt = TocTree(app.env)
|
tt = TocTree(app.env)
|
||||||
toctree = tt.get_toc_for(pagename, app.builder)
|
toctree = tt.get_toc_for(pagename, app.builder)
|
||||||
if toctree is not None:
|
if toctree is not None:
|
||||||
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
||||||
bl = subtree.first_child_matching_class(nodes.bullet_list)
|
bl = subtree.first_child_matching_class(nodes.bullet_list)
|
||||||
if bl is None:
|
if bl is None:
|
||||||
return # Empty ToC
|
return None # Empty ToC
|
||||||
subtree = subtree[bl]
|
subtree = subtree[bl]
|
||||||
# for li in subtree.traverse(nodes.list_item):
|
# for li in subtree.traverse(nodes.list_item):
|
||||||
# modify_li(li)
|
# modify_li(li)
|
||||||
@ -237,14 +242,14 @@ def create_toc(app, pagename):
|
|||||||
return app.builder.render_partial(subtree)['fragment']
|
return app.builder.render_partial(subtree)['fragment']
|
||||||
|
|
||||||
|
|
||||||
def add_html_context(app, pagename, templatename, context, *args):
|
def add_html_context(app: Any, pagename: str, templatename: str, context: Any, *args: Any) -> None:
|
||||||
if 'toc' in context:
|
if 'toc' in context:
|
||||||
context['toc'] = create_toc(app, pagename) or context['toc']
|
context['toc'] = create_toc(app, pagename) or context['toc']
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# CLI docs {{{
|
# CLI docs {{{
|
||||||
def write_cli_docs(all_kitten_names):
|
def write_cli_docs(all_kitten_names: Iterable[str]) -> None:
|
||||||
from kitty.launch import options_spec as launch_options_spec
|
from kitty.launch import options_spec as launch_options_spec
|
||||||
from kitty.cli import option_spec_as_rst
|
from kitty.cli import option_spec_as_rst
|
||||||
with open('generated/launch.rst', 'w') as f:
|
with open('generated/launch.rst', 'w') as f:
|
||||||
@ -290,13 +295,13 @@ if you specify a program-to-run you can use the special placeholder
|
|||||||
|
|
||||||
|
|
||||||
def write_remote_control_protocol_docs() -> None: # {{{
|
def write_remote_control_protocol_docs() -> None: # {{{
|
||||||
from kitty.rc.base import all_command_names, command_for_name
|
from kitty.rc.base import all_command_names, command_for_name, RemoteCommand
|
||||||
field_pat = re.compile(r'\s*([a-zA-Z0-9_+]+)\s*:\s*(.+)')
|
field_pat = re.compile(r'\s*([a-zA-Z0-9_+]+)\s*:\s*(.+)')
|
||||||
|
|
||||||
def format_cmd(p, name, cmd):
|
def format_cmd(p: Callable, name: str, cmd: RemoteCommand) -> None:
|
||||||
p(name)
|
p(name)
|
||||||
p('-' * 80)
|
p('-' * 80)
|
||||||
lines = cmd.__doc__.strip().splitlines()
|
lines = (cmd.__doc__ or '').strip().splitlines()
|
||||||
fields = []
|
fields = []
|
||||||
for line in lines:
|
for line in lines:
|
||||||
m = field_pat.match(line)
|
m = field_pat.match(line)
|
||||||
@ -386,7 +391,7 @@ class SessionLexer(RegexLexer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def link_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def link_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
||||||
m = re.match(r'(.+)\s+<(.+?)>', text)
|
m = re.match(r'(.+)\s+<(.+?)>', text)
|
||||||
if m is None:
|
if m is None:
|
||||||
msg = inliner.reporter.error(f'link "{text}" not recognized', line=lineno)
|
msg = inliner.reporter.error(f'link "{text}" not recognized', line=lineno)
|
||||||
@ -398,15 +403,15 @@ def link_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
return [node], []
|
return [node], []
|
||||||
|
|
||||||
|
|
||||||
def expand_opt_references(conf_name, text):
|
def expand_opt_references(conf_name: str, text: str) -> str:
|
||||||
conf_name += '.'
|
conf_name += '.'
|
||||||
|
|
||||||
def expand(m):
|
def expand(m: Match) -> str:
|
||||||
ref = m.group(1)
|
ref = m.group(1)
|
||||||
if '<' not in ref and '.' not in ref:
|
if '<' not in ref and '.' not in ref:
|
||||||
full_ref = conf_name + ref
|
full_ref = conf_name + ref
|
||||||
return ':opt:`{} <{}>`'.format(ref, full_ref)
|
return ':opt:`{} <{}>`'.format(ref, full_ref)
|
||||||
return m.group()
|
return str(m.group())
|
||||||
|
|
||||||
return re.sub(r':opt:`(.+?)`', expand, text)
|
return re.sub(r':opt:`(.+?)`', expand, text)
|
||||||
|
|
||||||
@ -415,7 +420,7 @@ opt_aliases: Dict[str, str] = {}
|
|||||||
shortcut_slugs: Dict[str, Tuple[str, str]] = {}
|
shortcut_slugs: Dict[str, Tuple[str, str]] = {}
|
||||||
|
|
||||||
|
|
||||||
def parse_opt_node(env, sig, signode):
|
def parse_opt_node(env: Any, sig: str, signode: Any) -> str:
|
||||||
"""Transform an option description into RST nodes."""
|
"""Transform an option description into RST nodes."""
|
||||||
count = 0
|
count = 0
|
||||||
firstname = ''
|
firstname = ''
|
||||||
@ -437,22 +442,22 @@ def parse_opt_node(env, sig, signode):
|
|||||||
return firstname
|
return firstname
|
||||||
|
|
||||||
|
|
||||||
def parse_shortcut_node(env, sig, signode):
|
def parse_shortcut_node(env: Any, sig: str, signode: Any) -> str:
|
||||||
"""Transform a shortcut description into RST nodes."""
|
"""Transform a shortcut description into RST nodes."""
|
||||||
conf_name, text = sig.split('.', 1)
|
conf_name, text = sig.split('.', 1)
|
||||||
signode += addnodes.desc_name(text, text)
|
signode += addnodes.desc_name(text, text)
|
||||||
return sig
|
return sig
|
||||||
|
|
||||||
|
|
||||||
def render_conf(conf_name, all_options):
|
def render_conf(conf_name: str, all_options: Iterable[Union['Option', Sequence['Shortcut']]]) -> str:
|
||||||
from kitty.conf.definition import merged_opts, Option, Group
|
from kitty.conf.definition import merged_opts, Option, Group
|
||||||
ans = ['.. default-domain:: conf', '']
|
ans = ['.. default-domain:: conf', '']
|
||||||
a = ans.append
|
a = ans.append
|
||||||
current_group: Optional[Group] = None
|
current_group: Optional[Group] = None
|
||||||
all_options = list(all_options)
|
all_options_ = list(all_options)
|
||||||
kitty_mod = 'kitty_mod'
|
kitty_mod = 'kitty_mod'
|
||||||
|
|
||||||
def render_group(group):
|
def render_group(group: Group) -> None:
|
||||||
a('')
|
a('')
|
||||||
a(f'.. _conf-{conf_name}-{group.name}:')
|
a(f'.. _conf-{conf_name}-{group.name}:')
|
||||||
a('')
|
a('')
|
||||||
@ -464,12 +469,12 @@ def render_conf(conf_name, all_options):
|
|||||||
a(group.start_text)
|
a(group.start_text)
|
||||||
a('')
|
a('')
|
||||||
|
|
||||||
def handle_group_end(group):
|
def handle_group_end(group: Group) -> None:
|
||||||
if group.end_text:
|
if group.end_text:
|
||||||
assert current_group is not None
|
assert current_group is not None
|
||||||
a(''), a(current_group.end_text)
|
a(''), a(current_group.end_text)
|
||||||
|
|
||||||
def handle_group(new_group, new_group_is_shortcut=False):
|
def handle_group(new_group: Group, new_group_is_shortcut: bool = False) -> None:
|
||||||
nonlocal current_group
|
nonlocal current_group
|
||||||
if new_group is not current_group:
|
if new_group is not current_group:
|
||||||
if current_group:
|
if current_group:
|
||||||
@ -477,14 +482,14 @@ def render_conf(conf_name, all_options):
|
|||||||
current_group = new_group
|
current_group = new_group
|
||||||
render_group(current_group)
|
render_group(current_group)
|
||||||
|
|
||||||
def handle_option(i, opt):
|
def handle_option(i: int, opt: Option) -> None:
|
||||||
nonlocal kitty_mod
|
nonlocal kitty_mod
|
||||||
if not opt.long_text or not opt.add_to_docs:
|
if not opt.long_text or not opt.add_to_docs:
|
||||||
return
|
return
|
||||||
handle_group(opt.group)
|
handle_group(opt.group)
|
||||||
if opt.name == 'kitty_mod':
|
if opt.name == 'kitty_mod':
|
||||||
kitty_mod = opt.defval_as_string
|
kitty_mod = opt.defval_as_string
|
||||||
mopts = list(merged_opts(all_options, opt, i))
|
mopts = list(merged_opts(all_options_, opt, i))
|
||||||
a('.. opt:: ' + ', '.join(conf_name + '.' + mo.name for mo in mopts))
|
a('.. opt:: ' + ', '.join(conf_name + '.' + mo.name for mo in mopts))
|
||||||
a('.. code-block:: conf')
|
a('.. code-block:: conf')
|
||||||
a('')
|
a('')
|
||||||
@ -496,7 +501,7 @@ def render_conf(conf_name, all_options):
|
|||||||
a(expand_opt_references(conf_name, opt.long_text))
|
a(expand_opt_references(conf_name, opt.long_text))
|
||||||
a('')
|
a('')
|
||||||
|
|
||||||
def handle_shortcuts(shortcuts):
|
def handle_shortcuts(shortcuts: Sequence[Shortcut]) -> None:
|
||||||
sc = shortcuts[0]
|
sc = shortcuts[0]
|
||||||
handle_group(sc.group, True)
|
handle_group(sc.group, True)
|
||||||
sc_text = f'{conf_name}.{sc.short_text}'
|
sc_text = f'{conf_name}.{sc.short_text}'
|
||||||
@ -514,7 +519,7 @@ def render_conf(conf_name, all_options):
|
|||||||
a(expand_opt_references(conf_name, sc.long_text))
|
a(expand_opt_references(conf_name, sc.long_text))
|
||||||
a('')
|
a('')
|
||||||
|
|
||||||
for i, opt in enumerate(all_options):
|
for i, opt in enumerate(all_options_):
|
||||||
if isinstance(opt, Option):
|
if isinstance(opt, Option):
|
||||||
handle_option(i, opt)
|
handle_option(i, opt)
|
||||||
else:
|
else:
|
||||||
@ -525,7 +530,7 @@ def render_conf(conf_name, all_options):
|
|||||||
return '\n'.join(ans)
|
return '\n'.join(ans)
|
||||||
|
|
||||||
|
|
||||||
def process_opt_link(env, refnode, has_explicit_title, title, target):
|
def process_opt_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
conf_name, opt = target.partition('.')[::2]
|
conf_name, opt = target.partition('.')[::2]
|
||||||
if not opt:
|
if not opt:
|
||||||
conf_name, opt = 'kitty', conf_name
|
conf_name, opt = 'kitty', conf_name
|
||||||
@ -533,7 +538,7 @@ def process_opt_link(env, refnode, has_explicit_title, title, target):
|
|||||||
return title, opt_aliases.get(full_name, full_name)
|
return title, opt_aliases.get(full_name, full_name)
|
||||||
|
|
||||||
|
|
||||||
def process_shortcut_link(env, refnode, has_explicit_title, title, target):
|
def process_shortcut_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
conf_name, slug = target.partition('.')[::2]
|
conf_name, slug = target.partition('.')[::2]
|
||||||
if not slug:
|
if not slug:
|
||||||
conf_name, slug = 'kitty', conf_name
|
conf_name, slug = 'kitty', conf_name
|
||||||
@ -548,7 +553,7 @@ def process_shortcut_link(env, refnode, has_explicit_title, title, target):
|
|||||||
return title, target
|
return title, target
|
||||||
|
|
||||||
|
|
||||||
def write_conf_docs(app, all_kitten_names):
|
def write_conf_docs(app: Any, all_kitten_names: Iterable[str]) -> None:
|
||||||
app.add_lexer('conf', ConfLexer())
|
app.add_lexer('conf', ConfLexer())
|
||||||
app.add_object_type(
|
app.add_object_type(
|
||||||
'opt', 'opt',
|
'opt', 'opt',
|
||||||
@ -569,7 +574,7 @@ def write_conf_docs(app, all_kitten_names):
|
|||||||
sc_role.warn_dangling = True
|
sc_role.warn_dangling = True
|
||||||
sc_role.process_link = process_shortcut_link
|
sc_role.process_link = process_shortcut_link
|
||||||
|
|
||||||
def generate_default_config(all_options, name):
|
def generate_default_config(all_options: Dict[str, Union[Option, Sequence[Shortcut]]], name: str) -> None:
|
||||||
from kitty.conf.definition import as_conf_file
|
from kitty.conf.definition import as_conf_file
|
||||||
with open(f'generated/conf-{name}.rst', 'w', encoding='utf-8') as f:
|
with open(f'generated/conf-{name}.rst', 'w', encoding='utf-8') as f:
|
||||||
print('.. highlight:: conf\n', file=f)
|
print('.. highlight:: conf\n', file=f)
|
||||||
@ -591,7 +596,7 @@ def write_conf_docs(app, all_kitten_names):
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Any) -> None:
|
||||||
os.makedirs('generated/conf', exist_ok=True)
|
os.makedirs('generated/conf', exist_ok=True)
|
||||||
from kittens.runner import all_kitten_names
|
from kittens.runner import all_kitten_names
|
||||||
kn = all_kitten_names()
|
kn = all_kitten_names()
|
||||||
|
|||||||
16
test.py
16
test.py
@ -6,7 +6,7 @@ import importlib
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from typing import Callable, NoReturn, Set
|
from typing import Callable, Generator, NoReturn, Sequence, Set
|
||||||
|
|
||||||
base = os.path.dirname(os.path.abspath(__file__))
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ def init_env() -> None:
|
|||||||
sys.path.insert(0, base)
|
sys.path.insert(0, base)
|
||||||
|
|
||||||
|
|
||||||
def itertests(suite):
|
def itertests(suite: unittest.TestSuite) -> Generator[unittest.TestCase, None, None]:
|
||||||
stack = [suite]
|
stack = [suite]
|
||||||
while stack:
|
while stack:
|
||||||
suite = stack.pop()
|
suite = stack.pop()
|
||||||
@ -28,7 +28,7 @@ def itertests(suite):
|
|||||||
yield test
|
yield test
|
||||||
|
|
||||||
|
|
||||||
def find_tests_in_dir(path, excludes=('main.py',)):
|
def find_tests_in_dir(path: str, excludes: Sequence[str] = ('main.py',)) -> unittest.TestSuite:
|
||||||
package = os.path.relpath(path, base).replace(os.sep, '/').replace('/', '.')
|
package = os.path.relpath(path, base).replace(os.sep, '/').replace('/', '.')
|
||||||
items = os.listdir(path)
|
items = os.listdir(path)
|
||||||
suits = []
|
suits = []
|
||||||
@ -52,7 +52,7 @@ def filter_tests(suite: unittest.TestSuite, test_ok: Callable[[unittest.TestCase
|
|||||||
def filter_tests_by_name(suite: unittest.TestSuite, *names: str) -> unittest.TestSuite:
|
def filter_tests_by_name(suite: unittest.TestSuite, *names: str) -> unittest.TestSuite:
|
||||||
names_ = {x if x.startswith('test_') else 'test_' + x for x in names}
|
names_ = {x if x.startswith('test_') else 'test_' + x for x in names}
|
||||||
|
|
||||||
def q(test):
|
def q(test: unittest.TestCase) -> bool:
|
||||||
return test._testMethodName in names_
|
return test._testMethodName in names_
|
||||||
return filter_tests(suite, q)
|
return filter_tests(suite, q)
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ def filter_tests_by_name(suite: unittest.TestSuite, *names: str) -> unittest.Tes
|
|||||||
def filter_tests_by_module(suite: unittest.TestSuite, *names: str) -> unittest.TestSuite:
|
def filter_tests_by_module(suite: unittest.TestSuite, *names: str) -> unittest.TestSuite:
|
||||||
names_ = frozenset(names)
|
names_ = frozenset(names)
|
||||||
|
|
||||||
def q(test):
|
def q(test: unittest.TestCase) -> bool:
|
||||||
m = test.__class__.__module__.rpartition('.')[-1]
|
m = test.__class__.__module__.rpartition('.')[-1]
|
||||||
return m in names_
|
return m in names_
|
||||||
return filter_tests(suite, q)
|
return filter_tests(suite, q)
|
||||||
@ -77,7 +77,7 @@ def type_check() -> NoReturn:
|
|||||||
os.execlp(sys.executable, 'python', '-m', 'mypy', '--pretty')
|
os.execlp(sys.executable, 'python', '-m', 'mypy', '--pretty')
|
||||||
|
|
||||||
|
|
||||||
def run_tests():
|
def run_tests() -> None:
|
||||||
import argparse
|
import argparse
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@ -86,7 +86,7 @@ def run_tests():
|
|||||||
parser.add_argument('--verbosity', default=4, type=int, help='Test verbosity')
|
parser.add_argument('--verbosity', default=4, type=int, help='Test verbosity')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if args.name and args.name[0] in ('type-check', 'type_check', 'mypy'):
|
if args.name and args.name[0] in ('type-check', 'type_check', 'mypy'):
|
||||||
return type_check()
|
type_check()
|
||||||
tests = find_tests_in_dir(os.path.join(base, 'kitty_tests'))
|
tests = find_tests_in_dir(os.path.join(base, 'kitty_tests'))
|
||||||
if args.name:
|
if args.name:
|
||||||
tests = filter_tests_by_name(tests, *args.name)
|
tests = filter_tests_by_name(tests, *args.name)
|
||||||
@ -106,7 +106,7 @@ def run_cli(suite: unittest.TestSuite, verbosity: int = 4) -> None:
|
|||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
run_tests()
|
run_tests()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user