This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 79528ea76e95eab55432d241734b7c8e052af099 Merge: e1a5eab414 250b4eaa44 Author: Stephen Mallette <[email protected]> AuthorDate: Wed Mar 26 20:38:21 2025 -0400 Merge branch '3.8-dev' .../language/grammar/TraversalStrategyVisitor.java | 2 +- .../translator/DotNetTranslateVisitor.java | 28 ++++-- .../language/translator/GoTranslateVisitor.java | 27 ++++-- .../language/translator/JavaTranslateVisitor.java | 19 +++- .../AbstractWarningVerificationStrategy.java | 13 ++- .../ReservedKeysVerificationStrategy.java | 12 ++- .../grammar/TraversalStrategyVisitorTest.java | 2 +- .../language/translator/GremlinTranslatorTest.java | 18 ++++ gremlin-go/driver/strategies.go | 107 +++++++++++++++------ gremlin-go/driver/strategies_test.go | 6 +- .../gremlin-javascript/test/cucumber/gremlin.js | 2 +- .../src/main/python/radish/feature_steps.py | 14 ++- gremlin-python/src/main/python/radish/gremlin.py | 2 +- .../ReservedKeysVerificationStrategy.feature | 2 +- 14 files changed, 189 insertions(+), 65 deletions(-) diff --cc gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalStrategyVisitor.java index d3fca634a1,d3fca634a1..1e0a8b9177 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalStrategyVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalStrategyVisitor.java @@@ -95,7 -95,7 +95,7 @@@ public class TraversalStrategyVisitor e return (TraversalStrategy) clazz.getMethod("create", Configuration.class).invoke(null, conf); } } catch (Exception ex) { -- throw new IllegalStateException("TraversalStrategy not recognized - " + strategyName, ex); ++ throw new IllegalStateException("TraversalStrategy cannot be instantiated - " + strategyName, ex); } } } diff --cc gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java index 9830d8c95c,9802e26db0..4368cea1cd --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java @@@ -74,11 -74,20 +75,21 @@@ public class JavaTranslateVisitor exten final List<ParseTree> configs = ctx.children.stream(). filter(c -> c instanceof GremlinParser.ConfigurationContext).collect(Collectors.toList()); + - // the rest are the arguments to the strategy - for (ParseTree config : configs) { - sb.append("."); - visit(config); + if (configs.size() > 0 && ctx.getChild(1).getText().equals(OptionsStrategy.class.getSimpleName())) { + for (int ix = 0; ix < configs.size(); ix++) { + sb.append(".with(\""); + sb.append(configs.get(ix).getChild(0).getText()); + sb.append("\", "); + visit(configs.get(ix).getChild(2)); + sb.append(")"); + } + } else { + // the rest are the arguments to the strategy + for (ParseTree config : configs) { + sb.append("."); + visit(config); + } } sb.append(".create()"); diff --cc gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java index d0aba5fc0d,d0aba5fc0d..6810c56dfc --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/AbstractWarningVerificationStrategy.java @@@ -18,11 -18,11 +18,14 @@@ */ package org.apache.tinkerpop.gremlin.process.traversal.strategy.verification; ++import org.apache.commons.configuration2.BaseConfiguration; import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.MapConfiguration; ++import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy; import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy; ++import org.apache.tinkerpop.gremlin.util.GremlinDisabledListDelimiterHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@@ -73,10 -73,10 +76,12 @@@ public abstract class AbstractWarningVe @Override public Configuration getConfiguration() { -- final Map<String, Object> m = new LinkedHashMap<>(2); -- m.put(THROW_EXCEPTION, this.throwException); -- m.put(LOG_WARNING, this.logWarning); -- return new MapConfiguration(m); ++ final BaseConfiguration conf = new BaseConfiguration(); ++ conf.setListDelimiterHandler(GremlinDisabledListDelimiterHandler.instance()); ++ conf.setProperty(THROW_EXCEPTION, this.throwException); ++ conf.setProperty(LOG_WARNING, this.logWarning); ++ ++ return conf; } public static abstract class Builder<T extends AbstractWarningVerificationStrategy, B extends Builder> { diff --cc gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java index 460a05573d,460a05573d..43f4c8b86b --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/ReservedKeysVerificationStrategy.java @@@ -28,6 -28,6 +28,7 @@@ import org.apache.tinkerpop.gremlin.pro import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters; ++import org.apache.tinkerpop.gremlin.util.GremlinDisabledListDelimiterHandler; import java.util.ArrayList; import java.util.Arrays; @@@ -77,18 -77,18 +78,19 @@@ public class ReservedKeysVerificationSt } public static ReservedKeysVerificationStrategy create(final Configuration configuration) { ++ Set<String> keys = (Set) configuration.getProperty(KEYS); ++ if (null == keys) keys = new LinkedHashSet<>(DEFAULT_RESERVED_KEYS); return build() -- .reservedKeys(configuration.getList(KEYS, new ArrayList<>(DEFAULT_RESERVED_KEYS)). -- stream().map(Object::toString).collect(Collectors.toCollection(LinkedHashSet::new))) ++ .reservedKeys(keys) .throwException(configuration.getBoolean(THROW_EXCEPTION, false)) .logWarning(configuration.getBoolean(LOG_WARNING, false)).create(); } @Override public Configuration getConfiguration() { -- final Configuration c = super.getConfiguration(); -- c.setProperty(KEYS, this.reservedKeys); -- return c; ++ final Configuration conf = super.getConfiguration(); ++ conf.setProperty(KEYS, this.reservedKeys); ++ return conf; } public static ReservedKeysVerificationStrategy.Builder build() { diff --cc gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalStrategyVisitorTest.java index 6cd705110e,6cd705110e..42d957eebf --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalStrategyVisitorTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalStrategyVisitorTest.java @@@ -71,7 -71,7 +71,7 @@@ public class TraversalStrategyVisitorTe {"new ReservedKeysVerificationStrategy(logWarning: true, throwException: true)", ReservedKeysVerificationStrategy.build().logWarning(true).throwException(true).create()}, {"ReservedKeysVerificationStrategy(logWarning: true, throwException: true)", ReservedKeysVerificationStrategy.build().logWarning(true).throwException(true).create()}, {"new ReservedKeysVerificationStrategy(logWarning: true, throwException: false)", ReservedKeysVerificationStrategy.build().logWarning(true).create()}, -- {"new ReservedKeysVerificationStrategy(keys: ['a','b'])", ReservedKeysVerificationStrategy.build().reservedKeys(new LinkedHashSet<>(Arrays.asList("a", "b"))).create()}, ++ {"new ReservedKeysVerificationStrategy(keys: {'a','b'})", ReservedKeysVerificationStrategy.build().reservedKeys(new LinkedHashSet<>(Arrays.asList("a", "b"))).create()}, {"new SubgraphStrategy(vertices: hasLabel('person'))", SubgraphStrategy.build().vertices(hasLabel("person")).create()}, {"SubgraphStrategy(vertices: hasLabel('person'))", SubgraphStrategy.build().vertices(hasLabel("person")).create()}, {"new SubgraphStrategy(vertices: hasLabel('person'), edges: hasLabel('knows'), vertexProperties: has('time', between(1234, 4321)), checkAdjacentVertices: true)", SubgraphStrategy.build().vertices(hasLabel("person")).edges(hasLabel("knows")).vertexProperties(has("time", P.between(1234, 4321))).checkAdjacentVertices(true).create()}, diff --cc gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js index ef215c4bb0,c31c13953d..e533585a3c --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js @@@ -527,9 -490,9 +527,9 @@@ const gremlins = g_withStrategiesXRepeatUnrollStrategyX_V_repeatXoutX_timesX2X: [function({g}) { return g.withStrategies(new RepeatUnrollStrategy()).V().repeat(__.out()).times(2) }], g_withoutStrategiesXRepeatUnrollStrategyX_V_repeatXoutX_timesX2X: [function({g}) { return g.withoutStrategies(RepeatUnrollStrategy).V().repeat(__.out()).times(2) }], g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXid_123X_propertyXname_markoX: [function({g}) { return g.withStrategies(new ReservedKeysVerificationStrategy({throwException: true})).addV("person").property("id", 123).property("name", "marko") }], -- g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXage_29X_propertyXname_markoX: [function({g}) { return g.withStrategies(new ReservedKeysVerificationStrategy({throwException: true, keys: ["age"]})).addV("person").property("age", 29).property("name", "marko") }], ++ g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXage_29X_propertyXname_markoX: [function({g}) { return g.withStrategies(new ReservedKeysVerificationStrategy({throwException: true, keys: new Set(["age"])})).addV("person").property("age", 29).property("name", "marko") }], g_withoutStrategiesXReservedKeysVerificationStrategyX_addVXpersonX_propertyXid_123X_propertyXname_markoX: [function({g}) { return g.withoutStrategies(ReservedKeysVerificationStrategy).addV("person").property("id", 123).property("name", "marko") }], - g_withStrategiesXSeedStrategyX_V: [function({g}) { return g.withStrategies(new SeedStrategy({seed: 7})).V().coin(0.5) }], + g_withStrategiesXSeedStrategyX_V_coinX0.5X: [function({g}) { return g.withStrategies(new SeedStrategy({seed: 7})).V().coin(0.5) }], g_withoutStrategiesXSeedStrategyX_V: [function({g}) { return g.withoutStrategies(SeedStrategy).V() }], g_withStrategiesXStandardVerificationStrategyX_V: [function({g}) { return g.withStrategies(new StandardVerificationStrategy()).V() }], g_withoutStrategiesXStandardVerificationStrategyX_V: [function({g}) { return g.withoutStrategies(StandardVerificationStrategy).V() }], diff --cc gremlin-python/src/main/python/radish/feature_steps.py index cb622f7c06,8d07d7c71f..b09a0d009e --- a/gremlin-python/src/main/python/radish/feature_steps.py +++ b/gremlin-python/src/main/python/radish/feature_steps.py @@@ -36,40 -36,10 +36,43 @@@ project = __.projec tail = __.tail ignores = [ - "g.withoutStrategies(CountStrategy).V().count()" # serialization issues with Class in GraphSON + "g.withoutStrategies(CountStrategy).V().count()", # serialization issues with Class in GraphSON "g.withoutStrategies(LazyBarrierStrategy).V().as(\"label\").aggregate(local,\"x\").select(\"x\").select(\"label\")", "g.withSack(xx1, Operator.assign).V().local(__.out(\"knows\").barrier(Barrier.normSack)).in(\"knows\").barrier().sack()", # issues with BigInteger/BigDecimal - why do we carry BigDecimal? just use python Decimal module? - "g.withSack(2).V().sack(Operator.div).by(__.constant(xx1)).sack()" # issues with BigInteger/BigDecimal - why do we carry BigDecimal? just use python Decimal module? + "g.withSack(2).V().sack(Operator.div).by(__.constant(xx1)).sack()", # issues with BigInteger/BigDecimal - why do we carry BigDecimal? just use python Decimal module? + ## The following section has queries that aren't supported by gremlin-lang parameters + 'g.V().branch(l1).option("a", __.values("age")).option("b", __.values("lang")).option("b", __.values("name"))', + 'g.V().choose(pred1, __.out("knows"), __.in("created")).values("name")', + 'g.V().repeat(__.both()).until(pred1).groupCount().by("name")', + 'g.V().both().properties("name").order().by(c1).dedup().value()', + 'g.V().filter(pred1)', + 'g.V(vid1).filter(pred1)', + 'g.V(vid2).filter(pred1)', + 'g.V(vid1).out().filter(pred1)', + 'g.E().filter(pred1)', + 'g.V().out("created").has("name", __.map(l1).is(P.gt(3))).values("name")', + 'g.V(vid1).map(l1)', + 'g.V(vid1).outE().label().map(l1)', + 'g.V(vid1).out().map(l1).map(l2)', + 'g.withPath().V().as("a").out().map(l1)', + 'g.withPath().V().as("a").out().out().map(l1)', + 'g.V().values("name").order().by(c1).by(c2)', + 'g.V().order().by("name", c1).by("name", c2).values("name")', + 'g.V().hasLabel("person").order().by(l1, Order.desc).values("name")', + 'g.V(v1).hasLabel("person").map(l1).order(Scope.local).by(Column.values, Order.desc).by(Column.keys, Order.asc)', + 'g.V().valueMap().unfold().map(l1)', + 'g.E(e11)', + 'g.E(e7,e11)', + 'g.E(xx1)', + 'g.withSideEffect("a", xx1).V().both().values("name").aggregate(Scope.local,"a").cap("a")', + 'g.V().group().by(l1).by(__.constant(1))', + 'g.V(vid1).out().values("name").inject("daniel").as("a").map(l1).path()', + 'g.V().group("a").by(l1).by(__.constant(1)).cap("a")', - 'g.withSideEffect("a", xx1).V().both().values("name").store("a").cap("a")' ++ 'g.withSideEffect("a", xx1).V().both().values("name").store("a").cap("a")', + ## section end ++ 'g.withStrategies(ReservedKeysVerificationStrategy(throwException: true, keys: {"age"})).addV("person").property("age", 29).property("name", "marko")', # TINKERPOP-3055 ++ 'g.withStrategies(ReservedKeysVerificationStrategy(throwException: true)).addV("person").property("id", 123).property("name", "marko")', # TINKERPOP-3055 ++ 'g.withoutStrategies(ReservedKeysVerificationStrategy).addV("person").property("id", 123).property("name", "marko")' # TINKERPOP-3055 ] @@@ -82,6 -52,6 +85,9 @@@ def choose_graph(step, graph_name) if not step.context.ignore: step.context.ignore = "AllowNullPropertyValues" in tagset ++ if not step.context.ignore: ++ step.context.ignore = "WithReservedKeysVerificationStrategy" in tagset ++ if (step.context.ignore): return @@@ -174,11 -155,17 +180,17 @@@ def next_the_traversal(step) @then("the traversal will raise an error") def raise_an_error(step): - if step.context.ignore: ++ if (step.context.ignore): + return + assert_that(step.context.failed, equal_to(True)) @then("the traversal will raise an error with message {comparison:w} text of {expected_message:QuotedString}") def raise_an_error_with_message(step, comparison, expected_message): - if step.context.ignore: ++ if (step.context.ignore): + return - ++ assert_that(step.context.failed, equal_to(True)) if comparison == "containing": diff --cc gremlin-python/src/main/python/radish/gremlin.py index 0b634f87c8,e6c38d9826..022b317416 --- a/gremlin-python/src/main/python/radish/gremlin.py +++ b/gremlin-python/src/main/python/radish/gremlin.py @@@ -505,16 -468,16 +505,16 @@@ world.gremlins = 'g_withStrategiesXReadOnlyStrategyX_E_propertyXweight_0X': [(lambda g:g.with_strategies(ReadOnlyStrategy()).E().property('weight', 0))], 'g_V_classic_recommendation': [(lambda g:g.V().has('name', 'DARK STAR').as_('a').out('followedBy').aggregate('stash').in_('followedBy').where(P.neq('a').and_(P.not_(P.within('stash')))).group_count().unfold().project('x', 'y', 'z').by(__.select(Column.keys).values('name')).by(__.select(Column.keys).values('performances')).by(__.select(Column.values)).order().by(__.select('z'), Order.desc).by(__.select('y'), Order.asc).limit(5).aggregate(Scope.local, 'm').select('x'))], 'g_withStrategiesXReferenceElementStrategyX_V': [(lambda g:g.with_strategies(ReferenceElementStrategy()).V())], - 'g_withoutStrategiesXReferenceElementStrategyX_V': [(lambda g:g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ReferenceElementStrategy')]).V())], + 'g_withoutStrategiesXReferenceElementStrategyX_V': [(lambda g:g.without_strategies(ReferenceElementStrategy).V())], 'g_withStrategiesXRepeatUnrollStrategyX_V_repeatXoutX_timesX2X': [(lambda g:g.with_strategies(RepeatUnrollStrategy()).V().repeat(__.out()).times(2))], - 'g_withoutStrategiesXRepeatUnrollStrategyX_V_repeatXoutX_timesX2X': [(lambda g:g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy')]).V().repeat(__.out()).times(2))], + 'g_withoutStrategiesXRepeatUnrollStrategyX_V_repeatXoutX_timesX2X': [(lambda g:g.without_strategies(RepeatUnrollStrategy).V().repeat(__.out()).times(2))], 'g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXid_123X_propertyXname_markoX': [(lambda g:g.with_strategies(ReservedKeysVerificationStrategy(throw_exception=True)).add_v('person').property('id', 123).property('name', 'marko'))], -- 'g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXage_29X_propertyXname_markoX': [(lambda g:g.with_strategies(ReservedKeysVerificationStrategy(throw_exception=True, keys=['age'])).add_v('person').property('age', 29).property('name', 'marko'))], - 'g_withoutStrategiesXReservedKeysVerificationStrategyX_addVXpersonX_propertyXid_123X_propertyXname_markoX': [(lambda g:g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy')]).add_v('person').property('id', 123).property('name', 'marko'))], - 'g_withStrategiesXSeedStrategyX_V': [(lambda g:g.with_strategies(SeedStrategy(seed=7)).V().coin(0.5))], - 'g_withoutStrategiesXSeedStrategyX_V': [(lambda g:g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V())], ++ 'g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXage_29X_propertyXname_markoX': [(lambda g:g.with_strategies(ReservedKeysVerificationStrategy(throw_exception=True, keys={'age'})).add_v('person').property('age', 29).property('name', 'marko'))], + 'g_withoutStrategiesXReservedKeysVerificationStrategyX_addVXpersonX_propertyXid_123X_propertyXname_markoX': [(lambda g:g.without_strategies(ReservedKeysVerificationStrategy).add_v('person').property('id', 123).property('name', 'marko'))], + 'g_withStrategiesXSeedStrategyX_V_coinX0.5X': [(lambda g:g.with_strategies(SeedStrategy(seed=7)).V().coin(0.5))], + 'g_withoutStrategiesXSeedStrategyX_V': [(lambda g:g.without_strategies(SeedStrategy).V())], 'g_withStrategiesXStandardVerificationStrategyX_V': [(lambda g:g.with_strategies(StandardVerificationStrategy()).V())], - 'g_withoutStrategiesXStandardVerificationStrategyX_V': [(lambda g:g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy')]).V())], + 'g_withoutStrategiesXStandardVerificationStrategyX_V': [(lambda g:g.without_strategies(StandardVerificationStrategy).V())], 'g_withStrategiesXSubgraphStrategyXsubgraphAXX_V': [(lambda g:g.with_strategies(SubgraphStrategy(vertices=__.has('name', P.within('josh', 'lop', 'ripple')))).V())], 'g_withStrategiesXSubgraphStrategyXsubgraphAXX_E': [(lambda g:g.with_strategies(SubgraphStrategy(vertices=__.has('name', P.within('josh', 'lop', 'ripple')))).E())], 'g_withStrategiesXSubgraphStrategyXsubgraphAXX_VX4X_outE': [(lambda g, vid4=None:g.with_strategies(SubgraphStrategy(vertices=__.has('name', P.within('josh', 'lop', 'ripple')))).V(vid4).out_e())],
