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 2025/08/02 17:02:54 UTC
(tinkerpop) 01/02: Backported e8b9532fc0ec811460e97ebf5e00b8b9ec9192ac from 4.x
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch backport-discard
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 343eef4a851329c23bd031bf24247a1868f7c5f6
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Sat Aug 2 12:05:41 2025 -0400
Backported e8b9532fc0ec811460e97ebf5e00b8b9ec9192ac from 4.x
Implement list filtering none() step that takes a predicate and filters out lists that fail to have none of their elements satisfying the predicate.
---
CHANGELOG.asciidoc | 3 +-
docs/src/dev/provider/gremlin-semantics.asciidoc | 34 +++++
docs/src/reference/the-traversal.asciidoc | 23 +++
.../grammar/DefaultGremlinBaseVisitor.java | 4 +
.../language/grammar/TraversalMethodVisitor.java | 8 +
.../traversal/dsl/graph/GraphTraversal.java | 15 ++
.../gremlin/process/traversal/dsl/graph/__.java | 5 +
.../process/traversal/step/filter/NoneStep.java | 87 +++++++++++
.../process/traversal/util/BytecodeHelper.java | 2 +
.../traversal/step/filter/NoneStepTest.java | 89 +++++++++++
.../Process/Traversal/GraphTraversal.cs | 9 ++
.../src/Gremlin.Net/Process/Traversal/__.cs | 12 +-
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 13 ++
gremlin-go/driver/anonymousTraversal.go | 7 +
gremlin-go/driver/cucumber/gremlin.go | 13 ++
gremlin-go/driver/graphTraversal.go | 6 +
.../lib/process/graph-traversal.js | 11 ++
.../gremlin-javascript/test/cucumber/gremlin.js | 13 ++
gremlin-language/src/main/antlr4/Gremlin.g4 | 5 +
.../gremlin_python/process/graph_traversal.py | 14 ++
gremlin-python/src/main/python/radish/gremlin.py | 13 ++
.../gremlin/test/features/filter/None.feature | 168 +++++++++++++++++++++
22 files changed, 551 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d59b9f0969..ee1703fa24 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,7 +26,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
This release also includes changes from <<release-3-7-XXX, 3.7.XXX>>.
* Removed Vertex/ReferenceVertex from grammar. Use vertex id in traversals now instead.
-* Renamed the traversal discarding `none()` step to `discard()`.
+* Renamed `none()` step to `discard()`.
+* Repurposed `none()` step as a list filtering step with the signature `none(P)`.
* Modified mathematical operators to prevent overflows in steps such as `sum()` and 'sack()' to prefer promotion to the next highest number type.
* Added `DateTime` ontop of the existing 'datetime' grammar.
* Added `UUID()` and `UUID(value)` to grammar.
diff --git a/docs/src/dev/provider/gremlin-semantics.asciidoc b/docs/src/dev/provider/gremlin-semantics.asciidoc
index 6fe0d2c68e..5e3f166f18 100644
--- a/docs/src/dev/provider/gremlin-semantics.asciidoc
+++ b/docs/src/dev/provider/gremlin-semantics.asciidoc
@@ -1832,6 +1832,40 @@ resolve to a `Map`.
See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java[source],
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#mergev-step[reference]
+[[none-step]]
+=== none()
+
+*Description:* Filters array data from the traversal stream if none of the array's items match the supplied predicate.
+
+*Syntax:* `none(P predicate)`
+
+[width="100%",options="header"]
+|=========================================================
+|Start Step |Mid Step |Modulated |Domain |Range
+|N |Y |N |`List`/`array`/`Iterable`/`Iterator` |`List`/`array`/`Iterable`/`Iterator`
+|=========================================================
+
+*Arguments:*
+
+* `predicate` - The predicate used to test each value in the array data.
+
+*Modulation:*
+
+None
+
+*Considerations:*
+
+Each value will be tested using the supplied predicate. Empty lists always pass through and null/non-list traversers
+will be filtered out of the traversal stream.
+
+*Exceptions*
+
+* A GremlinTypeErrorException will be thrown if one occurs and no other value evaluates to true.
+
+See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java[source],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#none-step[reference]
+
+
[[product-step]]
=== product()
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index edd28510cb..1bb31c090a 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -3255,6 +3255,29 @@ link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#min(org.apache.tinkerpop.gremlin.process.traversal.Scope)++[`min(Scope)`],
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/Scope.html++[`Scope`]
+[[none-step]]
+=== None Step
+
+It is possible to filter list traversers using `none()`-step (*filter*). Every item in the list will be tested against
+the supplied predicate and if none of the items pass then the traverser is passed along the stream, otherwise it is
+filtered. Empty lists are passed along but null or non-iterable traversers are filtered out.
+
+NOTE: Prior to release 3.8.0, `none()` was a traversal discarding step primarily used by <<iterate-step,`iterate()`>>.
+This step has since been renamed to <<discard-step,`discard()`>>
+
+[gremlin-groovy,modern]
+----
+g.V().values('age').fold().none(gt(25)) <1>
+----
+
+<1> Return the list of ages only if no one's age is greater than 25.
+
+*Additional References*
+
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#none(org.apache.tinkerpop.gremlin.process.traversal.P)++[`none(P)`],
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/P.html++[`P`]
+
+
[[not-step]]
=== Not Step
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index 6a7382c144..c4dcb81f52 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -615,6 +615,10 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalMethod_discard(final GremlinParser.TraversalMethod_discardContext ctx) { notImplemented(ctx); return null; }
+ /**
+ * {@inheritDoc}
+ */
+ @Override public T visitTraversalMethod_none_P(final GremlinParser.TraversalMethod_none_PContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 9ff820393b..7fc4b9a78e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -1115,6 +1115,14 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
return this.graphTraversal.discard();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public GraphTraversal visitTraversalMethod_none_P(final GremlinParser.TraversalMethod_none_PContext ctx) {
+ return graphTraversal.none(antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index b91e8f5950..ffe1394889 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -68,6 +68,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.LambdaFilterStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DiscardStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
@@ -2882,6 +2883,19 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new AnyStep<>(this.asAdmin(), predicate));
}
+ /**
+ * Filters <code>E</code> lists given the provided {@code predicate}.
+ *
+ * @param predicate the filter to apply
+ * @return the traversal with an appended {@link NoneStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#none-step" target="_blank">Reference Documentation - None Step</a>
+ * @since 3.8.0
+ */
+ public default <S2> GraphTraversal<S, E> none(final P<S2> predicate) {
+ this.asAdmin().getBytecode().addStep(Symbols.none, predicate);
+ return this.asAdmin().addStep(new NoneStep<>(this.asAdmin(), predicate));
+ }
+
///////////////////// SIDE-EFFECT STEPS /////////////////////
/**
@@ -4150,6 +4164,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public static final String dateDiff = "dateDiff";
public static final String all = "all";
public static final String any = "any";
+ public static final String none = "none";
public static final String merge = "merge";
public static final String product = "product";
public static final String combine = "combine";
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 068a200e9d..b20dc48f78 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -1213,6 +1213,11 @@ public class __ {
*/
public static <A> GraphTraversal<A, A> any(final P<A> predicate) { return __.<A>start().any(predicate); }
+ /**
+ * @see GraphTraversal#none(P)
+ */
+ public static <A> GraphTraversal<A, A> none(final P<A> predicate) { return __.<A>start().none(predicate); }
+
///////////////////// SIDE-EFFECT STEPS /////////////////////
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java
new file mode 100644
index 0000000000..78f4f755e8
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java
@@ -0,0 +1,87 @@
+/*
+ * 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.step.filter;
+
+import org.apache.tinkerpop.gremlin.process.traversal.GremlinTypeErrorException;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public final class NoneStep<S, S2> extends FilterStep<S> {
+
+ private P<S2> predicate;
+
+ public NoneStep(final Traversal.Admin traversal, final P<S2> predicate) {
+ super(traversal);
+
+ if (null == predicate) {
+ throw new IllegalArgumentException("Input predicate to none step can't be null.");
+ }
+
+ this.predicate = predicate;
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ final S item = traverser.get();
+
+ if (item instanceof Iterable || item instanceof Iterator || ((item != null) && item.getClass().isArray())) {
+ GremlinTypeErrorException typeError = null;
+ final Iterator<S2> iterator = IteratorUtils.asIterator(item);
+ while (iterator.hasNext()) {
+ try {
+ if (this.predicate.test(iterator.next())) {
+ return false;
+ }
+ } catch (GremlinTypeErrorException gtee) {
+ // hold onto it until the end in case any other element evaluates to TRUE
+ typeError = gtee;
+ }
+ }
+ if (typeError != null) throw typeError;
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return StringFactory.stepString(this, this.predicate);
+ }
+
+ @Override
+ public NoneStep<S, S2> clone() {
+ final NoneStep<S, S2> clone = (NoneStep<S, S2>) super.clone();
+ clone.predicate = this.predicate.clone();
+ return clone;
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return EnumSet.of(TraverserRequirement.OBJECT);
+ }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
index 5eb5ef252b..2d5b526a3d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
@@ -52,6 +52,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.LambdaFilterStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DiscardStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
@@ -251,6 +252,7 @@ public final class BytecodeHelper {
put(GraphTraversal.Symbols.dateDiff, Collections.singletonList(DateDiffStep.class));
put(GraphTraversal.Symbols.all, Collections.singletonList(AllStep.class));
put(GraphTraversal.Symbols.any, Collections.singletonList(AnyStep.class));
+ put(GraphTraversal.Symbols.none, Collections.singletonList(NoneStep.class));
put(GraphTraversal.Symbols.combine, Collections.singletonList(CombineStep.class));
put(GraphTraversal.Symbols.difference, Collections.singletonList(DifferenceStep.class));
put(GraphTraversal.Symbols.disjunct, Collections.singletonList(DisjunctStep.class));
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStepTest.java
new file mode 100644
index 0000000000..f53ec9f28a
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStepTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.step.filter;
+
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+public class NoneStepTest extends StepTest {
+
+ @Override
+ protected List<Traversal> getTraversals() { return Collections.singletonList(__.none(P.gt(0))); }
+
+ @Test
+ public void testReturnTypes() {
+ assertTrue(__.__(new int[]{}).none(P.gt(7)).hasNext());
+ assertArrayEquals(new int[] {5, 6}, __.__(new int[] {5, 8, 10}, new int[] {5, 6}).none(P.gte(7)).next());
+ assertArrayEquals(new long[] {5L, 6L}, __.__(new long[] {5L, 8L, 10L}, new long[] {5L, 6L}).none(P.gte(7)).next());
+ assertArrayEquals(new Long[] {5L, 6L}, __.__(1).constant(new Long[] {5L, 6L}).none(P.gte(7)).next());
+ assertArrayEquals(new double[] {5.1, 6.5}, __.__(new double[] {5.5, 8.0, 10.1}, new double[] {5.1, 6.5}).none(P.gte(7.0)).next(), 0.01);
+ }
+
+ @Test
+ public void testNullParameter() {
+ final Throwable thrown = assertThrows(IllegalArgumentException.class, () -> __.__(new int[]{1}).none(null).hasNext());
+ assertEquals("Input predicate to none step can't be null.", thrown.getMessage());
+ }
+
+ @Test
+ public void testSetTraverser() {
+ final Set<Integer> numbers = new HashSet<>();
+ numbers.add(5);
+ numbers.add(6);
+
+ assertTrue(__.__(numbers).none(P.gt(7)).hasNext());
+ }
+
+ @Test
+ public void testListIteratorTraverser() {
+ final List<Integer> numbers = new ArrayList<>();
+ numbers.add(10);
+ numbers.add(11);
+
+ assertTrue(__.__(numbers.iterator()).none(P.lt(10)).hasNext());
+ }
+
+ @Test
+ public void testCornerCases() {
+ final List validOne = new ArrayList() {{ add(20); }};
+ final List validTwo = new ArrayList() {{ add(21); add(25);}};
+ final List validThree = new ArrayList() {{ add(51); add(57); add(71); }};
+ final List containsNull = new ArrayList() {{ add(50); add(null); add(60); }};
+ final List empty = new ArrayList();
+ final List incorrectType = new ArrayList() {{ add(100); add("25"); }};
+ final List valueTooSmall = new ArrayList() {{ add(101); add(1); add(10);}};
+
+ assertEquals(4L, __.__(validOne, null, containsNull, empty, incorrectType, valueTooSmall, validTwo, validThree)
+ .none(P.lte(3)).count().next().longValue());
+ }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 162a89c0fe..40e742b64d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -1519,6 +1519,15 @@ namespace Gremlin.Net.Process.Traversal
return Wrap<TStart, TNewEnd>(this);
}
+ /// <summary>
+ /// Adds the none step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
+ public GraphTraversal<TStart, TEnd> None (P? predicate)
+ {
+ Bytecode.AddStep("none", predicate);
+ return Wrap<TStart, TEnd>(this);
+ }
+
/// <summary>
/// Adds the not step to this <see cref="GraphTraversal{SType, EType}" />.
/// </summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 6e5644da70..14b63979f3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -117,7 +117,7 @@ namespace Gremlin.Net.Process.Traversal
}
/// <summary>
- /// Spawns a <see cref="GraphTraversal{SType, EType}" /> all adds the all step to that traversal.
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the all step to that traversal.
/// </summary>
public static GraphTraversal<object, object> All(P? predicate)
{
@@ -135,13 +135,21 @@ namespace Gremlin.Net.Process.Traversal
}
/// <summary>
- /// Spawns a <see cref="GraphTraversal{SType, EType}" /> any adds the any step to that traversal.
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the any step to that traversal.
/// </summary>
public static GraphTraversal<object, object> Any(P? predicate)
{
return new GraphTraversal<object, object>().Any(predicate);
}
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the none step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, object> None(P? predicate)
+ {
+ return new GraphTraversal<object, object>().None(predicate);
+ }
+
/// <summary>
/// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the as step to that traversal.
/// </summary>
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 81bb7242df..1549d3ae0d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -324,6 +324,19 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_valuesXageX_isXgte_29X_isXlt_34X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Is(P.Gte(29)).Is(P.Lt(34))}},
{"g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Where(__.In("created").Count().Is(1)).Values<object>("name")}},
{"g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Where(__.In("created").Count().Is(P.Gte(2))).Values<object>("name")}},
+ {"g_V_valuesXageX_noneXgtX32XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").None(P.Gt(32))}},
+ {"g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Where(__.Is(P.Gt(33))).Fold().None(P.Lte(33))}},
+ {"g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Order().By(Order.Desc).Fold().None(P.Lt(10))}},
+ {"g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Order().By(Order.Desc).Fold().None(P.Gt(30))}},
+ {"g_injectXabc_bcdX_noneXeqXbcdXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(new List<object> { "abc", "bcd" }).None(P.Eq("bcd"))}},
+ {"g_injectXbcd_bcdX_noneXeqXabcXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).None(P.Eq("abc"))}},
+ {"g_injectXnull_bcdX_noneXP_eqXabcXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).None(P.Eq("abc"))}},
+ {"g_injectX5_8_10_10_7X_noneXltX7XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"], p["xx2"]).None(P.Lt(7))}},
+ {"g_injectXnullX_noneXeqXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null).None(P.Eq(null))}},
+ {"g_injectX7X_noneXeqX7XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(7).None(P.Eq(7))}},
+ {"g_injectXnull_1_emptyX_noneXeqXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"], p["xx2"]).None(P.Eq(null))}},
+ {"g_injectXnull_nullX_noneXnotXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).None(P.Neq(null))}},
+ {"g_injectX3_threeX_noneXeqX3XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).None(P.Eq(3))}},
{"g_V_orXhasXage_gt_27X__outE_count_gte_2X_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Or(__.Has("age", P.Gt(27)), __.OutE().Count().Is(P.Gte(2))).Values<object>("name")}},
{"g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Or(__.OutE("knows"), __.Has(T.Label, "software").Or().Has("age", P.Gte(35))).Values<object>("name")}},
{"g_V_asXaX_orXselectXaX_selectXaXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Or(__.Select<object>("a"), __.Select<object>("a"))}},
diff --git a/gremlin-go/driver/anonymousTraversal.go b/gremlin-go/driver/anonymousTraversal.go
index ac6c9a5348..a72e89b679 100644
--- a/gremlin-go/driver/anonymousTraversal.go
+++ b/gremlin-go/driver/anonymousTraversal.go
@@ -207,6 +207,8 @@ type AnonymousTraversal interface {
MergeV(args ...interface{}) *GraphTraversal
// Min adds the min step to the GraphTraversal.
Min(args ...interface{}) *GraphTraversal
+ // None adds the not step to the GraphTraversal.
+ None(args ...interface{}) *GraphTraversal
// Not adds the not step to the GraphTraversal.
Not(args ...interface{}) *GraphTraversal
// Option adds the option step to the GraphTraversal.
@@ -731,6 +733,11 @@ func (anonymousTraversal *anonymousTraversal) Min(args ...interface{}) *GraphTra
return anonymousTraversal.graphTraversal().Min(args...)
}
+// None adds the none step to the GraphTraversal.
+func (anonymousTraversal *anonymousTraversal) None(args ...interface{}) *GraphTraversal {
+ return anonymousTraversal.graphTraversal().None(args...)
+}
+
// Not adds the not step to the GraphTraversal.
func (anonymousTraversal *anonymousTraversal) Not(args ...interface{}) *GraphTraversal {
return anonymousTraversal.graphTraversal().Not(args...)
diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index b09f540c46..79fecd7d60 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -294,6 +294,19 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_V_valuesXageX_isXgte_29X_isXlt_34X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Gte(29)).Is(gremlingo.P.Lt(34))}},
"g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.In("created").Count().Is(1)).Values("name")}},
"g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.In("created").Count().Is(gremlingo.P.Gte(2))).Values("name")}},
+ "g_V_valuesXageX_noneXgtX32XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").None(gremlingo.P.Gt(32))}},
+ "g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.T__.Is(gremlingo.P.Gt(33))).Fold().None(gremlingo.P.Lte(33))}},
+ "g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().By(gremlingo.Order.Desc).Fold().None(gremlingo.P.Lt(10))}},
+ "g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().By(gremlingo.Order.Desc).Fold().None(gremlingo.P.Gt(30))}},
+ "g_injectXabc_bcdX_noneXeqXbcdXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{"abc", "bcd"}).None(gremlingo.P.Eq("bcd"))}},
+ "g_injectXbcd_bcdX_noneXeqXabcXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.P.Eq("abc"))}},
+ "g_injectXnull_bcdX_noneXP_eqXabcXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.P.Eq("abc"))}},
+ "g_injectX5_8_10_10_7X_noneXltX7XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx2"]).None(gremlingo.P.Lt(7))}},
+ "g_injectXnullX_noneXeqXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(nil).None(gremlingo.P.Eq(nil))}},
+ "g_injectX7X_noneXeqX7XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(7).None(gremlingo.P.Eq(7))}},
+ "g_injectXnull_1_emptyX_noneXeqXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx2"]).None(gremlingo.P.Eq(nil))}},
+ "g_injectXnull_nullX_noneXnotXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.P.Neq(nil))}},
+ "g_injectX3_threeX_noneXeqX3XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.P.Eq(3))}},
"g_V_orXhasXage_gt_27X__outE_count_gte_2X_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Or(gremlingo.T__.Has("age", gremlingo.P.Gt(27)), gremlingo.T__.OutE().Count().Is(gremlingo.P.Gte(2))).Values("name")}},
"g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Or(gremlingo.T__.OutE("knows"), gremlingo.T__.Has(gremlingo.T.Label, "software").Or().Has("age", gremlingo.P.Gte(35))).Values("name")}},
"g_V_asXaX_orXselectXaX_selectXaXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().As("a").Or(gremlingo.T__.Select("a"), gremlingo.T__.Select("a"))}},
diff --git a/gremlin-go/driver/graphTraversal.go b/gremlin-go/driver/graphTraversal.go
index 6573db7485..6d8463a438 100644
--- a/gremlin-go/driver/graphTraversal.go
+++ b/gremlin-go/driver/graphTraversal.go
@@ -530,6 +530,12 @@ func (g *GraphTraversal) Min(args ...interface{}) *GraphTraversal {
return g
}
+// None adds the none step to the GraphTraversal.
+func (g *GraphTraversal) None(args ...interface{}) *GraphTraversal {
+ g.Bytecode.AddStep("none", args...)
+ return g
+}
+
// Not adds the not step to the GraphTraversal.
func (g *GraphTraversal) Not(args ...interface{}) *GraphTraversal {
g.Bytecode.AddStep("not", args...)
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index b2aa34afba..40bd087343 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -1131,6 +1131,16 @@ class GraphTraversal extends Traversal {
return this;
}
+ /**
+ * Graph traversal none method.
+ * @param {...Object} args
+ * @returns {GraphTraversal}
+ */
+ none(...args) {
+ this.bytecode.addStep('none', args);
+ return this;
+ }
+
/**
* Graph traversal not method.
* @param {...Object} args
@@ -1812,6 +1822,7 @@ const statics = {
mergeE: (...args) => callOnEmptyTraversal('mergeE', args),
mergeV: (...args) => callOnEmptyTraversal('mergeV', args),
min: (...args) => callOnEmptyTraversal('min', args),
+ none: (...args) => callOnEmptyTraversal('none', args),
not: (...args) => callOnEmptyTraversal('not', args),
optional: (...args) => callOnEmptyTraversal('optional', args),
or: (...args) => callOnEmptyTraversal('or', args),
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 03840c482b..5c23d7a430 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -324,6 +324,19 @@ const gremlins = {
g_V_valuesXageX_isXgte_29X_isXlt_34X: [function({g}) { return g.V().values("age").is(P.gte(29)).is(P.lt(34)) }],
g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(1)).values("name") }],
g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(P.gte(2))).values("name") }],
+ g_V_valuesXageX_noneXgtX32XX: [function({g}) { return g.V().values("age").none(P.gt(32)) }],
+ g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX: [function({g}) { return g.V().values("age").where(__.is(P.gt(33))).fold().none(P.lte(33)) }],
+ g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX: [function({g}) { return g.V().values("age").order().by(Order.desc).fold().none(P.lt(10)) }],
+ g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX: [function({g}) { return g.V().values("age").order().by(Order.desc).fold().none(P.gt(30)) }],
+ g_injectXabc_bcdX_noneXeqXbcdXX: [function({g}) { return g.inject(["abc", "bcd"]).none(P.eq("bcd")) }],
+ g_injectXbcd_bcdX_noneXeqXabcXX: [function({g, xx1}) { return g.inject(xx1).none(P.eq("abc")) }],
+ g_injectXnull_bcdX_noneXP_eqXabcXX: [function({g, xx1}) { return g.inject(xx1).none(P.eq("abc")) }],
+ g_injectX5_8_10_10_7X_noneXltX7XX: [function({g, xx1, xx2}) { return g.inject(xx1, xx2).none(P.lt(7)) }],
+ g_injectXnullX_noneXeqXnullXX: [function({g}) { return g.inject(null).none(P.eq(null)) }],
+ g_injectX7X_noneXeqX7XX: [function({g}) { return g.inject(7).none(P.eq(7)) }],
+ g_injectXnull_1_emptyX_noneXeqXnullXX: [function({g, xx1, xx2}) { return g.inject(xx1, xx2).none(P.eq(null)) }],
+ g_injectXnull_nullX_noneXnotXnullXX: [function({g, xx1}) { return g.inject(xx1).none(P.neq(null)) }],
+ g_injectX3_threeX_noneXeqX3XX: [function({g, xx1}) { return g.inject(xx1).none(P.eq(3)) }],
g_V_orXhasXage_gt_27X__outE_count_gte_2X_name: [function({g}) { return g.V().or(__.has("age", P.gt(27)), __.outE().count().is(P.gte(2))).values("name") }],
g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name: [function({g}) { return g.V().or(__.outE("knows"), __.has(T.label, "software").or().has("age", P.gte(35))).values("name") }],
g_V_asXaX_orXselectXaX_selectXaXX: [function({g}) { return g.V().as("a").or(__.select("a"), __.select("a")) }],
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 9fbcae894e..07c5059b97 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -239,6 +239,7 @@ traversalMethod
| traversalMethod_max
| traversalMethod_mean
| traversalMethod_min
+ | traversalMethod_none
| traversalMethod_not
| traversalMethod_option
| traversalMethod_optional
@@ -687,6 +688,10 @@ traversalMethod_min
| K_MIN LPAREN traversalScope RPAREN #traversalMethod_min_Scope
;
+traversalMethod_none
+ : K_NONE LPAREN traversalPredicate RPAREN #traversalMethod_none_P
+ ;
+
traversalMethod_not
: K_NOT LPAREN nestedTraversal RPAREN
;
diff --git a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
index df7c3d4e65..f21248b445 100644
--- a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
@@ -707,6 +707,10 @@ class GraphTraversal(Traversal):
self.bytecode.add_step("min", *args)
return self
+ def none(self, *args):
+ self.bytecode.add_step("none", *args)
+ return self
+
def not_(self, *args):
self.bytecode.add_step("not", *args)
return self
@@ -1487,6 +1491,10 @@ class __(object, metaclass=MagicType):
def min_(cls, *args):
return cls.graph_traversal(None, None, Bytecode()).min_(*args)
+ @classmethod
+ def none(cls, *args):
+ return cls.graph_traversal(None, None, Bytecode()).none(*args)
+
@classmethod
def not_(cls, *args):
return cls.graph_traversal(None, None, Bytecode()).not_(*args)
@@ -2181,6 +2189,10 @@ def min_(*args):
return __.min_(*args)
+def none(*args):
+ return __.none(*args)
+
+
def not_(*args):
return __.not_(*args)
@@ -2575,6 +2587,8 @@ statics.add_static('merge_v', merge_v)
statics.add_static('min_', min_)
+statics.add_static('none', none)
+
statics.add_static('not_', not_)
statics.add_static('optional', optional)
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 1351a0a4a1..64d5257aa9 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -297,6 +297,19 @@ world.gremlins = {
'g_V_valuesXageX_isXgte_29X_isXlt_34X': [(lambda g:g.V().values('age').is_(P.gte(29)).is_(P.lt(34)))],
'g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(1)).values('name'))],
'g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(P.gte(2))).values('name'))],
+ 'g_V_valuesXageX_noneXgtX32XX': [(lambda g:g.V().values('age').none(P.gt(32)))],
+ 'g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX': [(lambda g:g.V().values('age').where(__.is_(P.gt(33))).fold().none(P.lte(33)))],
+ 'g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX': [(lambda g:g.V().values('age').order().by(Order.desc).fold().none(P.lt(10)))],
+ 'g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX': [(lambda g:g.V().values('age').order().by(Order.desc).fold().none(P.gt(30)))],
+ 'g_injectXabc_bcdX_noneXeqXbcdXX': [(lambda g:g.inject(['abc', 'bcd']).none(P.eq('bcd')))],
+ 'g_injectXbcd_bcdX_noneXeqXabcXX': [(lambda g, xx1=None:g.inject(xx1).none(P.eq('abc')))],
+ 'g_injectXnull_bcdX_noneXP_eqXabcXX': [(lambda g, xx1=None:g.inject(xx1).none(P.eq('abc')))],
+ 'g_injectX5_8_10_10_7X_noneXltX7XX': [(lambda g, xx1=None,xx2=None:g.inject(xx1, xx2).none(P.lt(7)))],
+ 'g_injectXnullX_noneXeqXnullXX': [(lambda g:g.inject(None).none(P.eq(None)))],
+ 'g_injectX7X_noneXeqX7XX': [(lambda g:g.inject(7).none(P.eq(7)))],
+ 'g_injectXnull_1_emptyX_noneXeqXnullXX': [(lambda g, xx1=None,xx2=None:g.inject(xx1, xx2).none(P.eq(None)))],
+ 'g_injectXnull_nullX_noneXnotXnullXX': [(lambda g, xx1=None:g.inject(xx1).none(P.neq(None)))],
+ 'g_injectX3_threeX_noneXeqX3XX': [(lambda g, xx1=None:g.inject(xx1).none(P.eq(3)))],
'g_V_orXhasXage_gt_27X__outE_count_gte_2X_name': [(lambda g:g.V().or_(__.has('age', P.gt(27)), __.out_e().count().is_(P.gte(2))).values('name'))],
'g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name': [(lambda g:g.V().or_(__.out_e('knows'), __.has(T.label, 'software').or_().has('age', P.gte(35))).values('name'))],
'g_V_asXaX_orXselectXaX_selectXaXX': [(lambda g:g.V().as_('a').or_(__.select('a'), __.select('a')))],
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature
new file mode 100644
index 0000000000..b16ec5fc68
--- /dev/null
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature
@@ -0,0 +1,168 @@
+# 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.
+
+@StepClassFilter @StepNone
+Feature: Step - none()
+
+ Scenario: g_V_valuesXageX_noneXgtX32XX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().values("age").none(P.gt(32))
+ """
+ When iterated to list
+ Then the result should be empty
+
+ Scenario: g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().values("age").where(__.is(P.gt(33))).fold().none(P.lte(33))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[d[35].i] |
+
+ Scenario: g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().values("age").order().by(desc).fold().none(P.lt(10))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[d[35].i,d[32].i,d[29].i,d[27].i] |
+
+ Scenario: g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().values("age").order().by(desc).fold().none(P.gt(30))
+ """
+ When iterated to list
+ Then the result should be empty
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectXabc_bcdX_noneXeqXbcdXX
+ Given the empty graph
+ And the traversal of
+ """
+ g.inject(["abc","bcd"]).none(P.eq("bcd"))
+ """
+ When iterated to list
+ Then the result should be empty
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectXbcd_bcdX_noneXeqXabcXX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[bcd,bcd]"
+ And the traversal of
+ """
+ g.inject(xx1).none(P.eq("abc"))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[bcd,bcd] |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectXnull_bcdX_noneXP_eqXabcXX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[null,bcd]"
+ And the traversal of
+ """
+ g.inject(xx1).none(P.eq("abc"))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[null,bcd] |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectX5_8_10_10_7X_noneXltX7XX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[5].i,d[8].i,d[10].i]"
+ And using the parameter xx2 defined as "l[d[10].i,d[7].i]"
+ And the traversal of
+ """
+ g.inject(xx1,xx2).none(P.lt(7))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[d[10].i,d[7].i] |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectXnullX_noneXeqXnullXX
+ Given the empty graph
+ And the traversal of
+ """
+ g.inject(null).none(P.eq(null))
+ """
+ When iterated to list
+ Then the result should be empty
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectX7X_noneXeqX7XX
+ Given the empty graph
+ And the traversal of
+ """
+ g.inject(7).none(P.eq(7))
+ """
+ When iterated to list
+ Then the result should be empty
+
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectXnull_1_emptyX_noneXeqXnullXX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[null,1]"
+ And using the parameter xx2 defined as "l[]"
+ And the traversal of
+ """
+ g.inject(xx1,xx2).none(P.eq(null))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[] |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectXnull_nullX_noneXnotXnullXX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[null,null]"
+ And the traversal of
+ """
+ g.inject(xx1).none(P.neq(null))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[null,null] |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectX3_threeX_noneXeqX3XX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[3].i,three]"
+ And the traversal of
+ """
+ g.inject(xx1).none(P.eq(3))
+ """
+ When iterated to list
+ Then the result should be empty
\ No newline at end of file