From d451d85d12a87c5c3456eabab198cb8cf0c84322 Mon Sep 17 00:00:00 2001 From: davebshow <davebshow@gmail.com> Date: Tue, 30 Jun 2015 20:45:50 -0400 Subject: [PATCH] working on docs --- aiogremlin/client.py | 80 ++++++++++++++++++++++++++++++++++++--- aiogremlin/response.py | 15 +++++++- aiogremlin/subprotocol.py | 10 ++--- docs/aiogremlin.rst | 4 +- docs/index.rst | 16 +++++++- docs/usage.rst | 34 ++++++++++++++++- 6 files changed, 142 insertions(+), 17 deletions(-) diff --git a/aiogremlin/client.py b/aiogremlin/client.py index 9f8d2e1..1cecf65 100644 --- a/aiogremlin/client.py +++ b/aiogremlin/client.py @@ -86,7 +86,10 @@ class GremlinClient: @asyncio.coroutine def close(self): - """Close client. If client has not been detached from underlying + """ + :ref:`coroutine<coroutine>` method. + + Close client. If client has not been detached from underlying ws_connector, this coroutinemethod closes the latter as well.""" if self._closed: return @@ -105,6 +108,23 @@ class GremlinClient: 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 dict bindings: A mapping of bindings for Gremlin script. + :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 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) + :returns: :py:class:`aiogremlin.client.GremlinResponse` object """ lang = lang or self.lang op = op or self.op @@ -129,6 +149,24 @@ class GremlinClient: def execute(self, gremlin, *, bindings=None, lang=None, session=None, op=None, processor=None, binary=True, timeout=None): """ + :ref:`coroutine<coroutine>` method. + + Submit a script to the Gremlin Server and get the result. + + :param str gremlin: Gremlin script to submit to server. + :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 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 + :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None`` + `asyncio.get_event_loop` is used for getting default event loop + (optional) + :returns: :py:class:`list` of + :py:class:`aiogremlin.subprotocol.Message` """ lang = lang or self.lang op = op or self.op @@ -170,6 +208,7 @@ class GremlinClientSession(GremlinClient): @property def session(self): + """Getter setter property for session id.""" return self._session @session.setter @@ -177,6 +216,14 @@ class GremlinClientSession(GremlinClient): self._session = value def reset_session(self, session=None): + """ + Reset session id. + + :param str session: A unique session id (optional). If None, an id will + be generated using :py:func:`uuid.uuid4`. + + :returns: New session id. + """ if session is None: session = str(uuid.uuid4()) self._session = session @@ -201,20 +248,29 @@ class GremlinResponse: @property def stream(self): + """Read-only property used to get data from the stream in chunks. + + :returns: :py:class:`aiogremlin.client.ResponseStream`""" return self._stream @property def session(self): + """Session ID (if applicable).""" return self._session @asyncio.coroutine def get(self): + """ + :ref:`coroutine<coroutine>` method. + + Get all messages from the stream. + + :returns: :py:class:`list` :py:class:`aiogremlin.subprotocol.Message` + """ return (yield from self._run()) @asyncio.coroutine def _run(self): - """ - """ results = [] while True: message = yield from self._stream.read() @@ -244,12 +300,18 @@ class GremlinResponseStream: @asyncio.coroutine def read(self): - """Read a message from the stream""" + """ + :ref:`coroutine<coroutine>` method + + Read a message from the stream. + + :returns: :py:class:`aiogremlin.subprotocol.Message` + """ if self._stream.at_eof(): yield from self._ws.release() message = None else: - asyncio.async(self._ws.receive(), loop=self._loop) + asyncio.Task(self._ws.receive(), loop=self._loop) try: message = yield from self._stream.read() except RequestError: @@ -268,10 +330,15 @@ def submit(gremlin, *, timeout=None, session=None, loop=None): - """Submit a script to the Gremlin Server. + """ + :ref:`coroutine<coroutine>` + + Submit a script to the Gremlin Server. + :param str gremlin: The Gremlin script. :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 str op: Gremlin Server op argument. "eval" by default. @@ -282,6 +349,7 @@ def submit(gremlin, *, :param loop: :ref:`event loop<asyncio-event-loop>` If param is ``None``, `asyncio.get_event_loop` is used for getting default event loop (optional) + :returns: :py:class:`aiogremlin.client.GremlinResponse` object """ if loop is None: diff --git a/aiogremlin/response.py b/aiogremlin/response.py index a5170e0..fedf9d8 100644 --- a/aiogremlin/response.py +++ b/aiogremlin/response.py @@ -15,7 +15,9 @@ __all__ = ('GremlinClientWebSocketResponse',) class GremlinClientWebSocketResponse(ClientWebSocketResponse): - + """Wraps :py:class:`aiohttp.websocket_client.ClientWebSocketResponse` + with minimal added functionality for the Gremln Server use case. + """ def __init__(self, reader, writer, protocol, response, timeout, autoclose, autoping, loop): ClientWebSocketResponse.__init__(self, reader, writer, protocol, @@ -26,6 +28,11 @@ class GremlinClientWebSocketResponse(ClientWebSocketResponse): @property def parser(self): + """ + Read-only property. + + :returns: :py:class:`aiohttp.parsers.StreamParser` + """ return self._parser @asyncio.coroutine @@ -74,6 +81,7 @@ class GremlinClientWebSocketResponse(ClientWebSocketResponse): return True def send(self, message, *, binary=True): + """Send a message to the server.""" if binary: method = self.send_bytes else: @@ -89,6 +97,11 @@ class GremlinClientWebSocketResponse(ClientWebSocketResponse): @asyncio.coroutine def receive(self): + """ + :ref:`coroutine<coroutine>` method + + Receive a message from the server and push it into the parser. + """ msg = yield from super().receive() if msg.tp == aiohttp.MsgType.binary: self.parser.feed_data(msg.data.decode()) diff --git a/aiogremlin/subprotocol.py b/aiogremlin/subprotocol.py index dc2dfbf..c99b3ce 100644 --- a/aiogremlin/subprotocol.py +++ b/aiogremlin/subprotocol.py @@ -10,7 +10,7 @@ except ImportError: from aiogremlin.exceptions import RequestError, GremlinServerError -__all__ = ("GremlinWriter", "gremlin_response_parser") +__all__ = ("GremlinWriter", "gremlin_response_parser", "Message") Message = collections.namedtuple( @@ -43,8 +43,8 @@ def gremlin_response_parser(out, buf): class GremlinWriter: - def __init__(self, connection): - self._connection = connection + def __init__(self, ws): + self.ws = ws def write(self, gremlin, bindings=None, lang="gremlin-groovy", op="eval", processor="", session=None, binary=True, @@ -59,8 +59,8 @@ class GremlinWriter: message = json.dumps(message) if binary: message = self._set_message_header(message, mime_type) - self._connection.send(message, binary=binary) - return self._connection + self.ws.send(message, binary=binary) + return self.ws @staticmethod def _set_message_header(message, mime_type): diff --git a/docs/aiogremlin.rst b/docs/aiogremlin.rst index 1a87eb4..193331c 100644 --- a/docs/aiogremlin.rst +++ b/docs/aiogremlin.rst @@ -22,6 +22,9 @@ aiogremlin.client module aiogremlin.connector module --------------------------- +This module is based on :py:class:`aiohttp.client.ClientSession` and +:py:class:`aiohttp.connector.BaseConnector`. + .. automodule:: aiogremlin.connector :members: :undoc-members: @@ -43,7 +46,6 @@ aiogremlin.response module :members: :undoc-members: :show-inheritance: - :inherited-members: aiogremlin.subprotocol module ----------------------------- diff --git a/docs/index.rst b/docs/index.rst index 8fb9b94..83569b6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,7 +12,7 @@ based on the `asyncio`_ and `aiohttp`_ libraries. Releases ======== -The latest release of ``aiogremlin`` is **0.0.11**. +The latest release of :py:mod:`aiogremlin` is **0.0.11**. Requirements @@ -68,12 +68,23 @@ Submit a script to the Gremlin Server:: [Message(status_code=200, data=[2], message={}, metadata='')] -The above example demonstrates how ``aiogremlin`` uses the +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>`. +Contribute +---------- + +Contributions are welcome. If you find a bug, or have a suggestion, please open +an issue on `Github`_. If you would like to make a pull request, please make +sure to add appropriate tests and run them:: + + $ python setup.py test + +In the future there will be CI and more info on contributing. + Contents: .. toctree:: @@ -94,3 +105,4 @@ Indices and tables .. _`asyncio`: https://docs.python.org/3/library/asyncio.html .. _`aiohttp`: http://aiohttp.readthedocs.org/en/latest/ .. _`ujson`: https://pypi.python.org/pypi/ujson +.. _Github: https://github.com/davebshow/aiogremlin/issues diff --git a/docs/usage.rst b/docs/usage.rst index e4f0c5c..10d6f6b 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -37,6 +37,8 @@ read the chunked responses one at a time:: lang="gremlin-groovy", op="eval", processor="", timeout=None, session=None, loop=None): + :ref:`coroutine<coroutine>` + Submit a script to the Gremlin Server. :param str gremlin: Gremlin script to submit to server. @@ -129,7 +131,7 @@ point to different endpoints:: .. method:: close() - :ref:`coroutine<coroutine>` method. + :ref:`coroutine<coroutine>` method Close client. If client has not been detached from underlying ws_connector, this coroutinemethod closes the latter as well. @@ -141,6 +143,10 @@ point to different endpoints:: .. method:: submit(gremlin, *, bindings=None, lang=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/' @@ -165,6 +171,10 @@ point to different endpoints:: .. method:: execute(gremlin, *, bindings=None, lang=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/' @@ -184,10 +194,30 @@ point to different endpoints:: :param str session: Session id (optional). Typically a uuid - :returns: :py:class:`list` of messages + :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>` + + + + -- GitLab