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:23 UTC
[tinkerpop] 01/01: TINKERPOP-2296 support per-request options in
python
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()