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/19 13:37:05 UTC

[tinkerpop] 01/33: Initial setup for GraphBinary 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 391efe0678ceb5e856f68aa15d0d1818bf65b6b0
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Mon Jul 22 09:35:05 2019 -0400

    Initial setup for GraphBinary in Python
---
 .../gremlin_python/structure/io/graphbinaryV1.py   | 151 +++++++++++++++++++++
 .../tests/structure/io/test_graphbinaryV1.py       |  49 +++++++
 2 files changed, 200 insertions(+)

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
new file mode 100644
index 0000000..4eff156
--- /dev/null
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphbinaryV1.py
@@ -0,0 +1,151 @@
+"""
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+"""
+import datetime
+import struct
+import time
+import uuid
+import math
+import base64
+import numbers
+from collections import OrderedDict
+from decimal import *
+import logging
+from datetime import timedelta
+
+import six
+from aenum import Enum
+from isodate import parse_duration, duration_isoformat
+
+from gremlin_python import statics
+from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, SingleChar
+from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy, T
+from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
+
+log = logging.getLogger(__name__)
+
+# When we fall back to a superclass's serializer, we iterate over this map.
+# We want that iteration order to be consistent, so we use an OrderedDict,
+# not a dict.
+_serializers = OrderedDict()
+_deserializers = {}
+
+
+class DataType(Enum):
+    string = 0x03
+
+
+class GraphBinaryTypeType(type):
+    def __new__(mcs, name, bases, dct):
+        cls = super(GraphBinaryTypeType, mcs).__new__(mcs, name, bases, dct)
+        if not name.startswith('_'):
+            if cls.python_type:
+                _serializers[cls.python_type] = cls
+            if cls.graphbinary_type:
+                _deserializers[cls.graphbinary_type] = cls
+        return cls
+
+
+class GraphBinaryWriter(object):
+    def __init__(self, serializer_map=None):
+        self.serializers = _serializers.copy()
+        if serializer_map:
+            self.serializers.update(serializer_map)
+
+    def writeObject(self, objectData):
+        return self.toDict(objectData)
+
+    def toDict(self, obj):
+        try:
+            return self.serializers[type(obj)].dictify(obj, self)
+        except KeyError:
+            for key, serializer in self.serializers.items():
+                if isinstance(obj, key):
+                    return serializer.dictify(obj, self)
+
+        if isinstance(obj, dict):
+            return dict((self.toDict(k), self.toDict(v)) for k, v in obj.items())
+        elif isinstance(obj, set):
+            return set([self.toDict(o) for o in obj])
+        elif isinstance(obj, list):
+            return [self.toDict(o) for o in obj]
+        else:
+            return obj
+
+
+class GraphBinaryReader(object):
+    def __init__(self, deserializer_map=None):
+        self.deserializers = _deserializers.copy()
+        if deserializer_map:
+            self.deserializers.update(deserializer_map)
+
+    def readObject(self, b):
+        return self.toObject(b)
+
+    def toObject(self, obj):
+        binary_type, rest = DataType(obj[0]), obj[1:]
+        return self.deserializers[binary_type].objectify(rest, self)
+
+
+@six.add_metaclass(GraphBinaryTypeType)
+class _GraphBinaryTypeIO(object):
+    python_type = None
+    graphbinary_type = None
+
+    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
+                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
+                 "set_": "set", "list_": "list", "all_": "all", "with_": "with"}
+
+    @classmethod
+    def as_bytes(cls, graphbin_type, *args):
+        ba = bytearray([graphbin_type.value])
+        for arg in args:
+            if isinstance(arg, str):
+                ba.extend(arg.encode("utf-8"))
+            elif isinstance(arg, numbers.Number):
+                ba.extend(bytes([arg]))
+            elif isinstance(arg, (bytes, bytearray)):
+                ba.extend(arg)
+        return ba
+
+    @classmethod
+    def unmangleKeyword(cls, symbol):
+        return cls.symbolMap.get(symbol, symbol)
+
+    def dictify(self, obj, writer):
+        raise NotImplementedError()
+
+    def objectify(self, d, reader):
+        raise NotImplementedError()
+
+
+class StringIO(_GraphBinaryTypeIO):
+
+    python_type = str
+    graphbinary_type = DataType.string
+
+    @classmethod
+    def dictify(cls, n, writer):
+        return cls.as_bytes(cls.graphbinary_type, len(n), n)
+
+    @classmethod
+    def objectify(cls, b, reader):
+        len_block, rest = b[0:4], b[4:]
+        size = struct.unpack("<L", len_block)[0]
+        string_block, b = rest[0:size], rest[size:]
+        return string_block
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
new file mode 100644
index 0000000..9eb82cf
--- /dev/null
+++ b/gremlin-python/src/main/jython/tests/structure/io/test_graphbinaryV1.py
@@ -0,0 +1,49 @@
+"""
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+"""
+
+import datetime
+import time
+import uuid
+import math
+from decimal import *
+
+from mock import Mock
+
+import six
+
+from gremlin_python.statics import *
+from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
+from gremlin_python.structure.io.graphbinaryV1 import GraphBinaryWriter, GraphBinaryReader, DataType
+from gremlin_python.process.traversal import P
+from gremlin_python.process.strategies import SubgraphStrategy
+from gremlin_python.process.graph_traversal import __
+
+
+class TestGraphBinaryReader(object):
+    graphbinary_reader = GraphBinaryReader()
+
+
+class TestGraphSONWriter(object):
+    graphbinary_writer = GraphBinaryWriter()
+    graphbinary_reader = GraphBinaryReader()
+
+    def test_string(self):
+        x = "serialize this!"
+        output = self.graphbinary_reader.readObject(self.graphbinary_writer.writeObject(x))
+        assert x == output