You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2019/08/09 19:13:06 UTC

[tinkerpop] 08/23: Added double and float graphbinary serialization in python

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 16626d2d0c9db306829ef0225af8152e556d381b
Author: Stephen Mallette <sp...@genoprime.com>
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))