From a7b926625fb5ed44d42a4db660e578d9ddb97098 Mon Sep 17 00:00:00 2001
From: davebshow <davebshow@gmail.com>
Date: Mon, 27 Apr 2015 23:34:12 -0400
Subject: [PATCH] preparing for more refactoring, clean ups, error handling etc

---
 README.md                |  6 ++---
 aiogremlin/__init__.py   |  2 +-
 aiogremlin/abc.py        | 26 ++++++++------------
 aiogremlin/connection.py | 52 +++++++++++++++++++++++++++++++++-------
 aiogremlin/protocol.py   |  1 +
 aiogremlin/response.py   |  5 ++--
 aiogremlin/tasks.py      |  1 +
 7 files changed, 62 insertions(+), 31 deletions(-)

diff --git a/README.md b/README.md
index 1c3d412..8f5db31 100644
--- a/README.md
+++ b/README.md
@@ -17,11 +17,11 @@ Fire up the Gremlin Server:
 $ ./bin/gremlin-server.sh
 ```
 
-The `AsyncGremlinClient` communicates asynchronously with the Gremlin Server using websockets. The client uses a combination of [asyncio.coroutine](https://docs.python.org/3/library/asyncio-task.html#coroutines) and  [asyncio.Task](https://docs.python.org/3/library/asyncio-task.html#task) run on Asyncio's pluggable event loop to achieve this communication.
+The `GremlinClient` communicates asynchronously with the Gremlin Server using websockets. The client uses a combination of [asyncio.coroutine](https://docs.python.org/3/library/asyncio-task.html#coroutines) and  [asyncio.Task](https://docs.python.org/3/library/asyncio-task.html#task) run on Asyncio's pluggable event loop to achieve this communication.
 
-The majority of ``AsyncGremlinClient`` methods are an `asyncio.coroutine`, so you will also need to use either `asyncio` or the `aiogremlin` [Task API](#task-api). The following examples use `asyncio` to demonstrate the use of the AsyncioGremlineClient.
+The majority of `GremlinClient` methods are an `asyncio.coroutine`, so you will also need to use either `asyncio` or the `aiogremlin` [Task API](#task-api). The following examples use `asyncio` to demonstrate the use of the AsyncioGremlineClient.
 
-The Gremlin Server sends responses in chunks, so `AsyncGremlinClient.submit` returns a list of gremlin response objects:
+The Gremlin Server sends responses in chunks, so `GremlinClient.submit` returns a list of gremlin response objects:
 
 ```python
 >>> import asyncio
diff --git a/aiogremlin/__init__.py b/aiogremlin/__init__.py
index 00e596a..f462346 100644
--- a/aiogremlin/__init__.py
+++ b/aiogremlin/__init__.py
@@ -1,4 +1,4 @@
-from .abc import AbstractBaseFactory, AbstractBaseConnection
+from .abc import AbstractFactory, AbstractConnection
 from .connection import WebsocketPool, AiohttpFactory
 from .client import GremlinClient
 from .contextmanager import GremlinContext
diff --git a/aiogremlin/abc.py b/aiogremlin/abc.py
index 851503c..b5c480d 100644
--- a/aiogremlin/abc.py
+++ b/aiogremlin/abc.py
@@ -1,8 +1,7 @@
-import asyncio
 from abc import ABCMeta, abstractmethod
 
 
-class AbstractBaseFactory(metaclass=ABCMeta):
+class AbstractFactory(metaclass=ABCMeta):
 
     @classmethod
     @abstractmethod
@@ -10,30 +9,25 @@ class AbstractBaseFactory(metaclass=ABCMeta):
         pass
 
     @property
+    @abstractmethod
     def factory(self):
-        return self
-
+        pass
 
-class AbstractBaseConnection(metaclass=ABCMeta):
 
-    def __init__(self, socket, pool=None):
-        self.socket = socket
-        self._pool = pool
+class AbstractConnection(metaclass=ABCMeta):
 
+    @abstractmethod
     def feed_pool(self):
-        if self.pool:
-            if self in self.pool.active_conns:
-                self.pool.feed_pool(self)
+        pass
 
-    @asyncio.coroutine
+    @abstractmethod
     def release(self):
-        yield from self.close()
-        if self in self.pool.active_conns:
-            self.pool.active_conns.discard(self)
+        pass
 
     @property
+    @abstractmethod
     def pool(self):
-        return self._pool
+        pass
 
     @property
     @abstractmethod
diff --git a/aiogremlin/connection.py b/aiogremlin/connection.py
index ed35dc6..a135bb6 100644
--- a/aiogremlin/connection.py
+++ b/aiogremlin/connection.py
@@ -4,7 +4,7 @@ import asyncio
 
 import aiohttp
 
-from .abc import AbstractBaseFactory, AbstractBaseConnection
+from .abc import AbstractFactory, AbstractConnection
 from .exceptions import SocketClientError
 from .log import INFO, conn_logger
 
@@ -41,6 +41,8 @@ class WebsocketPool:
         return len(self.active_conns)
 
     def feed_pool(self, conn):
+        if self._closed:
+            raise RuntimeError("WebsocketPool is closed.")
         self.active_conns.discard(conn)
         self._put(conn)
 
@@ -70,6 +72,8 @@ class WebsocketPool:
 
     @asyncio.coroutine
     def connect(self, uri=None, loop=None, num_retries=None):
+        if self._closed:
+            raise RuntimeError("WebsocketPool is closed.")
         if num_retries is None:
             num_retries = self.max_retries
         uri = uri or self.uri
@@ -111,7 +115,14 @@ class WebsocketPool:
             pass
 
 
-class AiohttpFactory(AbstractBaseFactory):
+class BaseFactory(AbstractFactory):
+
+    @property
+    def factory(self):
+        return self
+
+
+class AiohttpFactory(BaseFactory):
 
     @classmethod
     @asyncio.coroutine
@@ -128,13 +139,34 @@ class AiohttpFactory(AbstractBaseFactory):
         return AiohttpConnection(socket, pool)
 
 
-class AiohttpConnection(AbstractBaseConnection):
+class BaseConnection(AbstractConnection):
 
     def __init__(self, socket, pool=None):
-        super().__init__(socket, pool=pool)
+        self.socket = socket
+        self._pool = pool
+
+    def feed_pool(self):
+        if self.pool:
+            if self in self.pool.active_conns:
+                self.pool.feed_pool(self)
+
+    @asyncio.coroutine
+    def release(self):
+        try:
+            yield from self.close()
+        finally:
+            if self in self.pool.active_conns:
+                self.pool.active_conns.discard(self)
+
+    @property
+    def pool(self):
+        return self._pool
 
-    def __str__(self):
-        return "{} wrapping {}".format(repr(self), repr(self.socket))
+
+class AiohttpConnection(BaseConnection):
+
+    def __init__(self, socket, pool=None):
+        super().__init__(socket, pool=pool)
 
     @property
     def closed(self):
@@ -142,7 +174,11 @@ class AiohttpConnection(AbstractBaseConnection):
 
     @asyncio.coroutine
     def close(self):
-        yield from self.socket.close()
+        if not self.socket._closed:
+            try:
+                yield from self.socket.close()
+            finally:
+                self._closed = True
 
     @asyncio.coroutine
     def send(self, message, binary=True):
@@ -189,7 +225,7 @@ class AiohttpConnection(AbstractBaseConnection):
                     elif message.tp == aiohttp.MsgType.error:
                         raise SocketClientError(self.socket.exception())
                     elif message.tp == aiohttp.MsgType.closed:
-                        raise SocketClientError("Socket closed.")
+                        raise RuntimeError("Socket closed.")
                     break
                 finally:
                     yield from self.release()
diff --git a/aiogremlin/protocol.py b/aiogremlin/protocol.py
index 3b46797..4f10ec3 100644
--- a/aiogremlin/protocol.py
+++ b/aiogremlin/protocol.py
@@ -27,6 +27,7 @@ def gremlin_response_parser(connection):
         finally:
             yield from connection.release()
 
+
 class GremlinWriter:
 
     def __init__(self, connection):
diff --git a/aiogremlin/response.py b/aiogremlin/response.py
index d6e3808..04a9944 100644
--- a/aiogremlin/response.py
+++ b/aiogremlin/response.py
@@ -1,10 +1,9 @@
 """
-gizmo.response
-
-This module defines parsers for the Gremlin Server response.
+THIS MODULE WILL BE REMOVED
 """
 
 class GremlinResponse(list):
+
     def __init__(self, message):
         """
         A subclass of list that parses and flattens the Gremlin Server's
diff --git a/aiogremlin/tasks.py b/aiogremlin/tasks.py
index 92218f2..562d173 100644
--- a/aiogremlin/tasks.py
+++ b/aiogremlin/tasks.py
@@ -1,4 +1,5 @@
 """
+THIS MODULE WILL BE COMPLETELY REFACTORED
 """
 import asyncio
 import itertools
-- 
GitLab