You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2017/07/06 21:56:55 UTC

[2/2] tinkerpop git commit: 99 percent complete GraphSON 3.0 working with Gremlin-Python. Extended test suite to support both GraphSON 2.0 and GraphSON 3.0 testing. There is one last requirement to do on the code -- a version flag on GraphSONMessageSeria

99 percent complete GraphSON 3.0 working with Gremlin-Python. Extended test suite to support both GraphSON 2.0 and GraphSON 3.0 testing. There is one last requirement to do on the code -- a version flag on GraphSONMessageSerializer. However, for some reason application/gremlin-v3.0 mime type stuff doesn't work for the Python->GremlinServer tests... Committing what I have so far as I think the issue might be an easy .yaml file fix or something. Dunno.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/b30b56b4
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/b30b56b4
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/b30b56b4

Branch: refs/heads/TINKERPOP-1427
Commit: b30b56b44a013ff024aa9908df955f01f0e27311
Parents: 3c241bc
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jul 6 15:56:46 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jul 6 15:56:46 2017 -0600

----------------------------------------------------------------------
 .../io/graphson/TraversalSerializersV3d0.java   |  14 +-
 .../jython/gremlin_python/driver/serializer.py  |  32 +-
 .../src/main/jython/gremlin_python/statics.py   |   6 +
 .../gremlin_python/structure/io/graphson.py     | 400 ----------------
 .../gremlin_python/structure/io/graphsonV2d0.py | 400 ++++++++++++++++
 .../gremlin_python/structure/io/graphsonV3d0.py | 466 +++++++++++++++++++
 .../jython/tests/structure/io/test_graphson.py  | 271 -----------
 .../tests/structure/io/test_graphsonV2d0.py     | 273 +++++++++++
 .../tests/structure/io/test_graphsonV3d0.py     | 287 ++++++++++++
 .../python/jsr223/JythonScriptEngineSetup.java  |   9 +-
 .../jsr223/PythonGraphSONJavaTranslator.java    |  29 +-
 .../gremlin/python/jsr223/PythonProvider.java   |   9 +-
 .../io/graphson/GraphSONReaderTest.java         | 149 +++---
 .../io/graphson/GraphSONWriterTest.java         | 142 +++---
 14 files changed, 1667 insertions(+), 820 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
index 57b6736..c629b3f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
@@ -38,7 +38,6 @@ import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
 import org.apache.tinkerpop.shaded.jackson.core.JsonToken;
 import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext;
 import org.apache.tinkerpop.shaded.jackson.databind.JavaType;
-import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
 import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
 import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer;
 import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
@@ -160,16 +159,9 @@ final class TraversalSerializersV3d0 {
                     jsonGenerator.writeObject(predicate);
                 }
                 jsonGenerator.writeEndArray();
-            } else {
-                if (p.getValue() instanceof Collection) {
-                    jsonGenerator.writeArrayFieldStart(GraphSONTokens.VALUE);
-                    for (final Object object : (Collection) p.getValue()) {
-                        jsonGenerator.writeObject(object);
-                    }
-                    jsonGenerator.writeEndArray();
-                } else
-                    jsonGenerator.writeObjectField(GraphSONTokens.VALUE, p.getValue());
-            }
+            } else
+                jsonGenerator.writeObjectField(GraphSONTokens.VALUE, p.getValue());
+
             jsonGenerator.writeEndObject();
         }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py b/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
index a29d4dc..3248b4e 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
@@ -21,7 +21,8 @@ try:
 except ImportError:
     import json
 
-from gremlin_python.structure.io import graphson
+from gremlin_python.structure.io import graphsonV2d0
+from gremlin_python.structure.io import graphsonV3d0
 
 __author__ = 'David M. Brown (davebshow@gmail.com)'
 
@@ -85,10 +86,10 @@ class GraphSONMessageSerializer:
 
     def __init__(self, reader=None, writer=None):
         if not reader:
-            reader = graphson.GraphSONReader()
+            reader = graphsonV2d0.GraphSONReader()
         self._graphson_reader = reader
         if not writer:
-            writer = graphson.GraphSONWriter()
+            writer = graphsonV2d0.GraphSONWriter()
         self.standard = Standard(writer)
         self.traversal = Traversal(writer)
 
@@ -127,3 +128,28 @@ class GraphSONMessageSerializer:
 
     def deserialize_message(self, message):
         return self._graphson_reader.toObject(message)
+
+class GraphSONSerializersV2d0(GraphSONMessageSerializer):
+    """Message serializer for GraphSON 2.0"""
+
+    def __init__(self, reader=None, writer=None):
+        GraphSONMessageSerializer.__init__(self, reader, writer, "2.0")
+        if not reader:
+            self._graphson_reader = graphsonV2d0.GraphSONReader()
+        if not writer:
+            self._graphson_writer = graphsonV2d0.GraphSONWriter()
+        self.standard = Standard(self._graphson_writer)
+        self.traversal = Traversal(self._graphson_writer)
+
+
+class GraphSONSerializersV3d0(GraphSONMessageSerializer):
+    """Message serializer for GraphSON 3.0"""
+
+    def __init__(self, reader=None, writer=None):
+        GraphSONMessageSerializer.__init__(self, reader, writer, "3.0")
+        if not reader:
+            self._graphson_reader = graphsonV3d0.GraphSONReader()
+        if not writer:
+            self._graphson_writer = graphsonV3d0.GraphSONWriter()
+        self.standard = Standard(self._graphson_writer)
+        self.traversal = Traversal(self._graphson_writer)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-python/src/main/jython/gremlin_python/statics.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/statics.py b/gremlin-python/src/main/jython/gremlin_python/statics.py
index a1abf8e..28cae14 100644
--- a/gremlin-python/src/main/jython/gremlin_python/statics.py
+++ b/gremlin-python/src/main/jython/gremlin_python/statics.py
@@ -29,12 +29,18 @@ if six.PY3:
     IntType = int
     LongType = long
     TypeType = type
+    ListType = list
+    DictType = dict
+    SetType = set
 else:
     long = long
+    SetType = set
     from types import FloatType
     from types import IntType
     from types import LongType
     from types import TypeType
+    from types import ListType
+    from types import DictType
 
 staticMethods = {}
 staticEnums = {}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
deleted file mode 100644
index 5c7ccdb..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
+++ /dev/null
@@ -1,400 +0,0 @@
-'''
-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.
-'''
-from aenum import Enum
-import json
-import six
-
-from gremlin_python import statics
-from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType
-from gremlin_python.process.traversal import Binding, Bytecode, P, Traversal, Traverser, TraversalStrategy
-from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
-
-_serializers = {}
-_deserializers = {}
-
-
-class GraphSONTypeType(type):
-    def __new__(mcs, name, bases, dct):
-        cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
-        if not name.startswith('_'):
-            if cls.python_type:
-                _serializers[cls.python_type] = cls
-            if cls.graphson_type:
-                _deserializers[cls.graphson_type] = cls
-        return cls
-
-
-class GraphSONUtil(object):
-    TYPE_KEY = "@type"
-    VALUE_KEY = "@value"
-
-    @classmethod
-    def typedValue(cls, type_name, value, prefix="g"):
-        out = {cls.TYPE_KEY: cls.formatType(prefix, type_name)}
-        if value is not None:
-            out[cls.VALUE_KEY] = value
-        return out
-
-    @classmethod
-    def formatType(cls, prefix, type_name):
-        return "%s:%s" % (prefix, type_name)
-
-
-# Read/Write classes split to follow precedence of the Java API
-class GraphSONWriter(object):
-    def __init__(self, serializer_map=None):
-        """
-        :param serializer_map: map from Python type to serializer instance implementing `dictify`
-        """
-        self.serializers = _serializers.copy()
-        if serializer_map:
-            self.serializers.update(serializer_map)
-
-    def writeObject(self, objectData):
-        # to JSON
-        return json.dumps(self.toDict(objectData), separators=(',', ':'))
-
-    def toDict(self, obj):
-        """
-        Encodes python objects in GraphSON type-tagged dict values
-        """
-        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)
-
-        # list and map are treated as normal json objs (could be isolated serializers)
-        if isinstance(obj, (list, set)):
-            return [self.toDict(o) for o in obj]
-        elif isinstance(obj, dict):
-            return dict((self.toDict(k), self.toDict(v)) for k, v in obj.items())
-        else:
-            return obj
-
-
-class GraphSONReader(object):
-    def __init__(self, deserializer_map=None):
-        """
-        :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
-        """
-        self.deserializers = _deserializers.copy()
-        if deserializer_map:
-            self.deserializers.update(deserializer_map)
-
-    def readObject(self, jsonData):
-        # from JSON
-        return self.toObject(json.loads(jsonData))
-
-    def toObject(self, obj):
-        """
-        Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
-        """
-        if isinstance(obj, dict):
-            try:
-                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
-            except KeyError:
-                pass
-            # list and map are treated as normal json objs (could be isolated deserializers)
-            return dict((self.toObject(k), self.toObject(v)) for k, v in obj.items())
-        elif isinstance(obj, list):
-            return [self.toObject(o) for o in obj]
-        else:
-            return obj
-
-
-@six.add_metaclass(GraphSONTypeType)
-class _GraphSONTypeIO(object):
-    python_type = None
-    graphson_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"}
-
-    @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 _BytecodeSerializer(_GraphSONTypeIO):
-    @classmethod
-    def _dictify_instructions(cls, instructions, writer):
-        out = []
-        for instruction in instructions:
-            inst = [instruction[0]]
-            inst.extend(writer.toDict(arg) for arg in instruction[1:])
-            out.append(inst)
-        return out
-
-    @classmethod
-    def dictify(cls, bytecode, writer):
-        if isinstance(bytecode, Traversal):
-            bytecode = bytecode.bytecode
-        out = {}
-        if bytecode.source_instructions:
-            out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
-        if bytecode.step_instructions:
-            out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
-        return GraphSONUtil.typedValue("Bytecode", out)
-
-
-class TraversalSerializer(_BytecodeSerializer):
-    python_type = Traversal
-
-
-class BytecodeSerializer(_BytecodeSerializer):
-    python_type = Bytecode
-
-
-class VertexSerializer(_GraphSONTypeIO):
-    python_type = Vertex
-    graphson_type = "g:Vertex"
-
-    @classmethod
-    def dictify(cls, vertex, writer):
-        return GraphSONUtil.typedValue("Vertex", {"id": writer.toDict(vertex.id),
-                                                  "label": writer.toDict(vertex.label)})
-
-
-class EdgeSerializer(_GraphSONTypeIO):
-    python_type = Edge
-    graphson_type = "g:Edge"
-
-    @classmethod
-    def dictify(cls, edge, writer):
-        return GraphSONUtil.typedValue("Edge", {"id": writer.toDict(edge.id),
-                                                "outV": writer.toDict(edge.outV.id),
-                                                "outVLabel": writer.toDict(edge.outV.label),
-                                                "label": writer.toDict(edge.label),
-                                                "inV": writer.toDict(edge.inV.id),
-                                                "inVLabel": writer.toDict(edge.inV.label)})
-
-
-class VertexPropertySerializer(_GraphSONTypeIO):
-    python_type = VertexProperty
-    graphson_type = "g:VertexProperty"
-
-    @classmethod
-    def dictify(cls, vertex_property, writer):
-        return GraphSONUtil.typedValue("VertexProperty", {"id": writer.toDict(vertex_property.id),
-                                                          "label": writer.toDict(vertex_property.label),
-                                                          "value": writer.toDict(vertex_property.value),
-                                                          "vertex": writer.toDict(vertex_property.vertex.id)})
-
-
-class PropertySerializer(_GraphSONTypeIO):
-    python_type = Property
-    graphson_type = "g:Property"
-
-    @classmethod
-    def dictify(cls, property, writer):
-        elementDict = writer.toDict(property.element)
-        if elementDict is not None:
-            valueDict = elementDict["@value"]
-            if "outVLabel" in valueDict:
-                del valueDict["outVLabel"]
-            if "inVLabel" in valueDict:
-                del valueDict["inVLabel"]
-            if "properties" in valueDict:
-                del valueDict["properties"]
-            if "value" in valueDict:
-                del valueDict["value"]
-        return GraphSONUtil.typedValue("Property", {"key": writer.toDict(property.key),
-                                                    "value": writer.toDict(property.value),
-                                                    "element": elementDict})
-
-
-class TraversalStrategySerializer(_GraphSONTypeIO):
-    python_type = TraversalStrategy
-
-    @classmethod
-    def dictify(cls, strategy, writer):
-        return GraphSONUtil.typedValue(strategy.strategy_name, writer.toDict(strategy.configuration))
-
-
-class TraverserIO(_GraphSONTypeIO):
-    python_type = Traverser
-    graphson_type = "g:Traverser"
-
-    @classmethod
-    def dictify(cls, traverser, writer):
-        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
-                                                     "bulk": writer.toDict(traverser.bulk)})
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Traverser(reader.toObject(d["value"]),
-                         reader.toObject(d["bulk"]))
-
-
-class EnumSerializer(_GraphSONTypeIO):
-    python_type = Enum
-
-    @classmethod
-    def dictify(cls, enum, _):
-        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
-                                       cls.unmangleKeyword(str(enum.name)))
-
-
-class PSerializer(_GraphSONTypeIO):
-    python_type = P
-
-    @classmethod
-    def dictify(cls, p, writer):
-        out = {"predicate": p.operator,
-               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
-               writer.toDict(p.value)}
-        return GraphSONUtil.typedValue("P", out)
-
-
-class BindingSerializer(_GraphSONTypeIO):
-    python_type = Binding
-
-    @classmethod
-    def dictify(cls, binding, writer):
-        out = {"key": binding.key,
-               "value": writer.toDict(binding.value)}
-        return GraphSONUtil.typedValue("Binding", out)
-
-
-class LambdaSerializer(_GraphSONTypeIO):
-    python_type = FunctionType
-
-    @classmethod
-    def dictify(cls, lambda_object, writer):
-        lambda_result = lambda_object()
-        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
-        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
-        out = {"script": script,
-               "language": language}
-        if language == "gremlin-jython" or language == "gremlin-python":
-            if not script.strip().startswith("lambda"):
-                script = "lambda " + script
-                out["script"] = script
-            out["arguments"] = six.get_function_code(eval(out["script"])).co_argcount
-        else:
-            out["arguments"] = -1
-        return GraphSONUtil.typedValue("Lambda", out)
-
-
-class TypeSerializer(_GraphSONTypeIO):
-    python_type = TypeType
-
-    @classmethod
-    def dictify(cls, typ, writer):
-        return writer.toDict(typ())
-
-
-class _NumberIO(_GraphSONTypeIO):
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
-            return n
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-    @classmethod
-    def objectify(cls, v, _):
-        return cls.python_type(v)
-
-
-class FloatIO(_NumberIO):
-    python_type = FloatType
-    graphson_type = "g:Float"
-    graphson_base_type = "Float"
-
-
-class DoubleIO(FloatIO):
-    graphson_type = "g:Double"
-    graphson_base_type = "Double"
-
-
-class Int64IO(_NumberIO):
-    python_type = LongType
-    graphson_type = "g:Int64"
-    graphson_base_type = "Int64"
-
-
-class Int32IO(_NumberIO):
-    python_type = IntType
-    graphson_type = "g:Int32"
-    graphson_base_type = "Int32"
-
-    @classmethod
-    def dictify(cls, n, writer):
-        if isinstance(n, bool):
-            return n
-        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
-
-
-class VertexDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Vertex"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Vertex(reader.toObject(d["id"]), d.get("label", "vertex"))
-
-
-class EdgeDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Edge"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        return Edge(reader.toObject(d["id"]),
-                    Vertex(reader.toObject(d["outV"]), d.get("outVLabel", "vertex")),
-                    d.get("label", "edge"),
-                    Vertex(reader.toObject(d["inV"]), d.get("inVLabel", "vertex")))
-
-
-class VertexPropertyDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:VertexProperty"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        vertex = Vertex(reader.toObject(d.get("vertex"))) if "vertex" in d else None
-        return VertexProperty(reader.toObject(d["id"]),
-                              d["label"],
-                              reader.toObject(d["value"]),
-                              vertex)
-
-
-class PropertyDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Property"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        element = reader.toObject(d["element"]) if "element" in d else None
-        return Property(d["key"], reader.toObject(d["value"]), element)
-
-
-class PathDeserializer(_GraphSONTypeIO):
-    graphson_type = "g:Path"
-
-    @classmethod
-    def objectify(cls, d, reader):
-        labels = [set(label) for label in d["labels"]]
-        objects = [reader.toObject(o) for o in d["objects"]]
-        return Path(labels, objects)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
new file mode 100644
index 0000000..5c7ccdb
--- /dev/null
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
@@ -0,0 +1,400 @@
+'''
+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.
+'''
+from aenum import Enum
+import json
+import six
+
+from gremlin_python import statics
+from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType
+from gremlin_python.process.traversal import Binding, Bytecode, P, Traversal, Traverser, TraversalStrategy
+from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
+
+_serializers = {}
+_deserializers = {}
+
+
+class GraphSONTypeType(type):
+    def __new__(mcs, name, bases, dct):
+        cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
+        if not name.startswith('_'):
+            if cls.python_type:
+                _serializers[cls.python_type] = cls
+            if cls.graphson_type:
+                _deserializers[cls.graphson_type] = cls
+        return cls
+
+
+class GraphSONUtil(object):
+    TYPE_KEY = "@type"
+    VALUE_KEY = "@value"
+
+    @classmethod
+    def typedValue(cls, type_name, value, prefix="g"):
+        out = {cls.TYPE_KEY: cls.formatType(prefix, type_name)}
+        if value is not None:
+            out[cls.VALUE_KEY] = value
+        return out
+
+    @classmethod
+    def formatType(cls, prefix, type_name):
+        return "%s:%s" % (prefix, type_name)
+
+
+# Read/Write classes split to follow precedence of the Java API
+class GraphSONWriter(object):
+    def __init__(self, serializer_map=None):
+        """
+        :param serializer_map: map from Python type to serializer instance implementing `dictify`
+        """
+        self.serializers = _serializers.copy()
+        if serializer_map:
+            self.serializers.update(serializer_map)
+
+    def writeObject(self, objectData):
+        # to JSON
+        return json.dumps(self.toDict(objectData), separators=(',', ':'))
+
+    def toDict(self, obj):
+        """
+        Encodes python objects in GraphSON type-tagged dict values
+        """
+        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)
+
+        # list and map are treated as normal json objs (could be isolated serializers)
+        if isinstance(obj, (list, set)):
+            return [self.toDict(o) for o in obj]
+        elif isinstance(obj, dict):
+            return dict((self.toDict(k), self.toDict(v)) for k, v in obj.items())
+        else:
+            return obj
+
+
+class GraphSONReader(object):
+    def __init__(self, deserializer_map=None):
+        """
+        :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
+        """
+        self.deserializers = _deserializers.copy()
+        if deserializer_map:
+            self.deserializers.update(deserializer_map)
+
+    def readObject(self, jsonData):
+        # from JSON
+        return self.toObject(json.loads(jsonData))
+
+    def toObject(self, obj):
+        """
+        Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
+        """
+        if isinstance(obj, dict):
+            try:
+                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
+            except KeyError:
+                pass
+            # list and map are treated as normal json objs (could be isolated deserializers)
+            return dict((self.toObject(k), self.toObject(v)) for k, v in obj.items())
+        elif isinstance(obj, list):
+            return [self.toObject(o) for o in obj]
+        else:
+            return obj
+
+
+@six.add_metaclass(GraphSONTypeType)
+class _GraphSONTypeIO(object):
+    python_type = None
+    graphson_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"}
+
+    @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 _BytecodeSerializer(_GraphSONTypeIO):
+    @classmethod
+    def _dictify_instructions(cls, instructions, writer):
+        out = []
+        for instruction in instructions:
+            inst = [instruction[0]]
+            inst.extend(writer.toDict(arg) for arg in instruction[1:])
+            out.append(inst)
+        return out
+
+    @classmethod
+    def dictify(cls, bytecode, writer):
+        if isinstance(bytecode, Traversal):
+            bytecode = bytecode.bytecode
+        out = {}
+        if bytecode.source_instructions:
+            out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
+        if bytecode.step_instructions:
+            out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
+        return GraphSONUtil.typedValue("Bytecode", out)
+
+
+class TraversalSerializer(_BytecodeSerializer):
+    python_type = Traversal
+
+
+class BytecodeSerializer(_BytecodeSerializer):
+    python_type = Bytecode
+
+
+class VertexSerializer(_GraphSONTypeIO):
+    python_type = Vertex
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def dictify(cls, vertex, writer):
+        return GraphSONUtil.typedValue("Vertex", {"id": writer.toDict(vertex.id),
+                                                  "label": writer.toDict(vertex.label)})
+
+
+class EdgeSerializer(_GraphSONTypeIO):
+    python_type = Edge
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def dictify(cls, edge, writer):
+        return GraphSONUtil.typedValue("Edge", {"id": writer.toDict(edge.id),
+                                                "outV": writer.toDict(edge.outV.id),
+                                                "outVLabel": writer.toDict(edge.outV.label),
+                                                "label": writer.toDict(edge.label),
+                                                "inV": writer.toDict(edge.inV.id),
+                                                "inVLabel": writer.toDict(edge.inV.label)})
+
+
+class VertexPropertySerializer(_GraphSONTypeIO):
+    python_type = VertexProperty
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def dictify(cls, vertex_property, writer):
+        return GraphSONUtil.typedValue("VertexProperty", {"id": writer.toDict(vertex_property.id),
+                                                          "label": writer.toDict(vertex_property.label),
+                                                          "value": writer.toDict(vertex_property.value),
+                                                          "vertex": writer.toDict(vertex_property.vertex.id)})
+
+
+class PropertySerializer(_GraphSONTypeIO):
+    python_type = Property
+    graphson_type = "g:Property"
+
+    @classmethod
+    def dictify(cls, property, writer):
+        elementDict = writer.toDict(property.element)
+        if elementDict is not None:
+            valueDict = elementDict["@value"]
+            if "outVLabel" in valueDict:
+                del valueDict["outVLabel"]
+            if "inVLabel" in valueDict:
+                del valueDict["inVLabel"]
+            if "properties" in valueDict:
+                del valueDict["properties"]
+            if "value" in valueDict:
+                del valueDict["value"]
+        return GraphSONUtil.typedValue("Property", {"key": writer.toDict(property.key),
+                                                    "value": writer.toDict(property.value),
+                                                    "element": elementDict})
+
+
+class TraversalStrategySerializer(_GraphSONTypeIO):
+    python_type = TraversalStrategy
+
+    @classmethod
+    def dictify(cls, strategy, writer):
+        return GraphSONUtil.typedValue(strategy.strategy_name, writer.toDict(strategy.configuration))
+
+
+class TraverserIO(_GraphSONTypeIO):
+    python_type = Traverser
+    graphson_type = "g:Traverser"
+
+    @classmethod
+    def dictify(cls, traverser, writer):
+        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
+                                                     "bulk": writer.toDict(traverser.bulk)})
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Traverser(reader.toObject(d["value"]),
+                         reader.toObject(d["bulk"]))
+
+
+class EnumSerializer(_GraphSONTypeIO):
+    python_type = Enum
+
+    @classmethod
+    def dictify(cls, enum, _):
+        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
+                                       cls.unmangleKeyword(str(enum.name)))
+
+
+class PSerializer(_GraphSONTypeIO):
+    python_type = P
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("P", out)
+
+
+class BindingSerializer(_GraphSONTypeIO):
+    python_type = Binding
+
+    @classmethod
+    def dictify(cls, binding, writer):
+        out = {"key": binding.key,
+               "value": writer.toDict(binding.value)}
+        return GraphSONUtil.typedValue("Binding", out)
+
+
+class LambdaSerializer(_GraphSONTypeIO):
+    python_type = FunctionType
+
+    @classmethod
+    def dictify(cls, lambda_object, writer):
+        lambda_result = lambda_object()
+        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
+        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
+        out = {"script": script,
+               "language": language}
+        if language == "gremlin-jython" or language == "gremlin-python":
+            if not script.strip().startswith("lambda"):
+                script = "lambda " + script
+                out["script"] = script
+            out["arguments"] = six.get_function_code(eval(out["script"])).co_argcount
+        else:
+            out["arguments"] = -1
+        return GraphSONUtil.typedValue("Lambda", out)
+
+
+class TypeSerializer(_GraphSONTypeIO):
+    python_type = TypeType
+
+    @classmethod
+    def dictify(cls, typ, writer):
+        return writer.toDict(typ())
+
+
+class _NumberIO(_GraphSONTypeIO):
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+    @classmethod
+    def objectify(cls, v, _):
+        return cls.python_type(v)
+
+
+class FloatIO(_NumberIO):
+    python_type = FloatType
+    graphson_type = "g:Float"
+    graphson_base_type = "Float"
+
+
+class DoubleIO(FloatIO):
+    graphson_type = "g:Double"
+    graphson_base_type = "Double"
+
+
+class Int64IO(_NumberIO):
+    python_type = LongType
+    graphson_type = "g:Int64"
+    graphson_base_type = "Int64"
+
+
+class Int32IO(_NumberIO):
+    python_type = IntType
+    graphson_type = "g:Int32"
+    graphson_base_type = "Int32"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+
+class VertexDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Vertex(reader.toObject(d["id"]), d.get("label", "vertex"))
+
+
+class EdgeDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Edge(reader.toObject(d["id"]),
+                    Vertex(reader.toObject(d["outV"]), d.get("outVLabel", "vertex")),
+                    d.get("label", "edge"),
+                    Vertex(reader.toObject(d["inV"]), d.get("inVLabel", "vertex")))
+
+
+class VertexPropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        vertex = Vertex(reader.toObject(d.get("vertex"))) if "vertex" in d else None
+        return VertexProperty(reader.toObject(d["id"]),
+                              d["label"],
+                              reader.toObject(d["value"]),
+                              vertex)
+
+
+class PropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Property"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        element = reader.toObject(d["element"]) if "element" in d else None
+        return Property(d["key"], reader.toObject(d["value"]), element)
+
+
+class PathDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Path"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        labels = [set(label) for label in d["labels"]]
+        objects = [reader.toObject(o) for o in d["objects"]]
+        return Path(labels, objects)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
new file mode 100644
index 0000000..1818df7
--- /dev/null
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
@@ -0,0 +1,466 @@
+'''
+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.
+'''
+from aenum import Enum
+import json
+import six
+
+from gremlin_python import statics
+from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType
+from gremlin_python.process.traversal import Binding, Bytecode, P, Traversal, Traverser, TraversalStrategy
+from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
+
+_serializers = {}
+_deserializers = {}
+
+
+class GraphSONTypeType(type):
+    def __new__(mcs, name, bases, dct):
+        cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
+        if not name.startswith('_'):
+            if cls.python_type:
+                _serializers[cls.python_type] = cls
+            if cls.graphson_type:
+                _deserializers[cls.graphson_type] = cls
+        return cls
+
+
+class GraphSONUtil(object):
+    TYPE_KEY = "@type"
+    VALUE_KEY = "@value"
+
+    @classmethod
+    def typedValue(cls, type_name, value, prefix="g"):
+        out = {cls.TYPE_KEY: cls.formatType(prefix, type_name)}
+        if value is not None:
+            out[cls.VALUE_KEY] = value
+        return out
+
+    @classmethod
+    def formatType(cls, prefix, type_name):
+        return "%s:%s" % (prefix, type_name)
+
+
+# Read/Write classes split to follow precedence of the Java API
+class GraphSONWriter(object):
+    def __init__(self, serializer_map=None):
+        """
+        :param serializer_map: map from Python type to serializer instance implementing `dictify`
+        """
+        self.serializers = _serializers.copy()
+        if serializer_map:
+            self.serializers.update(serializer_map)
+
+    def writeObject(self, objectData):
+        # to JSON
+        return json.dumps(self.toDict(objectData), separators=(',', ':'))
+
+    def toDict(self, obj):
+        """
+        Encodes python objects in GraphSON type-tagged dict values
+        """
+        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 GraphSONReader(object):
+    def __init__(self, deserializer_map=None):
+        """
+        :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
+        """
+        self.deserializers = _deserializers.copy()
+        if deserializer_map:
+            self.deserializers.update(deserializer_map)
+
+    def readObject(self, jsonData):
+        # from JSON
+        return self.toObject(json.loads(jsonData))
+
+    def toObject(self, obj):
+        """
+        Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
+        """
+        if isinstance(obj, dict):
+            try:
+                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
+            except KeyError:
+                pass
+            return dict((self.toObject(k), self.toObject(v)) for k, v in obj.items())
+        elif isinstance(obj, set):
+            return set([self.toObject(o) for o in obj])
+        elif isinstance(obj, list):
+            return [self.toObject(o) for o in obj]
+        else:
+            return obj
+
+
+@six.add_metaclass(GraphSONTypeType)
+class _GraphSONTypeIO(object):
+    python_type = None
+    graphson_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"}
+
+    @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 _BytecodeSerializer(_GraphSONTypeIO):
+    @classmethod
+    def _dictify_instructions(cls, instructions, writer):
+        out = []
+        for instruction in instructions:
+            inst = [instruction[0]]
+            inst.extend(writer.toDict(arg) for arg in instruction[1:])
+            out.append(inst)
+        return out
+
+    @classmethod
+    def dictify(cls, bytecode, writer):
+        if isinstance(bytecode, Traversal):
+            bytecode = bytecode.bytecode
+        out = {}
+        if bytecode.source_instructions:
+            out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
+        if bytecode.step_instructions:
+            out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
+        return GraphSONUtil.typedValue("Bytecode", out)
+
+
+class TraversalSerializer(_BytecodeSerializer):
+    python_type = Traversal
+
+
+class BytecodeSerializer(_BytecodeSerializer):
+    python_type = Bytecode
+
+
+class VertexSerializer(_GraphSONTypeIO):
+    python_type = Vertex
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def dictify(cls, vertex, writer):
+        return GraphSONUtil.typedValue("Vertex", {"id": writer.toDict(vertex.id),
+                                                  "label": writer.toDict(vertex.label)})
+
+
+class EdgeSerializer(_GraphSONTypeIO):
+    python_type = Edge
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def dictify(cls, edge, writer):
+        return GraphSONUtil.typedValue("Edge", {"id": writer.toDict(edge.id),
+                                                "outV": writer.toDict(edge.outV.id),
+                                                "outVLabel": writer.toDict(edge.outV.label),
+                                                "label": writer.toDict(edge.label),
+                                                "inV": writer.toDict(edge.inV.id),
+                                                "inVLabel": writer.toDict(edge.inV.label)})
+
+
+class VertexPropertySerializer(_GraphSONTypeIO):
+    python_type = VertexProperty
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def dictify(cls, vertex_property, writer):
+        return GraphSONUtil.typedValue("VertexProperty", {"id": writer.toDict(vertex_property.id),
+                                                          "label": writer.toDict(vertex_property.label),
+                                                          "value": writer.toDict(vertex_property.value),
+                                                          "vertex": writer.toDict(vertex_property.vertex.id)})
+
+
+class PropertySerializer(_GraphSONTypeIO):
+    python_type = Property
+    graphson_type = "g:Property"
+
+    @classmethod
+    def dictify(cls, property, writer):
+        elementDict = writer.toDict(property.element)
+        if elementDict is not None:
+            valueDict = elementDict["@value"]
+            if "outVLabel" in valueDict:
+                del valueDict["outVLabel"]
+            if "inVLabel" in valueDict:
+                del valueDict["inVLabel"]
+            if "properties" in valueDict:
+                del valueDict["properties"]
+            if "value" in valueDict:
+                del valueDict["value"]
+        return GraphSONUtil.typedValue("Property", {"key": writer.toDict(property.key),
+                                                    "value": writer.toDict(property.value),
+                                                    "element": elementDict})
+
+
+class TraversalStrategySerializer(_GraphSONTypeIO):
+    python_type = TraversalStrategy
+
+    @classmethod
+    def dictify(cls, strategy, writer):
+        configuration = {}
+        for key in strategy.configuration:
+            configuration[key] = writer.toDict(strategy.configuration[key])
+        return GraphSONUtil.typedValue(strategy.strategy_name, configuration)
+
+
+class TraverserIO(_GraphSONTypeIO):
+    python_type = Traverser
+    graphson_type = "g:Traverser"
+
+    @classmethod
+    def dictify(cls, traverser, writer):
+        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
+                                                     "bulk": writer.toDict(traverser.bulk)})
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Traverser(reader.toObject(d["value"]),
+                         reader.toObject(d["bulk"]))
+
+
+class EnumSerializer(_GraphSONTypeIO):
+    python_type = Enum
+
+    @classmethod
+    def dictify(cls, enum, _):
+        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
+                                       cls.unmangleKeyword(str(enum.name)))
+
+
+class PSerializer(_GraphSONTypeIO):
+    python_type = P
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("P", out)
+
+
+class BindingSerializer(_GraphSONTypeIO):
+    python_type = Binding
+
+    @classmethod
+    def dictify(cls, binding, writer):
+        out = {"key": binding.key,
+               "value": writer.toDict(binding.value)}
+        return GraphSONUtil.typedValue("Binding", out)
+
+
+class LambdaSerializer(_GraphSONTypeIO):
+    python_type = FunctionType
+
+    @classmethod
+    def dictify(cls, lambda_object, writer):
+        lambda_result = lambda_object()
+        script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
+        language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
+        out = {"script": script,
+               "language": language}
+        if language == "gremlin-jython" or language == "gremlin-python":
+            if not script.strip().startswith("lambda"):
+                script = "lambda " + script
+                out["script"] = script
+            out["arguments"] = six.get_function_code(eval(out["script"])).co_argcount
+        else:
+            out["arguments"] = -1
+        return GraphSONUtil.typedValue("Lambda", out)
+
+
+class TypeSerializer(_GraphSONTypeIO):
+    python_type = TypeType
+
+    @classmethod
+    def dictify(cls, typ, writer):
+        return writer.toDict(typ())
+
+
+class _NumberIO(_GraphSONTypeIO):
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+    @classmethod
+    def objectify(cls, v, _):
+        return cls.python_type(v)
+
+
+class ListIO(_GraphSONTypeIO):
+    python_type = ListType
+    graphson_type = "g:List"
+
+    @classmethod
+    def dictify(cls, l, writer):
+        new_list = []
+        for obj in l:
+            new_list.append(writer.toDict(obj))
+        return GraphSONUtil.typedValue("List", new_list)
+
+    @classmethod
+    def objectify(cls, l, reader):
+        new_list = []
+        for obj in l:
+            new_list.append(reader.toObject(obj))
+        return new_list
+
+
+class SetIO(_GraphSONTypeIO):
+    python_type = SetType
+    graphson_type = "g:Set"
+
+    @classmethod
+    def dictify(cls, s, writer):
+        new_list = []
+        for obj in s:
+            new_list.append(writer.toDict(obj))
+        return GraphSONUtil.typedValue("Set", new_list)
+
+    @classmethod
+    def objectify(cls, s, reader):
+        new_set = set()
+        for obj in s:
+            new_set.add(reader.toObject(obj))
+        return new_set
+
+
+class MapType(_GraphSONTypeIO):
+    python_type = DictType
+    graphson_type = "g:Map"
+
+    @classmethod
+    def dictify(cls, d, writer):
+        l = []
+        for key in d:
+            l.append(writer.toDict(key))
+            l.append(writer.toDict(d[key]))
+        return GraphSONUtil.typedValue("Map", l)
+
+    @classmethod
+    def objectify(cls, l, reader):
+        new_dict = {}
+        if len(l) > 0:
+            x = 0
+            while x < len(l):
+                new_dict[reader.toObject(l[x])] = reader.toObject(l[x + 1])
+                x = x + 2
+        return new_dict
+
+
+class FloatIO(_NumberIO):
+    python_type = FloatType
+    graphson_type = "g:Float"
+    graphson_base_type = "Float"
+
+
+class DoubleIO(FloatIO):
+    graphson_type = "g:Double"
+    graphson_base_type = "Double"
+
+
+class Int64IO(_NumberIO):
+    python_type = LongType
+    graphson_type = "g:Int64"
+    graphson_base_type = "Int64"
+
+
+class Int32IO(_NumberIO):
+    python_type = IntType
+    graphson_type = "g:Int32"
+    graphson_base_type = "Int32"
+
+    @classmethod
+    def dictify(cls, n, writer):
+        if isinstance(n, bool):
+            return n
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
+
+
+class VertexDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Vertex"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Vertex(reader.toObject(d["id"]), d.get("label", "vertex"))
+
+
+class EdgeDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Edge"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        return Edge(reader.toObject(d["id"]),
+                    Vertex(reader.toObject(d["outV"]), d.get("outVLabel", "vertex")),
+                    d.get("label", "edge"),
+                    Vertex(reader.toObject(d["inV"]), d.get("inVLabel", "vertex")))
+
+
+class VertexPropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:VertexProperty"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        vertex = Vertex(reader.toObject(d.get("vertex"))) if "vertex" in d else None
+        return VertexProperty(reader.toObject(d["id"]),
+                              d["label"],
+                              reader.toObject(d["value"]),
+                              vertex)
+
+
+class PropertyDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Property"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        element = reader.toObject(d["element"]) if "element" in d else None
+        return Property(d["key"], reader.toObject(d["value"]), element)
+
+
+class PathDeserializer(_GraphSONTypeIO):
+    graphson_type = "g:Path"
+
+    @classmethod
+    def objectify(cls, d, reader):
+        labels = [set(label) for label in d["labels"]]
+        objects = [reader.toObject(o) for o in d["objects"]]
+        return Path(labels, objects)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py
deleted file mode 100644
index 719550b..0000000
--- a/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py
+++ /dev/null
@@ -1,271 +0,0 @@
-'''
-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.
-'''
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-import sys
-import json
-from mock import Mock
-
-import six
-
-from gremlin_python.statics import *
-from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty
-from gremlin_python.structure.graph import Path
-from gremlin_python.structure.io.graphson import GraphSONWriter, GraphSONReader, GraphSONUtil
-import gremlin_python.structure.io.graphson
-from gremlin_python.process.traversal import P
-from gremlin_python.process.strategies import SubgraphStrategy
-from gremlin_python.process.graph_traversal import __
-
-
-class TestGraphSONReader(object):
-    graphson_reader = GraphSONReader()
-
-    def test_number_input(self):
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Int32",
-            "@value": 31
-        }))
-        assert isinstance(x, int)
-        assert 31 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Int64",
-            "@value": 31
-        }))
-        assert isinstance(x, long)
-        assert long(31) == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Float",
-            "@value": 31.3
-        }))
-        assert isinstance(x, float)
-        assert 31.3 == x
-        ##
-        x = self.graphson_reader.readObject(json.dumps({
-            "@type": "g:Double",
-            "@value": 31.2
-        }))
-        assert isinstance(x, float)
-        assert 31.2 == x
-
-    def test_graph(self):
-        vertex = self.graphson_reader.readObject("""
-        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type":"g:Double","@value":1.0}}}]},"properties":{"name":[{"id":{"@type":"g:Int64","@value":0},"value":"marko"}],"age":[{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29}}]}}}""")
-        assert isinstance(vertex, Vertex)
-        assert "person" == vertex.label
-        assert 1 == vertex.id
-        assert isinstance(vertex.id, int)
-        assert vertex == Vertex(1)
-        ##
-        vertex = self.graphson_reader.readObject("""
-        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
-        assert isinstance(vertex, Vertex)
-        assert 45.23 == vertex.id
-        assert isinstance(vertex.id, FloatType)
-        assert "vertex" == vertex.label
-        assert vertex == Vertex(45.23)
-        ##
-        vertex_property = self.graphson_reader.readObject("""
-        {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
-        assert isinstance(vertex_property, VertexProperty)
-        assert "anId" == vertex_property.id
-        assert "aKey" == vertex_property.label
-        assert vertex_property.value
-        assert vertex_property.vertex == Vertex(9)
-        ##
-        vertex_property = self.graphson_reader.readObject("""
-        {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
-        assert isinstance(vertex_property, VertexProperty)
-        assert 1 == vertex_property.id
-        assert "name" == vertex_property.label
-        assert "marko" == vertex_property.value
-        assert vertex_property.vertex is None
-        ##
-        edge = self.graphson_reader.readObject("""
-        {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
-        # print edge
-        assert isinstance(edge, Edge)
-        assert 17 == edge.id
-        assert "knows" == edge.label
-        assert edge.inV == Vertex("x", "xLabel")
-        assert edge.outV == Vertex("y", "vertex")
-        ##
-        property = self.graphson_reader.readObject("""
-        {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
-        # print property
-        assert isinstance(property, Property)
-        assert "aKey" == property.key
-        assert 17 == property.value
-        assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
-
-    def test_path(self):
-        path = self.graphson_reader.readObject(
-            """{"@type":"g:Path","@value":{"labels":[["a"],["b","c"],[]],"objects":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":3},"label":"software","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":4},"value":"lop","label":"name"}}],"lang":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":5},"value":"java","label":"lang"}}]}}},"lop"]}}"""
-        )
-        assert isinstance(path, Path)
-        if six.PY3:
-            assert "[v[1], v[3], 'lop']" == str(path)
-        else:
-            assert "[v[1], v[3], u'lop']" == str(path)
-        assert Vertex(1) == path[0]
-        assert Vertex(1) == path["a"]
-        assert "lop" == path[2]
-        assert 3 == len(path)
-
-    def test_custom_mapping(self):
-
-        # extended mapping
-        class X(object):
-            pass
-
-        type_string = "test:Xtype"
-        override_string = "g:Int64"
-        serdes = Mock()
-
-        reader = GraphSONReader(deserializer_map={type_string: serdes})
-        assert type_string in reader.deserializers
-
-        # base dicts are not modified
-        assert type_string not in gremlin_python.structure.io.graphson._deserializers
-
-        x = X()
-        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
-        serdes.objectify.assert_called_once_with(x, reader)
-        assert o is serdes.objectify()
-
-        # overridden mapping
-        type_string = "g:Int64"
-        serdes = Mock()
-        reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
-        assert gremlin_python.structure.io.graphson._deserializers[type_string] is not reader.deserializers[type_string]
-
-        value = 3
-        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
-        serdes.objectify.assert_called_once_with(value, reader)
-        assert o is serdes.objectify()
-
-
-class TestGraphSONWriter(object):
-
-    graphson_writer = GraphSONWriter()
-
-    def test_number_output(self):
-        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
-        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
-        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
-        assert """true""" == self.graphson_writer.writeObject(True)
-
-    def test_numbers(self):
-        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
-        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
-        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
-        assert """true""" == self.graphson_writer.writeObject(True)
-
-    def test_P(self):
-        result = {'@type': 'g:P',
-                  '@value': {
-                     'predicate': 'and',
-                     'value': [{
-                        '@type': 'g:P',
-                        '@value': {
-                            'predicate': 'or',
-                            'value': [{
-                                '@type': 'g:P',
-                                '@value': {'predicate': 'lt', 'value': 'b'}
-                            },
-                            {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
-                            ]
-                        }
-                    },
-                    {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
-
-        assert  result == json.loads(
-            self.graphson_writer.writeObject(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
-
-    def test_strategies(self):
-        # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the Gremlin traversal machine (yet)
-        assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
-            self.graphson_writer.writeObject(SubgraphStrategy))
-        assert {"@type": "g:SubgraphStrategy", "@value": {
-            "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
-            self.graphson_writer.writeObject(SubgraphStrategy(vertices=__.has("name", "marko"))))
-
-    def test_graph(self):
-        # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
-        assert {"@type": "g:Vertex", "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(self.graphson_writer.writeObject(Vertex(long(12), "person")))
-
-        assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
-                                              "outV": {"@type": "g:Int32", "@value": 0},
-                                              "outVLabel": "person",
-                                              "label": "knows",
-                                              "inV": {"@type": "g:Int32", "@value": 1},
-                                              "inVLabel": "dog"}} == json.loads(
-            self.graphson_writer.writeObject(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
-        assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
-                                                        "vertex": "stephen"}} == json.loads(
-            self.graphson_writer.writeObject(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
-
-        assert {"@type": "g:Property",
-                "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
-                                                                        "@value": {
-                                                                            "vertex": "vertexId",
-                                                                            "id": {"@type": "g:Int32", "@value": 1234},
-                                                                            "label": "aKey"}}}} == json.loads(
-            self.graphson_writer.writeObject(
-                Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
-
-    def test_custom_mapping(self):
-        # extended mapping
-        class X(object):
-            pass
-
-        serdes = Mock()
-        writer = GraphSONWriter(serializer_map={X: serdes})
-        assert X in writer.serializers
-
-        # base dicts are not modified
-        assert X not in gremlin_python.structure.io.graphson._serializers
-
-        obj = X()
-        d = writer.toDict(obj)
-        serdes.dictify.assert_called_once_with(obj, writer)
-        assert d is serdes.dictify()
-
-        # overridden mapping
-        serdes = Mock()
-        writer = GraphSONWriter(serializer_map={int: serdes})
-        assert gremlin_python.structure.io.graphson._serializers[int] is not writer.serializers[int]
-
-        value = 3
-        d = writer.toDict(value)
-        serdes.dictify.assert_called_once_with(value, writer)
-        assert d is serdes.dictify()
-
-    def test_write_long(self):
-
-        mapping = self.graphson_writer.toDict(1)
-        assert mapping['@type'] == 'g:Int32'
-        assert mapping['@value'] == 1
-
-        mapping = self.graphson_writer.toDict(long(1))
-        assert mapping['@type'] == 'g:Int64'
-        assert mapping['@value'] == 1

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b30b56b4/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV2d0.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV2d0.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV2d0.py
new file mode 100644
index 0000000..6bc5097
--- /dev/null
+++ b/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV2d0.py
@@ -0,0 +1,273 @@
+'''
+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.
+'''
+
+__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+import sys
+import json
+from mock import Mock
+
+import six
+
+from gremlin_python.statics import *
+from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty
+from gremlin_python.structure.graph import Path
+from gremlin_python.structure.io.graphsonV2d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
+import gremlin_python.structure.io.graphsonV2d0
+from gremlin_python.process.traversal import P
+from gremlin_python.process.strategies import SubgraphStrategy
+from gremlin_python.process.graph_traversal import __
+
+
+class TestGraphSONReader(object):
+    graphson_reader = GraphSONReader()
+
+    def test_number_input(self):
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Int32",
+            "@value": 31
+        }))
+        assert isinstance(x, int)
+        assert 31 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Int64",
+            "@value": 31
+        }))
+        assert isinstance(x, long)
+        assert long(31) == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Float",
+            "@value": 31.3
+        }))
+        assert isinstance(x, float)
+        assert 31.3 == x
+        ##
+        x = self.graphson_reader.readObject(json.dumps({
+            "@type": "g:Double",
+            "@value": 31.2
+        }))
+        assert isinstance(x, float)
+        assert 31.2 == x
+
+    def test_graph(self):
+        vertex = self.graphson_reader.readObject("""
+        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type":"g:Double","@value":1.0}}}]},"properties":{"name":[{"id":{"@type":"g:Int64","@value":0},"value":"marko"}],"age":[{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29}}]}}}""")
+        assert isinstance(vertex, Vertex)
+        assert "person" == vertex.label
+        assert 1 == vertex.id
+        assert isinstance(vertex.id, int)
+        assert vertex == Vertex(1)
+        ##
+        vertex = self.graphson_reader.readObject("""
+        {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
+        assert isinstance(vertex, Vertex)
+        assert 45.23 == vertex.id
+        assert isinstance(vertex.id, FloatType)
+        assert "vertex" == vertex.label
+        assert vertex == Vertex(45.23)
+        ##
+        vertex_property = self.graphson_reader.readObject("""
+        {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
+        assert isinstance(vertex_property, VertexProperty)
+        assert "anId" == vertex_property.id
+        assert "aKey" == vertex_property.label
+        assert vertex_property.value
+        assert vertex_property.vertex == Vertex(9)
+        ##
+        vertex_property = self.graphson_reader.readObject("""
+        {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
+        assert isinstance(vertex_property, VertexProperty)
+        assert 1 == vertex_property.id
+        assert "name" == vertex_property.label
+        assert "marko" == vertex_property.value
+        assert vertex_property.vertex is None
+        ##
+        edge = self.graphson_reader.readObject("""
+        {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
+        # print edge
+        assert isinstance(edge, Edge)
+        assert 17 == edge.id
+        assert "knows" == edge.label
+        assert edge.inV == Vertex("x", "xLabel")
+        assert edge.outV == Vertex("y", "vertex")
+        ##
+        property = self.graphson_reader.readObject("""
+        {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
+        # print property
+        assert isinstance(property, Property)
+        assert "aKey" == property.key
+        assert 17 == property.value
+        assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
+
+    def test_path(self):
+        path = self.graphson_reader.readObject(
+            """{"@type":"g:Path","@value":{"labels":[["a"],["b","c"],[]],"objects":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":3},"label":"software","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":4},"value":"lop","label":"name"}}],"lang":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":5},"value":"java","label":"lang"}}]}}},"lop"]}}"""
+        )
+        assert isinstance(path, Path)
+        if six.PY3:
+            assert "[v[1], v[3], 'lop']" == str(path)
+        else:
+            assert "[v[1], v[3], u'lop']" == str(path)
+        assert Vertex(1) == path[0]
+        assert Vertex(1) == path["a"]
+        assert "lop" == path[2]
+        assert 3 == len(path)
+
+    def test_custom_mapping(self):
+
+        # extended mapping
+        class X(object):
+            pass
+
+        type_string = "test:Xtype"
+        override_string = "g:Int64"
+        serdes = Mock()
+
+        reader = GraphSONReader(deserializer_map={type_string: serdes})
+        assert type_string in reader.deserializers
+
+        # base dicts are not modified
+        assert type_string not in gremlin_python.structure.io.graphsonV2d0._deserializers
+
+        x = X()
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
+        serdes.objectify.assert_called_once_with(x, reader)
+        assert o is serdes.objectify()
+
+        # overridden mapping
+        type_string = "g:Int64"
+        serdes = Mock()
+        reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
+        assert gremlin_python.structure.io.graphsonV2d0._deserializers[type_string] is not reader.deserializers[type_string]
+
+        value = 3
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
+        serdes.objectify.assert_called_once_with(value, reader)
+        assert o is serdes.objectify()
+
+class TestGraphSONWriter(object):
+
+    graphson_writer = GraphSONWriter()
+
+    def test_number_output(self):
+        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
+        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
+        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
+        assert """true""" == self.graphson_writer.writeObject(True)
+
+    def test_numbers(self):
+        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
+        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
+        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
+        assert """true""" == self.graphson_writer.writeObject(True)
+
+    def test_P(self):
+        result = {'@type': 'g:P',
+                  '@value': {
+                     'predicate': 'and',
+                     'value': [{
+                        '@type': 'g:P',
+                        '@value': {
+                            'predicate': 'or',
+                            'value': [{
+                                '@type': 'g:P',
+                                '@value': {'predicate': 'lt', 'value': 'b'}
+                            },
+                            {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
+                            ]
+                        }
+                    },
+                    {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
+
+        assert  result == json.loads(
+            self.graphson_writer.writeObject(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
+
+        result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1},{"@type": "g:Int32", "@value": 2}]}}
+        assert result == json.loads(self.graphson_writer.writeObject(P.within([1,2])))
+
+    def test_strategies(self):
+        # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the Gremlin traversal machine (yet)
+        assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
+            self.graphson_writer.writeObject(SubgraphStrategy))
+        assert {"@type": "g:SubgraphStrategy", "@value": {
+            "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
+            self.graphson_writer.writeObject(SubgraphStrategy(vertices=__.has("name", "marko"))))
+
+    def test_graph(self):
+        # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
+        assert {"@type": "g:Vertex", "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(self.graphson_writer.writeObject(Vertex(long(12), "person")))
+
+        assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
+                                              "outV": {"@type": "g:Int32", "@value": 0},
+                                              "outVLabel": "person",
+                                              "label": "knows",
+                                              "inV": {"@type": "g:Int32", "@value": 1},
+                                              "inVLabel": "dog"}} == json.loads(
+            self.graphson_writer.writeObject(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
+        assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
+                                                        "vertex": "stephen"}} == json.loads(
+            self.graphson_writer.writeObject(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
+
+        assert {"@type": "g:Property",
+                "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
+                                                                        "@value": {
+                                                                            "vertex": "vertexId",
+                                                                            "id": {"@type": "g:Int32", "@value": 1234},
+                                                                            "label": "aKey"}}}} == json.loads(
+            self.graphson_writer.writeObject(
+                Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
+
+    def test_custom_mapping(self):
+        # extended mapping
+        class X(object):
+            pass
+
+        serdes = Mock()
+        writer = GraphSONWriter(serializer_map={X: serdes})
+        assert X in writer.serializers
+
+        # base dicts are not modified
+        assert X not in gremlin_python.structure.io.graphsonV2d0._serializers
+
+        obj = X()
+        d = writer.toDict(obj)
+        serdes.dictify.assert_called_once_with(obj, writer)
+        assert d is serdes.dictify()
+
+        # overridden mapping
+        serdes = Mock()
+        writer = GraphSONWriter(serializer_map={int: serdes})
+        assert gremlin_python.structure.io.graphsonV2d0._serializers[int] is not writer.serializers[int]
+
+        value = 3
+        d = writer.toDict(value)
+        serdes.dictify.assert_called_once_with(value, writer)
+        assert d is serdes.dictify()
+
+    def test_write_long(self):
+
+        mapping = self.graphson_writer.toDict(1)
+        assert mapping['@type'] == 'g:Int32'
+        assert mapping['@value'] == 1
+
+        mapping = self.graphson_writer.toDict(long(1))
+        assert mapping['@type'] == 'g:Int64'
+        assert mapping['@value'] == 1
\ No newline at end of file