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 545b0ca623c522167f765354d2e6718066590a35 Author: Stephen Mallette <[email protected]> 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 | 1 + 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, 550 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index dbbcf07024..a6a96cf4eb 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -27,6 +27,7 @@ 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()`. +* Repurposed `none()` step as a list filtering step. * 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
