This is an automated email from the ASF dual-hosted git repository.
xiazcy pushed a commit to branch 3.8-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/3.8-dev by this push:
new 7bf19dfb1f Disallow the use of `choose().option(Traversal, v)` (#3244)
7bf19dfb1f is described below
commit 7bf19dfb1f62ef03b898c72808ffed9ad6d7b876
Author: Yang Xia <[email protected]>
AuthorDate: Mon Oct 20 17:37:16 2025 -0700
Disallow the use of `choose().option(Traversal, v)` (#3244)
---
CHANGELOG.asciidoc | 1 +
docs/src/dev/provider/gremlin-semantics.asciidoc | 6 ++--
docs/src/upgrade/release-3.8.x.asciidoc | 37 ++++++++++++++++++++++
.../process/traversal/step/branch/ChooseStep.java | 6 ++--
.../traversal/step/branch/ChooseStepTest.java | 10 ++++++
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 3 ++
gremlin-go/driver/cucumber/gremlin.go | 3 ++
.../gremlin-javascript/test/cucumber/gremlin.js | 3 ++
gremlin-python/src/main/python/radish/gremlin.py | 3 ++
.../gremlin/test/features/branch/Choose.feature | 29 ++++++++++++++++-
.../gremlin/test/features/branch/Union.feature | 17 +++++++++-
11 files changed, 111 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 888cf44f03..0a912be998 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -71,6 +71,7 @@ This release also includes changes from <<release-3-7-XXX,
3.7.XXX>>.
* Changed `choose` to only use the first `option` matched.
* Added `Pick.unproductive` to allow for matches on unproductive predicates.
* Changed `choose` to pass through traversers of unproductive predicates and
unmatched choices.
+* Disallowed `Traversal` as a `Pick` token for `option` in `choose`.
* Updated `OptionsStrategy` in `gremlin-python` to take options directly as
keyword arguments.
* Added static `instance()` method to `ElementIdStrategy` to an instance with
the default configuration.
* Updated `ElementIdStrategy.getConfiguration()` to help with serialization.
diff --git a/docs/src/dev/provider/gremlin-semantics.asciidoc
b/docs/src/dev/provider/gremlin-semantics.asciidoc
index dff6cda769..8ac0f17449 100644
--- a/docs/src/dev/provider/gremlin-semantics.asciidoc
+++ b/docs/src/dev/provider/gremlin-semantics.asciidoc
@@ -1138,9 +1138,9 @@
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#call-step[reference]
*Modulation:*
* `option(pickToken, traversalOption)` - Adds a traversal option to the
`choose` step. The `pickToken` is matched
-against the result of the choice traversal. The `pickToken` may be a literal
value, a predicate `P`, a `Traversal`
-(whose first returned value is used for matching) or a `Pick` enum value. If a
match is found, the traverser is routed
-to the corresponding `traversalOption`.
+against the result of the choice traversal. The `pickToken` may be a literal
value, a predicate `P` or a `Pick` enum
+value. `Traversal` is not allowed as a `pickToken` here and will lead to
`IllegalArgumentException`. If a match is
+found, the traverser is routed to the corresponding `traversalOption`.
*Considerations:*
diff --git a/docs/src/upgrade/release-3.8.x.asciidoc
b/docs/src/upgrade/release-3.8.x.asciidoc
index e8795e8b43..1e03810bd6 100644
--- a/docs/src/upgrade/release-3.8.x.asciidoc
+++ b/docs/src/upgrade/release-3.8.x.asciidoc
@@ -697,6 +697,43 @@ gremlin> g.V().choose(__.values("age")).
==>peter
----
+*Removal of choose().option(Traversal, v)*
+
+The `choose().option(Traversal, v)` was relatively unused in comparison to the
other overloads with constants, predicates
+and Pick tokens. The previous implementation often led to confusion as it only
evaluated if the traversal was productive,
+rather than performing comparisons based on the traversal's output value. To
eliminate this confusion, `Traversal` is no
+longer permitted as an option token for `choose()`. Any usages which are
dependent on the Traversal for dynamic case
+matching can be rewritten using `union()`, with filters prepended to each
child traversal.
+
+[source,text]
+----
+// 3.7.x
+gremlin> g.V().hasLabel("person").choose(identity()).
+......1> option(outE().count().is(P.gt(2)), values("age")).
+......2> option(none, values("name"))
+==>29
+==>vadas
+==>josh
+==>peter
+
+// 3.8.0 - an IllegalArgumentException will be thrown
+gremlin> g.V().hasLabel("person").choose(identity()).
+......1> option(outE().count().is(P.gt(2)), values("age")).
+......2> option(none, values("name"))
+Traversal is not allowed as a Pick token for choose().option()
+Type ':help' or ':h' for help.
+Display stack trace? [yN]n
+
+// use union() in these cases
+gremlin> g.V().hasLabel("person").union(
+......1> where(outE().count().is(P.gt(2))).values("age"),
+......2> __.not(where(outE().count().is(P.gt(2)))).values("name"))
+==>29
+==>vadas
+==>josh
+==>peter
+----
+
See: link:https://issues.apache.org/jira/browse/TINKERPOP-3178[TINKERPOP-3178],
link:https://tinkerpop.apache.org/docs/3.8.0/reference/#choose-step[Reference
Documentation - choose()]
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
index 9ca0d101ec..366ad6bfde 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
@@ -62,11 +62,11 @@ public final class ChooseStep<S, E, M> extends
BranchStep<S, E, M> {
private boolean hasDefaultNone = true;
private ChooseStep(final Traversal.Admin traversal, final
Traversal.Admin<S, M> choiceTraversal,
- final ChooseSemantics chooseSemantics) {
+ final ChooseSemantics chooseSemantics) {
super(traversal);
this.chooseSemantics = chooseSemantics;
this.setBranchTraversal(choiceTraversal);
-
+
// defaults Pick.unproductive/none options are just identity()
final Traversal.Admin<S,E> unproductivePassthrough = new
DefaultGraphTraversal<>();
unproductivePassthrough.addStep(new IdentityStep<>(traversal));
@@ -120,6 +120,8 @@ public final class ChooseStep<S, E, M> extends
BranchStep<S, E, M> {
} else if (pickToken == Pick.none &&
!this.traversalPickOptions.containsKey(Pick.none)) {
super.addChildOption(pickToken, traversalOption);
}
+ } else if (pickToken instanceof Traversal) {
+ throw new IllegalArgumentException("Traversal is not allowed as a
Pick token for choose().option()");
} else {
super.addChildOption(pickToken, traversalOption);
}
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java
index 604ae20ec8..ac7218b3f5 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java
@@ -22,6 +22,7 @@ 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.Arrays;
import java.util.List;
@@ -30,6 +31,7 @@ import static
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
import static
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
import static org.apache.tinkerpop.gremlin.process.traversal.Pick.none;
+import static org.junit.Assert.assertThrows;
/**
* @author Daniel Kuppitz (http://gremlin.guru)
@@ -48,4 +50,12 @@ public class ChooseStepTest extends StepTest {
__.choose(out("knows").is(P.gt(0)), out("knows"))
);
}
+
+ @Test
+ public void shouldRejectTraversalAsOptionToken() {
+ assertThrows(IllegalArgumentException.class, () -> {
+ __.choose(__.hasLabel("person")).
+ option(__.values("name"), __.out("knows"));
+ });
+ }
}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 9ab8812476..9bbaea98a7 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -104,6 +104,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_chooseXhasXname_vadasX__valuesXnameXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Choose<object>(__.Has("name", "vadas"),
__.Values<object>("name"))}},
{"g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX_constantXotherXX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().HasLabel("person").Values<object>("age").Choose<object>(P.Eq(29),
__.Constant<object>("matched"), __.Constant<object>("other"))}},
{"g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().HasLabel("person").Values<object>("age").Choose<object>(P.Eq(29),
__.Constant<object>("matched"))}},
+
{"g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_isXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().HasLabel("person").Choose<object>(__.Values<object>("name")).Option(__.Is("marko"),
__.Values<object>("age")).Option(Pick.None, __.Values<object>("name"))}},
+
{"g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_PeqXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().HasLabel("person").Choose<object>(__.Values<object>("name")).Option(P.Eq("marko"),
__.Values<object>("age")).Option(Pick.None, __.Values<object>("name"))}},
{"g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().Local<object>(__.Properties<object>("location").Order().By(T.Value,
Order.Asc).Range<object>(0, 2)).Value<object>()}},
{"g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Has(T.Label,
"person").As("a").Local<object>(__.Out("created").As("b")).Select<object>("a",
"b").By("name").By(T.Id)}},
{"g_V_localXoutE_countX", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.V().Local<object>(__.OutE().Count())}},
@@ -169,6 +171,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V(p["vid1"],
p["vid2"]).Local<object>(__.Union<object>(__.OutE().Count(), __.InE().Count(),
__.OutE().Values<object>("weight").Sum<object>()))}},
{"g_VX1_2X_localXunionXcountXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V(p["vid1"],
p["vid2"]).Local<object>(__.Union<object>(__.Count()))}},
{"g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Union<object>(__.AddV("person").Property("name", "alice"),
__.AddV("person").Property("name", "bob"), __.AddV("person").Property("name",
"chris")).Values<object>("name")}},
+
{"g_VX_hasLabelXpersonX_unionX_whereX_out_count_isXgtX2XXX_valuesXageX_notX_whereX_bothE_count_isXgt2XXX_valusXnameXX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().HasLabel("person").Union<object>(__.Where(__.OutE().Count().Is(P.Gt(2))).Values<object>("age"),
__.Not(__.Where(__.OutE().Count().Is(P.Gt(2)))).Values<object>("name"))}},
{"g_V_aggregateXxX_byXnameX_byXageX_capXxX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Aggregate("x").By("name").By("age").Cap<object>("x")}},
{"g_V_aggregateXScope_local_xX_byXnameX_byXageX_capXxX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Aggregate(Scope.Local,
"x").By("name").By("age").Cap<object>("x")}},
{"g_V_valuesXageX_allXgtX32XX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Values<object>("age").All(P.Gt(32))}},
diff --git a/gremlin-go/driver/cucumber/gremlin.go
b/gremlin-go/driver/cucumber/gremlin.go
index 3c3d92fc6b..d80c8bf088 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -74,6 +74,8 @@ var translationMap = map[string][]func(g
*gremlingo.GraphTraversalSource, p map[
"g_V_chooseXhasXname_vadasX__valuesXnameXX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V().Choose(gremlingo.T__.Has("name",
"vadas"), gremlingo.T__.Values("name"))}},
"g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX_constantXotherXX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Values("age").Choose(gremlingo.P.Eq(29),
gremlingo.T__.Constant("matched"), gremlingo.T__.Constant("other"))}},
"g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Values("age").Choose(gremlingo.P.Eq(29),
gremlingo.T__.Constant("matched"))}},
+
"g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_isXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Choose(gremlingo.T__.Values("name")).Option(gremlingo.T__.Is("marko"),
gremlingo.T__.Values("age")).Option(gremlingo.Pick.None,
gremlingo.T__.Values("name"))}},
+
"g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_PeqXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Choose(gremlingo.T__.Values("name")).Option(gremlingo.P.Eq("marko"),
gremlingo.T__.Values("age")).Option(gremlingo.Pick.None,
gremlingo.T__.Values("name"))}},
"g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().Local(gremlingo.T__.Properties("location").Order().By(gremlingo.T.Value,
gremlingo.Order.Asc).Range(0, 2)).Value()}},
"g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label,
"person").As("a").Local(gremlingo.T__.Out("created").As("b")).Select("a",
"b").By("name").By(gremlingo.T.Id)}},
"g_V_localXoutE_countX": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return
g.V().Local(gremlingo.T__.OutE().Count())}},
@@ -139,6 +141,7 @@ var translationMap = map[string][]func(g
*gremlingo.GraphTraversalSource, p map[
"g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V(p["vid1"],
p["vid2"]).Local(gremlingo.T__.Union(gremlingo.T__.OutE().Count(),
gremlingo.T__.InE().Count(), gremlingo.T__.OutE().Values("weight").Sum()))}},
"g_VX1_2X_localXunionXcountXX": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"],
p["vid2"]).Local(gremlingo.T__.Union(gremlingo.T__.Count()))}},
"g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.Union(gremlingo.T__.AddV("person").Property("name", "alice"),
gremlingo.T__.AddV("person").Property("name", "bob"),
gremlingo.T__.AddV("person").Property("name", "chris")).Values("name")}},
+
"g_VX_hasLabelXpersonX_unionX_whereX_out_count_isXgtX2XXX_valuesXageX_notX_whereX_bothE_count_isXgt2XXX_valusXnameXX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Union(gremlingo.T__.Where(gremlingo.T__.OutE().Count().Is(gremlingo.P.Gt(2))).Values("age"),
gremlingo.T__.Not(gremlingo.T__.Where(gremlingo.T__.OutE().Count().Is(gremlingo.P.Gt(2)))).Values("name"))}},
"g_V_aggregateXxX_byXnameX_byXageX_capXxX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().Aggregate("x").By("name").By("age").Cap("x")}},
"g_V_aggregateXScope_local_xX_byXnameX_byXageX_capXxX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V().Aggregate(gremlingo.Scope.Local,
"x").By("name").By("age").Cap("x")}},
"g_V_valuesXageX_allXgtX32XX": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return
g.V().Values("age").All(gremlingo.P.Gt(32))}},
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 e01d05fbc1..0e31f0c437 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
@@ -105,6 +105,8 @@ const gremlins = {
g_V_chooseXhasXname_vadasX__valuesXnameXX: [function({g}) { return
g.V().choose(__.has("name", "vadas"), __.values("name")) }],
g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX_constantXotherXX:
[function({g}) { return g.V().hasLabel("person").values("age").choose(P.eq(29),
__.constant("matched"), __.constant("other")) }],
g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX: [function({g})
{ return g.V().hasLabel("person").values("age").choose(P.eq(29),
__.constant("matched")) }],
+
g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_isXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX:
[function({g}) { return
g.V().hasLabel("person").choose(__.values("name")).option(__.is("marko"),
__.values("age")).option(Pick.none, __.values("name")) }],
+
g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_PeqXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX:
[function({g}) { return
g.V().hasLabel("person").choose(__.values("name")).option(P.eq("marko"),
__.values("age")).option(Pick.none, __.values("name")) }],
g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value:
[function({g}) { return
g.V().local(__.properties("location").order().by(T.value, Order.asc).range(0,
2)).value() }],
g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX:
[function({g}) { return g.V().has(T.label,
"person").as("a").local(__.out("created").as("b")).select("a",
"b").by("name").by(T.id) }],
g_V_localXoutE_countX: [function({g}) { return
g.V().local(__.outE().count()) }],
@@ -170,6 +172,7 @@ const gremlins = {
g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX:
[function({g, vid2, vid1}) { return g.V(vid1,
vid2).local(__.union(__.outE().count(), __.inE().count(),
__.outE().values("weight").sum())) }],
g_VX1_2X_localXunionXcountXX: [function({g, vid2, vid1}) { return
g.V(vid1, vid2).local(__.union(__.count())) }],
g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name:
[function({g}) { return g.union(__.addV("person").property("name", "alice"),
__.addV("person").property("name", "bob"), __.addV("person").property("name",
"chris")).values("name") }],
+
g_VX_hasLabelXpersonX_unionX_whereX_out_count_isXgtX2XXX_valuesXageX_notX_whereX_bothE_count_isXgt2XXX_valusXnameXX:
[function({g}) { return
g.V().hasLabel("person").union(__.where(__.outE().count().is(P.gt(2))).values("age"),
__.not(__.where(__.outE().count().is(P.gt(2)))).values("name")) }],
g_V_aggregateXxX_byXnameX_byXageX_capXxX: [function({g}) { return
g.V().aggregate("x").by("name").by("age").cap("x") }],
g_V_aggregateXScope_local_xX_byXnameX_byXageX_capXxX: [function({g}) {
return g.V().aggregate(Scope.local, "x").by("name").by("age").cap("x") }],
g_V_valuesXageX_allXgtX32XX: [function({g}) { return
g.V().values("age").all(P.gt(32)) }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py
b/gremlin-python/src/main/python/radish/gremlin.py
index 3fd2da2666..264caf10ed 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -77,6 +77,8 @@ world.gremlins = {
'g_V_chooseXhasXname_vadasX__valuesXnameXX': [(lambda
g:g.V().choose(__.has('name', 'vadas'), __.values('name')))],
'g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX_constantXotherXX':
[(lambda g:g.V().has_label('person').values('age').choose(P.eq(29),
__.constant('matched'), __.constant('other')))],
'g_V_hasLabelXpersonX_age_chooseXP_eqX29X_constantXmatchedX': [(lambda
g:g.V().has_label('person').values('age').choose(P.eq(29),
__.constant('matched')))],
+
'g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_isXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX':
[(lambda
g:g.V().has_label('person').choose(__.values('name')).option(__.is_('marko'),
__.values('age')).option(Pick.none, __.values('name')))],
+
'g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_PeqXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX':
[(lambda
g:g.V().has_label('person').choose(__.values('name')).option(P.eq('marko'),
__.values('age')).option(Pick.none, __.values('name')))],
'g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value': [(lambda
g:g.V().local(__.properties('location').order().by(T.value,
Order.asc).range_(0, 2)).value())],
'g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX':
[(lambda g:g.V().has(T.label,
'person').as_('a').local(__.out('created').as_('b')).select('a',
'b').by('name').by(T.id_))],
'g_V_localXoutE_countX': [(lambda g:g.V().local(__.out_e().count()))],
@@ -142,6 +144,7 @@ world.gremlins = {
'g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX': [(lambda
g, vid2=None,vid1=None:g.V(vid1, vid2).local(__.union(__.out_e().count(),
__.in_e().count(), __.out_e().values('weight').sum_())))],
'g_VX1_2X_localXunionXcountXX': [(lambda g, vid2=None,vid1=None:g.V(vid1,
vid2).local(__.union(__.count())))],
'g_unionXaddVXpersonX_propertyXname_aliceX_addVXpersonX_propertyXname_bobX_addVXpersonX_propertyXname_chrisX_name':
[(lambda g:g.union(__.add_v('person').property('name', 'alice'),
__.add_v('person').property('name', 'bob'), __.add_v('person').property('name',
'chris')).values('name'))],
+
'g_VX_hasLabelXpersonX_unionX_whereX_out_count_isXgtX2XXX_valuesXageX_notX_whereX_bothE_count_isXgt2XXX_valusXnameXX':
[(lambda
g:g.V().has_label('person').union(__.where(__.out_e().count().is_(P.gt(2))).values('age'),
__.not_(__.where(__.out_e().count().is_(P.gt(2)))).values('name')))],
'g_V_aggregateXxX_byXnameX_byXageX_capXxX': [(lambda
g:g.V().aggregate('x').by('name').by('age').cap('x'))],
'g_V_aggregateXScope_local_xX_byXnameX_byXageX_capXxX': [(lambda
g:g.V().aggregate(Scope.local, 'x').by('name').by('age').cap('x'))],
'g_V_valuesXageX_allXgtX32XX': [(lambda
g:g.V().values('age').all_(P.gt(32)))],
diff --git
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
index f6c24ff724..18f80f0084 100644
---
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
+++
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Choose.feature
@@ -666,4 +666,31 @@ Feature: Step - choose()
| matched |
| d[27].i |
| d[32].i |
- | d[35].i |
\ No newline at end of file
+ | d[35].i |
+
+ Scenario:
g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_isXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().hasLabel("person").choose(values("name")).
+ option(is("marko"), values("age")).
+ option(Pick.none, values("name"))
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of
"Traversal is not allowed as a Pick token"
+
+ Scenario:
g_V_hasLabelXpersonX_chooseX_valuesXnameX_option1X_PeqXmarkoX_valuesXageXX_option2Xnone_valuesXnameXX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().hasLabel("person").choose(values("name")).
+ option(P.eq("marko"), values("age")).
+ option(Pick.none, values("name"))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | vadas |
+ | josh |
+ | peter |
diff --git
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature
index 20b4713a01..92d76f1c92 100644
---
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature
+++
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Union.feature
@@ -296,4 +296,19 @@ Feature: Step - union()
| result |
| alice |
| bob |
- | chris |
\ No newline at end of file
+ | chris |
+
+ Scenario:
g_VX_hasLabelXpersonX_unionX_whereX_out_count_isXgtX2XXX_valuesXageX_notX_whereX_bothE_count_isXgt2XXX_valusXnameXX
+ Given the modern graph
+ And the traversal of
+ """
+
g.V().hasLabel("person").union(where(outE().count().is(P.gt(2))).values("age"),
+
__.not(where(outE().count().is(P.gt(2)))).values("name"))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | vadas |
+ | josh |
+ | peter |
\ No newline at end of file