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 2020/09/14 20:42:22 UTC

[tinkerpop] branch TINKERPOP-2296 created (now 4bc4d85)

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a change to branch TINKERPOP-2296
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.


      at 4bc4d85  TINKERPOP-2296 support per-request options in python

This branch includes the following new commits:

     new 4bc4d85  TINKERPOP-2296 support per-request options in python

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[tinkerpop] 01/01: TINKERPOP-2296 support per-request options in python

Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-2296
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 4bc4d85a02a45871e33b73da3e784265df54b299
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Mon Sep 14 16:41:44 2020 -0400

    TINKERPOP-2296 support per-request options in python
---
 CHANGELOG.asciidoc                                 |  1 +
 docs/src/reference/gremlin-variants.asciidoc       | 32 +++++++++++-
 gremlin-python/glv/GraphTraversalSource.template   | 14 ++++-
 gremlin-python/glv/generate.groovy                 |  1 +
 .../main/jython/gremlin_python/driver/client.py    |  8 +--
 .../driver/driver_remote_connection.py             | 16 +++++-
 .../gremlin_python/process/graph_traversal.py      | 17 ++++--
 .../jython/gremlin_python/process/strategies.py    | 60 ++++++++++++----------
 .../tests/driver/test_driver_remote_connection.py  |  8 ++-
 .../main/jython/tests/process/test_strategies.py   | 11 ++++
 10 files changed, 128 insertions(+), 40 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index a1d822d..f441616 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -29,6 +29,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Removed `Connection` from `Connection Pool` when server closes a connection with no pending requests in Java Driver.
 * Improved initialization time of Java Driver if the default serializer is replaced.
 * Deprecated `withGraph()` in favor of `withEmbedded()` on `AnonymousTraversalSource`.
+* Added support for per-request level configurations, like timeouts, in Python.
 * Fixed bug in Javascript `Translator` that wasn't handling child traversals well.
 * Implemented `AutoCloseable` on `MultiIterator`.
 * Fixed an iterator leak in `HasContainer`.
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index 934e4ae..abf6952 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -215,6 +215,10 @@ GraphTraversalSource g = traversal().withRemote(conf);
 List<Vertex> vertices = g.with(Tokens.ARGS_EVAL_TIMEOUT, 500L).V().out("knows").toList()
 ----
 
+The following options are allowed on a per-request basis in this fashion: `batchSize`, `requestId`, `userAgent` and
+`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also supported but now deprecated). Use of `Tokens`
+to reference these options is preferred.
+
 anchor:java-imports[]
 [[gremlin-java-imports]]
 === Common Imports
@@ -421,7 +425,7 @@ which will boost performance and reduce resources required on the server.
 
 There are a number of overloads to `Client.submit()` that accept a `RequestOptions` object. The `RequestOptions`
 provide a way to include options that are specific to the request made with the call to `submit()`. A good use-case for
-this feature is to set a per-request override to the `scriptEvaluationTimeout` so that it only applies to the current
+this feature is to set a per-request override to the `evaluationTimeout` so that it only applies to the current
 request.
 
 [source,java]
@@ -675,6 +679,17 @@ traversals to complete is acceptable, it might be helpful to set `pool_size` and
 See the <<python-configuration,Configuration>> section just below.  Examples where this could apply are serverless cloud functions or WSGI
 worker processes.
 
+Some connection options can also be set on individual requests made through the using `with()` step on the
+`TraversalSource`. For instance to set request timeout to 500 milliseconds:
+
+[source,python]
+----
+vertices = g.with_("evaluationTimeout", 500L).V().out("knows").toList()
+----
+
+The following options are allowed on a per-request basis in this fashion: `batchSize`, `requestId`, `userAgent` and
+`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also supported but now deprecated).
+
 anchor:python-imports[]
 [[gremlin-python-imports]]
 === Common Imports
@@ -937,6 +952,21 @@ returns a `concurrent.futures.Future` that resolves to a list when it is complet
 <9> Verify that the all results have been read and stream is closed.
 <10> Close client and underlying pool connections.
 
+==== Per Request Settings
+
+The `client.submit()` functions accept a `request_options` which expects a dictionary. The `request_options`
+provide a way to include options that are specific to the request made with the call to `submit()`. A good use-case for
+this feature is to set a per-request override to the `evaluationTimeout` so that it only applies to the current
+request.
+
+[source,java]
+----
+result_set = client.submit("[1,2,3,4]", result_options={'evaluationTimeout': 5000})
+----
+
+The following options are allowed on a per-request basis in this fashion: `batchSize`, `requestId`, `userAgent` and
+`evaluationTimeout` (formerly 'scriptEvaluationTimeout' which is also supported but now deprecated).
+
 [[gremlin-python-dsl]]
 === Domain Specific Languages
 
diff --git a/gremlin-python/glv/GraphTraversalSource.template b/gremlin-python/glv/GraphTraversalSource.template
index 27d9e15..b8a4912 100644
--- a/gremlin-python/glv/GraphTraversalSource.template
+++ b/gremlin-python/glv/GraphTraversalSource.template
@@ -21,7 +21,7 @@ import sys
 import copy
 from .traversal import Traversal
 from .traversal import TraversalStrategies
-from .strategies import VertexProgramStrategy
+from .strategies import VertexProgramStrategy, OptionsStrategy
 from .traversal import Bytecode
 from ..driver.remote_connection import RemoteStrategy
 from .. import statics
@@ -51,6 +51,18 @@ class GraphTraversalSource(object):
         source.bytecode.add_source("<%= toJava.call(method) %>", *args)
         return source
 <% } %>
+    def with_(self, *args):
+        source = self.get_graph_traversal_source()
+        options_strategy = next((x for x in source.bytecode.source_instructions
+                                if x[0] == "withStrategies" and type(x[1]) is OptionsStrategy), None)
+        if options_strategy is None:
+            options_strategy = OptionsStrategy({args[0]: args[1]})
+            source = self.withStrategies(options_strategy)
+        else:
+            options_strategy[1].configuration[args[0]] = args[1]
+
+        return source
+
     def withRemote(self, remote_connection):
         source = self.get_graph_traversal_source()
         source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
diff --git a/gremlin-python/glv/generate.groovy b/gremlin-python/glv/generate.groovy
index 5011a40..214eb2f 100644
--- a/gremlin-python/glv/generate.groovy
+++ b/gremlin-python/glv/generate.groovy
@@ -90,6 +90,7 @@ def binding = ["enums": CoreImports.getClassImports()
                        findAll { GraphTraversalSource.class.equals(it.returnType) }.
                        findAll {
                            !it.name.equals("clone") &&
+                                   !it.name.equals(TraversalSource.Symbols.with) &&
                                    !it.name.equals(TraversalSource.Symbols.withRemote) &&
                                    !it.name.equals(TraversalSource.Symbols.withComputer)
                        }.
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 f43a054..2885e32 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/client.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/client.py
@@ -123,10 +123,10 @@ class Client:
             self._transport_factory, self._executor, self._pool,
             headers=self._headers)
 
-    def submit(self, message, bindings=None):
-        return self.submitAsync(message, bindings=bindings).result()
+    def submit(self, message, bindings=None, request_options=None):
+        return self.submitAsync(message, bindings=bindings, request_options=request_options).result()
 
-    def submitAsync(self, message, bindings=None):
+    def submitAsync(self, message, bindings=None, request_options=None):
         if isinstance(message, traversal.Bytecode):
             message = request.RequestMessage(
                 processor='traversal', op='bytecode',
@@ -143,4 +143,6 @@ class Client:
                 message = message._replace(processor='session')
                 message.args.update({'session': self._session})
         conn = self._pool.get(True)
+        if request_options:
+            message.args.update(request_options)
         return conn.write(message)
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 3b6a760..067f65b 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
@@ -21,6 +21,7 @@ from concurrent.futures import Future
 from gremlin_python.driver import client, serializer
 from gremlin_python.driver.remote_connection import (
     RemoteConnection, RemoteTraversal, RemoteTraversalSideEffects)
+from gremlin_python.process.strategies import OptionsStrategy
 
 __author__ = 'David M. Brown (davebshow@gmail.com)'
 
@@ -52,7 +53,7 @@ class DriverRemoteConnection(RemoteConnection):
         self._client.close()
 
     def submit(self, bytecode):
-        result_set = self._client.submit(bytecode)
+        result_set = self._client.submit(bytecode, request_options=self._extract_request_options(bytecode))
         results = result_set.all().result()
         side_effects = RemoteTraversalSideEffects(result_set.request_id, self._client,
                                                   result_set.status_attributes)
@@ -60,7 +61,7 @@ class DriverRemoteConnection(RemoteConnection):
 
     def submitAsync(self, bytecode):
         future = Future()
-        future_result_set = self._client.submitAsync(bytecode)
+        future_result_set = self._client.submitAsync(bytecode, request_options=self._extract_request_options(bytecode))
 
         def cb(f):
             try:
@@ -74,3 +75,14 @@ class DriverRemoteConnection(RemoteConnection):
 
         future_result_set.add_done_callback(cb)
         return future
+
+    @staticmethod
+    def _extract_request_options(bytecode):
+        options_strategy = next((x for x in bytecode.source_instructions
+                                 if x[0] == "withStrategies" and type(x[1]) is OptionsStrategy), None)
+        request_options = None
+        if options_strategy:
+            allowed_keys = ['evaluationTimeout', 'scriptEvaluationTimeout', 'batchSize', 'requestId', 'userAgent']
+            request_options = {allowed: options_strategy[1].configuration[allowed] for allowed in allowed_keys
+                               if allowed in options_strategy[1].configuration}
+        return request_options
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
index d47301b..edb10ac 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
@@ -21,7 +21,7 @@ import sys
 import copy
 from .traversal import Traversal
 from .traversal import TraversalStrategies
-from .strategies import VertexProgramStrategy
+from .strategies import VertexProgramStrategy, OptionsStrategy
 from .traversal import Bytecode
 from ..driver.remote_connection import RemoteStrategy
 from .. import statics
@@ -71,14 +71,21 @@ class GraphTraversalSource(object):
         source.bytecode.add_source("withStrategies", *args)
         return source
 
-    def with_(self, *args):
+    def withoutStrategies(self, *args):
         source = self.get_graph_traversal_source()
-        source.bytecode.add_source("with", *args)
+        source.bytecode.add_source("withoutStrategies", *args)
         return source
 
-    def withoutStrategies(self, *args):
+    def with_(self, *args):
         source = self.get_graph_traversal_source()
-        source.bytecode.add_source("withoutStrategies", *args)
+        options_strategy = next((x for x in source.bytecode.source_instructions
+                                if x[0] == "withStrategies" and type(x[1]) is OptionsStrategy), None)
+        if options_strategy is None:
+            options_strategy = OptionsStrategy({args[0]: args[1]})
+            source = self.withStrategies(options_strategy)
+        else:
+            options_strategy[1].configuration[args[0]] = args[1]
+
         return source
 
     def withRemote(self, remote_connection):
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
index 8988b79..6d97b27 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
@@ -21,38 +21,45 @@ __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
 
 from gremlin_python.process.traversal import TraversalStrategy
 
+base_namespace = 'org.apache.tinkerpop.gremlin.process.traversal.strategy.'
+decoration_namespace = base_namespace + 'decoration.'
+finalization_namespace = base_namespace + 'finalization.'
+optimization_namespace = base_namespace + 'optimization.'
+verification_namespace = base_namespace + 'verification.'
+computer_decoration_namespace = 'org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.'
 
 #########################
 # DECORATION STRATEGIES #
 #########################
 
+
 class ConnectiveStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy")
+        TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'ConnectiveStrategy')
 
 
 class ElementIdStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy")
+        TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'ElementIdStrategy')
 
 
 # EventStrategy doesn't make sense outside JVM traversal machine
 
 class HaltedTraverserStrategy(TraversalStrategy):
     def __init__(self, halted_traverser_factory=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy")
+        TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'HaltedTraverserStrategy')
         if halted_traverser_factory is not None:
             self.configuration["haltedTraverserFactory"] = halted_traverser_factory
 
 
 class OptionsStrategy(TraversalStrategy):
     def __init__(self, options=None):
-        TraversalStrategy.__init__(self, configuration=options, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy")
+        TraversalStrategy.__init__(self, configuration=options, fqcn=decoration_namespace + 'OptionsStrategy')
 
 
 class PartitionStrategy(TraversalStrategy):
     def __init__(self, partition_key=None, write_partition=None, read_partitions=None, include_meta_properties=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy")
+        TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'PartitionStrategy')
         if partition_key is not None:
             self.configuration["partitionKey"] = partition_key
         if write_partition is not None:
@@ -66,7 +73,7 @@ class PartitionStrategy(TraversalStrategy):
 class SubgraphStrategy(TraversalStrategy):
 
     def __init__(self, vertices=None, edges=None, vertex_properties=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy")
+        TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'SubgraphStrategy')
         if vertices is not None:
             self.configuration["vertices"] = vertices
         if edges is not None:
@@ -78,7 +85,7 @@ class SubgraphStrategy(TraversalStrategy):
 class VertexProgramStrategy(TraversalStrategy):
     def __init__(self, graph_computer=None, workers=None, persist=None, result=None, vertices=None, edges=None,
                  configuration=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy")
+        TraversalStrategy.__init__(self, fqcn=computer_decoration_namespace + 'VertexProgramStrategy')
         if graph_computer is not None:
             self.configuration["graphComputer"] = graph_computer
         if workers is not None:
@@ -101,7 +108,7 @@ class VertexProgramStrategy(TraversalStrategy):
 
 class MatchAlgorithmStrategy(TraversalStrategy):
     def __init__(self, match_algorithm=None):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy")
+        TraversalStrategy.__init__(self, fqcn=finalization_namespace + 'MatchAlgorithmStrategy')
         if match_algorithm is not None:
             self.configuration["matchAlgorithm"] = match_algorithm
 
@@ -112,73 +119,73 @@ class MatchAlgorithmStrategy(TraversalStrategy):
 
 class AdjacentToIncidentStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'AdjacentToIncidentStrategy')
 
 
 class FilterRankingStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'FilterRankingStrategy')
 
 
 class IdentityRemovalStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'IdentityRemovalStrategy')
 
 
 class IncidentToAdjacentStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'IncidentToAdjacentStrategy')
 
 
 class InlineFilterStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.InlineFilterStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'InlineFilterStrategy')
 
 
 class LazyBarrierStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.LazyBarrierStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'LazyBarrierStrategy')
 
 
 class MatchPredicateStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'MatchPredicateStrategy')
 
 
 class OrderLimitStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'OrderLimitStrategy')
 
 
 class PathProcessorStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'PathProcessorStrategy')
 
 
 class PathRetractionStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'PathRetractionStrategy')
 
 
 class CountStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'CountStrategy')
 
 
 class RepeatUnrollStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'RepeatUnrollStrategy')
 
 
 class GraphFilterStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'GraphFilterStrategy')
 
 
 
 class EarlyLimitStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy")
+        TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'EarlyLimitStrategy')
 
 ###########################
 # VERIFICATION STRATEGIES #
@@ -187,24 +194,23 @@ class EarlyLimitStrategy(TraversalStrategy):
 
 class LambdaRestrictionStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy")
-
+        TraversalStrategy.__init__(self, fqcn=verification_namespace + 'LambdaRestrictionStrategy')
 
 class ReadOnlyStrategy(TraversalStrategy):
     def __init__(self):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy")
+        TraversalStrategy.__init__(self, fqcn=verification_namespace + 'ReadOnlyStrategy')
 
 
 class EdgeLabelVerificationStrategy(TraversalStrategy):
     def __init__(self, log_warning=False, throw_exception=False):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy")
+        TraversalStrategy.__init__(self, fqcn=verification_namespace + 'EdgeLabelVerificationStrategy')
         self.configuration["logWarning"] = log_warning
         self.configuration["throwException"] = throw_exception
 
 
 class ReservedKeysVerificationStrategy(TraversalStrategy):
     def __init__(self, log_warning=False, throw_exception=False, keys=["id", "label"]):
-        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy")
+        TraversalStrategy.__init__(self, fqcn=verification_namespace + 'ReservedKeysVerificationStrategy')
         self.configuration["logWarning"] = log_warning
         self.configuration["throwException"] = throw_exception
         self.configuration["keys"] = keys
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
index 44d8dea..bc1d405 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
@@ -100,7 +100,6 @@ class TestDriverRemoteConnection(object):
         results = g.V().has('person', 'age', Bindings.of('x', lt(30))).count().next()
         assert 2 == results
 
-
     def test_lambda_traversals(self, remote_connection):
         statics.load_statics(globals())
         assert "remoteconnection[ws://localhost:45940/gremlin,gmodern]" == str(remote_connection)
@@ -194,6 +193,13 @@ class TestDriverRemoteConnection(object):
             assert False
         except GremlinServerError as gse:
             assert gse.status_code == 500
+        #
+        g = traversal().withRemote(remote_connection).with_("x", True).with_('evaluationTimeout', 10)
+        try:
+            g.inject(1).sideEffect(lambda: ("Thread.sleep(5000)", "gremlin-groovy")).iterate()
+            assert False
+        except GremlinServerError as gse:
+            assert gse.status_code == 598
 
     def test_side_effects(self, remote_connection):
         statics.load_statics(globals())
diff --git a/gremlin-python/src/main/jython/tests/process/test_strategies.py b/gremlin-python/src/main/jython/tests/process/test_strategies.py
index 4b03f8a..27394cc 100644
--- a/gremlin-python/src/main/jython/tests/process/test_strategies.py
+++ b/gremlin-python/src/main/jython/tests/process/test_strategies.py
@@ -77,6 +77,17 @@ class TestTraversalStrategies(object):
         assert LazyBarrierStrategy() == bytecode.source_instructions[1][2]
         assert 1 == len(bytecode.step_instructions)
         assert "V" == bytecode.step_instructions[0][0]
+        ###
+        g = Graph().traversal()
+        bytecode = g.with_("x", "test").with_("y", True).bytecode
+        assert 1 == len(bytecode.source_instructions)
+        assert 2 == len(bytecode.source_instructions[0])
+        assert "withStrategies" == bytecode.source_instructions[0][0]
+        assert OptionsStrategy() == bytecode.source_instructions[0][1]
+        strategy = bytecode.source_instructions[0][1]
+        assert 2 == len(strategy.configuration)
+        assert "test" == strategy.configuration["x"]
+        assert strategy.configuration["y"]
 
     def test_configurable(self):
         g = Graph().traversal()