Skip to content

Instantly share code, notes, and snippets.

View twilligon's full-sized avatar

twilligon

View GitHub Profile
import ast
from collections import defaultdict
from dataclasses import dataclass
from textwrap import dedent
@dataclass
class FunctionSpan:
indent: int
definition_line: int
@twilligon
twilligon / 4ocr.py
Created June 17, 2024 22:42
Document OCR via GPT-4o
#!/usr/bin/env python3
from concurrent.futures import ThreadPoolExecutor
from io import BytesIO
import asyncio
import base64
import random
import sys
from openai import AsyncOpenAI, APIError, RateLimitError
from openai.types.completion import CompletionUsage
@twilligon
twilligon / coco.py
Created May 24, 2024 23:48
Decode COCO RLE images to PNG masks
#!/usr/bin/env python3
import sys
import re
import numpy as np
from PIL import Image
def decode_rle(rle, width, height):
img = np.zeros((height, width), dtype=np.uint8)
seq = img.ravel()
#!/bin/sh
set -eu
NETNS="$(printf '%s' "$1" | sed -n 's#.*/\([^.]*\)\..*#\1#p')"
mkdir -p "/etc/netns/${NETNS}"
sed -nr 's/^DNS = (.*)/\1/p' "$1" | tr ',' '\n' | sed 's/^/nameserver /' > "/etc/netns/${NETNS}/resolv.conf"
ip netns del "${NETNS}" 2>/dev/null || :
ip netns add "${NETNS}"
@twilligon
twilligon / read.py
Created March 3, 2024 02:35
Create an audiobook from a text file with OpenAI TTS
#!/bin/env python3
import asyncio, os, string, sys
from contextlib import suppress
from aiolimiter import AsyncLimiter
FORMAT = "flac"
MAX_INPUT_LENGTH = 4096
COST_PER_CHAR = 0.030 / 1000
REQUESTS_PER_MIN = 10
@twilligon
twilligon / mutable.py
Created February 7, 2024 11:54
Interior mutability (like Rust's Cell<T>) in Python
from functools import update_wrapper
def Mutable(inner):
def rebind(unbound):
return lambda self, *args, **kwargs: unbound(
self.inner,
*(a.inner if isinstance(a, type(self)) else a
for a in args),
**{k: v.inner if isinstance(v, type(self)) else v
for k, v in kwargs.items()},
@twilligon
twilligon / async_agnostic.py
Created January 24, 2024 06:30
@async_agnostic decorator for running async functions at the REPL
import asyncio
def async_agnostic(corofn):
@wraps(corofn)
def wrapper(*args, **kwargs):
with suppress(RuntimeError):
loop = asyncio.get_running_loop()
if loop.is_running():
return corofn(*args, **kwargs)
return asyncio.run(corofn(*args, **kwargs))
#!/usr/bin/env python
# Usage: with both the terminal and /dev/input keylogger running, press every
# key on your keyboard. This program will correlate the two transcripts to
# generate a mapping from Linux kernel keycodes to terminal chars/escape codes.
#
# In other words, run:
#
# ./keylogger > kb-keylogger.csv & ./terminal > kb-terminal.csv
# killall -SIGINT keylogger
# ./generate-keymap.py
@twilligon
twilligon / 0000-fix-CVE-2019-5786.patch
Last active March 18, 2019 16:15
Chromium unstable patch for CVE-2019-5786
From 0b8ac062693ce67019dfef28f76e0c79db8fa0a3 Mon Sep 17 00:00:00 2001
From: Will Harris <[email protected]>
Date: Thu, 28 Feb 2019 19:32:41 +0000
Subject: [PATCH] Merge M73: FileReader: Make a copy of the ArrayBuffer when
returning partial results.
This is to avoid accidentally ending up with multiple references to the
same underlying ArrayBuffer. The extra performance overhead of this is
minimal as usage of partial results is very rare anyway (as can be seen
on https://www.chromestatus.com/metrics/feature/timeline/popularity/2158).
@twilligon
twilligon / ld-musl-workaround
Created April 13, 2018 16:00
I hate autoconf
#!/bin/bash
# When autoconf configure scripts look for the LIBC PATH, they assume ld
# prefaces the paths with "attempt to open /lib/path.so" (the behavior of
# GNU ld) while lld uses a different format. With CONFIGURE_LIBC_WORKAROUND
# set the output will be transformed to GNU ld's format.
if [ -n "${CONFIGURE_LIBC_WORKAROUND+1}" ] && (echo $@ | grep -q -- "--verbose"); then
exec -a $0 ld $@ 2> >(sed "s@^$0: /\(.*\)\$@attempt to open /\1 succeeded@g" >&2)
else
exec -a $0 ld $@