From 07bfb40425a5de3b363bc7e8b48642da446f653c Mon Sep 17 00:00:00 2001 From: Simon Bruder Date: Tue, 25 Feb 2020 23:37:11 +0000 Subject: [PATCH] Blacken python scripts --- .pre-commit-config.yaml | 6 ++++ android-touchpad.py | 63 ++++++++++++++++++++++++----------- downloaders/comic-valkyrie.py | 27 ++++++++++----- downloaders/mangadex.py | 22 +++++++----- downloaders/mangarock.py | 33 +++++++++--------- encoder-parameters.py | 28 ++++++++-------- huion-tablet.py | 54 +++++++++++++++--------------- ssim-stats.py | 49 +++++++++++++++------------ wordclock.py | 8 ++--- 9 files changed, 171 insertions(+), 119 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d0a5a47 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,6 @@ +repos: + - repo: https://github.com/psf/black + rev: stable + hooks: + - id: black + language_version: python3 diff --git a/android-touchpad.py b/android-touchpad.py index b81b833..08a6bf1 100755 --- a/android-touchpad.py +++ b/android-touchpad.py @@ -2,31 +2,54 @@ # made for samsung galaxy note 4 # only works with stylus # open phone app, dial *#0*#, choose “Black” +# requirements: +# * python-libxdo import argparse import subprocess from xdo import Xdo -parser = argparse.ArgumentParser(description='Use android phone stylus as input method') -parser.add_argument('--pos', type=str, default='100x100+0x0', help='Position on phone to use in percent (e.g. 40x40+10x10)') -parser.add_argument('--screen', type=str, default='1920x1080+0x0', help='Screen resolution and offset') -parser.add_argument('--phone', type=str, default='12544x7056', help='Phone resolution (not necessarily equal to the phone’s screen resolution)') +parser = argparse.ArgumentParser(description="Use android phone stylus as input method") +parser.add_argument( + "--pos", + type=str, + default="100x100+0x0", + help="Position on phone to use in percent (e.g. 40x40+10x10)", +) +parser.add_argument( + "--screen", type=str, default="1920x1080+0x0", help="Screen resolution and offset" +) +parser.add_argument( + "--phone", + type=str, + default="12544x7056", + help="Phone resolution (not necessarily equal to the phone’s screen resolution)", +) args = parser.parse_args() -screen_res = tuple(map(int, args.screen.split('+')[0].split('x'))) -offset = tuple(map(int, args.screen.split('+')[1].split('x'))) -phone_res = tuple(map(int, args.phone.split('x'))) +screen_res = tuple(map(int, args.screen.split("+")[0].split("x"))) +offset = tuple(map(int, args.screen.split("+")[1].split("x"))) +phone_res = tuple(map(int, args.phone.split("x"))) limits = [[0, 0], [0, 0]] -limits[0][0] = int(args.pos.split('+')[1].split('x')[0]) / 100 * phone_res[0] -limits[0][1] = limits[0][0] + int(args.pos.split('+')[0].split('x')[0]) / 100 * phone_res[0] -limits[1][0] = int(args.pos.split('+')[1].split('x')[1]) / 100 * phone_res[1] -limits[1][1] = limits[1][0] + int(args.pos.split('+')[0].split('x')[1]) / 100 * phone_res[1] +limits[0][0] = int(args.pos.split("+")[1].split("x")[0]) / 100 * phone_res[0] +limits[0][1] = ( + limits[0][0] + int(args.pos.split("+")[0].split("x")[0]) / 100 * phone_res[0] +) +limits[1][0] = int(args.pos.split("+")[1].split("x")[1]) / 100 * phone_res[1] +limits[1][1] = ( + limits[1][0] + int(args.pos.split("+")[0].split("x")[1]) / 100 * phone_res[1] +) + def real_value(axis, value): if axis == 1: value = phone_res[1] - value # https://stackoverflow.com/a/929107 - return int(((value - limits[axis][0]) * screen_res[axis]) / (limits[axis][1] - limits[axis][0])) + return int( + ((value - limits[axis][0]) * screen_res[axis]) + / (limits[axis][1] - limits[axis][0]) + ) + update = 0 x = 0 @@ -35,17 +58,19 @@ pressure = 0 xdo = Xdo() -process = subprocess.Popen(['adb', 'shell', 'getevent', '-q', '-l'], stdout=subprocess.PIPE) +process = subprocess.Popen( + ["adb", "shell", "getevent", "-q", "-l"], stdout=subprocess.PIPE +) for line in process.stdout: - line = line.decode('utf-8') + line = line.decode("utf-8") line = line.split() - if line[1] != 'EV_ABS': + if line[1] != "EV_ABS": continue event = line[2] - value = int('0x' + line[3], 16) + value = int("0x" + line[3], 16) - if event == 'ABS_PRESSURE': + if event == "ABS_PRESSURE": if value == 0 and pressure != 0: xdo.mouse_up(0, 1) elif pressure == 0: @@ -53,13 +78,13 @@ for line in process.stdout: pressure = value # Y and X flipped (landscape) - elif event == 'ABS_Y': + elif event == "ABS_Y": old_x = x x = real_value(0, value) if old_x != x: update += 1 - elif event == 'ABS_X': + elif event == "ABS_X": old_y = y y = real_value(1, value) if old_y != y: diff --git a/downloaders/comic-valkyrie.py b/downloaders/comic-valkyrie.py index 2c6ae42..3b3bfa5 100755 --- a/downloaders/comic-valkyrie.py +++ b/downloaders/comic-valkyrie.py @@ -6,29 +6,38 @@ import re import requests import sys + def parse_filename(filename): - split = re.split(':|,|\+|>', filename) + split = re.split(":|,|\+|>", filename) return map(int, split[1:]) + def get_image_urls(): url = sys.argv[1] - soup = BeautifulSoup(requests.get(url).text, 'html.parser') - for div in soup.find(id='content').find_all('div'): - yield url + div.get('data-ptimg') + soup = BeautifulSoup(requests.get(url).text, "html.parser") + for div in soup.find(id="content").find_all("div"): + yield url + div.get("data-ptimg") + pages = list(get_image_urls()) for metadata_url in tqdm(pages): - image_url = re.sub('\.ptimg\.json$', '.jpg', metadata_url) + image_url = re.sub("\.ptimg\.json$", ".jpg", metadata_url) ptimg_data = requests.get(metadata_url).json() image_data = requests.get(image_url, stream=True).raw scrambled_image = Image.open(image_data) - combined_image = Image.new('RGB', (ptimg_data['views'][0]['width'], ptimg_data['views'][0]['height'])) + combined_image = Image.new( + "RGB", (ptimg_data["views"][0]["width"], ptimg_data["views"][0]["height"]) + ) - for from_x, from_y, width, height, to_x, to_y in map(parse_filename, ptimg_data['views'][0]['coords']): - chunk_data = scrambled_image.crop((from_x, from_y, from_x+width, from_y+height)) + for from_x, from_y, width, height, to_x, to_y in map( + parse_filename, ptimg_data["views"][0]["coords"] + ): + chunk_data = scrambled_image.crop( + (from_x, from_y, from_x + width, from_y + height) + ) combined_image.paste(chunk_data, (to_x, to_y)) - combined_image.save(image_url.split('/')[-1]) + combined_image.save(image_url.split("/")[-1]) diff --git a/downloaders/mangadex.py b/downloaders/mangadex.py index b9d6c78..7584b68 100755 --- a/downloaders/mangadex.py +++ b/downloaders/mangadex.py @@ -7,31 +7,35 @@ import sys import os if len(sys.argv) < 2: - raise Exception('sys.argv[1]') + raise Exception("sys.argv[1]") + def parse_chapter_api(data): - if not data['server'].startswith('http'): - data['server'] = 'https://mangadex.org/data/' - base_url = data['server'] + data['hash'] + '/' - return list(map(lambda page: base_url + page, data['page_array'])) + if not data["server"].startswith("http"): + data["server"] = "https://mangadex.org/data/" + base_url = data["server"] + data["hash"] + "/" + return list(map(lambda page: base_url + page, data["page_array"])) + for chapter in tqdm(sys.argv[1:]): chapter_api_response = requests.get( - f'https://mangadex.org/api/?id={chapter}&type=chapter' + f"https://mangadex.org/api/?id={chapter}&type=chapter" ) - chapter_number = chapter_api_response.json()['chapter'] + chapter_number = chapter_api_response.json()["chapter"] os.makedirs(chapter_number, exist_ok=True) try: for image in tqdm(parse_chapter_api(chapter_api_response.json())): r = requests.get(image, stream=True) - with open(chapter_number + '/' + image.split('/')[-1], 'wb') as f: + with open(chapter_number + "/" + image.split("/")[-1], "wb") as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) except simplejson.errors.JSONDecodeError as e: if chapter_api_response.status_code != 200: - raise Exception(f'API request failed with HTTP status code {chapter_api_response.status_code}') from None + raise Exception( + f"API request failed with HTTP status code {chapter_api_response.status_code}" + ) from None else: raise e diff --git a/downloaders/mangarock.py b/downloaders/mangarock.py index 81b02b7..67d9428 100755 --- a/downloaders/mangarock.py +++ b/downloaders/mangarock.py @@ -9,46 +9,45 @@ import sys XOR_KEY = 101 + def get_pages(chapter): api_response = requests.get( - 'https://api.mangarockhd.com/query/web401/pagesv2', - params={ - 'oid': 'mrs-chapter-' + chapter - } + "https://api.mangarockhd.com/query/web401/pagesv2", + params={"oid": "mrs-chapter-" + chapter}, ).json() - for item in api_response['data']: - yield item['url'] + for item in api_response["data"]: + yield item["url"] + def decode_ciphertext(byte): return byte ^ XOR_KEY + def get_image(url): ciphertext = requests.get(url).content size = len(ciphertext) + 7 cleartext = BytesIO() - cleartext.write('RIFF'.encode('ascii')) - cleartext.write(bytes([ - size >> 0 & 255, - size >> 8 & 255, - size >> 16 & 255, - size >> 24 & 255 - ])) - cleartext.write('WEBPVP8'.encode('ascii')) + cleartext.write("RIFF".encode("ascii")) + cleartext.write( + bytes([size >> 0 & 255, size >> 8 & 255, size >> 16 & 255, size >> 24 & 255]) + ) + cleartext.write("WEBPVP8".encode("ascii")) cleartext.write(bytes(list(map(decode_ciphertext, ciphertext)))) cleartext.seek(0) return cleartext + requested_chapters = sys.argv[1:] for chapter_idx, chapter in tqdm(list(enumerate(requested_chapters))): - chapter_dir = str(chapter_idx+1) + chapter_dir = str(chapter_idx + 1) os.makedirs(chapter_dir, exist_ok=True) pages = get_pages(chapter) for idx, page in tqdm(list(enumerate(pages))): - filename = os.path.join(chapter_dir, f'{idx+1:04}.webp') + filename = os.path.join(chapter_dir, f"{idx+1:04}.webp") if os.path.isfile(filename): continue image = get_image(page) - with open(filename, 'wb') as f: + with open(filename, "wb") as f: f.write(image.read()) diff --git a/encoder-parameters.py b/encoder-parameters.py index 5500696..2111836 100755 --- a/encoder-parameters.py +++ b/encoder-parameters.py @@ -3,20 +3,22 @@ import sys import subprocess import json + def is_number(value): - numeric_chars = [*map(str, range(10)), '-'] + numeric_chars = [*map(str, range(10)), "-"] numeric_charcodes = list(map(ord, numeric_chars)) return all(ord(char) in numeric_charcodes for char in value) + def parse_encoder_params(encoder_params): - for param in encoder_params.split(' / '): - if '=' in param: - key, value = param.split('=', 1) + for param in encoder_params.split(" / "): + if "=" in param: + key, value = param.split("=", 1) if is_number(value): value = int(value) - elif is_number(value.replace('.', '', 1)): + elif is_number(value.replace(".", "", 1)): value = float(value) else: key = param @@ -24,23 +26,21 @@ def parse_encoder_params(encoder_params): yield key, value + def run_mediainfo(file): cmd = [ - 'mediainfo', - '--Inform=Video;%Encoded_Library%\\n%Encoded_Library_Settings%', - file + "mediainfo", + "--Inform=Video;%Encoded_Library%\\n%Encoded_Library_Settings%", + file, ] process = subprocess.run(cmd, stdout=subprocess.PIPE) - output = process.stdout.decode('utf-8').split('\n') + output = process.stdout.decode("utf-8").split("\n") encoder = output[0] params = dict(parse_encoder_params(output[1])) - return { - 'file': file, - 'encoder': encoder, - 'params': params - } + return {"file": file, "encoder": encoder, "params": params} + info = list(map(run_mediainfo, sys.argv[1:])) print(json.dumps(info, indent=2, sort_keys=True)) diff --git a/huion-tablet.py b/huion-tablet.py index 7da22b2..15b953c 100755 --- a/huion-tablet.py +++ b/huion-tablet.py @@ -22,40 +22,42 @@ import argparse import os.path import yaml -def set_parameter(device, *args): - if device == 'stylus': - device = 'HUION Huion Tablet Pen stylus' - elif device == 'pad': - device = 'HUION Huion Tablet Pad pad' - args = map(str, args) - run(['xsetwacom', 'set', device, *args], check=True) -parser = argparse.ArgumentParser(description='setup huion h430p tablet') -parser.add_argument('--area', type=str, default='') -parser.add_argument('--screen', type=str, default='') -parser.add_argument('preset', metavar='PRESET', type=str, nargs='?', help='a preset') +def set_parameter(device, *args): + if device == "stylus": + device = "HUION Huion Tablet Pen stylus" + elif device == "pad": + device = "HUION Huion Tablet Pad pad" + args = map(str, args) + run(["xsetwacom", "set", device, *args], check=True) + + +parser = argparse.ArgumentParser(description="setup huion h430p tablet") +parser.add_argument("--area", type=str, default="") +parser.add_argument("--screen", type=str, default="") +parser.add_argument("preset", metavar="PRESET", type=str, nargs="?", help="a preset") args = parser.parse_args() -area = '0 0 24384 15240' -screen = '' +area = "0 0 24384 15240" +screen = "" if args.preset is not None: - with open(os.path.expanduser('~/.config/huion-tablet.yml'), 'r') as f: + with open(os.path.expanduser("~/.config/huion-tablet.yml"), "r") as f: config = yaml.load(f, Loader=yaml.SafeLoader) - preset = config['presets'][args.preset] - area = preset['area'] - screen = preset['screen'] - if 'buttons' in preset: - for device in preset['buttons']: - for button, mapping in preset['buttons'][device].items(): - set_parameter(device, 'button', button, *str(mapping).split(' ')) + preset = config["presets"][args.preset] + area = preset["area"] + screen = preset["screen"] + if "buttons" in preset: + for device in preset["buttons"]: + for button, mapping in preset["buttons"][device].items(): + set_parameter(device, "button", button, *str(mapping).split(" ")) -if args.area != '': +if args.area != "": area = args.area -if args.screen != '': +if args.screen != "": screen = args.screen -area = tuple(map(int, area.split(' '))) +area = tuple(map(int, area.split(" "))) -set_parameter('stylus', 'Area', ' '.join(map(str, area))) -set_parameter('stylus', 'MapToOutput', screen) +set_parameter("stylus", "Area", " ".join(map(str, area))) +set_parameter("stylus", "MapToOutput", screen) diff --git a/ssim-stats.py b/ssim-stats.py index b682bab..88502ea 100755 --- a/ssim-stats.py +++ b/ssim-stats.py @@ -5,39 +5,46 @@ import sys from pprint import pprint from tabulate import tabulate + def process_raw_line(line): - fields = line.rstrip().split(' ') - fields = [field.split(':')[-1] for field in fields] + fields = line.rstrip().split(" ") + fields = [field.split(":")[-1] for field in fields] fields[5] = fields[5][1:-1] fields[0] = int(fields[0]) fields[1:] = list(map(np.float, fields[1:])) return fields -with open(sys.argv[1], 'r') as f: + +with open(sys.argv[1], "r") as f: data = list(map(process_raw_line, f.readlines())) df = pd.DataFrame(data) -df.columns = ['frame', 'Y', 'U', 'V', 'All', 'dB'] -df['inv'] = [1 - value for value in df['All']] +df.columns = ["frame", "Y", "U", "V", "All", "dB"] +df["inv"] = [1 - value for value in df["All"]] print(f'Mean overall SSIM: {df["All"].mean()}') print(f'Median overall SSIM: {df["All"].median()}') print(f'Frame with worst SSIM: {df.idxmin()["All"]+1}') print(f'Frame with best SSIM: {df.idxmax()["All"]+1}') -print(tabulate( - [(key, value * 100) for key, value in [ - ['best', df['All'].max()], - [50, 1 - df['inv'].quantile(0.50)], - [66.6, 1 - df['inv'].quantile(0.666)], - [75, 1 - df['inv'].quantile(0.75)], - [80, 1 - df['inv'].quantile(0.80)], - [90, 1 - df['inv'].quantile(0.90)], - [95, 1 - df['inv'].quantile(0.95)], - [98, 1 - df['inv'].quantile(0.98)], - [99, 1 - df['inv'].quantile(0.99)], - [99.9, 1 - df['inv'].quantile(0.999)], - [100, df['All'].min()] - ]], - headers=['% Frames', '≥ SSIM'] -)) +print( + tabulate( + [ + (key, value * 100) + for key, value in [ + ["best", df["All"].max()], + [50, 1 - df["inv"].quantile(0.50)], + [66.6, 1 - df["inv"].quantile(0.666)], + [75, 1 - df["inv"].quantile(0.75)], + [80, 1 - df["inv"].quantile(0.80)], + [90, 1 - df["inv"].quantile(0.90)], + [95, 1 - df["inv"].quantile(0.95)], + [98, 1 - df["inv"].quantile(0.98)], + [99, 1 - df["inv"].quantile(0.99)], + [99.9, 1 - df["inv"].quantile(0.999)], + [100, df["All"].min()], + ] + ], + headers=["% Frames", "≥ SSIM"], + ) +) diff --git a/wordclock.py b/wordclock.py index 13fa40f..643125e 100755 --- a/wordclock.py +++ b/wordclock.py @@ -3,11 +3,11 @@ import sys import paho.mqtt.client as mqtt import wordclock_credentials as creds -client = mqtt.Client('wordclock.py') +client = mqtt.Client("wordclock.py") client.username_pw_set(creds.USER, creds.PASSWORD) client.connect(creds.MQTT_HOST, 1883, 60) -client.publish('wordclock/color/red', sys.argv[2], retain=True) -client.publish('wordclock/color/green', sys.argv[1], retain=True) -client.publish('wordclock/color/blue', sys.argv[3], retain=True) +client.publish("wordclock/color/red", sys.argv[2], retain=True) +client.publish("wordclock/color/green", sys.argv[1], retain=True) +client.publish("wordclock/color/blue", sys.argv[3], retain=True)