* feat: support `--fake` for aerich upgrade * Add `--fake` to downgrade * tests: check --fake result for aerich upgrade and downgrade * Update readme * Fix unittest failed because of `db_field_types` changed * refactor: improve type hints and document
164 lines
6.4 KiB
Python
164 lines
6.4 KiB
Python
import contextlib
|
|
import os
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
from aerich.ddl.sqlite import SqliteDDL
|
|
from aerich.migrate import Migrate
|
|
from tests._utils import chdir, copy_files
|
|
|
|
|
|
def run_aerich(cmd: str) -> None:
|
|
with contextlib.suppress(subprocess.TimeoutExpired):
|
|
if not cmd.startswith("aerich") and not cmd.startswith("poetry"):
|
|
cmd = "aerich " + cmd
|
|
subprocess.run(shlex.split(cmd), timeout=2)
|
|
|
|
|
|
def run_shell(cmd: str) -> subprocess.CompletedProcess:
|
|
envs = dict(os.environ, PYTHONPATH=".")
|
|
return subprocess.run(shlex.split(cmd), env=envs)
|
|
|
|
|
|
def test_sqlite_migrate(tmp_path: Path) -> None:
|
|
if (ddl := getattr(Migrate, "ddl", None)) and not isinstance(ddl, SqliteDDL):
|
|
return
|
|
test_dir = Path(__file__).parent
|
|
asset_dir = test_dir / "assets" / "sqlite_migrate"
|
|
with chdir(tmp_path):
|
|
files = ("models.py", "settings.py", "_tests.py")
|
|
copy_files(*(asset_dir / f for f in files), target_dir=Path())
|
|
models_py, settings_py, test_py = (Path(f) for f in files)
|
|
copy_files(asset_dir / "conftest_.py", target_dir=Path("conftest.py"))
|
|
if (db_file := Path("db.sqlite3")).exists():
|
|
db_file.unlink()
|
|
MODELS = models_py.read_text("utf-8")
|
|
run_aerich("aerich init -t settings.TORTOISE_ORM")
|
|
config_file = Path("pyproject.toml")
|
|
modify_time = config_file.stat().st_mtime
|
|
run_aerich("aerich init-db")
|
|
run_aerich("aerich init -t settings.TORTOISE_ORM")
|
|
assert modify_time == config_file.stat().st_mtime
|
|
r = run_shell("pytest _tests.py::test_allow_duplicate")
|
|
assert r.returncode == 0
|
|
# Add index
|
|
models_py.write_text(MODELS.replace("index=False", "index=True"))
|
|
run_aerich("aerich migrate") # migrations/models/1_
|
|
run_aerich("aerich upgrade")
|
|
r = run_shell("pytest -s _tests.py::test_allow_duplicate")
|
|
assert r.returncode == 0
|
|
# Drop index
|
|
models_py.write_text(MODELS)
|
|
run_aerich("aerich migrate") # migrations/models/2_
|
|
run_aerich("aerich upgrade")
|
|
r = run_shell("pytest -s _tests.py::test_allow_duplicate")
|
|
assert r.returncode == 0
|
|
# Add unique index
|
|
models_py.write_text(MODELS.replace("index=False", "index=True, unique=True"))
|
|
run_aerich("aerich migrate") # migrations/models/3_
|
|
run_aerich("aerich upgrade")
|
|
r = run_shell("pytest _tests.py::test_unique_is_true")
|
|
assert r.returncode == 0
|
|
# Drop unique index
|
|
models_py.write_text(MODELS)
|
|
run_aerich("aerich migrate") # migrations/models/4_
|
|
run_aerich("aerich upgrade")
|
|
r = run_shell("pytest _tests.py::test_allow_duplicate")
|
|
assert r.returncode == 0
|
|
# Add field with unique=True
|
|
with models_py.open("a") as f:
|
|
f.write(" age = fields.IntField(unique=True, default=0)")
|
|
run_aerich("aerich migrate") # migrations/models/5_
|
|
run_aerich("aerich upgrade")
|
|
r = run_shell("pytest _tests.py::test_add_unique_field")
|
|
assert r.returncode == 0
|
|
# Drop unique field
|
|
models_py.write_text(MODELS)
|
|
run_aerich("aerich migrate") # migrations/models/6_
|
|
run_aerich("aerich upgrade")
|
|
r = run_shell("pytest -s _tests.py::test_drop_unique_field")
|
|
assert r.returncode == 0
|
|
|
|
# Initial with indexed field and then drop it
|
|
migrations_dir = Path("migrations/models")
|
|
shutil.rmtree(migrations_dir)
|
|
db_file.unlink()
|
|
models_py.write_text(MODELS + " age = fields.IntField(db_index=True)")
|
|
run_aerich("aerich init -t settings.TORTOISE_ORM")
|
|
run_aerich("aerich init-db")
|
|
migration_file = list(migrations_dir.glob("0_*.py"))[0]
|
|
assert "CREATE INDEX" in migration_file.read_text()
|
|
r = run_shell("pytest _tests.py::test_with_age_field")
|
|
assert r.returncode == 0
|
|
models_py.write_text(MODELS)
|
|
run_aerich("aerich migrate")
|
|
run_aerich("aerich upgrade")
|
|
migration_file_1 = list(migrations_dir.glob("1_*.py"))[0]
|
|
assert "DROP INDEX" in migration_file_1.read_text()
|
|
r = run_shell("pytest _tests.py::test_without_age_field")
|
|
assert r.returncode == 0
|
|
|
|
# Generate migration file in emptry directory
|
|
db_file.unlink()
|
|
run_aerich("aerich init-db")
|
|
assert not db_file.exists()
|
|
for p in migrations_dir.glob("*"):
|
|
if p.is_dir():
|
|
shutil.rmtree(p)
|
|
else:
|
|
p.unlink()
|
|
run_aerich("aerich init-db")
|
|
assert db_file.exists()
|
|
|
|
# init without '[tool]' section in pyproject.toml
|
|
config_file = Path("pyproject.toml")
|
|
config_file.write_text('[project]\nname = "project"')
|
|
run_aerich("init -t settings.TORTOISE_ORM")
|
|
assert "[tool.aerich]" in config_file.read_text()
|
|
|
|
# add m2m with custom model for through
|
|
new = """
|
|
groups = fields.ManyToManyField("models.Group", through="foo_group")
|
|
|
|
class Group(Model):
|
|
name = fields.CharField(max_length=60)
|
|
|
|
class FooGroup(Model):
|
|
foo = fields.ForeignKeyField("models.Foo")
|
|
group = fields.ForeignKeyField("models.Group")
|
|
is_active = fields.BooleanField(default=False)
|
|
|
|
class Meta:
|
|
table = "foo_group"
|
|
"""
|
|
models_py.write_text(MODELS + new)
|
|
run_aerich("aerich migrate")
|
|
run_aerich("aerich upgrade")
|
|
migration_file_1 = list(migrations_dir.glob("1_*.py"))[0]
|
|
assert "foo_group" in migration_file_1.read_text()
|
|
r = run_shell("pytest _tests.py::test_m2m_with_custom_through")
|
|
assert r.returncode == 0
|
|
|
|
# add m2m field after init-db
|
|
new = """
|
|
groups = fields.ManyToManyField("models.Group", through="foo_group", related_name="users")
|
|
|
|
class Group(Model):
|
|
name = fields.CharField(max_length=60)
|
|
"""
|
|
if db_file.exists():
|
|
db_file.unlink()
|
|
if migrations_dir.exists():
|
|
shutil.rmtree(migrations_dir)
|
|
models_py.write_text(MODELS)
|
|
run_aerich("aerich init-db")
|
|
models_py.write_text(MODELS + new)
|
|
run_aerich("aerich migrate")
|
|
run_aerich("aerich upgrade")
|
|
migration_file_1 = list(migrations_dir.glob("1_*.py"))[0]
|
|
assert "foo_group" in migration_file_1.read_text()
|
|
r = run_shell("pytest _tests.py::test_add_m2m_field_after_init_db")
|
|
assert r.returncode == 0
|