You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2020/06/11 17:21:03 UTC

[tinkerpop] branch master updated (16ac4d6 -> 05f8453)

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.


    from 16ac4d6  Merge branch 'TINKERPOP-2361'
     add 417a1ec  TINKERPOP-2264 update Python graphson tests to use calendar.timegm and utctimetuple when testing g:Date->datetime conversion - they were failing for some timezones/systems.
     add eca7769  EXPOSE secure port 45941 in gremlin-server Dockfile.template. Add -p arguments to docker run in gremlin-server.sh so that the ports are exposed on macos.
     new 05f8453  Merge branch 'pr-1293'

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 docker/gremlin-server.sh                                             | 2 +-
 docker/gremlin-server/Dockerfile.template                            | 2 +-
 .../src/main/python/tests/structure/io/test_graphsonV2d0.py          | 5 ++---
 .../src/main/python/tests/structure/io/test_graphsonV3d0.py          | 5 ++---
 4 files changed, 6 insertions(+), 8 deletions(-)


[tinkerpop] 01/01: Merge branch 'pr-1293'

Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 05f84539611c67373dcca0634425d6792971b646
Merge: 16ac4d6 eca7769
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Thu Jun 11 13:04:37 2020 -0400

    Merge branch 'pr-1293'

 docker/gremlin-server.sh                                             | 2 +-
 docker/gremlin-server/Dockerfile.template                            | 2 +-
 .../src/main/python/tests/structure/io/test_graphsonV2d0.py          | 5 ++---
 .../src/main/python/tests/structure/io/test_graphsonV3d0.py          | 5 ++---
 4 files changed, 6 insertions(+), 8 deletions(-)

diff --cc gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
index 32d2c04,0000000..03d84a1
mode 100644,000000..100644
--- a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
+++ b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
@@@ -1,519 -1,0 +1,518 @@@
 +#
 +# 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 datetime
- import time
++import calendar
 +import json
 +import uuid
 +import math
 +from decimal import *
 +
 +from mock import Mock
 +
 +from gremlin_python.statics import *
 +from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, 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": "gx:Byte",
 +            "@value": 1
 +        }))
 +        assert isinstance(x, SingleByte)
 +        assert 1 == x
 +        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
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "g:Double",
 +            "@value": "NaN"
 +        }))
 +        assert isinstance(x, float)
 +        assert math.isnan(x)
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "g:Double",
 +            "@value": "Infinity"
 +        }))
 +        assert isinstance(x, float)
 +        assert math.isinf(x) and x > 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "g:Double",
 +            "@value": "-Infinity"
 +        }))
 +        assert isinstance(x, float)
 +        assert math.isinf(x) and x < 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": 31.2
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert Decimal(31.2) == x
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": 123456789987654321123456789987654321
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert Decimal('123456789987654321123456789987654321') == x
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": "NaN"
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert math.isnan(x)
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": "Infinity"
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert math.isinf(x) and x > 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": "-Infinity"
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert math.isinf(x) and x < 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigInteger",
 +            "@value": 31
 +        }))
 +        assert isinstance(x, long)
 +        assert 31 == x
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigInteger",
 +            "@value": 123456789987654321123456789987654321
 +        }))
 +        assert isinstance(x, long)
 +        assert 123456789987654321123456789987654321 == 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 [...]
 +        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" [...]
 +        )
 +        assert isinstance(path, Path)
 +        assert "path[v[1], v[3], 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()
 +
 +    def test_datetime(self):
 +        expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
-         pts = time.mktime(expected.timetuple()) + expected.microsecond / 1e6 - \
-                          (time.mktime(datetime.datetime(1970, 1, 1).timetuple()))
++        pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
 +        ts = int(round(pts * 1000))
 +        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Date", "@value": ts}))
 +        assert isinstance(dt, datetime.datetime)
 +        # TINKERPOP-1848
 +        assert dt == expected
 +
 +    def test_timestamp(self):
 +        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
 +        assert isinstance(dt, timestamp)
 +        assert float(dt) == 1481750076.295
 +
 +    def test_duration(self):
 +        d = self.graphson_reader.readObject(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
 +        assert isinstance(d, datetime.timedelta)
 +        assert d == datetime.timedelta(hours=120)
 +
 +    def test_uuid(self):
 +        prop = self.graphson_reader.readObject(
 +            json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
 +        assert isinstance(prop, uuid.UUID)
 +        assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
 +
 +    def test_metrics(self):
 +        prop = self.graphson_reader.readObject(
 +            json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
 +                {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
 +                {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
 +            ]}}]))
 +        assert isinstance(prop, list)
 +        assert prop == [{'dur': 1.468594, 'metrics': [
 +                {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
 +                {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
 +                ]}]
 +
 +    def test_bytebuffer(self):
 +        bb = self.graphson_reader.readObject(
 +            json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
 +        assert isinstance(bb, ByteBufferType)
 +        assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
 +
 +    def test_char(self):
 +        c = self.graphson_reader.readObject(json.dumps({"@type": "gx:Char", "@value": "L"}))
 +        assert isinstance(c, SingleChar)
 +        assert chr(76) == c
 +
 +    def test_null(self):
 +        c = self.graphson_reader.readObject(json.dumps(None))
 +        assert c is None
 +
 +
 +class TestGraphSONWriter(object):
 +    graphson_writer = GraphSONWriter()
 +    graphson_reader = GraphSONReader()
 +
 +    def test_numbers(self):
 +        assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.writeObject(int.__new__(SingleByte, 1)))
 +        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
 +        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(long(851401972585122)))
 +        assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.writeObject(long(-2)))
 +        assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.writeObject(long(-851401972585122)))
 +        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
 +        assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.writeObject(-1))
 +        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(851401972585122))
 +        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
 +        assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(float('nan')))
 +        assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(float('inf')))
 +        assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(float('-inf')))
 +        assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(Decimal('123456789987654321123456789987654321')))
 +        assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(Decimal('nan')))
 +        assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('inf')))
 +        assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('-inf')))
 +        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(long(123456789987654321123456789987654321)))
 +        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(123456789987654321123456789987654321))
 +        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])))
 +        assert result == json.loads(self.graphson_writer.writeObject(P.within(1, 2)))
 +
 +        result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1}]}}
 +        assert result == json.loads(self.graphson_writer.writeObject(P.within([1])))
 +        assert result == json.loads(self.graphson_writer.writeObject(P.within(1)))
 +
 +    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")))))
 +
 +        vertex = self.graphson_reader.readObject(self.graphson_writer.writeObject(Vertex(1, "person")))
 +        assert 1 == vertex.id
 +        assert "person" == vertex.label
 +
 +        edge = self.graphson_reader.readObject(
 +            self.graphson_writer.writeObject(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
 +        assert "knows" == edge.label
 +        assert 3 == edge.id
 +        assert 1 == edge.outV.id
 +        assert 2 == edge.inV.id
 +
 +        vertex_property = self.graphson_reader.readObject(
 +            self.graphson_writer.writeObject(VertexProperty(1, "age", 32, Vertex(1))))
 +        assert 1 == vertex_property.id
 +        assert "age" == vertex_property.key
 +        assert 32 == vertex_property.value
 +
 +        property = self.graphson_reader.readObject(self.graphson_writer.writeObject(Property("age", 32.2, Edge(1,Vertex(2),"knows",Vertex(3)))))
 +        assert "age" == property.key
 +        assert 32.2 == property.value
 +
 +    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
 +
 +    def test_datetime(self):
 +        expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
 +        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
 +        output = self.graphson_writer.writeObject(dt)
 +        assert expected == output
 +
 +    def test_timestamp(self):
 +        expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
 +        ts = timestamp(1481750076295 / 1000.0)
 +        output = self.graphson_writer.writeObject(ts)
 +        assert expected == output
 +
 +    def test_duration(self):
 +        expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
 +        d = datetime.timedelta(hours=120)
 +        output = self.graphson_writer.writeObject(d)
 +        assert expected == output
 +
 +    def test_uuid(self):
 +        expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
 +        prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
 +        output = self.graphson_writer.writeObject(prop)
 +        assert expected == output
 +
 +    def test_bytebuffer(self):
 +        expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
 +        bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
 +        output = self.graphson_writer.writeObject(bb)
 +        assert expected == output
 +
 +    def test_char(self):
 +        expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
 +        c = str.__new__(SingleChar, chr(76))
 +        output = self.graphson_writer.writeObject(c)
 +        assert expected == output
 +
 +
 +class TestFunctionalGraphSONIO(object):
 +    """Functional IO tests"""
 +
 +    def test_timestamp(self, remote_connection_v2):
 +        g = Graph().traversal().withRemote(remote_connection_v2)
 +        ts = timestamp(1481750076295 / 1000)
 +        resp = g.addV('test_vertex').property('ts', ts)
 +        resp = resp.toList()
 +        vid = resp[0].id
 +        try:
 +            ts_prop = g.V(vid).properties('ts').toList()[0]
 +            assert isinstance(ts_prop.value, timestamp)
 +            assert ts_prop.value == ts
 +        except OSError:
 +            assert False, "Error making request"
 +        finally:
 +            g.V(vid).drop().iterate()
 +
 +    def test_datetime(self, remote_connection_v2):
 +        g = Graph().traversal().withRemote(remote_connection_v2)
 +        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000)
 +        resp = g.addV('test_vertex').property('dt', dt).toList()
 +        vid = resp[0].id
 +        try:
 +            dt_prop = g.V(vid).properties('dt').toList()[0]
 +            assert isinstance(dt_prop.value, datetime.datetime)
 +            assert dt_prop.value == dt
 +        except OSError:
 +            assert False, "Error making request"
 +        finally:
 +            g.V(vid).drop().iterate()
 +
 +    def test_uuid(self, remote_connection_v2):
 +        g = Graph().traversal().withRemote(remote_connection_v2)
 +        uid = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
 +        resp = g.addV('test_vertex').property('uuid', uid).toList()
 +        vid = resp[0].id
 +        try:
 +            uid_prop = g.V(vid).properties('uuid').toList()[0]
 +            assert isinstance(uid_prop.value, uuid.UUID)
 +            assert uid_prop.value == uid
 +        except OSError:
 +            assert False, "Error making request"
 +        finally:
 +            g.V(vid).drop().iterate()
diff --cc gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py
index d7b837b,0000000..83aa55f
mode 100644,000000..100644
--- a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py
+++ b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py
@@@ -1,537 -1,0 +1,536 @@@
 +#
 +# 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 datetime
- import time
++import calendar
 +import json
 +import uuid
 +import math
 +from decimal import *
 +
 +from mock import Mock
 +
 +from gremlin_python.statics import *
 +from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
 +from gremlin_python.structure.io.graphsonV3d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
 +import gremlin_python.structure.io.graphsonV3d0
 +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_collections(self):
 +        x = self.graphson_reader.readObject(
 +            json.dumps({"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
 +                                                      {"@type": "g:Int32", "@value": 2},
 +                                                      "3"]}))
 +        assert isinstance(x, list)
 +        assert x[0] == 1
 +        assert x[1] == 2
 +        assert x[2] == "3"
 +        ##
 +
 +        x = self.graphson_reader.readObject(
 +            json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
 +                                                     {"@type": "g:Int32", "@value": 2},
 +                                                     "3"]}))
 +        # return a set as normal
 +        assert isinstance(x, set)
 +        assert x == set([1, 2, "3"])
 +
 +        x = self.graphson_reader.readObject(
 +            json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
 +                                                    {"@type": "g:Int32", "@value": 2},
 +                                                    {"@type": "g:Float", "@value": 2.0},
 +                                                    "3"]}))
 +        # coerce to list here because Java might return numerics of different types which python won't recognize
 +        # see comments of TINKERPOP-1844 for more details
 +        assert isinstance(x, list)
 +        assert x == list([1, 2, 2.0, "3"])
 +        ##
 +        x = self.graphson_reader.readObject(
 +            json.dumps({"@type": "g:Map",
 +                        "@value": ['a', {"@type": "g:Int32", "@value": 1}, 'b', "marko"]}))
 +        assert isinstance(x, dict)
 +        assert x['a'] == 1
 +        assert x['b'] == "marko"
 +        assert len(x) == 2
 +
 +        # BulkSet gets coerced to a List - both have the same behavior
 +        x = self.graphson_reader.readObject(
 +            json.dumps({"@type": "g:BulkSet",
 +                        "@value": ["marko", {"@type": "g:Int64", "@value": 1}, "josh", {"@type": "g:Int64", "@value": 3}]}))
 +        assert isinstance(x, list)
 +        assert len(x) == 4
 +        assert x.count("marko") == 1
 +        assert x.count("josh") == 3
 +
 +    def test_number_input(self):
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:Byte",
 +            "@value": 1
 +        }))
 +        assert isinstance(x, SingleByte)
 +        assert 1 == x
 +        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
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "g:Double",
 +            "@value": "NaN"
 +        }))
 +        assert isinstance(x, float)
 +        assert math.isnan(x)
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "g:Double",
 +            "@value": "Infinity"
 +        }))
 +        assert isinstance(x, float)
 +        assert math.isinf(x) and x > 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "g:Double",
 +            "@value": "-Infinity"
 +        }))
 +        assert isinstance(x, float)
 +        assert math.isinf(x) and x < 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": 31.2
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert Decimal(31.2) == x
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": 123456789987654321123456789987654321
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert Decimal('123456789987654321123456789987654321') == x
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": "NaN"
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert math.isnan(x)
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": "Infinity"
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert math.isinf(x) and x > 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigDecimal",
 +            "@value": "-Infinity"
 +        }))
 +        assert isinstance(x, Decimal)
 +        assert math.isinf(x) and x < 0
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigInteger",
 +            "@value": 31
 +        }))
 +        assert isinstance(x, long)
 +        assert 31 == x
 +        ##
 +        x = self.graphson_reader.readObject(json.dumps({
 +            "@type": "gx:BigInteger",
 +            "@value": 123456789987654321123456789987654321
 +        }))
 +        assert isinstance(x, long)
 +        assert 123456789987654321123456789987654321 == 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 [...]
 +        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":{"@type":"g:List","@value":[{"@type":"g:Set","@value":["a"]},{"@type":"g:Set","@value":["b","c"]},{"@type":"g:Set","@value":[]}]},"objects":{"@type":"g:List","@value":[{"@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" [...]
 +        )
 +        assert isinstance(path, Path)
 +        assert "path[v[1], v[3], 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.graphsonV3d0._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.graphsonV3d0._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()
 +
 +    def test_datetime(self):
 +        expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
-         pts = time.mktime(expected.timetuple()) + expected.microsecond / 1e6 - \
-               (time.mktime(datetime.datetime(1970, 1, 1).timetuple()))
++        pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
 +        ts = int(round(pts * 1000))
 +        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Date", "@value": ts}))
 +        assert isinstance(dt, datetime.datetime)
 +        # TINKERPOP-1848
 +        assert dt == expected
 +
 +    def test_timestamp(self):
 +        dt = self.graphson_reader.readObject(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
 +        assert isinstance(dt, timestamp)
 +        assert float(dt) == 1481750076.295
 +
 +    def test_duration(self):
 +        d = self.graphson_reader.readObject(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
 +        assert isinstance(d, datetime.timedelta)
 +        assert d == datetime.timedelta(hours=120)
 +
 +    def test_uuid(self):
 +        prop = self.graphson_reader.readObject(
 +            json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
 +        assert isinstance(prop, uuid.UUID)
 +        assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
 +
 +    def test_metrics(self):
 +        prop = self.graphson_reader.readObject(
 +            json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
 +                {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
 +                {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
 +            ]}}]))
 +        assert isinstance(prop, list)
 +        assert prop == [{'dur': 1.468594, 'metrics': [
 +                {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
 +                {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
 +                ]}]
 +
 +    def test_bytebuffer(self):
 +        bb = self.graphson_reader.readObject(
 +            json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
 +        assert isinstance(bb, ByteBufferType)
 +        assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
 +
 +    def test_char(self):
 +        c = self.graphson_reader.readObject(json.dumps({"@type": "gx:Char", "@value": "L"}))
 +        assert isinstance(c, SingleChar)
 +        assert chr(76) == c
 +
 +    def test_null(self):
 +        c = self.graphson_reader.readObject(json.dumps(None))
 +        assert c is None
 +
 +
 +class TestGraphSONWriter(object):
 +    graphson_writer = GraphSONWriter()
 +    graphson_reader = GraphSONReader()
 +
 +    def test_collections(self):
 +        assert {"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
 +                                              {"@type": "g:Int32", "@value": 2},
 +                                              {"@type": "g:Int32", "@value": 3}]} == json.loads(
 +            self.graphson_writer.writeObject([1, 2, 3]))
 +        assert {"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
 +                                             {"@type": "g:Int32", "@value": 2},
 +                                             {"@type": "g:Int32", "@value": 3}]} == json.loads(
 +            self.graphson_writer.writeObject(set([1, 2, 3, 3])))
 +        assert {"@type": "g:Map",
 +                "@value": ['a', {"@type": "g:Int32", "@value": 1}]} == json.loads(
 +            self.graphson_writer.writeObject({'a': 1}))
 +
 +    def test_numbers(self):
 +        assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.writeObject(int.__new__(SingleByte, 1)))
 +        assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.writeObject(long(2)))
 +        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(long(851401972585122)))
 +        assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.writeObject(long(-2)))
 +        assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.writeObject(long(-851401972585122)))
 +        assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.writeObject(1))
 +        assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.writeObject(-1))
 +        assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.writeObject(851401972585122))
 +        assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.writeObject(3.2))
 +        assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(float('nan')))
 +        assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(float('inf')))
 +        assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(float('-inf')))
 +        assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(Decimal('123456789987654321123456789987654321')))
 +        assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.writeObject(Decimal('nan')))
 +        assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('inf')))
 +        assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.writeObject(Decimal('-inf')))
 +        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(long(123456789987654321123456789987654321)))
 +        assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.writeObject(123456789987654321123456789987654321))
 +        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:List', '@value': [
 +            {"@type": "g:Int32", "@value": 1}, {"@type": "g:Int32", "@value": 2}]}}}
 +        assert result == json.loads(self.graphson_writer.writeObject(P.within([1, 2])))
 +        assert result == json.loads(self.graphson_writer.writeObject(P.within(1, 2)))
 +
 +        result = {'@type': 'g:P', '@value': {'predicate': 'within', 'value': {'@type': 'g:List', '@value': [
 +            {"@type": "g:Int32", "@value": 1}]}}}
 +        assert result == json.loads(self.graphson_writer.writeObject(P.within([1])))
 +        assert result == json.loads(self.graphson_writer.writeObject(P.within(1)))
 +
 +    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")))))
 +
 +        vertex = self.graphson_reader.readObject(self.graphson_writer.writeObject(Vertex(1, "person")))
 +        assert 1 == vertex.id
 +        assert "person" == vertex.label
 +
 +        edge = self.graphson_reader.readObject(
 +            self.graphson_writer.writeObject(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
 +        assert "knows" == edge.label
 +        assert 3 == edge.id
 +        assert 1 == edge.outV.id
 +        assert 2 == edge.inV.id
 +
 +        vertex_property = self.graphson_reader.readObject(
 +            self.graphson_writer.writeObject(VertexProperty(1, "age", 32, Vertex(1))))
 +        assert 1 == vertex_property.id
 +        assert "age" == vertex_property.key
 +        assert 32 == vertex_property.value
 +
 +        property = self.graphson_reader.readObject(self.graphson_writer.writeObject(Property("age", 32.2, Edge(1,Vertex(2),"knows",Vertex(3)))))
 +        assert "age" == property.key
 +        assert 32.2 == property.value
 +
 +    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.graphsonV3d0._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.graphsonV3d0._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
 +
 +    def test_datetime(self):
 +        expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
 +        dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
 +        output = self.graphson_writer.writeObject(dt)
 +        assert expected == output
 +
 +    def test_timestamp(self):
 +        expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
 +        ts = timestamp(1481750076295 / 1000.0)
 +        output = self.graphson_writer.writeObject(ts)
 +        assert expected == output
 +
 +    def test_duration(self):
 +        expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
 +        d = datetime.timedelta(hours=120)
 +        output = self.graphson_writer.writeObject(d)
 +        assert expected == output
 +
 +    def test_uuid(self):
 +        expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
 +        prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
 +        output = self.graphson_writer.writeObject(prop)
 +        assert expected == output
 +
 +    def test_bytebuffer(self):
 +        expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
 +        bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
 +        output = self.graphson_writer.writeObject(bb)
 +        assert expected == output
 +
 +    def test_char(self):
 +        expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
 +        c = str.__new__(SingleChar, chr(76))
 +        output = self.graphson_writer.writeObject(c)
 +        assert expected == output