Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/61 alembic seed lookup tables #65

Merged
merged 12 commits into from
Dec 15, 2023
58 changes: 58 additions & 0 deletions db_revisions/feed/address_state.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
code|name
AL|Alabama
AK|Alaska
AZ|Arizona
AR|Arkansas
CA|California
CO|Colorado
CT|Connecticut
DE|Delaware
FL|Florida
GA|Georgia
HI|Hawaii
ID|Idaho
IL|Illinois
IN|Indiana
IA|Iowa
KS|Kansas
KY|Kentucky
LA|Louisiana
ME|Maine
MD|Maryland
MA|Massachusetts
MI|Michigan
MN|Minnesota
MS|Mississippi
MO|Missouri
MT|Montana
NE|Nebraska
NV|Nevada
NH|New Hampshire
NJ|New Jersey
NM|New Mexico
NY|New York
NC|North Carolina
ND|North Dakota
OH|Ohio
OK|Oklahoma
OR|Oregon
PA|Pennsylvania
RI|Rhode Island
SC|South Carolina
SD|South Dakota
TN|Tennessee
TX|Texas
UT|Utah
VT|Vermont
VA|Virginia
WA|Washington
WV|West Virginia
WI|Wisconsin
WY|Wyoming
DC|District of Columbia
AS|American Samoa
GU|Guam
MP|Northern Mariana Islands
PR|Puerto Rico
UM|United States Minor Outlying Islands
VI|Virgin Islands, U.S.
8 changes: 8 additions & 0 deletions db_revisions/feed/federal_regulator.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
id|name
FCA|Farm Credit Administration
FDIC|Federal Deposit Insurance Corporation
FHFA|Federal Housing Finance Agency
FRS|Federal Reserve System
NCUA|National Credit Union Administration
OCC|Office of the Comptroller of the Currency
OTS|Office of Thrift Supervision (only valid until July 21, 2011)
19 changes: 19 additions & 0 deletions db_revisions/feed/hmda_institution_type.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
id|name
1|National Bank (OCC supervised)
2|State Member Bank (FRS Supervised):
3|State non-member bank (FDIC supervised)
4|State Chartered Thrift (FDIC supervised)
5|Federal Chartered Thrift (OCC supervised)
6|Credit Union (NCUA supervised)
7|Federal Branch or Agency of Foreign Banking Organization (FBO)
8|Branch or Agency of FBO (FRS supervised)
9|MBS of national Bank (OCC supervised)
10|MBS of state member bank (FRS supervised)
11|MBS of state non-member bank (FDIC supervised)
12|MBS of Bank Holding Company (BHC) (FRS supervised)
13|MBS of credit union (NCUA supervised)
14|independent MBS, no depository affiliation
15|MBS of Savings and Loan Holding Co
16|MBS of state chartered Thrift
17|MBS of federally chartered thrift (OCC supervised)
18|Affiliate of depository institution. MBS is in the same ownership org as a depository.
14 changes: 14 additions & 0 deletions db_revisions/feed/sbl_institution_type.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
id|name
1|Bank or savings association.
2|Minority depository institution.
3|Credit union.
4|Nondepository institution.
5|Community development financial institution (CDFI).
6|Other nonprofit financial institution.
7|Farm Credit System institution.
8|Government lender.
9|Commercial finance company.
10|Equipment finance company.
11|Industrial loan company.
12|Online lender.
13|Other
13 changes: 13 additions & 0 deletions db_revisions/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from alembic import op
from sqlalchemy import engine_from_config
import sqlalchemy
from csv import DictReader
import os


def table_exists(table_name):
Expand All @@ -11,3 +13,14 @@ def table_exists(table_name):
inspector = sqlalchemy.inspect(engine)
tables = inspector.get_table_names()
return table_name in tables


def get_feed_data_from_file(table_name):
file_dir = os.path.dirname(os.path.realpath(__file__))
data_file_path = f"{file_dir}/feed/%s.csv" % table_name
data_file = open(data_file_path, "r")
reader = DictReader(data_file, delimiter="|")
output_list = list()
for dictionary in reader:
output_list.append(dictionary)
return output_list
28 changes: 28 additions & 0 deletions db_revisions/versions/26a742d97ad9_feed_federal_regulator_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Feed Federal Regulator table

Revision ID: 26a742d97ad9
Revises: 7b6ff51002b5
Create Date: 2023-12-14 01:23:17.872728

"""
from typing import Sequence, Union
from alembic import op
from db_revisions.utils import get_feed_data_from_file
from entities.models import FederalRegulatorDao


# revision identifiers, used by Alembic.
revision: str = "26a742d97ad9"
down_revision: Union[str, None] = "7b6ff51002b5"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
data = get_feed_data_from_file(FederalRegulatorDao.__tablename__)

op.bulk_insert(FederalRegulatorDao.__table__, data)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mentioned in chat, but let's use the actual table names here and the other scripts, instead of relying on the dao property so that in a rare case should there actually be a change in the table name for the dao there is a history, and there wouldn't be conflicts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure



def downgrade() -> None:
op.execute(FederalRegulatorDao.__table__.delete())
28 changes: 28 additions & 0 deletions db_revisions/versions/7b6ff51002b5_feed_address_state_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Feed Address State table

Revision ID: 7b6ff51002b5
Revises: 045aa502e050
Create Date: 2023-12-14 01:21:48.325752

"""
from typing import Sequence, Union
from alembic import op
from db_revisions.utils import get_feed_data_from_file
from entities.models import AddressStateDao


# revision identifiers, used by Alembic.
revision: str = "7b6ff51002b5"
down_revision: Union[str, None] = "045aa502e050"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
data = get_feed_data_from_file(AddressStateDao.__tablename__)

op.bulk_insert(AddressStateDao.__table__, data)


def downgrade() -> None:
op.execute(AddressStateDao.__table__.delete())
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Feed SBL Institution Type table

Revision ID: a41281b1e109
Revises: f4ff7d1aa6df
Create Date: 2023-12-14 01:24:00.120073

"""
from typing import Sequence, Union
from alembic import op
from db_revisions.utils import get_feed_data_from_file
from entities.models import SBLInstitutionTypeDao

# revision identifiers, used by Alembic.
revision: str = "a41281b1e109"
down_revision: Union[str, None] = "f4ff7d1aa6df"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
data = get_feed_data_from_file(SBLInstitutionTypeDao.__tablename__)

op.bulk_insert(SBLInstitutionTypeDao.__table__, data)


def downgrade() -> None:
op.execute(SBLInstitutionTypeDao.__table__.delete())
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Feed HMDA Institution Type table

Revision ID: f4ff7d1aa6df
Revises: 26a742d97ad9
Create Date: 2023-12-14 01:23:47.017878

"""
from typing import Sequence, Union
from alembic import op
from db_revisions.utils import get_feed_data_from_file
from entities.models import HMDAInstitutionTypeDao


# revision identifiers, used by Alembic.
revision: str = "f4ff7d1aa6df"
down_revision: Union[str, None] = "26a742d97ad9"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
data = get_feed_data_from_file(HMDAInstitutionTypeDao.__tablename__)

op.bulk_insert(HMDAInstitutionTypeDao.__table__, data)


def downgrade() -> None:
op.execute(HMDAInstitutionTypeDao.__table__.delete())
70 changes: 70 additions & 0 deletions tests/migrations/test_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
)

import sqlalchemy
from sqlalchemy import text
from sqlalchemy.engine import Engine
import os
import csv
from entities.models import AddressStateDao, FederalRegulatorDao, HMDAInstitutionTypeDao, SBLInstitutionTypeDao

from pytest_alembic import MigrationContext

Expand All @@ -22,3 +26,69 @@ def test_tables_exist_after_migration(alembic_runner: MigrationContext, alembic_
assert "federal_regulator" in tables
assert "hmda_institution_type" in tables
assert "sbl_institution_type" in tables


def data_feed_migration_helper(table_name):
file_dir = os.path.dirname(os.path.realpath(__file__))
data_file_path = f"{file_dir}/../../db_revisions/feed/%s.csv" % table_name
with open(data_file_path) as f:
reader = csv.reader(f, delimiter="|")
next(reader)
output_list = list(tuple(line) for line in reader)
return output_list


def test_address_state_data_feed(alembic_runner: MigrationContext, alembic_engine: Engine):
# Migrate up to, but not including this new migration
alembic_runner.migrate_up_before("7b6ff51002b5")

# Test address_state feed
address_state_tablename = AddressStateDao.__tablename__
alembic_runner.migrate_up_one()
with alembic_engine.connect() as conn:
address_state_rows = conn.execute(text("SELECT code, name from %s" % address_state_tablename)).fetchall()
address_state_expected = data_feed_migration_helper(address_state_tablename)
assert address_state_rows == address_state_expected


def test_federal_regulator_data_feed(alembic_runner: MigrationContext, alembic_engine: Engine):
# Migrate up to, but not including this new migration
alembic_runner.migrate_up_before("26a742d97ad9")

# Test federal_regulator feed
federal_regulator_tablename = FederalRegulatorDao.__tablename__
alembic_runner.migrate_up_one()
with alembic_engine.connect() as conn:
federal_regulator_rows = conn.execute(text("SELECT id, name from %s" % federal_regulator_tablename)).fetchall()
federal_regulator_expected = data_feed_migration_helper(federal_regulator_tablename)
assert federal_regulator_rows == federal_regulator_expected


def test_hmda_institution_type_data_feed(alembic_runner: MigrationContext, alembic_engine: Engine):
# Migrate up to, but not including this new migration
alembic_runner.migrate_up_before("f4ff7d1aa6df")

# Test hmda_institution_type feed
hmda_institution_type_tablename = HMDAInstitutionTypeDao.__tablename__
alembic_runner.migrate_up_one()
with alembic_engine.connect() as conn:
hmda_institution_type_rows = conn.execute(
text("SELECT id, name from %s" % hmda_institution_type_tablename)
).fetchall()
hmda_institution_type_expected = data_feed_migration_helper(hmda_institution_type_tablename)
assert hmda_institution_type_rows == hmda_institution_type_expected


def test_sbl_institution_type_data_feed(alembic_runner: MigrationContext, alembic_engine: Engine):
# Migrate up to, but not including this new migration
alembic_runner.migrate_up_before("a41281b1e109")

# Test sbl_institution_type feed
sbl_institution_type_tablename = SBLInstitutionTypeDao.__tablename__
alembic_runner.migrate_up_one()
with alembic_engine.connect() as conn:
sbl_institution_type_rows = conn.execute(
text("SELECT id, name from %s" % sbl_institution_type_tablename)
).fetchall()
sbl_institution_type_expected = data_feed_migration_helper(sbl_institution_type_tablename)
assert sbl_institution_type_rows == sbl_institution_type_expected
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, a couple of things, let's move the new tests into a separate file, and name it something that relates to seeding the tables; the other thing is I don't think you need to have actual sql statement in here to check the results; you should be able to leverage sqlalchemy's orm retrieval for all the statements

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working on it ...

Loading