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 2016/08/24 17:34:34 UTC

tinkerpop git commit: wrote lots of good graphson.py serialization/deserialization tests. had to redo how JythonScrtipEngine is used in the test suite as it can have residual data in it where test ordering matters. Added gremlin:lambda to GraphSONModule.

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1278 8ce282ebe -> f4c5914fc


wrote lots of good graphson.py serialization/deserialization tests. had to redo how JythonScrtipEngine is used in the test suite as it can have residual data in it where test ordering matters. Added gremlin:lambda to GraphSONModule. Wasn't there -- and test exposed it. Fixed up PDeserializer a bit (needs more work though).


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

Branch: refs/heads/TINKERPOP-1278
Commit: f4c5914fc73b839daa3788246f3bc3a42e2a3eb4
Parents: 8ce282e
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Aug 24 11:34:18 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Aug 24 11:34:29 2016 -0600

----------------------------------------------------------------------
 .../structure/io/graphson/GraphSONModule.java   |   1 +
 .../GraphSONTraversalSerializersV2d0.java       |  14 +-
 gremlin-python/pom.xml                          |  11 ++
 .../jython/gremlin_python/structure/graph.py    |   5 +-
 .../gremlin_python/structure/io/graphson.py     |  36 ++++-
 .../gremlin/python/GremlinPythonTest.java       |  37 ------
 .../python/jsr223/JythonScriptEngineSetup.java  |  17 ++-
 .../io/graphson/GraphSONReaderTest.java         | 133 +++++++++++++++++++
 .../io/graphson/GraphSONWriterTest.java         | 113 ++++++++++++++++
 9 files changed, 316 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index 5aeae98..efbee8f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -113,6 +113,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     put(ZoneOffset.class, "zoneoffset");
 
                     // Tinkerpop Graph objects
+                    put(Lambda.class, "lambda");
                     put(Vertex.class, "vertex");
                     put(Edge.class, "edge");
                     put(Property.class, "property");

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializersV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializersV2d0.java
index ef3fd04..d5c8de0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializersV2d0.java
@@ -39,10 +39,12 @@ import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdScalarSerializer;
 import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
 
 import java.io.IOException;
+import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -278,7 +280,17 @@ final class GraphSONTraversalSerializersV2d0 {
                 return predicate.equals(GraphSONTokens.AND) ? new AndP((List<P>) value) : new OrP((List<P>) value);
             } else {
                 try {
-                    return (P) P.class.getMethod(predicate, value instanceof Collection ? Collection.class : Object.class).invoke(null, value); // TODO: number stuff, eh?
+                    if (value instanceof Collection) {
+                        final Optional<Method> method = Arrays.stream(P.class.getMethods()).filter(m -> m.getName().equals(predicate)).findAny();
+                        if (method.isPresent()) {
+                            if (!Collection.class.isAssignableFrom(method.get().getParameterTypes()[0]))
+                                return (P) method.get().invoke(null, ((Collection) value).toArray());
+                            else
+                                return (P) method.get().invoke(null, value);
+                        } else
+                            throw new IllegalStateException("No such P method: " + predicate);
+                    }
+                    return (P) P.class.getMethod(predicate, Object.class).invoke(null, value);
                 } catch (final Exception e) {
                     throw new IllegalStateException(e.getMessage(), e);
                 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-python/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml
index a16c0b9..3d45a07 100644
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@ -238,6 +238,17 @@
                             </excludes>
                             <followSymlinks>false</followSymlinks>
                         </fileset>
+                        <fileset>
+                            <directory>${basedir}/src/main/jython/gremlin_python/structure/io</directory>
+                            <includes>
+                                <include>**/*.pyc</include>
+                                <include>**/*.class</include>
+                            </includes>
+                            <excludes>
+                                <exclude>**/*.py</exclude>
+                            </excludes>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
                     </filesets>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/graph.py b/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
index c0e3157..7a50418 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
@@ -32,7 +32,7 @@ class Graph(object):
         return GraphTraversalSource(self, TraversalStrategies.global_cache[self.__class__])
 
     def __repr__(self):
-        return "graph[]"
+        return "graph[empty]"
 
 
 class Element(object):
@@ -42,6 +42,9 @@ class Element(object):
 
 
 class Vertex(Element):
+    def __init__(self, id, label="vertex"):
+        Element.__init__(self, id, label)
+
     def __repr__(self):
         return "v[" + str(self.id) + "]"
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/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
index 7cce4a5..6fb32b6 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
@@ -20,6 +20,7 @@ under the License.
 import json
 from abc import abstractmethod
 from aenum import Enum
+from types import FloatType
 from types import FunctionType
 from types import IntType
 from types import LongType
@@ -42,11 +43,23 @@ class GraphSONWriter(object):
         for key in serializers:
             if isinstance(object, key):
                 return serializers[key]._dictify(object)
-        return object
+        # list and map are treated as normal json objects (could be isolated serializers)
+        if isinstance(object, list):
+            newList = []
+            for item in object:
+                newList.append(GraphSONWriter._dictify(item))
+            return newList
+        elif isinstance(object, dict):
+            newDict = {}
+            for key in object:
+                newDict[GraphSONWriter._dictify(key)] = GraphSONWriter._dictify(object[key])
+            return newDict
+        else:
+            return object
 
     @staticmethod
-    def writeObject(object):
-        return json.dumps(GraphSONWriter._dictify(object))
+    def writeObject(objectData):
+        return json.dumps(GraphSONWriter._dictify(objectData))
 
 
 class GraphSONReader(object):
@@ -57,6 +70,7 @@ class GraphSONReader(object):
                 type = object[_SymbolHelper._TYPE]
                 if type in deserializers:
                     return deserializers[type]._objectify(object)
+        # list and map are treated as normal json objects (could be isolated deserializers)
             newDict = {}
             for key in object:
                 newDict[GraphSONReader._objectify(key)] = GraphSONReader._objectify(object[key])
@@ -70,8 +84,8 @@ class GraphSONReader(object):
             return object
 
     @staticmethod
-    def readObject(data):
-        return GraphSONReader._objectify(json.loads(data))
+    def readObject(jsonData):
+        return GraphSONReader._objectify(json.loads(jsonData))
 
 
 '''
@@ -111,6 +125,12 @@ class BytecodeSerializer(GraphSONSerializer):
         return _SymbolHelper.objectify("bytecode", dict)
 
 
+class TraverserSerializer(GraphSONSerializer):
+    def _dictify(self, traverser):
+        return _SymbolHelper.objectify("traverser", {"value": GraphSONWriter._dictify(traverser.object),
+                                                     "bulk": GraphSONWriter._dictify(traverser.bulk)})
+
+
 class EnumSerializer(GraphSONSerializer):
     def _dictify(self, enum):
         return _SymbolHelper.objectify(_SymbolHelper.toGremlin(type(enum).__name__),
@@ -162,6 +182,8 @@ class NumberSerializer(GraphSONSerializer):
             return _SymbolHelper.objectify("int64", number)
         elif isinstance(number, int):
             return _SymbolHelper.objectify("int32", number)
+        elif isinstance(number, float):
+            return _SymbolHelper.objectify("float", number)
         else:
             return number
 
@@ -241,13 +263,15 @@ class _SymbolHelper(object):
 
 serializers = {
     Traversal: BytecodeSerializer(),
+    Traverser: TraverserSerializer(),
     Bytecode: BytecodeSerializer(),
     Binding: BindingSerializer(),
     P: PSerializer(),
     Enum: EnumSerializer(),
     FunctionType: LambdaSerializer(),
     LongType: NumberSerializer(),
-    IntType: NumberSerializer()
+    IntType: NumberSerializer(),
+    FloatType: NumberSerializer()
 }
 
 deserializers = {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/GremlinPythonTest.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/GremlinPythonTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/GremlinPythonTest.java
deleted file mode 100644
index 9eede82..0000000
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/GremlinPythonTest.java
+++ /dev/null
@@ -1,37 +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.
- */
-
-package org.apache.tinkerpop.gremlin.python;
-
-import org.apache.tinkerpop.gremlin.python.jsr223.JythonScriptEngineSetup;
-import org.apache.tinkerpop.gremlin.util.ScriptEngineCache;
-
-import javax.script.ScriptEngine;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class GremlinPythonTest {
-
-    public static final ScriptEngine jythonEngine = ScriptEngineCache.get("jython");
-    static {
-        JythonScriptEngineSetup.setup();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
index 1698b30..e71d3e6 100644
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
@@ -20,8 +20,8 @@
 package org.apache.tinkerpop.gremlin.python.jsr223;
 
 import org.apache.tinkerpop.gremlin.util.ScriptEngineCache;
+import org.python.jsr223.PyScriptEngine;
 
-import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
 /**
@@ -33,12 +33,11 @@ public class JythonScriptEngineSetup {
     }
 
     public static void setup() {
+        setup((PyScriptEngine) ScriptEngineCache.get("jython"));
+    }
+
+    public static PyScriptEngine setup(final PyScriptEngine jythonEngine) {
         try {
-            final ScriptEngine jythonEngine = ScriptEngineCache.get("jython");
-            if (null != System.getenv("PYTHONPATH")) {
-                jythonEngine.eval("import sys");
-                jythonEngine.eval("sys.path.append('" + System.getenv("PYTHONPATH") + "')");
-            }
             jythonEngine.eval("import gremlin_python.statics");
             jythonEngine.eval("from gremlin_python.process.traversal import *");
             jythonEngine.eval("from gremlin_python.process.graph_traversal import *");
@@ -46,7 +45,13 @@ public class JythonScriptEngineSetup {
             // jythonEngine.eval("from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection");
             jythonEngine.eval("from gremlin_python.process.traversal import Bytecode");
             jythonEngine.eval("from gremlin_python.structure.graph import Graph");
+            jythonEngine.eval("from gremlin_python.structure.graph import Vertex");
+            jythonEngine.eval("from gremlin_python.structure.graph import Edge");
+            jythonEngine.eval("from gremlin_python.structure.graph import VertexProperty");
+            jythonEngine.eval("from gremlin_python.structure.graph import Property");
             jythonEngine.eval("from gremlin_python.structure.io.graphson import GraphSONWriter");
+            jythonEngine.eval("from gremlin_python.structure.io.graphson import GraphSONReader");
+            return jythonEngine;
         } catch (final ScriptException e) {
             throw new IllegalStateException(e.getMessage(), e);
         }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONReaderTest.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONReaderTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONReaderTest.java
new file mode 100644
index 0000000..171fd04
--- /dev/null
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONReaderTest.java
@@ -0,0 +1,133 @@
+/*
+ *  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.
+ */
+
+package org.apache.tinkerpop.gremlin.python.structure.io.graphson;
+
+import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.python.jsr223.JythonScriptEngineSetup;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
+import org.junit.Test;
+import org.python.jsr223.PyScriptEngine;
+
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class GraphSONReaderTest {
+
+    private static final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
+    private static final ObjectMapper mapper = GraphSONMapper.build().version(GraphSONVersion.V2_0).create().createMapper();
+    private static final GraphTraversalSource g = TinkerFactory.createModern().traversal();
+
+
+    @Test
+    public void shouldDeserializeGraphObjects() throws Exception {
+        final Vertex vertex = g.V(1).next();
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(vertex));
+        assertEquals(vertex.toString(), jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),Vertex)"));
+        //
+        final Edge edge = g.V(1).outE("created").next();
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(edge));
+        assertEquals(edge.toString(), jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),Edge)"));
+        //
+        final VertexProperty vertexProperty = (VertexProperty) g.V(1).properties("name").next();
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(vertexProperty));
+        assertEquals(vertexProperty.toString(), jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),VertexProperty)"));
+        //
+        final Property property = g.V(1).outE("created").properties("weight").next();
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(property));
+        assertEquals(property.toString(), jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),Property)"));
+        //
+        final Traverser<Vertex> traverser = new DefaultRemoteTraverser<>(vertex, 3L);
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(traverser));
+        assertEquals(traverser.toString(), jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertEquals(BigInteger.valueOf(3L), jythonEngine.eval("GraphSONReader.readObject(x).bulk")); // jython uses big integer in Java
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x).object,Vertex)"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),Traverser)"));
+    }
+
+    @Test
+    public void shouldDeserializeNumbers() throws Exception {
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1));
+        assertEquals("1", jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),int)"));
+        //
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1L));
+        assertEquals("1", jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),long)"));
+        //
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1.2f));
+        assertEquals("1.2", jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),float)"));
+        //
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(1.3d));
+        assertEquals("1.3", jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x),float)"));
+    }
+
+    @Test
+    public void shouldDeserializeCollections() throws Exception {
+        final Map<String, Number> map = new LinkedHashMap<>();
+        map.put("a", 2);
+        map.put("b", 2.3d);
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(map));
+        assertEquals("{u'a': 2, u'b': 2.3}", jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertEquals(2, jythonEngine.eval("GraphSONReader.readObject(x)['a']"));
+        assertEquals(2.3d, jythonEngine.eval("GraphSONReader.readObject(x)['b']")); // jython is smart about double
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x)['a'],int)"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x)['b'],float)"));
+        //
+        final List<Object> list = Arrays.asList(g.V(1).next(), "hello", map, true);
+        jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE).put("x", mapper.writeValueAsString(list));
+        assertEquals("[v[1], u'hello', {u'a': 2, u'b': 2.3}, True]", jythonEngine.eval("str(GraphSONReader.readObject(x))"));
+        assertEquals(g.V(1).next().toString(), jythonEngine.eval("str(GraphSONReader.readObject(x)[0])"));
+        assertEquals("hello", jythonEngine.eval("GraphSONReader.readObject(x)[1]"));
+        assertEquals("{u'a': 2, u'b': 2.3}", jythonEngine.eval("str(GraphSONReader.readObject(x)[2])"));
+        assertTrue((Boolean) jythonEngine.eval("GraphSONReader.readObject(x)[3]"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x)[0],Vertex)"));
+        // assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x)[1],str)")); // its python unicode jython object
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x)[2],dict)"));
+        assertTrue((Boolean) jythonEngine.eval("isinstance(GraphSONReader.readObject(x)[3],bool)"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f4c5914f/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
new file mode 100644
index 0000000..51f4c53
--- /dev/null
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
@@ -0,0 +1,113 @@
+/*
+ *  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.
+ */
+
+package org.apache.tinkerpop.gremlin.python.structure.io.graphson;
+
+import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
+import org.apache.tinkerpop.gremlin.python.jsr223.JythonScriptEngineSetup;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
+import org.apache.tinkerpop.gremlin.util.ScriptEngineCache;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
+import org.junit.Test;
+import org.python.jsr223.PyScriptEngine;
+import org.python.jsr223.PyScriptEngineFactory;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class GraphSONWriterTest {
+
+    private static final ScriptEngine jythonEngine = JythonScriptEngineSetup.setup((PyScriptEngine) new ScriptEngineManager().getEngineByName("jython"));
+    private static final ObjectMapper mapper = GraphSONMapper.build().version(GraphSONVersion.V2_0).create().createMapper();
+
+    @Test
+    public void shouldSerializeNumbers() throws Exception {
+        assertEquals(1, mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(1)").toString(), Object.class));
+        assertEquals(mapper.writeValueAsString(1), jythonEngine.eval("GraphSONWriter.writeObject(1)").toString().replace(" ", ""));
+        //
+        assertEquals(2L, mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(2L)").toString(), Object.class));
+        assertEquals(mapper.writeValueAsString(2L), jythonEngine.eval("GraphSONWriter.writeObject(2L)").toString().replace(" ", ""));
+        //
+        assertEquals(3.4f, mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(3.4)").toString(), Object.class));
+        assertEquals(mapper.writeValueAsString(3.4f), jythonEngine.eval("GraphSONWriter.writeObject(3.4)").toString().replace(" ", ""));
+    }
+
+    @Test
+    public void shouldSerializeCollections() throws Exception {
+        final Map<String, Number> map = new LinkedHashMap<>();
+        map.put("a", 2);
+        map.put("b", 2.3f);
+        assertEquals(map, mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject({'a':2,'b':2.3})").toString(), Object.class));
+        //
+        final List<Object> list = Arrays.asList(new DefaultRemoteTraverser<>("hello", 3L), "hello", map, true);
+        assertTrue((Boolean) jythonEngine.eval("isinstance([Traverser('hello',3L),'hello',{'a':2,'b':2.3},True],list)"));
+        assertEquals(list, mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject([Traverser('hello',3L),'hello',{'a':2,'b':2.3},True])").toString(), Object.class));
+    }
+
+    @Test
+    public void shouldSerializeTraverser() throws Exception {
+        assertEquals(
+                new DefaultRemoteTraverser<>("hello", 3L),
+                mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(Traverser('hello',3L))").toString(), Object.class));
+        assertEquals(3L, mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(Traverser('hello',3L))").toString(), Traverser.class).bulk());
+        assertEquals("hello", mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(Traverser('hello',3L))").toString(), Traverser.class).get());
+    }
+
+    /*@Test
+    public void shouldSerializeBytecode() throws Exception {
+        assertEquals(P.eq(7L), mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(P.eq(7L))").toString(), Object.class));
+        // TODO: assertEquals(mapper.writeValueAsString(P.between(1, 2).and(P.eq(7L))), jythonEngine.eval("GraphSONWriter.writeObject(P.eq(7L)._and(P.between(1,2)))").toString().replace(" ",""));
+        assertEquals(AndP.class, mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(P.eq(7L)._and(P.between(1,2)))").toString(), Object.class).getClass());
+    }
+
+    @Test
+    public void shouldSerializeLambda() throws Exception {
+        assertEquals(
+                Lambda.function("lambda z : 1+2", "gremlin-python"),
+                mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(lambda : 'z : 1+2')").toString(), Object.class));
+        assertEquals(
+                Lambda.function("lambda z : z+ 7", "gremlin-python"),
+                mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(lambda : 'lambda z : z+ 7')").toString(), Object.class));
+        assertEquals(
+                Lambda.supplier("lambda : 23", "gremlin-python"),
+                mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(lambda : 'lambda : 23')").toString(), Object.class));
+        assertEquals(
+                Lambda.consumer("lambda z : z + 23", "gremlin-python"),
+                mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(lambda : 'lambda z : z + 23')").toString(), Object.class));
+        assertEquals(
+                Lambda.biFunction("lambda z,y : z - y + 2", "gremlin-python"),
+                mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(lambda : 'lambda z,y : z - y + 2')").toString(), Object.class));
+    }*/
+
+}