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/02/07 14:32:28 UTC
(tinkerpop) branch TINKERPOP-3130 created (now e3ea7c360c)
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a change to branch TINKERPOP-3130
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
at e3ea7c360c TINKERPOP-3130 Allowed none() as anonymous and chained
This branch includes the following new commits:
new e3ea7c360c TINKERPOP-3130 Allowed none() as anonymous and chained
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(tinkerpop) 01/01: TINKERPOP-3130 Allowed none() as anonymous and chained
Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-3130
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit e3ea7c360c1db980fc7f9cb8e2c8a35931aa8c70
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Feb 7 08:01:04 2025 -0500
TINKERPOP-3130 Allowed none() as anonymous and chained
---
CHANGELOG.asciidoc | 1 +
.../grammar/DefaultGremlinBaseVisitor.java | 16 ++---
.../language/grammar/TraversalMethodVisitor.java | 10 ++-
.../language/grammar/TraversalRootVisitor.java | 48 +------------
.../gremlin/process/traversal/dsl/graph/__.java | 7 ++
.../grammar/TraversalMethodVisitorTest.java | 7 ++
.../traversal/translator/PythonTranslatorTest.java | 8 ++-
.../src/Gremlin.Net/Process/Traversal/__.cs | 8 +++
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 6 ++
gremlin-go/driver/cucumber/gremlin.go | 6 ++
.../lib/process/graph-traversal.js | 1 +
.../gremlin-javascript/test/cucumber/gremlin.js | 6 ++
gremlin-language/src/main/antlr4/Gremlin.g4 | 20 ++----
.../gremlin_python/process/graph_traversal.py | 10 +++
gremlin-python/src/main/python/radish/gremlin.py | 6 ++
.../gremlin/test/features/filter/None.feature | 81 ++++++++++++++++++++++
16 files changed, 166 insertions(+), 75 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 447a9b33e3..82236a2d79 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -31,6 +31,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Changed Gremlin grammar to make use of `g` to spawn child traversals a syntax error.
* Added `unexpected-response` handler to `ws` for `gremlin-javascript`
* Fixed bug in `TinkerTransactionGraph` where a read-only transaction may leave elements trapped in a "zombie transaction".
+* Modified grammar to make `none()` usage more consistent as a filter step where it can now be used to chain additional traversal steps and be used anonymously.
[[release-3-7-3]]
=== TinkerPop 3.7.3 (October 23, 2024)
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 35660c1089..09df5822f3 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
@@ -143,10 +143,6 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitChainedTraversal(final GremlinParser.ChainedTraversalContext ctx) { notImplemented(ctx); return null; }
- /**
- * {@inheritDoc}
- */
- @Override public T visitChainedParentOfGraphTraversal(final GremlinParser.ChainedParentOfGraphTraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -615,6 +611,10 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalMethod_min_Scope(final GremlinParser.TraversalMethod_min_ScopeContext ctx) { notImplemented(ctx); return null; }
+ /**
+ * {@inheritDoc}
+ */
+ @Override public T visitTraversalMethod_none(final GremlinParser.TraversalMethod_noneContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -1119,10 +1119,6 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalSackMethod(final GremlinParser.TraversalSackMethodContext ctx) { notImplemented(ctx); return null; }
- /**
- * {@inheritDoc}
- */
- @Override public T visitTraversalSelfMethod(final GremlinParser.TraversalSelfMethodContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -1247,10 +1243,6 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalTerminalMethod_toBulkSet(final GremlinParser.TraversalTerminalMethod_toBulkSetContext ctx) { notImplemented(ctx); return null; }
- /**
- * {@inheritDoc}
- */
- @Override public T visitTraversalSelfMethod_none(final GremlinParser.TraversalSelfMethod_noneContext 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 d5124e20b3..c0a084b38d 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
@@ -18,14 +18,12 @@
*/
package org.apache.tinkerpop.gremlin.language.grammar;
-import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Operator;
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
-import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiFunction;
@@ -1082,6 +1080,14 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
return graphTraversal.min(antlr.argumentVisitor.parseScope(ctx.traversalScopeArgument()));
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public GraphTraversal visitTraversalMethod_none(final GremlinParser.TraversalMethod_noneContext ctx) {
+ return this.graphTraversal.none();
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitor.java
index 0e52b606d5..4f9e328276 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitor.java
@@ -56,9 +56,6 @@ public class TraversalRootVisitor<G extends Traversal> extends DefaultGremlinBas
public Traversal visitNestedTraversal(final GremlinParser.NestedTraversalContext ctx) {
if (ctx.getChild(0) instanceof GremlinParser.RootTraversalContext) {
return visitChildren(ctx);
- } else if (ctx.getChild(2) instanceof GremlinParser.ChainedParentOfGraphTraversalContext) {
- return new TraversalRootVisitor<Traversal>(antlr.createAnonymous.get()).
- visitChainedParentOfGraphTraversal(ctx.chainedTraversal().chainedParentOfGraphTraversal());
} else {
return new TraversalMethodVisitor(antlr, antlr.createAnonymous.get()).visitChainedTraversal(ctx.chainedTraversal());
}
@@ -79,53 +76,14 @@ public class TraversalRootVisitor<G extends Traversal> extends DefaultGremlinBas
(GremlinParser.TraversalSourceSpawnMethodContext) ctx.getChild(childIndexOfTraversalSourceSpawnMethod));
if (ctx.getChildCount() == 5) {
- // handle chained traversal
- final int childIndexOfChainedTraversal = 4;
-
- if (ctx.getChild(childIndexOfChainedTraversal) instanceof GremlinParser.ChainedParentOfGraphTraversalContext) {
- final TraversalRootVisitor traversalRootVisitor = new TraversalRootVisitor(traversal);
- return traversalRootVisitor.visitChainedParentOfGraphTraversal(
- (GremlinParser.ChainedParentOfGraphTraversalContext) ctx.getChild(childIndexOfChainedTraversal));
- } else {
- final TraversalMethodVisitor traversalMethodVisitor = new TraversalMethodVisitor(antlr, traversal);
- return traversalMethodVisitor.visitChainedTraversal(
- (GremlinParser.ChainedTraversalContext) ctx.getChild(childIndexOfChainedTraversal));
- }
+ final TraversalMethodVisitor traversalMethodVisitor = new TraversalMethodVisitor(antlr, traversal);
+ return traversalMethodVisitor.visitChainedTraversal(
+ (GremlinParser.ChainedTraversalContext) ctx.getChild(4));
} else {
return traversal;
}
}
- /**
- * {@inheritDoc}
- */
- @Override
- public Traversal visitTraversalSelfMethod(final GremlinParser.TraversalSelfMethodContext ctx) {
- return visitChildren(ctx);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Traversal visitTraversalSelfMethod_none(final GremlinParser.TraversalSelfMethod_noneContext ctx) {
- this.traversal = traversal.none();
- return this.traversal;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Traversal visitChainedParentOfGraphTraversal(final GremlinParser.ChainedParentOfGraphTraversalContext ctx) {
- if (ctx.getChildCount() == 1) {
- return visitChildren(ctx);
- } else {
- visit(ctx.getChild(0));
- return visit(ctx.getChild(2));
- }
- }
-
/**
* {@inheritDoc}
*/
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 d6cdc1ef7f..a0cadeef84 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
@@ -1060,6 +1060,13 @@ public class __ {
return __.<A>start().is(value);
}
+ /**
+ * @see GraphTraversal#none()
+ */
+ public static <A> GraphTraversal<A, A> none() {
+ return __.<A>start().none();
+ }
+
/**
* @see GraphTraversal#not(Traversal)
*/
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
index 51244cdf17..6e4a26f5ab 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
@@ -1298,4 +1298,11 @@ public class TraversalMethodVisitorTest {
public void shouldParseTraversalMethod_substring_long_long() throws Exception {
compare(g.V().substring(1, 3), eval("g.V().substring(1, 3)"));
}
+
+ @Test
+ public void shouldParseTraversalMethod_none_somethingAfter() throws Exception {
+ compare(g.V().none().path(), eval("g.V().none().path()"));
+ compare(g.V().none().E(), eval("g.V().none().E()"));
+ compare(g.V().none().none(), eval("g.V().none().none()"));
+ }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslatorTest.java
index e5c3ca7d01..e444c9bc96 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslatorTest.java
@@ -26,7 +26,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.Translator;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.CardinalityValueTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -61,6 +60,13 @@ public class PythonTranslatorTest {
assertEquals("g.V().has('person','name','marko')", gremlinAsPython);
}
+ @Test
+ public void shouldTranslateValues() {
+ final String gremlinAsPython = translator.translate(
+ g.V().values("age").asAdmin().getBytecode()).getScript();
+ assertEquals("g.V().age", gremlinAsPython);
+ }
+
@Test
public void shouldTranslateCardinality() {
final String gremlinAsPython = translator.translate(
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 51bfe761f8..2ae4603cd1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -1096,6 +1096,14 @@ namespace Gremlin.Net.Process.Traversal
return new GraphTraversal<object, E2>().Min<E2>(scope);
}
+ /// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the none step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, object> None()
+ {
+ return new GraphTraversal<object, object>().None();
+ }
+
/// <summary>
/// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the not 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 2fafd987a8..a97e660a2c 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -315,6 +315,12 @@ 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_none", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().None()}},
+ {"g_V_none_none", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().None().None()}},
+ {"g_V_none_fold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().None().Fold()}},
+ {"g_V_none_fold_none", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().None().Fold().None()}},
+ {"g_V_none_fold_constantX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().None().Fold().Constant<object>(1)}},
+ {"g_V_projectXxX_byXcoalesceXage_isXgtX29XX_noneXX_selectXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Project<object>("x").By(__.Coalesce<object>(__.Values<object>("age").Is(P.Gt(29)),__.None())).Select<object>("x")}},
{"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/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index 22f55bba57..f4f3263fd7 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -286,6 +286,12 @@ 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_none": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().None()}},
+ "g_V_none_none": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().None().None()}},
+ "g_V_none_fold": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().None().Fold()}},
+ "g_V_none_fold_none": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().None().Fold().None()}},
+ "g_V_none_fold_constantX1X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().None().Fold().Constant(1)}},
+ "g_V_projectXxX_byXcoalesceXage_isXgtX29XX_noneXX_selectXxX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Project("x").By(gremlingo.T__.Coalesce(gremlingo.T__.Values("age").Is(gremlingo.P.Gt(29)), gremlingo.T__.None())).Select("x")}},
"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-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 1838f66a09..1bbe704d19 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
@@ -1820,6 +1820,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 85866fd021..be9ba42240 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
@@ -306,6 +306,12 @@ 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_none: [function({g}) { return g.V().none() }],
+ g_V_none_none: [function({g}) { return g.V().none().none() }],
+ g_V_none_fold: [function({g}) { return g.V().none().fold() }],
+ g_V_none_fold_none: [function({g}) { return g.V().none().fold().none() }],
+ g_V_none_fold_constantX1X: [function({g}) { return g.V().none().fold().constant(1) }],
+ g_V_projectXxX_byXcoalesceXage_isXgtX29XX_noneXX_selectXxX: [function({g}) { return g.V().project("x").by(__.coalesce(__.values("age").is(P.gt(29)),__.none())).select("x") }],
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 de39307566..cd624eb88a 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -54,7 +54,6 @@ transactionPart
rootTraversal
: traversalSource DOT traversalSourceSpawnMethod
| traversalSource DOT traversalSourceSpawnMethod DOT chainedTraversal
- | traversalSource DOT traversalSourceSpawnMethod DOT chainedParentOfGraphTraversal
;
traversalSourceSelfMethod
@@ -158,12 +157,6 @@ traversalSourceSpawnMethod_union
chainedTraversal
: traversalMethod
| chainedTraversal DOT traversalMethod
- | chainedTraversal DOT chainedParentOfGraphTraversal
- ;
-
-chainedParentOfGraphTraversal
- : traversalSelfMethod
- | chainedParentOfGraphTraversal DOT traversalSelfMethod
;
nestedTraversal
@@ -240,6 +233,7 @@ traversalMethod
| traversalMethod_max
| traversalMethod_mean
| traversalMethod_min
+ | traversalMethod_none
| traversalMethod_not
| traversalMethod_option
| traversalMethod_optional
@@ -626,6 +620,10 @@ traversalMethod_min
| 'min' LPAREN traversalScopeArgument RPAREN #traversalMethod_min_Scope
;
+traversalMethod_none
+ : 'none' LPAREN RPAREN
+ ;
+
traversalMethod_not
: 'not' LPAREN nestedTraversal RPAREN
;
@@ -1146,10 +1144,6 @@ traversalSackMethod
: 'normSack' | 'Barrier.normSack'
;
-traversalSelfMethod
- : traversalSelfMethod_none
- ;
-
// Additional special rules that are derived from above
// These are used to restrict broad method signatures that accept lambdas
// to a smaller set.
@@ -1281,10 +1275,6 @@ traversalTerminalMethod_toBulkSet
: 'toBulkSet' LPAREN RPAREN
;
-traversalSelfMethod_none
- : 'none' LPAREN RPAREN
- ;
-
// Gremlin specific lexer rules
withOptionKeys
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 c5c30097cf..6316a1563f 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
@@ -1467,6 +1467,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)
@@ -2147,6 +2151,10 @@ def min_(*args):
return __.min_(*args)
+def none(*args):
+ return __.none(*args)
+
+
def not_(*args):
return __.not_(*args)
@@ -2535,6 +2543,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 0a4ddf9563..17a290b6d8 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -288,6 +288,12 @@ world.gremlins = {
'g_V_valuesXageX_isXgte_29X_isXlt_34X': [(lambda g:g.V().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)).name)],
'g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(P.gte(2))).name)],
+ 'g_V_none': [(lambda g:g.V().none())],
+ 'g_V_none_none': [(lambda g:g.V().none().none())],
+ 'g_V_none_fold': [(lambda g:g.V().none().fold())],
+ 'g_V_none_fold_none': [(lambda g:g.V().none().fold().none())],
+ 'g_V_none_fold_constantX1X': [(lambda g:g.V().none().fold().constant(1))],
+ 'g_V_projectXxX_byXcoalesceXage_isXgtX29XX_noneXX_selectXxX': [(lambda g:g.V().project('x').by(__.coalesce(__.age.is_(P.gt(29)),__.none())).select('x'))],
'g_V_orXhasXage_gt_27X__outE_count_gte_2X_name': [(lambda g:g.V().or_(__.has('age',P.gt(27)),__.outE().count().is_(P.gte(2))).name)],
'g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name': [(lambda g:g.V().or_(__.outE('knows'),__.has(T.label,'software').or_().has('age',P.gte(35))).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..59f9788497
--- /dev/null
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature
@@ -0,0 +1,81 @@
+# 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_none
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().none()
+ """
+ When iterated to list
+ Then the result should be empty
+
+ Scenario: g_V_none_none
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().none().none()
+ """
+ When iterated to list
+ Then the result should be empty
+
+ Scenario: g_V_none_fold
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().none().fold()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[] |
+
+ Scenario: g_V_none_fold_none
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().none().fold().none()
+ """
+ When iterated to list
+ Then the result should be empty
+
+ Scenario: g_V_none_fold_constantX1X
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().none().fold().constant(1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+
+ Scenario: g_V_projectXxX_byXcoalesceXage_isXgtX29XX_noneXX_selectXxX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().project("x").by(__.coalesce(__.values("age").is(P.gt(29)), __.none())).
+ select("x")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[32].i |
+ | d[35].i |
\ No newline at end of file