예제 #1
0
def test_build_migration_plan_unknown_version(known_versions):
    settings = configuration.Settings(
        target_version=Version.from_string("1.5"))
    from_version = Version.from_string("0")

    with pytest.raises(ValueError):
        list(core.build_migration_plan(settings, from_version=from_version))
예제 #2
0
def migrate(settings: configuration.Settings,
            stylist: style.Stylist = style.noop_stylist) -> None:

    logger.info("Starting migrations")

    if not db.is_schema_initialized(settings=settings):
        logger.info("Migration table is empty, loading a schema")
        # schema not inited
        schema_version = core.get_best_schema_version(settings=settings)
        init_schema(settings=settings,
                    init_version=schema_version,
                    stylist=stylist)
        from_version = schema_version
    else:
        _from_version = db.get_current_schema_version(settings=settings)
        assert _from_version  # mypy shenanigans
        from_version = _from_version

    # play migrations
    with stylist.activate("title") as echo:
        echo("Applying migrations")

    for plan in core.build_migration_plan(settings=settings,
                                          from_version=from_version):
        version = plan["version"]
        logger.info("Processing version %s", version)
        with stylist.activate("subtitle") as echo:
            echo("Version {}".format(version))
        for mig, applied, path, is_manual in plan["plan"]:
            logger.debug(
                "Processing migration %(mig)s, applied: %(applied)s, "
                "path: %(path)s, manual: %(is_manual)s",
                {
                    "mig": mig,
                    "applied": applied,
                    "path": path,
                    "is_manual": is_manual
                },
            )
            title = mig
            if is_manual:
                title += " (manual)"
            title += " "
            if applied:
                stylist.draw_checkbox(checked=True, content="Already applied")
                stylist.echo("")  # new line
            else:
                with stylist.checkbox(
                        content="Applying {}...".format(title),
                        content_after="Applied {}".format(title),
                ):
                    run_script(settings=settings, path=path)
                    logger.info("Saving operation in the database")
                    db.write_migration(settings=settings,
                                       version=version,
                                       name=mig)
예제 #3
0
def test_build_migration_plan_with_schema(mocker, known_versions):
    mocker.patch("septentrion.core.db.get_applied_migrations", return_value=[])
    settings = configuration.Settings(target_version="1.2")
    from_version = Version.from_string("1.1")

    plan = list(
        core.build_migration_plan(settings=settings,
                                  from_version=from_version))

    expected = [
        {
            "plan": [],
            "version": Version.from_string("1.1")
        },
        {
            "plan": [],
            "version": Version.from_string("1.2")
        },
    ]
    assert list(plan) == expected
예제 #4
0
def test_build_migration_plan_db(mocker, known_versions):
    # What a mock hell ><

    # So first, we mock db.get_applied_migrations to tell the following story:
    # - on 1.1, only migration "a" was previously applied.
    # - on 1.2, no migration was previously applied.
    mocker.patch(
        "septentrion.db.get_applied_migrations",
        side_effect=lambda settings, version: {
            Version.from_string("1.1"): ["a"],
            Version.from_string("1.2"): [],
        }[version],
    )
    # Then, regarding the migration files that exist on the disk:
    # - There are 2 files for 1.1 (so one already applied and one new)
    # - 1 file for 1.2
    # - 1 file for 1.3
    mocker.patch(
        "septentrion.files.get_migrations_files_mapping",
        side_effect=lambda settings, version: {
            Version.from_string("1.1"): {
                "a": pathlib.Path("a"),
                "b": pathlib.Path("b"),
            },
            Version.from_string("1.2"): {
                "c": pathlib.Path("c"),
            },
            Version.from_string("1.3"): {
                "d": pathlib.Path("d")
            },
        }[version],
    )
    # The contents of each migration is ignored
    mocker.patch("septentrion.files.file_lines_generator", return_value="")
    # Migration "c" is a manual migration
    mocker.patch(
        "septentrion.files.is_manual_migration",
        side_effect=(lambda migration_path, migration_contents: str(
            migration_path) == "c"),
    )
    # We'll apply migrations up until 1.2 included
    settings = configuration.Settings(
        target_version=Version.from_string("1.2"), )
    # And we'll start at version 1.1 included
    from_version = Version.from_string("1.1")
    plan = core.build_migration_plan(settings=settings,
                                     from_version=from_version)

    expected = [
        {
            "version":
            Version.from_string("1.1"),
            "plan": [
                # On 1.1, migration a is already applied. It's not manual
                ("a", True, pathlib.Path("a"), False),
                # migration b, though needs to be applied. It's not manual
                ("b", False, pathlib.Path("b"), False),
            ],
        },
        {
            "version":
            Version.from_string("1.2"),
            "plan": [
                # migration c also needs to be applied. It's manual (the last True)
                ("c", False, pathlib.Path("c"), True),
            ],
        },
    ]

    assert list(plan) == expected
예제 #5
0
def build_migration_plan(**settings_kwargs):
    lib_kwargs = initialize(settings_kwargs)
    schema_version = core.get_best_schema_version(
        settings=lib_kwargs["settings"])
    return core.build_migration_plan(settings=lib_kwargs["settings"],
                                     from_version=schema_version)