You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2016/08/15 15:37:09 UTC

[1/2] tinkerpop git commit: added simple WebSocketRemoteConnection, made RemoteConnection into actual abstract base class, fixed typo in remote_graph

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1278 9353adb9b -> 5049caaea


added simple WebSocketRemoteConnection, made RemoteConnection into actual abstract base class, fixed typo in remote_graph


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/1f026658
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/1f026658
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/1f026658

Branch: refs/heads/TINKERPOP-1278
Commit: 1f026658f1615d203161fcd469752b6dbb8fc306
Parents: 9353adb
Author: davebshow <da...@gmail.com>
Authored: Sun Aug 14 18:47:55 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Sun Aug 14 18:47:55 2016 -0400

----------------------------------------------------------------------
 .../gremlin_python/driver/remote_connection.py  |  22 ++-
 .../driver/websocket_remote_connection.py       | 170 +++++++++++++++++++
 .../gremlin_python/structure/remote_graph.py    |   2 +-
 3 files changed, 189 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/1f026658/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
index 4952fbe..89a7898 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
@@ -16,23 +16,37 @@ 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
+
 
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
 
 
+@six.add_metaclass(abc.ABCMeta)
 class RemoteConnection(object):
+
     def __init__(self, url, traversal_source):
-        self.url = url
-        self.traversal_source = traversal_source
+        self._url = url
+        self._traversal_source = traversal_source
 
-    @abstractmethod
+    @property
+    def url(self):
+        return self._url
+
+    @property
+    def traversal_source(self):
+        return self._traversal_source
+
+    @abc.abstractmethod
     def submit(self, target_language, bytecode):
         print "sending " + bytecode + " to GremlinServer..."
         return RemoteResponse(iter([]), {})
 
 
 class RemoteResponse(object):
+
     def __init__(self, traversers, side_effects):
         self.traversers = traversers
         self.side_effects = side_effects

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/1f026658/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py
new file mode 100644
index 0000000..7876083
--- /dev/null
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py
@@ -0,0 +1,170 @@
+import json
+import uuid
+
+from tornado import gen
+from tornado import ioloop
+from tornado import websocket
+
+from ..process.traversal import Traverser
+from .remote_connection import RemoteConnection
+from .remote_connection import RemoteResponse
+
+
+class GremlinServerError(Exception):
+    pass
+
+
+class WebSocketRemoteConnection(RemoteConnection):
+    """Remote connection to the Gremlin Server"""
+    def __init__(self, url, traversal_source, loop=None, username='',
+                 password=''):
+        super(WebSocketRemoteConnection, self).__init__(
+            url, traversal_source)
+        if loop is None:
+            self._loop = ioloop.IOLoop.current()
+        self._ws = self._loop.run_sync(
+            lambda: websocket.websocket_connect(self.url))
+        self._username = username
+        self._password = password
+
+    def submit(self,
+               target_language,
+               bytecode,
+               op="eval",
+               processor="",
+               session=None):
+        traversers = self._loop.run_sync(lambda: self._submit(
+            target_language, bytecode, op, processor, session))
+        return RemoteResponse(iter(traversers), {})
+
+    @gen.coroutine
+    def _submit(self,
+                target_language,
+                bytecode,
+                op,
+                processor,
+                session):
+        """
+        Submit a script and bindings 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 str session: Session id (optional). Typically a uuid
+
+        :returns: :py:class:`Response` object
+        """
+        request_id = str(uuid.uuid4())
+        message = self._prepare_message(bytecode,
+                                        bytecode.bindings,
+                                        target_language,
+                                        op,
+                                        processor,
+                                        session,
+                                        request_id)
+        if self._ws.protocol is None:
+            self._ws = yield websocket.websocket_connect(self.url)
+        self._ws.write_message(message, binary=True)
+        resp = Response(self._ws, processor, session, self._username,
+                        self._password)
+        traversers = []
+        while True:
+            msg = yield resp.receive()
+            if msg is None:
+                break
+            traversers += msg
+        raise gen.Return(traversers)
+
+    def close(self):
+        """Close underlying connection and mark as closed."""
+        self._ws.close()
+
+    def _prepare_message(self, gremlin, bindings, lang, op,
+                         processor, session, request_id):
+        message = {
+            "requestId": request_id,
+            "op": op,
+            "processor": processor,
+            "args": {
+                "gremlin": gremlin,
+                "bindings": bindings,
+                "language":  lang,
+                "aliases": {'g': self.traversal_source}
+            }
+        }
+        message = self._finalize_message(message, processor, session)
+        return message
+
+    def _authenticate(self, username, password, processor, session):
+        auth = b"".join([b"\x00", username.encode("utf-8"),
+                         b"\x00", password.encode("utf-8")])
+        message = {
+            "requestId": str(uuid.uuid4()),
+            "op": "authentication",
+            "processor": "",
+            "args": {
+                "sasl": base64.b64encode(auth).decode()
+            }
+        }
+        message = self._finalize_message(message, processor, session)
+        self._ws.send_message(message, binary=True)
+
+    def _finalize_message(self, message, processor, session):
+        if processor == "session":
+            if session is None:
+                raise RuntimeError("session processor requires a session id")
+            else:
+                message["args"].update({"session": session})
+        message = json.dumps(message)
+        return self._set_message_header(message, "application/json")
+
+    @staticmethod
+    def _set_message_header(message, mime_type):
+        if mime_type == "application/json":
+            mime_len = b"\x10"
+            mime_type = b"application/json"
+        else:
+            raise ValueError("Unknown mime type.")
+        return b"".join([mime_len, mime_type, message.encode("utf-8")])
+
+
+class Response:
+
+    def __init__(self, ws, processor, session, username, password):
+        self._ws = ws
+        self._closed = False
+        self._processor = processor
+        self._session = session
+        self._username = username
+        self._password
+
+    @gen.coroutine
+    def receive(self):
+        if self._closed:
+            return
+        data = yield self._ws.read_message()
+        message = json.loads(data)
+        status_code = message['status']['code']
+        data = message["result"]["data"]
+        msg = message["status"]["message"]
+        if status_code == 407:
+            self._authenticate(self._username, self._password, self._processor,
+                               self._session)
+            traversers = yield self.receive()
+        elif status_code == 204:
+            self._closed = True
+            return
+        elif status_code in [200, 206]:
+            traversers = []
+            for result in data:
+                traversers.append(Traverser(result, 1))
+            if status_code == 200:
+                self._closed = True
+        else:
+            self._closed = True
+            raise GremlinServerError(
+                "{0}: {1}".format(status_code, msg))
+        raise gen.Return(traversers)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/1f026658/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py b/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py
index 525bdfd..72be076 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py
@@ -41,7 +41,7 @@ class RemoteStrategy(TraversalStrategy):
         if traversal.traversers is None:
             remote_response = traversal.graph.remote_connection.submit(
                 'gremlin-groovy',  # script engine
-                traversal.bytecode),  # script
+                traversal.bytecode)  # script
             traversal.side_effects = remote_response.side_effects
             traversal.traversers = remote_response.traversers
         return


[2/2] tinkerpop git commit: Add missing license header.

Posted by sp...@apache.org.
Add missing license header.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/5049caae
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/5049caae
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/5049caae

Branch: refs/heads/TINKERPOP-1278
Commit: 5049caaeaf2f7bb7e163366ca61483179f5dabfc
Parents: 1f02665
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Aug 15 11:36:51 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Aug 15 11:36:51 2016 -0400

----------------------------------------------------------------------
 .../driver/websocket_remote_connection.py         | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5049caae/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py
index 7876083..52a9a88 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/websocket_remote_connection.py
@@ -1,3 +1,21 @@
+'''
+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 json
 import uuid