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:12:59 UTC
[tinkerpop] 01/23: 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 f2a929aaea542b2e4bc1ac552690a6ed928c906f
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