# Path: spanner_orm/error.py
# class SpannerError(Exception):
# class ValidationError(Exception):
# 
# Path: spanner_orm/field.py
# class FieldType(abc.ABC):
# class Field(object):
# class Boolean(FieldType):
# class Integer(FieldType):
# class Float(FieldType):
# class String(FieldType):
# class StringArray(FieldType):
# class Timestamp(FieldType):
# class BytesBase64(FieldType):
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def __init__(self,
#                field_type: Type[FieldType],
#                nullable: bool = False,
#                primary_key: bool = False):
#   def ddl(self) -> str:
#   def field_type(self) -> Type[FieldType]:
#   def grpc_type(self) -> str:
#   def nullable(self) -> bool:
#   def primary_key(self) -> bool:
#   def validate(self, value) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value) -> None:
# ALL_TYPES = [
#     Boolean, Integer, Float, String, StringArray, Timestamp, BytesBase64
# ]
# 
# Path: spanner_orm/testlib/spanner_emulator/testlib.py
# def _make_emulator_spanner_orm_connection(
#     db: database.Database, inst: instance.Instance,
#     spanner_client: client.Client) -> spanner_orm.SpannerConnection:
# def _get_instance(spanner_client: client.Client) -> instance.Instance:
# def _migrate_database_at_connection(connection: spanner_orm.SpannerConnection,
#                                     migrations_dir: str) -> None:
# def _database_id() -> str:
#   def setUpClass(cls):
#   def setUp(self):
#   def tearDownClass(cls):
#   def run_orm_migrations(self, migrations_folder: str) -> None:
# class TestCase(unittest.TestCase):
# 
# Path: spanner_orm/tests/models.py
# class SmallTestModel(model.Model):
# class SmallTestModelWithoutSecondaryIndexes(model.Model):
# class ChildTestModel(model.Model):
# class IndexTestModel(model.Model):
# class RelationshipTestModel(model.Model):
# class ForeignKeyTestModel(model.Model):
# class InheritanceTestModel(SmallTestModel):
# class UnittestModel(model.Model):
# class UnittestModelWithoutSecondaryIndexes(model.Model):
# class NullFilteredIndexModel(model.Model):


import datetime
import logging
import os
import typing
import unittest
from typing import List
from unittest import mock
from absl.testing import parameterized
from google.api_core import exceptions
from google.cloud import spanner  # pytype: disable=import-error
from spanner_orm import error
from spanner_orm import field
from spanner_orm.testlib.spanner_emulator import testlib as spanner_emulator_testlib
from spanner_orm.tests import models
    test_model = models.UnittestModel(all_data)
    self.assertEqual(test_model.id(), primary_key)

  def test_changes(self):
    test_model = models.SmallTestModel({'key': 'key', 'value_1': 'value'})
    test_model.value_1 = 'change'
    self.assertEqual(test_model.changes(), {'value_1': 'change'})

    test_model.value_1 = 'value'
    self.assertEqual(test_model.changes(), {})

  def test_object_changes(self):
    array = ['foo', 'bar']
    timestamp = datetime.datetime.now(tz=datetime.timezone.utc)
    test_model = models.UnittestModel({
        'int_': 0,
        'float_': 0,
        'string': '',
        'bytes_': b'',
        'string_array': array,
        'timestamp': timestamp
    })

    # Make sure that changing an object on the model shows up in changes()
    string_array = typing.cast(List[str], test_model.string_array)
    string_array.append('bat')
    self.assertIn('string_array', test_model.changes())

  def test_field_exists_on_model_class(self):
    self.assertIsInstance(models.SmallTestModel.key, field.Field)

# Path: spanner_orm/error.py
# class SpannerError(Exception):
# class ValidationError(Exception):
# 
# Path: spanner_orm/field.py
# class FieldType(abc.ABC):
# class Field(object):
# class Boolean(FieldType):
# class Integer(FieldType):
# class Float(FieldType):
# class String(FieldType):
# class StringArray(FieldType):
# class Timestamp(FieldType):
# class BytesBase64(FieldType):
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def __init__(self,
#                field_type: Type[FieldType],
#                nullable: bool = False,
#                primary_key: bool = False):
#   def ddl(self) -> str:
#   def field_type(self) -> Type[FieldType]:
#   def grpc_type(self) -> str:
#   def nullable(self) -> bool:
#   def primary_key(self) -> bool:
#   def validate(self, value) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value: Any) -> None:
#   def ddl() -> str:
#   def grpc_type() -> type_pb2.Type:
#   def validate_type(value) -> None:
# ALL_TYPES = [
#     Boolean, Integer, Float, String, StringArray, Timestamp, BytesBase64
# ]
# 
# Path: spanner_orm/testlib/spanner_emulator/testlib.py
# def _make_emulator_spanner_orm_connection(
#     db: database.Database, inst: instance.Instance,
#     spanner_client: client.Client) -> spanner_orm.SpannerConnection:
# def _get_instance(spanner_client: client.Client) -> instance.Instance:
# def _migrate_database_at_connection(connection: spanner_orm.SpannerConnection,
#                                     migrations_dir: str) -> None:
# def _database_id() -> str:
#   def setUpClass(cls):
#   def setUp(self):
#   def tearDownClass(cls):
#   def run_orm_migrations(self, migrations_folder: str) -> None:
# class TestCase(unittest.TestCase):
# 
# Path: spanner_orm/tests/models.py
# class SmallTestModel(model.Model):
# class SmallTestModelWithoutSecondaryIndexes(model.Model):
# class ChildTestModel(model.Model):
# class IndexTestModel(model.Model):
# class RelationshipTestModel(model.Model):
# class ForeignKeyTestModel(model.Model):
# class InheritanceTestModel(SmallTestModel):
# class UnittestModel(model.Model):
# class UnittestModelWithoutSecondaryIndexes(model.Model):
# class NullFilteredIndexModel(model.Model):


# Path: spanner_orm/tests/model_test.py
import datetime
import logging
import os
import typing
import unittest
from typing import List
from unittest import mock
from absl.testing import parameterized
from google.api_core import exceptions
from google.cloud import spanner  # pytype: disable=import-error
from spanner_orm import error
from spanner_orm import field
from spanner_orm.testlib.spanner_emulator import testlib as spanner_emulator_testlib
from spanner_orm.tests import models

    test_model = models.UnittestModel(all_data)
    self.assertEqual(test_model.id(), primary_key)

  def test_changes(self):
    test_model = models.SmallTestModel({'key': 'key', 'value_1': 'value'})
    test_model.value_1 = 'change'
    self.assertEqual(test_model.changes(), {'value_1': 'change'})

    test_model.value_1 = 'value'
    self.assertEqual(test_model.changes(), {})

  def test_object_changes(self):
    array = ['foo', 'bar']
    timestamp = datetime.datetime.now(tz=datetime.timezone.utc)
    test_model = models.UnittestModel({
        'int_': 0,
        'float_': 0,
        'string': '',
        'bytes_': b'',
        'string_array': array,
        'timestamp': timestamp
    })

    # Make sure that changing an object on the model shows up in changes()
    string_array = typing.cast(List[str], test_model.string_array)
    string_array.append('bat')
    self.assertIn('string_array', test_model.changes())

  def test_field_exists_on_model_class(self):
    self.assertIsInstance(models.SmallTestModel.key, field.Field)

    self.assertEqual(models.SmallTestModel.key.field_type(), field.String)