# Path: spanner_orm/error.py
# class SpannerError(Exception):
# class ValidationError(Exception):
# 
# Path: spanner_orm/admin/migration.py
# def no_update_callable() -> update.MigrationUpdate:
#   def __init__(
#       self,
#       migration_id: str,
#       prev_migration_id: Optional[str],
#       upgrade: Optional[Callable[[], update.MigrationUpdate]] = None,
#       downgrade: Optional[Callable[[], update.MigrationUpdate]] = None,
#   ):
#   def migration_id(self) -> str:
#   def prev_migration_id(self) -> Optional[str]:
#   def upgrade(self) -> Optional[Callable[[], update.MigrationUpdate]]:
#   def downgrade(self) -> Optional[Callable[[], update.MigrationUpdate]]:
# class Migration:
# 
# Path: spanner_orm/admin/migration_executor.py
# class MigrationExecutor:
#   def __init__(self,
#                connection: api.SpannerConnection,
#                basedir: Optional[str] = None):
#   def migrated(self, migration_id: str) -> bool:
#   def migrations(self) -> List[migration.Migration]:
#   def migrate(self, target_migration: Optional[str] = None) -> None:
#   def rollback(self, target_migration: str) -> None:
#   def _connect(self) -> None:
#   def _hangup(self) -> None:
#   def _filter_migrations(
#       self, migrations: Iterable[migration.Migration], migrated: bool,
#       last_migration: Optional[str]) -> List[migration.Migration]:
#   def _migration_status(self) -> Dict[str, bool]:
#   def _update_status(self, migration_id: str, new_status: bool) -> None:
#   def _validate_migrations(self) -> None:
# 
# Path: spanner_orm/admin/migration_manager.py
# class MigrationManager:
#   DEFAULT_DIRECTORY = 'migrations'
#   def __init__(self, basedir: Optional[str] = None):
#   def generate(self, migration_name: str) -> str:
#   def migrations(self) -> List[migration.Migration]:
#   def _migration_from_file(self, filename: str) -> migration.Migration:
#   def _all_migrations(self) -> List[migration.Migration]:
#   def _order_migrations(
#       self,
#       migrations: Iterable[migration.Migration]) -> List[migration.Migration]:
# 
# Path: spanner_orm/admin/update.py
# class MigrationUpdate(abc.ABC):
# class NoUpdate(MigrationUpdate):
# class SchemaUpdate(MigrationUpdate, abc.ABC):
# class CreateTable(SchemaUpdate):
# class DropTable(SchemaUpdate):
# class AddColumn(SchemaUpdate):
# class DropColumn(SchemaUpdate):
# class AlterColumn(SchemaUpdate):
# class CreateIndex(SchemaUpdate):
# class DropIndex(SchemaUpdate):
# class ExecutePartitionedDml(MigrationUpdate):
#   def execute(self) -> None:
#   def execute(self) -> None:
#   def ddl(self) -> str:
#   def execute(self) -> None:
#   def validate(self) -> None:
#   def __init__(self, model_: Type[model.Model]):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def _validate_parent(self) -> None:
#   def _validate_primary_keys(self) -> None:
#   def __init__(self, table_name: str):
#   def ddl(self) -> str:
#   def __init__(self, table_name: str, column_name: str, field_: field.Field):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self, table_name: str, column_name: str):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self, table_name: str, column_name: str, field_: field.Field):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self,
#                table_name: str,
#                index_name: str,
#                columns: Iterable[str],
#                interleaved: Optional[str] = None,
#                null_filtered: bool = False,
#                unique: bool = False,
#                storing_columns: Optional[Iterable[str]] = None):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def _validate_columns(self, model_: Type[model.Model]) -> None:
#   def _validate_parent(self, model_: Type[model.Model]) -> None:
#   def __init__(self, table_name: str, index_name: str):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self, dml: str):
#   def execute(self) -> None:
# def model_creation_ddl(model_: Type[model.Model]) -> List[str]:


import logging
import os
import shutil
import stat
import tempfile
import unittest
from unittest import mock
from spanner_orm import error
from spanner_orm.admin import migration
from spanner_orm.admin import migration_executor
from spanner_orm.admin import migration_manager
from spanner_orm.admin import update

    manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR)
    with self.assertRaisesRegex(error.SpannerError, 'unclear successor'):
      manager._order_migrations(migrations)

  def test_order_migrations_error_on_unclear_start_migration(self):
    first = migration.Migration('1', None)
    second = migration.Migration('3', '2')
    migrations = [first, second]

    manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR)
    with self.assertRaisesRegex(error.SpannerError, 'no valid previous'):
      manager._order_migrations(migrations)

  def test_order_migrations_error_on_circular_dependency(self):
    first = migration.Migration('1', '3')
    second = migration.Migration('2', '1')
    third = migration.Migration('3', '2')
    migrations = [third, first, second]

    manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR)
    with self.assertRaisesRegex(error.SpannerError, 'No valid migration'):
      manager._order_migrations(migrations)

  def test_order_migrations_error_on_no_successor(self):
    first = migration.Migration('1', None)
    second = migration.Migration('2', '3')
    third = migration.Migration('3', '2')
    migrations = [third, first, second]


# Path: spanner_orm/error.py
# class SpannerError(Exception):
# class ValidationError(Exception):
# 
# Path: spanner_orm/admin/migration.py
# def no_update_callable() -> update.MigrationUpdate:
#   def __init__(
#       self,
#       migration_id: str,
#       prev_migration_id: Optional[str],
#       upgrade: Optional[Callable[[], update.MigrationUpdate]] = None,
#       downgrade: Optional[Callable[[], update.MigrationUpdate]] = None,
#   ):
#   def migration_id(self) -> str:
#   def prev_migration_id(self) -> Optional[str]:
#   def upgrade(self) -> Optional[Callable[[], update.MigrationUpdate]]:
#   def downgrade(self) -> Optional[Callable[[], update.MigrationUpdate]]:
# class Migration:
# 
# Path: spanner_orm/admin/migration_executor.py
# class MigrationExecutor:
#   def __init__(self,
#                connection: api.SpannerConnection,
#                basedir: Optional[str] = None):
#   def migrated(self, migration_id: str) -> bool:
#   def migrations(self) -> List[migration.Migration]:
#   def migrate(self, target_migration: Optional[str] = None) -> None:
#   def rollback(self, target_migration: str) -> None:
#   def _connect(self) -> None:
#   def _hangup(self) -> None:
#   def _filter_migrations(
#       self, migrations: Iterable[migration.Migration], migrated: bool,
#       last_migration: Optional[str]) -> List[migration.Migration]:
#   def _migration_status(self) -> Dict[str, bool]:
#   def _update_status(self, migration_id: str, new_status: bool) -> None:
#   def _validate_migrations(self) -> None:
# 
# Path: spanner_orm/admin/migration_manager.py
# class MigrationManager:
#   DEFAULT_DIRECTORY = 'migrations'
#   def __init__(self, basedir: Optional[str] = None):
#   def generate(self, migration_name: str) -> str:
#   def migrations(self) -> List[migration.Migration]:
#   def _migration_from_file(self, filename: str) -> migration.Migration:
#   def _all_migrations(self) -> List[migration.Migration]:
#   def _order_migrations(
#       self,
#       migrations: Iterable[migration.Migration]) -> List[migration.Migration]:
# 
# Path: spanner_orm/admin/update.py
# class MigrationUpdate(abc.ABC):
# class NoUpdate(MigrationUpdate):
# class SchemaUpdate(MigrationUpdate, abc.ABC):
# class CreateTable(SchemaUpdate):
# class DropTable(SchemaUpdate):
# class AddColumn(SchemaUpdate):
# class DropColumn(SchemaUpdate):
# class AlterColumn(SchemaUpdate):
# class CreateIndex(SchemaUpdate):
# class DropIndex(SchemaUpdate):
# class ExecutePartitionedDml(MigrationUpdate):
#   def execute(self) -> None:
#   def execute(self) -> None:
#   def ddl(self) -> str:
#   def execute(self) -> None:
#   def validate(self) -> None:
#   def __init__(self, model_: Type[model.Model]):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def _validate_parent(self) -> None:
#   def _validate_primary_keys(self) -> None:
#   def __init__(self, table_name: str):
#   def ddl(self) -> str:
#   def __init__(self, table_name: str, column_name: str, field_: field.Field):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self, table_name: str, column_name: str):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self, table_name: str, column_name: str, field_: field.Field):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self,
#                table_name: str,
#                index_name: str,
#                columns: Iterable[str],
#                interleaved: Optional[str] = None,
#                null_filtered: bool = False,
#                unique: bool = False,
#                storing_columns: Optional[Iterable[str]] = None):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def _validate_columns(self, model_: Type[model.Model]) -> None:
#   def _validate_parent(self, model_: Type[model.Model]) -> None:
#   def __init__(self, table_name: str, index_name: str):
#   def ddl(self) -> str:
#   def validate(self) -> None:
#   def __init__(self, dml: str):
#   def execute(self) -> None:
# def model_creation_ddl(model_: Type[model.Model]) -> List[str]:


# Path: spanner_orm/tests/migrations_test.py
import logging
import os
import shutil
import stat
import tempfile
import unittest
from unittest import mock
from spanner_orm import error
from spanner_orm.admin import migration
from spanner_orm.admin import migration_executor
from spanner_orm.admin import migration_manager
from spanner_orm.admin import update


    manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR)
    with self.assertRaisesRegex(error.SpannerError, 'unclear successor'):
      manager._order_migrations(migrations)

  def test_order_migrations_error_on_unclear_start_migration(self):
    first = migration.Migration('1', None)
    second = migration.Migration('3', '2')
    migrations = [first, second]

    manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR)
    with self.assertRaisesRegex(error.SpannerError, 'no valid previous'):
      manager._order_migrations(migrations)

  def test_order_migrations_error_on_circular_dependency(self):
    first = migration.Migration('1', '3')
    second = migration.Migration('2', '1')
    third = migration.Migration('3', '2')
    migrations = [third, first, second]

    manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR)
    with self.assertRaisesRegex(error.SpannerError, 'No valid migration'):
      manager._order_migrations(migrations)

  def test_order_migrations_error_on_no_successor(self):
    first = migration.Migration('1', None)
    second = migration.Migration('2', '3')
    third = migration.Migration('3', '2')
    migrations = [third, first, second]


    manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR)