"""Export a consistent SQLite snapshot without modifying the source database.""" import argparse import os from pathlib import Path import sqlite3 import sys import tempfile def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("source", type=Path) parser.add_argument("output", type=Path) args = parser.parse_args() source = args.source.resolve(strict=True) output = args.output.resolve() if output.exists(): parser.error("Output already exists; choose a new filename.") output.parent.mkdir(parents=True, exist_ok=True) # Refuse to overwrite either the original database or an earlier export. with tempfile.TemporaryDirectory(prefix="csr-sqlite-export-") as temporary: snapshot = Path(temporary) / "snapshot.sqlite3" origin = sqlite3.connect(source.as_uri() + "?mode=ro", uri=True) destination = sqlite3.connect(snapshot) try: origin.backup(destination) finally: destination.close() origin.close() os.environ["SQLITE_MIGRATION_SNAPSHOT"] = str(snapshot) os.environ["DJANGO_SETTINGS_MODULE"] = "csr_inventory.sqlite_migration_settings" sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) import django django.setup() from django.core.management import call_command from django.db import connections try: call_command("migrate", interactive=False, verbosity=0) with output.open("x", encoding="utf-8") as stream: os.chmod(output, 0o600) try: call_command( "dumpdata", natural_foreign=True, exclude=["contenttypes", "auth.permission", "sessions.session"], stdout=stream, verbosity=0, ) except BaseException: stream.close() output.unlink() raise finally: connections.close_all() print(f"Export created: {output}. Original SQLite database unchanged.") if __name__ == "__main__": main()