Beispiel #1
0
async def init_db(ctx: Context, safe):
    config = ctx.obj["config"]
    location = ctx.obj["location"]
    app = ctx.obj["app"]

    dirname = os.path.join(location, app)
    if not os.path.isdir(dirname):
        os.mkdir(dirname)
        click.secho(f"Success create app migrate location {dirname}", fg=Color.green)
    else:
        return click.secho(f"Inited {app} already", fg=Color.yellow)

    Migrate.write_old_models(config, app, location)

    await Tortoise.init(config=config)
    connection = get_app_connection(config, app)
    await generate_schema_for_client(connection, safe)

    schema = get_schema_sql(connection, safe)

    version = await Migrate.generate_version()
    await Aerich.create(version=version, app=app)
    with open(os.path.join(dirname, version), "w", encoding="utf-8") as f:
        content = {
            "upgrade": [schema],
        }
        json.dump(content, f, ensure_ascii=False, indent=2)
    return click.secho(f'Success generate schema for app "{app}"', fg=Color.green)
Beispiel #2
0
 def wrapper(*args, **kwargs):
     loop = asyncio.get_event_loop()
     ctx = args[0]
     loop.run_until_complete(f(*args, **kwargs))
     app = ctx.obj.get("app")
     if app:
         Migrate.remove_old_model_file(app, ctx.obj["location"])
Beispiel #3
0
async def upgrade(ctx: Context):
    config = ctx.obj["config"]
    app = ctx.obj["app"]
    location = ctx.obj["location"]
    migrated = False
    for version_file in Migrate.get_all_version_files():
        try:
            exists = await Aerich.exists(version=version_file, app=app)
        except OperationalError:
            exists = False
        if not exists:
            async with in_transaction(get_app_connection_name(config,
                                                              app)) as conn:
                file_path = Path(Migrate.migrate_location, version_file)
                content = get_version_content_from_file(file_path)
                upgrade_query_list = content.get("upgrade")
                for upgrade_query in upgrade_query_list:
                    await conn.execute_script(upgrade_query)
                await Aerich.create(
                    version=version_file,
                    app=app,
                    content=Migrate.get_models_content(config, app, location),
                )
            click.secho(f"Success upgrade {version_file}", fg=Color.green)
            migrated = True
    if not migrated:
        click.secho("No upgrade items found", fg=Color.yellow)
Beispiel #4
0
async def migrate(ctx: Context, name: str = typer.Option("update", help="Migrate name.")):
    """Generate migrate changes file."""
    app, config, location = await connect_tortoise(ctx)
    ret = await Migrate.migrate(name)
    if not ret:
        return typer.secho("No changes detected", fg=typer.colors.YELLOW)
    Migrate.write_old_models(config, app, location)
    typer.secho(f"Success migrate {ret}", fg=typer.colors.GREEN)
Beispiel #5
0
async def migrate(ctx: Context, name):
    config = ctx.obj["config"]
    location = ctx.obj["location"]
    app = ctx.obj["app"]

    ret = await Migrate.migrate(name)
    if not ret:
        return click.secho("No changes detected", fg=Color.yellow)
    Migrate.write_old_models(config, app, location)
    click.secho(f"Success migrate {ret}", fg=Color.green)
Beispiel #6
0
async def history(ctx: Context):
    """List all migrate items."""
    versions = Migrate.get_all_version_files()
    for version in versions:
        typer.secho(version, fg=typer.colors.GREEN)
    if not versions:
        typer.secho("No history,try migrate", fg=typer.colors.GREEN)
Beispiel #7
0
 async def heads(self):
     ret = []
     versions = Migrate.get_all_version_files()
     for version in versions:
         if not await Aerich.exists(version=version, app=self.app):
             ret.append(version)
     return ret
Beispiel #8
0
async def init_db(ctx: Context, safe):
    config = ctx.obj["config"]
    location = ctx.obj["location"]
    app = ctx.obj["app"]

    dirname = Path(location, app)
    if not dirname.is_dir():
        os.mkdir(dirname)
        click.secho(f"Success create app migrate location {dirname}",
                    fg=Color.green)
    else:
        return click.secho(
            f"Inited {app} already, or delete {dirname} and try again.",
            fg=Color.yellow)

    await Tortoise.init(config=config)
    connection = get_app_connection(config, app)
    await generate_schema_for_client(connection, safe)

    schema = get_schema_sql(connection, safe)

    version = await Migrate.generate_version()
    await Aerich.create(
        version=version,
        app=app,
        content=Migrate.get_models_content(config, app, location),
    )
    content = {
        "upgrade": [schema],
    }
    write_version_file(Path(dirname, version), content)
    click.secho(f'Success generate schema for app "{app}"', fg=Color.green)
Beispiel #9
0
async def init_db(ctx: Context, safe):
    config = ctx.obj["config"]
    location = ctx.obj["location"]
    app = ctx.obj["app"]

    dirname = os.path.join(location, app)
    if not os.path.isdir(dirname):
        os.mkdir(dirname)
        click.secho(f"Success create app migrate location {dirname}", fg=Color.green)
    else:
        return click.secho(f'Already inited app "{app}"', fg=Color.yellow)

    Migrate.write_old_models(config, app, location)

    await Tortoise.init(config=config)
    connection = get_app_connection(config, app)
    await generate_schema_for_client(connection, safe)

    return click.secho(f'Success generate schema for app "{app}"', fg=Color.green)
Beispiel #10
0
async def heads(ctx: Context):
    app = ctx.obj["app"]
    versions = Migrate.get_all_version_files()
    is_heads = False
    for version in versions:
        if not await Aerich.exists(version=version, app=app):
            click.secho(version, fg=Color.green)
            is_heads = True
    if not is_heads:
        click.secho("No available heads,try migrate first", fg=Color.green)
Beispiel #11
0
async def heads(ctx: Context):
    """Show current available heads in migrate location."""
    app,config,location=await connect_tortoise(ctx)
    versions = Migrate.get_all_version_files()
    is_heads = False
    for version in versions:
        if not await Aerich.exists(version=version, app=app):
            typer.secho(version, fg=typer.colors.GREEN)
            is_heads = True
    if not is_heads:
        typer.secho("No available heads,try migrate", fg=typer.colors.GREEN)
Beispiel #12
0
def test_migrate(mocker: MockerFixture):
    mocker.patch("click.prompt", return_value=True)
    apps = Tortoise.apps
    models = apps.get("models")
    diff_models = apps.get("diff_models")
    Migrate.diff_models(diff_models, models)
    if isinstance(Migrate.ddl, SqliteDDL):
        with pytest.raises(NotSupportError):
            Migrate.diff_models(models, diff_models, False)
    else:
        Migrate.diff_models(models, diff_models, False)
    Migrate._merge_operators()
    if isinstance(Migrate.ddl, MysqlDDL):
        assert Migrate.upgrade_operators == [
            "ALTER TABLE `email` DROP FOREIGN KEY `fk_email_user_5b58673d`",
            "ALTER TABLE `category` ADD `name` VARCHAR(200) NOT NULL",
            "ALTER TABLE `user` ADD UNIQUE INDEX `uid_user_usernam_9987ab` (`username`)",
            "ALTER TABLE `user` RENAME COLUMN `last_login_at` TO `last_login`",
        ]
        assert Migrate.downgrade_operators == [
            "ALTER TABLE `category` DROP COLUMN `name`",
            "ALTER TABLE `user` DROP INDEX `uid_user_usernam_9987ab`",
            "ALTER TABLE `user` RENAME COLUMN `last_login` TO `last_login_at`",
            "ALTER TABLE `email` ADD CONSTRAINT `fk_email_user_5b58673d` FOREIGN KEY "
            "(`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE",
        ]
    elif isinstance(Migrate.ddl, PostgresDDL):
        assert Migrate.upgrade_operators == [
            'ALTER TABLE "email" DROP CONSTRAINT "fk_email_user_5b58673d"',
            'ALTER TABLE "category" ADD "name" VARCHAR(200) NOT NULL',
            'ALTER TABLE "user" ADD CONSTRAINT "uid_user_usernam_9987ab" UNIQUE ("username")',
            'ALTER TABLE "user" RENAME COLUMN "last_login_at" TO "last_login"',
        ]
        assert Migrate.downgrade_operators == [
            'ALTER TABLE "category" DROP COLUMN "name"',
            'ALTER TABLE "user" DROP CONSTRAINT "uid_user_usernam_9987ab"',
            'ALTER TABLE "user" RENAME COLUMN "last_login" TO "last_login_at"',
            'ALTER TABLE "email" ADD CONSTRAINT "fk_email_user_5b58673d" FOREIGN KEY ("user_id") REFERENCES "user" ("id") ON DELETE CASCADE',
        ]
    elif isinstance(Migrate.ddl, SqliteDDL):
        assert Migrate.upgrade_operators == [
            'ALTER TABLE "email" DROP FOREIGN KEY "fk_email_user_5b58673d"',
            'ALTER TABLE "category" ADD "name" VARCHAR(200) NOT NULL',
            'ALTER TABLE "user" ADD UNIQUE INDEX "uid_user_usernam_9987ab" ("username")',
            'ALTER TABLE "user" RENAME COLUMN "last_login_at" TO "last_login"',
        ]
        assert Migrate.downgrade_operators == []
Beispiel #13
0
def test_migrate():
    apps = Tortoise.apps
    models = apps.get("models")
    diff_models = apps.get("diff_models")
    Migrate.diff_models(diff_models, models)
    Migrate.diff_models(models, diff_models, False)
    if isinstance(Migrate.ddl, MysqlDDL):
        assert Migrate.upgrade_operators == [
            "ALTER TABLE `category` ADD `name` VARCHAR(200) NOT NULL",
            "ALTER TABLE `user` ADD UNIQUE INDEX `uid_user_usernam_9987ab` (`username`)",
        ]
        assert Migrate.downgrade_operators == [
            "ALTER TABLE `category` DROP COLUMN `name`",
            "ALTER TABLE `user` DROP INDEX `uid_user_usernam_9987ab`",
        ]
    else:
        assert Migrate.upgrade_operators == [
            'ALTER TABLE "category" ADD "name" VARCHAR(200) NOT NULL',
            'ALTER TABLE "user" ADD UNIQUE INDEX "uid_user_usernam_9987ab" ("username")',
        ]
        assert Migrate.downgrade_operators == [
            'ALTER TABLE "category" DROP COLUMN "name"',
            'ALTER TABLE "user" DROP INDEX "uid_user_usernam_9987ab"',
        ]
Beispiel #14
0
async def upgrade(ctx: Context):
    config = ctx.obj["config"]
    app = ctx.obj["app"]
    migrated = False
    for version in Migrate.get_all_version_files():
        if not await Aerich.exists(version=version, app=app):
            async with in_transaction(get_app_connection_name(config, app)) as conn:
                file_path = os.path.join(Migrate.migrate_location, version)
                with open(file_path, "r") as f:
                    content = json.load(f)
                    upgrade_query_list = content.get("upgrade")
                    for upgrade_query in upgrade_query_list:
                        await conn.execute_query(upgrade_query)
            await Aerich.create(version=version, app=app)
            click.secho(f"Success upgrade {version}", fg=Color.green)
            migrated = True
    if not migrated:
        click.secho("No migrate items", fg=Color.yellow)
Beispiel #15
0
async def upgrade(ctx: Context):
    app = ctx.obj["app"]
    config = ctx.obj["config"]
    available_versions = Migrate.get_all_version_files(is_all=False)
    if not available_versions:
        return click.secho("No migrate items", fg=Color.yellow)
    async with in_transaction(get_app_connection_name(config, app)) as conn:
        for file in available_versions:
            file_path = os.path.join(Migrate.migrate_location, file)
            with open(file_path, "r") as f:
                content = json.load(f)
                upgrade_query_list = content.get("upgrade")
                for upgrade_query in upgrade_query_list:
                    await conn.execute_query(upgrade_query)

            with open(file_path, "w") as f:
                content["migrate"] = True
                json.dump(content, f, indent=2, ensure_ascii=False)
                click.secho(f"Success upgrade {file}", fg=Color.green)
Beispiel #16
0
def test_sort_all_version_files(mocker):
    mocker.patch(
        "os.listdir",
        return_value=[
            "1_datetime_update.sql",
            "11_datetime_update.sql",
            "10_datetime_update.sql",
            "2_datetime_update.sql",
        ],
    )

    Migrate.migrate_location = "."

    assert Migrate.get_all_version_files() == [
        "1_datetime_update.sql",
        "2_datetime_update.sql",
        "10_datetime_update.sql",
        "11_datetime_update.sql",
    ]
Beispiel #17
0
async def upgrade(ctx: Context):
    """Upgrade to latest version."""
    app, config, location = await connect_tortoise(ctx)
    migrated = False
    for version in Migrate.get_all_version_files():
        try:
            exists = await Aerich.exists(version=version, app=app)
        except OperationalError:
            exists = False
        if not exists:
            async with in_transaction(get_app_connection_name(config, app)) as conn:
                file_path = os.path.join(Migrate.migrate_location, version)
                with open(file_path, "r", encoding="utf-8") as f:
                    content = json.load(f)
                    upgrade_query_list = content.get("upgrade")
                    for upgrade_query in upgrade_query_list:
                        await conn.execute_script(upgrade_query)
                await Aerich.create(version=version, app=app)
            typer.secho(f"Success upgrade {version}", fg=typer.colors.GREEN)
            migrated = True
    if not migrated:
        typer.secho("No migrate items", fg=typer.colors.YELLOW)
Beispiel #18
0
 async def upgrade(self):
     migrated = []
     for version_file in Migrate.get_all_version_files():
         try:
             exists = await Aerich.exists(version=version_file,
                                          app=self.app)
         except OperationalError:
             exists = False
         if not exists:
             async with in_transaction(
                     get_app_connection_name(self.tortoise_config,
                                             self.app)) as conn:
                 file_path = Path(Migrate.migrate_location, version_file)
                 content = get_version_content_from_file(file_path)
                 upgrade_query_list = content.get("upgrade")
                 for upgrade_query in upgrade_query_list:
                     await conn.execute_script(upgrade_query)
                 await Aerich.create(
                     version=version_file,
                     app=self.app,
                     content=get_models_describe(self.app),
                 )
             migrated.append(version_file)
     return migrated
Beispiel #19
0
 async def test_migrate(self):
     Migrate.diff_model(
         Tortoise.apps.get("models").get("Category"),
         Tortoise.apps.get("diff_models").get("Category"),
     )
     print(Migrate.upgrade_operators)
Beispiel #20
0
def heads(ctx: Context):
    for version in Migrate.get_all_version_files(is_all=False):
        click.secho(version, fg=Color.green)
Beispiel #21
0
def test_migrate(mocker: MockerFixture):
    """
    models.py diff with old_models.py
    - change email pk: id -> email_id
    - add field: Email.address
    - add fk: Config.user
    - drop fk: Email.user
    - drop field: User.avatar
    - add index: Email.email
    - add many to many: Email.users
    - remove unique: User.username
    - change column: length User.password
    - add unique_together: (name,type) of Product
    - alter default: Config.status
    - rename column: Product.image -> Product.pic
    """
    mocker.patch("click.prompt", side_effect=(False, True))

    models_describe = get_models_describe("models")
    Migrate.app = "models"
    if isinstance(Migrate.ddl, SqliteDDL):
        with pytest.raises(NotSupportError):
            Migrate.diff_models(old_models_describe, models_describe)
            Migrate.diff_models(models_describe, old_models_describe, False)
    else:
        Migrate.diff_models(old_models_describe, models_describe)
        Migrate.diff_models(models_describe, old_models_describe, False)
    Migrate._merge_operators()
    if isinstance(Migrate.ddl, MysqlDDL):
        assert sorted(Migrate.upgrade_operators) == sorted(
            [
                "ALTER TABLE `category` MODIFY COLUMN `name` VARCHAR(200)",
                "ALTER TABLE `category` MODIFY COLUMN `slug` VARCHAR(100) NOT NULL",
                "ALTER TABLE `config` ADD `user_id` INT NOT NULL  COMMENT 'User'",
                "ALTER TABLE `config` ADD CONSTRAINT `fk_config_user_17daa970` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE",
                "ALTER TABLE `config` ALTER COLUMN `status` DROP DEFAULT",
                "ALTER TABLE `email` ADD `address` VARCHAR(200) NOT NULL",
                "ALTER TABLE `email` DROP COLUMN `user_id`",
                "ALTER TABLE `product` RENAME COLUMN `image` TO `pic`",
                "ALTER TABLE `email` RENAME COLUMN `id` TO `email_id`",
                "ALTER TABLE `email` DROP FOREIGN KEY `fk_email_user_5b58673d`",
                "ALTER TABLE `email` ADD INDEX `idx_email_email_4a1a33` (`email`)",
                "ALTER TABLE `product` ADD UNIQUE INDEX `uid_product_name_f14935` (`name`, `type`)",
                "ALTER TABLE `product` ALTER COLUMN `view_num` SET DEFAULT 0",
                "ALTER TABLE `user` DROP COLUMN `avatar`",
                "ALTER TABLE `user` MODIFY COLUMN `password` VARCHAR(100) NOT NULL",
                "ALTER TABLE `user` MODIFY COLUMN `username` VARCHAR(20) NOT NULL",
                "CREATE TABLE IF NOT EXISTS `newmodel` (\n    `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,\n    `name` VARCHAR(50) NOT NULL\n) CHARACTER SET utf8mb4;",
                "ALTER TABLE `user` ADD UNIQUE INDEX `uid_user_usernam_9987ab` (`username`)",
                "CREATE TABLE `email_user` (`email_id` INT NOT NULL REFERENCES `email` (`email_id`) ON DELETE CASCADE,`user_id` INT NOT NULL REFERENCES `user` (`id`) ON DELETE CASCADE) CHARACTER SET utf8mb4",
            ]
        )

        assert sorted(Migrate.downgrade_operators) == sorted(
            [
                "ALTER TABLE `category` MODIFY COLUMN `name` VARCHAR(200) NOT NULL",
                "ALTER TABLE `category` MODIFY COLUMN `slug` VARCHAR(200) NOT NULL",
                "ALTER TABLE `config` DROP COLUMN `user_id`",
                "ALTER TABLE `config` DROP FOREIGN KEY `fk_config_user_17daa970`",
                "ALTER TABLE `config` ALTER COLUMN `status` SET DEFAULT 1",
                "ALTER TABLE `email` ADD `user_id` INT NOT NULL",
                "ALTER TABLE `email` DROP COLUMN `address`",
                "ALTER TABLE `product` RENAME COLUMN `pic` TO `image`",
                "ALTER TABLE `email` RENAME COLUMN `email_id` TO `id`",
                "ALTER TABLE `email` ADD CONSTRAINT `fk_email_user_5b58673d` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE",
                "ALTER TABLE `email` DROP INDEX `idx_email_email_4a1a33`",
                "ALTER TABLE `product` DROP INDEX `uid_product_name_f14935`",
                "ALTER TABLE `product` ALTER COLUMN `view_num` DROP DEFAULT",
                "ALTER TABLE `user` ADD `avatar` VARCHAR(200) NOT NULL  DEFAULT ''",
                "ALTER TABLE `user` DROP INDEX `idx_user_usernam_9987ab`",
                "ALTER TABLE `user` MODIFY COLUMN `password` VARCHAR(200) NOT NULL",
                "ALTER TABLE `user` MODIFY COLUMN `username` VARCHAR(20) NOT NULL",
                "DROP TABLE IF EXISTS `email_user`",
                "DROP TABLE IF EXISTS `newmodel`",
            ]
        )

    elif isinstance(Migrate.ddl, PostgresDDL):
        assert sorted(Migrate.upgrade_operators) == sorted(
            [
                'ALTER TABLE "category" ALTER COLUMN "name" TYPE VARCHAR(200)',
                'ALTER TABLE "category" ALTER COLUMN "slug" TYPE VARCHAR(100)',
                'ALTER TABLE "config" ADD "user_id" INT NOT NULL',
                'ALTER TABLE "config" ADD CONSTRAINT "fk_config_user_17daa970" FOREIGN KEY ("user_id") REFERENCES "user" ("id") ON DELETE CASCADE',
                'ALTER TABLE "config" ALTER COLUMN "status" DROP DEFAULT',
                'ALTER TABLE "email" ADD "address" VARCHAR(200) NOT NULL',
                'ALTER TABLE "email" DROP COLUMN "user_id"',
                'ALTER TABLE "product" RENAME COLUMN "image" TO "pic"',
                'ALTER TABLE "email" RENAME COLUMN "id" TO "email_id"',
                'ALTER TABLE "email" DROP CONSTRAINT "fk_email_user_5b58673d"',
                'CREATE INDEX "idx_email_email_4a1a33" ON "email" ("email")',
                'ALTER TABLE "user" ALTER COLUMN "username" TYPE VARCHAR(20)',
                'CREATE UNIQUE INDEX "uid_product_name_f14935" ON "product" ("name", "type")',
                'ALTER TABLE "product" ALTER COLUMN "view_num" SET DEFAULT 0',
                'ALTER TABLE "user" DROP COLUMN "avatar"',
                'ALTER TABLE "user" ALTER COLUMN "password" TYPE VARCHAR(100)',
                'CREATE TABLE IF NOT EXISTS "newmodel" (\n    "id" SERIAL NOT NULL PRIMARY KEY,\n    "name" VARCHAR(50) NOT NULL\n);\nCOMMENT ON COLUMN "config"."user_id" IS \'User\';',
                'CREATE UNIQUE INDEX "uid_user_usernam_9987ab" ON "user" ("username")',
                'CREATE TABLE "email_user" ("email_id" INT NOT NULL REFERENCES "email" ("email_id") ON DELETE CASCADE,"user_id" INT NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE)',
            ]
        )
        assert sorted(Migrate.downgrade_operators) == sorted(
            [
                'ALTER TABLE "category" ALTER COLUMN "name" TYPE VARCHAR(200)',
                'ALTER TABLE "category" ALTER COLUMN "slug" TYPE VARCHAR(200)',
                'ALTER TABLE "user" ALTER COLUMN "password" TYPE VARCHAR(200)',
                'ALTER TABLE "user" ALTER COLUMN "username" TYPE VARCHAR(20)',
                'ALTER TABLE "config" DROP COLUMN "user_id"',
                'ALTER TABLE "config" DROP CONSTRAINT "fk_config_user_17daa970"',
                'ALTER TABLE "config" ALTER COLUMN "status" SET DEFAULT 1',
                'ALTER TABLE "email" ADD "user_id" INT NOT NULL',
                'ALTER TABLE "email" DROP COLUMN "address"',
                'ALTER TABLE "product" RENAME COLUMN "pic" TO "image"',
                'ALTER TABLE "email" RENAME COLUMN "email_id" TO "id"',
                'ALTER TABLE "email" ADD CONSTRAINT "fk_email_user_5b58673d" FOREIGN KEY ("user_id") REFERENCES "user" ("id") ON DELETE CASCADE',
                'DROP INDEX "idx_email_email_4a1a33"',
                'ALTER TABLE "product" ALTER COLUMN "view_num" DROP DEFAULT',
                'ALTER TABLE "user" ADD "avatar" VARCHAR(200) NOT NULL  DEFAULT \'\'',
                'DROP INDEX "idx_user_usernam_9987ab"',
                'DROP INDEX "uid_product_name_f14935"',
                'DROP TABLE IF EXISTS "email_user"',
                'DROP TABLE IF EXISTS "newmodel"',
            ]
        )
    elif isinstance(Migrate.ddl, SqliteDDL):
        assert Migrate.upgrade_operators == []

        assert Migrate.downgrade_operators == []
Beispiel #22
0
async def history(ctx: Context):
    versions = Migrate.get_all_version_files()
    for version in versions:
        click.secho(version, fg=Color.green)
    if not versions:
        click.secho("No history,try migrate", fg=Color.green)
Beispiel #23
0
def history(ctx):
    for version in Migrate.get_all_version_files():
        click.secho(version, fg=Color.green)
Beispiel #24
0
 async def history(self):
     ret = []
     versions = Migrate.get_all_version_files()
     for version in versions:
         ret.append(version)
     return ret