Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Feat/climsoft models #28

Merged
merged 7 commits into from
Sep 11, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,4 @@ ENV/
# IDE settings
.vscode/
.idea/
shaibu-activity.log
isedwards marked this conversation as resolved.
Show resolved Hide resolved
71 changes: 54 additions & 17 deletions opencdms/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from pprint import pprint
from typing import Callable, List, Optional, Sequence
from alembic import migration
from sqlalchemy import MetaData, create_engine
from sqlalchemy import MetaData, create_engine, Table, Index
from alembic.autogenerate import compare_metadata


def filter_ignored_tables(
def filter_out_excluded_tables(
tables: Sequence[str],
) -> Callable[[tuple], bool]:
""" Accept sequence of table names to be ignored when comparing model to\
Expand All @@ -23,10 +24,40 @@ def filter_func(item: tuple):
"""
Return true if item's table name not in `tables`
"""
operation: str = item[0]
if operation == "add_table":
_, table = item
return table.name not in tables
target_object = item[1]
if isinstance(target_object, Table):
return target_object.name not in tables
if isinstance(target_object, Index):
return target_object.table.name not in tables
return True

return filter_func


def filter_in_included_tables(
tables: Sequence[str],
) -> Callable[[tuple], bool]:
""" Accept sequence of table names to be included when comparing model to\
db schema
Parameters
-----
`tables`: Sequence[str]
Table names to be included, other tables not in this list would be ignored.

Return
------
`Callable[[tuple]], bool]`
"""

def filter_func(item: tuple):
"""
Return true if item's table name not in `tables`
"""
target_object = item[1]
if isinstance(target_object, Table):
return target_object.name in tables
if isinstance(target_object, Index):
return target_object.table.name in tables
return True

return filter_func
Expand All @@ -35,7 +66,8 @@ def filter_func(item: tuple):
def get_schema_diff(
metadata: MetaData,
database_url: str,
ignore_tables: Optional[Sequence[str]] = None,
include_tables: Optional[Sequence[str]] = None,
exclude_tables: Optional[Sequence[str]] = None,
) -> List[tuple]:
"""
Parameters
Expand All @@ -44,7 +76,9 @@ def get_schema_diff(
Sqlalchemy Metadata
`database_url`:
Target databse url e.g. `sqlite://`
`ignore_tables`: Sequence[str] | None
`include_tables`: Sequence[str] | None
List of table names to check against the database
`exclude_tables`: Sequence[str] | None
List of table names to be ignored

Return
Expand All @@ -55,19 +89,22 @@ def get_schema_diff(
engine = create_engine(database_url)
mc = migration.MigrationContext.configure(engine.connect())
diff = compare_metadata(mc, metadata)
if ignore_tables is not None:
diff = list(filter(filter_ignored_tables(ignore_tables), diff))
if include_tables is not None and exclude_tables is not None:
raise Exception("`include_tables` and `exclude_tables` must not be used together") #TODO define custom error class
if exclude_tables is not None:
diff = list(filter(filter_out_excluded_tables(exclude_tables), diff))
if include_tables is not None:
diff = list(filter(filter_in_included_tables(include_tables), diff))
return list(diff)


# TODO remove and use automated tests instead.
isedwards marked this conversation as resolved.
Show resolved Hide resolved
if __name__ == "__main__":
from opencdms.models.clide import metadata, CLIDE_VIEWS

print(
get_schema_diff(
from opencdms.models.climsoft.v4_1_1_core import metadata, TARGET_TABLES
diff = get_schema_diff(
metadata,
"postgresql+psycopg2://localhost/clideDB",
ignore_tables=CLIDE_VIEWS,
"mysql://root:#Classicnerdswag1@localhost/mariadb_climsoft_db_v4",
include_tables=TARGET_TABLES
)
)
with open('output.txt', 'wt') as out:
pprint(diff, stream=out, indent=4)
Empty file.
Loading