diff --git a/docs/driver.rst b/docs/driver.rst
index 2a37e1a513426e8329fea03954a3033dbe72998c..81e68906f58f9734034f3972000a3c4d661a3615 100644
--- a/docs/driver.rst
+++ b/docs/driver.rst
@@ -9,7 +9,7 @@ Gremlin Server::
     >>> import asyncio
     >>> from goblin import driver
     >>> loop = asyncio.get_event_loop()
-    >>> conn = await driver.Connection.open('ws://localhost:8182', loop)
+    >>> conn = await driver.Connection.open('ws://localhost:8182/gremlin', loop)
 
 The :py:class:`Connection<goblin.driver.connection.Connection>` object can be
 used to :py:meth:`submit<goblin.driver.connection.Connection.submit>` messages
@@ -92,5 +92,5 @@ uses the following configuration:
 +-------------------+----------------------------------------------+-------------+
 |message_serializer |String denoting the class used for message    |'classpath'  |
 |                   |serialization, currently only supports        |             |
-|                   |basic GraphSONMessageSerializer               |             |
+|                   |basic GraphSON2MessageSerializer              |             |
 +-------------------+----------------------------------------------+-------------+
diff --git a/docs/glv.rst b/docs/glv.rst
new file mode 100644
index 0000000000000000000000000000000000000000..dd50e61aa7e31755f19a2daba444c1c4520b4dac
--- /dev/null
+++ b/docs/glv.rst
@@ -0,0 +1,95 @@
+Using AsyncGraph (GLV)
+======================
+
+:py:mod:`Goblin` provides an asynchronous version of the gremlin-python
+Gremlin Language Variant (GLV) that is bundled with Apache TinkerPop beginning
+with the 3.2.2 release. Traversal are generated using the class
+:py:class:`AsyncGraph<goblin.driver.graph.AsyncGraph>` combined with a remote
+connection class, either :py:class:`Connection<goblin.driver.connection.Connection>` or
+:py:class:`DriverRemoteConnection<goblin.driver.connection.DriverRemoteConnection>`::
+
+    >>> import asyncio
+    >>> from goblin import driver
+
+    >>> loop = asyncio.get_event_loop()
+    >>> remote_conn = loop.run_until_complete(
+    ...     driver.Connection.open(
+    ...         "http://localhost:8182/gremlin", loop))
+    >>> graph = driver.AsyncGraph()
+    >>> g = graph.traversal().withRemote(remote_conn)
+
+Once you have a traversal source, it's all Gremlin...::
+
+    >>> traversal = g.addV('query_language').property('name', 'gremlin')
+
+`traversal` is in an instance of
+:py:class:`AsyncGraphTraversal<goblin.driver.graph.AsyncGraphTraversal>`, which
+implements the Python 3.5 asynchronous iterator protocol::
+
+    >>> async def iterate_traversal(traversal):
+    >>>     async for msg in traversal:
+    >>>         print(msg)
+
+    >>> loop.run_until_complete(iterate_traversal(traversal))
+    # v[0]
+
+:py:class:`AsyncGraphTraversal<goblin.driver.graph.AsyncGraphTraversal>` also
+provides several convenience methods to help iterate over results:
+
+- :py:meth:`next<goblin.driver.graph.AsyncGraphTraversal.next>`
+- :py:meth:`toList<goblin.driver.graph.AsyncGraphTraversal.toList>`
+- :py:meth:`toSet<goblin.driver.graph.AsyncGraphTraversal.toSet>`
+- :py:meth:`oneOrNone<goblin.driver.graph.AsyncGraphTraversal.oneOrNone>`
+
+Notice the mixedCase? Not very pythonic? Well no, but it maintains continuity
+with the Gremlin query language, and that's what the GLV is all about...
+
+Note: Gremlin steps that are reserved words in Python, like `or`, `in`, use a
+a trailing underscore `or_` and `in_`.
+
+The Side Effect Interface
+-------------------------
+
+When using TinkerPop 3.2.2+ with the default
+:py:class:`GraphSON2MessageSerializer<goblin.driver.serializer.GraphSON2MessageSerializer>`,
+:py:mod:`Goblin` provides an asynchronous side effects interface using the
+:py:class:`AsyncRemoteTraversalSideEffects<goblin.driver.graph.AsyncRemoteTraversalSideEffects>`
+class. This allows side effects to be retrieved after executing the traversal::
+
+    >>> traversal = g.V().aggregate('a')
+    >>> results = loop.run_until_complete(traversal.toList())
+    >>> print(results)
+    # [v[0]]
+
+Calling
+:py:meth:`keys<goblin.driver.graph.AsyncRemoteTraversalSideEffects.keys>`
+will then return an asynchronous iterator containing all keys for cached
+side effects:
+
+    >>> async def get_side_effect_keys(traversal):
+    ...     resp = await traversal.side_effects.keys()
+    ...     async for key in resp:
+    ...         print(key)
+
+
+    >>> loop.run_until_complete(get_side_effect_keys(traversal))
+    # 'a'
+
+Then calling
+:py:meth:`get<goblin.driver.graph.AsyncRemoteTraversalSideEffects.get>`
+using a valid key will return the cached side effects::
+
+    >>> async def get_side_effects(traversal):
+    ...     resp = await traversal.side_effects.get('a')
+    ...     async for side_effect in resp:
+    ...         print(side_effect)
+
+
+    >>> loop.run_until_complete(get_side_effects(traversal))
+    # v[0]
+
+And that's it! For more information on Gremlin Language Variants, please
+visit the `Apache TinkerPop GLV Documentation`_.
+
+
+.. _Apache TinkerPop GLV Documentation: http://tinkerpop.apache.org/docs/3.2.2/tutorials/gremlin-language-variants/
diff --git a/docs/goblin.driver.rst b/docs/goblin.driver.rst
index 82a612bb700e4a26116ad23f322f9a51addd72d7..776807e89d5fccf56106292e722c4293c8e23851 100644
--- a/docs/goblin.driver.rst
+++ b/docs/goblin.driver.rst
@@ -44,6 +44,14 @@ goblin.driver.pool module
     :undoc-members:
     :show-inheritance:
 
+goblin.driver.serializer module
+-------------------------------
+
+.. automodule:: goblin.driver.serializer
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
 goblin.driver.server module
 ---------------------------
 
diff --git a/docs/goblin.rst b/docs/goblin.rst
index b75195c66a868d1d4ae7306c74458b2e8992af08..da9f726d77954985d490dfa8e22eb5134fa7d9a9 100644
--- a/docs/goblin.rst
+++ b/docs/goblin.rst
@@ -83,15 +83,6 @@ goblin.session module
     :undoc-members:
     :show-inheritance:
 
-goblin.traversal module
------------------------
-
-.. automodule:: goblin.traversal
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
 Module contents
 ---------------
 
diff --git a/docs/index.rst b/docs/index.rst
index 66cc0db3343fda9da34b8c2ac635dd088aa4ba1e..1704c1732e48d19d3f558566c03999a406e2e75f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -46,7 +46,8 @@ Submit scripts and bindings to the `Gremlin Server`_::
     >>> async def go(loop):
     ...     script = "g.addV('developer').property(k1, v1)"
     ...     bindings = {'k1': 'name', 'v1': 'Leif'}
-    ...     conn = await driver.Connection.open('ws://localhost:8182/', loop)
+    ...     conn = await driver.Connection.open(
+    ...         'ws://localhost:8182/gremlin', loop)
     ...     async with conn:
     ...         resp = await conn.submit(gremlin=script, bindings=bindings)
     ...         async for msg in resp:
@@ -58,28 +59,31 @@ Submit scripts and bindings to the `Gremlin Server`_::
 
 For more information on using the driver, see the :doc:`Driver docs</driver>`
 
-**AsyncRemoteGraph**
+**AsyncGraph**
 
 Generate and submit Gremlin traversals in native Python::
 
-    >>> from gremlin_python import process
 
+    >>> remote_conn = loop.run_until_complete(
+    ...     driver.Connection.open(
+    ...         "http://localhost:8182/gremlin", loop))
+    >>> graph = driver.AsyncGraph()
+    >>> g = graph.traversal().withRemote(remote_conn)
 
-    >>> host = loop.run_until_complete(
-    ...     driver.Connection.open("http://localhost:8182/", loop))
-    >>> translator = process.GroovyTranslator('g')
-    >>> graph = driver.AsyncRemoteGraph(translator, connection)
 
-    >>> async def go(graph):
-    ...     g = graph.traversal()
-    ...     resp = await g.addV('developer').property('name', 'Leif').next()
-    ...     async for msg in resp:
+    >>> async def go(g):
+    ...     traversal = g.addV('developer').property('name', 'Leif')
+    ...     async for msg in traversal:
     ...         print(msg)
-    ...     await graph.close()
+    ...     await remote_conn.close()
 
-    >>> loop.run_until_complete(go(graph))
+
+    >>> loop.run_until_complete(go(g))
     # {'properties': {'name': [{'value': 'Leif', 'id': 3}]}, 'label': 'developer', 'id': 2, 'type': 'vertex'}
 
+For more information on using the :py:class:`goblin.driver.graph.AsyncGraph<AsyncGraph>`,
+see the :doc:`GLV docs</glv>`
+
 
 **OGM**
 
@@ -123,9 +127,9 @@ database::
     ...     works_with = Knows(leif, jon)
     ...     session.add(leif, jon, works_with)
     ...     await session.flush()
-    ...     result = await session.g.E(works_with.id).one_or_none()
+    ...     result = await session.g.E(works_with.id).oneOrNone()
     ...     assert result is works_with
-    ...     people = await session.traversal(Person).all()  # element class based traversal source
+    ...     people = session.traversal(Person)  # element class based traversal source
     ...     async for person in people:
     ...         print(person)
 
@@ -142,12 +146,30 @@ for an element, that element will be updated to reflect these changes.
 For more information on using the OGM, see the :doc:`OGM docs</ogm>`
 
 
+A note about GraphSON message serialization
+-------------------------------------------
+
+The :py:mod:`goblin.driver` provides support for both GraphSON2 and GraphSON1
+out of the box. By default, it uses the
+:py:class:`GraphSON2MessageSerializer<goblin.driver.serializer.GraphSON2MessageSerializer>`.
+Since GraphSON2 was only recently included in the TinkerPop 3.2.2 release,
+:py:mod:`goblin.driver` also ships with
+:py:class:`GraphSONMessageSerializer<goblin.driver.serializer.GraphSONMessageSerializer>`.
+In the near future (when projects like Titan and DSE support the 3.2 Gremlin
+Server line), support for GraphsSON1 will be dropped.
+
+The :py:mod:`goblin<Goblin>` OGM still uses GraphSON1 by default and will do so
+until :py:mod:`goblin.driver` support is dropped. It will then be updated to
+use GraphSON2.
+
+
 Contents:
 
 .. toctree::
    :maxdepth: 4
 
    ogm
+   glv
    driver
    modules
 
diff --git a/docs/ogm.rst b/docs/ogm.rst
index bfdfb84fa61cb78867a68a4ea3ebecb47a970631..cf1b228eab111ae126ab57dc03fe52a1b220744a 100644
--- a/docs/ogm.rst
+++ b/docs/ogm.rst
@@ -317,14 +317,21 @@ the value to be specified::
     >>> traversal = session.traversal(Person)
     >>> traversal.has(bindprop(Person, 'name', 'Leifur', binding='v1'))
 
-Finally, to submit a traversal, :py:mod:`Goblin` provides two methods:
-:py:meth:`all` and :py:meth:`one_or_none`. :py:meth:`all` returns all results
-produced by the traversal, while :py:meth:`one_or_none` returns either the last
-result, or in the case that the traversal did not return results, `None`. Remember
-to `await` the traversal when calling these methods::
+Finally, there are a variety of ways to to submit a traversal to the server.
+First of all, all traversals are themselve asynchronous iterators, and using
+them as such will cause a traversal to be sent on the wire:
+
+    >>> async for msg in session.g.V().hasLabel('person'):
+    ...     print(msg)
+
+Furthermore, :py:mod:`Goblin` provides several convenience methods that
+submit a traversal as well as process the results :py:meth:`toList`,
+:py:meth:`toSet` and :py:meth:`oneOrNone`. These methods both submit a script
+to the server and iterate over the results. Remember to `await` the traversal
+when calling these methods::
 
     >>> traversal = session.traversal(Person)
     >>> leif = await traversal.has(
-    ...     bindprop(Person, 'name', 'Leifur', binding='v1')).one_or_none()
+    ...     bindprop(Person, 'name', 'Leifur', binding='v1')).oneOrNone()
 
 And that is pretty much it. We hope you enjoy the :py:mod:`Goblin` OGM.
diff --git a/goblin/app.py b/goblin/app.py
index e2228e6fec90382195213ab18745361caf2850fc..c8c56a3453645db9b34c206b6bfa3849fe1fc507 100644
--- a/goblin/app.py
+++ b/goblin/app.py
@@ -40,19 +40,14 @@ class Goblin:
     :param dict config: Config parameters for application
     """
 
-    def __init__(self, cluster, *, translator=None, traversal_source=None,
-                 get_hashable_id=None, aliases=None):
+    def __init__(self, cluster, *, get_hashable_id=None, aliases=None):
         self._cluster = cluster
         self._loop = self._cluster._loop
-        self._traversal_source = traversal_source
         self._transactions = None
         self._cluster = cluster
         self._vertices = collections.defaultdict(
             lambda: element.GenericVertex)
         self._edges = collections.defaultdict(lambda: element.GenericEdge)
-        if not translator:
-            translator = process.GroovyTranslator('g')
-        self._translator = translator
         if not get_hashable_id:
             get_hashable_id = lambda x: x
         self._get_hashable_id = get_hashable_id
@@ -62,7 +57,11 @@ class Goblin:
 
     @classmethod
     async def open(cls, loop, *, get_hashable_id=None, aliases=None, **config):
-        cluster = await driver.Cluster.open(loop, aliases=aliases, **config)
+        # App currently only supports GraphSON 1
+        cluster = await driver.Cluster.open(
+            loop, aliases=aliases,
+            message_serializer=driver.GraphSONMessageSerializer,
+            **config)
         app = Goblin(cluster, get_hashable_id=get_hashable_id, aliases=aliases)
         await app.supports_transactions()
         return app
@@ -81,11 +80,6 @@ class Goblin:
         """Registered edge classes"""
         return self._edges
 
-    @property
-    def translator(self):
-        """gremlin-python translator class"""
-        return self._translator
-
     @property
     def url(self):
         """Database url"""
@@ -103,8 +97,27 @@ class Goblin:
             if element.__type__ == 'edge':
                 self._edges[element.__label__] = element
 
+    def config_from_file(self, filename):
+        """
+        Load configuration from from file.
+
+        :param str filename: Path to the configuration file.
+        """
+        self._cluster.config_from_file(filename)
+
+    def config_from_yaml(self, filename):
+        self._cluster.config_from_yaml(filename)
+
+    def config_from_json(self, filename):
+        """
+        Load configuration from from JSON file.
+
+        :param str filename: Path to the configuration file.
+        """
+        self._cluster.config_from_json(filename)
+
     def register_from_module(self, modulename):
-        pass
+        raise NotImplementedError
 
     async def session(self, *, use_session=False, processor='', op='eval',
                       aliases=None):
@@ -131,6 +144,7 @@ class Goblin:
                 gremlin='graph.features().graph().supportsTransactions()',
                 aliases=self._aliases)
             msg = await stream.fetch_data()
+            msg = msg.object
             stream.close()
             self._transactions = msg
         return self._transactions
diff --git a/goblin/driver/__init__.py b/goblin/driver/__init__.py
index 565c9b555e98c11469c41fe4df9f0939d4aac938..f60c40ba52da3f22a2c584e4528530f732588036 100644
--- a/goblin/driver/__init__.py
+++ b/goblin/driver/__init__.py
@@ -16,8 +16,9 @@
 # along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
 
 from goblin.driver.cluster import Cluster
-from goblin.driver.client import Client
+from goblin.driver.client import Client, SessionedClient
 from goblin.driver.connection import AbstractConnection, Connection
-from goblin.driver.graph import AsyncRemoteGraph
-from goblin.driver.serializer import GraphSONMessageSerializer
+from goblin.driver.graph import AsyncGraph
+from goblin.driver.serializer import (
+    GraphSONMessageSerializer, GraphSON2MessageSerializer)
 from goblin.driver.server import GremlinServer
diff --git a/goblin/driver/client.py b/goblin/driver/client.py
index 0fedefef847c63f0c89200448323fdbe87767405..b00e51f291afaee75b485fab5dacfb1b98a3738d 100644
--- a/goblin/driver/client.py
+++ b/goblin/driver/client.py
@@ -15,6 +15,8 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
 
+from goblin import exception
+
 
 class Client:
     """
@@ -26,8 +28,8 @@ class Client:
         client
     :param asyncio.BaseEventLoop loop:
     """
-    def __init__(self, cluster, loop, *, aliases=None,
-                 processor=None, op=None):
+    def __init__(self, cluster, loop, *, aliases=None, processor=None,
+                 op=None):
         self._cluster = cluster
         self._loop = loop
         if aliases is None:
@@ -40,6 +42,10 @@ class Client:
             op = 'eval'
         self._op = op
 
+    @property
+    def message_serializer(self):
+        return self.cluster.config['message_serializer']
+
     @property
     def cluster(self):
         """
@@ -63,11 +69,11 @@ class Client:
                      **args):
         """
         **coroutine** Submit a script and bindings to the Gremlin Server.
+
         :param str processor: Gremlin Server processor argument
         :param str op: Gremlin Server op argument
         :param args: Keyword arguments for Gremlin Server. Depend on processor
             and op.
-
         :returns: :py:class:`Response` object
         """
         processor = processor or self._processor
@@ -81,3 +87,25 @@ class Client:
             processor=processor, op=op, **args)
         self._loop.create_task(conn.release_task(resp))
         return resp
+
+
+class SessionedClient(Client):
+
+    def __init__(self, cluster, loop, session, *, aliases=None):
+        super().__init__(cluster, loop, aliases=aliases, processor='session',
+                         op='eval')
+        self._session = session
+
+    @property
+    def session(self):
+        return self._session
+
+    async def submit(self, **args):
+        if not args.get('gremlin', ''):
+            raise exception.ClientError('Session requires a gremlin string')
+        return await super().submit(processor='session', op='eval',
+                                    session=self.session,
+                                    **args)
+
+    async def close(self):
+        raise NotImplementedError
diff --git a/goblin/driver/cluster.py b/goblin/driver/cluster.py
index d93bee03ad60341126f39de3871551bc4ba8b9de..5e0024a3697a52512632f4bf978900c754610876 100644
--- a/goblin/driver/cluster.py
+++ b/goblin/driver/cluster.py
@@ -56,7 +56,7 @@ class Cluster:
         'min_conns': 1,
         'max_times_acquired': 16,
         'max_inflight': 64,
-        'message_serializer': 'goblin.driver.GraphSONMessageSerializer'
+        'message_serializer': 'goblin.driver.GraphSON2MessageSerializer'
     }
 
     def __init__(self, loop, aliases=None, **config):
@@ -108,7 +108,7 @@ class Cluster:
         if not self._hosts:
             await self.establish_hosts()
         host = self._hosts.popleft()
-        conn = await host.connect()
+        conn = await host.get_connection()
         self._hosts.append(host)
         return conn
 
@@ -164,7 +164,8 @@ class Cluster:
     def config_from_module(self, filename):
         raise NotImplementedError
 
-    async def connect(self, processor=None, op=None, aliases=None):
+    async def connect(self, processor=None, op=None, aliases=None,
+                      session=None):
         """
         **coroutine** Get a connected client. Main API method.
 
@@ -173,8 +174,15 @@ class Cluster:
         aliases = aliases or self._aliases
         if not self._hosts:
             await self.establish_hosts()
-        return driver.Client(self, self._loop, processor=processor, op=op,
-                             aliases=aliases)
+        if session:
+            host = self._hosts.popleft()
+            client = driver.SessionedClient(host, self._loop, session,
+                                            aliases=aliases)
+            self._hosts.append(host)
+        else:
+            client = driver.Client(self, self._loop, processor=processor,
+                                   op=op, aliases=aliases)
+        return client
 
     async def close(self):
         """**coroutine** Close cluster and all connected hosts."""
diff --git a/goblin/driver/connection.py b/goblin/driver/connection.py
index f4cb864307cbc57822f44a15e4487f78cefab59c..1b63c42707e98a6f5db172287039ed28e10fe684 100644
--- a/goblin/driver/connection.py
+++ b/goblin/driver/connection.py
@@ -53,12 +53,17 @@ def error_handler(fn):
 
 class Response:
     """Gremlin Server response implementated as an async iterator."""
-    def __init__(self, response_queue, timeout, loop):
+    def __init__(self, response_queue, request_id, timeout, loop):
         self._response_queue = response_queue
+        self._request_id = request_id
         self._loop = loop
         self._timeout = timeout
         self._done = asyncio.Event(loop=self._loop)
 
+    @property
+    def request_id(self):
+        return self._request_id
+
     @property
     def done(self):
         """
@@ -74,7 +79,7 @@ class Response:
     async def __anext__(self):
         msg = await self.fetch_data()
         if msg:
-            return msg
+            return msg.object
         else:
             raise StopAsyncIteration
 
@@ -147,11 +152,10 @@ class Connection(AbstractConnection):
             message_serializer = message_serializer()
         self._message_serializer = message_serializer
 
-
     @classmethod
     async def open(cls, url, loop, *, ssl_context=None, username='',
                    password='', max_inflight=64, response_timeout=None,
-                   message_serializer=serializer.GraphSONMessageSerializer):
+                   message_serializer=serializer.GraphSON2MessageSerializer):
         """
         **coroutine** Open a connection to the Gremlin Server.
 
@@ -173,6 +177,10 @@ class Connection(AbstractConnection):
         return cls(url, ws, loop, client_session, username, password,
                    max_inflight, response_timeout, message_serializer)
 
+    @property
+    def message_serializer(self):
+        return self._message_serializer
+
     @property
     def closed(self):
         """
@@ -198,6 +206,7 @@ class Connection(AbstractConnection):
                      **args):
         """
         Submit a script and bindings to the Gremlin Server
+
         :param str processor: Gremlin Server processor argument
         :param str op: Gremlin Server op argument
         :param args: Keyword arguments for Gremlin Server. Depend on processor
@@ -213,7 +222,7 @@ class Connection(AbstractConnection):
         if self._ws.closed:
             self._ws = await self.client_session.ws_connect(self.url)
         self._ws.send_bytes(message)
-        resp = Response(response_queue, self._response_timeout, self._loop)
+        resp = Response(response_queue, request_id, self._response_timeout, self._loop)
         self._loop.create_task(self._terminate_response(resp, request_id))
         return resp
 
@@ -266,9 +275,11 @@ class Connection(AbstractConnection):
                 else:
                     if data:
                         for result in data:
+                            result = self._message_serializer.deserialize_message(result)
                             message = Message(status_code, result, msg)
                             response_queue.put_nowait(message)
                     else:
+                        data = self._message_serializer.deserialize_message(data)
                         message = Message(status_code, data, msg)
                         response_queue.put_nowait(message)
                     if status_code != 206:
@@ -280,3 +291,6 @@ class Connection(AbstractConnection):
     async def __aexit__(self, exc_type, exc, tb):
         await self.close()
         self._conn = None
+
+
+DriverRemoteConnection = Connection
diff --git a/goblin/driver/graph.py b/goblin/driver/graph.py
index 553cfffefc0fe99c483ded423a15eb5c61021980..4720b8ddcb7bf9b1e3d986b9498e27d943130b1c 100644
--- a/goblin/driver/graph.py
+++ b/goblin/driver/graph.py
@@ -17,75 +17,151 @@
 
 """A temporary solution to allow integration with gremlin_python package."""
 
+import functools
+
 from gremlin_python.process.graph_traversal import (
-    GraphTraversalSource, GraphTraversal)
-from gremlin_python.process.traversal import (
-    TraversalStrategy, TraversalStrategies)
+    GraphTraversal, GraphTraversalSource)
+from gremlin_python.process.traversal import TraversalStrategies
+from gremlin_python.driver.remote_connection import (
+    RemoteStrategy, RemoteTraversalSideEffects)
+from gremlin_python.structure.graph import Graph
+from goblin.driver.serializer import GraphSON2MessageSerializer
 
 
-class AsyncGraphTraversal(GraphTraversal):
-    def __init__(self, graph, traversal_strategies, bytecode):
-        GraphTraversal.__init__(self, graph, traversal_strategies, bytecode)
+class AsyncRemoteTraversalSideEffects(RemoteTraversalSideEffects):
 
-    def __repr__(self):
-        return self.graph.translator.translate(self.bytecode)
+    async def keys(self):
+        return await self.keys_lambda()
 
-    def toList(self):
-        raise NotImplementedError
-
-    def toSet(self):
-        raise NotImplementedError
+    async def get(self, key):
+        return await self.value_lambda(sideEffectKey=key)
 
-    async def next(self):
-        resp = await self.traversal_strategies.apply(self)
-        return resp
 
+class AsyncRemoteStrategy(RemoteStrategy):
 
-class AsyncRemoteStrategy(TraversalStrategy):
     async def apply(self, traversal):
-        result = await traversal.graph.remote_connection.submit(
-            gremlin=traversal.graph.translator.translate(traversal.bytecode),
-            bindings=traversal.bindings,
-            lang=traversal.graph.translator.target_language)
+        if isinstance(self.remote_connection.message_serializer,
+                      GraphSON2MessageSerializer):
+            processor = 'traversal'
+            op = 'bytecode'
+            side_effects = AsyncRemoteTraversalSideEffects
+        else:
+            processor = ''
+            op = 'eval'
+            side_effects = None
+        if traversal.traversers is None:
+            resp = await self.remote_connection.submit(
+                gremlin=traversal.bytecode, processor=processor, op=op)
+            traversal.traversers = resp
+            if side_effects:
+                keys_lambda = functools.partial(self.remote_connection.submit,
+                                                processor='traversal',
+                                                op='keys',
+                                                sideEffect=resp.request_id)
+                value_lambda = functools.partial(self.remote_connection.submit,
+                                                 processor='traversal',
+                                                 op='gather',
+                                                 sideEffect=resp.request_id)
+                side_effects = side_effects(keys_lambda, value_lambda)
+            traversal.side_effects = side_effects
+
+
+
+class AsyncGraphTraversal(GraphTraversal):
+
+    async def __aiter__(self):
+        return self
+
+    async def __anext__(self):
+        if self.traversers is None:
+            await self._get_traversers()
+        if self.last_traverser is None:
+            self.last_traverser = await self.traversers.fetch_data()
+            if self.last_traverser is None:
+                raise StopAsyncIteration
+        obj = self.last_traverser.object
+        self.last_traverser.bulk = self.last_traverser.bulk - 1
+        if self.last_traverser.bulk <= 0:
+            self.last_traverser = None
+        return obj
+
+    async def _get_traversers(self):
+        for ts in self.traversal_strategies.traversal_strategies:
+            await ts.apply(self)
+
+    async def next(self, amount=None):
+        """
+        **coroutine** Return the next result from the iterator.
+
+        :param int amount: The number of results returned, defaults to None
+            (1 result)
+        """
+        if amount is None:
+            try:
+                return await self.__anext__()
+            except StopAsyncIteration:
+                pass
+        else:
+            count = 0
+            tempList = []
+            while count < amount:
+                count = count + 1
+                try: temp = await self.__anext__()
+                except StopIteration: return tempList
+                tempList.append(temp)
+            return tempList
+
+    async def toList(self):
+        """**coroutine** Submit the travesal, iterate results, return a list"""
+        results = []
+        async for msg in self:
+            results.append(msg)
+        return results
+
+    async def toSet(self):
+        """**coroutine** Submit the travesal, iterate results, return a set"""
+        results = set()
+        async for msg in self:
+            results.add(msg)
+        return results
+
+    async def oneOrNone(self):
+        """
+        **coroutine** Get one or zero results from a traveral. Returns last
+        iterated result.
+        """
+        result = None
+        async for msg in self:
+            result = msg
         return result
 
+    def iterate(self):
+        raise NotImplementedError
 
-class AsyncGraph:
-    def traversal(self):
-        return GraphTraversalSource(self, self.traversal_strategy,
-                                    graph_traversal=self.graph_traversal)
-
-
-class AsyncRemoteGraph(AsyncGraph):
-    """
-    Generate asynchronous gremlin traversals using native Python.
-
-    :param gremlin_python.process.GroovyTranslator translator:
-        gremlin_python translator class, typically
-        :py:class:`GroovyTranslator<gremlin_python.process.GroovyTranslator>`
-    :param goblin.driver.connection connection: underlying remote
-        connection
-    :param gremlin_python.process.GraphTraversal graph_traversal:
-        Custom graph traversal class
-    """
-    def __init__(self, translator, remote_connection, *, graph_traversal=None):
-        self.traversal_strategy = AsyncRemoteStrategy()  # A single traversal strategy
-        self.translator = translator
-        self.remote_connection = remote_connection
-        if graph_traversal is None:
-            graph_traversal = AsyncGraphTraversal
-        self.graph_traversal = graph_traversal
+    def nextTraverser(self):
+        raise NotImplementedError
 
-    def __repr__(self):
-        return "remotegraph[" + self.remote_connection.url + "]"
 
-    async def close(self):
-        """Close underlying remote connection"""
-        await self.remote_connection.close()
-        self.remote_connection = None
+class AsyncGraph(Graph):
+    """Generate asynchronous gremlin traversals using native Python"""
 
-    async def __aenter__(self):
-        return self
+    def traversal(self, *, graph_traversal=None, remote_strategy=None):
+        """
+        Get a traversal source from the Graph
+
+        :param gremlin_python.process.GraphTraversal graph_traversal:
+            Custom graph traversal class
+        :param gremlin_python.driver.remote_connection.RemoteStrategy remote_strategy:
+            Custom remote strategy class
 
-    async def __aexit__(self, exc_type, exc, tb):
-        await self.close()
+        :returns:
+            :py:class:`gremlin_python.process.graph_traversal.GraphTraversalSource`
+        """
+        if graph_traversal is None:
+            graph_traversal = AsyncGraphTraversal
+        if remote_strategy is None:
+            remote_strategy = AsyncRemoteStrategy
+        return GraphTraversalSource(
+            self, TraversalStrategies.global_cache[self.__class__],
+            remote_strategy=remote_strategy,
+            graph_traversal=graph_traversal)
diff --git a/goblin/driver/serializer.py b/goblin/driver/serializer.py
index 8c1f2230ee02298005cbe66a9ed42a95faa30aa0..d39a759e6aafd6f94d17641d04528fc79ac49c3c 100644
--- a/goblin/driver/serializer.py
+++ b/goblin/driver/serializer.py
@@ -17,19 +17,132 @@
 
 import json
 
+from gremlin_python.process.traversal import Bytecode, Traverser
+from gremlin_python.process.translator import GroovyTranslator
+from gremlin_python.structure.io.graphson import GraphSONWriter, GraphSONReader
+
+
+class Processor:
+    """Base class for OpProcessor serialization system."""
+
+    def get_op(self, op):
+        op = getattr(self, op, None)
+        if not op:
+            raise Exception("Processor does not support op")
+        return op
+
 
 class GraphSONMessageSerializer:
+    """Message serializer for GraphSONv1"""
+    # processors and ops
+    class standard(Processor):
+
+        def authentication(self, args):
+            return args
+
+        def eval(self, args):
+            gremlin = args['gremlin']
+            if isinstance(gremlin, Bytecode):
+                translator = GroovyTranslator('g')
+                args['gremlin'] = translator.translate(gremlin)
+                args['bindings'] = gremlin.bindings
+            return args
+
+
+    class session(standard):
+        pass
+
+
+    def get_processor(self, processor):
+        processor = getattr(self, processor, None)
+        if not processor:
+            raise Exception("Unknown processor")
+        return processor()
 
     def serialize_message(self, request_id, processor, op, **args):
+        if not processor:
+            processor_obj = self.get_processor('standard')
+        else:
+            processor_obj = self.get_processor(processor)
+        op_method = processor_obj.get_op(op)
+        args = op_method(args)
+        message = self.build_message(request_id, processor, op, args)
+        return message
+
+    def build_message(self, request_id, processor, op, args):
         message = {
             'requestId': request_id,
             'processor': processor,
             'op': op,
             'args': args
         }
+        return self.finalize_message(message,  b'\x10', b'application/json')
+
+    def finalize_message(self, message, mime_len, mime_type):
         message = json.dumps(message)
-        mime_len = b'\x10'
-        mime_type = b'application/json'
         message = b''.join([mime_len, mime_type, message.encode('utf-8')])
-        print(message)
         return message
+
+    def deserialize_message(self, message):
+        return Traverser(message)
+
+
+class GraphSON2MessageSerializer(GraphSONMessageSerializer):
+    """Message serializer for GraphSONv2"""
+
+    class session(GraphSONMessageSerializer.session):
+
+        def close(self, args):
+            return args
+
+
+    class traversal(Processor):
+
+        def authentication(self, args):
+            return args
+
+        def bytecode(self, args):
+            gremlin = args['gremlin']
+            args['gremlin'] = GraphSONWriter.writeObject(gremlin)
+            aliases = args.get('aliases', '')
+            if not aliases:
+                aliases = {'g': 'g'}
+            args['aliases'] = aliases
+            return args
+
+        def close(self, args):
+            return self.keys(args)
+
+        def gather(self, args):
+            side_effect = args['sideEffect']
+            args['sideEffect'] = {'@type': 'g:UUID', '@value': side_effect}
+            aliases = args.get('aliases', '')
+            if not aliases:
+                aliases = {'g': 'g'}
+            args['aliases'] = aliases
+            return args
+
+        def keys(self, args):
+            side_effect = args['sideEffect']
+            args['sideEffect'] = {'@type': 'g:UUID', '@value': side_effect}
+            return args
+
+    def build_message(self, request_id, processor, op, args):
+        message = {
+            'requestId': {'@type': 'g:UUID', '@value': request_id},
+            'processor': processor,
+            'op': op,
+            'args': args
+        }
+        return self.finalize_message(message, b"\x21",
+                                     b"application/vnd.gremlin-v2.0+json")
+
+    def deserialize_message(self, message):
+        if isinstance(message, dict):
+            if message.get('@type', '') == 'g:Traverser':
+                obj = GraphSONReader._objectify(message)
+            else:
+                obj = Traverser(message.get('@value', message))
+        else:
+            obj = Traverser(message)
+        return obj
diff --git a/goblin/driver/server.py b/goblin/driver/server.py
index 130e59e80b5ae9072b89ee0c86023d03f3fbb680..3ba5a24b1fd0763b11cbbdfbad2b2e7a57f1425e 100644
--- a/goblin/driver/server.py
+++ b/goblin/driver/server.py
@@ -70,7 +70,7 @@ class GremlinServer:
             await self._pool.close()
             self._pool = None
 
-    async def connect(self):
+    async def get_connection(self):
         """**coroutine** Acquire a connection from the pool."""
         try:
             conn = await self._pool.acquire()
diff --git a/goblin/exception.py b/goblin/exception.py
index ccdfdef7f6b86a4da6a8014b6e30863f22d56bb9..203102b9e8db4217ac6903fc63ccb9492402b011 100644
--- a/goblin/exception.py
+++ b/goblin/exception.py
@@ -15,6 +15,11 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
 
+
+class ClientError(Exception):
+    pass
+
+
 class MappingError(Exception):
     pass
 
diff --git a/goblin/session.py b/goblin/session.py
index e832e6bcdd718d34bdc055ef55aa9d5652da7243..6a1671acf961a5c1e46ef458ec032aa5ea3663e4 100644
--- a/goblin/session.py
+++ b/goblin/session.py
@@ -22,14 +22,77 @@ import collections
 import logging
 import weakref
 
-from goblin import exception, mapper, traversal
+from goblin import cardinality, exception, mapper
 from goblin.driver import connection, graph
 from goblin.element import GenericVertex
 
+from gremlin_python.driver.remote_connection import RemoteStrategy
+from gremlin_python.process.traversal import Cardinality
+
+
 
 logger = logging.getLogger(__name__)
 
 
+def bindprop(element_class, ogm_name, val, *, binding=None):
+    """
+    Helper function for binding ogm properties/values to corresponding db
+    properties/values for traversals.
+
+    :param goblin.element.Element element_class: User defined element class
+    :param str ogm_name: Name of property as defined in the ogm
+    :param val: The property value
+    :param str binding: The binding for val (optional)
+
+    :returns: tuple object ('db_property_name', ('binding(if passed)', val))
+    """
+    db_name = getattr(element_class, ogm_name, ogm_name)
+    _, data_type = element_class.__mapping__.ogm_properties[ogm_name]
+    val = data_type.to_db(val)
+    if binding:
+        val = (binding, val)
+    return db_name, val
+
+
+class TraversalResponse:
+    """Asynchronous iterator that encapsulates a traversal response queue"""
+    def __init__(self, response_queue, request_id):
+        self._queue = response_queue
+        self._request_id = request_id
+        self._done = False
+
+    @property
+    def request_id(self):
+        return self._request_id
+
+    async def __aiter__(self):
+        return self
+
+    async def __anext__(self):
+        if self._done:
+            return
+        msg = await self.fetch_data()
+        if msg:
+            return msg
+        else:
+            self._done = True
+            raise StopAsyncIteration
+
+    async def fetch_data(self):
+        return await self._queue.get()
+
+
+class GoblinAsyncRemoteStrategy(RemoteStrategy):
+
+    async def apply(self, traversal):
+
+        if traversal.traversers is None:
+            resp = await self.remote_connection.submit(
+                gremlin=traversal.bytecode, processor='', op='eval')
+            traversal.traversers = resp
+            traversal.side_effects = None
+
+
 class Session(connection.AbstractConnection):
     """
     Provides the main API for interacting with the database. Does not
@@ -50,10 +113,15 @@ class Session(connection.AbstractConnection):
         self._pending = collections.deque()
         self._current = weakref.WeakValueDictionary()
         self._get_hashable_id = get_hashable_id
-        remote_graph = graph.AsyncRemoteGraph(
-            self._app.translator, self,
-            graph_traversal=traversal.GoblinTraversal)
-        self._traversal_factory = traversal.TraversalFactory(remote_graph)
+        self._graph = graph.AsyncGraph()
+
+    @property
+    def graph(self):
+        return self._graph
+
+    @property
+    def message_serializer(self):
+        return self.conn.message_serializer
 
     @property
     def app(self):
@@ -63,10 +131,6 @@ class Session(connection.AbstractConnection):
     def conn(self):
         return self._conn
 
-    @property
-    def traversal_factory(self):
-        return self._traversal_factory
-
     @property
     def current(self):
         return self._current
@@ -93,19 +157,40 @@ class Session(connection.AbstractConnection):
             :py:class:`goblin.gremlin_python.process.GraphTraversalSource`
             object
         """
-        return self.traversal_factory.traversal()
+        return self.traversal()
 
-    def traversal(self, element_class):
+    @property
+    def _g(self):
+        """
+        Traversal source for internal use. Uses undelying conn. Doesn't
+        trigger complex deserailization.
         """
-        Get a traversal spawned from an element class.
+        return self.graph.traversal(
+            graph_traversal=graph.AsyncGraphTraversal,
+            remote_strategy=GoblinAsyncRemoteStrategy).withRemote(self.conn)
 
-        :param :goblin.element.Element element_class: Element class
-            used to spawn traversal.
+    def traversal(self, element_class=None):
+        """
+        Generate a traversal using a user defined element class as a
+        starting point.
 
-        :returns: :py:class:`GoblinTraversal<goblin.traversal.GoblinTraversal>`
-            object
+        :param goblin.element.Element element_class: An optional element
+            class that will dictate the element type (vertex/edge) as well as
+            the label for the traversal source
+
+        :returns: :py:class:`AsyncGraphTraversal`
         """
-        return self.traversal_factory.traversal(element_class=element_class)
+        traversal = self.graph.traversal(
+            graph_traversal=graph.AsyncGraphTraversal,
+            remote_strategy=GoblinAsyncRemoteStrategy).withRemote(self)
+        if element_class:
+            label = element_class.__mapping__.label
+            if element_class.__type__ == 'vertex':
+                traversal = traversal.V()
+            if element_class.__type__ == 'edge':
+                traversal = traversal.E()
+            traversal = traversal.hasLabel(label)
+        return traversal
 
     async def submit(self,
                      **args):
@@ -124,25 +209,30 @@ class Session(connection.AbstractConnection):
         response_queue = asyncio.Queue(loop=self._loop)
         self._loop.create_task(
             self._receive(async_iter, response_queue))
-        return traversal.TraversalResponse(response_queue)
+        return TraversalResponse(response_queue, async_iter.request_id)
 
     async def _receive(self, async_iter, response_queue):
-        async for result in async_iter:
-            if (isinstance(result, dict) and
-                    result.get('type', '') in ['vertex', 'edge']):
-                hashable_id = self._get_hashable_id(result['id'])
+        while True:
+            result = await async_iter.fetch_data()
+            if result is None:
+                break
+            obj = result.object
+            if (isinstance(obj, dict) and
+                    obj.get('type', '') in ['vertex', 'edge']):
+                hashable_id = self._get_hashable_id(obj['id'])
                 current = self.current.get(hashable_id, None)
                 if not current:
-                    element_type = result['type']
-                    label = result['label']
+                    element_type = obj['type']
+                    label = obj['label']
                     if element_type == 'vertex':
                         current = self.app.vertices[label]()
                     else:
                         current = self.app.edges[label]()
                         current.source = GenericVertex()
                         current.target = GenericVertex()
-                element = current.__mapping__.mapper_func(result, current)
-                response_queue.put_nowait(element)
+                element = current.__mapping__.mapper_func(obj, current)
+                result.object = element
+                response_queue.put_nowait(result)
             else:
                 response_queue.put_nowait(result)
         response_queue.put_nowait(None)
@@ -172,7 +262,7 @@ class Session(connection.AbstractConnection):
 
         :param goblin.element.Vertex vertex: Vertex to be removed
         """
-        traversal = self.traversal_factory.remove_vertex(vertex)
+        traversal = self._g.V(vertex.id).drop()
         result = await self._simple_traversal(traversal, vertex)
         hashable_id = self._get_hashable_id(vertex.id)
         vertex = self.current.pop(hashable_id)
@@ -185,7 +275,7 @@ class Session(connection.AbstractConnection):
 
         :param goblin.element.Edge edge: Element to be removed
         """
-        traversal = self.traversal_factory.remove_edge(edge)
+        traversal = self._g.E(edge.id).drop()
         result = await self._simple_traversal(traversal, edge)
         hashable_id = self._get_hashable_id(edge.id)
         edge = self.current.pop(hashable_id)
@@ -252,8 +342,7 @@ class Session(connection.AbstractConnection):
 
         :returns: :py:class:`Vertex<goblin.element.Vertex>` | None
         """
-        return await self.traversal_factory.get_vertex_by_id(
-            vertex).one_or_none()
+        return await self.g.V(vertex.id).oneOrNone()
 
     async def get_edge(self, edge):
         """
@@ -263,8 +352,7 @@ class Session(connection.AbstractConnection):
 
         :returns: :py:class:`Edge<goblin.element.Edge>` | None
         """
-        return await self.traversal_factory.get_edge_by_id(
-            edge).one_or_none()
+        return await self.g.E(edge.id).oneOrNone()
 
     async def update_vertex(self, vertex):
         """
@@ -276,7 +364,7 @@ class Session(connection.AbstractConnection):
         """
         props = mapper.map_props_to_db(vertex, vertex.__mapping__)
         # vert_props = mapper.map_vert_props_to_db
-        traversal = self.g.V(vertex.id)
+        traversal = self._g.V(vertex.id)
         return await self._update_vertex_properties(vertex, traversal, props)
 
     async def update_edge(self, edge):
@@ -288,7 +376,7 @@ class Session(connection.AbstractConnection):
         :returns: :py:class:`Edge<goblin.element.Edge>` object
         """
         props = mapper.map_props_to_db(edge, edge.__mapping__)
-        traversal = self.g.E(edge.id)
+        traversal = self._g.E(edge.id)
         return await self._update_edge_properties(edge, traversal, props)
 
     # Transaction support
@@ -308,13 +396,10 @@ class Session(connection.AbstractConnection):
 
     # *metodos especiales privados for creation API
     async def _simple_traversal(self, traversal, element):
-        stream = await self.conn.submit(
-            gremlin=repr(traversal), bindings=traversal.bindings)
-        msg = await stream.fetch_data()
-        stream.close()
+        msg = await traversal.oneOrNone()
         if msg:
             msg = element.__mapping__.mapper_func(msg, element)
-            return msg
+        return msg
 
     async def _save_element(self,
                             elem,
@@ -331,66 +416,57 @@ class Session(connection.AbstractConnection):
             result = await create_func(elem)
         return result
 
-    async def _add_vertex(self, elem):
+    async def _add_vertex(self, vertex):
         """Convenience function for generating crud traversals."""
-        props = mapper.map_props_to_db(elem, elem.__mapping__)
-        traversal = self.g.addV(elem.__mapping__.label)
-        traversal, _, metaprops = self.traversal_factory.add_properties(
-            traversal, props)
-        result = await self._simple_traversal(traversal, elem)
+        props = mapper.map_props_to_db(vertex, vertex.__mapping__)
+        traversal = self._g.addV(vertex.__mapping__.label)
+        traversal, _, metaprops = self._add_properties(traversal, props)
+        result = await self._simple_traversal(traversal, vertex)
         if metaprops:
             await self._add_metaprops(result, metaprops)
-            traversal = self.traversal_factory.get_vertex_by_id(elem)
-            result = await self._simple_traversal(traversal, elem)
+            traversal = self._g.V(vertex.id)
+            result = await self._simple_traversal(traversal, vertex)
         return result
 
-    async def _add_edge(self, elem):
+    async def _add_edge(self, edge):
         """Convenience function for generating crud traversals."""
-        props = mapper.map_props_to_db(elem, elem.__mapping__)
-        traversal = self.g.V(elem.source.id)
-        traversal = traversal.addE(elem.__mapping__._label)
+        props = mapper.map_props_to_db(edge, edge.__mapping__)
+        traversal = self._g.V(edge.source.id)
+        traversal = traversal.addE(edge.__mapping__._label)
         traversal = traversal.to(
-            self.g.V(elem.target.id))
-        traversal, _, _ = self.traversal_factory.add_properties(
+            self._g.V(edge.target.id))
+        traversal, _, _ = self._add_properties(
             traversal, props)
-        return await self._simple_traversal(traversal, elem)
+        return await self._simple_traversal(traversal, edge)
 
     async def _check_vertex(self, vertex):
         """Used to check for existence, does not update session vertex"""
-        traversal = self.g.V(vertex.id)
-        stream = await self.conn.submit(gremlin=repr(traversal))
-        msg = await stream.fetch_data()
-        stream.close()
+        msg = await self._g.V(vertex.id).oneOrNone()
         return msg
 
     async def _check_edge(self, edge):
         """Used to check for existence, does not update session edge"""
-        traversal = self.g.E(edge.id)
-        stream = await self.conn.submit(gremlin=repr(traversal))
-        msg = await stream.fetch_data()
-        stream.close()
+        msg = await self._g.E(edge.id).oneOrNone()
         return msg
 
     async def _update_vertex_properties(self, vertex, traversal, props):
-        traversal, removals, metaprops = self.traversal_factory.add_properties(
-            traversal, props)
+        traversal, removals, metaprops = self._add_properties(traversal, props)
         for k in removals:
-            await self.g.V(vertex.id).properties(k).drop().one_or_none()
+            await self._g.V(vertex.id).properties(k).drop().oneOrNone()
         result = await self._simple_traversal(traversal, vertex)
         if metaprops:
             removals = await self._add_metaprops(result, metaprops)
             for db_name, key, value in removals:
-                await self.g.V(vertex.id).properties(
-                    db_name).has(key, value).drop().one_or_none()
-            traversal = self.traversal_factory.get_vertex_by_id(vertex)
+                await self._g.V(vertex.id).properties(
+                    db_name).has(key, value).drop().oneOrNone()
+            traversal = self._g.V(vertex.id)
             result = await self._simple_traversal(traversal, vertex)
         return result
 
     async def _update_edge_properties(self, edge, traversal, props):
-        traversal, removals, _ = self.traversal_factory.add_properties(
-            traversal, props)
+        traversal, removals, _ = self._add_properties(traversal, props)
         for k in removals:
-            await self.g.E(edge.id).properties(k).drop().one_or_none()
+            await self._g.E(edge.id).properties(k).drop().oneOrNone()
         return await self._simple_traversal(traversal, edge)
 
     async def _add_metaprops(self, result, metaprops):
@@ -399,12 +475,35 @@ class Session(connection.AbstractConnection):
             db_name, (binding, value), metaprops = metaprop
             for key, val in metaprops.items():
                 if val:
-                    traversal = self.g.V(result.id).properties(
+                    traversal = self._g.V(result.id).properties(
                         db_name).hasValue(value).property(key, val)
-                    stream = await self.conn.submit(
-                        gremlin=repr(traversal), bindings=traversal.bindings)
-                    await stream.fetch_data()
-                    stream.close()
+                    await traversal.oneOrNone()
                 else:
                     potential_removals.append((db_name, key, value))
         return potential_removals
+
+    def _add_properties(self, traversal, props):
+        binding = 0
+        potential_removals = []
+        potential_metaprops = []
+        for card, db_name, val, metaprops in props:
+            if val:
+                key = ('k' + str(binding), db_name)
+                val = ('v' + str(binding), val)
+                if card:
+                    # Maybe use a dict here as a translator
+                    if card == cardinality.Cardinality.list:
+                        card = Cardinality.list
+                    elif card == cardinality.Cardinality.set:
+                        card = Cardinality.set
+                    else:
+                        card = Cardinality.single
+                    traversal = traversal.property(card, key, val)
+                else:
+                    traversal = traversal.property(key, val)
+                binding += 1
+                if metaprops:
+                    potential_metaprops.append((db_name, val, metaprops))
+            else:
+                potential_removals.append(db_name)
+        return traversal, potential_removals, potential_metaprops
diff --git a/goblin/traversal.py b/goblin/traversal.py
deleted file mode 100644
index f516a65c55276e12163257628e20ba97a8d39c62..0000000000000000000000000000000000000000
--- a/goblin/traversal.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# Copyright 2016 ZEROFAIL
-#
-# This file is part of Goblin.
-#
-# Goblin is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Goblin is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
-
-"""Query API and helpers"""
-
-import asyncio
-import functools
-import logging
-
-from goblin import cardinality, element, mapper
-from goblin.driver import connection, graph
-from gremlin_python import process
-
-
-logger = logging.getLogger(__name__)
-
-
-def bindprop(element_class, ogm_name, val, *, binding=None):
-    """
-    Helper function for binding ogm properties/values to corresponding db
-    properties/values for traversals.
-
-    :param goblin.element.Element element_class: User defined element class
-    :param str ogm_name: Name of property as defined in the ogm
-    :param val: The property value
-    :param str binding: The binding for val (optional)
-
-    :returns: tuple object ('db_property_name', ('binding(if passed)', val))
-    """
-    db_name = getattr(element_class, ogm_name, ogm_name)
-    _, data_type = element_class.__mapping__.ogm_properties[ogm_name]
-    val = data_type.to_db(val)
-    if binding:
-        val = (binding, val)
-    return db_name, val
-
-
-class TraversalResponse:
-    """Asynchronous iterator that encapsulates a traversal response queue"""
-    def __init__(self, response_queue):
-        self._queue = response_queue
-        self._done = False
-
-    async def __aiter__(self):
-        return self
-
-    async def __anext__(self):
-        if self._done:
-            return
-        msg = await self._queue.get()
-        if msg:
-            return msg
-        else:
-            self._done = True
-            raise StopAsyncIteration
-
-
-# This is all until we figure out GLV integration...
-class GoblinTraversal(graph.AsyncGraphTraversal):
-
-    async def all(self):
-        """
-        Get all results from traversal.
-
-        :returns: :py:class:`TraversalResponse` object
-        """
-        return await self.next()
-
-    async def one_or_none(self):
-        """
-        Get one or zero results from a traveral.
-
-        :returns: :py:class:`Element<goblin.element.Element>` object
-        """
-        result = None
-        async for msg in await self.next():
-            result = msg
-        return result
-
-
-class TraversalFactory:
-    """Helper that wraps a AsyncRemoteGraph"""
-    def __init__(self, graph):
-        self._graph = graph
-
-    @property
-    def graph(self):
-        return self._graph
-
-    def traversal(self, *, element_class=None):
-        """
-        Generate a traversal using a user defined element class as a
-        starting point.
-
-        :param goblin.element.Element element_class: An optional element
-            class that will dictate the element type (vertex/edge) as well as
-            the label for the traversal source
-
-        :returns: :py:class:`GoblinTraversal`
-        """
-        traversal = self.graph.traversal()
-        if element_class:
-            label = element_class.__mapping__.label
-            traversal = self._graph.traversal()
-            if element_class.__type__ == 'vertex':
-                traversal = traversal.V()
-            if element_class.__type__ == 'edge':
-                traversal = traversal.E()
-            traversal = traversal.hasLabel(label)
-        return traversal
-
-    def remove_vertex(self, elem):
-        """Convenience function for generating crud traversals."""
-        return self.traversal().V(elem.id).drop()
-
-    def remove_edge(self, elem):
-        """Convenience function for generating crud traversals."""
-        return self.traversal().E(elem.id).drop()
-
-    def get_vertex_by_id(self, elem):
-        """Convenience function for generating crud traversals."""
-        return self.traversal().V(elem.id)
-
-    def get_edge_by_id(self, elem):
-        """Convenience function for generating crud traversals."""
-        return self.traversal().E(elem.id)
-
-    def add_properties(self, traversal, props):
-        binding = 0
-        potential_removals = []
-        potential_metaprops = []
-        for card, db_name, val, metaprops in props:
-            if val:
-                key = ('k' + str(binding), db_name)
-                val = ('v' + str(binding), val)
-                if card:
-                    # Maybe use a dict here as a translator
-                    if card == cardinality.Cardinality.list:
-                        card = process.Cardinality.list
-                    elif card == cardinality.Cardinality.set:
-                        card = process.Cardinality.set
-                    else:
-                        card = process.Cardinality.single
-                    traversal = traversal.property(card, key, val)
-                else:
-                    traversal = traversal.property(key, val)
-                binding += 1
-                if metaprops:
-                    potential_metaprops.append((db_name, val, metaprops))
-            else:
-                potential_removals.append(db_name)
-        return traversal, potential_removals, potential_metaprops
diff --git a/gremlin_python/__init__.py b/gremlin_python/__init__.py
index 518d8e008b256688b90e792343fd0cf1e7bb26e2..7626550738f12ccd5e18b8c06a8d68aaab882066 100644
--- a/gremlin_python/__init__.py
+++ b/gremlin_python/__init__.py
@@ -16,6 +16,5 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-from . import statics
 
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
diff --git a/gremlin_python/driver/__init__.py b/gremlin_python/driver/__init__.py
index 7e1c0f1a812f96353a3b4b12daf4db66b2ce4a51..7626550738f12ccd5e18b8c06a8d68aaab882066 100644
--- a/gremlin_python/driver/__init__.py
+++ b/gremlin_python/driver/__init__.py
@@ -16,7 +16,5 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-from .remote_connection import RemoteConnection
-from .rest_remote_connection import RESTRemoteConnection
 
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
diff --git a/gremlin_python/driver/remote_connection.py b/gremlin_python/driver/remote_connection.py
index 1651b92ad7809e01fd6fecf06371edacd3a7b937..452fcaf5f6e5c6915bcdeafaa28851911002a46e 100644
--- a/gremlin_python/driver/remote_connection.py
+++ b/gremlin_python/driver/remote_connection.py
@@ -16,16 +16,64 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-from abc import abstractmethod
+import abc
+import six
+
+from ..process.traversal import Traversal
+from ..process.traversal import TraversalStrategy
+from ..process.traversal import TraversalSideEffects
 
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
 
 
+@six.add_metaclass(abc.ABCMeta)
 class RemoteConnection(object):
-    def __init__(self, url):
-        self.url = url
+    def __init__(self, url, traversal_source):
+        self._url = url
+        self._traversal_source = traversal_source
+
+    @property
+    def url(self):
+        return self._url
+
+    @property
+    def traversal_source(self):
+        return self._traversal_source
+
+    @abc.abstractmethod
+    def submit(self, bytecode):
+        print("sending " + bytecode + " to GremlinServer...")
+        return RemoteTraversal(iter([]), TraversalSideEffects())
+
+    def __repr__(self):
+        return "remoteconnection[" + self._url + "," + self._traversal_source + "]"
+
+
+class RemoteTraversal(Traversal):
+    def __init__(self, traversers, side_effects):
+        Traversal.__init__(self, None, None, None)
+        self.traversers = traversers
+        self.side_effects = side_effects
+
+
+class RemoteTraversalSideEffects(TraversalSideEffects):
+    def __init__(self, keys_lambda, value_lambda):
+        self.keys_lambda = keys_lambda
+        self.value_lambda = value_lambda
+
+    def keys(self):
+        return self.keys_lambda()
+
+    def get(self, key):
+        return self.value_lambda(key)
+
+
+class RemoteStrategy(TraversalStrategy):
+    def __init__(self, remote_connection):
+        self.remote_connection = remote_connection
 
-    @abstractmethod
-    def submit(self, target_language, script, bindings):
-        print "sending " + script + " to GremlinServer..."
-        return iter([])
+    def apply(self, traversal):
+        if traversal.traversers is None:
+            remote_traversal = self.remote_connection.submit(traversal.bytecode)
+            # traversal.side_effects = remote_traversal.side_effects
+            traversal.traversers = remote_traversal#.traversers
diff --git a/gremlin_python/process/__init__.py b/gremlin_python/process/__init__.py
index e93356e95724d6eaab0892313c6744643294229b..7626550738f12ccd5e18b8c06a8d68aaab882066 100644
--- a/gremlin_python/process/__init__.py
+++ b/gremlin_python/process/__init__.py
@@ -17,22 +17,4 @@ specific language governing permissions and limitations
 under the License.
 '''
 
-from .graph_traversal import GraphTraversal
-from .graph_traversal import GraphTraversalSource
-from .graph_traversal import __
-from .groovy_translator import GroovyTranslator
-from .jython_translator import JythonTranslator
-from .traversal import Barrier
-from .traversal import Bytecode
-from .traversal import Cardinality
-from .traversal import Column
-from .traversal import Direction
-from .traversal import Operator
-from .traversal import Order
-from .traversal import P
-from .traversal import Pop
-from .traversal import Scope
-from .traversal import T
-from .traversal import Traversal
-
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
diff --git a/gremlin_python/process/graph_traversal.py b/gremlin_python/process/graph_traversal.py
index 37f9deb66a251c8d75ab2e316501ff6755f184c9..9010f603076efc69e6ad08950fa7fbda890ed9b6 100644
--- a/gremlin_python/process/graph_traversal.py
+++ b/gremlin_python/process/graph_traversal.py
@@ -16,933 +16,402 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-from .traversal import RawExpression
+import sys
 from .traversal import Traversal
+from .traversal import TraversalStrategies
 from .traversal import Bytecode
-from gremlin_python import statics
+from ..driver.remote_connection import RemoteStrategy
+from .. import statics
 
 class GraphTraversalSource(object):
-  def __init__(self, graph, traversal_strategies, graph_traversal=None, bytecode=Bytecode()):
+  def __init__(self, graph, traversal_strategies, bytecode=None,
+               graph_traversal=None, remote_strategy=None):
     self.graph = graph
     self.traversal_strategies = traversal_strategies
     if graph_traversal is None:
         graph_traversal = GraphTraversal
     self.graph_traversal = graph_traversal
+    if remote_strategy is None:
+        remote_strategy = RemoteStrategy
+    self.remote_strategy = remote_strategy
+    if bytecode is None:
+      bytecode = Bytecode()
     self.bytecode = bytecode
   def __repr__(self):
     return "graphtraversalsource[" + str(self.graph) + "]"
-  def E(self, *args):
-    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
-    traversal.bytecode.add_step("E", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return traversal
-  def V(self, *args):
-    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
-    traversal.bytecode.add_step("V", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return traversal
-  def addV(self, *args):
-    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
-    traversal.bytecode.add_step("addV", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return traversal
-  def inject(self, *args):
-    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
-    traversal.bytecode.add_step("inject", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return traversal
   def withBulk(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
     source.bytecode.add_source("withBulk", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return source
   def withComputer(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
     source.bytecode.add_source("withComputer", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return source
   def withPath(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
     source.bytecode.add_source("withPath", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return source
   def withSack(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
     source.bytecode.add_source("withSack", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return source
   def withSideEffect(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
     source.bytecode.add_source("withSideEffect", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return source
   def withStrategies(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
     source.bytecode.add_source("withStrategies", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return source
-  def withTranslator(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
-    source.bytecode.add_source("withTranslator", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return source
   def withoutStrategies(self, *args):
-    source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
     source.bytecode.add_source("withoutStrategies", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return source
+  def withRemote(self, remote_connection):
+    source = GraphTraversalSource(
+        self.graph, TraversalStrategies(self.traversal_strategies),
+        Bytecode(self.bytecode), self.graph_traversal, self.remote_strategy)
+    source.traversal_strategies.add_strategies([self.remote_strategy(remote_connection)])
+    return source
+  def withBindings(self, bindings):
+    return self
+  def E(self, *args):
+    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    traversal.bytecode.add_step("E", *args)
+    return traversal
+  def V(self, *args):
+    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    traversal.bytecode.add_step("V", *args)
+    return traversal
+  def addV(self, *args):
+    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    traversal.bytecode.add_step("addV", *args)
+    return traversal
+  def inject(self, *args):
+    traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+    traversal.bytecode.add_step("inject", *args)
+    return traversal
 
 
 class GraphTraversal(Traversal):
   def __init__(self, graph, traversal_strategies, bytecode):
     Traversal.__init__(self, graph, traversal_strategies, bytecode)
+  def __getitem__(self, index):
+    if isinstance(index, int):
+        return self.range(index, index + 1)
+    elif isinstance(index, slice):
+        return self.range(0 if index.start is None else index.start, sys.maxint if index.stop is None else index.stop)
+    else:
+        raise TypeError("Index must be int or slice")
+  def __getattr__(self, key):
+    return self.values(key)
   def V(self, *args):
     self.bytecode.add_step("V", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def _and(self, *args):
-    self.bytecode.add_step("_and", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def _as(self, *args):
-    self.bytecode.add_step("_as", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def _from(self, *args):
-    self.bytecode.add_step("_from", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def _in(self, *args):
-    self.bytecode.add_step("_in", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def _is(self, *args):
-    self.bytecode.add_step("_is", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def _not(self, *args):
-    self.bytecode.add_step("_not", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def _or(self, *args):
-    self.bytecode.add_step("_or", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def addE(self, *args):
     self.bytecode.add_step("addE", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def addInE(self, *args):
     self.bytecode.add_step("addInE", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def addOutE(self, *args):
     self.bytecode.add_step("addOutE", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def addV(self, *args):
     self.bytecode.add_step("addV", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def aggregate(self, *args):
     self.bytecode.add_step("aggregate", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def asAdmin(self, *args):
-    self.bytecode.add_step("asAdmin", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
+    return self
+  def and_(self, *args):
+    self.bytecode.add_step("and", *args)
+    return self
+  def as_(self, *args):
+    self.bytecode.add_step("as", *args)
     return self
   def barrier(self, *args):
     self.bytecode.add_step("barrier", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def both(self, *args):
     self.bytecode.add_step("both", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def bothE(self, *args):
     self.bytecode.add_step("bothE", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def bothV(self, *args):
     self.bytecode.add_step("bothV", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def branch(self, *args):
     self.bytecode.add_step("branch", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def by(self, *args):
     self.bytecode.add_step("by", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def cap(self, *args):
     self.bytecode.add_step("cap", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def choose(self, *args):
     self.bytecode.add_step("choose", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def coalesce(self, *args):
     self.bytecode.add_step("coalesce", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def coin(self, *args):
     self.bytecode.add_step("coin", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def constant(self, *args):
     self.bytecode.add_step("constant", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def count(self, *args):
     self.bytecode.add_step("count", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def cyclicPath(self, *args):
     self.bytecode.add_step("cyclicPath", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def dedup(self, *args):
     self.bytecode.add_step("dedup", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def drop(self, *args):
     self.bytecode.add_step("drop", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def emit(self, *args):
     self.bytecode.add_step("emit", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def filter(self, *args):
     self.bytecode.add_step("filter", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def flatMap(self, *args):
     self.bytecode.add_step("flatMap", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def fold(self, *args):
     self.bytecode.add_step("fold", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
+    return self
+  def from_(self, *args):
+    self.bytecode.add_step("from", *args)
     return self
   def group(self, *args):
     self.bytecode.add_step("group", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def groupCount(self, *args):
     self.bytecode.add_step("groupCount", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def groupV3d0(self, *args):
     self.bytecode.add_step("groupV3d0", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def has(self, *args):
     self.bytecode.add_step("has", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def hasId(self, *args):
     self.bytecode.add_step("hasId", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def hasKey(self, *args):
     self.bytecode.add_step("hasKey", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def hasLabel(self, *args):
     self.bytecode.add_step("hasLabel", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def hasNot(self, *args):
     self.bytecode.add_step("hasNot", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def hasValue(self, *args):
     self.bytecode.add_step("hasValue", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def id(self, *args):
     self.bytecode.add_step("id", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def identity(self, *args):
     self.bytecode.add_step("identity", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def inE(self, *args):
     self.bytecode.add_step("inE", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def inV(self, *args):
     self.bytecode.add_step("inV", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
+    return self
+  def in_(self, *args):
+    self.bytecode.add_step("in", *args)
     return self
   def inject(self, *args):
     self.bytecode.add_step("inject", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
-    return self
-  def iterate(self, *args):
-    self.bytecode.add_step("iterate", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
+    return self
+  def is_(self, *args):
+    self.bytecode.add_step("is", *args)
     return self
   def key(self, *args):
     self.bytecode.add_step("key", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def label(self, *args):
     self.bytecode.add_step("label", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def limit(self, *args):
     self.bytecode.add_step("limit", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def local(self, *args):
     self.bytecode.add_step("local", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def loops(self, *args):
     self.bytecode.add_step("loops", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def map(self, *args):
     self.bytecode.add_step("map", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def mapKeys(self, *args):
     self.bytecode.add_step("mapKeys", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def mapValues(self, *args):
     self.bytecode.add_step("mapValues", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def match(self, *args):
     self.bytecode.add_step("match", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def max(self, *args):
     self.bytecode.add_step("max", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def mean(self, *args):
     self.bytecode.add_step("mean", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def min(self, *args):
     self.bytecode.add_step("min", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
+    return self
+  def not_(self, *args):
+    self.bytecode.add_step("not", *args)
     return self
   def option(self, *args):
     self.bytecode.add_step("option", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def optional(self, *args):
     self.bytecode.add_step("optional", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
+    return self
+  def or_(self, *args):
+    self.bytecode.add_step("or", *args)
     return self
   def order(self, *args):
     self.bytecode.add_step("order", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def otherV(self, *args):
     self.bytecode.add_step("otherV", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def out(self, *args):
     self.bytecode.add_step("out", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def outE(self, *args):
     self.bytecode.add_step("outE", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def outV(self, *args):
     self.bytecode.add_step("outV", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def pageRank(self, *args):
     self.bytecode.add_step("pageRank", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def path(self, *args):
     self.bytecode.add_step("path", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def peerPressure(self, *args):
     self.bytecode.add_step("peerPressure", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def profile(self, *args):
     self.bytecode.add_step("profile", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def program(self, *args):
     self.bytecode.add_step("program", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def project(self, *args):
     self.bytecode.add_step("project", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def properties(self, *args):
     self.bytecode.add_step("properties", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def property(self, *args):
     self.bytecode.add_step("property", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def propertyMap(self, *args):
     self.bytecode.add_step("propertyMap", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def range(self, *args):
     self.bytecode.add_step("range", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def repeat(self, *args):
     self.bytecode.add_step("repeat", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def sack(self, *args):
     self.bytecode.add_step("sack", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def sample(self, *args):
     self.bytecode.add_step("sample", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def select(self, *args):
     self.bytecode.add_step("select", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def sideEffect(self, *args):
     self.bytecode.add_step("sideEffect", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def simplePath(self, *args):
     self.bytecode.add_step("simplePath", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def store(self, *args):
     self.bytecode.add_step("store", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def subgraph(self, *args):
     self.bytecode.add_step("subgraph", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def sum(self, *args):
     self.bytecode.add_step("sum", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def tail(self, *args):
     self.bytecode.add_step("tail", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def timeLimit(self, *args):
     self.bytecode.add_step("timeLimit", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def times(self, *args):
     self.bytecode.add_step("times", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def to(self, *args):
     self.bytecode.add_step("to", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def toE(self, *args):
     self.bytecode.add_step("toE", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def toV(self, *args):
     self.bytecode.add_step("toV", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def tree(self, *args):
     self.bytecode.add_step("tree", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def unfold(self, *args):
     self.bytecode.add_step("unfold", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def union(self, *args):
     self.bytecode.add_step("union", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def until(self, *args):
     self.bytecode.add_step("until", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def value(self, *args):
     self.bytecode.add_step("value", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def valueMap(self, *args):
     self.bytecode.add_step("valueMap", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def values(self, *args):
     self.bytecode.add_step("values", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
   def where(self, *args):
     self.bytecode.add_step("where", *args)
-    for arg in args:
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-        self.bindings[arg[0]] = arg[1]
-      elif isinstance(arg, RawExpression):
-        self.bindings.update(arg.bindings)
     return self
 
 
@@ -954,24 +423,6 @@ class __(object):
   def __(*args):
     return GraphTraversal(None, None, Bytecode()).__(*args)
   @staticmethod
-  def _and(*args):
-    return GraphTraversal(None, None, Bytecode())._and(*args)
-  @staticmethod
-  def _as(*args):
-    return GraphTraversal(None, None, Bytecode())._as(*args)
-  @staticmethod
-  def _in(*args):
-    return GraphTraversal(None, None, Bytecode())._in(*args)
-  @staticmethod
-  def _is(*args):
-    return GraphTraversal(None, None, Bytecode())._is(*args)
-  @staticmethod
-  def _not(*args):
-    return GraphTraversal(None, None, Bytecode())._not(*args)
-  @staticmethod
-  def _or(*args):
-    return GraphTraversal(None, None, Bytecode())._or(*args)
-  @staticmethod
   def addE(*args):
     return GraphTraversal(None, None, Bytecode()).addE(*args)
   @staticmethod
@@ -987,6 +438,12 @@ class __(object):
   def aggregate(*args):
     return GraphTraversal(None, None, Bytecode()).aggregate(*args)
   @staticmethod
+  def and_(*args):
+    return GraphTraversal(None, None, Bytecode()).and_(*args)
+  @staticmethod
+  def as_(*args):
+    return GraphTraversal(None, None, Bytecode()).as_(*args)
+  @staticmethod
   def barrier(*args):
     return GraphTraversal(None, None, Bytecode()).barrier(*args)
   @staticmethod
@@ -1080,9 +537,15 @@ class __(object):
   def inV(*args):
     return GraphTraversal(None, None, Bytecode()).inV(*args)
   @staticmethod
+  def in_(*args):
+    return GraphTraversal(None, None, Bytecode()).in_(*args)
+  @staticmethod
   def inject(*args):
     return GraphTraversal(None, None, Bytecode()).inject(*args)
   @staticmethod
+  def is_(*args):
+    return GraphTraversal(None, None, Bytecode()).is_(*args)
+  @staticmethod
   def key(*args):
     return GraphTraversal(None, None, Bytecode()).key(*args)
   @staticmethod
@@ -1119,9 +582,15 @@ class __(object):
   def min(*args):
     return GraphTraversal(None, None, Bytecode()).min(*args)
   @staticmethod
+  def not_(*args):
+    return GraphTraversal(None, None, Bytecode()).not_(*args)
+  @staticmethod
   def optional(*args):
     return GraphTraversal(None, None, Bytecode()).optional(*args)
   @staticmethod
+  def or_(*args):
+    return GraphTraversal(None, None, Bytecode()).or_(*args)
+  @staticmethod
   def order(*args):
     return GraphTraversal(None, None, Bytecode()).order(*args)
   @staticmethod
@@ -1233,36 +702,6 @@ def V(*args):
 
 statics.add_static('V', V)
 
-def _and(*args):
-      return __._and(*args)
-
-statics.add_static('_and', _and)
-
-def _as(*args):
-      return __._as(*args)
-
-statics.add_static('_as', _as)
-
-def _in(*args):
-      return __._in(*args)
-
-statics.add_static('_in', _in)
-
-def _is(*args):
-      return __._is(*args)
-
-statics.add_static('_is', _is)
-
-def _not(*args):
-      return __._not(*args)
-
-statics.add_static('_not', _not)
-
-def _or(*args):
-      return __._or(*args)
-
-statics.add_static('_or', _or)
-
 def addE(*args):
       return __.addE(*args)
 
@@ -1288,6 +727,16 @@ def aggregate(*args):
 
 statics.add_static('aggregate', aggregate)
 
+def and_(*args):
+      return __.and_(*args)
+
+statics.add_static('and_', and_)
+
+def as_(*args):
+      return __.as_(*args)
+
+statics.add_static('as_', as_)
+
 def barrier(*args):
       return __.barrier(*args)
 
@@ -1443,11 +892,21 @@ def inV(*args):
 
 statics.add_static('inV', inV)
 
+def in_(*args):
+      return __.in_(*args)
+
+statics.add_static('in_', in_)
+
 def inject(*args):
       return __.inject(*args)
 
 statics.add_static('inject', inject)
 
+def is_(*args):
+      return __.is_(*args)
+
+statics.add_static('is_', is_)
+
 def key(*args):
       return __.key(*args)
 
@@ -1508,11 +967,21 @@ def min(*args):
 
 statics.add_static('min', min)
 
+def not_(*args):
+      return __.not_(*args)
+
+statics.add_static('not_', not_)
+
 def optional(*args):
       return __.optional(*args)
 
 statics.add_static('optional', optional)
 
+def or_(*args):
+      return __.or_(*args)
+
+statics.add_static('or_', or_)
+
 def order(*args):
       return __.order(*args)
 
diff --git a/gremlin_python/process/jython_translator.py b/gremlin_python/process/jython_translator.py
deleted file mode 100644
index c3169f07c71a0fb0e5a35a33ef2c60bf66e7b5e6..0000000000000000000000000000000000000000
--- a/gremlin_python/process/jython_translator.py
+++ /dev/null
@@ -1,102 +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.
-'''
-
-import inspect
-import sys
-from aenum import Enum
-
-from .traversal import Barrier
-from .traversal import Bytecode
-from .traversal import Cardinality
-from .traversal import Column
-from .traversal import P
-from .traversal import RawExpression
-from .traversal import SymbolHelper
-from .traversal import Translator
-
-if sys.version_info.major > 2:
-    long = int
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-
-class JythonTranslator(Translator):
-    def __init__(self, traversal_source, anonymous_traversal="__", target_language="gremlin-jython"):
-        Translator.__init__(self, traversal_source, anonymous_traversal, target_language)
-
-    def translate(self, bytecode):
-        return self.__internalTranslate(self.traversal_source, bytecode)
-
-    def __internalTranslate(self, start, bytecode):
-        traversal_script = start
-        for instruction in bytecode.source_instructions:
-            traversal_script = traversal_script + "." + SymbolHelper.toJava(
-                instruction[0]) + "(" + self.stringify(*instruction[1]) + ")"
-        for instruction in bytecode.step_instructions:
-            traversal_script = traversal_script + "." + SymbolHelper.toJava(
-                instruction[0]) + "(" + self.stringify(*instruction[1]) + ")"
-        return traversal_script
-
-    def stringOrObject(self, arg):
-        if isinstance(arg, str):
-            return "\"" + arg + "\""
-        elif isinstance(arg, long):
-            return str(arg)
-        elif isinstance(arg, Barrier):
-            return "Barrier" + "." + SymbolHelper.toJava(str(arg.name))
-        elif isinstance(arg, Column):
-            return "Column.valueOf('" + SymbolHelper.toJava(str(arg.name)) + "')"
-        elif isinstance(arg, Cardinality):
-            return "Cardinality" + "." + SymbolHelper.toJava(str(arg.name))
-        elif isinstance(arg, Enum):  # Order, Direction, Scope, T, etc.
-            return SymbolHelper.toJava(type(arg).__name__) + "." + SymbolHelper.toJava(str(arg.name))
-        elif isinstance(arg, P):
-            if arg.other is None:
-                return "P." + SymbolHelper.toJava(arg.operator) + "(" + self.stringOrObject(
-                    arg.value) + ")"
-            else:
-                return self.stringOrObject(arg.other) + "." + SymbolHelper.toJava(
-                    arg.operator) + "(" + self.stringOrObject(arg.value) + ")"
-        elif isinstance(arg, Bytecode):
-            return self.__internalTranslate(self.anonymous_traversal, arg)
-        elif callable(arg):  # lambda that produces a string that is a lambda
-            argLambdaString = arg().strip()
-            argLength = len(inspect.getargspec(eval(argLambdaString)).args)
-            if argLength == 0:
-                return "JythonZeroArgLambda(" + argLambdaString + ")"
-            elif argLength == 1:
-                return "JythonOneArgLambda(" + argLambdaString + ")"
-            elif argLength == 2:
-                return "JythonTwoArgLambda(" + argLambdaString + ")"
-            else:
-                raise
-        elif isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):  # bindings
-            return arg[0]
-        elif isinstance(arg, RawExpression):
-            return "".join(self.stringOrObject(i) for i in arg.parts)
-        else:
-            return str(arg)
-
-    def stringify(self, *args):
-        if len(args) == 0:
-            return ""
-        elif len(args) == 1:
-            return self.stringOrObject(args[0])
-        else:
-            return ", ".join(self.stringOrObject(i) for i in args)
diff --git a/gremlin_python/process/groovy_translator.py b/gremlin_python/process/translator.py
similarity index 60%
rename from gremlin_python/process/groovy_translator.py
rename to gremlin_python/process/translator.py
index 2c2d79a860da80b70bb427df6351793e06c8df45..ac1ebe73cb7e02db5cc00c07927fcbd164a85b63 100644
--- a/gremlin_python/process/groovy_translator.py
+++ b/gremlin_python/process/translator.py
@@ -17,19 +17,68 @@ specific language governing permissions and limitations
 under the License.
 '''
 
-import sys
+# Translate bytecode. Used for backwards compatiblitity
+
+from abc import abstractmethod
 from aenum import Enum
 
-from .traversal import Bytecode
-from .traversal import P
-from .traversal import RawExpression
-from .traversal import SymbolHelper
-from .traversal import Translator
+from gremlin_python.process.traversal import P, Bytecode, Binding
+
+
+class RawExpression(object):
+   def __init__(self, *args):
+      self.bindings = dict()
+      self.parts = [self._process_arg(arg) for arg in args]
+
+   def _process_arg(self, arg):
+      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
+         self.bindings[arg[0]] = arg[1]
+         return Raw(arg[0])
+      else:
+         return Raw(arg)
+
+class Raw(object):
+   def __init__(self, value):
+      self.value = value
+
+   def __str__(self):
+      return str(self.value)
+
+
+TO_JAVA_MAP = {"_global": "global", "_as": "as", "_in": "in", "_and": "and",
+               "_or": "or", "_is": "is", "_not": "not", "_from": "from",
+               "Cardinality": "VertexProperty.Cardinality", "Barrier": "SackFunctions.Barrier"}
 
-if sys.version_info.major > 2:
-    long = int
 
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+class Translator(object):
+    def __init__(self, traversal_source, anonymous_traversal, target_language):
+        self.traversal_source = traversal_source
+        self.anonymous_traversal = anonymous_traversal
+        self.target_language = target_language
+
+    @abstractmethod
+    def translate(self, bytecode):
+        return
+
+    @abstractmethod
+    def __repr__(self):
+        return "translator[" + self.traversal_source + ":" + self.target_language + "]"
+
+
+class SymbolHelper(object):
+    @staticmethod
+    def toJava(symbol):
+        if (symbol in TO_JAVA_MAP):
+            return TO_JAVA_MAP[symbol]
+        else:
+            return symbol
+
+    @staticmethod
+    def mapEnum(enum):
+        if (enum in enumMap):
+            return enumMap[enum]
+        else:
+            return enum
 
 
 class GroovyTranslator(Translator):
@@ -37,16 +86,16 @@ class GroovyTranslator(Translator):
         Translator.__init__(self, traversal_source, anonymous_traversal, target_language)
 
     def translate(self, bytecode):
-        return self.__internalTranslate(self.traversal_source, bytecode)
+        return self._internalTranslate(self.traversal_source, bytecode)
 
-    def __internalTranslate(self, start, bytecode):
+    def _internalTranslate(self, start, bytecode):
         traversal_script = start
         for instruction in bytecode.source_instructions:
             traversal_script = traversal_script + "." + SymbolHelper.toJava(
-                instruction[0]) + "(" + self.stringify(*instruction[1]) + ")"
+                instruction[0]) + "(" + self.stringify(*instruction[1:]) + ")"
         for instruction in bytecode.step_instructions:
             traversal_script = traversal_script + "." + SymbolHelper.toJava(
-                instruction[0]) + "(" + self.stringify(*instruction[1]) + ")"
+                instruction[0]) + "(" + self.stringify(*instruction[1:]) + ")"
         return traversal_script
 
     def stringOrObject(self, arg):
@@ -54,7 +103,7 @@ class GroovyTranslator(Translator):
             return "\"" + arg + "\""
         elif isinstance(arg, bool):
             return str(arg).lower()
-        elif isinstance(arg, long):
+        elif isinstance(arg, int):
             return str(arg) + "L"
         elif isinstance(arg, float):
             return str(arg) + "f"
@@ -67,8 +116,10 @@ class GroovyTranslator(Translator):
             else:
                 return self.stringOrObject(arg.other) + "." + SymbolHelper.toJava(
                     arg.operator) + "(" + self.stringOrObject(arg.value) + ")"
+        elif isinstance(arg, Binding):
+            return arg.key
         elif isinstance(arg, Bytecode):
-            return self.__internalTranslate(self.anonymous_traversal, arg)
+            return self._internalTranslate(self.anonymous_traversal, arg)
         elif callable(arg):  # closures
             lambdaString = arg().strip()
             if lambdaString.startswith("{"):
diff --git a/gremlin_python/process/traversal.py b/gremlin_python/process/traversal.py
index 7558151f79f9ca7d837bc11e0c650c810eb52a19..cbba42d8bfd8d16817cf2ac7ca74658262184cde 100644
--- a/gremlin_python/process/traversal.py
+++ b/gremlin_python/process/traversal.py
@@ -16,53 +16,50 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-from abc import abstractmethod
+import abc
+import six
 from aenum import Enum
-from gremlin_python import statics
+from .. import statics
 
 class Traversal(object):
     def __init__(self, graph, traversal_strategies, bytecode):
         self.graph = graph
         self.traversal_strategies = traversal_strategies
         self.bytecode = bytecode
-        self.results = None
+        self.side_effects = TraversalSideEffects()
+        self.traversers = None
         self.last_traverser = None
-        self.bindings = {}
-
     def __repr__(self):
-        return self.graph.translator.translate(self.bytecode)
-
-    def __getitem__(self, index):
-        if isinstance(index, int):
-            return self.range(index, index + 1)
-        elif isinstance(index, slice):
-            return self.range(index.start, index.stop)
-        else:
-            raise TypeError("Index must be int or slice")
-
-    def __getattr__(self, key):
-        return self.values(key)
-
+        return str(self.bytecode)
     def __iter__(self):
         return self
-
     def __next__(self):
-        if self.results is None:
+        if self.traversers is None:
             self.traversal_strategies.apply_strategies(self)
         if self.last_traverser is None:
-            self.last_traverser = next(self.results)
+            self.last_traverser = next(self.traversers)
         object = self.last_traverser.object
         self.last_traverser.bulk = self.last_traverser.bulk - 1
         if self.last_traverser.bulk <= 0:
             self.last_traverser = None
         return object
-
     def toList(self):
         return list(iter(self))
-
     def toSet(self):
         return set(iter(self))
-
+    def iterate(self):
+        while True:
+            try: self.nextTraverser()
+            except StopIteration: return self
+    def nextTraverser(self):
+        if self.traversers is None:
+            self.traversal_strategies.apply_strategies(self)
+        if self.last_traverser is None:
+            return next(self.traversers)
+        else:
+            temp = self.last_traverser
+            self.last_traverser = None
+            return temp
     def next(self, amount=None):
         if amount is None:
             return self.__next__()
@@ -76,29 +73,25 @@ class Traversal(object):
                 tempList.append(temp)
             return tempList
 
-Barrier = Enum('Barrier', 'normSack')
 
+Barrier = Enum('Barrier', 'normSack')
 statics.add_static('normSack', Barrier.normSack)
 
 Cardinality = Enum('Cardinality', 'list set single')
-
 statics.add_static('single', Cardinality.single)
 statics.add_static('list', Cardinality.list)
 statics.add_static('set', Cardinality.set)
 
 Column = Enum('Column', 'keys values')
-
 statics.add_static('keys', Column.keys)
 statics.add_static('values', Column.values)
 
 Direction = Enum('Direction', 'BOTH IN OUT')
-
 statics.add_static('OUT', Direction.OUT)
 statics.add_static('IN', Direction.IN)
 statics.add_static('BOTH', Direction.BOTH)
 
-Operator = Enum('Operator', 'addAll _and assign div max min minus mult _or sum sumLong')
-
+Operator = Enum('Operator', 'addAll and_ assign div max min minus mult or_ sum sumLong')
 statics.add_static('sum', Operator.sum)
 statics.add_static('minus', Operator.minus)
 statics.add_static('mult', Operator.mult)
@@ -106,13 +99,12 @@ statics.add_static('div', Operator.div)
 statics.add_static('min', Operator.min)
 statics.add_static('max', Operator.max)
 statics.add_static('assign', Operator.assign)
-statics.add_static('_and', Operator._and)
-statics.add_static('_or', Operator._or)
+statics.add_static('and_', Operator.and_)
+statics.add_static('or_', Operator.or_)
 statics.add_static('addAll', Operator.addAll)
 statics.add_static('sumLong', Operator.sumLong)
 
 Order = Enum('Order', 'decr incr keyDecr keyIncr shuffle valueDecr valueIncr')
-
 statics.add_static('incr', Order.incr)
 statics.add_static('decr', Order.decr)
 statics.add_static('keyIncr', Order.keyIncr)
@@ -121,19 +113,16 @@ statics.add_static('keyDecr', Order.keyDecr)
 statics.add_static('valueDecr', Order.valueDecr)
 statics.add_static('shuffle', Order.shuffle)
 
-Pop = Enum('Pop', 'all first last')
-
+Pop = Enum('Pop', 'all_ first last')
 statics.add_static('first', Pop.first)
 statics.add_static('last', Pop.last)
-statics.add_static('all', Pop.all)
+statics.add_static('all_', Pop.all_)
 
-Scope = Enum('Scope', '_global local')
-
-statics.add_static('_global', Scope._global)
+Scope = Enum('Scope', 'global_ local')
+statics.add_static('global_', Scope.global_)
 statics.add_static('local', Scope.local)
 
 T = Enum('T', 'id key label value')
-
 statics.add_static('label', T.label)
 statics.add_static('id', T.id)
 statics.add_static('key', T.key)
@@ -145,9 +134,6 @@ class P(object):
       self.value = value
       self.other = other
    @staticmethod
-   def _not(*args):
-      return P("not", *args)
-   @staticmethod
    def between(*args):
       return P("between", *args)
    @staticmethod
@@ -172,6 +158,9 @@ class P(object):
    def neq(*args):
       return P("neq", *args)
    @staticmethod
+   def not_(*args):
+      return P("not", *args)
+   @staticmethod
    def outside(*args):
       return P("outside", *args)
    @staticmethod
@@ -184,106 +173,94 @@ class P(object):
    def without(*args):
       return P("without", *args)
    def _and(self, arg):
-      return P("_and", arg, self)
+      return P("and", arg, self)
    def _or(self, arg):
-      return P("_or", arg, self)
-
-def _not(*args):
-      return P._not(*args)
-
-statics.add_static('_not',_not)
+      return P("or", arg, self)
+   def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
+   def __repr__(self):
+      return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
 
 def between(*args):
       return P.between(*args)
-
 statics.add_static('between',between)
 
 def eq(*args):
       return P.eq(*args)
-
 statics.add_static('eq',eq)
 
 def gt(*args):
       return P.gt(*args)
-
 statics.add_static('gt',gt)
 
 def gte(*args):
       return P.gte(*args)
-
 statics.add_static('gte',gte)
 
 def inside(*args):
       return P.inside(*args)
-
 statics.add_static('inside',inside)
 
 def lt(*args):
       return P.lt(*args)
-
 statics.add_static('lt',lt)
 
 def lte(*args):
       return P.lte(*args)
-
 statics.add_static('lte',lte)
 
 def neq(*args):
       return P.neq(*args)
-
 statics.add_static('neq',neq)
 
+def not_(*args):
+      return P.not_(*args)
+statics.add_static('not_',not_)
+
 def outside(*args):
       return P.outside(*args)
-
 statics.add_static('outside',outside)
 
 def test(*args):
       return P.test(*args)
-
 statics.add_static('test',test)
 
 def within(*args):
       return P.within(*args)
-
 statics.add_static('within',within)
 
 def without(*args):
       return P.without(*args)
-
 statics.add_static('without',without)
 
 
-class RawExpression(object):
-   def __init__(self, *args):
-      self.bindings = dict()
-      self.parts = [self._process_arg(arg) for arg in args]
-
-   def _process_arg(self, arg):
-      if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-         self.bindings[arg[0]] = arg[1]
-         return Raw(arg[0])
-      else:
-         return Raw(arg)
-
-class Raw(object):
-   def __init__(self, value):
-      self.value = value
-
-   def __str__(self):
-      return str(self.value)
-
 
 '''
 TRAVERSER
 '''
 
 class Traverser(object):
-    def __init__(self, object, bulk):
+    def __init__(self, object, bulk=1):
         self.object = object
         self.bulk = bulk
     def __repr__(self):
         return str(self.object)
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.object == other.object
+
+'''
+TRAVERSAL SIDE-EFFECTS
+'''
+
+class TraversalSideEffects(object):
+    def keys(self):
+        return set()
+    def get(self, key):
+        raise KeyError(key)
+    def __getitem__(self, key):
+        return self.get(key)
+    def __repr__(self):
+        return "sideEffects[size:" + str(len(self.keys())) + "]"
 
 '''
 TRAVERSAL STRATEGIES
@@ -291,87 +268,68 @@ TRAVERSAL STRATEGIES
 
 class TraversalStrategies(object):
     global_cache = {}
-
-    def __init__(self, traversal_strategies):
-        self.traversal_strategies = traversal_strategies
-        return
-
+    def __init__(self, traversal_strategies=None):
+        self.traversal_strategies = traversal_strategies.traversal_strategies if traversal_strategies is not None else []
+    def add_strategies(self, traversal_strategies):
+        self.traversal_strategies = self.traversal_strategies + traversal_strategies
     def apply_strategies(self, traversal):
         for traversal_strategy in self.traversal_strategies:
             traversal_strategy.apply(traversal)
-        return
 
 
+@six.add_metaclass(abc.ABCMeta)
 class TraversalStrategy(object):
-    @abstractmethod
+    @abc.abstractmethod
     def apply(self, traversal):
         return
 
 '''
-BYTECODE AND TRANSLATOR
+BYTECODE
 '''
 
 class Bytecode(object):
     def __init__(self, bytecode=None):
         self.source_instructions = []
         self.step_instructions = []
+        self.bindings = {}
         if bytecode is not None:
             self.source_instructions = list(bytecode.source_instructions)
             self.step_instructions = list(bytecode.step_instructions)
-
     def add_source(self, source_name, *args):
-        newArgs = ()
+        instruction = [source_name]
         for arg in args:
-            newArgs = newArgs + (Bytecode.__convertArgument(arg),)
-        self.source_instructions.append((source_name, newArgs))
-        return
-
+            instruction.append(self._convertArgument(arg))
+        self.source_instructions.append(instruction)
     def add_step(self, step_name, *args):
-        newArgs = ()
+        instruction = [step_name]
         for arg in args:
-            newArgs = newArgs + (Bytecode.__convertArgument(arg),)
-        self.step_instructions.append((step_name, newArgs))
-        return
-
-    @staticmethod
-    def __convertArgument(arg):
+            instruction.append(self._convertArgument(arg))
+        self.step_instructions.append(instruction)
+    def _convertArgument(self,arg):
         if isinstance(arg, Traversal):
+            self.bindings.update(arg.bytecode.bindings)
             return arg.bytecode
+        elif isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
+            self.bindings[arg[0]] = arg[1]
+            return Binding(arg[0],arg[1])
         else:
             return arg
-
-
-TO_JAVA_MAP = {"_global": "global", "_as": "as", "_in": "in", "_and": "and",
-               "_or": "or", "_is": "is", "_not": "not", "_from": "from",
-               "Cardinality": "VertexProperty.Cardinality", "Barrier": "SackFunctions.Barrier"}
-
-
-class Translator(object):
-    def __init__(self, traversal_source, anonymous_traversal, target_language):
-        self.traversal_source = traversal_source
-        self.anonymous_traversal = anonymous_traversal
-        self.target_language = target_language
-
-    @abstractmethod
-    def translate(self, bytecode):
-        return
-
-    @abstractmethod
     def __repr__(self):
-        return "translator[" + self.traversal_source + ":" + self.target_language + "]"
+        return (str(self.source_instructions) if len(self.source_instructions) > 0 else "") + \
+               (str(self.step_instructions) if len(self.step_instructions) > 0 else "")
 
 
-class SymbolHelper(object):
-    @staticmethod
-    def toJava(symbol):
-        if (symbol in TO_JAVA_MAP):
-            return TO_JAVA_MAP[symbol]
-        else:
-            return symbol
+'''
+BINDINGS
+'''
 
-    @staticmethod
-    def mapEnum(enum):
-        if (enum in enumMap):
-            return enumMap[enum]
-        else:
-            return enum
+class Bindings(object):
+    def of(self,key,value):
+        if not isinstance(key, str):
+            raise TypeError("Key must be str")
+        return (key,value)
+
+class Binding(object):
+    def __init__(self,key,value):
+        self.key = key
+        self.value = value
diff --git a/gremlin_python/statics.py b/gremlin_python/statics.py
index 12cbb702c22b2366eaf0679fc32b941f46eba030..293ff93a6200ac7084fea76ffae509d45bc4d6d1 100644
--- a/gremlin_python/statics.py
+++ b/gremlin_python/statics.py
@@ -20,6 +20,7 @@ from aenum import Enum
 
 staticMethods = {}
 staticEnums = {}
+default_lambda_language = "gremlin-python"
 
 
 def add_static(key, value):
diff --git a/gremlin_python/structure/__init__.py b/gremlin_python/structure/__init__.py
index 1c69b5c0e00ef94926514351d5f58116fc30f5c6..7626550738f12ccd5e18b8c06a8d68aaab882066 100644
--- a/gremlin_python/structure/__init__.py
+++ b/gremlin_python/structure/__init__.py
@@ -16,7 +16,5 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-from .graph import Graph
-from .remote_graph import RemoteGraph
 
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
diff --git a/gremlin_python/structure/graph.py b/gremlin_python/structure/graph.py
index 60b22113b57b5ac40156ad0a4adaaeded39b6586..22403b653b715b2b8b3c4b3f113e3c74864d9156 100644
--- a/gremlin_python/structure/graph.py
+++ b/gremlin_python/structure/graph.py
@@ -24,5 +24,67 @@ from gremlin_python.process.traversal import TraversalStrategies
 
 
 class Graph(object):
+    def __init__(self):
+        if self.__class__ not in TraversalStrategies.global_cache:
+            TraversalStrategies.global_cache[self.__class__] = TraversalStrategies()
+
     def traversal(self):
         return GraphTraversalSource(self, TraversalStrategies.global_cache[self.__class__])
+
+    def __repr__(self):
+        return "graph[empty]"
+
+
+class Element(object):
+    def __init__(self, id, label):
+        self.id = id
+        self.label = label
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.id == other.id
+
+    def __hash__(self):
+        return hash(self.id)
+
+
+class Vertex(Element):
+    def __init__(self, id, label="vertex"):
+        Element.__init__(self, id, label)
+
+    def __repr__(self):
+        return "v[" + str(self.id) + "]"
+
+
+class Edge(Element):
+    def __init__(self, id, outV, label, inV):
+        Element.__init__(self, id, label)
+        self.outV = outV
+        self.inV = inV
+
+    def __repr__(self):
+        return "e[" + str(self.id) + "][" + str(self.outV.id) + "-" + self.label + "->" + str(self.inV.id) + "]"
+
+
+class VertexProperty(Element):
+    def __init__(self, id, label, value):
+        Element.__init__(self, id, label)
+        self.value = value
+        self.key = self.label
+
+    def __repr__(self):
+        return "vp[" + str(self.label) + "->" + str(self.value)[0:20] + "]"
+
+
+class Property(object):
+    def __init__(self, key, value):
+        self.key = key
+        self.value = value
+
+    def __repr__(self):
+        return "p[" + str(self.key) + "->" + str(self.value)[0:20] + "]"
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.key == other.key and self.value == other.value
+
+    def __hash__(self):
+        return hash(self.key) + hash(self.value)
diff --git a/gremlin_python/driver/rest_remote_connection.py b/gremlin_python/structure/io/__init__.py
similarity index 51%
rename from gremlin_python/driver/rest_remote_connection.py
rename to gremlin_python/structure/io/__init__.py
index 6d967f8268efeb7749209879d6ae86a5e9bbd1f3..7626550738f12ccd5e18b8c06a8d68aaab882066 100644
--- a/gremlin_python/driver/rest_remote_connection.py
+++ b/gremlin_python/structure/io/__init__.py
@@ -16,28 +16,5 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-import json
-import requests
-
-from gremlin_python.process.traversal import Traverser
-from .remote_connection import RemoteConnection
 
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-
-class RESTRemoteConnection(RemoteConnection):
-    def __init__(self, url):
-        RemoteConnection.__init__(self, url)
-
-    def __repr__(self):
-        return "RESTRemoteConnection[" + self.url + "]"
-
-    def submit(self, target_language, script, bindings):
-        response = requests.post(self.url, data=json.dumps(
-            {"gremlin": script, "language": target_language, "bindings": bindings}))
-        if response.status_code != requests.codes.ok:
-            raise BaseException(response.text)
-        results = []
-        for x in response.json()['result']['data']:
-            results.append(Traverser(x, 1))
-        return iter(results)
diff --git a/gremlin_python/structure/io/graphson.py b/gremlin_python/structure/io/graphson.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed3114554061a772f5396f4e2dad55dbecaccb57
--- /dev/null
+++ b/gremlin_python/structure/io/graphson.py
@@ -0,0 +1,292 @@
+'''
+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 json
+from abc import abstractmethod
+from aenum import Enum
+from types import FunctionType
+
+from gremlin_python import statics
+from gremlin_python.process.traversal import Binding
+from gremlin_python.process.traversal import Bytecode
+from gremlin_python.process.traversal import P
+from gremlin_python.process.traversal import Traversal
+from gremlin_python.process.traversal import Traverser
+from gremlin_python.structure.graph import Edge
+from gremlin_python.structure.graph import Property
+from gremlin_python.structure.graph import Vertex
+from gremlin_python.structure.graph import VertexProperty
+
+
+class long(int): pass
+FloatType = float
+IntType = int
+LongType = long
+
+
+
+class GraphSONWriter(object):
+    @staticmethod
+    def _dictify(object):
+        for key in serializers:
+            if isinstance(object, key):
+                return serializers[key]._dictify(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(objectData):
+        return json.dumps(GraphSONWriter._dictify(objectData), separators=(',', ':'))
+
+
+class GraphSONReader(object):
+    @staticmethod
+    def _objectify(object):
+        if isinstance(object, dict):
+            if _SymbolHelper._TYPE in 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])
+            return newDict
+        elif isinstance(object, list):
+            newList = []
+            for item in object:
+                newList.append(GraphSONReader._objectify(item))
+            return newList
+        else:
+            return object
+
+    @staticmethod
+    def readObject(jsonData):
+        return GraphSONReader._objectify(json.loads(jsonData))
+
+
+'''
+SERIALIZERS
+'''
+
+
+class GraphSONSerializer(object):
+    @abstractmethod
+    def _dictify(self, object):
+        return object
+
+
+class BytecodeSerializer(GraphSONSerializer):
+    def _dictify(self, bytecode):
+        if isinstance(bytecode, Traversal):
+            bytecode = bytecode.bytecode
+        dict = {}
+        sources = []
+        for instruction in bytecode.source_instructions:
+            inst = []
+            inst.append(instruction[0])
+            for arg in instruction[1:]:
+                inst.append(GraphSONWriter._dictify(arg))
+            sources.append(inst)
+        steps = []
+        for instruction in bytecode.step_instructions:
+            inst = []
+            inst.append(instruction[0])
+            for arg in instruction[1:]:
+                inst.append(GraphSONWriter._dictify(arg))
+            steps.append(inst)
+        if len(sources) > 0:
+            dict["source"] = sources
+        if len(steps) > 0:
+            dict["step"] = steps
+        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__),
+                                       _SymbolHelper.toGremlin(str(enum.name)))
+
+
+class PSerializer(GraphSONSerializer):
+    def _dictify(self, p):
+        dict = {}
+        dict["predicate"] = p.operator
+        if p.other is None:
+            dict["value"] = GraphSONWriter._dictify(p.value)
+        else:
+            dict["value"] = [GraphSONWriter._dictify(p.value), GraphSONWriter._dictify(p.other)]
+        return _SymbolHelper.objectify("P", dict)
+
+
+class BindingSerializer(GraphSONSerializer):
+    def _dictify(self, binding):
+        dict = {}
+        dict["key"] = binding.key
+        dict["value"] = GraphSONWriter._dictify(binding.value)
+        return _SymbolHelper.objectify("Binding", dict)
+
+
+class LambdaSerializer(GraphSONSerializer):
+    def _dictify(self, lambdaObject):
+        lambdaResult = lambdaObject()
+        dict = {}
+        script = lambdaResult if isinstance(lambdaResult, str) else lambdaResult[0]
+        language = statics.default_lambda_language if isinstance(lambdaResult, str) else lambdaResult[1]
+        dict["script"] = script
+        dict["language"] = language
+        if language == "gremlin-jython" or language == "gremlin-python":
+            if not script.strip().startswith("lambda"):
+                script = "lambda " + script
+                dict["script"] = script
+            dict["arguments"] = eval(dict["script"]).func_code.co_argcount
+        else:
+            dict["arguments"] = -1
+        return _SymbolHelper.objectify("Lambda", dict)
+
+
+class NumberSerializer(GraphSONSerializer):
+    def _dictify(self, number):
+        if isinstance(number, bool):  # python thinks that 0/1 integers are booleans
+            return number
+        elif isinstance(number, int):
+            return _SymbolHelper.objectify("Int64", number)
+        elif isinstance(number, float):
+            return _SymbolHelper.objectify("Float", number)
+        else:
+            return number
+
+
+'''
+DESERIALIZERS
+'''
+
+
+class GraphSONDeserializer(object):
+    @abstractmethod
+    def _objectify(self, dict):
+        return dict
+
+
+class TraverserDeserializer(GraphSONDeserializer):
+    def _objectify(self, dict):
+        return Traverser(GraphSONReader._objectify(dict[_SymbolHelper._VALUE]["value"]),
+                         GraphSONReader._objectify(dict[_SymbolHelper._VALUE]["bulk"]))
+
+
+class NumberDeserializer(GraphSONDeserializer):
+    def _objectify(self, dict):
+        type = dict[_SymbolHelper._TYPE]
+        value = dict[_SymbolHelper._VALUE]
+        if type == "g:Int32":
+            return int(value)
+        elif type == "g:Int64":
+            return long(value)
+        else:
+            return float(value)
+
+
+class VertexDeserializer(GraphSONDeserializer):
+    def _objectify(self, dict):
+        value = dict[_SymbolHelper._VALUE]
+        return Vertex(GraphSONReader._objectify(value["id"]), value["label"] if "label" in value else "")
+
+
+class EdgeDeserializer(GraphSONDeserializer):
+    def _objectify(self, dict):
+        value = dict[_SymbolHelper._VALUE]
+        return Edge(GraphSONReader._objectify(value["id"]),
+                    Vertex(GraphSONReader._objectify(value["outV"]), ""),
+                    value["label"] if "label" in value else "vertex",
+                    Vertex(GraphSONReader._objectify(value["inV"]), ""))
+
+
+class VertexPropertyDeserializer(GraphSONDeserializer):
+    def _objectify(self, dict):
+        value = dict[_SymbolHelper._VALUE]
+        return VertexProperty(GraphSONReader._objectify(value["id"]), value["label"],
+                              GraphSONReader._objectify(value["value"]))
+
+
+class PropertyDeserializer(GraphSONDeserializer):
+    def _objectify(self, dict):
+        value = dict[_SymbolHelper._VALUE]
+        return Property(value["key"], GraphSONReader._objectify(value["value"]))
+
+
+class _SymbolHelper(object):
+    symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
+                 "or_": "or", "is_": "is", "not_": "not", "from_": "from",
+                 "set_": "set", "list_": "list", "all_": "all"}
+
+    _TYPE = "@type"
+    _VALUE = "@value"
+
+    @staticmethod
+    def toGremlin(symbol):
+        return _SymbolHelper.symbolMap[symbol] if symbol in _SymbolHelper.symbolMap else symbol
+
+    @staticmethod
+    def objectify(type, value, prefix="g"):
+        return {_SymbolHelper._TYPE: prefix + ":" + type, _SymbolHelper._VALUE: value}
+
+
+serializers = {
+    Traversal: BytecodeSerializer(),
+    Traverser: TraverserSerializer(),
+    Bytecode: BytecodeSerializer(),
+    Binding: BindingSerializer(),
+    P: PSerializer(),
+    Enum: EnumSerializer(),
+    FunctionType: LambdaSerializer(),
+    LongType: NumberSerializer(),
+    IntType: NumberSerializer(),
+    FloatType: NumberSerializer()
+}
+
+deserializers = {
+    "g:Traverser": TraverserDeserializer(),
+    "g:Int32": NumberDeserializer(),
+    "g:Int64": NumberDeserializer(),
+    "g:Float": NumberDeserializer(),
+    "g:Double": NumberDeserializer(),
+    "g:Vertex": VertexDeserializer(),
+    "g:Edge": EdgeDeserializer(),
+    "g:VertexProperty": VertexPropertyDeserializer(),
+    "g:Property": PropertyDeserializer()
+}
diff --git a/gremlin_python/structure/remote_graph.py b/gremlin_python/structure/remote_graph.py
deleted file mode 100644
index 778895b24a4438477a328b383bedc900935eae5e..0000000000000000000000000000000000000000
--- a/gremlin_python/structure/remote_graph.py
+++ /dev/null
@@ -1,47 +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)'
-
-from .graph import Graph
-from gremlin_python.process.traversal import TraversalStrategies
-from gremlin_python.process.traversal import TraversalStrategy
-
-
-class RemoteGraph(Graph):
-    def __init__(self, translator, remote_connection):
-        TraversalStrategies.global_cache[self.__class__] = TraversalStrategies([RemoteStrategy()])
-        self.translator = translator
-        self.remote_connection = remote_connection
-
-    def __repr__(self):
-        return "remotegraph[" + self.remote_connection.url + "]"
-
-
-class RemoteStrategy(TraversalStrategy):
-    def apply(self, traversal):
-        if not (traversal.graph.__class__.__name__ == "RemoteGraph"):
-            raise BaseException(
-                "RemoteStrategy can only be used with a RemoteGraph: " + traversal.graph.__class__.__name__)
-        if traversal.results is None:
-            traversal.results = traversal.graph.remote_connection.submit(
-                traversal.graph.translator.target_language,  # script engine
-                traversal.graph.translator.translate(traversal.bytecode),  # script
-                traversal.bindings)  # bindings
-        return
diff --git a/tests/conftest.py b/tests/conftest.py
index 3b5255e1bb5927a7ea13f5c07d928e3be8134925..9468d106aa32532b57e9ab5fbf4f35d06daeff12 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -21,6 +21,11 @@ from goblin.driver import pool, serializer
 from gremlin_python import process
 
 
+def pytest_generate_tests(metafunc):
+    if 'cluster' in metafunc.fixturenames:
+        metafunc.parametrize("cluster", ['c1', 'c2'], indirect=True)
+
+
 class HistoricalName(element.VertexProperty):
     notes = properties.Property(properties.String)
     year = properties.Property(properties.Integer)  # this is dumb but handy
@@ -66,7 +71,9 @@ def unused_server_url(unused_tcp_port):
 @pytest.fixture
 def connection(event_loop):
     conn = event_loop.run_until_complete(
-        driver.Connection.open("http://localhost:8182/gremlin", event_loop))
+        driver.Connection.open(
+            "http://localhost:8182/gremlin", event_loop,
+            message_serializer=serializer.GraphSONMessageSerializer))
     return conn
 
 
@@ -78,23 +85,32 @@ def connection_pool(event_loop):
 
 
 @pytest.fixture
-def cluster(event_loop):
-    return driver.Cluster(event_loop)
+def cluster(request, event_loop):
+    if request.param == 'c1':
+        cluster = driver.Cluster(
+            event_loop,
+            message_serializer=serializer.GraphSONMessageSerializer)
+    elif request.param == 'c2':
+        cluster = driver.Cluster(
+            event_loop,
+            message_serializer=serializer.GraphSON2MessageSerializer)
+    return cluster
 
 
 @pytest.fixture
-def remote_graph(connection):
-     translator = process.GroovyTranslator('g')
-     return driver.AsyncRemoteGraph(translator, connection)
+def remote_graph():
+     return driver.AsyncGraph()
 
 
 @pytest.fixture
 def app(request, event_loop):
     app = event_loop.run_until_complete(
         Goblin.open(event_loop, aliases={'g': 'g'}))
+
     app.register(Person, Place, Knows, LivesIn)
     return app
 
+
 # Instance fixtures
 @pytest.fixture
 def string():
diff --git a/tests/test_app.py b/tests/test_app.py
index d28dd9e66da31340713b668fe633587033b66cc7..89067f1a3dcdab29121562b75350b88ece3cc8d5 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -18,6 +18,7 @@
 import pytest
 
 from goblin import element
+from goblin.driver import serializer
 from gremlin_python import process
 
 
@@ -45,10 +46,6 @@ async def test_transaction_discovery(app):
     assert app._transactions is not None
     await app.close()
 
-@pytest.mark.asyncio
-async def test_translator(app):
-    assert isinstance(app.translator, process.GroovyTranslator)
-    await app.close()
 
 @pytest.mark.asyncio
 async def test_aliases(app):
diff --git a/tests/test_client.py b/tests/test_client.py
index 8077b952f783ad8c2429faebcf95104e9b479c53..889ffe6fad09cb1350544992f7402ddedf08b74a 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -16,8 +16,12 @@
 # along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
 
 import asyncio
+import uuid
+
 import pytest
 
+from goblin.driver.server import GremlinServer
+
 
 @pytest.mark.asyncio
 async def test_client_auto_release(cluster):
@@ -38,3 +42,23 @@ async def test_alias(cluster):
     assert aliased_client._aliases == {"g": "g1"}
     assert aliased_client._cluster is client._cluster
     assert aliased_client._loop is client._loop
+    await cluster.close()
+
+
+@pytest.mark.asyncio
+async def test_sessioned_client(cluster):
+    session = str(uuid.uuid4())
+    client = await cluster.connect(session=session)
+    assert isinstance(client.cluster, GremlinServer)
+    resp = await client.submit(gremlin="v = g.addV('person').property('name', 'joe').next(); v")
+    async for msg in resp:
+        try:
+            assert msg['properties']['name'][0]['value'] == 'joe'
+        except KeyError:
+            assert msg['properties']['name'][0]['@value']['value'] == 'joe'
+
+    resp = await client.submit(gremlin="g.V(v.id).values('name')")
+
+    async for msg in resp:
+        assert msg == 'joe'
+    await cluster.close()
diff --git a/tests/test_config.py b/tests/test_config.py
index b86c3d30cbdcfea53e63bce5e4fa6cf4b6ec314d..72d4bcf4189a5c03e87f25ab43bb6fc543d1ae9c 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -21,6 +21,9 @@ import pytest
 from goblin import driver, exception
 
 
+dirname = os.path.dirname(os.path.dirname(__file__))
+
+
 def test_cluster_default_config(cluster):
     assert cluster.config['scheme'] == 'ws'
     assert cluster.config['hosts'] == ['localhost']
@@ -63,7 +66,6 @@ def test_cluster_custom_config(event_loop, cluster_class):
 
 
 def test_cluster_config_from_json(event_loop, cluster_class):
-    dirname = os.path.dirname(os.path.dirname(__file__))
     cluster = cluster_class(event_loop)
     cluster.config_from_file(dirname + '/tests/config/config.json')
     assert cluster.config['scheme'] == 'wss'
@@ -78,8 +80,8 @@ def test_cluster_config_from_json(event_loop, cluster_class):
     assert issubclass(cluster.config['message_serializer'],
                       driver.GraphSONMessageSerializer)
 
+
 def test_cluster_config_from_yaml(event_loop, cluster_class):
-    dirname = os.path.dirname(os.path.dirname(__file__))
     cluster = cluster_class(event_loop)
     cluster.config_from_file(dirname + '/tests/config/config.yml')
     assert cluster.config['scheme'] == 'wss'
@@ -92,3 +94,35 @@ def test_cluster_config_from_yaml(event_loop, cluster_class):
     assert cluster.config['password'] == ''
     assert issubclass(cluster.config['message_serializer'],
                       driver.GraphSONMessageSerializer)
+
+@pytest.mark.asyncio
+async def test_app_config_from_json(app):
+    app.config_from_file(dirname + '/tests/config/config.json')
+    assert app.config['scheme'] == 'wss'
+    assert app.config['hosts'] == ['localhost']
+    assert app.config['port'] == 8182
+    assert app.config['ssl_certfile'] == ''
+    assert app.config['ssl_keyfile'] == ''
+    assert app.config['ssl_password'] == ''
+    assert app.config['username'] == 'dave'
+    assert app.config['password'] == 'mypass'
+
+    assert issubclass(app.config['message_serializer'],
+                      driver.GraphSONMessageSerializer)
+    await app.close()
+
+
+@pytest.mark.asyncio
+async def test_app_config_from_yaml(app):
+    app.config_from_file(dirname + '/tests/config/config.yml')
+    assert app.config['scheme'] == 'wss'
+    assert app.config['hosts'] == ['localhost']
+    assert app.config['port'] == 8183
+    assert app.config['ssl_certfile'] == ''
+    assert app.config['ssl_keyfile'] == ''
+    assert app.config['ssl_password'] == ''
+    assert app.config['username'] == ''
+    assert app.config['password'] == ''
+    assert issubclass(app.config['message_serializer'],
+                      driver.GraphSONMessageSerializer)
+    await app.close()
diff --git a/tests/test_connection.py b/tests/test_connection.py
index 12b33b546be542a9aa28846eb9653e9be5ad72ce..5ed44f641decd3aa836381796bed489c6ffb7fa1 100644
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -94,7 +94,7 @@ async def test_stream_done(connection):
         assert stream.done
 
 @pytest.mark.asyncio
-async def test_connection(connection):
+async def test_connection_response_timeout(connection):
     async with connection:
         connection._response_timeout = 0.0000001
         with pytest.raises(exception.ResponseTimeoutError):
diff --git a/tests/test_connection_protocol.py b/tests/test_connection_protocol.py
new file mode 100644
index 0000000000000000000000000000000000000000..227cdec02c2580772ca3a5a246b6196ad4491f5d
--- /dev/null
+++ b/tests/test_connection_protocol.py
@@ -0,0 +1,137 @@
+# Copyright 2016 ZEROFAIL
+#
+# This file is part of Goblin.
+#
+# Goblin is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Goblin is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
+
+import asyncio
+import uuid
+import pytest
+
+from goblin import exception
+from goblin.driver import serializer
+
+
+@pytest.mark.asyncio
+async def test_eval(remote_graph, connection):
+    async with connection:
+        connection._message_serializer = serializer.GraphSON2MessageSerializer()
+        g = remote_graph.traversal()
+        traversal = "g.addV('person').property('name', 'leifur')"
+        resp = await connection.submit(
+            processor='', op='eval', gremlin=traversal, scriptEvalTimeout=1)
+
+        async for msg in resp:
+            assert msg['label'] == 'person'
+
+
+@pytest.mark.asyncio
+async def test_bytecode(remote_graph, connection):
+    async with connection:
+        connection._message_serializer = serializer.GraphSON2MessageSerializer()
+        g = remote_graph.traversal()
+        traversal = g.addV('person').property('name', 'leifur')
+        resp = await connection.submit(
+            processor='traversal', op='bytecode', gremlin=traversal.bytecode)
+        async for msg in resp:
+            vid = msg.id
+        traversal = g.V(vid).label()
+        resp = await connection.submit(
+            processor='traversal', op='bytecode', gremlin=traversal.bytecode)
+        async for msg in resp:
+            assert msg == 'person'
+        traversal = g.V(vid).name
+        resp = await connection.submit(
+            processor='traversal', op='bytecode', gremlin=traversal.bytecode)
+        async for msg in resp:
+            assert msg == 'leifur'
+
+
+@pytest.mark.asyncio
+async def test_side_effects(remote_graph, connection):
+    async with connection:
+        connection._message_serializer = serializer.GraphSON2MessageSerializer()
+        g = remote_graph.traversal()
+        # Add some nodes
+        traversal = g.addV('person').property('name', 'leifur')
+        resp = await connection.submit(
+            processor='traversal', op='bytecode', gremlin=traversal.bytecode)
+        async for msg in resp:
+            pass
+        traversal = g.addV('person').property('name', 'dave')
+        resp = await connection.submit(
+            processor='traversal', op='bytecode', gremlin=traversal.bytecode)
+        async for msg in resp:
+            pass
+        traversal = g.addV('person').property('name', 'jonathan')
+        resp = await connection.submit(
+            processor='traversal', op='bytecode', gremlin=traversal.bytecode)
+        async for msg in resp:
+            pass
+
+        # # Make a query
+        traversal = g.V().aggregate('a').aggregate('b')
+        resp = await connection.submit(
+            processor='traversal', op='bytecode', gremlin=traversal.bytecode)
+        request_id = resp.request_id
+        async for msg in resp:
+            pass
+        resp = await connection.submit(processor='traversal', op='keys',
+                                       sideEffect=request_id)
+        keys = []
+        async for msg in resp:
+            keys.append(msg)
+        assert keys == ['a', 'b']
+
+        resp = await connection.submit(processor='traversal', op='gather',
+                                       sideEffect=request_id,
+                                       sideEffectKey='a')
+        side_effects = []
+        async for msg in resp:
+            side_effects.append(msg)
+        assert side_effects
+
+        # Close isn't implmented yet
+        # resp = await connection.submit(processor='traversal', op='close',
+        #                                sideEffect=request_id)
+        # async for msg in resp:
+        #     print(msg)
+
+
+@pytest.mark.asyncio
+async def test_session(connection):
+    async with connection:
+        connection._message_serializer = serializer.GraphSON2MessageSerializer()
+        session = str(uuid.uuid4())
+        resp = await connection.submit(
+            gremlin="v = g.addV('person').property('name', 'unused_name').next(); v",
+            processor='session',
+            op='eval',
+            session=session)
+        async for msg in resp:
+            assert msg['label'] == 'person'
+        resp = await connection.submit(
+            gremlin="v.values('name')",
+            processor='session',
+            op='eval',
+            session=session)
+        async for msg in resp:
+            assert msg == 'unused_name'
+        # Close isnt' implemented yet
+        # resp = await connection.submit(
+        #     processor='session',
+        #     op='close',
+        #     session=session)
+        # async for msg in resp:
+        #     print(msg)
diff --git a/tests/test_graph.py b/tests/test_graph.py
index c538f3a30927bc4c6c2f112356bfa92f576ef19d..c4a9ec7f71df191045641217ced28904475602a1 100644
--- a/tests/test_graph.py
+++ b/tests/test_graph.py
@@ -17,42 +17,64 @@
 
 import pytest
 
-from gremlin_python import process
-
-
-@pytest.mark.asyncio
-async def test_close_graph(remote_graph):
-    remote_connection = remote_graph.remote_connection
-    await remote_graph.close()
-    assert remote_connection.closed
-
+from goblin.driver import serializer
 
-@pytest.mark.asyncio
-async def test_conn_context_manager(remote_graph):
-    remote_connection = remote_graph.remote_connection
-    async with remote_graph:
-        assert not remote_graph.remote_connection.closed
-    assert remote_connection.closed
+from gremlin_python import process
 
 
 @pytest.mark.asyncio
-async def test_generate_traversal(remote_graph):
-    async with remote_graph:
-        traversal = remote_graph.traversal().V().hasLabel(('v1', 'person'))
-        assert isinstance(traversal, process.GraphTraversal)
-        assert traversal.bindings['v1'] == 'person'
+async def test_generate_traversal(remote_graph, connection):
+    async with connection:
+        g = remote_graph.traversal().withRemote(connection)
+        traversal = g.V().hasLabel(('v1', 'person'))
+        assert isinstance(traversal, process.graph_traversal.GraphTraversal)
+        assert traversal.bytecode.bindings['v1'] == 'person'
 
 
 @pytest.mark.asyncio
-async def test_submit_traversal(remote_graph):
-    async with remote_graph:
-        g = remote_graph.traversal()
-        resp = await g.addV('person').property('name', 'leifur').next()
-        leif = await resp.fetch_data()
-        resp.close()
+async def test_submit_traversal(remote_graph, connection):
+    async with connection:
+        g = remote_graph.traversal().withRemote(connection)
+        resp = g.addV('person').property('name', 'leifur')
+        leif = await resp.next()
+        resp.traversers.close()
         assert leif['properties']['name'][0]['value'] == 'leifur'
         assert leif['label'] == 'person'
-        resp = await g.V(leif['id']).drop().next()
-        none = await resp.fetch_data()
-        resp.close()
+        resp = g.V(leif['id']).drop()
+        none = await resp.next()
         assert none is None
+
+
+@pytest.mark.asyncio
+async def test_side_effects(remote_graph, connection):
+    async with connection:
+        connection._message_serializer = serializer.GraphSON2MessageSerializer()
+        g = remote_graph.traversal().withRemote(connection)
+        # create some nodes
+        resp = g.addV('person').property('name', 'leifur')
+        leif = await resp.next()
+        resp.traversers.close()
+        resp = g.addV('person').property('name', 'dave')
+        dave = await resp.next()
+        resp.traversers.close()
+        resp = g.addV('person').property('name', 'jon')
+        jonthan = await resp.next()
+        resp.traversers.close()
+        traversal = g.V().aggregate('a').aggregate('b')
+        async for msg in traversal:
+            pass
+        keys = []
+        resp = await traversal.side_effects.keys()
+        async for msg in resp:
+            keys.append(msg)
+        assert keys == ['a', 'b']
+        side_effects = []
+        resp = await traversal.side_effects.get('a')
+        async for msg in resp:
+            side_effects.append(msg)
+        assert side_effects
+        side_effects = []
+        resp = await traversal.side_effects.get('b')
+        async for msg in resp:
+            side_effects.append(msg)
+        assert side_effects
diff --git a/tests/test_session.py b/tests/test_session.py
index 25dc2886854cc809005abf65970c71c0a9a300c9..59b2eeb55dbeda15e32ad545427565c8999d19e6 100644
--- a/tests/test_session.py
+++ b/tests/test_session.py
@@ -20,7 +20,15 @@
 import pytest
 
 from goblin import element
-from goblin.traversal import bindprop
+from goblin.session import bindprop
+from gremlin_python.process.translator import GroovyTranslator
+
+
+def test_bindprop(person_class):
+    db_val, (binding, val) = bindprop(person_class, 'name', 'dave', binding='n1')
+    assert db_val == 'name'
+    assert binding == 'n1'
+    assert val == 'dave'
 
 
 class TestCreationApi:
@@ -149,14 +157,14 @@ class TestCreationApi:
         person.name = 'dave'
         person.age = 35
         await session.save(person)
-        result = await session.g.V(person.id).one_or_none()
+        result = await session.g.V(person.id).oneOrNone()
         assert result is person
         rid = result.id
         await session.remove_vertex(person)
-        result = await session.g.V(rid).one_or_none()
+        result = await session.g.V(rid).oneOrNone()
         assert not result
         await app.close()
-
+#
     @pytest.mark.asyncio
     async def test_remove_edge(self, app, person_class, place_class,
                                lives_in_class):
@@ -169,11 +177,11 @@ class TestCreationApi:
         lives_in = lives_in_class(jon, montreal)
         session.add(jon, montreal, lives_in)
         await session.flush()
-        result = await session.g.E(lives_in.id).one_or_none()
+        result = await session.g.E(lives_in.id).oneOrNone()
         assert result is lives_in
         rid = result.id
         await session.remove_edge(lives_in)
-        result = await session.g.E(rid).one_or_none()
+        result = await session.g.E(rid).oneOrNone()
         assert not result
         await app.close()
 
@@ -219,9 +227,10 @@ class TestTraversalApi:
                                                knows_class):
         session = await app.session()
         traversal = session.traversal(person_class)
-        assert repr(traversal) == 'g.V().hasLabel("person")'
+        translator = GroovyTranslator('g')
+        assert translator.translate(traversal.bytecode) == 'g.V().hasLabel("person")'
         traversal = session.traversal(knows_class)
-        assert repr(traversal) == 'g.E().hasLabel("knows")'
+        assert translator.translate(traversal.bytecode) == 'g.E().hasLabel("knows")'
         await app.close()
 
 
@@ -233,7 +242,7 @@ class TestTraversalApi:
         jon = person_class()
         session.add(dave, leif, jon)
         await session.flush()
-        resp = await session.traversal(person_class).all()
+        resp = session.traversal(person_class)
         results = []
         async for msg in resp:
             assert isinstance(msg, person_class)
@@ -242,14 +251,14 @@ class TestTraversalApi:
         await app.close()
 
     @pytest.mark.asyncio
-    async def test_one_or_none_one(self, app, person_class):
+    async def test_oneOrNone_one(self, app, person_class):
         session = await app.session()
         dave = person_class()
         leif = person_class()
         jon = person_class()
         session.add(dave, leif, jon)
         await session.flush()
-        resp = await session.traversal(person_class).one_or_none()
+        resp = await session.traversal(person_class).oneOrNone()
         assert isinstance(resp, person_class)
         await app.close()
 
@@ -261,14 +270,14 @@ class TestTraversalApi:
         result1 = await session.save(itziri)
         bound_name = bindprop(person_class, 'name', 'itziri', binding='v1')
         p1 = await session.traversal(person_class).has(
-        *bound_name).one_or_none()
+        *bound_name).oneOrNone()
         await app.close()
 
     @pytest.mark.asyncio
-    async def test_one_or_none_none(self, app):
+    async def test_oneOrNone_none(self, app):
         session = await app.session()
         none = await session.g.V().hasLabel(
-            'a very unlikey label').one_or_none()
+            'a very unlikey label').oneOrNone()
         assert not none
         await app.close()
 
@@ -276,7 +285,7 @@ class TestTraversalApi:
     async def test_vertex_deserialization(self, app, person_class):
         session = await app.session()
         resp = await session.g.addV('person').property(
-            person_class.name, 'leif').property('place_of_birth', 'detroit').one_or_none()
+            person_class.name, 'leif').property('place_of_birth', 'detroit').oneOrNone()
         assert isinstance(resp, person_class)
         assert resp.name == 'leif'
         assert resp.place_of_birth == 'detroit'
@@ -285,12 +294,12 @@ class TestTraversalApi:
     @pytest.mark.asyncio
     async def test_edge_desialization(self, app, knows_class):
         session = await app.session()
-        p1 = await session.g.addV('person').one_or_none()
-        p2 = await session.g.addV('person').one_or_none()
+        p1 = await session.g.addV('person').oneOrNone()
+        p2 = await session.g.addV('person').oneOrNone()
         e1 = await session.g.V(p1.id).addE('knows').to(
         session.g.V(p2.id)).property(
             knows_class.notes, 'somehow').property(
-            'how_long', 1).one_or_none()
+            'how_long', 1).oneOrNone()
         assert isinstance(e1, knows_class)
         assert e1.notes == 'somehow'
         assert e1.how_long == 1
@@ -300,7 +309,7 @@ class TestTraversalApi:
     async def test_unregistered_vertex_deserialization(self, app):
         session = await app.session()
         dave = await session.g.addV(
-            'unregistered').property('name', 'dave').one_or_none()
+            'unregistered').property('name', 'dave').oneOrNone()
         assert isinstance(dave, element.GenericVertex)
         assert dave.name == 'dave'
         assert dave.__label__ == 'unregistered'
@@ -309,10 +318,10 @@ class TestTraversalApi:
     @pytest.mark.asyncio
     async def test_unregistered_edge_desialization(self, app):
         session = await app.session()
-        p1 = await session.g.addV('person').one_or_none()
-        p2 = await session.g.addV('person').one_or_none()
+        p1 = await session.g.addV('person').oneOrNone()
+        p2 = await session.g.addV('person').oneOrNone()
         e1 = await session.g.V(p1.id).addE('unregistered').to(
-        session.g.V(p2.id)).property('how_long', 1).one_or_none()
+        session.g.V(p2.id)).property('how_long', 1).oneOrNone()
         assert isinstance(e1, element.GenericEdge)
         assert e1.how_long == 1
         assert e1.__label__ == 'unregistered'
@@ -322,8 +331,8 @@ class TestTraversalApi:
     async def test_property_deserialization(self, app):
         session = await app.session()
         p1 = await session.g.addV('person').property(
-        'name', 'leif').one_or_none()
-        name = await session.g.V(p1.id).properties('name').one_or_none()
+        'name', 'leif').oneOrNone()
+        name = await session.g.V(p1.id).properties('name').oneOrNone()
         assert name['value'] == 'leif'
         assert name['label'] == 'name'
         await app.close()
@@ -332,7 +341,7 @@ class TestTraversalApi:
     async def test_non_element_deserialization(self, app):
         session = await app.session()
         p1 = await session.g.addV('person').property(
-        'name', 'leif').one_or_none()
-        one = await session.g.V(p1.id).count().one_or_none()
+        'name', 'leif').oneOrNone()
+        one = await session.g.V(p1.id).count().oneOrNone()
         assert one == 1
         await app.close()
diff --git a/tests/test_traversal.py b/tests/test_traversal.py
deleted file mode 100644
index 999821c264c3ffda6585bd5a77dcc43a64388b99..0000000000000000000000000000000000000000
--- a/tests/test_traversal.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2016 ZEROFAIL
-#
-# This file is part of Goblin.
-#
-# Goblin is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Goblin is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
-
-from goblin.traversal import bindprop
-
-
-def test_bindprop(person_class):
-    db_val, (binding, val) = bindprop(person_class, 'name', 'dave', binding='n1')
-    assert db_val == 'name'
-    assert binding == 'n1'
-    assert val == 'dave'
diff --git a/tests/test_vertex_properties_functional.py b/tests/test_vertex_properties_functional.py
index 703d085fe769ea3f81ab03f8bd9a2133f8f5c0e9..ae9c9997ca3bacfc40268b5df930dc9fade5de9d 100644
--- a/tests/test_vertex_properties_functional.py
+++ b/tests/test_vertex_properties_functional.py
@@ -1,3 +1,20 @@
+# Copyright 2016 ZEROFAIL
+#
+# This file is part of Goblin.
+#
+# Goblin is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Goblin is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Goblin.  If not, see <http://www.gnu.org/licenses/>.
+
 import pytest