From 3b605782e38aa854f1dc27bf8d188c26eed01d15 Mon Sep 17 00:00:00 2001 From: Rahul Yadav Date: Tue, 19 Dec 2023 05:49:32 +0000 Subject: [PATCH 1/3] feat(spanner): add support of float32 type --- google/cloud/spanner_v1/types/type.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/google/cloud/spanner_v1/types/type.py b/google/cloud/spanner_v1/types/type.py index f25c465dd4..d9b6b9def5 100644 --- a/google/cloud/spanner_v1/types/type.py +++ b/google/cloud/spanner_v1/types/type.py @@ -50,6 +50,9 @@ class TypeCode(proto.Enum): FLOAT64 (3): Encoded as ``number``, or the strings ``"NaN"``, ``"Infinity"``, or ``"-Infinity"``. + FLOAT32 (15): + Encoded as TBD (``number`` or ``string``), or the strings + ``"NaN"``, ``"Infinity"``, or ``"-Infinity"``. TIMESTAMP (4): Encoded as ``string`` in RFC 3339 timestamp format. The time zone must be present, and must be ``"Z"``. @@ -99,6 +102,7 @@ class TypeCode(proto.Enum): BOOL = 1 INT64 = 2 FLOAT64 = 3 + FLOAT32 = 15 TIMESTAMP = 4 DATE = 5 STRING = 6 From 026c1bb2501e3205b8949a926e8a69616bbc2e45 Mon Sep 17 00:00:00 2001 From: rahul yadav Date: Wed, 20 Dec 2023 11:45:12 +0530 Subject: [PATCH 2/3] add float32 support --- google/cloud/spanner_dbapi/parse_utils.py | 2 + google/cloud/spanner_v1/_helpers.py | 17 ++++- google/cloud/spanner_v1/param_types.py | 1 + tests/_fixtures.py | 2 + tests/system/test_session_api.py | 76 +++++++++++++++++------ tests/system/test_table_api.py | 1 + 6 files changed, 80 insertions(+), 19 deletions(-) diff --git a/google/cloud/spanner_dbapi/parse_utils.py b/google/cloud/spanner_dbapi/parse_utils.py index 76ac951e0c..123e267914 100644 --- a/google/cloud/spanner_dbapi/parse_utils.py +++ b/google/cloud/spanner_dbapi/parse_utils.py @@ -18,6 +18,7 @@ import decimal import re +import numpy import sqlparse from google.cloud import spanner_v1 as spanner from google.cloud.spanner_v1 import JsonObject @@ -36,6 +37,7 @@ str: spanner.param_types.STRING, int: spanner.param_types.INT64, float: spanner.param_types.FLOAT64, + numpy.float32: spanner.param_types.Float32, datetime.datetime: spanner.param_types.TIMESTAMP, datetime.date: spanner.param_types.DATE, DateStr: spanner.param_types.DATE, diff --git a/google/cloud/spanner_v1/_helpers.py b/google/cloud/spanner_v1/_helpers.py index e0e2bfdbd0..3b80cfe6d3 100644 --- a/google/cloud/spanner_v1/_helpers.py +++ b/google/cloud/spanner_v1/_helpers.py @@ -19,6 +19,7 @@ import math import time +import numpy from google.protobuf.struct_pb2 import ListValue from google.protobuf.struct_pb2 import Value @@ -134,7 +135,7 @@ def _make_value_pb(value): """ if value is None: return Value(null_value="NULL_VALUE") - if isinstance(value, (list, tuple)): + if isinstance(value, (list, tuple, numpy.ndarray)): return Value(list_value=_make_list_value_pb(value)) if isinstance(value, bool): return Value(bool_value=value) @@ -149,6 +150,15 @@ def _make_value_pb(value): else: return Value(string_value="-Infinity") return Value(number_value=value) + if isinstance(value, numpy.float32): + if numpy.isnan(value): + return Value(string_value="NaN") + if numpy.isinf(value): + if value > 0: + return Value(string_value="Infinity") + else: + return Value(string_value="-Infinity") + return Value(number_value=value) if isinstance(value, datetime_helpers.DatetimeWithNanoseconds): return Value(string_value=value.rfc3339()) if isinstance(value, datetime.datetime): @@ -228,6 +238,11 @@ def _parse_value_pb(value_pb, field_type): return float(value_pb.string_value) else: return value_pb.number_value + elif type_code == TypeCode.FLOAT32: + if value_pb.HasField("string_value"): + return numpy.float32(value_pb.string_value) + else: + return value_pb.number_value elif type_code == TypeCode.DATE: return _date_from_iso8601_date(value_pb.string_value) elif type_code == TypeCode.TIMESTAMP: diff --git a/google/cloud/spanner_v1/param_types.py b/google/cloud/spanner_v1/param_types.py index 0c03f7ecc6..6bceac1ab5 100644 --- a/google/cloud/spanner_v1/param_types.py +++ b/google/cloud/spanner_v1/param_types.py @@ -26,6 +26,7 @@ BOOL = Type(code=TypeCode.BOOL) INT64 = Type(code=TypeCode.INT64) FLOAT64 = Type(code=TypeCode.FLOAT64) +Float32 = Type(code=TypeCode.FLOAT32) DATE = Type(code=TypeCode.DATE) TIMESTAMP = Type(code=TypeCode.TIMESTAMP) NUMERIC = Type(code=TypeCode.NUMERIC) diff --git a/tests/_fixtures.py b/tests/_fixtures.py index b6f4108490..8b8e11da19 100644 --- a/tests/_fixtures.py +++ b/tests/_fixtures.py @@ -40,6 +40,8 @@ date_array ARRAY, float_value FLOAT64, float_array ARRAY, + float32_value FLOAT32, + float32_array ARRAY, string_value STRING(16), string_array ARRAY, timestamp_value TIMESTAMP, diff --git a/tests/system/test_session_api.py b/tests/system/test_session_api.py index 30981322cc..47cf292166 100644 --- a/tests/system/test_session_api.py +++ b/tests/system/test_session_api.py @@ -20,6 +20,7 @@ import threading import time import pytest +import numpy import grpc from google.rpc import code_pb2 @@ -39,6 +40,8 @@ NANO_TIME = datetime_helpers.DatetimeWithNanoseconds(1995, 8, 31, nanosecond=987654321) POS_INF = float("+inf") NEG_INF = float("-inf") +NUMPY_POS_INF = numpy.float32("+inf") +NUMPY_NEG_INF = numpy.float32("-inf") (OTHER_NAN,) = struct.unpack(" Date: Sun, 7 Jan 2024 13:05:15 +0530 Subject: [PATCH 3/3] remove numpy support --- google/cloud/spanner_dbapi/parse_utils.py | 2 - google/cloud/spanner_v1/_helpers.py | 14 +----- tests/system/test_session_api.py | 61 ++++++++--------------- 3 files changed, 23 insertions(+), 54 deletions(-) diff --git a/google/cloud/spanner_dbapi/parse_utils.py b/google/cloud/spanner_dbapi/parse_utils.py index 123e267914..76ac951e0c 100644 --- a/google/cloud/spanner_dbapi/parse_utils.py +++ b/google/cloud/spanner_dbapi/parse_utils.py @@ -18,7 +18,6 @@ import decimal import re -import numpy import sqlparse from google.cloud import spanner_v1 as spanner from google.cloud.spanner_v1 import JsonObject @@ -37,7 +36,6 @@ str: spanner.param_types.STRING, int: spanner.param_types.INT64, float: spanner.param_types.FLOAT64, - numpy.float32: spanner.param_types.Float32, datetime.datetime: spanner.param_types.TIMESTAMP, datetime.date: spanner.param_types.DATE, DateStr: spanner.param_types.DATE, diff --git a/google/cloud/spanner_v1/_helpers.py b/google/cloud/spanner_v1/_helpers.py index 3b80cfe6d3..c26b876461 100644 --- a/google/cloud/spanner_v1/_helpers.py +++ b/google/cloud/spanner_v1/_helpers.py @@ -19,7 +19,6 @@ import math import time -import numpy from google.protobuf.struct_pb2 import ListValue from google.protobuf.struct_pb2 import Value @@ -135,8 +134,6 @@ def _make_value_pb(value): """ if value is None: return Value(null_value="NULL_VALUE") - if isinstance(value, (list, tuple, numpy.ndarray)): - return Value(list_value=_make_list_value_pb(value)) if isinstance(value, bool): return Value(bool_value=value) if isinstance(value, int): @@ -150,15 +147,6 @@ def _make_value_pb(value): else: return Value(string_value="-Infinity") return Value(number_value=value) - if isinstance(value, numpy.float32): - if numpy.isnan(value): - return Value(string_value="NaN") - if numpy.isinf(value): - if value > 0: - return Value(string_value="Infinity") - else: - return Value(string_value="-Infinity") - return Value(number_value=value) if isinstance(value, datetime_helpers.DatetimeWithNanoseconds): return Value(string_value=value.rfc3339()) if isinstance(value, datetime.datetime): @@ -240,7 +228,7 @@ def _parse_value_pb(value_pb, field_type): return value_pb.number_value elif type_code == TypeCode.FLOAT32: if value_pb.HasField("string_value"): - return numpy.float32(value_pb.string_value) + return float(value_pb.string_value) else: return value_pb.number_value elif type_code == TypeCode.DATE: diff --git a/tests/system/test_session_api.py b/tests/system/test_session_api.py index 47cf292166..04f70bf0f5 100644 --- a/tests/system/test_session_api.py +++ b/tests/system/test_session_api.py @@ -40,8 +40,6 @@ NANO_TIME = datetime_helpers.DatetimeWithNanoseconds(1995, 8, 31, nanosecond=987654321) POS_INF = float("+inf") NEG_INF = float("-inf") -NUMPY_POS_INF = numpy.float32("+inf") -NUMPY_NEG_INF = numpy.float32("-inf") (OTHER_NAN,) = struct.unpack("