Archive Project
# Conflicts: # .gitignore
This commit is contained in:
5
alembic_data/ops/__init__.py
Normal file
5
alembic_data/ops/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Operations used by Alembic-Data to create, update and delete objects."""
|
||||
|
||||
from .delete_row import *
|
||||
from .insert_row import *
|
||||
from .update_row import *
|
||||
54
alembic_data/ops/delete_row.py
Normal file
54
alembic_data/ops/delete_row.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from typing import Any, Mapping, List
|
||||
|
||||
import sqlalchemy
|
||||
from alembic.autogenerate import renderers
|
||||
from alembic.autogenerate.api import AutogenContext
|
||||
from alembic.operations import Operations, MigrateOperation
|
||||
from sqlalchemy import and_
|
||||
|
||||
__all__ = ["DeleteRowOp"]
|
||||
|
||||
from sqlalchemy.sql.elements import ColumnClause
|
||||
|
||||
|
||||
@Operations.register_operation("delete_row")
|
||||
class DeleteRowOp(MigrateOperation):
|
||||
"""This `MigrationOperation` deletes a rows from a database table."""
|
||||
|
||||
def __init__(self, table_name: str, **kwargs: Mapping[str, Any]) -> None:
|
||||
"""Creates a new `DeleteRowOp`.
|
||||
|
||||
:param table_name: The name of the table to delete the row from.
|
||||
:param kwargs: The values used to identify the exact row. Keys must correspond to column names in the table and
|
||||
values to their values.
|
||||
"""
|
||||
self.table_name = table_name
|
||||
self.values = kwargs
|
||||
|
||||
@classmethod
|
||||
def delete_row(cls, operations: Operations, table_name: str, **kwargs: Mapping[str, Any]):
|
||||
"""Factory method for `DeleteRowOp`."""
|
||||
op = DeleteRowOp(table_name, **kwargs)
|
||||
return operations.invoke(op)
|
||||
|
||||
def reverse(self) -> MigrateOperation:
|
||||
"""Reverses the insert row operation by inserting the respective row."""
|
||||
from .insert_row import InsertRowOp
|
||||
return InsertRowOp(self.table_name, **self.values)
|
||||
|
||||
|
||||
@Operations.implementation_for(DeleteRowOp)
|
||||
def delete_row(operations, operation: DeleteRowOp) -> None:
|
||||
columns: List[ColumnClause] = [sqlalchemy.column(key) for key in operation.values.keys()]
|
||||
table = sqlalchemy.table(operation.table_name, *columns)
|
||||
where_clauses = [table.columns[key] == value for (key, value) in operation.values.items()]
|
||||
sql = table.delete().where(and_(*where_clauses))
|
||||
operations.execute(sql)
|
||||
|
||||
|
||||
@renderers.dispatch_for(DeleteRowOp)
|
||||
def render_delete_row(autogen_context: AutogenContext, op: DeleteRowOp) -> str:
|
||||
return "op.delete_row(%r, **%r)" % (
|
||||
op.table_name,
|
||||
op.values
|
||||
)
|
||||
51
alembic_data/ops/insert_row.py
Normal file
51
alembic_data/ops/insert_row.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from typing import Any, Mapping, List
|
||||
|
||||
import sqlalchemy
|
||||
from alembic.autogenerate import renderers
|
||||
from alembic.autogenerate.api import AutogenContext
|
||||
from alembic.operations import Operations, MigrateOperation
|
||||
|
||||
__all__ = ["InsertRowOp"]
|
||||
|
||||
from sqlalchemy.sql.elements import ColumnClause
|
||||
|
||||
|
||||
@Operations.register_operation("insert_row")
|
||||
class InsertRowOp(MigrateOperation):
|
||||
"""This `MigrationOperation` adds rows to a database table."""
|
||||
|
||||
def __init__(self, table_name: str, **kwargs: Mapping[str, Any]) -> None:
|
||||
"""Creates a new `InsertRowOp`.
|
||||
|
||||
:param table_name: The name of the table to insert the row.
|
||||
:param kwargs: The values to insert into the table. Keys must correspond to column names in the table.
|
||||
"""
|
||||
self.table_name = table_name
|
||||
self.values = kwargs
|
||||
|
||||
@classmethod
|
||||
def insert_row(cls, operations: Operations, table_name: str, **kwargs: Mapping[str, Any]):
|
||||
"""Factory method for `InsertRowOp`."""
|
||||
op = InsertRowOp(table_name, **kwargs)
|
||||
return operations.invoke(op)
|
||||
|
||||
def reverse(self) -> MigrateOperation:
|
||||
"""Reverses the insert row operation by deleting the respective row."""
|
||||
from .delete_row import DeleteRowOp
|
||||
return DeleteRowOp(self.table_name, **self.values)
|
||||
|
||||
|
||||
@Operations.implementation_for(InsertRowOp)
|
||||
def insert_row(operations: Operations, operation: InsertRowOp) -> None:
|
||||
columns: List[ColumnClause] = [sqlalchemy.column(key) for key in operation.values.keys()]
|
||||
table = sqlalchemy.table(operation.table_name, *columns)
|
||||
sql = table.insert().values(**operation.values)
|
||||
operations.execute(sql)
|
||||
|
||||
|
||||
@renderers.dispatch_for(InsertRowOp)
|
||||
def render_insert_row(autogen_context: AutogenContext, op: InsertRowOp) -> str:
|
||||
return "op.insert_row(%r, **%r)" % (
|
||||
op.table_name,
|
||||
op.values
|
||||
)
|
||||
57
alembic_data/ops/update_row.py
Normal file
57
alembic_data/ops/update_row.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from typing import Any, Mapping, List
|
||||
|
||||
import sqlalchemy
|
||||
from alembic.autogenerate import renderers
|
||||
from alembic.autogenerate.api import AutogenContext
|
||||
from alembic.operations import Operations, MigrateOperation
|
||||
|
||||
__all__ = ["UpdateRowOp"]
|
||||
|
||||
from sqlalchemy.sql.elements import ColumnClause
|
||||
|
||||
|
||||
@Operations.register_operation("update_row")
|
||||
class UpdateRowOp(MigrateOperation):
|
||||
"""This `MigrationOperation` updates rows in a database table."""
|
||||
|
||||
def __init__(self, table_name: str, new_values: Mapping[str, Any], old_values: Mapping[str, Any]) -> None:
|
||||
"""Creates a new `InsertRowOp`.
|
||||
|
||||
:param table_name: The name of the table to update values in.
|
||||
:param new_values: The new values to update in the table. Keys must correspond to column names in the table and
|
||||
values to their values.
|
||||
:param old_values: The old values used to identify the row that should be updated.
|
||||
"""
|
||||
self.table_name = table_name
|
||||
self.new_values = new_values
|
||||
self.old_values = old_values
|
||||
|
||||
@classmethod
|
||||
def update_row(cls, operations: Operations, table_name: str, new_values: Mapping[str, Any],
|
||||
old_values: Mapping[str, Any]):
|
||||
"""Factory method for `UpdateRowOp`."""
|
||||
op = UpdateRowOp(table_name, new_values, old_values)
|
||||
return operations.invoke(op)
|
||||
|
||||
def reverse(self) -> MigrateOperation:
|
||||
"""Reverses the update operation by reverting back to the old values."""
|
||||
return UpdateRowOp(self.table_name, self.old_values, self.new_values)
|
||||
|
||||
|
||||
@Operations.implementation_for(UpdateRowOp)
|
||||
def update_row(operations: Operations, operation: UpdateRowOp) -> None:
|
||||
columns: List[ColumnClause] = [sqlalchemy.column(key) for key in operation.values.keys()]
|
||||
table = sqlalchemy.table(operation.table_name, *columns)
|
||||
where_clauses = [table.columns[key] == value for (key, value) in operation.old_values.items()]
|
||||
operations.execute(
|
||||
table.update().where(*where_clauses).values(**operation.new_values)
|
||||
)
|
||||
|
||||
|
||||
@renderers.dispatch_for(UpdateRowOp)
|
||||
def render_update_row(autogen_context: AutogenContext, op: UpdateRowOp) -> str:
|
||||
return "op.update_row(%r, **%r, **%r)" % (
|
||||
op.table_name,
|
||||
op.new_values,
|
||||
op.old_values
|
||||
)
|
||||
Reference in New Issue
Block a user