diff --git a/.github/workflows/ci.py b/.github/workflows/ci.py index 5acddd406..62f12e4e5 100644 --- a/.github/workflows/ci.py +++ b/.github/workflows/ci.py @@ -48,7 +48,7 @@ def install_deps(): def build_kitty(): python = shutil.which('python3') if is_bundle else sys.executable - cmd = '{} setup.py build --verbose'.format(python) + cmd = f'{python} setup.py build --verbose' if os.environ.get('KITTY_SANITIZE') == '1': cmd += ' --debug --sanitize' run(cmd) @@ -59,8 +59,8 @@ def test_kitty(): def package_kitty(): - py = 'python3' if is_macos else 'python' - run(py + ' setup.py linux-package --update-check-interval=0 --verbose') + python = 'python3' if is_macos else 'python' + run(f'{python} setup.py linux-package --update-check-interval=0 --verbose') if is_macos: run('python3 setup.py kitty.app --update-check-interval=0 --verbose') run('kitty.app/Contents/MacOS/kitty +runpy "from kitty.constants import *; print(kitty_exe())"') @@ -76,11 +76,11 @@ def replace_in_file(path, src, dest): def setup_bundle_env(): global SW os.environ['SW'] = SW = '/Users/Shared/kitty-build/sw/sw' if is_macos else os.path.join(os.environ['GITHUB_WORKSPACE'], 'sw') - os.environ['PKG_CONFIG_PATH'] = SW + '/lib/pkgconfig' + os.environ['PKG_CONFIG_PATH'] = os.path.join(SW, 'lib', 'pkgconfig') if is_macos: os.environ['PATH'] = '{}:{}'.format('/usr/local/opt/sphinx-doc/bin', os.environ['PATH']) else: - os.environ['LD_LIBRARY_PATH'] = SW + '/lib' + os.environ['LD_LIBRARY_PATH'] = os.path.join(SW, 'lib') os.environ['PYTHONHOME'] = SW os.environ['PATH'] = '{}:{}'.format(os.path.join(SW, 'bin'), os.environ['PATH']) @@ -111,7 +111,7 @@ def main(): setup_bundle_env() else: if not is_macos and 'pythonLocation' in os.environ: - os.environ['LD_LIBRARY_PATH'] = '{}/lib'.format(os.environ['pythonLocation']) + os.environ['LD_LIBRARY_PATH'] = os.path.join(os.environ['pythonLocation'], 'lib') action = sys.argv[-1] if action in ('build', 'package'): install_deps() @@ -122,7 +122,7 @@ def main(): elif action == 'test': test_kitty() else: - raise SystemExit('Unknown action: ' + action) + raise SystemExit(f'Unknown action: {action}') if __name__ == '__main__': diff --git a/build-terminfo b/build-terminfo index 3fbae33b5..25bbc50bc 100755 --- a/build-terminfo +++ b/build-terminfo @@ -13,7 +13,7 @@ import tempfile def compile_terminfo(base): with tempfile.TemporaryDirectory() as tdir: - proc = subprocess.run(['tic', '-x', '-o' + tdir, 'terminfo/kitty.terminfo'], check=True, stderr=subprocess.PIPE) + proc = subprocess.run(['tic', '-x', f'-o{tdir}', 'terminfo/kitty.terminfo'], check=True, stderr=subprocess.PIPE) regex = '^"terminfo/kitty.terminfo", line [0-9]+, col [0-9]+, terminal \'xterm-kitty\': older tic versions may treat the description field as an alias$' for error in proc.stderr.decode('utf-8').splitlines(): if not re.match(regex, error): diff --git a/bypy/init_env.py b/bypy/init_env.py index 02ae0ca04..1678d90bc 100644 --- a/bypy/init_env.py +++ b/bypy/init_env.py @@ -26,7 +26,7 @@ def initialize_constants(): kitty_constants = {} src = read_src_file('constants.py') nv = re.search(r'Version\((\d+), (\d+), (\d+)\)', src) - kitty_constants['version'] = '%s.%s.%s' % (nv.group(1), nv.group(2), nv.group(3)) + kitty_constants['version'] = f'{nv.group(1)}.{nv.group(2)}.{nv.group(3)}' kitty_constants['appname'] = re.search( r'appname: str\s+=\s+(u{0,1})[\'"]([^\'"]+)[\'"]', src ).group(2) diff --git a/bypy/linux/__main__.py b/bypy/linux/__main__.py index 5dde2c911..b89518f1d 100644 --- a/bypy/linux/__main__.py +++ b/bypy/linux/__main__.py @@ -38,7 +38,7 @@ def binary_includes(): 'ncursesw', 'readline', 'brotlicommon', 'brotlienc', 'brotlidec' ))) + ( get_dll_path('bz2', 2), get_dll_path('ssl', 2), get_dll_path('crypto', 2), - get_dll_path('python' + py_ver, 2), + get_dll_path(f'python{py_ver}', 2), ) @@ -47,7 +47,7 @@ class Env: def __init__(self, package_dir): self.base = package_dir self.lib_dir = j(self.base, 'lib') - self.py_dir = j(self.lib_dir, 'python' + py_ver) + self.py_dir = j(self.lib_dir, f'python{py_ver}') os.makedirs(self.py_dir) self.bin_dir = j(self.base, 'bin') self.obj_dir = mkdtemp('launchers-') @@ -107,7 +107,7 @@ def add_ca_certs(env): def copy_python(env): print('Copying python...') - srcdir = j(PREFIX, 'lib/python' + py_ver) + srcdir = j(PREFIX, f'lib/python{py_ver}') for x in os.listdir(srcdir): y = j(srcdir, x) @@ -187,11 +187,11 @@ def strip_files(files, argv_max=(256 * 1024)): def strip_binaries(files): - print('Stripping %d files...' % len(files)) + print(f'Stripping {len(files)} files...') before = sum(os.path.getsize(x) for x in files) strip_files(files) after = sum(os.path.getsize(x) for x in files) - print('Stripped %.1f MB' % ((before - after) / (1024 * 1024.))) + print('Stripped {:.1f} MB'.format((before - after) / (1024 * 1024.))) def create_tarfile(env, compression_level='9'): @@ -203,7 +203,7 @@ def create_tarfile(env, compression_level='9'): if err.errno != errno.ENOENT: raise os.mkdir(base) - dist = os.path.join(base, '%s-%s-%s.tar' % (kitty_constants['appname'], kitty_constants['version'], arch)) + dist = os.path.join(base, f'{kitty_constants["appname"]}-{kitty_constants["version"]}-{arch}.tar') with tarfile.open(dist, mode='w', format=tarfile.PAX_FORMAT) as tf: cwd = os.getcwd() os.chdir(env.base) @@ -213,13 +213,13 @@ def create_tarfile(env, compression_level='9'): finally: os.chdir(cwd) print('Compressing archive...') - ans = dist.rpartition('.')[0] + '.txz' + ans = f'{dist.rpartition(".")[0]}.txz' start_time = time.time() - subprocess.check_call(['xz', '--threads=0', '-f', '-' + compression_level, dist]) + subprocess.check_call(['xz', '--threads=0', '-f', f'-{compression_level}', dist]) secs = time.time() - start_time - print('Compressed in %d minutes %d seconds' % (secs // 60, secs % 60)) - os.rename(dist + '.xz', ans) - print('Archive %s created: %.2f MB' % ( + print('Compressed in {} minutes {} seconds'.format(secs // 60, secs % 60)) + os.rename(f'{dist}.xz', ans) + print('Archive {} created: {:.2f} MB'.format( os.path.basename(ans), os.stat(ans).st_size / (1024.**2))) diff --git a/bypy/macos/__main__.py b/bypy/macos/__main__.py index 15e5fbe29..e21eb924b 100644 --- a/bypy/macos/__main__.py +++ b/bypy/macos/__main__.py @@ -90,7 +90,7 @@ def strip_files(files, argv_max=(256 * 1024)): def files_in(folder): for record in os.walk(folder): for f in record[-1]: - yield os.path.join(record[0], f) + yield join(record[0], f) def expand_dirs(items, exclude=lambda x: x.endswith('.so')): @@ -103,7 +103,7 @@ def expand_dirs(items, exclude=lambda x: x.endswith('.so')): def do_sign(app_dir): - with current_dir(os.path.join(app_dir, 'Contents')): + with current_dir(join(app_dir, 'Contents')): # Sign all .so files so_files = {x for x in files_in('.') if x.endswith('.so')} codesign(so_files) @@ -153,7 +153,7 @@ class Freeze(object): self.to_strip = [] self.warnings = [] self.py_ver = py_ver - self.python_stdlib = join(self.resources_dir, 'Python', 'lib', 'python' + self.py_ver) + self.python_stdlib = join(self.resources_dir, 'Python', 'lib', f'python{self.py_ver}') self.site_packages = self.python_stdlib # hack to avoid needing to add site-packages to path self.obj_dir = mkdtemp('launchers-') @@ -177,7 +177,7 @@ class Freeze(object): self.run_tests() # self.run_shell() - ret = self.makedmg(self.build_dir, APPNAME + '-' + VERSION) + ret = self.makedmg(self.build_dir, f'{APPNAME}-{VERSION}') return ret @@ -186,7 +186,7 @@ class Freeze(object): print('\nDownloading CA certs...') from urllib.request import urlopen cdata = urlopen(kitty_constants['cacerts_url']).read() - dest = os.path.join(self.contents_dir, 'Resources', 'cacert.pem') + dest = join(self.contents_dir, 'Resources', 'cacert.pem') with open(dest, 'wb') as f: f.write(cdata) @@ -197,7 +197,7 @@ class Freeze(object): @flush def run_tests(self): - iv['run_tests'](os.path.join(self.contents_dir, 'MacOS', 'kitty')) + iv['run_tests'](join(self.contents_dir, 'MacOS', 'kitty')) @flush def set_id(self, path_to_lib, new_id): @@ -222,10 +222,10 @@ class Freeze(object): @flush def get_local_dependencies(self, path_to_lib): for x, is_id in self.get_dependencies(path_to_lib): - for y in (PREFIX + '/lib/', PREFIX + '/python/Python.framework/', '@rpath/'): + for y in (f'{PREFIX}/lib/', f'{PREFIX}/python/Python.framework/', '@rpath/'): if x.startswith(y): - if y == PREFIX + '/python/Python.framework/': - y = PREFIX + '/python/' + if y == f'{PREFIX}/python/Python.framework/': + y = f'{PREFIX}/python/' yield x, x[len(y):], is_id break @@ -239,7 +239,7 @@ class Freeze(object): self.to_strip.append(path_to_lib) old_mode = flipwritable(path_to_lib) for dep, bname, is_id in self.get_local_dependencies(path_to_lib): - ndep = self.FID + '/' + bname + ndep = f'{self.FID}/{bname}' self.change_dep(dep, ndep, is_id, path_to_lib) ldeps = list(self.get_local_dependencies(path_to_lib)) if ldeps: @@ -252,7 +252,7 @@ class Freeze(object): @flush def add_python_framework(self): print('\nAdding Python framework') - src = join(PREFIX + '/python', 'Python.framework') + src = join(f'{PREFIX}/python', 'Python.framework') x = join(self.frameworks_dir, 'Python.framework') curr = os.path.realpath(join(src, 'Versions', 'Current')) currd = join(x, 'Versions', basename(curr)) @@ -262,12 +262,12 @@ class Freeze(object): shutil.copy2(join(curr, 'Python'), currd) self.set_id( join(currd, 'Python'), - self.FID + '/Python.framework/Versions/%s/Python' % basename(curr)) + f'{self.FID}/Python.framework/Versions/{basename(curr)}/Python') # The following is needed for codesign with current_dir(x): os.symlink(basename(curr), 'Versions/Current') for y in ('Python', 'Resources'): - os.symlink('Versions/Current/%s' % y, y) + os.symlink(f'Versions/Current/{y}', y) @flush def install_dylib(self, path, set_id=True): @@ -275,7 +275,7 @@ class Freeze(object): if set_id: self.set_id( join(self.frameworks_dir, basename(path)), - self.FID + '/' + basename(path)) + f'{self.FID}/{basename(path)}') self.fix_dependencies_in_lib(join(self.frameworks_dir, basename(path))) @flush @@ -291,11 +291,11 @@ class Freeze(object): 'rsync.2', ): print('\nAdding', x) - x = 'lib%s.dylib' % x + x = f'lib{x}.dylib' src = join(PREFIX, 'lib', x) shutil.copy2(src, self.frameworks_dir) dest = join(self.frameworks_dir, x) - self.set_id(dest, self.FID + '/' + x) + self.set_id(dest, f'{self.FID}/{x}') self.fix_dependencies_in_lib(dest) @flush @@ -321,7 +321,7 @@ class Freeze(object): @flush def add_stdlib(self): print('\nAdding python stdlib') - src = PREFIX + '/python/Python.framework/Versions/Current/lib/python' + self.py_ver + src = f'{PREFIX}/python/Python.framework/Versions/Current/lib/python{self.py_ver}' dest = self.python_stdlib if not os.path.exists(dest): os.makedirs(dest) @@ -345,19 +345,19 @@ class Freeze(object): kitty_dir = join(self.resources_dir, 'kitty') bases = ('kitty', 'kittens', 'kitty_tests') for x in bases: - dest = os.path.join(self.python_stdlib, x) - os.rename(os.path.join(kitty_dir, x), dest) + dest = join(self.python_stdlib, x) + os.rename(join(kitty_dir, x), dest) if x == 'kitty': - shutil.rmtree(os.path.join(dest, 'launcher')) - os.rename(os.path.join(kitty_dir, '__main__.py'), os.path.join(self.python_stdlib, 'kitty_main.py')) - shutil.rmtree(os.path.join(kitty_dir, '__pycache__')) - pdir = os.path.join(dirname(self.python_stdlib), 'kitty-extensions') + shutil.rmtree(join(dest, 'launcher')) + os.rename(join(kitty_dir, '__main__.py'), join(self.python_stdlib, 'kitty_main.py')) + shutil.rmtree(join(kitty_dir, '__pycache__')) + pdir = join(dirname(self.python_stdlib), 'kitty-extensions') os.mkdir(pdir) print('Extracting extension modules from', self.python_stdlib, 'to', pdir) ext_map = extract_extension_modules(self.python_stdlib, pdir) - shutil.copy(os.path.join(os.path.dirname(self_dir), 'site.py'), os.path.join(self.python_stdlib, 'site.py')) + shutil.copy(join(os.path.dirname(self_dir), 'site.py'), join(self.python_stdlib, 'site.py')) for x in bases: - iv['sanitize_source_folder'](os.path.join(self.python_stdlib, x)) + iv['sanitize_source_folder'](join(self.python_stdlib, x)) self.compile_py_modules() freeze_python(self.python_stdlib, pdir, self.obj_dir, ext_map, develop_mode_env_var='KITTY_DEVELOP_FROM', remove_pyc_files=True) iv['build_frozen_launcher']([path_to_freeze_dir(), self.obj_dir]) @@ -434,23 +434,23 @@ class Freeze(object): ''' Copy a directory d into a dmg named volname ''' print('\nMaking dmg...') sys.stdout.flush() - destdir = os.path.join(SW, 'dist') + destdir = join(SW, 'dist') try: shutil.rmtree(destdir) except FileNotFoundError: pass os.mkdir(destdir) - dmg = os.path.join(destdir, volname + '.dmg') + dmg = join(destdir, f'{volname}.dmg') if os.path.exists(dmg): os.unlink(dmg) tdir = tempfile.mkdtemp() - appdir = os.path.join(tdir, os.path.basename(d)) + appdir = join(tdir, os.path.basename(d)) shutil.copytree(d, appdir, symlinks=True) if self.sign_installers: with timeit() as times: sign_app(appdir, self.notarize) - print('Signing completed in %d minutes %d seconds' % tuple(times)) - os.symlink('/Applications', os.path.join(tdir, 'Applications')) + print('Signing completed in {} minutes {} seconds'.format(*times)) + os.symlink('/Applications', join(tdir, 'Applications')) size_in_mb = int( subprocess.check_output(['du', '-s', '-k', tdir]).decode('utf-8') .split()[0]) / 1024. @@ -466,10 +466,10 @@ class Freeze(object): print('\nCreating dmg...') with timeit() as times: subprocess.check_call(cmd + [dmg]) - print('dmg created in %d minutes and %d seconds' % tuple(times)) + print('dmg created in {} minutes and {} seconds'.format(*times)) shutil.rmtree(tdir) size = os.stat(dmg).st_size / (1024 * 1024.) - print('\nInstaller size: %.2fMB\n' % size) + print(f'\nInstaller size: {size:.2f}MB\n') return dmg @@ -477,7 +477,7 @@ def main(): args = globals()['args'] ext_dir = globals()['ext_dir'] Freeze( - os.path.join(ext_dir, kitty_constants['appname'] + '.app'), + join(ext_dir, f'{kitty_constants["appname"]}.app'), dont_strip=args.dont_strip, sign_installers=args.sign_installers, notarize=args.notarize, diff --git a/docs/conf.py b/docs/conf.py index fc6d621a7..c0a95b913 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,7 +13,7 @@ import subprocess import sys import time from functools import partial -from typing import Any, Callable, Dict, Iterable, List, Match, Optional, Tuple +from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple from docutils import nodes from docutils.parsers.rst.roles import set_classes @@ -28,7 +28,7 @@ kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if kitty_src not in sys.path: sys.path.insert(0, kitty_src) -from kitty.conf.types import Definition # noqa +from kitty.conf.types import Definition, expand_opt_references # noqa from kitty.constants import str_version, website_url # noqa # config {{{ @@ -217,7 +217,8 @@ if you specify a program-to-run you can use the special placeholder from kitty.remote_control import cli_msg, global_options_spec with open('generated/cli-kitty-at.rst', 'w') as f: p = partial(print, file=f) - p('kitty @\n' + '-' * 80) + p('kitty @') + p('-' * 80) p('.. program::', 'kitty @') p('\n\n' + as_rst( global_options_spec, message=cli_msg, usage='command ...', appname='kitty @')) @@ -225,7 +226,8 @@ if you specify a program-to-run you can use the special placeholder for cmd_name in sorted(all_command_names()): func = command_for_name(cmd_name) p(f'.. _at_{func.name}:\n') - p('kitty @', func.name + '\n' + '-' * 120) + p('kitty @', func.name) + p('-' * 120) p('.. program::', 'kitty @', func.name) p('\n\n' + as_rst(*cli_params_for(func))) from kittens.runner import get_kitten_cli_docs @@ -234,12 +236,12 @@ if you specify a program-to-run you can use the special placeholder if data: with open(f'generated/cli-kitten-{kitten}.rst', 'w') as f: p = partial(print, file=f) - p('.. program::', f'kitty +kitten {kitten}') - p(f'\nSource code for {kitten}') + p('.. program::', 'kitty +kitten', kitten) + p('\nSource code for', kitten) p('-' * 72) p(f'\nThe source code for this kitten is `available on GitHub `_.') p('\nCommand Line Interface') - p('-' * 72, file=f) + p('-' * 72) p('\n\n' + option_spec_as_rst( data['options'], message=data['help_text'], usage=data['usage'], appname=f'kitty +kitten {kitten}', heading_char='^')) @@ -364,19 +366,6 @@ def link_role( return [node], [] -def expand_opt_references(conf_name: str, text: str) -> str: - conf_name += '.' - - def expand(m: Match[str]) -> str: - ref = m.group(1) - if '<' not in ref and '.' not in ref: - full_ref = conf_name + ref - return f':opt:`{ref} <{full_ref}>`' - return str(m.group()) - - return re.sub(r':opt:`(.+?)`', expand, text) - - opt_aliases: Dict[str, str] = {} shortcut_slugs: Dict[str, Tuple[str, str]] = {} @@ -414,7 +403,7 @@ def process_opt_link(env: Any, refnode: Any, has_explicit_title: bool, title: st conf_name, opt = target.partition('.')[::2] if not opt: conf_name, opt = 'kitty', conf_name - full_name = conf_name + '.' + opt + full_name = f'{conf_name}.{opt}' return title, opt_aliases.get(full_name, full_name) @@ -422,7 +411,7 @@ def process_shortcut_link(env: Any, refnode: Any, has_explicit_title: bool, titl conf_name, slug = target.partition('.')[::2] if not slug: conf_name, slug = 'kitty', conf_name - full_name = conf_name + '.' + slug + full_name = f'{conf_name}.{slug}' try: target, stitle = shortcut_slugs[full_name] except KeyError: diff --git a/gen-apc-parsers.py b/gen-apc-parsers.py index 67067101a..241209a62 100755 --- a/gen-apc-parsers.py +++ b/gen-apc-parsers.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # License: GPLv3 Copyright: 2018, Kovid Goyal +import os import subprocess from collections import defaultdict from typing import Any, DefaultDict, Dict, FrozenSet, List, Tuple, Union @@ -42,7 +43,7 @@ def parse_flag(keymap: KeymapType, type_map: Dict[str, Any], command_class: str) lines = [] for ch in type_map['flag']: attr, allowed_values = keymap[ch] - q = ' && '.join(f"g.{attr} != '{x}'" for x in allowed_values) + q = ' && '.join(f"g.{attr} != '{x}'" for x in sorted(allowed_values)) lines.append(f''' case {attr}: {{ g.{attr} = screen->parser_buf[pos++] & 0xff; @@ -67,7 +68,7 @@ def cmd_for_report(report_name: str, keymap: KeymapType, type_map: Dict[str, Any flag_fmt, flag_attrs = [], [] cv = {'flag': 'c', 'int': 'i', 'uint': 'I'}[atype] for ch in type_map[atype]: - flag_fmt.append('s' + cv) + flag_fmt.append(f's{cv}') attr = keymap[ch][0] flag_attrs.append(f'"{attr}", {conv}g.{attr}') return ' '.join(flag_fmt), ', '.join(flag_attrs) @@ -240,7 +241,7 @@ static inline void def write_header(text: str, path: str) -> None: with open(path, 'w') as f: - print(f'// This file is generated by {__file__} do not edit!', file=f, end='\n\n') + print(f'// This file is generated by {os.path.basename(__file__)} do not edit!', file=f, end='\n\n') print('#pragma once', file=f) print(text, file=f) subprocess.check_call(['clang-format', '-i', path]) diff --git a/gen-key-constants.py b/gen-key-constants.py index 81e366f85..f52050be1 100755 --- a/gen-key-constants.py +++ b/gen-key-constants.py @@ -238,7 +238,7 @@ def patch_file(path: str, what: str, text: str, start_marker: str = '/* ', end_m end = raw.index(end_q) except ValueError: raise SystemExit(f'Failed to find "{end_q}" in {path}') - raw = raw[:start] + start_q + '\n' + text + '\n' + raw[end:] + raw = f'{raw[:start]}{start_q}\n{text}\n{raw[end:]}' f.seek(0) f.truncate(0) f.write(raw) @@ -368,7 +368,7 @@ def generate_ctrl_mapping() -> None: val = str(ctrl_mapping[k]) items.append(val) if k in "\\'": - k = '\\' + k + k = f'\\{k}' mi.append(f" case '{k}': return {val};") for line_items in chunks(items, 6): diff --git a/glfw/glfw.py b/glfw/glfw.py index 6cfb89650..e7a5cf0c7 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -80,7 +80,7 @@ def init_env( ) -> Env: ans = env.copy() ans.cflags.append('-fPIC') - ans.cppflags.append('-D_GLFW_' + module.upper()) + ans.cppflags.append(f'-D_GLFW_{module.upper()}') ans.cppflags.append('-D_GLFW_BUILD_DLL') with open(os.path.join(base, 'source-info.json')) as f: diff --git a/kittens/diff/collect.py b/kittens/diff/collect.py index 2380de75c..104f8ee11 100644 --- a/kittens/diff/collect.py +++ b/kittens/diff/collect.py @@ -101,7 +101,7 @@ def remote_hostname(path: str) -> Tuple[Optional[str], Optional[str]]: def resolve_remote_name(path: str, default: str) -> str: remote_dir, rh = remote_hostname(path) if remote_dir and rh: - return rh + ':' + os.path.relpath(path, remote_dir) + return f'{rh}:{os.path.relpath(path, remote_dir)}' return default diff --git a/kittens/diff/highlight.py b/kittens/diff/highlight.py index 968b195b3..0a1eb502d 100644 --- a/kittens/diff/highlight.py +++ b/kittens/diff/highlight.py @@ -97,7 +97,7 @@ def highlight_data(code: str, filename: str, aliases: Optional[Dict[str, str]] = base, ext = os.path.splitext(filename) alias = aliases.get(ext[1:]) if alias is not None: - filename = base + '.' + alias + filename = f'{base}.{alias}' try: lexer = get_lexer_for_filename(filename, stripnl=False) except ClassNotFound: diff --git a/kittens/diff/main.py b/kittens/diff/main.py index c5282f85e..16e00efa0 100644 --- a/kittens/diff/main.py +++ b/kittens/diff/main.py @@ -347,7 +347,7 @@ class DiffHandler(Handler): text = line.text if line.image_data is not None: image_involved = True - self.write('\r\x1b[K' + text + '\x1b[0m') + self.write(f'\r\x1b[K{text}\x1b[0m') if self.current_search is not None: self.current_search.highlight_line(self.write, lpos) if i < num - 1: @@ -465,7 +465,7 @@ class DiffHandler(Handler): ) else: counts = styled(f'{len(self.current_search)} matches', fg=self.opts.margin_fg) - suffix = counts + ' ' + scroll_frac + suffix = f'{counts} {scroll_frac}' prefix = styled(':', fg=self.opts.margin_fg) filler = self.screen_size.cols - wcswidth(prefix) - wcswidth(suffix) text = '{}{}{}'.format(prefix, ' ' * filler, suffix) diff --git a/kittens/diff/patch.py b/kittens/diff/patch.py index 0042af76e..44c777a76 100644 --- a/kittens/diff/patch.py +++ b/kittens/diff/patch.py @@ -244,14 +244,14 @@ class Differ: except Exception as e: return f'Running git diff for {left_path} vs. {right_path} generated an exception: {e}' if not ok: - return output + f'\nRunning git diff for {left_path} vs. {right_path} failed' + return f'{output}\nRunning git diff for {left_path} vs. {right_path} failed' left_lines = lines_for_path(left_path) right_lines = lines_for_path(right_path) try: patch = parse_patch(output) except Exception: import traceback - return traceback.format_exc() + f'\nParsing diff for {left_path} vs. {right_path} failed' + return f'{traceback.format_exc()}\nParsing diff for {left_path} vs. {right_path} failed' else: ans[key] = patch return ans diff --git a/kittens/diff/render.py b/kittens/diff/render.py index 5b29b0f71..6e6cbdf13 100644 --- a/kittens/diff/render.py +++ b/kittens/diff/render.py @@ -101,7 +101,7 @@ def human_readable(size: int, sep: str = ' ') -> str: s = s[:s.find(".")+2] if s.endswith('.0'): s = s[:-2] - return s + sep + suffix + return f'{s}{sep}{suffix}' def fit_in(text: str, count: int) -> str: @@ -110,7 +110,7 @@ def fit_in(text: str, count: int) -> str: return text if count > 1: p = truncate_point_for_length(text, count - 1) - return text[:p] + '…' + return f'{text[:p]}…' def fill_in(text: str, sz: int) -> str: @@ -127,8 +127,8 @@ def place_in(text: str, sz: int) -> str: def format_func(which: str) -> Callable[[str], str]: def formatted(text: str) -> str: fmt = formats[which] - return '\x1b[' + fmt + 'm' + text + '\x1b[0m' - formatted.__name__ = which + '_format' + return f'\x1b[{fmt}m{text}\x1b[0m' + formatted.__name__ = f'{which}_format' return formatted @@ -148,8 +148,8 @@ highlight_map = {'remove': ('removed_highlight', 'removed'), 'add': ('added_high def highlight_boundaries(ltype: str) -> Tuple[str, str]: s, e = highlight_map[ltype] - start = '\x1b[' + formats[s] + 'm' - stop = '\x1b[' + formats[e] + 'm' + start = f'\x1b[{formats[s]}m' + stop = f'\x1b[{formats[e]}m' return start, stop diff --git a/kittens/hints/main.py b/kittens/hints/main.py index df2e7fe01..6acf9e292 100644 --- a/kittens/hints/main.py +++ b/kittens/hints/main.py @@ -729,7 +729,7 @@ def linenum_handle_result(args: List[str], data: Dict[str, Any], target_window_i else: import shlex text = ' '.join(shlex.quote(arg) for arg in cmd) - w.paste_bytes(text + '\r') + w.paste_bytes(f'{text}\r') elif action == 'background': import subprocess subprocess.Popen(cmd, cwd=data['cwd']) diff --git a/kittens/query_terminal/main.py b/kittens/query_terminal/main.py index b7d518710..22aeb2b7d 100644 --- a/kittens/query_terminal/main.py +++ b/kittens/query_terminal/main.py @@ -245,7 +245,7 @@ def main(args: List[str] = sys.argv) -> None: raise SystemExit(f'Unknown queries: {", ".join(extra)}') for key, val in do_queries(queries, cli_opts).items(): - print(key + ':', val) + print(f'{key}:', val) if __name__ == '__main__': diff --git a/kittens/show_key/kitty_mode.py b/kittens/show_key/kitty_mode.py index a1113440d..369a8c46d 100644 --- a/kittens/show_key/kitty_mode.py +++ b/kittens/show_key/kitty_mode.py @@ -52,7 +52,7 @@ class KeysHandler(Handler): self.cmd.colored(etype + ' ', 'yellow') self.cmd.styled(key_event.text, italic=True) self.print() - rep = 'CSI ' + encode_key_event(key_event)[2:] + rep = f'CSI {encode_key_event(key_event)[2:]}' rep = rep.replace(';', ' ; ').replace(':', ' : ')[:-1] + ' ' + rep[-1] self.cmd.styled(rep, fg='magenta') if (key_event.shifted_key or key_event.alternate_key): diff --git a/kittens/show_key/main.py b/kittens/show_key/main.py index 635074ea0..e4ba18e49 100644 --- a/kittens/show_key/main.py +++ b/kittens/show_key/main.py @@ -17,7 +17,7 @@ def print_key(raw: bytearray) -> None: unix = '' for ch in raw: if ch < len(ctrl_keys): - unix += '^' + ctrl_keys[ch] + unix += f'^{ctrl_keys[ch]}' elif ch == 127: unix += '^?' else: diff --git a/kittens/ssh/completion.py b/kittens/ssh/completion.py index ff97c6bd9..6ac079263 100644 --- a/kittens/ssh/completion.py +++ b/kittens/ssh/completion.py @@ -281,7 +281,7 @@ def complete_choices(ans: Completions, prefix: str, title: str, choices: Iterabl if q.startswith(effective_prefix): if comma_separated: tq = q - q = hidden_prefix + q + ',' + q = f'{hidden_prefix}{q},' word_transforms[q] = tq matches[q] = '' ans.add_match_group(title, matches, trailing_space=not comma_separated, word_transforms=word_transforms) diff --git a/kittens/ssh/main.py b/kittens/ssh/main.py index 5e286a29e..da5e022f9 100644 --- a/kittens/ssh/main.py +++ b/kittens/ssh/main.py @@ -131,7 +131,7 @@ def get_ssh_cli() -> Tuple[Set[str], Set[str]]: other_ssh_args: Set[str] = set() boolean_ssh_args: Set[str] = set() for k, v in ssh_options().items(): - k = '-' + k + k = f'-{k}' if v: other_ssh_args.add(k) else: @@ -213,7 +213,7 @@ class InvalidSSHArgs(ValueError): def parse_ssh_args(args: List[str]) -> Tuple[List[str], List[str], bool]: boolean_ssh_args, other_ssh_args = get_ssh_cli() - passthrough_args = {'-' + x for x in 'Nnf'} + passthrough_args = {f'-{x}' for x in 'Nnf'} ssh_args = [] server_args: List[str] = [] expecting_option_val = False @@ -230,7 +230,7 @@ def parse_ssh_args(args: List[str]) -> Tuple[List[str], List[str], bool]: # could be a multi-character option all_args = argument[1:] for i, arg in enumerate(all_args): - arg = '-' + arg + arg = f'-{arg}' if arg in passthrough_args: passthrough = True if arg in boolean_ssh_args: diff --git a/kittens/themes/collection.py b/kittens/themes/collection.py index 2b8c5935e..c7d24e79a 100644 --- a/kittens/themes/collection.py +++ b/kittens/themes/collection.py @@ -376,7 +376,7 @@ def fetch_themes( needs_delete = False try: - with tempfile.NamedTemporaryFile(suffix='-' + os.path.basename(dest_path), dir=os.path.dirname(dest_path), delete=False) as f: + with tempfile.NamedTemporaryFile(suffix=f'-{os.path.basename(dest_path)}', dir=os.path.dirname(dest_path), delete=False) as f: needs_delete = True shutil.copyfileobj(res, f) f.flush() @@ -405,7 +405,7 @@ def theme_name_from_file_name(fname: str) -> str: ans = ans.replace('_', ' ') def camel_case(m: 'Match[str]') -> str: - return str(m.group(1) + ' ' + m.group(2)) + return f'{m.group(1)} {m.group(2)}' ans = re.sub(r'([a-z])([A-Z])', camel_case, ans) return ' '.join(x.capitalize() for x in filter(None, ans.split())) @@ -533,7 +533,7 @@ class Theme: raw = '' nraw = patch_conf(raw, self.name) if raw: - with open(confpath + '.bak', 'w') as f: + with open(f'{confpath}.bak', 'w') as f: f.write(raw) atomic_save(nraw.encode('utf-8'), confpath) if reload_in == 'parent': diff --git a/kittens/themes/main.py b/kittens/themes/main.py index 48024bf1c..68ea6b0f8 100644 --- a/kittens/themes/main.py +++ b/kittens/themes/main.py @@ -37,7 +37,7 @@ def limit_length(text: str, limit: int = 32) -> str: x = truncate_point_for_length(text, limit - 1) if x >= len(text): return text - return text[:x] + '…' + return f'{text[:x]}…' class State(Enum): @@ -332,7 +332,7 @@ class ThemesHandler(Handler): for line, width, is_current in self.themes_list.lines(num_rows): num_rows -= 1 if is_current: - line = line.replace(MARK_AFTER, '\033[' + color_code('green') + 'm') + line = line.replace(MARK_AFTER, f'\033[{color_code("green")}m') self.cmd.styled('>' if is_current else ' ', fg='green') self.cmd.styled(line, bold=is_current, fg='green' if is_current else None) self.cmd.move_cursor_by(mw - width, 'right') diff --git a/kittens/transfer/librsync.py b/kittens/transfer/librsync.py index 1f951323d..21d9feed2 100644 --- a/kittens/transfer/librsync.py +++ b/kittens/transfer/librsync.py @@ -155,12 +155,12 @@ def develop() -> None: import sys src = sys.argv[-1] sig_loader = LoadSignature() - with open(src + '.sig', 'wb') as f: + with open(f'{src}.sig', 'wb') as f: for chunk in signature_of_file(src): sig_loader.add_chunk(chunk) f.write(chunk) sig_loader.commit() - with open(src + '.delta', 'wb') as f, PatchFile(src, src + '.output') as patcher: + with open(f'{src}.delta', 'wb') as f, PatchFile(src, f'{src}.output') as patcher: for chunk in delta_for_file(src, sig_loader.signature): f.write(chunk) patcher.write(chunk) diff --git a/kittens/transfer/utils.py b/kittens/transfer/utils.py index 54ed9589e..fa55b63a8 100644 --- a/kittens/transfer/utils.py +++ b/kittens/transfer/utils.py @@ -45,7 +45,7 @@ def render_path_in_width(path: str, width: int) -> str: if wcswidth(path) <= width: return path x = truncate_point_for_length(path, width - 1) - return path[:x] + '…' + return f'{path[:x]}…' def render_seconds(val: float) -> str: diff --git a/kittens/tui/dircolors.py b/kittens/tui/dircolors.py index 6d0fd304e..804b865ca 100644 --- a/kittens/tui/dircolors.py +++ b/kittens/tui/dircolors.py @@ -331,7 +331,7 @@ class Dircolors: # change .xyz to *.xyz yield '*' + pair[0], pair[1] - return ':'.join('%s=%s' % pair for pair in gen_pairs()) + return ':'.join('{}={}'.format(*pair) for pair in gen_pairs()) def _format_code(self, text: str, code: str) -> str: val = self.codes.get(code) diff --git a/kittens/tui/operations.py b/kittens/tui/operations.py index 308e758ed..add55d472 100644 --- a/kittens/tui/operations.py +++ b/kittens/tui/operations.py @@ -163,7 +163,7 @@ def set_scrolling_region(screen_size: Optional['ScreenSize'] = None, top: Option @cmd def scroll_screen(amt: int = 1) -> str: - return '\033[' + str(abs(amt)) + ('T' if amt < 0 else 'S') + return f'\033[{abs(amt)}{"T" if amt < 0 else "S"}' STANDARD_COLORS = {'black': 0, 'red': 1, 'green': 2, 'yellow': 3, 'blue': 4, 'magenta': 5, 'cyan': 6, 'gray': 7, 'white': 7} @@ -465,7 +465,7 @@ def as_type_stub() -> str: for name, func in all_cmds.items(): args = ', '.join(func_sig(func)) if args: - args = ', ' + args + args = f', {args}' methods.append(f' def {name}(self{args}) -> str: pass') ans += ['', '', 'class CMD:'] + methods diff --git a/kittens/unicode_input/main.py b/kittens/unicode_input/main.py index 0f2e90688..d7c996ca5 100644 --- a/kittens/unicode_input/main.py +++ b/kittens/unicode_input/main.py @@ -192,7 +192,7 @@ class Table: if w < 2: text += ' ' * (2 - w) if len(desc) > space_for_desc: - text += desc[:space_for_desc - 1] + '…' + text += f'{desc[:space_for_desc - 1]}…' else: text += desc extra = space_for_desc - len(desc) diff --git a/kitty/child.py b/kitty/child.py index 1bca54b7f..a8b990fc9 100644 --- a/kitty/child.py +++ b/kitty/child.py @@ -62,7 +62,7 @@ else: except Exception: continue try: - with open('/proc/' + x + '/stat', 'rb') as f: + with open(f'/proc/{x}/stat', 'rb') as f: raw = f.read().decode('utf-8') except OSError: continue @@ -268,7 +268,7 @@ class Child: # https://github.com/kovidgoyal/kitty/issues/1870 # xterm, urxvt, konsole and gnome-terminal do not do it in my # testing. - argv[0] = ('-' + exe.split('/')[-1]) + argv[0] = (f'-{exe.split("/")[-1]}') exe = which(exe) or exe pid = fast_data_types.spawn(exe, self.cwd, tuple(argv), env, master, slave, stdin_read_fd, stdin_write_fd, ready_read_fd, ready_write_fd) os.close(slave) diff --git a/kitty/cli_stub.py b/kitty/cli_stub.py index c14f83549..53714af3d 100644 --- a/kitty/cli_stub.py +++ b/kitty/cli_stub.py @@ -82,7 +82,7 @@ def generate_stub() -> None: for cmd_name in all_command_names(): cmd = command_for_name(cmd_name) if cmd.options_spec: - do(cmd.options_spec, cmd.__class__.__name__ + 'RCOptions') + do(cmd.options_spec, f'{cmd.__class__.__name__}RCOptions') save_type_stub(text, __file__) diff --git a/kitty/client.py b/kitty/client.py index ab727b681..3417f4ad5 100644 --- a/kitty/client.py +++ b/kitty/client.py @@ -12,8 +12,8 @@ from contextlib import suppress from typing import Any -CSI = '\033[' -OSC = '\033]' +CSI = '\x1b[' +OSC = '\x1b]' def write(x: str) -> None: @@ -42,11 +42,11 @@ def screen_alternate_keypad_mode() -> None: def screen_cursor_position(y: int, x: int) -> None: - write(CSI + f'{y};{x}H') + write(f'{CSI}{y};{x}H') def screen_cursor_forward(amt: int) -> None: - write(CSI + '%sC' % amt) + write(f'{CSI}{amt}C') def screen_save_cursor() -> None: @@ -58,105 +58,105 @@ def screen_restore_cursor() -> None: def screen_cursor_back1(amt: int) -> None: - write(CSI + '%sD' % amt) + write(f'{CSI}{amt}D') def screen_save_modes() -> None: - write(CSI + '?s') + write(f'{CSI}?s') def screen_restore_modes() -> None: - write(CSI + '?r') + write(f'{CSI}?r') def screen_designate_charset(which: int, to: int) -> None: w = '()'[int(which)] t = chr(int(to)) - write('\033' + w + t) + write(f'\x1b{w}{t}') def select_graphic_rendition(*a: int) -> None: - write(CSI + '%sm' % ';'.join(map(str, a))) + write(f'{CSI}{";".join(map(str, a))}m') def screen_cursor_to_column(c: int) -> None: - write(CSI + '%dG' % c) + write(f'{CSI}{c}G') def screen_cursor_to_line(ln: int) -> None: - write(CSI + '%dd' % ln) + write(f'{CSI}{ln}d') def screen_set_mode(x: int, private: bool) -> None: - write(CSI + ('?' if private else '') + str(x) + 'h') + write(f'{CSI}{"?" if private else ""}{x}h') def screen_save_mode(x: int, private: bool) -> None: - write(CSI + ('?' if private else '') + str(x) + 's') + write(f'{CSI}{"?" if private else ""}{x}s') def screen_reset_mode(x: int, private: bool) -> None: - write(CSI + ('?' if private else '') + str(x) + 'l') + write(f'{CSI}{"?" if private else ""}{x}l') def screen_restore_mode(x: int, private: bool) -> None: - write(CSI + ('?' if private else '') + str(x) + 'r') + write(f'{CSI}{"?" if private else ""}{x}r') def screen_set_margins(t: int, b: int) -> None: - write(CSI + '%d;%dr' % (t, b)) + write(f'{CSI}{t};{b}r') def screen_indexn(n: int) -> None: - write(CSI + '%dS' % n) + write(f'{CSI}{n}S') def screen_delete_characters(count: int) -> None: - write(CSI + '%dP' % count) + write(f'{CSI}{count}P') def screen_push_colors(which: int) -> None: - write(CSI + '%d#P' % which) + write(f'{CSI}{which}#P') def screen_pop_colors(which: int) -> None: - write(CSI + '%d#Q' % which) + write(f'{CSI}{which}#Q') def screen_report_colors() -> None: - write(CSI + '#R') + write(f'{CSI}#R') def screen_repeat_character(num: int) -> None: - write(CSI + '%db' % num) + write(f'{CSI}{num}b') def screen_insert_characters(count: int) -> None: - write(CSI + '%d@' % count) + write(f'{CSI}{count}@') def screen_scroll(count: int) -> None: - write(CSI + '%dS' % count) + write(f'{CSI}{count}S') def screen_erase_in_display(how: int, private: bool) -> None: - write(CSI + ('?' if private else '') + str(how) + 'J') + write(f'{CSI}{"?" if private else ""}{how}J') def screen_erase_in_line(how: int, private: bool) -> None: - write(CSI + ('?' if private else '') + str(how) + 'K') + write(f'{CSI}{"?" if private else ""}{how}K') def screen_delete_lines(num: int) -> None: - write(CSI + str(num) + 'M') + write(f'{CSI}{num}M') def screen_cursor_up2(count: int) -> None: - write(CSI + '%dA' % count) + write(f'{CSI}{count}A') def screen_cursor_down(count: int) -> None: - write(CSI + '%dB' % count) + write(f'{CSI}{count}B') def screen_carriage_return() -> None: @@ -176,11 +176,11 @@ def screen_backspace() -> None: def screen_set_cursor(mode: int, secondary: int) -> None: - write(CSI + '%d q' % secondary) + write(f'{CSI}{secondary} q') def screen_insert_lines(num: int) -> None: - write(CSI + '%dL' % num) + write(f'{CSI}{num}L') def draw(*a: str) -> None: @@ -188,7 +188,7 @@ def draw(*a: str) -> None: def screen_manipulate_title_stack(op: int, which: int) -> None: - write(CSI + '%d;%dt' % (op, which)) + write(f'{CSI}{op};{which}t') def report_device_attributes(mode: int, char: int) -> None: @@ -197,21 +197,22 @@ def report_device_attributes(mode: int, char: int) -> None: x += chr(char) if mode: x += str(mode) - write(CSI + x + 'c') + write(f'{CSI}{x}c') def screen_decsace(mode: int) -> None: - write(CSI + str(mode) + '*x') + write(f'{CSI}{mode}*x') def screen_set_8bit_controls(mode: int) -> None: - write('\x1b ' + ('G' if mode else 'F')) + write(f'\x1b {"G" if mode else "F"}') def write_osc(code: int, string: str = '') -> None: if string: - string = ';' + string - write(OSC + str(code) + string + '\x07') + write(f'{OSC}{code};{string}\x07') + else: + write(f'{OSC}{code}\x07') set_dynamic_color = set_color_table_color = process_cwd_notification = write_osc @@ -235,7 +236,7 @@ def clipboard_control(payload: str) -> None: clipboard_control_pending += data.lstrip(';') payload = clipboard_control_pending clipboard_control_pending = '' - write(OSC + payload + '\x07') + write(f'{OSC}{payload}\x07') def replay(raw: str) -> None: diff --git a/kitty/complete.py b/kitty/complete.py index dcaf14841..d3a49f978 100644 --- a/kitty/complete.py +++ b/kitty/complete.py @@ -270,7 +270,7 @@ def zsh_output_serializer(ans: Completions) -> str: yield ans for description, matches in ans.match_groups.items(): - cmd = ['compadd', '-U', '-J', shlex.quote(description), '-X', shlex.quote('%B' + description + '%b')] + cmd = ['compadd', '-U', '-J', shlex.quote(description), '-X', shlex.quote(f'%B{description}%b')] if not matches.trailing_space: cmd += ['-S', '""'] if matches.is_files: @@ -350,10 +350,10 @@ def fish2_output_serializer(ans: Completions) -> str: def completions_for_first_word(ans: Completions, prefix: str, entry_points: Iterable[str], namespaced_entry_points: Iterable[str]) -> None: - cmds = ['@' + c for c in remote_control_command_names()] + cmds = [f'@{c}' for c in remote_control_command_names()] ans.add_match_group('Entry points', { k: '' for k in - list(entry_points) + cmds + ['+' + k for k in namespaced_entry_points] + list(entry_points) + cmds + [f'+{k}' for k in namespaced_entry_points] if not prefix or k.startswith(prefix) }) if prefix: @@ -443,7 +443,7 @@ def complete_alias_map( long_opt = option_map.get(parts[0]) if long_opt is not None and complete_args is not None: complete_args(ans, long_opt, parts[1], Delegate()) - ans.add_prefix(parts[0] + '=') + ans.add_prefix(f'{parts[0]}=') return opt = option_map.get(w) if w is last_word and not new_word: @@ -682,7 +682,7 @@ def find_completions(words: Sequence[str], new_word: bool, entry_points: Iterabl if words[0].startswith('@'): if len(words) == 1 and not new_word: prefix = words[0] - ans.add_match_group('Remote control commands', {'@' + c: '' for c in remote_control_command_names() if c.startswith(prefix)}) + ans.add_match_group('Remote control commands', {f'@{c}': '' for c in remote_control_command_names() if c.startswith(prefix)}) else: complete_remote_command(ans, words[0][1:], words[1:], new_word) if words[0] == '+': diff --git a/kitty/conf/generate.py b/kitty/conf/generate.py index e8edc2b19..a1c0166a9 100644 --- a/kitty/conf/generate.py +++ b/kitty/conf/generate.py @@ -418,9 +418,9 @@ def generate_c_conversion(loc: str, ctypes: List[Option]) -> str: def write_output(loc: str, defn: Definition) -> None: cls, tc = generate_class(defn, loc) with open(os.path.join(*loc.split('.'), 'options', 'types.py'), 'w') as f: - f.write(cls + '\n') + f.write(f'{cls}\n') with open(os.path.join(*loc.split('.'), 'options', 'parse.py'), 'w') as f: - f.write(tc + '\n') + f.write(f'{tc}\n') ctypes = [] for opt in defn.root_group.iter_all_non_groups(): if isinstance(opt, Option) and opt.ctype: @@ -428,7 +428,7 @@ def write_output(loc: str, defn: Definition) -> None: if ctypes: c = generate_c_conversion(loc, ctypes) with open(os.path.join(*loc.split('.'), 'options', 'to-c-generated.h'), 'w') as f: - f.write(c + '\n') + f.write(f'{c}\n') def main() -> None: @@ -454,6 +454,6 @@ def main() -> None: loc = package_name cls, tc = generate_class(defn, loc) with open(os.path.join(os.path.dirname(path), 'kitten_options_types.py'), 'w') as f: - f.write(cls + '\n') + f.write(f'{cls}\n') with open(os.path.join(os.path.dirname(path), 'kitten_options_parse.py'), 'w') as f: - f.write(tc + '\n') + f.write(f'{tc}\n') diff --git a/kitty/conf/types.py b/kitty/conf/types.py index 03ab3df19..774d666b3 100644 --- a/kitty/conf/types.py +++ b/kitty/conf/types.py @@ -37,8 +37,8 @@ def expand_opt_references(conf_name: str, text: str) -> str: def expand(m: 'Match[str]') -> str: ref = m.group(1) if '<' not in ref and '.' not in ref: - full_ref = conf_name + ref - return f':opt:`{ref} <{full_ref}>`' + # full ref + return f':opt:`{ref} <{conf_name}{ref}>`' return str(m.group()) return re.sub(r':opt:`(.+?)`', expand, text) @@ -214,7 +214,7 @@ class Option: if not self.documented: return ans mopts = [self] + option_group - a('.. opt:: ' + ', '.join(conf_name + '.' + mo.name for mo in mopts)) + a('.. opt:: ' + ', '.join(f'{conf_name}.{mo.name}' for mo in mopts)) a('.. code-block:: conf') a('') sz = max(len(x.name) for x in mopts) @@ -330,7 +330,7 @@ class Mapping: raise ValueError(f'The shortcut for {self.name} has no short_text') sc_text = f'{conf_name}.{self.short_text}' shortcut_slugs[f'{conf_name}.{self.name}'] = (sc_text, self.key_text.replace('kitty_mod', kitty_mod)) - a('.. shortcut:: ' + sc_text) + a(f'.. shortcut:: {sc_text}') block_started = False for sc in [self] + action_group: if sc.add_to_default and sc.documented: @@ -534,7 +534,7 @@ class Group: ans[i] = ' '.join(parts) if commented: - ans = [x if x.startswith('#') or not x.strip() else ('# ' + x) for x in ans] + ans = [x if x.startswith('#') or not x.strip() else (f'# {x}') for x in ans] return ans diff --git a/kitty/config.py b/kitty/config.py index 1df21c944..745e1c07d 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -54,7 +54,7 @@ def atomic_save(data: bytes, path: str) -> None: @contextmanager def cached_values_for(name: str) -> Generator[Dict[str, Any], None, None]: - cached_path = os.path.join(cache_dir(), name + '.json') + cached_path = os.path.join(cache_dir(), f'{name}.json') cached_values: Dict[str, Any] = {} try: with open(cached_path, 'rb') as f: diff --git a/kitty/fonts/core_text.py b/kitty/fonts/core_text.py index 6718fc0f2..b9e4735b4 100644 --- a/kitty/fonts/core_text.py +++ b/kitty/fonts/core_text.py @@ -29,7 +29,7 @@ def create_font_map(all_fonts: Iterable[CoreTextFont]) -> FontMap: ps = (x['postscript_name'] or '').lower() ans['family_map'].setdefault(f, []).append(x) ans['ps_map'].setdefault(ps, []).append(x) - ans['full_map'].setdefault(f + ' ' + s, []).append(x) + ans['full_map'].setdefault(f'{f} {s}', []).append(x) return ans @@ -45,7 +45,7 @@ def list_fonts() -> Generator[ListedFont, None, None]: for fd in coretext_all_fonts(): f = fd['family'] if f: - fn = (f + ' ' + (fd['style'] or '')).strip() + fn = f'{f} {fd.get("style", "")}'.strip() is_mono = bool(fd['monospace']) yield {'family': f, 'full_name': fn, 'postscript_name': fd['postscript_name'] or '', 'is_monospace': is_mono} diff --git a/kitty/fonts/fontconfig.py b/kitty/fonts/fontconfig.py index 763f8d333..01c3ba047 100644 --- a/kitty/fonts/fontconfig.py +++ b/kitty/fonts/fontconfig.py @@ -58,7 +58,7 @@ def list_fonts() -> Generator[ListedFont, None, None]: if fn_: fn = str(fn_) else: - fn = (f + ' ' + str(fd.get('style', ''))).strip() + fn = f'{f} {fd.get("style", "")}'.strip() is_mono = fd.get('spacing') in ('MONO', 'DUAL') yield {'family': f, 'full_name': fn, 'postscript_name': str(fd.get('postscript_name', '')), 'is_monospace': is_mono} diff --git a/kitty/fonts/list.py b/kitty/fonts/list.py index 7cbc65209..e56343823 100644 --- a/kitty/fonts/list.py +++ b/kitty/fonts/list.py @@ -28,13 +28,13 @@ def main(argv: Sequence[str]) -> None: groups = create_family_groups() for k in sorted(groups, key=lambda x: x.lower()): if isatty: - print('\033[1;32m' + k + '\033[m') + print(f'\033[1;32m{k}\033[m') else: print(k) for f in sorted(groups[k], key=lambda x: x['full_name'].lower()): p = f['full_name'] if isatty: - p = '\033[3m' + p + '\033[m' + p = f'\033[3m{p}\033[m' if psnames: p += ' ({})'.format(f['postscript_name']) print(' ', p) diff --git a/kitty/fonts/render.py b/kitty/fonts/render.py index 500acb950..e617897a2 100644 --- a/kitty/fonts/render.py +++ b/kitty/fonts/render.py @@ -515,7 +515,7 @@ def test_fallback_font(qtext: Optional[str] = None, bold: bool = False, italic: try: print(text, f) except UnicodeEncodeError: - sys.stdout.buffer.write((text + ' %s\n' % f).encode('utf-8')) + sys.stdout.buffer.write(f'{text} {f}\n'.encode('utf-8')) def showcase() -> None: diff --git a/kitty/guess_mime_type.py b/kitty/guess_mime_type.py index cc03e8b6c..e392cacf8 100644 --- a/kitty/guess_mime_type.py +++ b/kitty/guess_mime_type.py @@ -58,7 +58,7 @@ def guess_type(path: str, allow_filesystem_access: bool = False) -> Optional[str ext = path.rpartition('.')[-1].lower() mt = known_extensions.get(ext) if mt in text_mimes: - mt = 'text/' + mt.split('/', 1)[-1] + mt = f'text/{mt.split("/", 1)[-1]}' if not mt and is_rc_file(path): mt = 'text/plain' if not mt and is_folder(path): diff --git a/kitty/key_encoding.c b/kitty/key_encoding.c index b0a7825e6..b132905e8 100644 --- a/kitty/key_encoding.c +++ b/kitty/key_encoding.c @@ -219,7 +219,6 @@ encode_function_key(const KeyEvent *ev, char *output) { case GLFW_FKEY_PAGE_UP: S(5, '~'); case GLFW_FKEY_PAGE_DOWN: S(6, '~'); case GLFW_FKEY_HOME: S(1, 'H'); - case GLFW_FKEY_KP_BEGIN: S(1, 'E'); case GLFW_FKEY_END: S(1, 'F'); case GLFW_FKEY_F1: S(1, 'P'); case GLFW_FKEY_F2: S(1, 'Q'); @@ -233,6 +232,7 @@ encode_function_key(const KeyEvent *ev, char *output) { case GLFW_FKEY_F10: S(21, '~'); case GLFW_FKEY_F11: S(23, '~'); case GLFW_FKEY_F12: S(24, '~'); + case GLFW_FKEY_KP_BEGIN: S(1, 'E'); /* end special numbers */ case GLFW_FKEY_MENU: // use the same encoding as xterm for this key in legacy mode (F16) diff --git a/kitty/key_encoding.py b/kitty/key_encoding.py index 02f1d38c7..49ab1ad58 100644 --- a/kitty/key_encoding.py +++ b/kitty/key_encoding.py @@ -181,7 +181,7 @@ class EventType(IntEnum): @lru_cache(maxsize=128) def parse_shortcut(spec: str) -> ParsedShortcut: if spec.endswith('+'): - spec = spec[:-1] + 'plus' + spec = f'{spec[:-1]}plus' parts = spec.split('+') key_name = parts[-1] key_name = functional_key_name_aliases.get(key_name.upper(), key_name) diff --git a/kitty/key_names.py b/kitty/key_names.py index 35e639193..edda8b252 100644 --- a/kitty/key_names.py +++ b/kitty/key_names.py @@ -63,7 +63,7 @@ else: import ctypes for suffix in ('.0', ''): with suppress(Exception): - lib = ctypes.CDLL('libxkbcommon.so' + suffix) + lib = ctypes.CDLL(f'libxkbcommon.so{suffix}') break else: from ctypes.util import find_library diff --git a/kitty/launch.py b/kitty/launch.py index 33365025b..f8b4ee932 100644 --- a/kitty/launch.py +++ b/kitty/launch.py @@ -369,7 +369,7 @@ def launch( if opts.stdin_add_formatting: if q in ('@screen', '@screen_scrollback', '@alternate', '@alternate_scrollback', '@first_cmd_output_on_screen', '@last_cmd_output', '@last_visited_cmd_output'): - q = '@ansi_' + q[1:] + q = f'@ansi_{q[1:]}' if opts.stdin_add_line_wrap_markers: q += '_wrap' penv, stdin = boss.process_stdin_source(window=active, stdin=q, copy_pipe_data=pipe_data) diff --git a/kitty/layout/base.py b/kitty/layout/base.py index 1843c6ae2..9310248bb 100644 --- a/kitty/layout/base.py +++ b/kitty/layout/base.py @@ -217,7 +217,7 @@ class Layout: self.blank_rects: List[Rect] = [] self.layout_opts = self.parse_layout_opts(layout_opts) assert self.name is not None - self.full_name = self.name + ((':' + layout_opts) if layout_opts else '') + self.full_name = f'{self.name}:{layout_opts}' if layout_opts else self.name self.remove_all_biases() def bias_increment_for_cell(self, is_horizontal: bool) -> float: diff --git a/kitty/main.py b/kitty/main.py index 458bb455e..6a1ba10fa 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -44,7 +44,7 @@ def set_custom_ibeam_cursor() -> None: data = f.read() rgba_data, width, height = load_png_data(data) c2x = os.path.splitext(beam_cursor_data_file) - with open(c2x[0] + '@2x' + c2x[1], 'rb') as f: + with open(f'{c2x[0]}@2x{c2x[1]}', 'rb') as f: data = f.read() rgba_data2, width2, height2 = load_png_data(data) images = (rgba_data, width, height), (rgba_data2, width2, height2) @@ -138,7 +138,7 @@ def get_macos_shortcut_for( def set_x11_window_icon() -> None: # max icon size on X11 64bits is 128x128 path, ext = os.path.splitext(logo_png_file) - set_default_window_icon(path + '-128' + ext) + set_default_window_icon(f'{path}-128{ext}') def _run_app(opts: Options, args: CLIOptions, bad_lines: Sequence[BadLine] = ()) -> None: @@ -220,7 +220,7 @@ def ensure_macos_locale() -> None: lang = 'en_US' else: log_error(f'Could not set LANG Cocoa returns language as: {lang}') - os.environ['LANG'] = lang + '.UTF-8' + os.environ['LANG'] = f'{lang}.UTF-8' @contextmanager diff --git a/kitty/notify.py b/kitty/notify.py index 2ed16bae4..00dfff5a6 100644 --- a/kitty/notify.py +++ b/kitty/notify.py @@ -113,7 +113,7 @@ def parse_osc_99(raw: str) -> NotificationCommand: elif k == 'd': cmd.done = v != '0' elif k == 'a': - cmd.actions += ',' + v + cmd.actions += f',{v}' if payload_type not in ('body', 'title'): log_error(f'Malformed OSC 99: unknown payload type: {payload_type}') return NotificationCommand() @@ -139,7 +139,7 @@ def limit_size(x: str) -> str: def merge_osc_99(prev: NotificationCommand, cmd: NotificationCommand) -> NotificationCommand: if prev.done or prev.identifier != cmd.identifier: return cmd - cmd.actions = limit_size(prev.actions + ',' + cmd.actions) + cmd.actions = limit_size(f'{prev.actions},{cmd.actions}') cmd.title = limit_size(prev.title + cmd.title) cmd.body = limit_size(prev.body + cmd.body) return cmd @@ -198,7 +198,7 @@ def notify_with_command(cmd: NotificationCommand, window_id: int, notify_impleme title = cmd.title or cmd.body body = cmd.body if cmd.title else '' if title: - identifier = 'i' + str(next(id_counter)) + identifier = f'i{next(id_counter)}' notify_implementation(title, body, identifier) register_identifier(identifier, cmd, window_id) diff --git a/kitty/open_actions.py b/kitty/open_actions.py index b4bf34698..5009b81da 100644 --- a/kitty/open_actions.py +++ b/kitty/open_actions.py @@ -114,7 +114,7 @@ def url_matches_criterion(purl: 'ParseResult', url: str, unquoted_path: str, mc: path = unquoted_path.lower() for ext in mc.value.split(','): ext = ext.strip() - if path.endswith('.' + ext): + if path.endswith(f'.{ext}'): return True return False diff --git a/kitty/options/utils.py b/kitty/options/utils.py index 1a735b62d..1e90097a7 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -379,7 +379,7 @@ def parse_mods(parts: Iterable[str], sc: str) -> Optional[int]: mods = 0 for m in parts: try: - mods |= getattr(defines, 'GLFW_MOD_' + map_mod(m.upper())) + mods |= getattr(defines, f'GLFW_MOD_{map_mod(m.upper())}') except AttributeError: if m.upper() != 'NONE': log_error(f'Shortcut: {sc} has unknown modifier, ignoring') @@ -394,7 +394,7 @@ def to_modifiers(val: str) -> int: def parse_shortcut(sc: str) -> SingleKey: if sc.endswith('+') and len(sc) > 1: - sc = sc[:-1] + 'plus' + sc = f'{sc[:-1]}plus' parts = sc.split('+') mods = 0 if len(parts) > 1: @@ -895,13 +895,13 @@ def resolve_aliases_and_parse_actions( parts = rest.split(maxsplit=1) if parts[0] != alias.name: continue - new_defn = possible_alias + ' ' + alias.value + ((' ' + parts[1]) if len(parts) > 1 else '') + new_defn = f'{possible_alias} {alias.value} {f" {parts[1]}" if len(parts) > 1 else ""}' new_aliases = aliases.copy() new_aliases[possible_alias] = [a for a in aliases[possible_alias] if a is not alias] yield from resolve_aliases_and_parse_actions(new_defn, new_aliases, map_type) return else: # action_alias - new_defn = alias.value + ((' ' + rest) if rest else '') + new_defn = f'{alias.value} {rest}' if rest else alias.value new_aliases = aliases.copy() new_aliases.pop(possible_alias) yield from resolve_aliases_and_parse_actions(new_defn, new_aliases, map_type) @@ -909,7 +909,7 @@ def resolve_aliases_and_parse_actions( if possible_alias == 'combine': sep, rest = rest.split(maxsplit=1) - parts = re.split(r'\s*' + re.escape(sep) + r'\s*', rest) + parts = re.split(fr'\s*{re.escape(sep)}\s*', rest) for x in parts: if x: yield from resolve_aliases_and_parse_actions(x, aliases, map_type) diff --git a/kitty/parse-graphics-command.h b/kitty/parse-graphics-command.h index e602d676f..025055ea8 100644 --- a/kitty/parse-graphics-command.h +++ b/kitty/parse-graphics-command.h @@ -1,5 +1,4 @@ -// This file is generated by /home/kovid/work/kitty/./gen-apc-parsers.py do not -// edit! +// This file is generated by gen-apc-parsers.py do not edit! #pragma once @@ -148,9 +147,9 @@ static inline void parse_graphics_code(Screen *screen, case action: { g.action = screen->parser_buf[pos++] & 0xff; - if (g.action != 'q' && g.action != 'p' && g.action != 't' && - g.action != 'd' && g.action != 'c' && g.action != 'a' && - g.action != 'T' && g.action != 'f') { + if (g.action != 'T' && g.action != 'a' && g.action != 'c' && + g.action != 'd' && g.action != 'f' && g.action != 'p' && + g.action != 'q' && g.action != 't') { REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag " "value for action: 0x%x", g.action); @@ -160,16 +159,16 @@ static inline void parse_graphics_code(Screen *screen, case delete_action: { g.delete_action = screen->parser_buf[pos++] & 0xff; - if (g.delete_action != 'q' && g.delete_action != 'Q' && - g.delete_action != 'c' && g.delete_action != 'C' && - g.delete_action != 'N' && g.delete_action != 'i' && - g.delete_action != 'A' && g.delete_action != 'y' && - g.delete_action != 'a' && g.delete_action != 'I' && - g.delete_action != 'F' && g.delete_action != 'p' && - g.delete_action != 'z' && g.delete_action != 'x' && - g.delete_action != 'n' && g.delete_action != 'X' && - g.delete_action != 'Y' && g.delete_action != 'P' && - g.delete_action != 'Z' && g.delete_action != 'f') { + if (g.delete_action != 'A' && g.delete_action != 'C' && + g.delete_action != 'F' && g.delete_action != 'I' && + g.delete_action != 'N' && g.delete_action != 'P' && + g.delete_action != 'Q' && g.delete_action != 'X' && + g.delete_action != 'Y' && g.delete_action != 'Z' && + g.delete_action != 'a' && g.delete_action != 'c' && + g.delete_action != 'f' && g.delete_action != 'i' && + g.delete_action != 'n' && g.delete_action != 'p' && + g.delete_action != 'q' && g.delete_action != 'x' && + g.delete_action != 'y' && g.delete_action != 'z') { REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag " "value for delete_action: 0x%x", g.delete_action); @@ -179,8 +178,8 @@ static inline void parse_graphics_code(Screen *screen, case transmission_type: { g.transmission_type = screen->parser_buf[pos++] & 0xff; - if (g.transmission_type != 's' && g.transmission_type != 't' && - g.transmission_type != 'd' && g.transmission_type != 'f') { + if (g.transmission_type != 'd' && g.transmission_type != 'f' && + g.transmission_type != 's' && g.transmission_type != 't') { REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag " "value for transmission_type: 0x%x", g.transmission_type); diff --git a/kitty/rc/send_text.py b/kitty/rc/send_text.py index 1a658029c..8c623c197 100644 --- a/kitty/rc/send_text.py +++ b/kitty/rc/send_text.py @@ -107,20 +107,20 @@ Do not send text to the active window, even if it is one of the matched windows. if '\x04' in decoded_data: decoded_data = decoded_data[:decoded_data.index('\x04')] keep_going = False - ret['data'] = 'text:' + decoded_data + ret['data'] = f'text:{decoded_data}' yield ret else: while True: data = sys.stdin.buffer.read(limit) if not data: break - ret['data'] = 'base64:' + base64.standard_b64encode(data).decode('ascii') + ret['data'] = f'base64:{base64.standard_b64encode(data).decode("ascii")}' yield ret def chunks(text: str) -> CmdGenerator: data = parse_send_text_bytes(text).decode('utf-8') while data: - ret['data'] = 'text:' + data[:limit] + ret['data'] = f'text:{data[:limit]}' yield ret data = data[limit:] @@ -130,7 +130,7 @@ Do not send text to the active window, even if it is one of the matched windows. data = f.read(limit) if not data: break - ret['data'] = 'base64:' + base64.standard_b64encode(data).decode('ascii') + ret['data'] = f'base64:{base64.standard_b64encode(data).decode("ascii")}' yield ret sources = [] diff --git a/kitty/rgb.py b/kitty/rgb.py index ff0e9b3e6..3f81c1950 100644 --- a/kitty/rgb.py +++ b/kitty/rgb.py @@ -28,7 +28,7 @@ def parse_single_color(c: str) -> int: def parse_sharp(spec: str) -> Optional[Color]: if len(spec) in (3, 6, 9, 12): part_len = len(spec) // 3 - colors = re.findall(r'[a-fA-F0-9]{%d}' % part_len, spec) + colors = re.findall(fr'[a-fA-F0-9]{{{part_len}}}', spec) return Color(*map(parse_single_color, colors)) return None diff --git a/kitty/shell.py b/kitty/shell.py index 639837647..6bbedd732 100644 --- a/kitty/shell.py +++ b/kitty/shell.py @@ -221,7 +221,7 @@ def real_main(global_opts: RCOptions) -> None: if e.code != 0: print(end=output_prefix, flush=True) print_err(e) - print_err('Use "{}" to see how to use this command.'.format(emph('help ' + cmd))) + print_err('Use "{}" to see how to use this command.'.format(emph(f'help {cmd}'))) continue except Exception: print(end=output_prefix, flush=True) diff --git a/kitty/tab_bar.py b/kitty/tab_bar.py index 686a4356f..327dc3bcd 100644 --- a/kitty/tab_bar.py +++ b/kitty/tab_bar.py @@ -102,14 +102,14 @@ class ColorFormatter: ans = '9' elif q == 'tab': col = color_from_int((self.draw_data.tab_bg if self.which == '4' else self.draw_data.tab_fg)(self.tab_data)) - ans = '8' + color_as_sgr(col) + ans = f'8{color_as_sgr(col)}' else: if name.startswith('_'): - q = '#' + name[1:] + q = f'#{name[1:]}' c = to_color(q) if c is None: raise AttributeError(f'{name} is not a valid color') - ans = '8' + color_as_sgr(c) + ans = f'8{color_as_sgr(c)}' return f'\x1b[{self.which}{ans}m' diff --git a/kitty/terminfo.py b/kitty/terminfo.py index c487a8524..f14744928 100644 --- a/kitty/terminfo.py +++ b/kitty/terminfo.py @@ -471,8 +471,8 @@ def get_capabilities(query_string: str, opts: 'Options') -> Generator[str, None, def result(encoded_query_name: str, x: Optional[str] = None) -> str: if x is None: - return '0+r' + encoded_query_name - return '1+r' + encoded_query_name + '=' + hexlify(str(x).encode('utf-8')).decode('ascii') + return f'0+r{encoded_query_name}' + return f'1+r{encoded_query_name}={hexlify(str(x).encode("utf-8")).decode("ascii")}' for encoded_query_name in query_string.split(';'): name = qname = unhexlify(encoded_query_name).decode('utf-8') diff --git a/publish.py b/publish.py index 063862c14..08dd3aedb 100755 --- a/publish.py +++ b/publish.py @@ -40,7 +40,7 @@ def echo_cmd(cmd: Iterable[str]) -> None: isatty = sys.stdout.isatty() end = '\n' if isatty: - end = '\x1b[m' + end + end = f'\x1b[m{end}' print('\x1b[92m', end='') print(shlex.join(cmd), end=end, flush=True) @@ -146,11 +146,11 @@ def run_website(args: Any) -> None: def sign_file(path: str) -> None: - dest = path + '.sig' + dest = f'{path}.sig' with suppress(FileNotFoundError): os.remove(dest) subprocess.check_call([ - os.environ['PENV'] + '/gpg-as-kovid', '--output', path + '.sig', + os.environ['PENV'] + '/gpg-as-kovid', '--output', f'{path}.sig', '--detach-sig', path ]) @@ -159,7 +159,7 @@ def run_sdist(args: Any) -> None: with tempfile.TemporaryDirectory() as tdir: base = os.path.join(tdir, f'kitty-{version}') os.mkdir(base) - subprocess.check_call('git archive HEAD | tar -x -C ' + base, shell=True) + subprocess.check_call(f'git archive HEAD | tar -x -C {base}', shell=True) dest = os.path.join(base, 'docs', '_build') os.mkdir(dest) for x in 'html man'.split(): @@ -167,9 +167,9 @@ def run_sdist(args: Any) -> None: dest = os.path.abspath(os.path.join('build', f'kitty-{version}.tar')) subprocess.check_call(['tar', '-cf', dest, os.path.basename(base)], cwd=tdir) with suppress(FileNotFoundError): - os.remove(dest + '.xz') + os.remove(f'{dest}.xz') subprocess.check_call(['xz', '-9', dest]) - sign_file(dest + '.xz') + sign_file(f'{dest}.xz') class ReadFileWithProgressReporting(io.FileIO): # {{{ @@ -231,7 +231,7 @@ class Base: # {{{ class GitHub(Base): # {{{ - API = 'https://api.github.com/' + API = 'https://api.github.com' def __init__( self, @@ -244,12 +244,12 @@ class GitHub(Base): # {{{ ): self.files, self.reponame, self.version, self.username, self.password, self.replace = ( files, reponame, version, username, password, replace) - self.current_tag_name = self.version if self.version == 'nightly' else ('v' + self.version) + self.current_tag_name = self.version if self.version == 'nightly' else f'v{self.version}' self.is_nightly = self.current_tag_name == 'nightly' self.requests = s = requests.Session() s.auth = (self.username, self.password) s.headers.update({'Accept': 'application/vnd.github.v3+json'}) - self.url_base = f'{self.API}repos/{self.username}/{self.reponame}/releases/' + self.url_base = f'{self.API}/repos/{self.username}/{self.reponame}/releases' def patch(self, url: str, fail_msg: str, **data: Any) -> None: rdata = json.dumps(data) @@ -262,7 +262,7 @@ class GitHub(Base): # {{{ self.fail(r, fail_msg) def update_nightly_description(self, release_id: int) -> None: - url = self.url_base + str(release_id) + url = f'{self.url_base}/{release_id}' now = str(datetime.datetime.utcnow()).split('.')[0] + ' UTC' with open('.git/refs/heads/master') as f: commit = f.read().strip() @@ -276,7 +276,7 @@ class GitHub(Base): # {{{ # self.clean_older_releases(releases) release = self.create_release() upload_url = release['upload_url'].partition('{')[0] - asset_url = self.url_base + 'assets/{}' + asset_url = f'{self.url_base}/assets/{{}}' existing_assets = self.existing_assets(release['id']) if self.is_nightly: for fname in existing_assets: @@ -308,7 +308,7 @@ class GitHub(Base): # {{{ self.info(f'\nDeleting old released installers from: {release["tag_name"]}') for asset in release['assets']: r = self.requests.delete( - f'{self.API}repos/{self.username}/{self.reponame}/releases/assets/{asset["id"]}') + f'{self.url_base}/assets/{asset["id"]}') if r.status_code != 204: self.fail(r, f'Failed to delete obsolete asset: {asset["name"]} for release: {release["tag_name"]}') @@ -336,7 +336,7 @@ class GitHub(Base): # {{{ return bool(error_code == 'already_exists') def existing_assets(self, release_id: str) -> Dict[str, str]: - url = f'{self.API}repos/{self.username}/{self.reponame}/releases/{release_id}/assets' + url = f'{self.url_base}/{release_id}/assets' r = self.requests.get(url) if r.status_code != 200: self.fail(r, 'Failed to get assets for release') @@ -345,15 +345,14 @@ class GitHub(Base): # {{{ def create_release(self) -> Dict[str, Any]: ' Create a release on GitHub or if it already exists, return the existing release ' # Check for existing release - url = f'{self.API}repos/{self.username}/{self.reponame}/releases/tags/{self.current_tag_name}' + url = f'{self.url_base}/tags/{self.current_tag_name}' r = self.requests.get(url) if r.status_code == 200: return dict(r.json()) if self.is_nightly: raise SystemExit('No existing nightly release found on GitHub') - url = f'{self.API}repos/{self.username}/{self.reponame}/releases' r = self.requests.post( - url, + self.url_base, data=json.dumps({ 'tag_name': self.current_tag_name, 'target_commitish': 'master', @@ -394,7 +393,7 @@ def files_for_upload() -> Dict[str, str]: files[f'build/kitty-{version}.tar.xz.sig'] = 'Source code GPG signature' for path, desc in signatures.items(): sign_file(path) - files[path + '.sig'] = desc + files[f'{path}.sig'] = desc for f in files: if not os.path.exists(f): raise SystemExit(f'The release artifact {f} does not exist') @@ -460,7 +459,7 @@ def exec_actions(actions: Iterable[str], args: Any) -> None: for action in actions: print('Running', action) cwd = os.getcwd() - globals()['run_' + action](args) + globals()[f'run_{action}'](args) os.chdir(cwd) diff --git a/setup.py b/setup.py index e5678aec6..c79b7985f 100755 --- a/setup.py +++ b/setup.py @@ -710,7 +710,7 @@ def compile_c_extension( def on_success() -> None: os.rename(dest, real_dest) - compilation_database.add_command(desc, cmd, partial(newer, real_dest, *objects), on_success=on_success, key=CompileKey('', module + '.so')) + compilation_database.add_command(desc, cmd, partial(newer, real_dest, *objects), on_success=on_success, key=CompileKey('', f'{module}.so')) def find_c_files() -> Tuple[List[str], List[str]]: @@ -1112,7 +1112,7 @@ def create_macos_app_icon(where: str = 'Resources') -> None: 'iconutil', '-c', 'icns', iconset_dir, '-o', icns_dir ]) except FileNotFoundError: - print(error('iconutil not found') + ', using png2icns (without retina support) to convert the logo', file=sys.stderr) + print(f'{error("iconutil not found")}, using png2icns (without retina support) to convert the logo', file=sys.stderr) subprocess.check_call([ 'png2icns', icns_dir ] + [os.path.join(iconset_dir, logo) for logo in [