From f56526a9428f127967a7ffae27e219e6d45eadc9 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Mon, 24 Aug 2026 16:40:17 +0300 Subject: [PATCH 1/4] Introduced number types and removed the default_int_type config --- docs/config.rst | 1 - examples/number_types/number_types_example.py | 15 ++ hazelcast/__init__.py | 3 +- hazelcast/config.py | 55 ------- hazelcast/number_types.py | 147 ++++++++++++++++++ hazelcast/serialization/serializer.py | 15 +- hazelcast/serialization/service.py | 42 ++--- tests/integration/asyncio/proxy/map_test.py | 4 +- tests/integration/asyncio/sql_test.py | 1 - .../backward_compatible/proxy/map_test.py | 4 +- .../serialization/serializers_test.py | 41 +++-- tests/unit/config_test.py | 19 --- .../binary_compatibility_test.py | 47 +++--- .../serialization/int_serialization_test.py | 118 -------------- 14 files changed, 237 insertions(+), 275 deletions(-) create mode 100644 examples/number_types/number_types_example.py create mode 100644 hazelcast/number_types.py delete mode 100644 tests/unit/serialization/int_serialization_test.py diff --git a/docs/config.rst b/docs/config.rst index 70e1d188a4..bc9d924546 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -7,7 +7,6 @@ Configuration API Documentation .. autoclass:: NearCacheConfig .. autoclass:: FlakeIdGeneratorConfig .. autoclass:: ReliableTopicConfig -.. autoclass:: IntType .. autoclass:: EvictionPolicy .. autoclass:: InMemoryFormat .. autoclass:: SSLProtocol diff --git a/examples/number_types/number_types_example.py b/examples/number_types/number_types_example.py new file mode 100644 index 0000000000..3a6a319441 --- /dev/null +++ b/examples/number_types/number_types_example.py @@ -0,0 +1,15 @@ +import asyncio + +from hazelcast.asyncio import HazelcastClient +from hazelcast import Int32 + + +async def amain(): + client = await HazelcastClient.create_and_start() + map = await client.get_map("number_test") + await map.set("i8", Int32(10)) + value_i8 = await map.get("i8") + assert(type(value_i8) == int) + +asyncio.run(amain()) + diff --git a/hazelcast/__init__.py b/hazelcast/__init__.py index 2c66ded3ef..4b77d715fd 100644 --- a/hazelcast/__init__.py +++ b/hazelcast/__init__.py @@ -1,4 +1,4 @@ -__version__ = "5.7.0" +__version__ = "6.0.0" # Set the default handler to "hazelcast" loggers # to avoid "No handlers could be found" warnings. @@ -7,3 +7,4 @@ logging.getLogger(__name__).addHandler(logging.NullHandler()) from hazelcast.client import HazelcastClient +from hazelcast.number_types import * \ No newline at end of file diff --git a/hazelcast/config.py b/hazelcast/config.py index 6c21423679..f8d1b8acab 100644 --- a/hazelcast/config.py +++ b/hazelcast/config.py @@ -20,46 +20,6 @@ ) -class IntType: - """Integer type options that can be used by serialization service.""" - - VAR = 0 - """ - Integer types will be serialized as 8, 16, 32, 64 bit integers - or as Java BigInteger according to their value. This option may - cause problems when the Python client is used in conjunction with - statically typed language clients such as Java or .NET. - """ - - BYTE = 1 - """ - Integer types will be serialized as a 8 bit integer(as Java byte) - """ - - SHORT = 2 - """ - Integer types will be serialized as a 16 bit integer(as Java short) - """ - - INT = 3 - """ - Integer types will be serialized as a 32 bit integer(as Java int) - """ - - LONG = 4 - """ - Integer types will be serialized as a 64 bit integer(as Java long) - """ - - BIG_INT = 5 - """ - Integer types will be serialized as Java BigInteger. This option can - handle integer types which are less than -2^63 or greater than or - equal to 2^63. However, when this option is set, serializing/de-serializing - integer types is costly. - """ - - class EvictionPolicy: """Near Cache eviction policy options.""" @@ -309,7 +269,6 @@ class Config: "_class_definitions", "_check_class_definition_errors", "_is_big_endian", - "_default_int_type", "_global_serializer", "_custom_serializers", "_near_caches", @@ -370,7 +329,6 @@ def __init__(self): self._class_definitions: typing.List[ClassDefinition] = [] self._check_class_definition_errors: bool = True self._is_big_endian: bool = True - self._default_int_type: int = IntType.INT self._global_serializer: typing.Optional[typing.Type[StreamSerializer]] = None self._custom_serializers: typing.Dict[ typing.Type[typing.Any], typing.Type[StreamSerializer] @@ -1021,19 +979,6 @@ def is_big_endian(self, value: bool) -> None: self._is_big_endian = value - @property - def default_int_type(self) -> int: - """Defines how the ``int`` type is represented on the member side. - - By default, it is serialized as ``INT`` (``32`` bits). See the - :class:`hazelcast.config.IntType` for possible values. - """ - return self._default_int_type - - @default_int_type.setter - def default_int_type(self, value: typing.Union[int, str]) -> None: - self._default_int_type = try_to_get_enum_value(value, IntType) - @property def global_serializer(self) -> typing.Optional[typing.Type[StreamSerializer]]: """Defines the global serializer. diff --git a/hazelcast/number_types.py b/hazelcast/number_types.py new file mode 100644 index 0000000000..1dd6e84a4e --- /dev/null +++ b/hazelcast/number_types.py @@ -0,0 +1,147 @@ +from typing import Self + +from hazelcast.serialization import MIN_SHORT, MAX_SHORT, MIN_INT, MAX_INT, MIN_LONG, MAX_LONG +from hazelcast.serialization.bits import MIN_BYTE, MAX_BYTE + +__all__ = "Int8", "Int16", "Int32", "Int64", "Float32", "Float64", "BigInt" + + + +class Int8: + """Int8 represents an 8-bit signed integer + + Corresponds to Java ``byte`` + """ + + MIN_VALUE = MIN_BYTE + MAX_VALUE = MAX_BYTE + + def __init__(self, value: int): + if not (self.MIN_VALUE <= value <= self.MAX_VALUE): + raise ValueError("{} value must be between {} and {}".format( + self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, + )) + self.value = value + + def __int__(self): + return self.value + + def __repr__(self) -> str: + return str(self.value) + + +class Int16: + """Int16 represents a 16-bit signed integer + + Corresponds to Java ``short``. + """ + + MIN_VALUE = MIN_SHORT + MAX_VALUE = MAX_SHORT + + def __init__(self, value: int): + if not (self.MIN_VALUE <= value <= self.MAX_VALUE): + raise ValueError("{} value must be between {} and {}".format( + self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, + )) + self.value = value + + def __int__(self): + return self.value + + def __repr__(self) -> str: + return str(self.value) + + +class Int32: + """Int32 represents a 32-bit signed integer + + Corresponds to Java ``int``. + """ + + MIN_VALUE = MIN_INT + MAX_VALUE = MAX_INT + + def __init__(self, value: int): + if not (self.MIN_VALUE <= value <= self.MAX_VALUE): + raise ValueError("{} value must be between {} and {}".format( + self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, + )) + self.value = value + + def __int__(self): + return self.value + + def __repr__(self) -> str: + return str(self.value) + + +class Int64: + """Int64 represents a 64-bit signed integer + + Corresponds to Java ``long``. + """ + + MIN_VALUE = MIN_LONG + MAX_VALUE = MAX_LONG + + def __init__(self, value: int): + if not (self.MIN_VALUE <= value <= self.MAX_VALUE): + raise ValueError("{} value must be between {} and {}".format( + self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, + )) + self.value = value + + def __int__(self): + return self.value + + def __repr__(self) -> str: + return str(self.value) + + +class BigInt: + """BigInt represents a big integer + + Corresponds to Java ``java.math.BigInteger``. + """ + + def __init__(self, value: int): + self.value = value + + def __int__(self): + return self.value + + def __repr__(self) -> str: + return str(self.value) + + +class Float32: + """Float32 represents a 32-bit floating point number + + Corresponds to Java ``float``. + """ + + def __init__(self, value: float|int): + self.value = float(value) + + def __float__(self): + return self.value + + def __repr__(self) -> str: + return str(self.value) + + +class Float64: + """Float32 represents a 64-bit floating point number + + Corresponds to Java ``double``. + """ + + def __init__(self, value: float|int): + self.value = float(value) + + def __float__(self): + return self.value + + def __repr__(self) -> str: + return str(self.value) diff --git a/hazelcast/serialization/serializer.py b/hazelcast/serialization/serializer.py index 6575ad5181..894d9d88c3 100644 --- a/hazelcast/serialization/serializer.py +++ b/hazelcast/serialization/serializer.py @@ -42,7 +42,7 @@ def read(self, inp): return inp.read_byte() def write(self, out, obj): - out.write_byte(obj) + out.write_byte(int(obj)) def get_type_id(self): return CONSTANT_TYPE_BYTE @@ -63,7 +63,7 @@ def read(self, inp): return inp.read_short() def write(self, out, obj): - out.write_short(obj) + out.write_short(int(obj)) def get_type_id(self): return CONSTANT_TYPE_SHORT @@ -74,7 +74,7 @@ def read(self, inp): return inp.read_int() def write(self, out, obj): - out.write_int(obj) + out.write_int(int(obj)) def get_type_id(self): return CONSTANT_TYPE_INTEGER @@ -85,7 +85,7 @@ def read(self, inp): return inp.read_long() def write(self, out, obj): - out.write_long(obj) + out.write_long(int(obj)) def get_type_id(self): return CONSTANT_TYPE_LONG @@ -95,7 +95,8 @@ class FloatSerializer(BaseSerializer): def read(self, inp): return inp.read_float() - # "write(self, out, obj)" is never called so not implemented here + def write(self, out, obj): + out.write_float(float(obj)) def get_type_id(self): return CONSTANT_TYPE_FLOAT @@ -106,7 +107,7 @@ def read(self, inp): return inp.read_double() def write(self, out, obj): - out.write_double(obj) + out.write_double(float(obj)) def get_type_id(self): return CONSTANT_TYPE_DOUBLE @@ -247,7 +248,7 @@ def read(self, inp): return IOUtil.read_big_integer(inp) def write(self, out, obj): - IOUtil.write_big_integer(out, obj) + IOUtil.write_big_integer(out, int(obj)) def get_type_id(self): return JAVA_DEFAULT_TYPE_BIG_INTEGER diff --git a/hazelcast/serialization/service.py b/hazelcast/serialization/service.py index 7913b7e2dd..c31748114c 100644 --- a/hazelcast/serialization/service.py +++ b/hazelcast/serialization/service.py @@ -6,7 +6,8 @@ import typing -from hazelcast.config import IntType, Config +from hazelcast.number_types import Int16, Int8, Float32, Float64, Int32, Int64, BigInt +from hazelcast.config import Config from hazelcast.errors import HazelcastInstanceNotActiveError, IllegalArgumentError from hazelcast.serialization.api import IdentifiedDataSerializable, Portable from hazelcast.serialization.compact import ( @@ -32,15 +33,6 @@ DEFAULT_OUT_BUFFER_SIZE = 4 * 1024 -_int_type_to_type_id = { - IntType.BYTE: CONSTANT_TYPE_BYTE, - IntType.SHORT: CONSTANT_TYPE_SHORT, - IntType.INT: CONSTANT_TYPE_INTEGER, - IntType.LONG: CONSTANT_TYPE_LONG, - IntType.BIG_INT: JAVA_DEFAULT_TYPE_BIG_INTEGER, -} - - def default_partition_strategy(key): if hasattr(key, "get_partition_key"): return key.get_partition_key() @@ -243,14 +235,16 @@ def _register_constant_serializers(self): self._registry.register_constant_serializer(self._data_serializer) self._registry.register_constant_serializer(self._portable_serializer) self._registry.register_constant_serializer(self._compact_stream_serializer) - self._registry.register_constant_serializer(ByteSerializer()) + self._registry.register_constant_serializer(ByteSerializer(), Int8) self._registry.register_constant_serializer(BooleanSerializer(), bool) self._registry.register_constant_serializer(CharSerializer()) - self._registry.register_constant_serializer(ShortSerializer()) + self._registry.register_constant_serializer(ShortSerializer(), Int16) self._registry.register_constant_serializer(IntegerSerializer(), int) - self._registry.register_constant_serializer(LongSerializer()) - self._registry.register_constant_serializer(FloatSerializer()) + self._registry.register_constant_serializer(IntegerSerializer(), Int32) + self._registry.register_constant_serializer(LongSerializer(), Int64) + self._registry.register_constant_serializer(FloatSerializer(), Float32) self._registry.register_constant_serializer(DoubleSerializer(), float) + self._registry.register_constant_serializer(DoubleSerializer(), Float64) self._registry.register_constant_serializer(UuidSerializer(), uuid.UUID) self._registry.register_constant_serializer(StringSerializer(), str) # Arrays of primitives and String @@ -264,7 +258,7 @@ def _register_constant_serializers(self): self._registry.register_constant_serializer(DoubleArraySerializer()) self._registry.register_constant_serializer(StringArraySerializer()) # EXTENSIONS - self._registry.register_constant_serializer(BigIntegerSerializer()) + self._registry.register_constant_serializer(BigIntegerSerializer(), BigInt) self._registry.register_constant_serializer(BigDecimalSerializer(), decimal.Decimal) self._registry.register_constant_serializer(JavaClassSerializer()) self._registry.register_constant_serializer(ArraySerializer()) @@ -348,7 +342,6 @@ def __init__( self._type_dict: typing.Dict[typing.Type, StreamSerializer] = {} self._registration_lock = threading.RLock() - self._int_type_id = _int_type_to_type_id.get(config.default_int_type, None) self._compact_types = {c.get_class() for c in config.compact_serializers} @@ -426,23 +419,8 @@ def lookup_default_serializer(self, obj_type, obj): if isinstance(obj, str): return self.serializer_by_type_id(CONSTANT_TYPE_STRING) - # LOCATE NUMERIC TYPES if obj_type is int: - type_id = self._int_type_id - if type_id is None: - # VAR size - if MIN_BYTE <= obj <= MAX_BYTE: - type_id = CONSTANT_TYPE_BYTE - elif MIN_SHORT <= obj <= MAX_SHORT: - type_id = CONSTANT_TYPE_SHORT - elif MIN_INT <= obj <= MAX_INT: - type_id = CONSTANT_TYPE_INTEGER - elif MIN_LONG <= obj <= MAX_LONG: - type_id = CONSTANT_TYPE_LONG - else: - type_id = JAVA_DEFAULT_TYPE_BIG_INTEGER - - return self.serializer_by_type_id(type_id) + return self.serializer_by_type_id(CONSTANT_TYPE_INTEGER) return self._constant_type_dict.get(obj_type, None) diff --git a/tests/integration/asyncio/proxy/map_test.py b/tests/integration/asyncio/proxy/map_test.py index ff716e240d..35feb541ac 100644 --- a/tests/integration/asyncio/proxy/map_test.py +++ b/tests/integration/asyncio/proxy/map_test.py @@ -40,7 +40,7 @@ pass from hazelcast.core import HazelcastJsonValue -from hazelcast.config import IndexType, IntType +from hazelcast.config import IndexType from hazelcast.predicate import greater_or_equal, less_or_equal, sql, paging, true from hazelcast.internal.asyncio_proxy.map import EntryEventType from hazelcast.serialization.api import IdentifiedDataSerializable @@ -847,7 +847,6 @@ class MapAggregatorsIntTest(SingleMemberTestCase): @classmethod def configure_client(cls, config): config["cluster_name"] = cls.cluster.id - config["default_int_type"] = IntType.INT return config async def asyncSetUp(self): @@ -952,7 +951,6 @@ class MapAggregatorsLongTest(SingleMemberTestCase): @classmethod def configure_client(cls, config): config["cluster_name"] = cls.cluster.id - config["default_int_type"] = IntType.LONG return config async def asyncSetUp(self): diff --git a/tests/integration/asyncio/sql_test.py b/tests/integration/asyncio/sql_test.py index 866cfc384a..c9948eba59 100644 --- a/tests/integration/asyncio/sql_test.py +++ b/tests/integration/asyncio/sql_test.py @@ -2,7 +2,6 @@ import datetime import decimal import math -import types import unittest from unittest.mock import patch diff --git a/tests/integration/backward_compatible/proxy/map_test.py b/tests/integration/backward_compatible/proxy/map_test.py index 5d51595711..5a0bd288fd 100644 --- a/tests/integration/backward_compatible/proxy/map_test.py +++ b/tests/integration/backward_compatible/proxy/map_test.py @@ -37,7 +37,7 @@ pass from hazelcast.core import HazelcastJsonValue -from hazelcast.config import IndexType, IntType +from hazelcast.config import IndexType from hazelcast.errors import HazelcastError from hazelcast.predicate import greater_or_equal, less_or_equal, sql, paging, true from hazelcast.proxy.map import EntryEventType @@ -842,7 +842,6 @@ class MapAggregatorsIntTest(SingleMemberTestCase): @classmethod def configure_client(cls, config): config["cluster_name"] = cls.cluster.id - config["default_int_type"] = IntType.INT return config def setUp(self): @@ -945,7 +944,6 @@ class MapAggregatorsLongTest(SingleMemberTestCase): @classmethod def configure_client(cls, config): config["cluster_name"] = cls.cluster.id - config["default_int_type"] = IntType.LONG return config def setUp(self): diff --git a/tests/integration/backward_compatible/serialization/serializers_test.py b/tests/integration/backward_compatible/serialization/serializers_test.py index 1b9403d9ca..946e9704ce 100644 --- a/tests/integration/backward_compatible/serialization/serializers_test.py +++ b/tests/integration/backward_compatible/serialization/serializers_test.py @@ -3,9 +3,9 @@ import decimal import uuid -from hazelcast import HazelcastClient -from hazelcast.config import IntType +from hazelcast import HazelcastClient, Int8, Int16, Int32, Int64, Float32, Float64 from hazelcast.core import HazelcastJsonValue +from hazelcast.number_types import BigInt from hazelcast.serialization import MAX_BYTE, MAX_SHORT, MAX_INT, MAX_LONG from tests.base import SingleMemberTestCase from tests.hzrc.ttypes import Lang @@ -57,8 +57,8 @@ def set_on_server(self, obj): response = self.rc.executeOnController(self.cluster.id, script, Lang.JAVASCRIPT) return response.success - def create_new_map_with(self, default_int_type): - client = HazelcastClient(cluster_name=self.cluster.id, default_int_type=default_int_type) + def create_new_map(self): + client = HazelcastClient(cluster_name=self.cluster.id) self.disposables.append(lambda: client.shutdown()) self.map = client.get_map(random_string()).blocking() @@ -70,32 +70,32 @@ def test_bool(self): self.assertEqual(value, response) def test_byte(self): - self.create_new_map_with(IntType.BYTE) + self.create_new_map() value = (1 << 7) - 1 - self.map.set("key", value) + self.map.set("key", Int8(value)) self.assertEqual(value, self.map.get("key")) response = int(self.get_from_server()) self.assertEqual(value, response) def test_short(self): - self.create_new_map_with(IntType.SHORT) + self.create_new_map() value = -1 * (1 << 15) - self.map.set("key", value) + self.map.set("key", Int16(value)) self.assertEqual(value, self.map.get("key")) response = int(self.get_from_server()) self.assertEqual(value, response) def test_int(self): value = (1 << 31) - 1 - self.map.set("key", value) + self.map.set("key", Int32(value)) self.assertEqual(value, self.map.get("key")) response = int(self.get_from_server()) self.assertEqual(value, response) def test_long(self): - self.create_new_map_with(IntType.LONG) + self.create_new_map() value = -1 * (1 << 63) - self.map.set("key", value) + self.map.set("key", Int64(value)) self.assertEqual(value, self.map.get("key")) response = int(self.get_from_server()) self.assertEqual(value, response) @@ -107,6 +107,20 @@ def test_double(self): response = float(self.get_from_server()) self.assertEqual(value, response) + def test_float32(self): + value = 123.0 + self.map.set("key", Float32(value)) + self.assertEqual(value, self.map.get("key")) + response = float(self.get_from_server()) + self.assertEqual(value, response) + + def test_float64(self): + value = 123.0 + self.map.set("key", Float64(value)) + self.assertEqual(value, self.map.get("key")) + response = float(self.get_from_server()) + self.assertEqual(value, response) + def test_string(self): value = "value" self.map.set("key", value) @@ -165,15 +179,14 @@ def test_datetime(self): self.assertTrue(response.startswith(value.strftime("%a %b %d %H:%M:%S"))) def test_big_integer(self): - self.create_new_map_with(IntType.BIG_INT) + self.create_new_map() value = 1 << 128 - self.map.set("key", value) + self.map.set("key", BigInt(value)) self.assertEqual(value, self.map.get("key")) response = int(self.get_from_server()) self.assertEqual(value, response) def test_variable_integer(self): - self.create_new_map_with(IntType.VAR) value = MAX_BYTE self.map.set("key", value) self.assertEqual(value, self.map.get("key")) diff --git a/tests/unit/config_test.py b/tests/unit/config_test.py index 231c9da38e..2e1ed02e77 100644 --- a/tests/unit/config_test.py +++ b/tests/unit/config_test.py @@ -6,7 +6,6 @@ Config, SSLProtocol, ReconnectMode, - IntType, InMemoryFormat, EvictionPolicy, IndexConfig, @@ -73,7 +72,6 @@ def test_from_dict(self): "class_definitions": [CLASS_DEFINITION], "check_class_definition_errors": False, "is_big_endian": False, - "default_int_type": IntType.LONG, "global_serializer": GlobalSerializer, "custom_serializers": {CustomSerializable: CustomSerializer}, "near_caches": { @@ -151,7 +149,6 @@ def test_from_dict(self): self.assertEqual([CLASS_DEFINITION], config.class_definitions) self.assertFalse(config.check_class_definition_errors) self.assertFalse(config.is_big_endian) - self.assertEqual(IntType.LONG, config.default_int_type) self.assertEqual(GlobalSerializer, config.global_serializer) self.assertEqual({CustomSerializable: CustomSerializer}, config.custom_serializers) @@ -619,22 +616,6 @@ def test_is_big_endian(self): config.is_big_endian = False self.assertFalse(config.is_big_endian) - def test_default_int_type(self): - config = self.config - self.assertEqual(IntType.INT, config.default_int_type) - - with self.assertRaises(TypeError): - config.default_int_type = None - - config.default_int_type = IntType.BIG_INT - self.assertEqual(IntType.BIG_INT, config.default_int_type) - - config.default_int_type = 0 - self.assertEqual(0, config.default_int_type) - - config.default_int_type = "INT" - self.assertEqual(IntType.INT, config.default_int_type) - def test_global_serializer(self): config = self.config self.assertIsNone(config.global_serializer) diff --git a/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py b/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py index 2660b7e093..b95492cb57 100644 --- a/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py +++ b/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py @@ -4,7 +4,8 @@ from os import path from parameterized import parameterized -from hazelcast.config import IntType, Config +from hazelcast.config import Config +from hazelcast.number_types import BigInt, Int8, Int16, Int32 from hazelcast.serialization import BE_INT, BE_FLOAT, SerializationServiceV1 from hazelcast.serialization.api import StreamSerializer from hazelcast.serialization.input import _ObjectDataInput @@ -49,12 +50,20 @@ def test_serialize(self, _, name, is_big_endian): if skip_on_serialize(name): return - ss = self._create_serialization_service( - is_big_endian, OBJECT_KEY_TO_INT_TYPE.get(name, IntType.INT) - ) + ss = self._create_serialization_service(is_big_endian) object_key = self._create_object_key(name, is_big_endian) from_binary = self.data_map[object_key] - serialized = ss.to_data(REFERENCE_OBJECTS[name]) + value = REFERENCE_OBJECTS[name] + match name: + case "Byte": + value = Int8(value) + case "Short": + value = Int16(value) + case "Long": + value = Int64(value) + case "BigInteger": + value = BigInt(value) + serialized = ss.to_data(value) self.assertEqual(from_binary, serialized) @parameterized.expand( @@ -67,11 +76,15 @@ def test_deserialize(self, _, name, is_big_endian): if skip_on_deserialize(name): return - ss = self._create_serialization_service(is_big_endian, IntType.INT) + ss = self._create_serialization_service(is_big_endian) object_key = self._create_object_key(name, is_big_endian) from_binary = self.data_map[object_key] deserialized = ss.to_object(from_binary) - self.assertTrue(is_equal(REFERENCE_OBJECTS[name], deserialized)) + obj = REFERENCE_OBJECTS[name] + # bool is an instance of int, so need to exclude that specifically --YT + if not isinstance(deserialized, bool) and isinstance(deserialized, int): + obj = int(obj) + self.assertTrue(is_equal(obj, deserialized)) @parameterized.expand( map( @@ -83,11 +96,12 @@ def test_serialize_deserialize(self, _, name, is_big_endian): if skip_on_deserialize(name) or skip_on_serialize(name): return - ss = self._create_serialization_service( - is_big_endian, OBJECT_KEY_TO_INT_TYPE.get(name, IntType.INT) - ) + ss = self._create_serialization_service(is_big_endian) obj = REFERENCE_OBJECTS[name] - data = ss.to_data(obj) + if name == 'BigInteger': + data = ss.to_data(BigInt(obj)) + else: + data = ss.to_data(obj) deserialized = ss.to_object(data) self.assertTrue(is_equal(obj, deserialized)) @@ -102,7 +116,7 @@ def _create_object_key(name, is_big_endian): return "1-%s-%s" % (name, BinaryCompatibilityTest._convert_to_byte_order(is_big_endian)) @staticmethod - def _create_serialization_service(is_big_endian, int_type): + def _create_serialization_service(is_big_endian): config = Config() config.custom_serializers = { CustomStreamSerializable: CustomStreamSerializer, @@ -125,7 +139,6 @@ def _create_serialization_service(is_big_endian, int_type): DATA_SERIALIZABLE_CLASS_ID: AnIdentifiedDataSerializable } } - config.default_int_type = int_type return SerializationServiceV1(config) @@ -163,11 +176,3 @@ def get_type_id(self): def destroy(self): pass - -OBJECT_KEY_TO_INT_TYPE = { - "Byte": IntType.BYTE, - "Short": IntType.SHORT, - "Integer": IntType.INT, - "Long": IntType.LONG, - "BigInteger": IntType.BIG_INT, -} diff --git a/tests/unit/serialization/int_serialization_test.py b/tests/unit/serialization/int_serialization_test.py deleted file mode 100644 index 6a2086eca1..0000000000 --- a/tests/unit/serialization/int_serialization_test.py +++ /dev/null @@ -1,118 +0,0 @@ -import unittest - -from hazelcast.config import IntType, Config -from hazelcast.errors import HazelcastSerializationError -from hazelcast.serialization.serialization_const import ( - CONSTANT_TYPE_BYTE, - CONSTANT_TYPE_SHORT, - CONSTANT_TYPE_INTEGER, - CONSTANT_TYPE_LONG, -) -from hazelcast.serialization.service import SerializationServiceV1 - -byte_val = 0x12 -short_val = 0x1234 -int_val = 0x12345678 -long_val = 0x1122334455667788 -big_int = 0x11223344556677881122334455667788 - - -class IntegerTestCase(unittest.TestCase): - def test_dynamic_case(self): - config = Config() - config.default_int_type = IntType.VAR - service = SerializationServiceV1(config) - - d1 = service.to_data(byte_val) - d2 = service.to_data(short_val) - d3 = service.to_data(int_val) - d4 = service.to_data(long_val) - v1 = service.to_object(d1) - v2 = service.to_object(d2) - v3 = service.to_object(d3) - v4 = service.to_object(d4) - - self.assertEqual(d1.get_type(), CONSTANT_TYPE_BYTE) - self.assertEqual(d2.get_type(), CONSTANT_TYPE_SHORT) - self.assertEqual(d3.get_type(), CONSTANT_TYPE_INTEGER) - self.assertEqual(d4.get_type(), CONSTANT_TYPE_LONG) - self.assertEqual(v1, byte_val) - self.assertEqual(v2, short_val) - self.assertEqual(v3, int_val) - self.assertEqual(v4, long_val) - - def test_byte_case(self): - config = Config() - config.default_int_type = IntType.BYTE - service = SerializationServiceV1(config) - - d1 = service.to_data(byte_val) - v1 = service.to_object(d1) - - self.assertEqual(d1.get_type(), CONSTANT_TYPE_BYTE) - self.assertEqual(v1, byte_val) - with self.assertRaises(HazelcastSerializationError): - service.to_data(big_int) - - def test_short_case(self): - config = Config() - config.default_int_type = IntType.SHORT - service = SerializationServiceV1(config) - - d1 = service.to_data(byte_val) - d2 = service.to_data(short_val) - v1 = service.to_object(d1) - v2 = service.to_object(d2) - - self.assertEqual(d1.get_type(), CONSTANT_TYPE_SHORT) - self.assertEqual(d2.get_type(), CONSTANT_TYPE_SHORT) - self.assertEqual(v1, byte_val) - self.assertEqual(v2, short_val) - with self.assertRaises(HazelcastSerializationError): - service.to_data(big_int) - - def test_int_case(self): - config = Config() - config.default_int_type = IntType.INT - service = SerializationServiceV1(config) - - d1 = service.to_data(byte_val) - d2 = service.to_data(short_val) - d3 = service.to_data(int_val) - v1 = service.to_object(d1) - v2 = service.to_object(d2) - v3 = service.to_object(d3) - - self.assertEqual(d1.get_type(), CONSTANT_TYPE_INTEGER) - self.assertEqual(d2.get_type(), CONSTANT_TYPE_INTEGER) - self.assertEqual(d3.get_type(), CONSTANT_TYPE_INTEGER) - self.assertEqual(v1, byte_val) - self.assertEqual(v2, short_val) - self.assertEqual(v3, int_val) - with self.assertRaises(HazelcastSerializationError): - service.to_data(big_int) - - def test_long_case(self): - config = Config() - config.default_int_type = IntType.LONG - service = SerializationServiceV1(config) - - d1 = service.to_data(byte_val) - d2 = service.to_data(short_val) - d3 = service.to_data(int_val) - d4 = service.to_data(long_val) - v1 = service.to_object(d1) - v2 = service.to_object(d2) - v3 = service.to_object(d3) - v4 = service.to_object(d4) - - self.assertEqual(d1.get_type(), CONSTANT_TYPE_LONG) - self.assertEqual(d2.get_type(), CONSTANT_TYPE_LONG) - self.assertEqual(d3.get_type(), CONSTANT_TYPE_LONG) - self.assertEqual(d4.get_type(), CONSTANT_TYPE_LONG) - self.assertEqual(v1, byte_val) - self.assertEqual(v2, short_val) - self.assertEqual(v3, int_val) - self.assertEqual(v4, long_val) - with self.assertRaises(HazelcastSerializationError): - service.to_data(big_int) From 394945486b16382c418e234e265228920d009962 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Mon, 24 Aug 2026 16:43:58 +0300 Subject: [PATCH 2/4] black --- examples/number_types/number_types_example.py | 4 +- hazelcast/__init__.py | 2 +- hazelcast/number_types.py | 45 ++++++++++++------- .../binary_compatibility_test.py | 3 +- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/examples/number_types/number_types_example.py b/examples/number_types/number_types_example.py index 3a6a319441..632c1fa092 100644 --- a/examples/number_types/number_types_example.py +++ b/examples/number_types/number_types_example.py @@ -9,7 +9,7 @@ async def amain(): map = await client.get_map("number_test") await map.set("i8", Int32(10)) value_i8 = await map.get("i8") - assert(type(value_i8) == int) + assert type(value_i8) == int -asyncio.run(amain()) +asyncio.run(amain()) diff --git a/hazelcast/__init__.py b/hazelcast/__init__.py index 4b77d715fd..66e4abca9e 100644 --- a/hazelcast/__init__.py +++ b/hazelcast/__init__.py @@ -7,4 +7,4 @@ logging.getLogger(__name__).addHandler(logging.NullHandler()) from hazelcast.client import HazelcastClient -from hazelcast.number_types import * \ No newline at end of file +from hazelcast.number_types import * diff --git a/hazelcast/number_types.py b/hazelcast/number_types.py index 1dd6e84a4e..7f420a1d2b 100644 --- a/hazelcast/number_types.py +++ b/hazelcast/number_types.py @@ -6,7 +6,6 @@ __all__ = "Int8", "Int16", "Int32", "Int64", "Float32", "Float64", "BigInt" - class Int8: """Int8 represents an 8-bit signed integer @@ -18,9 +17,13 @@ class Int8: def __init__(self, value: int): if not (self.MIN_VALUE <= value <= self.MAX_VALUE): - raise ValueError("{} value must be between {} and {}".format( - self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, - )) + raise ValueError( + "{} value must be between {} and {}".format( + self.__class__.__name__, + self.MIN_VALUE, + self.MAX_VALUE, + ) + ) self.value = value def __int__(self): @@ -41,9 +44,13 @@ class Int16: def __init__(self, value: int): if not (self.MIN_VALUE <= value <= self.MAX_VALUE): - raise ValueError("{} value must be between {} and {}".format( - self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, - )) + raise ValueError( + "{} value must be between {} and {}".format( + self.__class__.__name__, + self.MIN_VALUE, + self.MAX_VALUE, + ) + ) self.value = value def __int__(self): @@ -64,9 +71,13 @@ class Int32: def __init__(self, value: int): if not (self.MIN_VALUE <= value <= self.MAX_VALUE): - raise ValueError("{} value must be between {} and {}".format( - self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, - )) + raise ValueError( + "{} value must be between {} and {}".format( + self.__class__.__name__, + self.MIN_VALUE, + self.MAX_VALUE, + ) + ) self.value = value def __int__(self): @@ -87,9 +98,13 @@ class Int64: def __init__(self, value: int): if not (self.MIN_VALUE <= value <= self.MAX_VALUE): - raise ValueError("{} value must be between {} and {}".format( - self.__class__.__name__, self.MIN_VALUE, self.MAX_VALUE, - )) + raise ValueError( + "{} value must be between {} and {}".format( + self.__class__.__name__, + self.MIN_VALUE, + self.MAX_VALUE, + ) + ) self.value = value def __int__(self): @@ -121,7 +136,7 @@ class Float32: Corresponds to Java ``float``. """ - def __init__(self, value: float|int): + def __init__(self, value: float | int): self.value = float(value) def __float__(self): @@ -137,7 +152,7 @@ class Float64: Corresponds to Java ``double``. """ - def __init__(self, value: float|int): + def __init__(self, value: float | int): self.value = float(value) def __float__(self): diff --git a/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py b/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py index b95492cb57..7685428b6e 100644 --- a/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py +++ b/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py @@ -98,7 +98,7 @@ def test_serialize_deserialize(self, _, name, is_big_endian): ss = self._create_serialization_service(is_big_endian) obj = REFERENCE_OBJECTS[name] - if name == 'BigInteger': + if name == "BigInteger": data = ss.to_data(BigInt(obj)) else: data = ss.to_data(obj) @@ -175,4 +175,3 @@ def get_type_id(self): def destroy(self): pass - From 34159dd0b0a0e4eabb102fea5960f24a884a0738 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Mon, 24 Aug 2026 17:08:46 +0300 Subject: [PATCH 3/4] Removed test_variable_integer test --- .../serialization/serializers_test.py | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/tests/integration/backward_compatible/serialization/serializers_test.py b/tests/integration/backward_compatible/serialization/serializers_test.py index 946e9704ce..62573fd952 100644 --- a/tests/integration/backward_compatible/serialization/serializers_test.py +++ b/tests/integration/backward_compatible/serialization/serializers_test.py @@ -186,37 +186,6 @@ def test_big_integer(self): response = int(self.get_from_server()) self.assertEqual(value, response) - def test_variable_integer(self): - value = MAX_BYTE - self.map.set("key", value) - self.assertEqual(value, self.map.get("key")) - response = int(self.get_from_server()) - self.assertEqual(value, response) - - value = MAX_SHORT - self.map.set("key", value) - self.assertEqual(value, self.map.get("key")) - response = int(self.get_from_server()) - self.assertEqual(value, response) - - value = MAX_INT - self.map.set("key", value) - self.assertEqual(value, self.map.get("key")) - response = int(self.get_from_server()) - self.assertEqual(value, response) - - value = MAX_LONG - self.map.set("key", value) - self.assertEqual(value, self.map.get("key")) - response = int(self.get_from_server()) - self.assertEqual(value, response) - - value = 1234567890123456789012345678901234567890 - self.map.set("key", value) - self.assertEqual(value, self.map.get("key")) - response = int(self.get_from_server()) - self.assertEqual(value, response) - def test_decimal(self): skip_if_client_version_older_than(self, "5.0") decimal_value = "1234567890123456789012345678901234567890.987654321" From 9b459ed3076fb64464aa18bd273a98bbc4a40ea6 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Mon, 24 Aug 2026 17:25:03 +0300 Subject: [PATCH 4/4] test fix --- .../binary_compatibility/binary_compatibility_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py b/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py index 7685428b6e..023a5700ec 100644 --- a/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py +++ b/tests/unit/serialization/binary_compatibility/binary_compatibility_test.py @@ -5,7 +5,7 @@ from parameterized import parameterized from hazelcast.config import Config -from hazelcast.number_types import BigInt, Int8, Int16, Int32 +from hazelcast.number_types import BigInt, Int8, Int16, Int64 from hazelcast.serialization import BE_INT, BE_FLOAT, SerializationServiceV1 from hazelcast.serialization.api import StreamSerializer from hazelcast.serialization.input import _ObjectDataInput