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/19 22:27:21 UTC

[tinkerpop] branch TINKERPOP-2280 updated (5ad7f37 -> 1d4dcb0)

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

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


    omit 5ad7f37  TINKERPOP-2280 Changed toString of T
     add b9f010f  Minor changelog fixup
     add ef6e951  Postpone the timing of transport creation to `connection.write`
     add d998dbf  Merge branch 'pr-1177' into tp33
     add 7625874  Added js/.net docs to release announcement email template CTR
     add 74e0644  Use traversal() AnonymousTraversalSource in archetype CTR
     add 5014138  fix GraphStep.ids null bug
     add ba562d1  Updated CHANGELOG CTR
     add 4e9639f  Use ip address instead of hostname for connection
     add 25bb663  Merge branch 'pr-1182' into tp33
     add 4790fea  Updated CHANGELOG CTR
     add 91f0265  Isolate PowerMock to gremlin-driver.
     add 20fcff7  Code formatting CTR
     add 12a8bdf  TINKERPOP-2291 Added GraphSON support for deserialization of TraversalExplanation
     add dd14552  Merge branch 'TINKERPOP-2291' into tp33
     add 29e6131  TINKERPOP-2046 Gremlin-Python: Add support for custom request headers in WebSocket request
     add 5ab245c  Updated changelog CTR
     add 6555210  TINKERPOP-2159 Fixed multi-valued property handling in EventStrategy / AddPropertyStep.
     add 41ddc88  TINKERPOP-2132 Trigger authentication early to avoid unauthorized responses
     add a55df6a  transport tests from branch TINKERPOP-2132
     add 52d604d  Replace TimeoutException with NoHostAvailableException
     add 761a079  Merge branch 'pr-1187' into tp33
     add a075038  Minor text fixes CTR
     add 2d5cb47  Added upgrade docs and changelog entry CTR
     add fec2522  TINKERPOP-2132 Preserved original error messaging prior to #1187
     add d7dd67f  TINKERPOP-2285 Added ResponseError in gremlin-javascript
     add 429ff28  TINKERPOP-2213 Deprecated scriptEvaluationTimeout for evaluationTimeout
     new 1d4dcb0  TINKERPOP-2280 Add ReservedKeysVerificationStrategy

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (5ad7f37)
            \
             N -- N -- N   refs/heads/TINKERPOP-2280 (1d4dcb0)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

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.


Summary of changes:
 CHANGELOG.asciidoc                                 |  21 +++-
 docs/src/dev/developer/release.asciidoc            |   2 +
 docs/src/dev/provider/index.asciidoc               |   4 +-
 docs/src/reference/gremlin-applications.asciidoc   |   8 +-
 docs/src/reference/gremlin-variants.asciidoc       |  13 ++-
 docs/src/reference/the-traversal.asciidoc          |   6 ++
 docs/src/upgrade/release-3.3.x.asciidoc            |  74 ++++++++++++++
 .../src/test/java/SocialDslTest.java               |   6 +-
 .../src/test/resources/gremlin-server.yaml         |   2 +-
 .../console/jsr223/gremlin-server-integration.yaml |   2 +-
 .../process/traversal/step/map/GraphStep.java      |  18 ++--
 .../traversal/step/sideEffect/AddPropertyStep.java |  77 +++++++++-----
 .../AbstractWarningVerificationStrategy.java       | 111 ++++++++++++++++++++
 .../EdgeLabelVerificationStrategy.java             |  69 ++-----------
 .../ReservedKeysVerificationStrategy.java          | 106 +++++++++++++++++++
 ...alExplanation.java => AbstractExplanation.java} | 104 +++++++------------
 .../traversal/util/ImmutableExplanation.java       |  80 +++++++++++++++
 .../traversal/util/TraversalExplanation.java       | 112 ++++-----------------
 .../org/apache/tinkerpop/gremlin/structure/T.java  |   5 -
 .../structure/io/graphson/GraphSONModule.java      |   2 +
 .../io/graphson/GraphSONSerializersV2d0.java       |  28 ++++++
 .../io/graphson/GraphSONSerializersV3d0.java       |  28 ++++++
 .../EdgeLabelVerificationStrategyTest.java         |   6 +-
 ...a => ReservedKeysVerificationStrategyTest.java} |  38 ++++---
 .../traversal/util/TraversalExplanationTest.java   |   8 ++
 .../graphson/GraphSONMapperEmbeddedTypeTest.java   |  11 ++
 gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs    |   6 +-
 .../Verification/EdgeLabelVerificationStrategy.cs} |  34 ++-----
 .../ReservedKeysVerificationStrategy.cs            |  55 ++++++++++
 .../Driver/MessagesTests.cs                        |   2 +-
 .../GraphTraversalSourceTests.cs                   |   2 +
 gremlin-driver/pom.xml                             |  18 ++++
 .../apache/tinkerpop/gremlin/driver/Client.java    |   5 +-
 .../apache/tinkerpop/gremlin/driver/Cluster.java   |  17 ++--
 .../tinkerpop/gremlin/driver/Connection.java       |  23 +++++
 .../tinkerpop/gremlin/driver/ConnectionPool.java   |  16 ++-
 .../apache/tinkerpop/gremlin/driver/Handler.java   |  45 +++++++--
 .../org/apache/tinkerpop/gremlin/driver/Host.java  |   3 +-
 .../apache/tinkerpop/gremlin/driver/Tokens.java    |   6 ++
 .../driver/exception/NoHostAvailableException.java |  21 ++--
 .../apache/tinkerpop/gremlin/driver/HostTest.java  |  46 ++++++++-
 .../gremlin/groovy/engine/GremlinExecutor.java     |  63 +++++++++---
 .../groovy/jsr223/GroovyCompilerGremlinPlugin.java |   2 +-
 .../gremlin/groovy/jsr223/GroovyTranslator.java    |   3 -
 .../gremlin/groovy/engine/GremlinExecutorTest.java |  71 ++++++++++++-
 .../main/javascript/gremlin-javascript/index.js    |   2 +
 .../gremlin-javascript/lib/driver/connection.js    |  12 ++-
 .../{auth/authenticator.js => response-error.js}   |  37 ++++---
 .../test/integration/remote-connection-tests.js    |   5 +
 .../main/jython/gremlin_python/driver/client.py    |   7 +-
 .../jython/gremlin_python/driver/connection.py     |  13 ++-
 .../driver/driver_remote_connection.py             |   6 +-
 .../main/jython/gremlin_python/driver/protocol.py  |   3 +-
 .../gremlin_python/driver/tornado/transport.py     |   5 +-
 .../main/jython/gremlin_python/driver/transport.py |   2 +-
 .../jython/gremlin_python/process/strategies.py    |  17 ++++
 .../tests/driver/test_driver_remote_connection.py  |  13 ++-
 gremlin-server/conf/gremlin-server-classic.yaml    |   2 +-
 gremlin-server/conf/gremlin-server-modern-py.yaml  |   2 +-
 .../conf/gremlin-server-modern-readonly.yaml       |   2 +-
 gremlin-server/conf/gremlin-server-modern.yaml     |   2 +-
 gremlin-server/conf/gremlin-server-neo4j.yaml      |   2 +-
 .../conf/gremlin-server-rest-modern.yaml           |   2 +-
 .../conf/gremlin-server-rest-secure.yaml           |   2 +-
 gremlin-server/conf/gremlin-server-secure.yaml     |   2 +-
 gremlin-server/conf/gremlin-server-spark.yaml      |   2 +-
 gremlin-server/conf/gremlin-server.yaml            |   2 +-
 .../apache/tinkerpop/gremlin/server/Settings.java  |  21 +++-
 .../server/handler/SaslAuthenticationHandler.java  |  15 +--
 .../gremlin/server/op/AbstractEvalOpProcessor.java |  12 ++-
 .../gremlin/server/op/session/Session.java         |   2 +-
 .../server/op/traversal/TraversalOpProcessor.java  |  15 +--
 .../gremlin/server/util/ServerGremlinExecutor.java |   4 +-
 .../AbstractGremlinServerIntegrationTest.java      |   8 +-
 .../gremlin/server/GremlinDriverIntegrateTest.java |  17 ++--
 .../server/GremlinServerAuthIntegrateTest.java     |  66 +++++++++++-
 .../server/GremlinServerAuthKrb5IntegrateTest.java |  75 +++++++++++++-
 .../gremlin/server/GremlinServerIntegrateTest.java |  74 +++++++++++---
 .../server/GremlinServerSessionIntegrateTest.java  |   2 +-
 ...tractGremlinServerChannelizerIntegrateTest.java |  13 ---
 .../gremlin/server/gremlin-server-integration.yaml |   2 +-
 .../traversal/step/sideEffect/TinkerGraphStep.java |   2 +-
 .../tinkergraph/structure/TinkerGraphPlayTest.java |  37 ++++---
 .../tinkergraph/structure/TinkerGraphTest.java     |  31 +++++-
 84 files changed, 1403 insertions(+), 514 deletions(-)
 create mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java
 create mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
 copy gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/{TraversalExplanation.java => AbstractExplanation.java} (51%)
 create mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ImmutableExplanation.java
 copy gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/{EdgeLabelVerificationStrategyTest.java => ReservedKeysVerificationStrategyTest.java} (77%)
 copy gremlin-dotnet/src/Gremlin.Net/{Structure/Edge.cs => Process/Traversal/Strategy/Verification/EdgeLabelVerificationStrategy.cs} (53%)
 create mode 100644 gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
 copy spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/payload/MessagePayload.java => gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/NoHostAvailableException.java (67%)
 copy gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/{auth/authenticator.js => response-error.js} (58%)


[tinkerpop] 01/01: TINKERPOP-2280 Add ReservedKeysVerificationStrategy

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

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

commit 1d4dcb06dd9c118385cacc5a60fbc9c5314ccdb5
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Thu Sep 19 18:23:40 2019 -0400

    TINKERPOP-2280 Add ReservedKeysVerificationStrategy
    
    Abstracted out a "warning" style verification strategy that ended up being used by this new strategy and EdgeLabelVerificationStrategy. If this ReservedKeysVerificationStrategy is added it will prevent the specified keys from being used in property keys. Providers can choose to implement this strategy if they have keywords they wish to prevent use of and users can of course use it as needed for their own conventions. By default, the strategy blocks use of "id" and "label" as a convention.
---
 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    |  17 ++++
 .../tests/driver/test_driver_remote_connection.py  |  13 ++-
 .../tinkergraph/structure/TinkerGraphTest.java     |  31 +++++-
 14 files changed, 435 insertions(+), 86 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index ccc4899..cc2cf7a 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -28,8 +28,11 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Fixed `TraversalExplanation` deserialization in GraphSON 2 and 3 which was not supported before in Java.
 * Added support for custom request headers in Python.
 * Deprecated `scriptEvaluationTimeout` in favor of the more generic `evaluationTimeout`.
-* Update jackson databind 2.9.9.3.
 * Bumped jackson databind 2.9.9.3.
+* Added `ReservedKeysVerificationStrategy` to allow warnings or exceptions when certain keys are used for properties.
+* Added the `AbstractWarningVerificationStrategy` base class for "warning" style `VerificationStrategy` implementations.
+* Refactored `EdgeLabelVerificationStrategy` to use `AbstractWarningVerificationStrategy`.
+* Added `EdgeLabelVerificationStrategy` to Python.
 * Fixed Java driver authentication problems when calling the driver from multiple threads.
 * Modified Java driver to use IP address rather than hostname to create connections.
 * Fixed potential for `NullPointerException` with empty identifiers in `GraphStep`.
diff --git a/docs/src/upgrade/release-3.3.x.asciidoc b/docs/src/upgrade/release-3.3.x.asciidoc
index e7dc242..02eb328 100644
--- a/docs/src/upgrade/release-3.3.x.asciidoc
+++ b/docs/src/upgrade/release-3.3.x.asciidoc
@@ -29,6 +29,22 @@ Please see the link:https://github.com/apache/tinkerpop/blob/3.3.9/CHANGELOG.asc
 
 === Upgrading for Users
 
+==== ReservedKeysVerificationStrategy
+
+`ReservedKeysVerificationStrategy` is a new `VerificationStrategy` that can be used to help prevent traversals from
+adding property keys that are protected. They may be protected as a result of the key being a reserved keyword of the
+underlying graph system or they key may simply violate some standard conventions.
+
+[source,text]
+----
+gremlin> g.withStrategies(ReservedKeysVerificationStrategy.build().throwException().create()).addV('person').property("id",123)
+The provided traversal contains a AddVertexStartStep that is setting a property key to a reserved word: id
+Type ':help' or ':h' for help.
+Display stack trace? [yN]
+----
+
+link:https://issues.apache.org/jira/browse/TINKERPOP-2280[TINKERPOP-2280]
+
 ==== Javascript ResponseError
 
 Gremlin Javascript now enables more robust error handling by way of a `ResponseError` which provides access to more
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java
new file mode 100644
index 0000000..a7c5a3a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java
@@ -0,0 +1,111 @@
+/*
+ * 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.commons.configuration.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Base {@link TraversalStrategy} class that is configurable to throw warnings or exceptions.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public abstract class AbstractWarningVerificationStrategy
+        extends AbstractTraversalStrategy<TraversalStrategy.VerificationStrategy>
+        implements TraversalStrategy.VerificationStrategy  {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractWarningVerificationStrategy.class);
+
+    protected static final String THROW_EXCEPTION = "throwException";
+    protected static final String LOG_WARNING = "logWarning";
+
+    protected final boolean throwException;
+    protected final boolean logWarning;
+
+    AbstractWarningVerificationStrategy(final Builder builder) {
+        this.throwException = builder.throwException;
+        this.logWarning = builder.logWarning;
+    }
+
+    /**
+     * Implementations should check the traversal and throw a standard {@link VerificationException} as it would if
+     * it had directly implemented {@link #apply(Traversal.Admin)}. The message provided to the exception will be
+     * used to log a warning and/or the same exception thrown if configured to do so.
+     */
+    abstract void verify(final Traversal.Admin<?, ?> traversal) throws VerificationException;
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        try {
+            verify(traversal);
+        } catch (VerificationException ve) {
+            if (logWarning)
+                LOGGER.warn(ve.getMessage());
+
+            if (throwException)
+                throw ve;
+        }
+    }
+
+    @Override
+    public Configuration getConfiguration() {
+        final Map<String, Object> m = new HashMap<>(2);
+        m.put(THROW_EXCEPTION, this.throwException);
+        m.put(LOG_WARNING, this.logWarning);
+        return new MapConfiguration(m);
+    }
+
+    public static abstract class Builder<T extends AbstractWarningVerificationStrategy, B extends Builder> {
+
+        protected boolean throwException;
+        protected boolean logWarning;
+
+        Builder() { }
+
+        public B throwException(final boolean throwException) {
+            this.throwException = throwException;
+            return (B) this;
+        }
+
+        public B throwException() {
+            return this.throwException(true);
+        }
+
+        public B logWarning(final boolean logWarning) {
+            this.logWarning = logWarning;
+            return (B) this;
+        }
+
+        public B logWarning() {
+            return this.logWarning(true);
+        }
+
+        public abstract T create();
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java
index 47a016f..ff1e835 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategy.java
@@ -46,86 +46,39 @@ import java.util.Map;
  * __.toE(IN)          // throws an IllegalStateException
  * </pre>
  */
-public final class EdgeLabelVerificationStrategy
-        extends AbstractTraversalStrategy<TraversalStrategy.VerificationStrategy>
-        implements TraversalStrategy.VerificationStrategy {
+public final class EdgeLabelVerificationStrategy extends AbstractWarningVerificationStrategy {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(EdgeLabelVerificationStrategy.class);
-
-    private static final String THROW_EXCEPTION = "throwException";
-    private static final String LOG_WARNING = "logWarning";
-
-    private final boolean throwException;
-    private final boolean logWarning;
-
-    private EdgeLabelVerificationStrategy(final boolean throwException, final boolean logWarning) {
-        this.throwException = throwException;
-        this.logWarning = logWarning;
+    private EdgeLabelVerificationStrategy(final Builder builder) {
+        super(builder);
     }
 
     @Override
-    public void apply(final Traversal.Admin<?, ?> traversal) {
+    void verify(final Traversal.Admin<?, ?> traversal) throws VerificationException {
         for (final Step<?, ?> step : traversal.getSteps()) {
             if (step instanceof VertexStep && ((VertexStep) step).getEdgeLabels().length == 0) {
                 final String msg = String.format(
                         "The provided traversal contains a vertex step without any specified edge label: %s\nAlways " +
                                 "specify edge labels which restrict traversal paths ensuring optimal performance.", step);
-                if (logWarning) {
-                    LOGGER.warn(msg);
-                }
-                if (throwException) {
-                    throw new VerificationException(msg, traversal);
-                }
+                throw new VerificationException(msg, traversal);
             }
         }
     }
 
     public static EdgeLabelVerificationStrategy create(final Configuration configuration) {
-        return new EdgeLabelVerificationStrategy(
-                configuration.getBoolean(THROW_EXCEPTION, false),
-                configuration.getBoolean(LOG_WARNING, false));
-    }
-
-    @Override
-    public Configuration getConfiguration() {
-        final Map<String, Object> m = new HashMap<>(2);
-        m.put(THROW_EXCEPTION, this.throwException);
-        m.put(LOG_WARNING, this.logWarning);
-        return new MapConfiguration(m);
+        return build().throwException(configuration.getBoolean(THROW_EXCEPTION, false))
+                        .logWarning(configuration.getBoolean(LOG_WARNING, false)).create();
     }
 
     public static EdgeLabelVerificationStrategy.Builder build() {
         return new EdgeLabelVerificationStrategy.Builder();
     }
 
-    public final static class Builder {
-
-        private boolean throwException;
-        private boolean logWarning;
-
-        private Builder() {
-        }
-
-        public EdgeLabelVerificationStrategy.Builder throwException() {
-            return this.throwException(true);
-        }
-
-        public EdgeLabelVerificationStrategy.Builder throwException(final boolean throwException) {
-            this.throwException = throwException;
-            return this;
-        }
-
-        public EdgeLabelVerificationStrategy.Builder logWarning() {
-            return this.logWarning(true);
-        }
-
-        public EdgeLabelVerificationStrategy.Builder logWarning(final boolean logWarning) {
-            this.logWarning = logWarning;
-            return this;
-        }
+    public final static class Builder extends AbstractWarningVerificationStrategy.Builder<EdgeLabelVerificationStrategy, Builder> {
+        private Builder() {}
 
+        @Override
         public EdgeLabelVerificationStrategy create() {
-            return new EdgeLabelVerificationStrategy(this.throwException, this.logWarning);
+            return new EdgeLabelVerificationStrategy(this);
         }
     }
 }
diff --git 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
new file mode 100644
index 0000000..1a5404a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java
@@ -0,0 +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.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 --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategyTest.java
index 72a8841..b9c5330 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategyTest.java
@@ -43,7 +43,7 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 /**
- * @author Daniel Kuppitz (http://gremlin.guru)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 @RunWith(Parameterized.class)
 public class EdgeLabelVerificationStrategyTest {
@@ -57,7 +57,7 @@ public class EdgeLabelVerificationStrategyTest {
 
     @Before
     public void setupForEachTest() {
-        final org.apache.log4j.Logger strategyLogger = org.apache.log4j.Logger.getLogger(EdgeLabelVerificationStrategy.class);
+        final org.apache.log4j.Logger strategyLogger = org.apache.log4j.Logger.getLogger(AbstractWarningVerificationStrategy.class);
         previousLogLevel = strategyLogger.getLevel();
         strategyLogger.setLevel(Level.WARN);
         Logger.getRootLogger().addAppender(logAppender = new TestLogAppender());
@@ -65,7 +65,7 @@ public class EdgeLabelVerificationStrategyTest {
 
     @After
     public void teardownForEachTest() {
-        final org.apache.log4j.Logger strategyLogger = org.apache.log4j.Logger.getLogger(EdgeLabelVerificationStrategy.class);
+        final org.apache.log4j.Logger strategyLogger = org.apache.log4j.Logger.getLogger(AbstractWarningVerificationStrategy.class);
         strategyLogger.setLevel(previousLogLevel);
         Logger.getRootLogger().removeAppender(logAppender);
     }
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategyTest.java
similarity index 77%
copy from gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategyTest.java
copy to gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategyTest.java
index 72a8841..f25f66d 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/EdgeLabelVerificationStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategyTest.java
@@ -25,7 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
-import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.T;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -43,13 +43,13 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 /**
- * @author Daniel Kuppitz (http://gremlin.guru)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 @RunWith(Parameterized.class)
-public class EdgeLabelVerificationStrategyTest {
+public class ReservedKeysVerificationStrategyTest {
 
     private final static Predicate<String> MSG_PREDICATE = Pattern.compile(
-            "^The provided traversal contains a vertex step without any specified edge label: VertexStep.*")
+            ".*that is setting a property key to a reserved word.*")
             .asPredicate();
 
     private TestLogAppender logAppender;
@@ -57,7 +57,7 @@ public class EdgeLabelVerificationStrategyTest {
 
     @Before
     public void setupForEachTest() {
-        final org.apache.log4j.Logger strategyLogger = org.apache.log4j.Logger.getLogger(EdgeLabelVerificationStrategy.class);
+        final Logger strategyLogger = Logger.getLogger(AbstractWarningVerificationStrategy.class);
         previousLogLevel = strategyLogger.getLevel();
         strategyLogger.setLevel(Level.WARN);
         Logger.getRootLogger().addAppender(logAppender = new TestLogAppender());
@@ -65,7 +65,7 @@ public class EdgeLabelVerificationStrategyTest {
 
     @After
     public void teardownForEachTest() {
-        final org.apache.log4j.Logger strategyLogger = org.apache.log4j.Logger.getLogger(EdgeLabelVerificationStrategy.class);
+        final Logger strategyLogger = Logger.getLogger(AbstractWarningVerificationStrategy.class);
         strategyLogger.setLevel(previousLogLevel);
         Logger.getRootLogger().removeAppender(logAppender);
     }
@@ -73,16 +73,14 @@ public class EdgeLabelVerificationStrategyTest {
     @Parameterized.Parameters(name = "{0}")
     public static Iterable<Object[]> data() {
         return Arrays.asList(new Object[][]{
-                {"__.inE()", __.inE(), false},
-                {"__.outE()", __.outE(), false},
-                {"__.bothE()", __.bothE(), false},
-                {"__.to(OUT)", __.to(Direction.OUT), false},
-                {"__.toE(IN)", __.toE(Direction.IN), false},
-                {"__.inE('knows')", __.inE("knows"), true},
-                {"__.outE('knows')", __.outE("knows"), true},
-                {"__.bothE('created','knows')", __.bothE("created", "knows"), true},
-                {"__.to(OUT,'created','knows')", __.to(Direction.OUT, "created", "knows"), true},
-                {"__.toE(IN,'knows')", __.toE(Direction.IN, "knows"), true}
+                {"__.addV().property('id',123)", __.addV().property("id", 123), false},
+                {"__.addE('knows').property('id',123)", __.addE("knows").property("id", 123), false},
+                {"__.addV().property(T.id,123)", __.addV().property(T.id, 123), true},
+                {"__.addE('knows').property(T.label,123)", __.addE("knows").property(T.label, "blah"), true},
+                {"__.addV().property('label','xyz')", __.addV().property("label", "xyz"), false},
+                {"__.addE('knows').property('label','xyz')", __.addE("knows").property("id", "xyz"), false},
+                {"__.addV().property('x','xyz', 'label', 'xxx')", __.addV().property("x", "xyz", "label", "xxx"), false},
+                {"__.addV().property('x','xyz', 'not-Label', 'xxx')", __.addV().property("x", "xyz", "not-label", "xxx"), true},
         });
     }
 
@@ -98,7 +96,7 @@ public class EdgeLabelVerificationStrategyTest {
     @Test
     public void shouldIgnore() {
         final TraversalStrategies strategies = new DefaultTraversalStrategies();
-        strategies.addStrategies(EdgeLabelVerificationStrategy.build().create());
+        strategies.addStrategies(ReservedKeysVerificationStrategy.build().create());
         final Traversal traversal = this.traversal.asAdmin().clone();
         traversal.asAdmin().setStrategies(strategies);
         traversal.asAdmin().applyStrategies();
@@ -108,7 +106,7 @@ public class EdgeLabelVerificationStrategyTest {
     @Test
     public void shouldOnlyThrow() {
         final TraversalStrategies strategies = new DefaultTraversalStrategies();
-        strategies.addStrategies(EdgeLabelVerificationStrategy.build().throwException().create());
+        strategies.addStrategies(ReservedKeysVerificationStrategy.build().throwException().create());
         final Traversal traversal = this.traversal.asAdmin().clone();
         traversal.asAdmin().setStrategies(strategies);
         if (allow) {
@@ -127,7 +125,7 @@ public class EdgeLabelVerificationStrategyTest {
     @Test
     public void shouldOnlyLog() {
         final TraversalStrategies strategies = new DefaultTraversalStrategies();
-        strategies.addStrategies(EdgeLabelVerificationStrategy.build().logWarning().create());
+        strategies.addStrategies(ReservedKeysVerificationStrategy.build().logWarning().create());
         final Traversal traversal = this.traversal.asAdmin().clone();
         traversal.asAdmin().setStrategies(strategies);
         traversal.asAdmin().applyStrategies();
@@ -140,7 +138,7 @@ public class EdgeLabelVerificationStrategyTest {
     @Test
     public void shouldThrowAndLog() {
         final TraversalStrategies strategies = new DefaultTraversalStrategies();
-        strategies.addStrategies(EdgeLabelVerificationStrategy.build().throwException().logWarning().create());
+        strategies.addStrategies(ReservedKeysVerificationStrategy.build().throwException().logWarning().create());
         final Traversal traversal = this.traversal.asAdmin().clone();
         traversal.asAdmin().setStrategies(strategies);
         if (allow) {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/EdgeLabelVerificationStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/EdgeLabelVerificationStrategy.cs
new file mode 100644
index 0000000..a76751a
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/EdgeLabelVerificationStrategy.cs
@@ -0,0 +1,49 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+namespace Gremlin.Net.Process.Traversal.Strategy.Verification
+{
+    /// <summary>
+    ///     Provides a way to prevent traversals that sub-optimally fail to include edge label specification .
+    /// </summary>
+    public class EdgeLabelVerificationStrategy : AbstractTraversalStrategy
+    {
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="EdgeLabelVerificationStrategy" /> class.
+        /// </summary>
+        public EdgeLabelVerificationStrategy()
+        {
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="EdgeLabelVerificationStrategy" /> class.
+        /// </summary>
+        /// <param name="logWarning">Constrains vertices for the <see cref="ITraversal" />.</param>
+        /// <param name="throwException">Constrains edges for the <see cref="ITraversal" />.</param>
+        public EdgeLabelVerificationStrategy(bool logWarning = false, bool throwException = false)
+        {
+            Configuration["logWarning"] = logWarning;
+            Configuration["throwException"] = throwException;
+        }
+    }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
new file mode 100644
index 0000000..8ecc753
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
@@ -0,0 +1,55 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+
+namespace Gremlin.Net.Process.Traversal.Strategy.Verification
+{
+    /// <summary>
+    ///     Provides a way to prevent traversal from using property keys that are reserved terms. By default, these
+    ///     are "id" and "label" - providers may have their own reserved terms as well.
+    /// </summary>
+    public class ReservedKeysVerificationStrategy : AbstractTraversalStrategy
+    {
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="ReservedKeysVerificationStrategy" /> class.
+        /// </summary>
+        public ReservedKeysVerificationStrategy()
+        {
+        }
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="ReservedKeysVerificationStrategy" /> class
+        /// </summary>
+        /// <param name="logWarning">Write a warning to the configured log on the server if a reserved key is used.</param>
+        /// <param name="throwException">Throw an exception if a reserved key is used.</param>
+        /// <param name="keys">List of keys to define as reserved. If not set then the defaults are used.</param>
+        public ReservedKeysVerificationStrategy(bool logWarning = false, bool throwException = false, List<string> keys = null)
+        {
+            Configuration["logWarning"] = logWarning;
+            Configuration["throwException"] = throwException;
+            if (keys != null)
+                Configuration["keys"] = keys;
+        }
+    }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalSourceTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalSourceTests.cs
index 1bc45da..c62e359 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalSourceTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalSourceTests.cs
@@ -21,8 +21,10 @@
 
 #endregion
 
+using System;
 using System.Collections.Generic;
 using Gremlin.Net.Process.Traversal;
+using Gremlin.Net.Process.Traversal.Strategy.Verification;
 using Xunit;
 
 namespace Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py b/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
index 940b6ed..476b3ee 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/protocol.py
@@ -27,6 +27,7 @@ except ImportError:
     import json
 
 from gremlin_python.driver import serializer, request
+from gremlin_python.driver.resultset import ResultSet
 
 __author__ = 'David M. Brown (davebshow@gmail.com)'
 
@@ -75,7 +76,7 @@ class GremlinServerWSProtocol(AbstractBaseProtocol):
 
         message = self._message_serializer.deserialize_message(json.loads(message.decode('utf-8')))
         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 --git a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
index 6bb9ab9..6cc1091 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
@@ -168,6 +168,7 @@ class GraphFilterStrategy(TraversalStrategy):
     def __init__(self):
         TraversalStrategy.__init__(self)
 
+
 class EarlyLimitStrategy(TraversalStrategy):
     def __init__(self):
         TraversalStrategy.__init__(self)
@@ -176,6 +177,7 @@ class EarlyLimitStrategy(TraversalStrategy):
 # VERIFICATION STRATEGIES #
 ###########################
 
+
 class LambdaRestrictionStrategy(TraversalStrategy):
     def __init__(self):
         TraversalStrategy.__init__(self)
@@ -184,3 +186,18 @@ class LambdaRestrictionStrategy(TraversalStrategy):
 class ReadOnlyStrategy(TraversalStrategy):
     def __init__(self):
         TraversalStrategy.__init__(self)
+
+
+class EdgeLabelVerificationStrategy(TraversalStrategy):
+    def __init__(self, log_warning=False, throw_exception=False):
+        TraversalStrategy.__init__(self)
+        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)
+        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 aa666d9..769ed43 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
@@ -21,6 +21,7 @@ import pytest
 from tornado import ioloop, gen
 
 from gremlin_python import statics
+from gremlin_python.driver.protocol import GremlinServerError
 from gremlin_python.statics import long
 from gremlin_python.driver.driver_remote_connection import (
     DriverRemoteConnection)
@@ -30,7 +31,7 @@ from gremlin_python.process.traversal import P
 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
+from gremlin_python.process.strategies import SubgraphStrategy, ReservedKeysVerificationStrategy
 
 __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
 
@@ -167,6 +168,16 @@ 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:
+            # 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())
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
index a0a0ce7..eaaf752 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
@@ -26,6 +26,8 @@ import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
 import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -46,7 +48,6 @@ import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoClassResolverV1d0;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoMapper;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoVersion;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoWriter;
-import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComputer;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
 import org.apache.tinkerpop.shaded.kryo.ClassResolver;
@@ -67,6 +68,7 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
@@ -78,9 +80,11 @@ import java.util.function.Supplier;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.greaterThan;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.core.StringContains.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeThat;
 import static org.mockito.Mockito.mock;
 
@@ -104,7 +108,7 @@ public class TinkerGraphTest {
         g.createIndex("oid1", Edge.class);
         g.createIndex("oid2", Edge.class);
 
-        // add the same one twice to check idempotance
+        // add the same one twice to check idempotency
         g.createIndex("name1", Vertex.class);
 
         keys = g.getIndexedKeys(Vertex.class);
@@ -685,6 +689,29 @@ public class TinkerGraphTest {
         assertEquals(expected, g.withComputer(Computer.compute().workers(4)).V(1, 2).optional(__.bothE().dedup()).order().by(T.id).toList());
     }
 
+    @Test
+    public void shouldReservedKeyVerify() {
+        final Set<String> reserved = new HashSet<>(Arrays.asList("something", "id", "label"));
+        final GraphTraversalSource g = TinkerGraph.open().traversal().withStrategies(
+                ReservedKeysVerificationStrategy.build().reservedKeys(reserved).throwException().create());
+
+        g.addV("person").property(T.id, 123).iterate();
+
+        try {
+            g.addV("person").property("id", 123).iterate();
+            fail("Verification exception expected");
+        } catch (IllegalStateException ve) {
+            assertThat(ve.getMessage(), containsString("that is setting a property key to a reserved word"));
+        }
+
+        try {
+            g.addV("person").property("something", 123).iterate();
+            fail("Verification exception expected");
+        } catch (IllegalStateException ve) {
+            assertThat(ve.getMessage(), containsString("that is setting a property key to a reserved word"));
+        }
+    }
+
     /**
      * Coerces a {@code Color} to a {@link TinkerGraph} during serialization.  Demonstrates how custom serializers
      * can be developed that can coerce one value to another during serialization.