social media crossposting tool. 3rd time's the charm
mastodon misskey crossposting bluesky
at next 1.2 kB view raw
1import importlib.util 2from pathlib import Path 3import sqlite3 4from typing import Callable 5 6 7def load_migrations(path: Path) -> list[tuple[int, str, Callable[[sqlite3.Connection], None]]]: 8 migrations: list[tuple[int, str, Callable[[sqlite3.Connection], None]]] = [] 9 migration_files = sorted( 10 [f for f in path.glob("*.py") if not f.stem.startswith("_")] 11 ) 12 13 for filepath in migration_files: 14 filename = filepath.stem 15 version_str = filename.split("_")[0] 16 17 try: 18 version = int(version_str) 19 except ValueError: 20 raise ValueError('migrations must start with a number!!') 21 22 spec = importlib.util.spec_from_file_location(filepath.stem, filepath) 23 if not spec or not spec.loader: 24 raise Exception(f"Failed to load spec from file: {filepath}") 25 26 module = importlib.util.module_from_spec(spec) 27 spec.loader.exec_module(module) 28 29 if hasattr(module, "migrate"): 30 migrations.append((version, filename, module.migrate)) 31 else: 32 raise ValueError(f"Migration {filepath.name} missing 'migrate' function") 33 34 migrations.sort(key=lambda x: x[0]) 35 return migrations