diff --git a/LICENSE b/LICENSE
index 896fe276618ec00739abe3ee570fd069f267f451..589b3f2e856196abb86a6642856688b7c349f03c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,22 +1,13 @@
-The MIT License (MIT)
+Copyright [2017] [David M. Brown]
 
-Copyright (c) 2015 David Michael Brown
+Licensed 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
 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+    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.
diff --git a/README.md b/README.md
index 3b24f867bb30688bf94e848dc0436cda72d644bc..cd603cdb00c8b697d916c22d40458c0ffd279a4e 100644
--- a/README.md
+++ b/README.md
@@ -1,87 +1,38 @@
-# aiogremin is no longer maintained. Please use Goblin: https://github.com/ZEROFAIL/goblin
+# [aiogremlin 3.2.4](https://pypi.python.org/pypi/aiogremlin/3.2.4)
 
+[Official Documentation](http://aiogremlin.readthedocs.org/en/latest/)
 
-# [aiogremlin 0.1.3](https://pypi.python.org/pypi/aiogremlin/0.0.11)
+`aiogremlin` is a port of the official `Gremlin-Python` designed for integration with
+event loop based asynchronous Python networking libraries, including `asyncio`,
+`aiohttp`, `tornado`, and `curio`. It uses the `async/await` syntax introduced
+in PEP 492, and is therefore Python 3.5+ only.
 
-## [Official Documentation](http://aiogremlin.readthedocs.org/en/latest/)
+`aiogremlin` tries to follow `Gremlin-Python` as closely as possible both in terms
+of API and implementation. It is regularly rebased against the official Apache Git
+repository, and will be released according to the TinkerPop release schedule.
 
-`aiogremlin` is a **Python 3** driver for the the [Tinkerpop 3 Gremlin Server](http://tinkerpop.incubator.apache.org/docs/3.0.0.M9-incubating/#gremlin-server). This module is built on [Asyncio](https://docs.python.org/3/library/asyncio.html) and [aiohttp](http://aiohttp.readthedocs.org/en/v0.15.3/index.html) `aiogremlin` is currently in **alpha** mode, but all major functionality has test coverage.
-
-
-## Getting started
-
-Since Python 3.4 is not the default version on many systems, it's nice to create a virtualenv that uses Python 3.4 by default. Then use pip to install `aiogremlin`. Using virtualenvwrapper on Ubuntu 14.04:
-
-```bash
-$ mkvirtualenv -p /usr/bin/python3.4 aiogremlin
-$ pip install aiogremlin
-```
-
-Fire up the Gremlin Server:
-
-```bash
-$ ./bin/gremlin-server.sh
-```
-
-The `GremlinClient` communicates asynchronously with the Gremlin Server using websockets. The majority of `GremlinClient` methods are an `asyncio.coroutine`, so you will also need to use `asyncio`:
-
-```python
->>> import asyncio
->>> from aiogremlin import GremlinClient
-```
-
-The Gremlin Server responds with messages in chunks, `GremlinClient.submit` submits a script to the server, and returns a `GremlinResponse` object. This object provides the methods: `get` and the property `stream`. `get` collects all of the response messages and returns them as a Python list. `stream` returns an object of the type `GremlinResponseStream` that implements a method `read`. This allows you to read the response without loading all of the messages into memory.
-
-Note that the GremlinClient constructor and the create_client function take [keyword only arguments](https://www.python.org/dev/peps/pep-3102/) only!
+Note that this *NOT* an official Apache project component, it is a
+*THIRD PARTY PACKAGE!*
 
+## Getting Started
 
 ```python
->>> loop = asyncio.get_event_loop()
->>> gc = GremlinClient(url='ws://localhost:8182/', loop=loop)  # Default url
+import asyncio
+from aiogremlin import DriverRemoteConnection, Graph
 
-# Use get.
->>> @asyncio.coroutine
-... def get(gc):
-...     resp = yield from gc.submit("x + x", bindings={"x": 4})
-...     result = yield from resp.get()
-...     return result
 
->>> result = loop.run_until_complete(get(gc))
->>> result
-[Message(status_code=200, data=[8], message={}, metadata='')]
+loop = asyncio.get_event_loop()
 
->>> resp = result[0]
->>> resp.status_code
-200
 
->>> resp  # Named tuple.
-Message(status_code=200, data=[8], message={}, metadata='')
+async def go(loop):
+  remote_connection = await DriverRemoteConnection.open(
+    'ws://localhost:8182/gremlin', 'g')
+  g = Graph().traversal().withRemote(remote_connection)
+  vertices = await g.V().toList()
+  return vertices
 
-# Use stream.
->>> @asyncio.coroutine
-... def stream(gc):
-...     resp = yield from gc.submit("x + x", bindings={"x": 1})
-...     while True:
-...         result = yield from resp.stream.read()
-...         if result is None:
-...             break
-...         print(result)
->>> loop.run_until_complete(stream(gc))
-Message(status_code=200, data=[2], message={}, metadata='')
 
->>> loop.run_until_complete(gc.close())  # Explicitly close client!!!
->>> loop.close()
-```
-
-For convenience, `aiogremlin` also provides a method `execute`, which is equivalent to calling  `yield from submit()` and then `yield from get()` in the same coroutine.
-
-```python
->>> loop = asyncio.get_event_loop()
->>> gc = GremlinClient(loop=loop)
->>> execute = gc.execute("x + x", bindings={"x": 4})
->>> result = loop.run_until_complete(execute)
->>> result
-[Message(status_code=200, data=[8], message={}, metadata='')]
->>> loop.run_until_complete(gc.close())  # Explicitly close client!!!
->>> loop.close()
+vertices = loop.run_until_complete(go(loop))
+print(vertices)
+# [v[1], v[2], v[3], v[4], v[5], v[6]]
 ```
diff --git a/README.txt b/README.txt
index 1dd4b7c303908d36550cdc7e365d6851c26b53ac..4f9bc024541295da0db2ecaaa2933c6577530b66 100644
--- a/README.txt
+++ b/README.txt
@@ -1,8 +1,6 @@
-=========================================================
-aiogremlin - Async Python 3 driver for TP3 Gremlin Server
-=========================================================
-
-**alpha**
+=====================================================
+aiogremlin - Async Python 3.5+ port of Gremlin-Python
+=====================================================
 
 
 `Official Documentation`_
diff --git a/aiogremlin/__init__.py b/aiogremlin/__init__.py
index 48332a24203b242857bc873f758473eb601176ce..1c6df920bfa85a5a202192a931d73b8ddc7d2988 100644
--- a/aiogremlin/__init__.py
+++ b/aiogremlin/__init__.py
@@ -1,9 +1,5 @@
 from aiogremlin.driver.cluster import Cluster
 from aiogremlin.remote.driver_remote_connection import DriverRemoteConnection
-from aiogremlin.gremlin_python import statics
-from aiogremlin.gremlin_python.process import strategies
-from aiogremlin.gremlin_python.process.graph_traversal import __
-from aiogremlin.gremlin_python.process.traversal import Binding
 from aiogremlin.gremlin_python.structure.graph import Graph
 
 __version__ = "3.2.4"
diff --git a/aiogremlin/driver/client.py b/aiogremlin/driver/client.py
index 6bd597fe16108b4bac1bdbbda392b2b0716f6ead..2759d68649b0864dd729b1fbdd4006257bd7e792 100644
--- a/aiogremlin/driver/client.py
+++ b/aiogremlin/driver/client.py
@@ -14,33 +14,29 @@ class Client:
     :param aiogremlin.cluster.Cluster cluster: Cluster used by
         client
     :param asyncio.BaseEventLoop loop:
+    :param dict aliases: Optional mapping for aliases. Default is `None`
     """
-    def __init__(self, cluster, loop, *, aliases=None, processor=None,
-                 op=None):
+    def __init__(self, cluster, loop, *, aliases=None):
         self._cluster = cluster
         self._loop = loop
         if aliases is None:
             aliases = {}
         self._aliases = aliases
-        if processor is None:
-            processor = ''
-        self._processor = processor
-        if op is None:
-            op = 'eval'
-        self._op = op
 
     @property
     def aliases(self):
+        """Read-only property"""
         return self._aliases
 
     @property
     def message_serializer(self):
+        """Read-only property"""
         return self.cluster.config['message_serializer']
 
     @property
     def cluster(self):
         """
-        Readonly property.
+        Read-only property.
 
         :returns: The instance of
             :py:class:`Cluster<aiogremlin.driver.cluster.Cluster>` associated with
@@ -60,6 +56,11 @@ class Client:
         """
         **coroutine** Submit a script and bindings to the Gremlin Server.
 
+        :param message: Can be an instance of
+            `Message<aiogremlin.gremlin_python.request.RequestMessage>` or
+            `Bytecode<aiogremlin.gremlin_python.process.traversal.Bytecode>`
+            or a `str` representing a raw Gremlin script
+        :param dict bindings: Optional bindings used with raw Grelmin
         :returns: :py:class:`ResultSet<aiogremlin.driver.resultset.ResultSet>`
             object
         """
diff --git a/aiogremlin/driver/cluster.py b/aiogremlin/driver/cluster.py
index abaa8af7c6d639ca257feecdac29a02c430f357d..6cc403fb81d0243c1da49a0a6362c4dd125e0b50 100644
--- a/aiogremlin/driver/cluster.py
+++ b/aiogremlin/driver/cluster.py
@@ -35,6 +35,8 @@ class Cluster:
     level interface used by the :py:mod:`aiogremlin` module.
 
     :param asyncio.BaseEventLoop loop:
+    :param dict aliases: Optional mapping for aliases. Default is `None`
+    :param config: Optional cluster configuration passed as kwargs or `dict`
     """
 
     DEFAULT_CONFIG = {
@@ -73,8 +75,10 @@ class Cluster:
         specified in configuration.
 
         :param asyncio.BaseEventLoop loop:
+        :param dict aliases: Optional mapping for aliases. Default is `None`
         :param str configfile: Optional configuration file in .json or
             .yml format
+        :param config: Optional cluster configuration passed as kwargs or `dict`
         """
         cluster = cls(loop, aliases=aliases, **config)
         if configfile:
@@ -84,12 +88,13 @@ class Cluster:
 
     @property
     def hosts(self):
+        """Read-only property"""
         return self._hosts
 
     @property
     def config(self):
         """
-        Readonly property.
+        Read-only property.
 
         :returns: `dict` containing the cluster configuration
         """
@@ -100,7 +105,7 @@ class Cluster:
         **coroutine** Get connection from next available host in a round robin
         fashion.
 
-        :returns: :py:class:`Connection<aiogremlin.connection.Connection>`
+        :returns: :py:class:`Connection<aiogremlin.driver.connection.Connection>`
         """
         if not self._hosts:
             await self.establish_hosts()
@@ -136,6 +141,11 @@ class Cluster:
             raise exception.ConfigurationError('Unknown config file format')
 
     def config_from_yaml(self, filename):
+        """
+        Load configuration from from YAML file.
+
+        :param str filename: Path to the configuration file.
+        """
         with open(filename, 'r') as f:
             config = yaml.load(f)
         config = self._process_config_imports(config)
@@ -162,6 +172,11 @@ class Cluster:
         return config
 
     def config_from_module(self, module):
+        """
+        Load configuration from Python module.
+
+        :param str filename: Path to the configuration file.
+        """
         if isinstance(module, str):
             module = importlib.import_module(module)
         config = dict()
@@ -175,7 +190,8 @@ class Cluster:
         """
         **coroutine** Get a connected client. Main API method.
 
-        :returns: A connected instance of `Client<aiogremlin.client.Client>`
+        :returns: A connected instance of
+            `Client<aiogremlin.driver.client.Client>`
         """
         aliases = aliases or self._aliases
         if not self._hosts:
diff --git a/aiogremlin/driver/connection.py b/aiogremlin/driver/connection.py
index ceab16ea6d54f24dab5fd1d8ec585b4bf2423a6c..4ca67c2c3b988217c46604c1d2187d2634bfa726 100644
--- a/aiogremlin/driver/connection.py
+++ b/aiogremlin/driver/connection.py
@@ -28,15 +28,16 @@ class Connection:
     :py:meth:`Connection.open<aiogremlin.connection.Connection.open>`.
 
     :param str url: url for host Gremlin Server
-    :param aiohttp.ClientWebSocketResponse ws: open websocket connection
+    :param aiogremlin.gremlin_python.driver.transport.AbstractBaseTransport transport:
+        Transport implementation
+    :param aiogremlin.gremlin_python.driver.protocol.AbstractBaseProtocol protocol:
+        Protocol implementation
     :param asyncio.BaseEventLoop loop:
-    :param aiohttp.ClientSession: Client session used to establish websocket
-        connections
-    :param float response_timeout: (optional) `None` by default
     :param str username: Username for database auth
     :param str password: Password for database auth
     :param int max_inflight: Maximum number of unprocessed requests at any
         one time on the connection
+    :param float response_timeout: (optional) `None` by default
     """
     def __init__(self, url, transport, protocol, loop, username, password,
                  max_inflight, response_timeout, message_serializer, provider):
@@ -73,6 +74,9 @@ class Connection:
 
         :param str url: url for host Gremlin Server
         :param asyncio.BaseEventLoop loop:
+        :param aiogremlin.gremlin_python.driver.protocol.AbstractBaseProtocol protocol:
+            Protocol implementation
+        :param func transport_factory: Factory function for transports
         :param ssl.SSLContext ssl_context:
         :param str username: Username for database auth
         :param str password: Password for database auth
@@ -80,6 +84,8 @@ class Connection:
         :param int max_inflight: Maximum number of unprocessed requests at any
             one time on the connection
         :param float response_timeout: (optional) `None` by default
+        :param message_serializer: Message serializer implementation
+        :param provider: Graph provider object implementation
 
         :returns: :py:class:`Connection<aiogremlin.connection.Connection>`
         """
@@ -100,7 +106,7 @@ class Connection:
     @property
     def closed(self):
         """
-        Check if connection has been closed.
+        Read-only property. Check if connection has been closed.
 
         :returns: `bool`
         """
@@ -119,10 +125,7 @@ class Connection:
         """
         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.
+        :param `RequestMessage<aiogremlin.gremlin_python.driver.request.RequestMessage>` message:
         :returns: :py:class:`ResultSet<aiogremlin.driver.resultset.ResultSet>`
             object
         """
@@ -163,4 +166,4 @@ class Connection:
 
     async def __aexit__(self, exc_type, exc, tb):
         await self.close()
-        self._conn = None
+        self._transport = None
diff --git a/aiogremlin/driver/protocol.py b/aiogremlin/driver/protocol.py
index 03d189c127f9a8cc068cab98f98c9e0d61513e41..f82e28834e374c30232248af310e3a1f54cd895b 100644
--- a/aiogremlin/driver/protocol.py
+++ b/aiogremlin/driver/protocol.py
@@ -24,7 +24,7 @@ Message = collections.namedtuple(
 
 
 class GremlinServerWSProtocol(protocol.AbstractBaseProtocol):
-
+    """Implemenation of the Gremlin Server Websocket protocol"""
     def __init__(self, message_serializer, username='', password=''):
         if isinstance(message_serializer, type):
             message_serializer = message_serializer()
diff --git a/aiogremlin/driver/resultset.py b/aiogremlin/driver/resultset.py
index a53765d28f3682e6e9b3d97bf84a5925357e28b5..e759bac9280c137795c544b6bd56f1c4450bd11e 100644
--- a/aiogremlin/driver/resultset.py
+++ b/aiogremlin/driver/resultset.py
@@ -12,6 +12,7 @@ def error_handler(fn):
             if msg.status_code not in [200, 206]:
                 self.close()
                 raise exception.GremlinServerError(
+                    msg.status_code,
                     "{0}: {1}".format(msg.status_code, msg.message))
             msg = msg.data
         return msg
@@ -38,7 +39,7 @@ class ResultSet:
 
     def queue_result(self, result):
         if result is None:
-            self.done.set()
+            self.close()
         self._response_queue.put_nowait(result)
 
     @property
@@ -68,10 +69,8 @@ class ResultSet:
         return msg
 
     def close(self):
-        """Close response stream by setting done flag to true."""
         self.done.set()
         self._loop = None
-        self._response_queue = None
 
     @error_handler
     async def one(self):
@@ -79,7 +78,6 @@ class ResultSet:
         if not self._response_queue.empty():
             msg = self._response_queue.get_nowait()
         elif self.done.is_set():
-            self.close()
             msg = None
         else:
             try:
diff --git a/aiogremlin/exception.py b/aiogremlin/exception.py
index 51f0ea5967de894e2e8fd6e64c936d37cd6bf17b..13d3718590632d71cfe0db54802056feddf9ce9d 100644
--- a/aiogremlin/exception.py
+++ b/aiogremlin/exception.py
@@ -23,7 +23,11 @@ class ConfigurationError(Exception):
 
 
 class GremlinServerError(Exception):
-    pass
+
+    def __init__(self, status_code, msg):
+        super().__init__(msg)
+        self.status_code = status_code
+        self.msg = msg
 
 
 class ResponseTimeoutError(Exception):
diff --git a/aiogremlin/gremlin_python/__init__.py b/aiogremlin/gremlin_python/__init__.py
index 7626550738f12ccd5e18b8c06a8d68aaab882066..41aee8bc82bf4bb98ed95c3c6982612273e92e68 100644
--- a/aiogremlin/gremlin_python/__init__.py
+++ b/aiogremlin/gremlin_python/__init__.py
@@ -16,5 +16,10 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 '''
-
+'''THIS FILE HAS BEEN MODIFIED BY DAVID M. BROWN TO SUPPORT PEP 492'''
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+
+from aiogremlin.gremlin_python.statics import *
+from aiogremlin.gremlin_python.process.graph_traversal import __
+from aiogremlin.gremlin_python.process.strategies import *
+from aiogremlin.gremlin_python.process.traversal import Binding
diff --git a/aiogremlin/gremlin_python/process/traversal.py b/aiogremlin/gremlin_python/process/traversal.py
index 6e3290fa68ebe5035de29144726e492c6bc1d2e9..b0e98f4e53f2be47db38642253d3807af136e5b9 100644
--- a/aiogremlin/gremlin_python/process/traversal.py
+++ b/aiogremlin/gremlin_python/process/traversal.py
@@ -75,19 +75,19 @@ class Traversal(object):
             self.last_traverser = None
             return temp
     async def next(self, amount=None):
-        if amount is None:
-            return await self.__anext__()
-        else:
-            count = 0
-            tempList = []
-            while count < amount:
-                count = count + 1
-                try:
-                    temp = await self.__anext__()
-                except StopAsyncIteration:
-                    return tempList
-                tempList.append(temp)
-            return tempList
+        if not amount:
+            try:
+                return await self.__anext__()
+            except StopAsyncIteration:
+                return
+        results = []
+        for i in range(amount):
+            try:
+                result = await self.__anext__()
+            except StopAsyncIteration:
+                return results
+            results.append(result)
+        return results
 
 
 Barrier = Enum('Barrier', 'normSack')
diff --git a/aiogremlin/remote/driver_remote_connection.py b/aiogremlin/remote/driver_remote_connection.py
index 60531b4bbf42d38dfc4d8138e59bfbea4ac6b41e..4532da2b6386c44aa4600e9035fbe9e514ca3ca8 100644
--- a/aiogremlin/remote/driver_remote_connection.py
+++ b/aiogremlin/remote/driver_remote_connection.py
@@ -11,6 +11,15 @@ __author__ = 'David M. Brown (davebshow@gmail.com)'
 
 
 class DriverRemoteConnection:
+    """
+    Remote connection to a Gremlin Server. Do not instantiate directly,
+    instead use :py:meth:`DriverRemoteConnection.open` or
+    :py:meth:`DriverRemoteConnection.using`
+
+    :param aiogremlin.driver.client.Client client:
+    :param asyncio.BaseEventLoop loop:
+    :param aiogremlin.driver.cluster.Cluster cluster:
+    """
 
     def __init__(self, client, loop, *, cluster=None):
         self._client = client
@@ -26,15 +35,32 @@ class DriverRemoteConnection:
         return self._cluster.config
 
     @classmethod
-    async def using(cls, cluster, aliases=None, *, loop=None):
+    async def using(cls, cluster, aliases=None):
+        """
+        Create a :py:class:`DriverRemoteConnection` using a specific
+        :py:class:`Cluster<aiogremlin.driver.cluster.Cluster>`
+
+        :param aiogremlin.driver.cluster.Cluster cluster:
+        :param dict aliases: Optional mapping for aliases. Default is `None`.
+            Also accepts `str` argument which will be assigned to `g`
+        """
         client = await cluster.connect(aliases=aliases)
-        if not loop:
-            loop = asyncio.get_event_loop()
+        loop = cluster._loop
         return cls(client, loop)
 
     @classmethod
     async def open(cls, url=None, aliases=None, loop=None, *,
                    graphson_reader=None, graphson_writer=None, **config):
+        """
+        :param str url: Optional url for host Gremlin Server
+
+        :param dict aliases: Optional mapping for aliases. Default is `None`.
+            Also accepts `str` argument which will be assigned to `g`
+        :param asyncio.BaseEventLoop loop:
+        :param graphson_reader: Custom graphson_reader
+        :param graphson_writer: Custom graphson_writer
+        :param config: Optional cluster configuration passed as kwargs or `dict`
+        """
         if url:
             parsed_url = urlparse(url)
             config.update({
@@ -54,11 +80,24 @@ class DriverRemoteConnection:
         return cls(client, loop, cluster=cluster)
 
     async def close(self):
+        """
+        Close underlying cluster if applicable. If created with
+        :py:meth:`DriverRemoteConnection.using`, cluster is NOT closed.
+        """
         if self._cluster:
             await self._cluster.close()
 
     async def submit(self, bytecode):
+        """Submit bytecode to the Gremlin Server"""
         result_set = await self._client.submit(bytecode)
         side_effects = RemoteTraversalSideEffects(result_set.request_id,
                                                   self._client)
         return RemoteTraversal(result_set, side_effects)
+
+    async def __aenter__(self):
+        return self
+
+    async def __aexit__(self, exc_type, exc, tb):
+        await self.close()
+        self._client = None
+        self._cluster = None
diff --git a/aiogremlin/remote/driver_remote_side_effects.py b/aiogremlin/remote/driver_remote_side_effects.py
index 9dc59c7c82e7603f11a15a748e90268ac833eb14..d888b47c4efaacad28f34d66900ea724b625a0ed 100644
--- a/aiogremlin/remote/driver_remote_side_effects.py
+++ b/aiogremlin/remote/driver_remote_side_effects.py
@@ -18,6 +18,7 @@ class RemoteTraversalSideEffects(traversal.TraversalSideEffects):
         return await self.get(key)
 
     async def keys(self):
+        """Get side effect keys associated with Traversal"""
         if not self._closed:
             message = request.RequestMessage(
                 'traversal', 'keys',
@@ -29,6 +30,7 @@ class RemoteTraversalSideEffects(traversal.TraversalSideEffects):
         return self._keys
 
     async def get(self, key):
+        """Get side effects associated with a specific key"""
         if not self._side_effects.get(key):
             if not self._closed:
                 results = await self._get(key)
@@ -47,6 +49,7 @@ class RemoteTraversalSideEffects(traversal.TraversalSideEffects):
         return await self._aggregate_results(result_set)
 
     async def close(self):
+        """Release side effects"""
         if not self._closed:
             message = request.RequestMessage(
                 'traversal', 'close',
diff --git a/changes.txt b/changes.txt
deleted file mode 100644
index d7b4cbae6a3c25c0da7210e8d98c2f17fa3781ff..0000000000000000000000000000000000000000
--- a/changes.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-0.0.1 - 4/2015: Birth!
-0.0.2 - 5/1/2015: Added an init_pool method and a create_client constructor.
-0.0.3 - 5/2/2015: Using ujson for serialization.
-0.0.4 - 5/12/2015: Added support for sessions.
-0.0.5 - 5/13/2015: Using EofStream terminator technique to prepare for 3.0.0.M9
-0.0.7 - 5/20/2015: Full integration with aiohttp. Added Session object for HTTP
-                   connection pooling. Added a context manager.
-0.0.8 - 5/20/2015: Fixed bug in client constructor logic. Tested different client
-                   connection handling techniques.
diff --git a/docs/aiogremlin.driver.aiohttp.rst b/docs/aiogremlin.driver.aiohttp.rst
new file mode 100644
index 0000000000000000000000000000000000000000..99302423e404ec1dc68dd9705265ce085eae1750
--- /dev/null
+++ b/docs/aiogremlin.driver.aiohttp.rst
@@ -0,0 +1,13 @@
+aiogremlin.driver.aiohttp package
+=================================
+
+Submodules
+----------
+
+aiogremlin.driver.aiohttp.transport module
+------------------------------------------
+
+.. automodule:: aiogremlin.driver.aiohttp.transport
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.driver.rst b/docs/aiogremlin.driver.rst
new file mode 100644
index 0000000000000000000000000000000000000000..cba702eb424315532952a9a7a74a0a4a641e9159
--- /dev/null
+++ b/docs/aiogremlin.driver.rst
@@ -0,0 +1,76 @@
+aiogremlin.driver package
+=========================
+
+Subpackages
+-----------
+
+.. toctree::
+
+    aiogremlin.driver.aiohttp
+
+Submodules
+----------
+
+aiogremlin.driver.client module
+-------------------------------
+
+.. automodule:: aiogremlin.driver.client
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.driver.cluster module
+--------------------------------
+
+.. automodule:: aiogremlin.driver.cluster
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.driver.connection module
+-----------------------------------
+
+.. automodule:: aiogremlin.driver.connection
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.driver.pool module
+-----------------------------
+
+.. automodule:: aiogremlin.driver.pool
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.driver.protocol module
+---------------------------------
+
+.. automodule:: aiogremlin.driver.protocol
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.driver.provider module
+---------------------------------
+
+.. automodule:: aiogremlin.driver.provider
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.driver.resultset module
+----------------------------------
+
+.. automodule:: aiogremlin.driver.resultset
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.driver.server module
+-------------------------------
+
+.. automodule:: aiogremlin.driver.server
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.gremlin_python.driver.rst b/docs/aiogremlin.gremlin_python.driver.rst
new file mode 100644
index 0000000000000000000000000000000000000000..2eb5595197fe0cd4f613f7b6a1aad82e4376498c
--- /dev/null
+++ b/docs/aiogremlin.gremlin_python.driver.rst
@@ -0,0 +1,45 @@
+aiogremlin.gremlin_python.driver package
+========================================
+
+Submodules
+----------
+
+aiogremlin.gremlin_python.driver.protocol module
+------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.driver.protocol
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.gremlin_python.driver.remote_connection module
+---------------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.driver.remote_connection
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.gremlin_python.driver.request module
+-----------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.driver.request
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.gremlin_python.driver.serializer module
+--------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.driver.serializer
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.gremlin_python.driver.transport module
+-------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.driver.transport
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.gremlin_python.process.rst b/docs/aiogremlin.gremlin_python.process.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7cc2fdd25d9c33475cd8b58485c37ff50f69a5e9
--- /dev/null
+++ b/docs/aiogremlin.gremlin_python.process.rst
@@ -0,0 +1,29 @@
+aiogremlin.gremlin_python.process package
+=========================================
+
+Submodules
+----------
+
+aiogremlin.gremlin_python.process.graph_traversal module
+--------------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.process.graph_traversal
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.gremlin_python.process.strategies module
+---------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.process.strategies
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.gremlin_python.process.traversal module
+--------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.process.traversal
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.gremlin_python.rst b/docs/aiogremlin.gremlin_python.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7921453e676f4b7728102ffa085eadf77cccef70
--- /dev/null
+++ b/docs/aiogremlin.gremlin_python.rst
@@ -0,0 +1,22 @@
+aiogremlin.gremlin_python package
+=================================
+
+Subpackages
+-----------
+
+.. toctree::
+
+    aiogremlin.gremlin_python.driver
+    aiogremlin.gremlin_python.process
+    aiogremlin.gremlin_python.structure
+
+Submodules
+----------
+
+aiogremlin.gremlin_python.statics module
+----------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.statics
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.gremlin_python.structure.io.rst b/docs/aiogremlin.gremlin_python.structure.io.rst
new file mode 100644
index 0000000000000000000000000000000000000000..547f898395aca2155da2361056a8ffb74333c9da
--- /dev/null
+++ b/docs/aiogremlin.gremlin_python.structure.io.rst
@@ -0,0 +1,13 @@
+aiogremlin.gremlin_python.structure.io package
+==============================================
+
+Submodules
+----------
+
+aiogremlin.gremlin_python.structure.io.graphson module
+------------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.structure.io.graphson
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.gremlin_python.structure.rst b/docs/aiogremlin.gremlin_python.structure.rst
new file mode 100644
index 0000000000000000000000000000000000000000..3c12f02a101076205bc235bea5c1599981525dc0
--- /dev/null
+++ b/docs/aiogremlin.gremlin_python.structure.rst
@@ -0,0 +1,20 @@
+aiogremlin.gremlin_python.structure package
+===========================================
+
+Subpackages
+-----------
+
+.. toctree::
+
+    aiogremlin.gremlin_python.structure.io
+
+Submodules
+----------
+
+aiogremlin.gremlin_python.structure.graph module
+------------------------------------------------
+
+.. automodule:: aiogremlin.gremlin_python.structure.graph
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.remote.rst b/docs/aiogremlin.remote.rst
new file mode 100644
index 0000000000000000000000000000000000000000..45cd42f3f51f1f3114f4d4d59ab3130684fdf0ee
--- /dev/null
+++ b/docs/aiogremlin.remote.rst
@@ -0,0 +1,21 @@
+aiogremlin.remote package
+=========================
+
+Submodules
+----------
+
+aiogremlin.remote.driver_remote_connection module
+-------------------------------------------------
+
+.. automodule:: aiogremlin.remote.driver_remote_connection
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+aiogremlin.remote.driver_remote_side_effects module
+---------------------------------------------------
+
+.. automodule:: aiogremlin.remote.driver_remote_side_effects
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/aiogremlin.rst b/docs/aiogremlin.rst
index 193331c0067869925f82f4042a456745c72f50b4..e61427b2092f8d4438592a975f96c5a49df4f62c 100644
--- a/docs/aiogremlin.rst
+++ b/docs/aiogremlin.rst
@@ -1,56 +1,22 @@
-.. _aiogremlin-client-reference:
-
-Client Reference
-================
-
 aiogremlin package
--------------------------
+==================
 
-.. automodule:: aiogremlin
-    :members:
-    :undoc-members:
-    :show-inheritance:
+Subpackages
+-----------
 
-aiogremlin.client module
-------------------------
+.. toctree::
 
-.. automodule:: aiogremlin.client
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-aiogremlin.connector module
----------------------------
+    aiogremlin.driver
+    aiogremlin.gremlin_python
+    aiogremlin.remote
 
-This module is based on :py:class:`aiohttp.client.ClientSession` and
-:py:class:`aiohttp.connector.BaseConnector`.
+Submodules
+----------
 
-.. automodule:: aiogremlin.connector
-    :members:
-    :undoc-members:
-    :show-inheritance:
-    :inherited-members:
-
-aiogremlin.exceptions module
-----------------------------
-
-.. automodule:: aiogremlin.exceptions
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-aiogremlin.response module
---------------------------
-
-.. automodule:: aiogremlin.response
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-aiogremlin.subprotocol module
------------------------------
+aiogremlin.exception module
+---------------------------
 
-.. automodule:: aiogremlin.subprotocol
+.. automodule:: aiogremlin.exception
     :members:
     :undoc-members:
     :show-inheritance:
diff --git a/docs/index.rst b/docs/index.rst
index 7de713419e272bca278bf8c826367bf9ae07b5fe..a4f20be14fd0930310f91bdad8ccfb7a82e72b37 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -7,32 +7,35 @@
 aiogremlin
 ==========
 
-aiogremlin is no longer maintained!!! Please use Goblin: http://goblin.readthedocs.io/en/latest/index.html
-:py:mod:`aiogremlin` is an asynchronous client for the `TinkerPop 3 Gremlin Server`_
-based on the `asyncio`_ and `aiohttp`_ libraries.
+`aiogremlin` is a port of the official `Gremlin-Python` designed for integration with
+event loop based asynchronous Python networking libraries, including `asyncio`_,
+`aiohttp`_, and `tornado`_. It uses the `async/await` syntax introduced
+in `PEP 492`_, and is therefore Python 3.5+ only.
+
+`aiogremlin` tries to follow `Gremlin-Python` as closely as possible both in terms
+of API and implementation. It is regularly rebased against the official Apache Git
+repository, and will be released according to the `TinkerPop`_ release schedule.
+
+Note that this *NOT* an official Apache project component, it is a
+*THIRD PARTY PACKAGE!*
 
 Releases
 ========
-The latest release of :py:mod:`aiogremlin` is **0.1.3**.
+The latest release of :py:mod:`aiogremlin` is **3.2.4**.
 
 
 Requirements
 ============
 
-- Python 3.4
-- TinkerPop 3 Gremlin Server 3.1.0
+- Python 3.5+
+- TinkerPop 3.2.4
 
-Using Python 2? Checkout `gremlinrestclient`_.
 
 Dependencies
 ============
-- aiohttp 0.18.4
-- aiowebsocketclient 0.0.4
+- aiohttp 1.3.3
+- PyYAML 3.12
 
-To speed up serialization, you can also install `ujson`_. If not available,
-aiogremlin will use the Python standard library :any:`json<json>` module.
-
-- ujson 1.33
 
 
 Installation
@@ -46,35 +49,37 @@ Getting Started
 ===============
 
 :py:mod:`aiogremlin` has a simple API that is quite easy to use. However, as it relies
-heavily on `asyncio`_ and `aiohttp`_, it is helpful to be familar with the
-basics of these modules. If you're not, maybe check out the :py:mod:`asyncio`
-documentation relating to the :ref:`event loop<asyncio-event-loop>` and the
-concept of the :ref:`coroutine<coroutine>`. Also, I would recommend the
-documentation relating to :py:mod:`aiohttp`'s
-:ref:`websocket client<aiohttp-client-websockets>` and
-:ref:`HTTP client<aiohttp-client-reference>` implementations.
+heavily on `asyncio`_ and `aiohttp`_, it is helpful to be familiar with the
+basics of these modules.
+
+:py:mod:`aiogremlin` is *very* similar to Gremlin-Python, except it is all async, all the time.
 
 Minimal Example
 ---------------
 Submit a script to the Gremlin Server::
 
     >>> import asyncio
-    >>> import aiogremlin
-    >>> @asyncio.coroutine
-    ... def go():
-    ...     resp = yield from aiogremlin.submit("1 + 1")
-    ...     return (yield from resp.get())
+    >>> from aiogremlin import DriverRemoteConnection, Graph
+
     >>> loop = asyncio.get_event_loop()
-    >>> results = loop.run_until_complete(go())
+
+    >>> async def go(loop):
+    ...    remote_connection = await DriverRemoteConnection.open(
+    ...        'ws://localhost:8182/gremlin', 'g')
+    ...    g = Graph().traversal().withRemote(remote_connection)
+    ...    vertices = await g.V().toList()
+    ...    return vertices
+
+    >>> results = loop.run_until_complete(go(loop))
     >>> results
-    [Message(status_code=200, data=[2], message={}, metadata='')]
+    # [v[1], v[2], v[3], v[4], v[5], v[6]]
 
 
 The above example demonstrates how :py:mod:`aiogremlin` uses the
 :ref:`event loop<asyncio-event-loop>` to drive communication with the Gremlin
 Server, but the **rest of examples are written as if they were run in a Python
 interpreter**. In reality, **this isn't possible**, so remember, code *must*
-be wrapped in functions and run with the :ref:`event loop<asyncio-event-loop>`.
+be wrapped in a coroutine and run with the :ref:`event loop<asyncio-event-loop>`.
 
 Contribute
 ----------
@@ -103,9 +108,9 @@ Indices and tables
 * :ref:`modindex`
 * :ref:`search`
 
-.. _Tinkerpop 3 Gremlin Server: http://tinkerpop.incubator.apache.org/
+.. _TinkerPop: http://tinkerpop.apache.org/
 .. _`asyncio`: https://docs.python.org/3/library/asyncio.html
 .. _`aiohttp`: http://aiohttp.readthedocs.org/en/latest/
-.. _`ujson`: https://pypi.python.org/pypi/ujson
+.. _`Tornado`: http://www.tornadoweb.org/en/stable/
+.. _`PEP 492`: https://www.python.org/dev/peps/pep-0492/
 .. _Github: https://github.com/davebshow/aiogremlin/issues
-.. _`gremlinrestclient`: http://gremlinrestclient.readthedocs.org/en/latest/
diff --git a/docs/modules.rst b/docs/modules.rst
index ef0aa53dcfaa1d1db9bd7f1d0fb48b5f272ec968..eb1551773da58a1b8d912fda687f3448fdba18bf 100644
--- a/docs/modules.rst
+++ b/docs/modules.rst
@@ -1,7 +1,7 @@
-API
-===
+aiogremlin API
+==============
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 4
 
    aiogremlin
diff --git a/docs/usage.rst b/docs/usage.rst
index 28a3e65bf015ba364c54136aa202132e23da89a4..086b23231a90b14ed7903f2c11f8c0b3b4fcf12c 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -1,252 +1,200 @@
-Using aiogremlin
-================
+Using :py:mod:`aiogremlin`
+==========================
 
-Before you get started, make sure you have the `Gremlin Server`_ up and running.
-All of the following example assume a running Gremlin Server version 3.0.0 at
-'ws://localhost:8182/'.
+Before you get started, make sure you have the Gremlin Server up and running.
+All of the following example assume a running Gremlin Server version 3.2.4 at
+`ws://localhost:8182/gremlin` using the `conf/gremlin-server-modern-py.yaml`
+configuration::
 
+    $ ./bin/gremlin-server.sh conf/gremlin-server-modern-py.yaml
 
-Submitting a script with :py:func:`submit`
-------------------------------------------
 
+Using the Gremlin Language Variant
+----------------------------------
 
-The simplest way to interact with the Gremlin Server is by using the
-:py:func:`aiogremlin.client.submit` function::
+:py:mod:`aiogremlin` is used almost exactly like the official Gremlin-Python,
+except that all operations are asynchronous. Thus when coding with :py:mod:`aiogremlin`
+coroutines and the `async/await` syntax are used in combination with an `asyncio` compatible
+event loop implementation (`tornado`, `ZeroMQ`, `uvloop`, etc.).
 
-    >>> resp = yield from aiogremlin.submit("x + x", bindings={"x": 2})
+The following examples assume that you are already familiar with `asyncio`, coroutines,
+and the event loop. For readability, they strip away these details
+to focus on the syntax used by :py:mod:`aiogremlin`.
 
-This returns an instance of :py:class:`aiogremlin.client.GremlinResponse`. This
-class provides the interface used to read the underlying response stream. The
-easiest way to read the stream is using the
-:py:meth:`aiogremlin.client.GremlinResponse.get`::
+To create a traversal source, simply use
+:py:class:`DriverRemoteConnection<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection>`
+combined with :py:class:`Graph<aiogremlin.gremlin_python.structure.graph.Graph>`::
 
-    >>> results = yield from resp.get()
+    >>> remote_connection = await DriverRemoteConnection.open(
+    ...    'ws://localhost:8182/gremlin', 'g')
+    >>>  g = Graph().traversal().withRemote(remote_connection)
 
-However, if you are expecting a huge result set from the server, you may want to
-read the chunked responses one at a time::
+In :py:mod:`aiogremlin`, a
+:py:class:`Traversal<aiogremlin.gremlin_python.process.traversal.Traversal>`
+implements the Asynchronous Iterator Protocol as defined
+by PEP 492::
 
-    >>> results = []
-    >>> while True:
-    ...     msg = yield from resp.stream.read():
-    ...     if msg is None:
-    ...         break
-    ...     results.append(msg)
+    >>> async for vertex in g.V():
+    ...     print(vertex)
 
+Furthermore, it implements several convience methods - :py:meth:`toList`,
+:py:meth:`toSet`, and :py:meth:`next`::
 
-.. function:: submit(gremlin, *, url='ws://localhost:8182/', bindings=None,
-                     lang="gremlin-groovy", rebindings=None, op="eval",
-                     processor="", timeout=None, session=None, loop=None):
+    >>> vertex_list = await g.V().toList()
+    >>> vertex_set = await g.V().toSet()
+    >>> next_vertex = await g.V().next() # returns next result from the stream
 
-    :ref:`coroutine<coroutine>`
+:py:class:`Traversal<aiogremlin.gremlin_python.process.traversal.Traversal>`
+also contains a reference to a
+:py:class:`RemoteTraversalSideEffects<aiogremlin.remote.driver_remote_side_effects.RemoteTraversalSideEffects>`
+object that can be used to fetch side effects cached by the server (when applicable)::
 
-    Submit a script to the Gremlin Server.
+    >>> t = g.V().aggregate('a')
+    >>> await t.iterate()  # evaluate the traversal
+    >>> keys = await t.side_effects.keys()
+    >>> se = await t.side_effects.get('a')
+    >>> await t.side_effects.close()
 
-    :param str gremlin: Gremlin script to submit to server.
+Don't forget to close the
+:py:class:`DriverRemoteConnection<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection>`
+when finished::
 
-    :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
-        by default
+    >>> await remote_connection.close()
 
-    :param dict bindings: A mapping of bindings for Gremlin script.
 
-    :param str lang: Language of scripts submitted to the server.
-        "gremlin-groovy" by default
+Using :py:class:`DriverRemoteConnection<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection>`
+-----------------------------------------------------------------------------------------------------------
 
-    :param dict rebindings: Rebind ``Graph`` and ``TraversalSource``
-        objects to different variable names in the current request
+The
+:py:class:`DriverRemoteConnection<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection>`
+object allows you to configure you database connection in one of two ways:
 
-    :param str op: Gremlin Server op argument. "eval" by default.
+1. Passing configuration values as kwargs or a :py:class:`dict` to the classmethod
+:py:meth:`open<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection.open>`::
 
-    :param str processor: Gremlin Server processor argument. "" by default.
-
-    :param float timeout: timeout for websocket read (seconds)(optional).
-        Values ``0`` or ``None`` mean no timeout
-
-    :param str session: Session id (optional). Typically a uuid
-
-    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
-        `asyncio.get_event_loop` is used for getting default event loop
-        (optional)
-
-    :param float conn_timeout: timeout for establishing connection (seconds)
-        (optional). Values ``0`` or ``None`` mean no timeout
-
-    :param username: Username for SASL auth
-
-    :param password: Password for SASL auth
-
-    :returns: :py:class:`aiogremlin.client.GremlinResponse` object
-
-
-Reusing sockets with :py:class:`GremlinClient`
-----------------------------------------------
-
-To avoid the overhead of repeatedly establishing websocket connections,
-``aiogremlin`` provides the class :py:class:`aiogremlin.client.GremlinClient`.
-This class uses pooling to reuse websocket connections, and facilitates
-concurrent message passing by yielding new websocket connections as needed::
-
-    >>> client = aiogremlin.GremlinClient()
-    >>> resp = client.submit("x + x", bindings={"x": 2})
-
-For convenience, :py:class:`GremlinClient` provides the method
-:py:meth:`aiogremlin.client.GremlinClient.execute`. This is equivalent of calling,
-:py:meth:`GremlinClient.submit` and then :py:meth:`GremlinResponse.get`.
-Therefore::
-
-    >>> results = client.execute("x + x", bindings={"x": 2})
-
-Is equivalent to::
-
-    >>> resp = yield from aiogremlin.submit("x + x", bindings={"x": 2})
-    >>> results = yield from resp.get()
-
-:py:class:`GremlinClient` encapsulates :py:class:`aiogremlin.connector.GremlinConnector`.
-This class produces the websocket connections used by the client, and handles all
-of the connection pooling. It can also handle pools for multiple servers. To do
-so, you can share a :py:class:`GremlinConnector` amongst various client that
-point to different endpoints::
-
-    >>> connector = aiogremlin.GremlinConnector()
-    >>> client1 = aiogremlin.GremlinClient(url=url='ws://localhost:8182/'
-    ...                                    ws_connector=connector)
-    >>> client2 = aiogremlin.GremlinClient(url=url='ws://localhost:8080/'
-    ...                                    ws_connector=connector)
-
-
-Remember, when you are done you must explicitly close the :py:class:`GremlinClient`
-using the coroutinemethod :py:meth:`close`::
-
-    >>> yield from client.close()
-
-
-.. class:: GremlinClient(self, *, url='ws://localhost:8182/', loop=None,
-                         lang="gremlin-groovy", op="eval", processor="",
-                         timeout=None, ws_connector=None)
-
-    Main interface for interacting with the Gremlin Server.
-
-    :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
-        by default
-
-    :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``,
-        `asyncio.get_event_loop` is used for getting default event loop
-        (optional)
-
-    :param str lang: Language of scripts submitted to the server.
-        "gremlin-groovy" by default
-
-    :param str op: Gremlin Server op argument. "eval" by default
-
-    :param str processor: Gremlin Server processor argument. "" by default
-
-    :param float timeout: timeout for establishing connection (optional).
-        Values ``0`` or ``None`` mean no timeout
-
-    :param ws_connector: A class that implements the method :py:meth:`ws_connect`.
-        Usually an instance of :py:class:`aiogremlin.connector.GremlinConnector`
-
-.. method:: close()
-
-   :ref:`coroutine<coroutine>` method
-
-   Close client. If client has not been detached from underlying
-   ws_connector, this coroutinemethod closes the latter as well.
-
-.. method:: detach()
-
-   Detach client from ws_connector. Client status is switched to closed.
-
-.. method:: submit(gremlin, *, bindings=None, lang=None, rebindings=None,
-                   op=None, processor=None, binary=True, session=None,
-                   timeout=None)
-
-   :ref:`coroutine<coroutine>` method
-
-   Submit a script to the Gremlin Server.
-
-   :param str gremlin: Gremlin script to submit to server.
-
-   :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
-                   by default
-
-   :param dict bindings: A mapping of bindings for Gremlin script.
-
-   :param str lang: Language of scripts submitted to the server.
-                    "gremlin-groovy" by default
-
-   :param dict rebindings: Rebind ``Graph`` and ``TraversalSource``
-                           objects to different variable names in the current request
-
-   :param str op: Gremlin Server op argument. "eval" by default.
-
-   :param str processor: Gremlin Server processor argument. "" by default.
-
-   :param float timeout: timeout for establishing connection (optional).
-                         Values ``0`` or ``None`` mean no timeout
-
-   :param str session: Session id (optional). Typically a uuid
-
-   :returns: :py:class:`aiogremlin.client.GremlinResponse` object
-
-.. method:: execute(gremlin, *, bindings=None, lang=None, rebindings=None,
-                    op=None, processor=None, binary=True, session=None,
-                    timeout=None)
-
-   :ref:`coroutine<coroutine>` method
-
-   Submit a script to the Gremlin Server and get a list of the responses.
-
-   :param str gremlin: Gremlin script to submit to server.
-
-   :param str url: url for Gremlin Server (optional). 'ws://localhost:8182/'
-                   by default
-
-   :param dict bindings: A mapping of bindings for Gremlin script.
-
-   :param str lang: Language of scripts submitted to the server.
-                    "gremlin-groovy" by default
-
-   :param dict rebindings: Rebind ``Graph`` and ``TraversalSource``
-                           objects to different variable names in the current
-                           request
-
-   :param str op: Gremlin Server op argument. "eval" by default.
-
-   :param str processor: Gremlin Server processor argument. "" by default.
-
-   :param float timeout: timeout for establishing connection (optional).
-                         Values ``0`` or ``None`` mean no timeout
-
-   :param str session: Session id (optional). Typically a uuid
-
-   :returns: :py:class:`list` of :py:class:`aiogremlin.subprotocol.Message`
-
-
-Using Gremlin Server sessions with :py:class:`GremlinClientSession`.
---------------------------------------------------------------------
-
-The Gremlin Server supports sessions to maintain state across server
-messages. Although this is not the preffered method, it is quite useful in
-certain situations. For convenience, :py:mod:`aiogremlin` provides the class
-:py:class:`aiogremlin.client.GremlinClientSession`. It is basically the
-same as the :py:class:`GremlinClient`, but it uses sessions by default::
-
-    >>> client = aiogremlin.GremlinClientSession()
-    >>> client.session
-    '533f15fb-dc2e-4768-86c5-5b136b380b65'
-    >>> client.reset_session()
-    'd7bdb0da-d4ec-4609-8ac0-df9713803d43'
-
-That's basically it! For more info, see the
-:ref:`Client Reference Guide<aiogremlin-client-reference>`
-
-
-
-
-
-
-
-
-
-
-.. _Gremlin Server: http://tinkerpop.incubator.apache.org/
+    >>> remote_connection = await DriverRemoteConnection.open(
+    ...    'ws://localhost:8182/gremlin', 'g', port=9430)
+
+2. Passing a :py:class:`Cluster<aiogremlin.driver.cluster.Cluster>` object to the
+classmethod
+:py:meth:`using<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection.using>`::
+
+    >>> import asyncio
+    >>> from aiogremlin import Cluster
+    >>> loop = asyncio.get_event_loop()
+    >>> cluster = await Cluster.open(loop, port=9430, aliases={'g': 'g'})
+    >>> remote_connection = await DriverRemoteConnection.using(cluster)
+
+In the case that the
+:py:class:`DriverRemoteConnection<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection>`
+is created with
+:py:meth:`using<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection.using>`,
+it is not necessary to close the
+:py:class:`DriverRemoteConnection<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection>`,
+but the underlying :py:class:`Cluster<aiogremlin.driver.cluster.Cluster>` must be closed::
+
+    >>> await cluster.close()
+
+Configuration options are specified in the final section of this document.
+
+:py:class:`DriverRemoteConnection<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection>`
+is also an asynchronous context manager. It can be used as follows::
+
+    >>> async with remote_connection:
+    ...     g = Graph().traversal().withRemote(remote_connection)
+    ...     # traverse
+    # remote_connection is closed upon exit
+
+Taking this one step further, the
+:py:meth:`open<aiogremlin.remote.driver_remote_connection.DriverRemoteConnection.open>`
+can be awaited in the async context manager statement::
+
+    >>> async with await DriverRemoteConnection.open() as remote_connection:
+    ...     g = Graph().traversal().withRemote(remote_connection)
+    ...     # traverse
+    # remote connection is closed upon exit
+
+Using the :py:mod:`driver<aiogremlin.driver>` Module
+----------------------------------------------------
+
+:py:mod:`aiogremlin` also includes an asynchronous driver modeled after the
+official Gremlin-Python driver implementation. However, instead of using
+threads for asynchronous I/O, it uses an :py:mod:`asyncio` based implemenation.
+
+To submit a raw Gremlin script to the server, use the
+:py:class:`Client<aiogremlin.driver.client.Client>`. This class should not
+be instantiated directly, instead use a
+:py:class:`Cluster<aiogremlin.driver.cluster.Cluster>` object::
+
+    >>> cluster = await Cluster.open(loop)
+    >>> client = await cluster.connect()
+    >>> result_set = await client.submit('g.V().hasLabel(x)', {'x': 'person'})
+
+The :py:class:`ResultSet<aiogremlin.driver.resultset.ResultSet>` returned by
+:py:meth:`Client<aiogremlin.driver.client.Client.submit>` implements the
+async interator protocol::
+
+    >>> async for v in result_set:
+    ...     print(v)
+
+It also provides a convenience method
+:py:meth:`all<aiogremlin.driver.client.Client.all>`
+that aggregates and returns the result of the script in a :py:class:`list`::
+
+    >>> results = await result_set.all()
+
+Closing the client will close the underlying cluster::
+
+    >>> await client.close()
+
+Configuring the :py:class:`Cluster<aiogremlin.driver.cluster.Cluster>` object
+-----------------------------------------------------------------------------
+
+Configuration options can be set on
+:py:class:`Cluster<aiogremlin.driver.cluster.Cluster>` in one of two ways, either
+passed as keyword arguments to
+:py:meth:`Cluster<aiogremlin.driver.cluster.Cluster.open>`, or stored in a configuration
+file and passed to the :py:meth:`open<aiogremlin.driver.cluster.Cluster.open>`
+using the kwarg `configfile`. Configuration files can be either YAML or JSON
+format. Currently, :py:class:`Cluster<aiogremlin.driver.cluster.Cluster>`
+uses the following configuration:
+
++-------------------+----------------------------------------------+-------------+
+|Key                |Description                                   |Default      |
++===================+==============================================+=============+
+|scheme             |URI scheme, typically 'ws' or 'wss' for secure|'ws'         |
+|                   |websockets                                    |             |
++-------------------+----------------------------------------------+-------------+
+|hosts              |A list of hosts the cluster will connect to   |['localhost']|
++-------------------+----------------------------------------------+-------------+
+|port               |The port of the Gremlin Server to connect to, |8182         |
+|                   |same for all hosts                            |             |
++-------------------+----------------------------------------------+-------------+
+|ssl_certfile       |File containing ssl certificate               |''           |
++-------------------+----------------------------------------------+-------------+
+|ssl_keyfile        |File containing ssl key                       |''           |
++-------------------+----------------------------------------------+-------------+
+|ssl_password       |File containing password for ssl keyfile      |''           |
++-------------------+----------------------------------------------+-------------+
+|username           |Username for Gremlin Server authentication    |''           |
++-------------------+----------------------------------------------+-------------+
+|password           |Password for Gremlin Server authentication    |''           |
++-------------------+----------------------------------------------+-------------+
+|response_timeout   |Timeout for reading responses from the stream |`None`       |
++-------------------+----------------------------------------------+-------------+
+|max_conns          |The maximum number of connections open at any |4            |
+|                   |time to this host                             |             |
++-------------------+----------------------------------------------+-------------+
+|min_conns          |The minimum number of connection open at any  |1            |
+|                   |time to this host                             |             |
++-------------------+----------------------------------------------+-------------+
+|max_times_acquired |The maximum number of times a single pool     |16           |
+|                   |connection can be acquired and shared         |             |
++-------------------+----------------------------------------------+-------------+
+|max_inflight       |The maximum number of unresolved messages     |64           |
+|                   |that may be pending on any one connection     |             |
++-------------------+----------------------------------------------+-------------+
+|message_serializer |String denoting the class used for message    |'classpath'  |
+|                   |serialization, currently only supports        |             |
+|                   |basic GraphSONMessageSerializer               |             |
++-------------------+----------------------------------------------+-------------+
diff --git a/news.txt b/news.txt
new file mode 100644
index 0000000000000000000000000000000000000000..61a279c5081f466b5b8455bd8531960fdcde4dd7
--- /dev/null
+++ b/news.txt
@@ -0,0 +1 @@
+3.2.4 - Async GLV and driver released!!!
diff --git a/profiler.py b/profiler.py
deleted file mode 100644
index 2559772e05975d4c7974409ced3cbfbac007f786..0000000000000000000000000000000000000000
--- a/profiler.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import cProfile
-import asyncio
-import aiogremlin
-
-loop = asyncio.get_event_loop()
-gc = aiogremlin.GremlinClient(loop=loop)
-
-execute = gc.execute("x + x", bindings={"x": 4})
-cProfile.run('loop.run_until_complete(execute)')
diff --git a/requirements.txt b/requirements.txt
index 1bf0c3bdecc884909c96899dd474813efb74c957..e746163784527d036e7efb1856d11dab693ea47a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,2 @@
-aiohttp==0.18.4
-aiowebsocketclient==0.0.4
+aiohttp==1.3.3
+PyYAML==3.12
diff --git a/setup.py b/setup.py
index a041ad2d86b1fd0f5548815b51140f29d2b2f198..30c4b42e3617594316c5f79b93b5f3d74bf5fc39 100644
--- a/setup.py
+++ b/setup.py
@@ -3,9 +3,9 @@ from setuptools import setup
 
 setup(
     name='aiogremlin',
-    version='3.2.4',
+    version='3.2.4-rc.1',
     url='',
-    license='MIT',
+    license='Apache',
     author='davebshow',
     author_email='davebshow@gmail.com',
     description='Async Gremlin-Python',
@@ -24,13 +24,13 @@ setup(
     setup_requires=['pytest-runner'],
     tests_require=['pytest-asyncio', 'pytest', 'mock'],
     classifiers=[
-        'Development Status :: 3 - Alpha',
+        'Development Status :: 4 - Beta',
         'Intended Audience :: Developers',
-        'License :: OSI Approved :: MIT License',
+        'License :: OSI Approved :: Apache Software License',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
         'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3 :: Only'
     ]
 )