migrate --list is read-only with legacy sqlite-migrate classes too

The docs promise --list will not create the database file or the
_sqlite_migrations table, but legacy sqlite_migrate.Migrations classes
create the table (in the legacy schema) from their pending()/applied()
methods. The listing now runs inside a transaction that is rolled back,
keeping --list read-only regardless of what the migration class does.

Refs https://github.com/simonw/sqlite-utils/issues/769#issuecomment-4900034150

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Simon Willison 2026-07-06 21:58:52 -07:00
commit 93640a7dde
3 changed files with 29 additions and 1 deletions

View file

@ -485,3 +485,23 @@ def test_stop_before_applied_migration_errors(two_migrations):
assert "already been applied" in result.output
db = sqlite_utils.Database(db_path)
assert not db["bar"].exists()
def test_list_with_legacy_class_is_read_only(tmpdir):
# Legacy sqlite-migrate classes create the _sqlite_migrations table
# from their pending()/applied() methods - --list must roll that
# back so it stays a read-only operation as documented
path = pathlib.Path(tmpdir)
(path / "migrations.py").write_text(LEGACY_MIGRATIONS, "utf-8")
db_path = str(path / "test.db")
db = sqlite_utils.Database(db_path)
db["existing"].insert({"id": 1})
db.close()
result = CliRunner().invoke(
sqlite_utils.cli.cli, ["migrate", db_path, str(path), "--list"]
)
assert result.exit_code == 0, result.output
assert "first" in result.output
db2 = sqlite_utils.Database(db_path)
assert "_sqlite_migrations" not in db2.table_names()
db2.close()