More typing work

Also move notification_activated into a standalone function which will
hopefully fix #2410
This commit is contained in:
Kovid Goyal 2020-03-06 07:07:18 +05:30
parent 1e998b6a3f
commit f729985346
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 86 additions and 62 deletions

View File

@ -38,9 +38,16 @@ from .utils import (
log_error, open_url, parse_address_spec, remove_socket_file, safe_print, log_error, open_url, parse_address_spec, remove_socket_file, safe_print,
set_primary_selection, single_instance, startup_notification_handler set_primary_selection, single_instance, startup_notification_handler
) )
from .window import Window
def listen_on(spec): def notification_activated(identifier: str) -> None:
if identifier == 'new-version':
from .update_check import notification_activated
notification_activated()
def listen_on(spec: str) -> int:
import socket import socket
family, address, socket_path = parse_address_spec(spec) family, address, socket_path = parse_address_spec(spec)
s = socket.socket(family) s = socket.socket(family)
@ -50,8 +57,8 @@ def listen_on(spec):
return s.fileno() return s.fileno()
def data_for_at(w, arg, add_wrap_markers=False): def data_for_at(w: Window, arg: str, add_wrap_markers: bool = False) -> str:
def as_text(**kw): def as_text(**kw) -> str:
kw['add_wrap_markers'] = add_wrap_markers kw['add_wrap_markers'] = add_wrap_markers
return w.as_text(**kw) return w.as_text(**kw)
@ -143,7 +150,7 @@ class Boss:
change_os_window_state(args.start_as) change_os_window_state(args.start_as)
if is_macos: if is_macos:
from .fast_data_types import cocoa_set_notification_activated_callback from .fast_data_types import cocoa_set_notification_activated_callback
cocoa_set_notification_activated_callback(self.notification_activated) cocoa_set_notification_activated_callback(notification_activated)
def add_os_window(self, startup_session=None, os_window_id=None, wclass=None, wname=None, opts_for_size=None, startup_id=None): def add_os_window(self, startup_session=None, os_window_id=None, wclass=None, wname=None, opts_for_size=None, startup_id=None):
if os_window_id is None: if os_window_id is None:
@ -1141,11 +1148,6 @@ class Boss:
except Exception as e: except Exception as e:
log_error('Failed to process update check data {!r}, with error: {}'.format(raw, e)) log_error('Failed to process update check data {!r}, with error: {}'.format(raw, e))
def notification_activated(self, identifier):
if identifier == 'new-version':
from .update_check import notification_activated
notification_activated()
def dbus_notification_callback(self, activated, *args): def dbus_notification_callback(self, activated, *args):
from .notify import dbus_notification_created, dbus_notification_activated from .notify import dbus_notification_created, dbus_notification_activated
if activated: if activated:

128
setup.py
View File

@ -15,10 +15,11 @@ import subprocess
import sys import sys
import sysconfig import sysconfig
import time import time
from functools import partial
from collections import namedtuple from collections import namedtuple
from contextlib import suppress from contextlib import suppress
from functools import partial
from pathlib import Path from pathlib import Path
from typing import Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple
if sys.version_info[:2] < (3, 6): if sys.version_info[:2] < (3, 6):
raise SystemExit('kitty requires python >= 3.6') raise SystemExit('kitty requires python >= 3.6')
@ -42,9 +43,34 @@ version = tuple(
) )
_plat = sys.platform.lower() _plat = sys.platform.lower()
is_macos = 'darwin' in _plat is_macos = 'darwin' in _plat
env = None
class Env:
def __init__(
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
ldpaths: Optional[List[str]] = None, ccver: Optional[Tuple[int, int]] = None
):
self.cc, self.cppflags, self.cflags, self.ldflags, self.ldpaths = cc, cppflags, cflags, ldflags, [] if ldpaths is None else ldpaths
self.ccver = ccver
def copy(self):
return Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), list(self.ldpaths), self.ccver)
env = Env()
PKGCONFIG = os.environ.get('PKGCONFIG_EXE', 'pkg-config') PKGCONFIG = os.environ.get('PKGCONFIG_EXE', 'pkg-config')
CompileKey = namedtuple('CompileKey', 'src dest')
class Command(NamedTuple):
desc: str
cmd: Sequence[str]
is_newer_func: Callable[[], bool]
on_success: Callable[[], None]
key: Optional[CompileKey]
keyfile: Optional[str]
def emphasis(text): def emphasis(text):
@ -78,13 +104,15 @@ def at_least_version(package, major, minor=0):
q = '{}.{}'.format(major, minor) q = '{}.{}'.format(major, minor)
if subprocess.run([PKGCONFIG, package, '--atleast-version=' + q] if subprocess.run([PKGCONFIG, package, '--atleast-version=' + q]
).returncode != 0: ).returncode != 0:
qmajor = qminor = 0
try: try:
ver = subprocess.check_output([PKGCONFIG, package, '--modversion'] ver = subprocess.check_output([PKGCONFIG, package, '--modversion']
).decode('utf-8').strip() ).decode('utf-8').strip()
qmajor, qminor = map(int, re.match(r'(\d+).(\d+)', ver).groups()) m = re.match(r'(\d+).(\d+)', ver)
if m is not None:
qmajor, qminor = map(int, m.groups())
except Exception: except Exception:
ver = 'not found' ver = 'not found'
qmajor = qminor = 0
if qmajor < major or (qmajor == major and qminor < minor): if qmajor < major or (qmajor == major and qminor < minor):
raise SystemExit( raise SystemExit(
'{} >= {}.{} is required, found version: {}'.format( '{} >= {}.{} is required, found version: {}'.format(
@ -93,7 +121,7 @@ def at_least_version(package, major, minor=0):
) )
def cc_version(): def cc_version() -> Tuple[str, Tuple[int, int]]:
if 'CC' in os.environ: if 'CC' in os.environ:
cc = os.environ['CC'] cc = os.environ['CC']
else: else:
@ -107,9 +135,9 @@ def cc_version():
else: else:
cc = 'cc' cc = 'cc'
raw = subprocess.check_output([cc, '-dumpversion']).decode('utf-8') raw = subprocess.check_output([cc, '-dumpversion']).decode('utf-8')
ver = raw.split('.')[:2] ver_ = raw.split('.')[:2]
try: try:
ver = tuple(map(int, ver)) ver = int(ver_[0]), int(ver_[1])
except Exception: except Exception:
ver = (0, 0) ver = (0, 0)
return cc, ver return cc, ver
@ -125,9 +153,9 @@ def get_python_include_paths():
def get_python_flags(cflags): def get_python_flags(cflags):
cflags.extend('-I' + x for x in get_python_include_paths()) cflags.extend('-I' + x for x in get_python_include_paths())
libs = [] libs: List[str] = []
libs += sysconfig.get_config_var('LIBS').split() libs += (sysconfig.get_config_var('LIBS') or '').split()
libs += sysconfig.get_config_var('SYSLIBS').split() libs += (sysconfig.get_config_var('SYSLIBS') or '').split()
fw = sysconfig.get_config_var('PYTHONFRAMEWORK') fw = sysconfig.get_config_var('PYTHONFRAMEWORK')
if fw: if fw:
for var in 'data include stdlib'.split(): for var in 'data include stdlib'.split():
@ -141,15 +169,17 @@ def get_python_flags(cflags):
break break
else: else:
raise SystemExit('Failed to find Python framework') raise SystemExit('Failed to find Python framework')
libs.append( ldlib = sysconfig.get_config_var('LDLIBRARY')
os.path.join(framework_dir, sysconfig.get_config_var('LDLIBRARY')) if ldlib:
) libs.append(os.path.join(framework_dir, ldlib))
else: else:
libs += ['-L' + sysconfig.get_config_var('LIBDIR')] ldlib = sysconfig.get_config_var('LIBDIR')
libs += [ if ldlib:
'-lpython' + sysconfig.get_config_var('VERSION') + sys.abiflags libs += ['-L' + ldlib]
] ldlib = sysconfig.get_config_var('VERSION')
libs += sysconfig.get_config_var('LINKFORSHARED').split() if ldlib:
libs += ['-lpython' + ldlib + sys.abiflags]
libs += (sysconfig.get_config_var('LINKFORSHARED') or '').split()
return libs return libs
@ -180,16 +210,6 @@ def first_successful_compile(cc, *cflags, src=None):
return '' return ''
class Env:
def __init__(self, cc, cppflags, cflags, ldflags, ldpaths=None, ccver=None):
self.cc, self.cppflags, self.cflags, self.ldflags, self.ldpaths = cc, cppflags, cflags, ldflags, [] if ldpaths is None else ldpaths
self.ccver = ccver
def copy(self):
return Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), list(self.ldpaths), self.ccver)
def init_env( def init_env(
debug=False, sanitize=False, native_optimizations=True, profile=False, debug=False, sanitize=False, native_optimizations=True, profile=False,
extra_logging=() extra_logging=()
@ -209,13 +229,13 @@ def init_env(
fortify_source = '-D_FORTIFY_SOURCE=2' fortify_source = '-D_FORTIFY_SOURCE=2'
optimize = df if debug or sanitize else '-O3' optimize = df if debug or sanitize else '-O3'
sanitize_args = get_sanitize_args(cc, ccver) if sanitize else set() sanitize_args = get_sanitize_args(cc, ccver) if sanitize else set()
cppflags = os.environ.get( cppflags_ = os.environ.get(
'OVERRIDE_CPPFLAGS', '-D{}DEBUG'.format('' if debug else 'N'), 'OVERRIDE_CPPFLAGS', '-D{}DEBUG'.format('' if debug else 'N'),
) )
cppflags = shlex.split(cppflags) cppflags = shlex.split(cppflags_)
for el in extra_logging: for el in extra_logging:
cppflags.append('-DDEBUG_{}'.format(el.upper().replace('-', '_'))) cppflags.append('-DDEBUG_{}'.format(el.upper().replace('-', '_')))
cflags = os.environ.get( cflags_ = os.environ.get(
'OVERRIDE_CFLAGS', ( 'OVERRIDE_CFLAGS', (
'-Wextra {} -Wno-missing-field-initializers -Wall -Wstrict-prototypes -std=c11' '-Wextra {} -Wno-missing-field-initializers -Wall -Wstrict-prototypes -std=c11'
' -pedantic-errors -Werror {} {} -fwrapv {} {} -pipe {} -fvisibility=hidden {}' ' -pedantic-errors -Werror {} {} -fwrapv {} {} -pipe {} -fvisibility=hidden {}'
@ -229,21 +249,22 @@ def init_env(
fortify_source fortify_source
) )
) )
cflags = shlex.split(cflags) + shlex.split( cflags = shlex.split(cflags_) + shlex.split(
sysconfig.get_config_var('CCSHARED') sysconfig.get_config_var('CCSHARED') or ''
) )
ldflags = os.environ.get( ldflags_ = os.environ.get(
'OVERRIDE_LDFLAGS', 'OVERRIDE_LDFLAGS',
'-Wall ' + ' '.join(sanitize_args) + ('' if debug else ' -O3') '-Wall ' + ' '.join(sanitize_args) + ('' if debug else ' -O3')
) )
ldflags = shlex.split(ldflags) ldflags = shlex.split(ldflags_)
ldflags.append('-shared') ldflags.append('-shared')
cppflags += shlex.split(os.environ.get('CPPFLAGS', '')) cppflags += shlex.split(os.environ.get('CPPFLAGS', ''))
cflags += shlex.split(os.environ.get('CFLAGS', '')) cflags += shlex.split(os.environ.get('CFLAGS', ''))
ldflags += shlex.split(os.environ.get('LDFLAGS', '')) ldflags += shlex.split(os.environ.get('LDFLAGS', ''))
if not debug and not sanitize: if not debug and not sanitize:
# See https://github.com/google/sanitizers/issues/647 # See https://github.com/google/sanitizers/issues/647
cflags.append('-flto'), ldflags.append('-flto') cflags.append('-flto')
ldflags.append('-flto')
if profile: if profile:
cppflags.append('-DWITH_PROFILER') cppflags.append('-DWITH_PROFILER')
@ -373,11 +394,11 @@ def dependecies_for(src, obj, all_headers):
def parallel_run(items): def parallel_run(items):
try: try:
num_workers = max(2, os.cpu_count()) num_workers = max(2, os.cpu_count() or 1)
except Exception: except Exception:
num_workers = 2 num_workers = 2
items = list(reversed(items)) items = list(reversed(items))
workers = {} workers: Dict[int, Tuple[Optional[Command], Optional[subprocess.Popen]]] = {}
failed = None failed = None
num, total = 0, len(items) num, total = 0, len(items)
@ -387,7 +408,9 @@ def parallel_run(items):
return return
pid, s = os.wait() pid, s = os.wait()
compile_cmd, w = workers.pop(pid, (None, None)) compile_cmd, w = workers.pop(pid, (None, None))
if compile_cmd is not None and ((s & 0xff) != 0 or ((s >> 8) & 0xff) != 0): if compile_cmd is None:
return
if ((s & 0xff) != 0 or ((s >> 8) & 0xff) != 0):
if failed is None: if failed is None:
failed = compile_cmd failed = compile_cmd
elif compile_cmd.on_success is not None: elif compile_cmd.on_success is not None:
@ -415,10 +438,6 @@ def parallel_run(items):
run_tool(failed.cmd) run_tool(failed.cmd)
CompileKey = namedtuple('CompileKey', 'src dest')
Command = namedtuple('Command', 'desc cmd is_newer_func on_success key keyfile')
class CompilationDatabase: class CompilationDatabase:
def __init__(self, incremental): def __init__(self, incremental):
@ -499,10 +518,12 @@ def compile_c_extension(kenv, module, compilation_database, sources, headers, de
cppflags = kenv.cppflags[:] cppflags = kenv.cppflags[:]
is_special = src in SPECIAL_SOURCES is_special = src in SPECIAL_SOURCES
if is_special: if is_special:
src, defines = SPECIAL_SOURCES[src] src, defines_ = SPECIAL_SOURCES[src]
if callable(defines): if callable(defines_):
defines = defines() defines = defines_()
cppflags.extend(map(define, defines)) cppflags.extend(map(define, defines))
else:
cppflags.extend(map(define, defines_))
cmd = [kenv.cc, '-MMD'] + cppflags + kenv.cflags cmd = [kenv.cc, '-MMD'] + cppflags + kenv.cflags
cmd += ['-c', src] + ['-o', dest] cmd += ['-c', src] + ['-o', dest]
@ -697,7 +718,7 @@ def compile_python(base_path):
import compileall import compileall
import py_compile import py_compile
try: try:
num_workers = max(1, os.cpu_count()) num_workers = max(1, os.cpu_count() or 1)
except Exception: except Exception:
num_workers = 1 num_workers = 1
for root, dirs, files in os.walk(base_path): for root, dirs, files in os.walk(base_path):
@ -705,10 +726,10 @@ def compile_python(base_path):
if f.rpartition('.')[-1] in ('pyc', 'pyo'): if f.rpartition('.')[-1] in ('pyc', 'pyo'):
os.remove(os.path.join(root, f)) os.remove(os.path.join(root, f))
for optimize in (0, 1, 2): for optimize in (0, 1, 2):
kwargs = dict(ddir='', force=True, optimize=optimize, quiet=1, workers=num_workers) compileall.compile_dir(
if hasattr(py_compile, 'PycInvalidationMode'): base_path, ddir='', force=True, optimize=optimize, quiet=1,
kwargs['invalidation_mode'] = py_compile.PycInvalidationMode.UNCHECKED_HASH workers=num_workers, invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH
compileall.compile_dir(base_path, **kwargs) )
def create_linux_bundle_gunk(ddir, libdir_name): def create_linux_bundle_gunk(ddir, libdir_name):
@ -802,7 +823,8 @@ def create_minimal_macos_bundle(args, where):
shutil.rmtree(where) shutil.rmtree(where)
bin_dir = os.path.join(where, 'kitty.app/Contents/MacOS') bin_dir = os.path.join(where, 'kitty.app/Contents/MacOS')
resources_dir = os.path.join(where, 'kitty.app/Contents/Resources') resources_dir = os.path.join(where, 'kitty.app/Contents/Resources')
os.makedirs(resources_dir), os.makedirs(bin_dir) os.makedirs(resources_dir)
os.makedirs(bin_dir)
with open(os.path.join(where, 'kitty.app/Contents/Info.plist'), 'wb') as f: with open(os.path.join(where, 'kitty.app/Contents/Info.plist'), 'wb') as f:
f.write(macos_info_plist()) f.write(macos_info_plist())
build_launcher(args, bin_dir) build_launcher(args, bin_dir)