You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by da...@apache.org on 2017/02/15 23:26:20 UTC

[1/3] tinkerpop git commit: allow user to pass graphson reader/writer

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1599 5eff6398b -> 5fd4dfa8d


allow user to pass graphson reader/writer


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

Branch: refs/heads/TINKERPOP-1599
Commit: a794f50689ee90c1905e829dee53b27b6e301141
Parents: 5eff639
Author: davebshow <da...@gmail.com>
Authored: Wed Feb 15 16:27:46 2017 -0500
Committer: davebshow <da...@gmail.com>
Committed: Wed Feb 15 16:27:46 2017 -0500

----------------------------------------------------------------------
 .../main/jython/gremlin_python/driver/client.py |  6 +-
 .../driver/driver_remote_connection.py          | 20 +++--
 .../jython/gremlin_python/driver/protocol.py    |  9 +-
 .../jython/gremlin_python/driver/serializer.py  | 86 ++++++++++----------
 .../src/main/jython/tests/conftest.py           |  2 +
 5 files changed, 70 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a794f506/gremlin-python/src/main/jython/gremlin_python/driver/client.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/client.py b/gremlin-python/src/main/jython/gremlin_python/driver/client.py
index fcbdf07..0314a44 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/client.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/client.py
@@ -23,7 +23,7 @@ from concurrent.futures import ThreadPoolExecutor
 
 from six.moves import queue
 
-from gremlin_python.driver import connection, protocol, request
+from gremlin_python.driver import connection, protocol, request, serializer
 from gremlin_python.process import traversal
 
 # This is until concurrent.futures backport 3.1.0 release
@@ -44,6 +44,8 @@ class Client:
                  message_serializer=None, username="", password=""):
         self._url = url
         self._traversal_source = traversal_source
+        if message_serializer is None:
+            message_serializer = serializer.GraphSONMessageSerializer()
         self._message_serializer = message_serializer
         self._username = username
         self._password = password
@@ -59,7 +61,7 @@ class Client:
         self._transport_factory = transport_factory
         if protocol_factory is None:
             protocol_factory = lambda: protocol.GremlinServerWSProtocol(
-                message_serializer=self._message_serializer,
+                self._message_serializer,
                 username=self._username,
                 password=self._password)
         self._protocol_factory = protocol_factory

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a794f506/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
index fb0e4ba..1f08e2b 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
@@ -18,7 +18,7 @@ under the License.
 """
 from concurrent.futures import Future
 
-from gremlin_python.driver import client
+from gremlin_python.driver import client, serializer
 from gremlin_python.driver.remote_connection import (
     RemoteConnection, RemoteTraversal, RemoteTraversalSideEffects)
 
@@ -29,10 +29,20 @@ class DriverRemoteConnection(RemoteConnection):
 
     def __init__(self, url, traversal_source, protocol_factory=None,
                  transport_factory=None, pool_size=None, max_workers=None,
-                 username="", password=""):
-        self._client = client.Client(url, traversal_source, protocol_factory,
-                                     transport_factory, pool_size, max_workers,
-                                     None, username, password)
+                 username="", password="", message_serializer=None,
+                 graphson_reader=None, graphson_writer=None):
+        if message_serializer is None:
+            message_serializer = serializer.GraphSONMessageSerializer(
+                reader=graphson_reader,
+                writer=graphson_writer)
+        self._client = client.Client(url, traversal_source,
+                                     protocol_factory=protocol_factory,
+                                     transport_factory=transport_factory,
+                                     pool_size=pool_size,
+                                     max_workers=max_workers,
+                                     message_serializer=message_serializer,
+                                     username=username,
+                                     password=password)
         self._url = self._client._url
         self._traversal_source = self._client._traversal_source
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a794f506/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py b/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
index 279a8f5..33b4419 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
@@ -19,10 +19,13 @@ under the License.
 import abc
 import base64
 import collections
-import json
 import uuid
 
 import six
+try:
+    import ujson as json
+except ImportError:
+    import json
 
 from gremlin_python.driver import serializer, request
 
@@ -51,9 +54,7 @@ class AbstractBaseProtocol:
 
 class GremlinServerWSProtocol(AbstractBaseProtocol):
 
-    def __init__(self, message_serializer=None, username='', password=''):
-        if message_serializer is None:
-            message_serializer = serializer.GraphSONMessageSerializer()
+    def __init__(self, message_serializer, username='', password=''):
         self._message_serializer = message_serializer
         self._username = username
         self._password = password

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a794f506/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py b/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
index 2db7374..a29d4dc 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/serializer.py
@@ -29,72 +29,74 @@ __author__ = 'David M. Brown (davebshow@gmail.com)'
 class Processor:
     """Base class for OpProcessor serialization system."""
 
-    _graphson_writer = graphson.GraphSONWriter()
-
-    def __init__(self, default_args):
-        self._default_args = default_args
+    def __init__(self, writer):
+        self._graphson_writer = writer
 
     def get_op_args(self, op, args):
         op_method = getattr(self, op, None)
         if not op_method:
             raise Exception("Processor does not support op: {}".format(op))
-        args_ = self._default_args.get(op, dict()).copy()
-        args_.update(args)
-        return op_method(args_)
-
+        return op_method(args)
 
-class GraphSONMessageSerializer:
-    """Message serializer for GraphSON"""
 
-    _graphson_reader = graphson.GraphSONReader()
+class Standard(Processor):
 
+    def authentication(self, args):
+        return args
 
-    class standard(Processor):
+    def eval(self, args):
+        return args
 
-        def authentication(self, args):
-            return args
 
-        def eval(self, args):
-            return args
+class Traversal(Processor):
 
+    def authentication(self, args):
+        return args
 
-    class traversal(Processor):
+    def bytecode(self, args):
+        gremlin = args['gremlin']
+        args['gremlin'] = self._graphson_writer.toDict(gremlin)
+        aliases = args.get('aliases', '')
+        if not aliases:
+            aliases = {'g': 'g'}
+        args['aliases'] = aliases
+        return args
 
-        def authentication(self, args):
-            return args
+    def close(self, args):
+        return self.keys(args)
 
-        def bytecode(self, args):
-            gremlin = args['gremlin']
-            args['gremlin'] = self._graphson_writer.toDict(gremlin)
-            aliases = args.get('aliases', '')
-            if not aliases:
-                aliases = {'g': 'g'}
-            args['aliases'] = aliases
-            return args
+    def gather(self, args):
+        side_effect = args['sideEffect']
+        args['sideEffect'] = {'@type': 'g:UUID', '@value': side_effect}
+        aliases = args.get('aliases', '')
+        if not aliases:
+            aliases = {'g': 'g'}
+        args['aliases'] = aliases
+        return args
 
-        def close(self, args):
-            return self.keys(args)
+    def keys(self, args):
+        side_effect = args['sideEffect']
+        args['sideEffect'] = {'@type': 'g:UUID', '@value': side_effect}
+        return args
 
-        def gather(self, args):
-            side_effect = args['sideEffect']
-            args['sideEffect'] = {'@type': 'g:UUID', '@value': side_effect}
-            aliases = args.get('aliases', '')
-            if not aliases:
-                aliases = {'g': 'g'}
-            args['aliases'] = aliases
-            return args
 
-        def keys(self, args):
-            side_effect = args['sideEffect']
-            args['sideEffect'] = {'@type': 'g:UUID', '@value': side_effect}
-            return args
+class GraphSONMessageSerializer:
+    """Message serializer for GraphSON"""
 
+    def __init__(self, reader=None, writer=None):
+        if not reader:
+            reader = graphson.GraphSONReader()
+        self._graphson_reader = reader
+        if not writer:
+            writer = graphson.GraphSONWriter()
+        self.standard = Standard(writer)
+        self.traversal = Traversal(writer)
 
     def get_processor(self, processor):
         processor = getattr(self, processor, None)
         if not processor:
             raise Exception("Unknown processor")
-        return processor({})
+        return processor
 
     def serialize_message(self, request_id, request_message):
         processor = request_message.processor

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a794f506/gremlin-python/src/main/jython/tests/conftest.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/conftest.py b/gremlin-python/src/main/jython/tests/conftest.py
index 3425266..2cd4282 100644
--- a/gremlin-python/src/main/jython/tests/conftest.py
+++ b/gremlin-python/src/main/jython/tests/conftest.py
@@ -26,12 +26,14 @@ from gremlin_python.driver.connection import Connection
 from gremlin_python.driver.driver_remote_connection import (
     DriverRemoteConnection)
 from gremlin_python.driver.protocol import GremlinServerWSProtocol
+from gremlin_python.driver.serializer import GraphSONMessageSerializer
 from gremlin_python.driver.tornado.transport import TornadoTransport
 
 
 @pytest.fixture
 def connection(request):
     protocol = GremlinServerWSProtocol(
+        GraphSONMessageSerializer(),
         username='stephen', password='password')
     executor = concurrent.futures.ThreadPoolExecutor(5)
     pool = queue.Queue()


[3/3] tinkerpop git commit: updated changlog, added docs

Posted by da...@apache.org.
updated changlog, added docs


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

Branch: refs/heads/TINKERPOP-1599
Commit: 5fd4dfa8d4d049ad5dada6da8bb13d5a1d67ee71
Parents: d521d5b
Author: davebshow <da...@gmail.com>
Authored: Wed Feb 15 18:26:08 2017 -0500
Committer: davebshow <da...@gmail.com>
Committed: Wed Feb 15 18:26:08 2017 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  5 ++
 .../src/reference/gremlin-applications.asciidoc | 71 ++++++++++++++++++++
 .../upgrade/release-3.2.x-incubating.asciidoc   | 35 ++++++++++
 3 files changed, 111 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5fd4dfa8/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index b550fe4..cef509c 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,11 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.5 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Improved Gremlin-Python driver implementation by adding a threaded client with basic connection pooling and support for pluggable websocket clients.
+
+Improvements
+^^^^^^^^^^^^
+TINKERPOP-1599 implement real gremlin-python driver
 
 
 [[release-3-2-4]]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5fd4dfa8/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 7ca4efd..ece0a82 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -762,6 +762,77 @@ The above code demonstrates using the `TitanIoRegistry` which is an `IoRegistry`
 what classes (from Titan in this case) to auto-register during serialization.  Gremlin Server roughly uses this same
 approach when it configures it's serializers, so using this same model will ensure compatibility when making requests.
 
+[[connecting-via-python]]
+Connecting via Python
+~~~~~~~~~~~~~~~~~~~~~
+
+[source,python]
+----
+pip install gremlinpython
+----
+
+TinkerPop3 also includes a client for Python-based applications.  It is referred to as Gremlin-Python Driver.
+The `Client` class implementation/interface is based on the Java Driver, with some restrictions. Most notably,
+Gremlin-Python does not yet implement the `Cluster` class. Instead, `Client` is instantiated directly.
+Usage is as follows:
+
+[source,python]
+----
+from gremlin_python.driver import client <1>
+client = client.Client('ws://localhost:8182/gremlin', 'g') <2>
+----
+
+<1> Import the Gremlin-Python `client` module.
+<2> Opens a reference to `localhost` - note that there are various configuration options that can be passed
+to the `Client` object upon instantiation as keyword arguments.
+
+Once a `Client` instance is ready, it is possible to issue some Gremlin:
+
+[source,python]
+----
+result_set = client.submit("[1,2,3,4]")  <1>
+future_results = result_set.all()  <2>
+results = future_results.result() <3>
+assert results == [1, 2, 3, 4] <4>
+
+future_result_set = client.submitAsync("[1,2,3,4]") <5>
+result_set = future_result_set.result() <6>
+result = result_set.one() <7>
+assert results == [1, 2, 3, 4] <8>
+assert result_set.done.done() <9>
+----
+
+<1> Submit a script that simply returns a `List` of integers.  This method blocks until the request is written to
+the server and a `ResultSet` is constructed.
+<2> Even though the `ResultSet` is constructed, it does not mean that the server has sent back the results (or even
+evaluated the script potentially).  The `ResultSet` is just a holder that is awaiting the results from the server. The `all` method
+returns a `concurrent.futures.Future` that resolves to a list when it is complete.
+<3> Block until the the script is evaluated and results are sent back by the server.
+<4> Verify the result.
+<5> Submit the same script to the server but don't block.
+<6> Wait until request is written to the server and `ResultSet` is constructed.
+<7> Read a single result off the result stream.
+<8> Again, verify the result.
+<9> Verify that the all results have been read and stream is closed.
+
+Configuration
+^^^^^^^^^^^^^
+
+The following table describes the various configuration options for the Gremlin-Python Driver. They
+can be passed to the `Client` instance as keyword arguments:
+
+[width="100%",cols="3,10,^2",options="header"]
+|=========================================================
+|Key |Description |Default
+|protocol_factory |A callable that returns an instance of `AbstractBaseProtocol`. |`gremlin_python.driver.protocol.GremlinServerWSProtocol`
+|transport_factory |A callable that returns an instance of `AbstractBaseTransport`. |`gremlin_python.driver.tornado.transport.TornadoTransport`
+|pool_size |The number of connections used by the pool. |4
+|max_workers |Maximum number of worker threads. |Number of CPUs * 5
+|message_serializer |The message serializer implementation.|`gremlin_python.driver.serializer.GraphSONMessageSerializer`
+|password |The password to submit on requests that require authentication. |""
+|username |The username to submit on requests that require authentication. |""
+|=========================================================
+
 Connecting via REST
 ~~~~~~~~~~~~~~~~~~~
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5fd4dfa8/docs/src/upgrade/release-3.2.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.2.x-incubating.asciidoc b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
index c199238..c3c43e8 100644
--- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
@@ -22,6 +22,41 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 *Nine Inch Gremlins*
 
+TinkerPop 3.2.5
+---------------
+
+*Release Date:*
+
+Upgrading for Users
+~~~~~~~~~~~~~~~~~~~
+
+Gremlin-Python Driver
+^^^^^^^^^^^^^^^^^^^^^
+Gremlin-Python now offers a more complete driver implementation that uses connection pooling and
+the Python `concurrent.futures` module to provide asynchronous I/0 using threading. The default underlying
+websocket client implementation is still provided by Tornado, but it is trivial to plug in another client by
+defining the `Transport` interface.
+
+Using the `DriverRemoteConnection` class is the exact same as in previous versions; however,
+`DriverRemoteConnection` now uses the new `Client` class to submit messages to the server.
+
+The `Client` class implementation/interface is based on the Java Driver, with some restrictions.
+Most notably, Gremlin-Python does not yet implement the `Cluster` class. Instead, `Client` is
+instantiated directly. Usage is as follows:
+
+[source,python]
+----
+from gremlin_python.driver import client
+
+client = client.Client('ws://localhost:8182/gremlin', 'g')
+result_set = client.submit('1 + 1')
+future_results = result_set.all()  # returns a concurrent.futures.Future
+results = future_results.result()  # returns a list
+assert results == [2]
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1599[TINKERPOP-1599]
+
 TinkerPop 3.2.4
 ---------------
 


[2/3] tinkerpop git commit: allow client users to pass bindings as a second arg

Posted by da...@apache.org.
allow client users to pass bindings as a second arg


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

Branch: refs/heads/TINKERPOP-1599
Commit: d521d5b48d987fedf3a849b520a03b741576787d
Parents: a794f50
Author: davebshow <da...@gmail.com>
Authored: Wed Feb 15 17:57:32 2017 -0500
Committer: davebshow <da...@gmail.com>
Committed: Wed Feb 15 17:57:32 2017 -0500

----------------------------------------------------------------------
 .../src/main/jython/gremlin_python/driver/client.py          | 8 +++++---
 gremlin-python/src/main/jython/tests/driver/test_client.py   | 4 ++++
 2 files changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d521d5b4/gremlin-python/src/main/jython/gremlin_python/driver/client.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/client.py b/gremlin-python/src/main/jython/gremlin_python/driver/client.py
index 0314a44..c7c7037 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/client.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/client.py
@@ -103,10 +103,10 @@ class Client:
             self._url, self._traversal_source, protocol,
             self._transport_factory, self._executor, self._pool)
 
-    def submit(self, message):
-        return self.submitAsync(message).result()
+    def submit(self, message, bindings=None):
+        return self.submitAsync(message, bindings=bindings).result()
 
-    def submitAsync(self, message):
+    def submitAsync(self, message, bindings=None):
         if isinstance(message, traversal.Bytecode):
             message = request.RequestMessage(
                 processor='traversal', op='bytecode',
@@ -117,5 +117,7 @@ class Client:
                 processor='', op='eval',
                 args={'gremlin': message,
                       'aliases': {'g': self._traversal_source}})
+            if bindings:
+                message.args.update(bindings)
         conn = self._pool.get(True)
         return conn.write(message)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d521d5b4/gremlin-python/src/main/jython/tests/driver/test_client.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/driver/test_client.py b/gremlin-python/src/main/jython/tests/driver/test_client.py
index 02582a1..416caab 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_client.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_client.py
@@ -40,6 +40,10 @@ def test_client_simple_eval(client):
     assert client.submit('1 + 1').all().result()[0] == 2
 
 
+def test_client_simple_eval_bindings(client):
+    assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
+
+
 def test_client_eval_traversal(client):
     assert len(client.submit('g.V()').all().result()) == 6