<commit_before># -*- coding: utf-8 -*-

import os
import pytest
import subprocess

from alembic.config import Config as AlembicConfig
from alembic.script import ScriptDirectory
from os import path
from sqlalchemy import text

from db import db
from journalist_app import create_app

MIGRATION_PATH = path.join(path.dirname(__file__), '..', 'alembic', 'versions')

ALL_MIGRATIONS = [x.split('.')[0].split('_')[0]
                  for x in os.listdir(MIGRATION_PATH)
                  if x.endswith('.py')]


def list_migrations(cfg_path, head):
    cfg = AlembicConfig(cfg_path)
    script = ScriptDirectory.from_config(cfg)
    migrations = [x.revision
                  for x in script.walk_revisions(base='base', head=head)]
    migrations.reverse()
    return migrations


def upgrade(alembic_config, migration):
    subprocess.check_call(['alembic', 'upgrade', migration],
                          cwd=path.dirname(alembic_config))


def downgrade(alembic_config, migration):
    subprocess.check_call(['alembic', 'downgrade', migration],
                          cwd=path.dirname(alembic_config))


def get_schema(app):
    with app.app_context():
        return list(db.engine.execute(text('''
            SELECT type, name, tbl_name, sql
            FROM sqlite_master
            ORDER BY type, name, tbl_name
            ''')))


@pytest.mark.parametrize('migration', ALL_MIGRATIONS)
def test_alembic_migration_upgrade(alembic_config, config, migration):
    # run migrations in sequence from base -> head
    for mig in list_migrations(alembic_config, migration):
        upgrade(alembic_config, mig)


@pytest.mark.parametrize('migration', ALL_MIGRATIONS)
def test_alembic_migration_downgrade(alembic_config, config, migration):
    # upgrade to the parameterized test case ("head")
    upgrade(alembic_config, migration)

    # run migrations in sequence from "head" -> base
    migrations = list_migrations(alembic_config, migration)
    migrations.reverse()

    for mig in migrations:
        downgrade(alembic_config, mig)


@pytest.mark.parametrize('migration', ALL_MIGRATIONS)
def test_schema_unchanged_after_up_then_downgrade(alembic_config,
                                                  config,
                                                  migration):
    # Create the app here. Using a fixture will init the database.<commit_msg>added test to ensure alembic and models are synchronized<commit_after># -*- coding: utf-8 -*-

import os
import pytest
import subprocess

from alembic.config import Config as AlembicConfig
from alembic.script import ScriptDirectory
from os import path
from sqlalchemy import text

import conftest

from db import db
from journalist_app import create_app

MIGRATION_PATH = path.join(path.dirname(__file__), '..', 'alembic', 'versions')

ALL_MIGRATIONS = [x.split('.')[0].split('_')[0]
                  for x in os.listdir(MIGRATION_PATH)
                  if x.endswith('.py')]


def list_migrations(cfg_path, head):
    cfg = AlembicConfig(cfg_path)
    script = ScriptDirectory.from_config(cfg)
    migrations = [x.revision
                  for x in script.walk_revisions(base='base', head=head)]
    migrations.reverse()
    return migrations


def upgrade(alembic_config, migration):
    subprocess.check_call(['alembic', 'upgrade', migration],
                          cwd=path.dirname(alembic_config))


def downgrade(alembic_config, migration):
    subprocess.check_call(['alembic', 'downgrade', migration],
                          cwd=path.dirname(alembic_config))


def get_schema(app):
    with app.app_context():
        return list(db.engine.execute(text('''
            SELECT type, name, tbl_name, sql
            FROM sqlite_master
            ORDER BY type, name, tbl_name
            ''')))


def test_alembic_head_matches_db_models(journalist_app,
                                        alembic_config,
                                        config):
    '''This test is to make sure that our database models in `models.py` are
       always in sync with the schema generated by `alembic upgrade head`.
    '''
    models_schema = get_schema(journalist_app)

    config.DATABASE_FILE = config.DATABASE_FILE + '.new'
    # Use the fixture to rewrite the config with the new URI
    conftest.alembic_config(config)

    # Create database file
    subprocess.check_call(['sqlite3', config.DATABASE_FILE, '.databases'])
    upgrade(alembic_config, 'head')

    # Recreate the app to get a new SQLALCHEMY_DATABASE_URI
    app = create_app(config)
    alembic_schema = get_schema(app)

    # The initial migration creates the table 'alembic_version', but this is
    # not present in the schema created by `db.create_all()`.
    alembic_schema = list(filter(lambda x: x[2] != 'alembic_version',
                                 alembic_schema))

    assert alembic_schema == models_schema


@pytest.mark.parametrize('migration', ALL_MIGRATIONS)
def test_alembic_migration_upgrade(alembic_config, config, migration):
    # run migrations in sequence from base -> head
    for mig in list_migrations(alembic_config, migration):
        upgrade(alembic_config, mig)


@pytest.mark.parametrize('migration', ALL_MIGRATIONS)
def test_alembic_migration_downgrade(alembic_config, config, migration):
    # upgrade to the parameterized test case ("head")
    upgrade(alembic_config, migration)

    # run migrations in sequence from "head" -> base
    migrations = list_migrations(alembic_config, migration)
    migrations.reverse()

    for mig in migrations:
        downgrade(alembic_config, mig)


@pytest.mark.parametrize('migration', ALL_MIGRATIONS)
def test_schema_unchanged_after_up_then_downgrade(alembic_config,
                                                  config,
                                                  migration):
    # Create the app here. Using a fixture will init the database.
{'fraction_non_alphanumeric': 0.09134206497703691, 'fraction_numerical': 0.001360775642116006, 'mean_word_length': 2.941018766756032, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3200857', 'n_tokens_mistral': 1762, 'n_tokens_neox': 1739, 'n_words': 431}