tinkerpop-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From spmalle...@apache.org
Subject [tinkerpop] 02/02: Merge branch '3.4-dev'
Date Fri, 25 Sep 2020 15:41:24 GMT
This is an automated email from the ASF dual-hosted git repository.

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

commit 236e7d792b3133fb5135934e59cab578c5274c0d
Merge: b420ff5 bcc0f24
Author: Stephen Mallette <stepmall@amazon.com>
AuthorDate: Fri Sep 25 11:40:14 2020 -0400

    Merge branch '3.4-dev'

 CHANGELOG.asciidoc                                 |  1 +
 docs/src/reference/gremlin-variants.asciidoc       | 30 ++++++++++
 .../main/python/gremlin_python/driver/client.py    |  8 ++-
 .../driver/driver_remote_connection.py             | 16 +++++-
 .../gremlin_python/process/graph_traversal.py      | 19 +++++--
 .../python/gremlin_python/process/strategies.py    | 64 +++++++++++++---------
 .../tests/driver/test_driver_remote_connection.py  |  7 +++
 .../main/python/tests/process/test_strategies.py   | 11 ++++
 8 files changed, 120 insertions(+), 36 deletions(-)

diff --cc gremlin-python/src/main/python/gremlin_python/driver/client.py
index ff8dddb,0000000..4e2d026
mode 100644,000000..100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/client.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/client.py
@@@ -1,147 -1,0 +1,149 @@@
 +#
 +# 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.
 +#
 +from concurrent.futures import ThreadPoolExecutor
 +
 +from six.moves import queue
 +
 +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
 +try:
 +    from multiprocessing import cpu_count
 +except ImportError:
 +    # some platforms don't have multiprocessing
 +    def cpu_count():
 +        return None
 +
 +__author__ = 'David M. Brown (davebshow@gmail.com)'
 +
 +
 +class Client:
 +
 +    def __init__(self, url, traversal_source, protocol_factory=None,
 +                 transport_factory=None, pool_size=None, max_workers=None,
 +                 message_serializer=None, username="", password="",
 +                 kerberized_service="", headers=None, session=""):
 +        self._url = url
 +        self._headers = headers
 +        self._traversal_source = traversal_source
 +        if message_serializer is None:
 +            message_serializer = serializer.GraphSONSerializersV3d0()
 +        self._message_serializer = message_serializer
 +        self._username = username
 +        self._password = password
 +        self._session = session
 +        self._sessionEnabled = (session != "")
 +        if transport_factory is None:
 +            try:
 +                from gremlin_python.driver.tornado.transport import (
 +                    TornadoTransport)
 +            except ImportError:
 +                raise Exception("Please install Tornado or pass"
 +                                "custom transport factory")
 +            else:
 +                transport_factory = lambda: TornadoTransport()
 +        self._transport_factory = transport_factory
 +        if protocol_factory is None:
 +            protocol_factory = lambda: protocol.GremlinServerWSProtocol(
 +                self._message_serializer,
 +                username=self._username,
 +                password=self._password,
 +                kerberized_service=kerberized_service)
 +        self._protocol_factory = protocol_factory
 +        if self._sessionEnabled:
 +            if pool_size is None:
 +                pool_size = 1
 +            elif pool_size != 1:
 +                raise Exception("PoolSize must be 1 on session mode!")
 +        if pool_size is None:
 +            pool_size = 4
 +        self._pool_size = pool_size
 +        # This is until concurrent.futures backport 3.1.0 release
 +        if max_workers is None:
 +            # If your application is overlapping Gremlin I/O on multiple threads
 +            # consider passing kwarg max_workers = (cpu_count() or 1) * 5
 +            max_workers = pool_size
 +        self._executor = ThreadPoolExecutor(max_workers=max_workers)
 +        # Threadsafe queue
 +        self._pool = queue.Queue()
 +        self._fill_pool()
 +
 +    @property
 +    def available_pool_size(self):
 +        return self._pool.qsize()
 +
 +    @property
 +    def executor(self):
 +        return self._executor
 +
 +    @property
 +    def traversal_source(self):
 +        return self._traversal_source
 +
 +    def _fill_pool(self):
 +        for i in range(self._pool_size):
 +            conn = self._get_connection()
 +            self._pool.put_nowait(conn)
 +
 +    def close(self):
 +        if self._sessionEnabled:
 +            self._close_session()
 +        while not self._pool.empty():
 +            conn = self._pool.get(True)
 +            conn.close()
 +        self._executor.shutdown()
 +
 +    def _close_session(self):
 +        message = request.RequestMessage(
 +            processor='session', op='close',
 +            args={'session': self._session})
 +        conn = self._pool.get(True)
 +        return conn.write(message).result()
 +
 +    def _get_connection(self):
 +        protocol = self._protocol_factory()
 +        return connection.Connection(
 +            self._url, self._traversal_source, protocol,
 +            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',
 +                args={'gremlin': message,
 +                      'aliases': {'g': self._traversal_source}})
 +        elif isinstance(message, str):
 +            message = request.RequestMessage(
 +                processor='', op='eval',
 +                args={'gremlin': message,
 +                      'aliases': {'g': self._traversal_source}})
 +            if bindings:
 +                message.args.update({'bindings': bindings})
 +            if self._sessionEnabled:
 +                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 --cc gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
index 2b617b3,0000000..516ba4e
mode 100644,000000..100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
@@@ -1,73 -1,0 +1,85 @@@
 +#
 +# 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.
 +#
 +from concurrent.futures import Future
 +
 +from gremlin_python.driver import client, serializer
 +from gremlin_python.driver.remote_connection import (
 +    RemoteConnection, RemoteTraversal)
++from gremlin_python.process.strategies import OptionsStrategy
 +
 +__author__ = 'David M. Brown (davebshow@gmail.com)'
 +
 +
 +class DriverRemoteConnection(RemoteConnection):
 +
 +    def __init__(self, url, traversal_source, protocol_factory=None,
 +                 transport_factory=None, pool_size=None, max_workers=None,
 +                 username="", password="", kerberized_service='',
 +                 message_serializer=None, graphson_reader=None,
 +                 graphson_writer=None, headers=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,
 +                                     kerberized_service=kerberized_service,
 +                                     headers=headers)
 +        self._url = self._client._url
 +        self._traversal_source = self._client._traversal_source
 +
 +    def close(self):
 +        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()
 +        return RemoteTraversal(iter(results))
 +
 +    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:
 +                result_set = f.result()
 +                results = result_set.all().result()
 +                future.set_result(RemoteTraversal(iter(results)))
 +            except Exception as e:
 +                future.set_exception(e)
 +
 +        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 --cc gremlin-python/src/main/python/gremlin_python/process/strategies.py
index c2ee615,0000000..465659c
mode 100644,000000..100644
--- a/gremlin-python/src/main/python/gremlin_python/process/strategies.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/strategies.py
@@@ -1,220 -1,0 +1,232 @@@
 +#
 +# 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.
 +#
 +
 +__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:
 +            self.configuration["writePartition"] = write_partition
 +        if write_partition is not None:
 +            self.configuration["readPartitions"] = read_partitions
 +        if include_meta_properties is not None:
 +            self.configuration["includeMetaProperties"] = include_meta_properties
 +
 +
 +class SeedStrategy(TraversalStrategy):
 +    def __init__(self, seed):
 +        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy")
 +        self.configuration["seed"] = seed
 +
 +
 +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:
 +            self.configuration["edges"] = edges
 +        if vertex_properties is not None:
 +            self.configuration["vertexProperties"] = vertex_properties
 +
 +
 +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:
 +            self.configuration["workers"] = workers
 +        if persist is not None:
 +            self.configuration["persist"] = persist
 +        if result is not None:
 +            self.configuration["result"] = result
 +        if vertices is not None:
 +            self.configuration["vertices"] = vertices
 +        if edges is not None:
 +            self.configuration["edges"] = edges
 +        if configuration is not None:
 +            self.configuration.update(configuration)
 +
 +
 +###########################
 +# FINALIZATION STRATEGIES #
 +###########################
 +
 +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
 +
 +
 +###########################
 +# OPTIMIZATION STRATEGIES #
 +###########################
 +
 +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 ByModulatorOptimizationStrategy(TraversalStrategy):
 +    def __init__(self):
 +        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy")
 +
 +
 +class CountStrategy(TraversalStrategy):
 +    def __init__(self):
 +        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ByModulatorOptimizationStrategy")
 +
 +
 +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=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 #
 +###########################
 +
 +
 +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 --cc gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
index 309dbf4,0000000..b26749a
mode 100644,000000..100644
--- a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
@@@ -1,219 -1,0 +1,226 @@@
 +#
 +# 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 pytest
 +
 +from gremlin_python import statics
 +from gremlin_python.driver.protocol import GremlinServerError
 +from gremlin_python.statics import long
 +from gremlin_python.process.traversal import Traverser
 +from gremlin_python.process.traversal import TraversalStrategy
 +from gremlin_python.process.traversal import Bindings
 +from gremlin_python.process.traversal import P, Order, T
 +from gremlin_python.process.graph_traversal import __
 +from gremlin_python.process.anonymous_traversal import traversal
 +from gremlin_python.structure.graph import Vertex
 +from gremlin_python.process.strategies import SubgraphStrategy, ReservedKeysVerificationStrategy,
SeedStrategy
 +from gremlin_python.structure.io.util import HashableDict
 +from gremlin_python.driver.serializer import GraphSONSerializersV2d0
 +
 +__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
 +
 +
 +class TestDriverRemoteConnection(object):
 +    def test_traversals(self, remote_connection):
 +        statics.load_statics(globals())
 +        g = traversal().withRemote(remote_connection)
 +
 +        assert long(6) == g.V().count().toList()[0]
 +        # #
 +        assert Vertex(1) == g.V(1).next()
 +        assert 1 == g.V(1).id().next()
 +        assert Traverser(Vertex(1)) == g.V(1).nextTraverser()
 +        assert 1 == len(g.V(1).toList())
 +        assert isinstance(g.V(1).toList(), list)
 +        results = g.V().repeat(out()).times(2).name
 +        results = results.toList()
 +        assert 2 == len(results)
 +        assert "lop" in results
 +        assert "ripple" in results
 +        # #
 +        assert 10 == g.V().repeat(both()).times(5)[0:10].count().next()
 +        assert 1 == g.V().repeat(both()).times(5)[0:1].count().next()
 +        assert 0 == g.V().repeat(both()).times(5)[0:0].count().next()
 +        assert 4 == g.V()[2:].count().next()
 +        assert 2 == g.V()[:2].count().next()
 +        # #
 +        results = g.withSideEffect('a', ['josh', 'peter']).V(1).out('created').in_('created').values('name').where(P.within('a')).toList()
 +        assert 2 == len(results)
 +        assert 'josh' in results
 +        assert 'peter' in results
 +        # #
 +        results = g.V().out().profile().toList()
 +        assert 1 == len(results)
 +        assert 'metrics' in results[0]
 +        assert 'dur' in results[0]
 +        # #
 +        results = g.V().has('name', 'peter').as_('a').out('created').as_('b').select('a',
'b').by(
 +            __.valueMap()).toList()
 +        assert 1 == len(results)
 +        assert 'peter' == results[0]['a']['name'][0]
 +        assert 35 == results[0]['a']['age'][0]
 +        assert 'lop' == results[0]['b']['name'][0]
 +        assert 'java' == results[0]['b']['lang'][0]
 +        assert 2 == len(results[0]['a'])
 +        assert 2 == len(results[0]['b'])
 +        # #
 +        results = g.V(1).inject(g.V(2).next()).values('name').toList()
 +        assert 2 == len(results)
 +        assert 'marko' in results
 +        assert 'vadas' in results
 +        # #
 +        results = g.V().has('person', 'name', 'marko').map(lambda: ("it.get().value('name')",
"gremlin-groovy")).toList()
 +        assert 1 == len(results)
 +        assert 'marko' in results
 +        # #
 +        # this test just validates that the underscored versions of steps conflicting with
Gremlin work
 +        # properly and can be removed when the old steps are removed - TINKERPOP-2272
 +        results = g.V().filter_(__.values('age').sum_().and_(
 +            __.max_().is_(gt(0)), __.min_().is_(gt(0)))).range_(0, 1).id_().next()
 +        assert 1 == results
 +        # #
 +        # test binding in P
 +        results = g.V().has('person', 'age', Bindings.of('x', lt(30))).count().next()
 +        assert 2 == results
 +        # #
 +        # test dict keys which can only work on GraphBinary and GraphSON3 which include
specific serialization
 +        # types for dict
 +        if not isinstance(remote_connection._client._message_serializer, GraphSONSerializersV2d0):
 +            results = g.V().has('person', 'name', 'marko').elementMap("name").groupCount().next()
 +            assert {HashableDict.of({T.id: 1, T.label: 'person', 'name': 'marko'}): 1} ==
results
 +
 +    def test_lambda_traversals(self, remote_connection):
 +        statics.load_statics(globals())
 +        assert "remoteconnection[ws://localhost:45940/gremlin,gmodern]" == str(remote_connection)
 +        g = traversal().withRemote(remote_connection)
 +
 +        assert 24.0 == g.withSack(1.0, lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum().next()
 +        assert 24.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x ->
x + 1", "gremlin-groovy")).V().both().sack().sum().next()
 +
 +        assert 48.0 == g.withSack(1.0, lambda: ("x, y ->  x + y + 1", "gremlin-groovy")).V().both().sack().sum().next()
 +        assert 48.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x, y ->
 x + y + 1", "gremlin-groovy")).V().both().sack().sum().next()
 +
 +    def test_iteration(self, remote_connection):
 +        statics.load_statics(globals())
 +        g = traversal().withRemote(remote_connection)
 +
 +        t = g.V().count()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert 6 == t.next()
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +
 +        t = g.V().has('name', P.within('marko', 'peter')).values('name').order()
 +        assert "marko" == t.next()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert t.hasNext()
 +        assert "peter" == t.next()
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +        assert not(t.hasNext())
 +
 +        try:
 +            t.next()
 +            assert False
 +        except StopIteration:
 +            assert True
 +
 +    def test_strategies(self, remote_connection):
 +        statics.load_statics(globals())
 +        g = traversal().withRemote(remote_connection). \
 +            withStrategies(TraversalStrategy("SubgraphStrategy",
 +                                             {"vertices": __.hasLabel("person"),
 +                                              "edges": __.hasLabel("created")},
 +                                              "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy"))
 +        assert 4 == g.V().count().next()
 +        assert 0 == g.E().count().next()
 +        assert 1 == g.V().label().dedup().count().next()
 +        assert 4 == g.V().filter(lambda: ("x -> true", "gremlin-groovy")).count().next()
 +        assert "person" == g.V().label().dedup().next()
 +        #
 +        g = traversal().withRemote(remote_connection). \
 +            withStrategies(SubgraphStrategy(vertices=__.hasLabel("person"), edges=__.hasLabel("created")))
 +        assert 4 == g.V().count().next()
 +        assert 0 == g.E().count().next()
 +        assert 1 == g.V().label().dedup().count().next()
 +        assert "person" == g.V().label().dedup().next()
 +        #
 +        g = traversal().withRemote(remote_connection). \
 +            withStrategies(SubgraphStrategy(edges=__.hasLabel("created")))
 +        assert 6 == g.V().count().next()
 +        assert 4 == g.E().count().next()
 +        assert 1 == g.E().label().dedup().count().next()
 +        assert "created" == g.E().label().dedup().next()
 +        #
 +        g = g.withoutStrategies(SubgraphStrategy). \
 +            withComputer(vertices=__.has("name", "marko"), edges=__.limit(0))
 +        assert 1 == g.V().count().next()
 +        assert 0 == g.E().count().next()
 +        assert "person" == g.V().label().next()
 +        assert "marko" == g.V().name.next()
 +        #
 +        g = traversal().withRemote(remote_connection).withComputer()
 +        assert 6 == g.V().count().next()
 +        assert 6 == g.E().count().next()
 +        #
 +        g = traversal().withRemote(remote_connection).withStrategies(SeedStrategy(12345))
 +        shuffledResult = g.V().values("name").order().by(Order.shuffle).toList()
 +        assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
 +        assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
 +        assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
 +        #
 +        g = traversal().withRemote(remote_connection). \
 +            withStrategies(ReservedKeysVerificationStrategy(throw_exception=True))
 +        try:
 +            g.addV("person").property("id", "please-don't-use-id").iterate()
 +            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_clone(self, remote_connection):
 +        g = traversal().withRemote(remote_connection)
 +        t = g.V().count()
 +        assert 6 == t.next()
 +        assert 6 == t.clone().next()
 +        assert 6 == t.clone().next()
 +
 +    def test_authenticated(self, remote_connection_authenticated):
 +        statics.load_statics(globals())
 +        g = traversal().withRemote(remote_connection_authenticated)
 +
 +        assert long(6) == g.V().count().toList()[0]


Mime
View raw message