diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..cda05b9 Binary files /dev/null and b/.DS_Store differ diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..f06fb9e --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.7.10 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ac677ab --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.7.10 + +WORKDIR /app + +COPY ./ ./ +RUN pip install google-cloud-spanner==1.19.1 google_cloud_storage==1.43.0 + +RUN pip install -e . + +RUN pip install pytest absl-py google-api-core portpicker + +ENV GOOGLE_APPLICATION_CREDENTIALS '/app/spanner-key.json' diff --git a/setup.py b/setup.py index 6199fcd..ad9d221 100644 --- a/setup.py +++ b/setup.py @@ -17,14 +17,14 @@ setup( name='spanner-orm', - version='0.1.10', + version='0.1.12', description='Basic ORM for Spanner', maintainer='Python Spanner ORM developers', maintainer_email='python-spanner-orm@google.com', url='https://github.com/google/python-spanner-orm', packages=['spanner_orm', 'spanner_orm.admin'], include_package_data=True, - python_requires='~=3.7', + python_requires='>=3', install_requires=[ 'google-cloud-spanner >= 1.6, <4', 'immutabledict', diff --git a/spanner_orm/__init__.py b/spanner_orm/__init__.py index 193ab45..0a97789 100644 --- a/spanner_orm/__init__.py +++ b/spanner_orm/__init__.py @@ -60,8 +60,10 @@ Boolean = field.Boolean Field = field.Field -Integer = field.Integer Float = field.Float +FloatArray = field.FloatArray +Integer = field.Integer +IntegerArray = field.IntegerArray ForeignKeyRelationship = foreign_key_relationship.ForeignKeyRelationship Index = index.Index Relationship = relationship.Relationship diff --git a/spanner_orm/field.py b/spanner_orm/field.py index d5d864b..d06bfa8 100644 --- a/spanner_orm/field.py +++ b/spanner_orm/field.py @@ -167,6 +167,43 @@ def validate_type(value: Any) -> None: if not isinstance(item, str): raise error.ValidationError('{} is not of type str'.format(item)) +class FloatArray(FieldType): + """Represents an array of strings type.""" + + @staticmethod + def ddl() -> str: + return 'ARRAY' + + @staticmethod + def grpc_type() -> type_pb2.Type: + return type_pb2.Type(code=type_pb2.ARRAY) + + @staticmethod + def validate_type(value: Any) -> None: + if not isinstance(value, list): + raise error.ValidationError('{} is not of type list'.format(value)) + for item in value: + if not isinstance(item, float): + raise error.ValidationError('{} is not of type float'.format(item)) + +class IntegerArray(FieldType): + """Represents an array of strings type.""" + + @staticmethod + def ddl() -> str: + return 'ARRAY' + + @staticmethod + def grpc_type() -> type_pb2.Type: + return type_pb2.Type(code=type_pb2.ARRAY) + + @staticmethod + def validate_type(value: Any) -> None: + if not isinstance(value, list): + raise error.ValidationError('{} is not of type list'.format(value)) + for item in value: + if not isinstance(item, int): + raise error.ValidationError('{} is not of type int'.format(item)) class Timestamp(FieldType): """Represents a timestamp type.""" @@ -209,5 +246,5 @@ def validate_type(value) -> None: ALL_TYPES = [ - Boolean, Integer, Float, String, StringArray, Timestamp, BytesBase64 + Boolean, Integer, IntegerArray, Float, FloatArray, String, StringArray, Timestamp, BytesBase64 ] diff --git a/spanner_orm/tests/migrations_for_emulator_test/create_unittest_model.py b/spanner_orm/tests/migrations_for_emulator_test/create_unittest_model.py index db8387b..cf8fb3b 100644 --- a/spanner_orm/tests/migrations_for_emulator_test/create_unittest_model.py +++ b/spanner_orm/tests/migrations_for_emulator_test/create_unittest_model.py @@ -39,6 +39,8 @@ class OriginalUnittestModelTable(spanner_orm.model.Model): bytes_2 = field.Field(field.BytesBase64, nullable=True) timestamp = field.Field(field.Timestamp) string_array = field.Field(field.StringArray, nullable=True) + int_array = field.Field(field.IntegerArray, nullable=True) + float_array = field.Field(field.FloatArray, nullable=True) def upgrade() -> spanner_orm.CreateTable: diff --git a/spanner_orm/tests/models.py b/spanner_orm/tests/models.py index 697a582..c3a048d 100644 --- a/spanner_orm/tests/models.py +++ b/spanner_orm/tests/models.py @@ -140,3 +140,13 @@ class NullFilteredIndexModel(model.Model): value_1 = field.Field(field.String, nullable=True) value_2 = field.Field(field.Integer) value_index = index.Index(['value_1', 'value_2'], null_filtered=True) + + +class NumericFloatArrayModel(model.Model): + """Model class for testing Integer and Float Arrays.""" + + __table__ = 'NumericFloatArrayModel' + key = field.Field(field.String, primary_key=True) + value_1 = field.Field(field.FloatArray) + value_2 = field.Field(field.IntegerArray) +