diff --git a/colorschemes/main.py b/colorschemes/main.py index 11e34ee..1c236e4 100755 --- a/colorschemes/main.py +++ b/colorschemes/main.py @@ -3,8 +3,7 @@ import json import os from abc import abstractmethod -from typing import Dict, Iterable, List, Protocol, TextIO, runtime_checkable - +from typing import Dict, Iterator, List, Protocol, TextIO, runtime_checkable __dir__ = os.path.dirname(__file__) @@ -12,16 +11,20 @@ __dir__ = os.path.dirname(__file__) class Color: def __init__(self, r: int, g: int, b: int) -> None: - assert 0 <= r <= 0xff - assert 0 <= g <= 0xff - assert 0 <= b <= 0xff + if not (0 <= r <= 0xff): + raise Exception("r component out of range") + if not (0 <= g <= 0xff): + raise Exception("g component out of range") + if not (0 <= b <= 0xff): + raise Exception("b component out of range") self.r = r self.g = g self.b = b @classmethod def from_hex(cls, s: str) -> "Color": - assert len(s) == 6 + if len(s) != 6: + raise Exception("hex color string must be 6 characters long") return Color(int(s[0:2], 16), int(s[2:4], 16), int(s[4:6], 16)) @property @@ -42,7 +45,7 @@ class Color: else: raise IndexError("color component index out of range") - def __iter__(self) -> Iterable[int]: + def __iter__(self) -> Iterator[int]: yield self.r yield self.g yield self.b @@ -296,20 +299,21 @@ class ThemeGeneratorXfceTerminal(ThemeGenerator): class ThemeGeneratorVscode(ThemeGenerator): + ANSI_COLOR_NAMES = [ + "Black", + "Red", + "Green", + "Yellow", + "Blue", + "Magenta", + "Cyan", + "White", + ] + def file_name(self) -> str: return "vscode-colorCustomizations.json" def generate(self, theme: Theme, output: TextIO) -> None: - ANSI_COLOR_NAMES = [ - "Black", - "Red", - "Green", - "Yellow", - "Blue", - "Magenta", - "Cyan", - "White", - ] colors: Dict[str, str] = { "terminal.background": theme.bg.css_hex, @@ -320,8 +324,8 @@ class ThemeGeneratorVscode(ThemeGenerator): } for is_bright in [False, True]: - for color_index, color_name in enumerate(ANSI_COLOR_NAMES): - color = theme.ansi_colors[color_index + int(is_bright) * len(ANSI_COLOR_NAMES)] + for color_index, color_name in enumerate(self.ANSI_COLOR_NAMES): + color = theme.ansi_colors[color_index + int(is_bright) * len(self.ANSI_COLOR_NAMES)] colors["terminal.ansi" + ("Bright" if is_bright else "") + color_name] = color.css_hex json.dump(colors, output, ensure_ascii=False, indent=2) @@ -341,7 +345,7 @@ class ThemeGeneratorIterm(ThemeGenerator): output.write('\n') output.write("\n") - def write_color(key_name, color): + def write_color(key_name: str, color: Color) -> None: r, g, b = (float(component) / 0xff for component in color) output.write(" {} Color\n".format(key_name)) output.write(" \n") diff --git a/pyrightconfig.json b/pyrightconfig.json index 741e0a1..4867c0b 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -3,6 +3,10 @@ { "root": "scripts", "extraPaths": ["script-resources"] + }, + { + "root": "script-resources/welcome", + "extraPaths": ["script-resources/welcome"] } ] } diff --git a/python/flake8.ini b/python/flake8.ini index 83c9332..041fdb7 100644 --- a/python/flake8.ini +++ b/python/flake8.ini @@ -1,4 +1,27 @@ [flake8] + +select = + # + E W + # + F + # + Q0 + # + ANN + # + N8 + # + I0 + # + C8 + # + S + + # Also see this: + # + # + ignore = # Indent is not a multiple of 4 E111 @@ -13,8 +36,17 @@ ignore = # Line too long E501 # `except` without an exception type - E722 + # NOTE: write `except Exception` (or `except BaseException` if absolutely + # necessary) instead + # E722 # Newline before a binary operator W503 # Newline after a binary operator W504 + + # Missing type annotations for `self` and `cls` respectively + ANN101 ANN102 + +inline-quotes = " +multiline-quotes = " +docstring-quotes = " diff --git a/python/yapf.ini b/python/yapf.ini index e4ceea7..1fdac8a 100644 --- a/python/yapf.ini +++ b/python/yapf.ini @@ -3,7 +3,6 @@ based_on_style = google column_limit = 99 indent_width = 2 continuation_indent_width = 2 -blank_lines_between_top_level_imports_and_variables = 2 dedent_closing_brackets = true coalesce_brackets = true spaces_around_power_operator = true diff --git a/script-resources/common_script_utils.py b/script-resources/common_script_utils.py index 4d13e50..4065d99 100644 --- a/script-resources/common_script_utils.py +++ b/script-resources/common_script_utils.py @@ -1,6 +1,6 @@ -import sys import os import subprocess +import sys from pathlib import Path from typing import Iterable, NoReturn diff --git a/script-resources/factorio/property_tree.py b/script-resources/factorio/property_tree.py index 24f921c..a960c49 100644 --- a/script-resources/factorio/property_tree.py +++ b/script-resources/factorio/property_tree.py @@ -5,7 +5,7 @@ # import struct -from typing import Any, IO +from typing import IO, Any def read_bool(buf: IO[bytes]) -> bool: diff --git a/script-resources/pycalc_startup.py b/script-resources/pycalc_startup.py index 1ffb1b2..269a1af 100644 --- a/script-resources/pycalc_startup.py +++ b/script-resources/pycalc_startup.py @@ -2,7 +2,7 @@ from math import * from fractions import Fraction -def factors(n): +def factors(n: int) -> "set[int]": result = set() for i in range(1, int(sqrt(n)) + 1): if n % i == 0: @@ -11,7 +11,7 @@ def factors(n): return result -def solve_quadratic(a, b, c): +def solve_quadratic(a: int, b: int, c: int) -> None: if a == 0: raise Exception("not a quadratic equation") else: diff --git a/script-resources/welcome/colors.py b/script-resources/welcome/colors.py index a835612..7d4cb76 100644 --- a/script-resources/welcome/colors.py +++ b/script-resources/welcome/colors.py @@ -1,22 +1,25 @@ +from typing import List + from colorama import Fore, Style, ansi - -COLORS = [ansi.code_to_chars(30 + color_index) for color_index in range(0, 8)] +COLORS: List[str] = [ansi.code_to_chars(30 + color_index) for color_index in range(0, 8)] -def colored(string, *colors): +def colored(string: str, *colors: str) -> str: return "".join(colors + (string, Style.RESET_ALL)) -def bright_colored(string, *colors): +def bright_colored(string: str, *colors: str) -> str: return "".join(colors + (Style.BRIGHT, string, Style.RESET_ALL)) -def colorize_percent(percent, warning, critical, inverse=False): - COLORS = [Fore.GREEN, Fore.YELLOW, Fore.RED] +def colorize_percent( + percent: float, warning: float, critical: float, inverse: bool = False +) -> str: + colors = [Fore.GREEN, Fore.YELLOW, Fore.RED] color_index = 0 if percent < warning else 1 if percent < critical else 2 if inverse: color_index = 2 - color_index - return colored("%.2f%%" % percent, COLORS[color_index]) + return colored("%.2f%%" % percent, colors[color_index]) diff --git a/script-resources/welcome/humanize.py b/script-resources/welcome/humanize.py index 9631a9c..901de70 100644 --- a/script-resources/welcome/humanize.py +++ b/script-resources/welcome/humanize.py @@ -1,11 +1,15 @@ -def humanize_timedelta(timedelta): - result = [] +from datetime import timedelta +from typing import List, Tuple + + +def humanize_timedelta(timedelta: timedelta) -> str: + result: List[str] = [] days = timedelta.days mm, ss = divmod(timedelta.seconds, 60) hh, mm = divmod(mm, 60) - def plural(n): + def plural(n: int) -> Tuple[int, str]: return n, "s" if abs(n) != 1 else "" if days > 0: @@ -20,7 +24,7 @@ def humanize_timedelta(timedelta): return ", ".join(result) -def humanize_bytes(bytes): +def humanize_bytes(bytes: int) -> str: units = ["B", "kB", "MB", "GB"] factor = 1 diff --git a/script-resources/welcome/main.py b/script-resources/welcome/main.py index 6eb37f7..c6473c1 100755 --- a/script-resources/welcome/main.py +++ b/script-resources/welcome/main.py @@ -5,7 +5,6 @@ import re from colors import COLORS, Style from system_info import get_system_info - print("") logo_lines, info_lines = get_system_info() diff --git a/script-resources/welcome/system_info.py b/script-resources/welcome/system_info.py index 9d72ded..24cda1b 100644 --- a/script-resources/welcome/system_info.py +++ b/script-resources/welcome/system_info.py @@ -3,17 +3,17 @@ import platform import socket from datetime import datetime, timedelta from getpass import getuser +from typing import Dict, List, Optional, Tuple, cast import psutil - from colors import Fore, Style, bright_colored, colored, colorize_percent from humanize import humanize_bytes, humanize_timedelta -def get_system_info(): - info_lines = [] +def get_system_info() -> Tuple[List[str], List[str]]: + info_lines: List[str] = [] - def info(name, value, *format_args): + def info(name: str, value: str, *format_args) -> None: line = bright_colored(name + ":", Fore.YELLOW) + " " + value if format_args: line = line % format_args @@ -66,27 +66,27 @@ def get_system_info(): return logo_lines, info_lines -def _get_hostname(): +def _get_hostname() -> str: hostname = socket.gethostname() return hostname -def _get_uptime(): +def _get_uptime() -> timedelta: return datetime.now() - datetime.fromtimestamp(psutil.boot_time()) -def _get_users(): - users = {} +def _get_users() -> str: + users: Dict[str, List[str]] = {} for user in psutil.users(): - name = user.name - terminal = user.terminal + name: str = user.name + terminal: str = user.terminal if name in users: users[name].append(terminal) else: users[name] = [terminal] - result = [] + result: List[str] = [] for name in users: terminals = users[name] @@ -102,13 +102,13 @@ def _get_users(): return ", ".join(result) -def _get_shell(): +def _get_shell() -> Optional[str]: return os.environ.get("SHELL") -def _get_cpu_usage(): +def _get_cpu_usage() -> Optional[str]: try: - percent = psutil.cpu_percent() + percent = cast(float, psutil.cpu_percent()) except Exception as e: print("Error in _get_cpu_usage:", e) return None @@ -116,7 +116,7 @@ def _get_cpu_usage(): return colorize_percent(percent, warning=60, critical=80) -def _get_memory(): +def _get_memory() -> Tuple[str, str, str]: memory = psutil.virtual_memory() return ( humanize_bytes(memory.used), @@ -125,8 +125,8 @@ def _get_memory(): ) -def _get_disks(): - result = [] +def _get_disks() -> List[Tuple[str, str, str, str]]: + result: List[Tuple[str, str, str, str]] = [] for disk in psutil.disk_partitions(all=False): if psutil.WINDOWS and ("cdrom" in disk.opts or disk.fstype == ""): @@ -146,7 +146,7 @@ def _get_disks(): return result -def _get_battery(): +def _get_battery() -> Optional[Tuple[str, str]]: if not hasattr(psutil, "sensors_battery"): return None @@ -167,8 +167,8 @@ def _get_battery(): return colorize_percent(percent, critical=10, warning=20, inverse=True), status -def _get_local_ipv4_addresses(): - result = [] +def _get_local_ipv4_addresses() -> List[Tuple[str, str]]: + result: List[Tuple[str, str]] = [] for interface, addresses in psutil.net_if_addrs().items(): for address in addresses: @@ -184,7 +184,7 @@ def _get_local_ipv4_addresses(): return result -def _get_distro_info(): +def _get_distro_info() -> Tuple[str, str, str, str]: if psutil.WINDOWS: return "windows", platform.system(), platform.release(), "" elif psutil.OSX: @@ -194,9 +194,13 @@ def _get_distro_info(): sw_vers = plistlib.load(f) return "mac", sw_vers["ProductName"], sw_vers["ProductVersion"], "" elif _is_android(): - from subprocess import check_output + import subprocess - android_version = check_output(["getprop", "ro.build.version.release"]) + android_version = subprocess.run( + ["getprop", "ro.build.version.release"], + check=True, + stdout=subprocess.PIPE, + ).stdout return "android", "Android", android_version.decode().strip(), "" elif psutil.LINUX: import distro @@ -206,5 +210,5 @@ def _get_distro_info(): raise NotImplementedError("unsupported OS") -def _is_android(): +def _is_android() -> bool: return os.path.isdir("/system/app") and os.path.isdir("/system/priv-app") diff --git a/scripts/copy-crosscode-emoji-url b/scripts/copy-crosscode-emoji-url index 45c6935..a26016c 100755 --- a/scripts/copy-crosscode-emoji-url +++ b/scripts/copy-crosscode-emoji-url @@ -1,19 +1,17 @@ #!/usr/bin/env python3 -import sys -import os -from pathlib import Path -from configparser import ConfigParser import json -from typing import Any, Generator, Optional, Union +import os +import sys import urllib.parse import urllib.request - +from configparser import ConfigParser +from pathlib import Path +from typing import Any, Generator, Optional, Union sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", "script-resources")) import common_script_utils - DEFAULT_REGISTRY_DUMP_URL = "https://stronghold.crosscode.ru/~ccbot/emote-registry.json" if os.name == "posix": @@ -49,7 +47,8 @@ def emote_downloader_and_iterator() -> Generator[str, None, None]: with urllib.request.urlopen(registry_dump_url, timeout=10) as response: emote_registry_data = json.load(response) - assert emote_registry_data["version"] == 1 + if emote_registry_data["version"] != 1: + raise Exception("unsupported emote registry version") allow_nsfw = config.getboolean("default", "allow_nsfw", fallback=False) emotes = [emote for emote in emote_registry_data["list"] if emote["safe"] or allow_nsfw] diff --git a/scripts/crosscode-saved b/scripts/crosscode-saved index 8e64e33..adb4229 100755 --- a/scripts/crosscode-saved +++ b/scripts/crosscode-saved @@ -1,19 +1,19 @@ #!/usr/bin/env python3 -import base64 import argparse +import base64 +import sys from hashlib import md5 from typing import IO -from Crypto.Cipher import AES -from Crypto import Random -import sys +from Crypto import Random +from Crypto.Cipher import AES CC_ENCRYPTION_MARKER_BYTES = b"[-!_0_!-]" CC_ENCRYPTION_PASSPHRASE = b":_.NaN0" -def main(): +def main() -> None: parser = argparse.ArgumentParser() # NOTE: Empty help strings are necessary for subparsers to show up in help. subparsers = parser.add_subparsers(required=True, metavar="COMMAND") @@ -34,14 +34,15 @@ def main(): def cmd_pipe_decrypt(args: argparse.Namespace) -> None: input_file: IO[bytes] = ( - sys.stdin.buffer if args.input_file == "-" else open(args.input_file, 'rb') + sys.stdin.buffer if args.input_file == "-" else open(args.input_file, "rb") ) output_file: IO[bytes] = ( - sys.stdout.buffer if args.output_file == "-" else open(args.output_file, 'wb') + sys.stdout.buffer if args.output_file == "-" else open(args.output_file, "wb") ) encrypted = input_file.read() - assert encrypted.startswith(CC_ENCRYPTION_MARKER_BYTES) + if not encrypted.startswith(CC_ENCRYPTION_MARKER_BYTES): + raise Exception() encrypted = encrypted[len(CC_ENCRYPTION_MARKER_BYTES):] decrypted = CryptoJsBridge.decrypt(encrypted, CC_ENCRYPTION_PASSPHRASE) output_file.write(decrypted) @@ -49,10 +50,10 @@ def cmd_pipe_decrypt(args: argparse.Namespace) -> None: def cmd_pipe_encrypt(args: argparse.Namespace) -> None: input_file: IO[bytes] = ( - sys.stdin.buffer if args.input_file == "-" else open(args.input_file, 'rb') + sys.stdin.buffer if args.input_file == "-" else open(args.input_file, "rb") ) output_file: IO[bytes] = ( - sys.stdout.buffer if args.output_file == "-" else open(args.output_file, 'wb') + sys.stdout.buffer if args.output_file == "-" else open(args.output_file, "wb") ) decrypted = input_file.read() @@ -87,7 +88,8 @@ class CryptoJsBridge: """ Extended from . """ - assert len(salt) == cls.SALT_SIZE + if len(salt) != cls.SALT_SIZE: + raise Exception("invalid salt length") data += salt key = md5(data).digest() final_key = key @@ -114,7 +116,8 @@ class CryptoJsBridge: Equivalent to `CryptoJS.AES.decrypt(encrypted, passphrase).toString(CryptoJS.enc.Utf8)`. """ encrypted = base64.b64decode(encrypted) - assert encrypted.startswith(cls.SALTED_MARKER) + if not encrypted.startswith(cls.SALTED_MARKER): + raise Exception("expected salt marker") encrypted = encrypted[len(cls.SALTED_MARKER):] salt, ciphertext = encrypted[:cls.SALT_SIZE], encrypted[cls.SALT_SIZE:] key_iv = cls.bytes_to_key(passphrase, salt, cls.KEY_SIZE + cls.IV_SIZE) diff --git a/scripts/discord-snowflake b/scripts/discord-snowflake index 85343ba..42bb7ac 100755 --- a/scripts/discord-snowflake +++ b/scripts/discord-snowflake @@ -3,16 +3,16 @@ # https://discord.com/developers/docs/reference#snowflakes import sys -import colorama import time +import colorama DISCORD_EPOCH = 1420070400000 # milliseconds user_snowflake = int(sys.argv[1]) -def print_field(name, value): +def print_field(name: str, value: object) -> None: print( "{}{}:{} {}".format(colorama.Style.BRIGHT, name.rjust(21), colorama.Style.RESET_ALL, value) ) diff --git a/scripts/discord-stream-desktop-audio b/scripts/discord-stream-desktop-audio index da925b4..c37e1e8 100755 --- a/scripts/discord-stream-desktop-audio +++ b/scripts/discord-stream-desktop-audio @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -import discord -import sys import os +import sys +from typing import Optional, cast +import discord guild_id = int(sys.argv[1]) voice_channel_id = int(sys.argv[2]) @@ -16,17 +17,17 @@ bot = discord.Client() @bot.event -async def on_ready(): +async def on_ready() -> None: print("logged in as {0} ({0.id})".format(bot.user)) - guild: discord.Guild = bot.get_guild(guild_id) + guild: Optional[discord.Guild] = bot.get_guild(guild_id) if guild is None: raise Exception("guild not found") - voice_channel: discord.VoiceChannel = guild.get_channel(voice_channel_id) + voice_channel: Optional[discord.VoiceChannel] = guild.get_channel(voice_channel_id) if voice_channel is None: raise Exception("channel not found") - voice_client = await voice_channel.connect() + voice_client = cast(discord.voice_client.VoiceClient, await voice_channel.connect()) print("connected to {0} ({0.id}) in {1} ({1.id})".format(voice_channel, guild)) source = discord.FFmpegPCMAudio(pulseaudio_device, before_options="-f pulse") diff --git a/scripts/discord-whois b/scripts/discord-whois index 41403ee..c8b3b3d 100755 --- a/scripts/discord-whois +++ b/scripts/discord-whois @@ -4,15 +4,16 @@ # # -import sys -import os -import urllib.request -import urllib.error -import colorama -import time import argparse import json +import os +import sys +import time +import urllib.error +import urllib.request +from typing import Dict, List, Optional +import colorama DISCORD_EPOCH = 1420070400000 # milliseconds # https://discord.com/developers/docs/resources/user#user-object-user-flags @@ -37,17 +38,17 @@ parser.add_argument("user_snowflake", type=int) parser.add_argument("--bot-token", type=str) parser.add_argument("--image-size", type=int) parser.add_argument("--get-prop", type=str) -parser.add_argument("--api-response", action='store_true') +parser.add_argument("--api-response", action="store_true") cli_args = parser.parse_args() -user_snowflake = cli_args.user_snowflake +user_snowflake: int = cli_args.user_snowflake -bot_token = cli_args.bot_token +bot_token: Optional[str] = cli_args.bot_token if bot_token is None: with open(os.path.expanduser("~/.config/dotfiles/discord-tools-bot-token.txt")) as f: bot_token = f.read().strip() -image_size = cli_args.image_size +image_size: Optional[int] = cli_args.image_size if not (image_size is None or (image_size > 0 and image_size & (image_size - 1)) == 0): parser.error("image_size must be greater than zero and a power of two") @@ -70,10 +71,10 @@ except urllib.error.HTTPError as err: if cli_args.api_response: json.dump(raw_data, sys.stdout, ensure_ascii=False, indent=2) - sys.stdout.write('\n') + sys.stdout.write("\n") sys.exit() -data = {} +data: Dict[str, str] = {} data["ID"] = raw_data["id"] data["Name"] = "{}#{}".format(raw_data["username"], raw_data["discriminator"]) @@ -108,7 +109,7 @@ user_flags = raw_data["public_flags"] if user_flags == 0: data["Flags"] = "" else: - user_flag_names = [] + user_flag_names: List[str] = [] for flag_name, bitmask in DISCORD_FLAGS.items(): if user_flags & bitmask: user_flag_names.append(flag_name) diff --git a/scripts/factorio-dump-mod-settings b/scripts/factorio-dump-mod-settings index 8530465..b43446f 100755 --- a/scripts/factorio-dump-mod-settings +++ b/scripts/factorio-dump-mod-settings @@ -4,12 +4,11 @@ # # -import sys -import os -from pathlib import Path -import struct import json - +import os +import struct +import sys +from pathlib import Path sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", "script-resources")) import factorio.property_tree @@ -23,7 +22,8 @@ with open(Path.home() / ".factorio" / "mods" / "mod-settings.dat", "rb") as f: version_main, version_major, version_minor, version_developer = struct.unpack(" Union[str, list[int]]: elif encoding == "base85": return base64.b85encode(b).decode("ascii") else: - assert False + raise Exception("unreachable") key_encoding: str = cli_args.key_encoding or cli_args.encoding diff --git a/scripts/mark-as-recently-used b/scripts/mark-as-recently-used index c35e763..f151604 100755 --- a/scripts/mark-as-recently-used +++ b/scripts/mark-as-recently-used @@ -1,13 +1,12 @@ #!/usr/bin/env python3 # Taken from -import gi import sys +import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gio, GLib - +from gi.repository import Gio, GLib, Gtk rec_mgr = Gtk.RecentManager.get_default() for arg in sys.argv[1:]: diff --git a/scripts/mediawiki-preview b/scripts/mediawiki-preview index b2d978b..ed8e05a 100755 --- a/scripts/mediawiki-preview +++ b/scripts/mediawiki-preview @@ -39,12 +39,13 @@ # created by this script. import argparse -import mwclient -import json -from urllib.parse import urlencode import html +import json import re +from typing import Dict, List, cast +from urllib.parse import urlencode +import mwclient LANG = "en" LANG_TEXT_DIRECTION = "ltr" @@ -116,7 +117,7 @@ MODULES_PRELOAD_SCRIPTS = { # ported from -def escape_css_class(class_str): +def escape_css_class(class_str: str) -> str: class_str = re.sub( r"""(^[0-9\-])|[\x00-\x20!"#$%&'()*+,.\/:;<=>?@[\]^`{|}~]|\xA0""", "_", @@ -127,8 +128,8 @@ def escape_css_class(class_str): return class_str -def json_dumps_compact(data): - return json.dumps(data, indent=None, separators=(",", ":")) +def json_dumps_compact(data: object) -> str: + return json.dumps(data, indent=None, separators=(",", ":"), ensure_ascii=False) parser = argparse.ArgumentParser() @@ -147,7 +148,7 @@ cli_args = parser.parse_args() site = mwclient.Site(cli_args.site, scheme=cli_args.scheme) -def get_load_script_url(**args): +def get_load_script_url(**args: object) -> str: return "{path}load{ext}?{args}".format( path=site.path, ext=site.ext, @@ -177,7 +178,11 @@ result = site.post( )["parse"] -def get_modules(page_modules, added_modules_dict, blocked_modules_dict={}): +def get_modules( + page_modules: List[str], + added_modules_dict: Dict[str, List[str]], + blocked_modules_dict: Dict[str, List[str]] = {} +) -> List[str]: modules = page_modules + added_modules_dict[cli_args.skin] for blocked_module in blocked_modules_dict.get(cli_args.skin, []): try: @@ -272,7 +277,7 @@ rendered_html = """\ ), skin=html.escape(cli_args.skin), page_class=html.escape(escape_css_class(result["displaytitle"])), - title=html.escape(result["displaytitle"]), + title=html.escape(cast(str, result["displaytitle"])), indicators_html="\n".join([ '
{}
'.format( indicator["name"], indicator["*"] diff --git a/scripts/onscreen-message b/scripts/onscreen-message index 32c3b5a..d9d86e7 100755 --- a/scripts/onscreen-message +++ b/scripts/onscreen-message @@ -1,11 +1,11 @@ #!/usr/bin/env python3 -import gi import argparse +import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, Pango - +gi.require_version("Gdk", "3.0") +from gi.repository import Gdk, Gtk, Pango parser = argparse.ArgumentParser() parser.add_argument("message", type=str, nargs="+") @@ -24,13 +24,13 @@ scrolled_window.add(label) window.add(scrolled_window) -def on_key_release(target, event): +def on_key_release(_target, event) -> None: key = event.keyval if key in [Gdk.KEY_Escape, Gdk.KEY_q, Gdk.KEY_Q]: window.close() -def on_configure(target, event): +def on_configure(target, event) -> None: if target != window or event.type != Gdk.EventType.CONFIGURE: return font_desc = Pango.FontDescription() diff --git a/scripts/playerctl-simple-menu b/scripts/playerctl-simple-menu index 5791276..17d6dd3 100755 --- a/scripts/playerctl-simple-menu +++ b/scripts/playerctl-simple-menu @@ -7,15 +7,15 @@ # TODO: Update the menu on player status changes. import math -import gi import sys +import gi gi.require_version("Playerctl", "2.0") gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") gi.require_version("Pango", "1.0") -from gi.repository import Playerctl, Gtk, Gdk, GLib, Pango +from gi.repository import Gdk, GLib, Gtk, Pango, Playerctl # Larger priority values will make the player with this name appear higher in # the menu. The default priority is 0. @@ -39,7 +39,7 @@ PLAYER_PLAYBACK_STATUS_EMOJIS = { } -def humanize_duration(duration): +def humanize_duration(duration: float) -> str: minutes, seconds = divmod(math.floor(duration), 60) hours, minutes = divmod(minutes, 60) text = "{:02}:{:02}".format(minutes, seconds) diff --git a/scripts/query-bookmarks b/scripts/query-bookmarks index fa3867f..9281561 100755 --- a/scripts/query-bookmarks +++ b/scripts/query-bookmarks @@ -7,15 +7,14 @@ # # -import sys import os -from pathlib import Path -from configparser import ConfigParser -import tempfile import shutil import sqlite3 -from typing import Optional, Tuple, Generator - +import sys +import tempfile +from configparser import ConfigParser +from pathlib import Path +from typing import Generator, Optional, Tuple sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", "script-resources")) import common_script_utils