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 2019/09/26 17:03:18 UTC

[tinkerpop] 02/04: Merge branch 'tp33' into tp34

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 a8751c3fe416acca2248a9c957d1beec07df855c
Merge: 5803c26 13b60a6
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Thu Sep 26 11:48:09 2019 -0400

    Merge branch 'tp33' into tp34

 CHANGELOG.asciidoc                                 |   5 +-
 docs/src/upgrade/release-3.3.x.asciidoc            |  16 +++
 .../AbstractWarningVerificationStrategy.java       | 111 +++++++++++++++++++++
 .../EdgeLabelVerificationStrategy.java             |  69 ++-----------
 .../ReservedKeysVerificationStrategy.java          | 106 ++++++++++++++++++++
 .../EdgeLabelVerificationStrategyTest.java         |   6 +-
 ...a => ReservedKeysVerificationStrategyTest.java} |  38 ++++---
 .../Verification/EdgeLabelVerificationStrategy.cs  |  49 +++++++++
 .../ReservedKeysVerificationStrategy.cs            |  55 ++++++++++
 .../GraphTraversalSourceTests.cs                   |   2 +
 .../main/jython/gremlin_python/driver/protocol.py  |   3 +-
 .../jython/gremlin_python/process/strategies.py    |  18 +++-
 .../tests/driver/test_driver_remote_connection.py  |  15 ++-
 .../tinkergraph/structure/TinkerGraphTest.java     |  31 +++++-
 14 files changed, 437 insertions(+), 87 deletions(-)

diff --cc gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
index 0000000,1a5404a..8fe6424
mode 000000,100644..100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
@@@ -1,0 -1,106 +1,106 @@@
+ /*
+  * 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.
+  */
+ package org.apache.tinkerpop.gremlin.process.traversal.strategy.verification;
+ 
+ import org.apache.commons.configuration.Configuration;
 -import org.apache.tinkerpop.gremlin.process.traversal.Parameterizing;
+ import org.apache.tinkerpop.gremlin.process.traversal.Step;
+ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
++import org.apache.tinkerpop.gremlin.process.traversal.step.Parameterizing;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStartStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+ 
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.HashSet;
+ import java.util.Set;
+ import java.util.stream.Collectors;
+ 
+ /**
+  * This verification strategy detects property keys that should not be used by the traversal. A term may be reserved
+  * by a particular graph implementation or as a convention given best practices.
+  *
+  * @author Stephen Mallette (http://stephen.genoprime.com)
+  *  * @example <pre>
+  *  * __.addV("person").property("id", 123)           // throws an IllegalStateException
+  *  * __.addE("knows").property("label", "green")     // throws an IllegalStateException
+  *  * </pre>
+  */
+ public class ReservedKeysVerificationStrategy extends AbstractWarningVerificationStrategy {
+ 
+     private static final String KEYS = "keys";
+     private static final Set<String> DEFAULT_RESERVED_KEYS = new HashSet<>(Arrays.asList("id", "label"));
+     private final Set<String> reservedKeys;
+ 
+     private ReservedKeysVerificationStrategy(final Builder builder) {
+         super(builder);
+         this.reservedKeys = builder.reservedKeys;
+     }
+ 
+     @Override
+     void verify(final Traversal.Admin<?, ?> traversal) throws VerificationException {
+         for (final Step<?, ?> step : traversal.getSteps()) {
+             if (step instanceof AddVertexStep || step instanceof AddVertexStartStep ||
+                 step instanceof AddEdgeStartStep || step instanceof AddEdgeStep ||
+                 step instanceof AddPropertyStep) {
+                 final Parameterizing propertySettingStep = (Parameterizing) step;
+                 final Parameters params = propertySettingStep.getParameters();
+                 for (String key : reservedKeys) {
+                     if (params.contains(key)) {
+                         final String msg = String.format(
+                                 "The provided traversal contains a %s that is setting a property key to a reserved" +
+                                         " word: %s", propertySettingStep.getClass().getSimpleName(), key);
+                         throw new VerificationException(msg, traversal);
+                     }
+                 }
+             }
+         }
+     }
+ 
+     public static ReservedKeysVerificationStrategy create(final Configuration configuration) {
+         return build()
+                 .reservedKeys(configuration.getList(KEYS, new ArrayList<>(DEFAULT_RESERVED_KEYS)).
+                         stream().map(Object::toString).collect(Collectors.toSet()))
+                 .throwException(configuration.getBoolean(THROW_EXCEPTION, false))
+                 .logWarning(configuration.getBoolean(LOG_WARNING, false)).create();
+     }
+ 
+     public static ReservedKeysVerificationStrategy.Builder build() {
+         return new ReservedKeysVerificationStrategy.Builder();
+     }
+ 
+     public final static class Builder extends AbstractWarningVerificationStrategy.Builder<ReservedKeysVerificationStrategy, Builder> {
+         private Set<String> reservedKeys = DEFAULT_RESERVED_KEYS;
+ 
+         private Builder() {}
+ 
+         public Builder reservedKeys(final Set<String> keys) {
+             reservedKeys = keys;
+             return this;
+         }
+ 
+         @Override
+         public ReservedKeysVerificationStrategy create() {
+             return new ReservedKeysVerificationStrategy(this);
+         }
+     }
+ }
diff --cc gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
index bb3ab24,476b3ee..cd5e50a
--- a/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
@@@ -76,12 -72,11 +77,12 @@@ class GremlinServerWSProtocol(AbstractB
      def data_received(self, message, results_dict):
          # if Gremlin Server cuts off then we get a None for the message
          if message is None:
 -            raise GremlinServerError(500, "500: Server disconnected - please try to reconnect")
 +            raise GremlinServerError({'code': 500, 
 +                                      'message': 'Server disconnected - please try to reconnect', 'attributes': {}})
  
 -        message = self._message_serializer.deserialize_message(json.loads(message.decode('utf-8')))
 +        message = self._message_serializer.deserialize_message(message)
          request_id = message['requestId']
-         result_set = results_dict[request_id]
+         result_set = results_dict[request_id] if request_id in results_dict else ResultSet(None, None)
          status_code = message['status']['code']
          aggregate_to = message['result']['meta'].get('aggregateTo', 'list')
          data = message['result']['data']
diff --cc gremlin-python/src/main/jython/gremlin_python/process/strategies.py
index 0f8e876,6cc1091..b8c0677
--- a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
@@@ -64,9 -59,8 +64,9 @@@ class PartitionStrategy(TraversalStrate
  
  
  class SubgraphStrategy(TraversalStrategy):
-     
++
      def __init__(self, vertices=None, edges=None, vertex_properties=None):
 -        TraversalStrategy.__init__(self)
 +        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy")
          if vertices is not None:
              self.configuration["vertices"] = vertices
          if edges is not None:
@@@ -172,12 -166,12 +172,13 @@@ class RepeatUnrollStrategy(TraversalStr
  
  class GraphFilterStrategy(TraversalStrategy):
      def __init__(self):
 -        TraversalStrategy.__init__(self)
 +        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy")
 +
  
+ 
  class EarlyLimitStrategy(TraversalStrategy):
      def __init__(self):
 -        TraversalStrategy.__init__(self)
 +        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy")
  
  ###########################
  # VERIFICATION STRATEGIES #
@@@ -191,4 -185,19 +192,19 @@@ class LambdaRestrictionStrategy(Travers
  
  class ReadOnlyStrategy(TraversalStrategy):
      def __init__(self):
 -        TraversalStrategy.__init__(self)
 +        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy")
+ 
+ 
+ class EdgeLabelVerificationStrategy(TraversalStrategy):
+     def __init__(self, log_warning=False, throw_exception=False):
 -        TraversalStrategy.__init__(self)
++        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.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)
++        TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy")
+         self.configuration["logWarning"] = log_warning
+         self.configuration["throwException"] = throw_exception
+         self.configuration["keys"] = keys
diff --cc gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
index 52c272b,7e9add6..174fbc6
--- 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
@@@ -180,6 -179,16 +181,18 @@@ class TestDriverRemoteConnection(object
          g = traversal().withRemote(remote_connection).withComputer()
          assert 6 == g.V().count().next()
          assert 6 == g.E().count().next()
+         #
+         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 KeyError as gse:
++        except GremlinServerError as gse:
++            assert gse.status_code == 500
++        except KeyError as ke:
+             # gross we need to fix this: https://issues.apache.org/jira/browse/TINKERPOP-2297
+             # would prefer to assert a GremlinServerError status code
+             assert True
  
      def test_side_effects(self, remote_connection):
          statics.load_statics(globals())