This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch TINKERPOP-2279 in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit ecabb647d2e07d16972a32ef4715c735e40b7be9 Author: Stephen Mallette <[email protected]> AuthorDate: Fri Jul 26 12:37:58 2019 -0400 Added double and float graphbinary serialization in python --- .../GraphBinaryReaderWriterRoundTripTest.java | 3 ++ .../gremlin_python/structure/io/graphbinaryV1.py | 61 +++++++++++++++++++++- .../tests/structure/io/test_graphbinaryV1.py | 22 ++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java index d278602..48e324c 100644 --- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java +++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java @@ -165,6 +165,9 @@ public class GraphBinaryReaderWriterRoundTripTest { new Object[] {"Integer", 1, null}, new Object[] {"Float", 2f, null}, new Object[] {"Double", 3.1d, null}, + new Object[] {"Double", Double.NaN, null}, + new Object[] {"Double", Double.POSITIVE_INFINITY, null}, + new Object[] {"Double", Double.NEGATIVE_INFINITY, null}, new Object[] {"Long", 10122L, null}, new Object[] {"IntegerZero", 0, null}, new Object[] {"FloatZero", 0f, null}, diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py index f84d2a0..4a5dd0e 100644 --- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py +++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py @@ -54,6 +54,9 @@ class DataType(Enum): string = 0x03 date = 0x04 timestamp = 0x05 + clazz = 0x06 + double = 0x07 + float = 0x08 list = 0x09 @@ -123,8 +126,8 @@ class _GraphBinaryTypeIO(object): "set_": "set", "list_": "list", "all_": "all", "with_": "with"} @classmethod - def as_bytes(cls, graphbin_type, size=None, *args): - ba = bytearray([graphbin_type.value]) + def as_bytes(cls, graphbin_type=None, size=None, *args): + ba = bytearray() if graphbin_type is None else bytearray([graphbin_type.value]) if size is not None: ba.extend(struct.pack(">i", size)) @@ -218,6 +221,60 @@ class TimestampIO(_GraphBinaryTypeIO): return statics.timestamp(struct.unpack(">q", buff.read(8))[0] / 1000.0) +def _long_bits_to_double(bits): + return struct.unpack('d', struct.pack('Q', bits))[0] + + +NAN = _long_bits_to_double(0x7ff8000000000000) +POSITIVE_INFINITY = _long_bits_to_double(0x7ff0000000000000) +NEGATIVE_INFINITY = _long_bits_to_double(0xFff0000000000000) + + +class FloatIO(LongIO): + + python_type = FloatType + graphbinary_type = DataType.float + graphbinary_base_type = DataType.float + byte_format = ">f" + + @classmethod + def dictify(cls, obj, writer): + if math.isnan(obj): + return cls.as_bytes(cls.graphbinary_base_type, None, struct.pack(cls.byte_format, NAN)) + elif math.isinf(obj) and obj > 0: + return cls.as_bytes(cls.graphbinary_base_type, None, struct.pack(cls.byte_format, POSITIVE_INFINITY)) + elif math.isinf(obj) and obj < 0: + return cls.as_bytes(cls.graphbinary_base_type, None, struct.pack(cls.byte_format, NEGATIVE_INFINITY)) + else: + return cls.as_bytes(cls.graphbinary_base_type, None, struct.pack(cls.byte_format, obj)) + + @classmethod + def objectify(cls, buff, reader): + return struct.unpack(cls.byte_format, buff.read(4))[0] + + +class DoubleIO(FloatIO): + """ + Floats basically just fall through to double serialization. + """ + + graphbinary_type = DataType.double + graphbinary_base_type = DataType.double + byte_format = ">d" + + @classmethod + def objectify(cls, buff, reader): + return struct.unpack(cls.byte_format, buff.read(8))[0] + + +class TypeSerializer(_GraphBinaryTypeIO): + python_type = TypeType + + @classmethod + def dictify(cls, typ, writer): + return writer.toDict(typ()) + + class StringIO(_GraphBinaryTypeIO): python_type = str diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py index db58545..75b4392 100644 --- a/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py +++ b/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py @@ -54,6 +54,28 @@ class TestGraphSONWriter(object): output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x)) assert x == output + def test_float(self): + x = float(100.001) + output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x)) + assert x == output + + x = float('nan') + output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x)) + assert math.isnan(output) + + x = float('-inf') + output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x)) + assert math.isinf(output) and output < 0 + + x = float('inf') + output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x)) + assert math.isinf(output) and output > 0 + + def test_double(self): + x = 100.001 + output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x)) + assert x == output + def test_date(self): x = calendar.timegm(datetime.datetime(2016, 12, 14, 16, 14, 36, 295000).utctimetuple()) output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
