TINKERPOP-1895 Fixed jython based evaluations of withStrategies Similar to TINKERPOP-1896 in that a lambda would trigger a scriptengine evaluation with jython which would fail when withStrategies() was used as the JythonTranslator was actually producing Python valid code rather than Jython valid code.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/f3172bc5 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/f3172bc5 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/f3172bc5 Branch: refs/heads/TINKERPOP-1896 Commit: f3172bc55ef3e8f298dccfeb18c9fe6b4c27767c Parents: 5feadbd Author: Stephen Mallette <sp...@genoprime.com> Authored: Fri Mar 9 09:38:35 2018 -0500 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Mon Mar 12 11:56:16 2018 -0400 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + .../gremlin/python/jsr223/JythonTranslator.java | 19 +++++++++++++++++++ .../gremlin/python/jsr223/PythonTranslator.java | 14 ++++++++------ .../python/jsr223/JythonTranslatorTest.java | 13 +++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f3172bc5/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index a761003..350fce8 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -31,6 +31,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima * Bumped to Jackson 2.9.4. * Added `idleConnectionTimeout` and `keepAliveInterval` to Gremlin Server that enables a "ping" and auto-close for seemingly dead clients. * Fixed a bug where lambdas in `gremlin-python` would trigger a failure if steps using python-only symbols were present (such as `as_()`). +* Fixed a bug where lambdas in `gremlin-python` would trigger a failure if `withStrategies()` was evaluated. * Fixed a bug in `NumberHelper` that led to wrong min/max results if numbers exceeded the Integer limits. * Delayed setting of the request identifier until `RequestMessage` construction by the builder. * Improved error messaging for failed serialization and deserialization of request/response messages. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f3172bc5/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java index f8a5bc3..3d7d9fe 100644 --- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java +++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslator.java @@ -19,8 +19,17 @@ package org.apache.tinkerpop.gremlin.python.jsr223; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration.MapConfiguration; +import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy; import org.apache.tinkerpop.gremlin.util.function.Lambda; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + /** * @author Marko A. Rodriguez (http://markorodriguez.com) * @author Stephen Mallette (http://stephen.genoprime.com) @@ -63,4 +72,14 @@ public final class JythonTranslator extends PythonTranslator { // jython one can just pass them through. return methodName; } + + @Override + protected String resolveTraversalStrategyProxy(final TraversalStrategyProxy proxy) { + // since this is jython we don't need a traversal proxy here - we need the actual JVM version of the strategy + // since this script will be executed in Jython. + if (proxy.getConfiguration().isEmpty()) + return proxy.getStrategyClass().getCanonicalName() + ".instance()"; + else + return proxy.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration.MapConfiguration(" + convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + "))"; + } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f3172bc5/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java index 7c74b85..d8c73f0 100644 --- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java +++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java @@ -139,7 +139,7 @@ public class PythonTranslator implements Translator.ScriptTranslator { return traversalScript.toString(); } - private String convertToString(final Object object) { + protected String convertToString(final Object object) { if (object instanceof Bytecode.Binding) return ((Bytecode.Binding) object).variable(); else if (object instanceof Bytecode) @@ -172,11 +172,7 @@ public class PythonTranslator implements Translator.ScriptTranslator { } else if (object instanceof Long) return object + "L"; else if (object instanceof TraversalStrategyProxy) { - final TraversalStrategyProxy proxy = (TraversalStrategyProxy) object; - if (proxy.getConfiguration().isEmpty()) - return "TraversalStrategy(\"" + proxy.getStrategyClass().getSimpleName() + "\")"; - else - return "TraversalStrategy(\"" + proxy.getStrategyClass().getSimpleName() + "\"," + convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + ")"; + return resolveTraversalStrategyProxy((TraversalStrategyProxy) object); } else if (object instanceof TraversalStrategy) { return convertToString(new TraversalStrategyProxy((TraversalStrategy) object)); } else if (object instanceof Boolean) @@ -242,4 +238,10 @@ public class PythonTranslator implements Translator.ScriptTranslator { return SymbolHelper.toPython(methodName); } + protected String resolveTraversalStrategyProxy(final TraversalStrategyProxy proxy) { + if (proxy.getConfiguration().isEmpty()) + return "TraversalStrategy(\"" + proxy.getStrategyClass().getSimpleName() + "\")"; + else + return "TraversalStrategy(\"" + proxy.getStrategyClass().getSimpleName() + "\"," + convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + ")"; + } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f3172bc5/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java index 86e3b78..e35898b 100644 --- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java +++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonTranslatorTest.java @@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; 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.strategy.decoration.TranslationStrategy; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory; import org.apache.tinkerpop.gremlin.util.function.Lambda; @@ -103,4 +104,16 @@ public class JythonTranslatorTest { assertEquals(6, o.size()); } + + @Test + public void shouldTranslateToJythonWhenUsingLambdasAndStrategies() throws Exception { + // the jython translation kicks in when you add a lambda so ensure that it translates when strategies are + // present + GraphTraversalSource g = TinkerFactory.createModern().traversal(); + g = g.withStrategies(new TranslationStrategy(g, JythonTranslator.of("g"))); + final List<Object> o = g.withStrategies(ReadOnlyStrategy.instance()). + V().has("name").map(Lambda.function("lambda x: type(x.get())")).toList(); + + assertEquals(6, o.size()); + } }