You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2016/06/23 14:55:57 UTC
tinkerpop git commit: created CoreImports in gremlin-core which has
getImportClasses(), getImportMethods(),
getImportEnums() which is used by GremlinJythonScriptEngine,
but should be used by GremlinGroovyScriptEngine as well and all subsequent
GremlinXXX
Repository: tinkerpop
Updated Branches:
refs/heads/TINKERPOP-1278 2db67c08e -> 77b1bbddd
created CoreImports in gremlin-core which has getImportClasses(), getImportMethods(), getImportEnums() which is used by GremlinJythonScriptEngine, but should be used by GremlinGroovyScriptEngine as well and all subsequent GremlinXXXScriptEngine. Added toSet(), next(amount) to gremlin_python... added more tests to GremlinJythonScriptEngineTest. Created SymbolHelper which is useful for converting symbols between Python and Java -- generlized out of GremlinPythonSourceGenerator.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/77b1bbdd
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/77b1bbdd
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/77b1bbdd
Branch: refs/heads/TINKERPOP-1278
Commit: 77b1bbddd3ac1fae8c60843cb2e0eef14aa1afdf
Parents: 2db67c0
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jun 23 08:55:50 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jun 23 08:55:50 2016 -0600
----------------------------------------------------------------------
.../tinkerpop/gremlin/util/CoreImports.java | 222 +++++++++++++++++++
.../python/GremlinPythonSourceGenerator.groovy | 62 +++---
.../jsr223/GremlinJythonScriptEngine.java | 32 ++-
.../gremlin/python/util/SymbolHelper.java | 58 +++++
.../jython/gremlin_python/gremlin_python.py | 65 +++---
.../jython/gremlin_python/groovy_translator.py | 6 +-
.../jsr223/GremlinJythonScriptEngineTest.java | 46 +++-
7 files changed, 416 insertions(+), 75 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77b1bbdd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
new file mode 100644
index 0000000..b1bf59e
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
@@ -0,0 +1,222 @@
+/*
+ * 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.util;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.tinkerpop.gremlin.process.computer.Computer;
+import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
+import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
+import org.apache.tinkerpop.gremlin.process.computer.Memory;
+import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.bulkdumping.BulkDumperVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoaderVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.PeerPressureVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy;
+import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
+import org.apache.tinkerpop.gremlin.process.remote.RemoteGraph;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+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.creation.TranslationStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.LazyBarrierStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.Translator;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
+import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Transaction;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.io.GraphReader;
+import org.apache.tinkerpop.gremlin.structure.io.GraphWriter;
+import org.apache.tinkerpop.gremlin.structure.io.Io;
+import org.apache.tinkerpop.gremlin.structure.io.IoCore;
+import org.apache.tinkerpop.gremlin.structure.io.Storage;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class CoreImports {
+
+ private final static Set<Class> CLASS_IMPORTS = new HashSet<>();
+ private final static Set<Method> METHOD_IMPORTS = new HashSet<>();
+ private final static Set<Enum> ENUM_IMPORTS = new HashSet<>();
+
+ static {
+ /////////////
+ // CLASSES //
+ /////////////
+
+ // graph
+ CLASS_IMPORTS.add(Edge.class);
+ CLASS_IMPORTS.add(Element.class);
+ CLASS_IMPORTS.add(Graph.class);
+ CLASS_IMPORTS.add(Property.class);
+ CLASS_IMPORTS.add(Transaction.class);
+ CLASS_IMPORTS.add(Vertex.class);
+ CLASS_IMPORTS.add(VertexProperty.class);
+ // tokens
+ CLASS_IMPORTS.add(SackFunctions.Barrier.class);
+ CLASS_IMPORTS.add(VertexProperty.Cardinality.class);
+ CLASS_IMPORTS.add(Column.class);
+ CLASS_IMPORTS.add(Direction.class);
+ CLASS_IMPORTS.add(Operator.class);
+ CLASS_IMPORTS.add(Order.class);
+ CLASS_IMPORTS.add(Pop.class);
+ CLASS_IMPORTS.add(Scope.class);
+ CLASS_IMPORTS.add(T.class);
+ CLASS_IMPORTS.add(P.class);
+ // remote
+ CLASS_IMPORTS.add(RemoteConnection.class);
+ CLASS_IMPORTS.add(RemoteGraph.class);
+ // io
+ CLASS_IMPORTS.add(GraphReader.class);
+ CLASS_IMPORTS.add(GraphWriter.class);
+ CLASS_IMPORTS.add(Io.class);
+ CLASS_IMPORTS.add(IoCore.class);
+ CLASS_IMPORTS.add(Storage.class);
+ CLASS_IMPORTS.add(Configuration.class);
+ // strategies
+ CLASS_IMPORTS.add(TranslationStrategy.class);
+ CLASS_IMPORTS.add(ConnectiveStrategy.class);
+ CLASS_IMPORTS.add(ElementIdStrategy.class);
+ CLASS_IMPORTS.add(EventStrategy.class);
+ CLASS_IMPORTS.add(HaltedTraverserStrategy.class);
+ CLASS_IMPORTS.add(PartitionStrategy.class);
+ CLASS_IMPORTS.add(SubgraphStrategy.class);
+ CLASS_IMPORTS.add(LazyBarrierStrategy.class);
+ CLASS_IMPORTS.add(MatchAlgorithmStrategy.class);
+ CLASS_IMPORTS.add(ProfileStrategy.class);
+ CLASS_IMPORTS.add(AdjacentToIncidentStrategy.class);
+ CLASS_IMPORTS.add(FilterRankingStrategy.class);
+ CLASS_IMPORTS.add(IdentityRemovalStrategy.class);
+ CLASS_IMPORTS.add(IncidentToAdjacentStrategy.class);
+ CLASS_IMPORTS.add(MatchPredicateStrategy.class);
+ CLASS_IMPORTS.add(OrderLimitStrategy.class);
+ CLASS_IMPORTS.add(PathProcessorStrategy.class);
+ CLASS_IMPORTS.add(RangeByIsCountStrategy.class);
+ CLASS_IMPORTS.add(ComputerVerificationStrategy.class);
+ CLASS_IMPORTS.add(LambdaRestrictionStrategy.class);
+ CLASS_IMPORTS.add(ReadOnlyStrategy.class);
+ CLASS_IMPORTS.add(StandardVerificationStrategy.class);
+ // graph traversal
+ CLASS_IMPORTS.add(__.class);
+ CLASS_IMPORTS.add(GraphTraversal.class);
+ CLASS_IMPORTS.add(GraphTraversalSource.class);
+ CLASS_IMPORTS.add(TraversalMetrics.class);
+ CLASS_IMPORTS.add(Translator.class);
+ // graph computer
+ CLASS_IMPORTS.add(Computer.class);
+ CLASS_IMPORTS.add(ComputerResult.class);
+ CLASS_IMPORTS.add(GraphComputer.class);
+ CLASS_IMPORTS.add(Memory.class);
+ CLASS_IMPORTS.add(VertexProgram.class);
+ CLASS_IMPORTS.add(BulkDumperVertexProgram.class);
+ CLASS_IMPORTS.add(BulkLoaderVertexProgram.class);
+ CLASS_IMPORTS.add(PeerPressureVertexProgram.class);
+ CLASS_IMPORTS.add(PageRankVertexProgram.class);
+ CLASS_IMPORTS.add(GraphFilterStrategy.class);
+ CLASS_IMPORTS.add(VertexProgramStrategy.class);
+ // utils
+ CLASS_IMPORTS.add(Gremlin.class);
+ CLASS_IMPORTS.add(TimeUtil.class);
+
+ /////////////
+ // METHODS //
+ /////////////
+
+ Stream.of(IoCore.class.getMethods()).filter(m -> Modifier.isStatic(m.getModifiers())).forEach(METHOD_IMPORTS::add);
+ Stream.of(P.class.getMethods()).filter(m -> Modifier.isStatic(m.getModifiers())).forEach(METHOD_IMPORTS::add);
+ Stream.of(__.class.getMethods()).filter(m -> Modifier.isStatic(m.getModifiers())).filter(m -> !m.getName().equals("__")).forEach(METHOD_IMPORTS::add);
+ Stream.of(Computer.class.getMethods()).filter(m -> Modifier.isStatic(m.getModifiers())).forEach(METHOD_IMPORTS::add);
+ Stream.of(TimeUtil.class.getMethods()).filter(m -> Modifier.isStatic(m.getModifiers())).forEach(METHOD_IMPORTS::add);
+
+ ///////////
+ // ENUMS //
+ ///////////
+
+ Collections.addAll(ENUM_IMPORTS, SackFunctions.Barrier.values());
+ Collections.addAll(ENUM_IMPORTS, VertexProperty.Cardinality.values());
+ Collections.addAll(ENUM_IMPORTS, Column.values());
+ Collections.addAll(ENUM_IMPORTS, Direction.values());
+ Collections.addAll(ENUM_IMPORTS, Operator.values());
+ Collections.addAll(ENUM_IMPORTS, Order.values());
+ Collections.addAll(ENUM_IMPORTS, Pop.values());
+ Collections.addAll(ENUM_IMPORTS, Scope.values());
+ Collections.addAll(ENUM_IMPORTS, T.values());
+
+ }
+
+ private CoreImports() {
+ // static methods only, do not instantiate class
+ }
+
+ public static Set<Class> getClassImports() {
+ return Collections.unmodifiableSet(CLASS_IMPORTS);
+ }
+
+ public static Set<Method> getMethodImports() {
+ return Collections.unmodifiableSet(METHOD_IMPORTS);
+ }
+
+ public static Set<Enum> getEnumImports() {
+ return Collections.unmodifiableSet(ENUM_IMPORTS);
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77b1bbdd/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GremlinPythonSourceGenerator.groovy
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GremlinPythonSourceGenerator.groovy b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GremlinPythonSourceGenerator.groovy
index 24bb703..78e65ba 100644
--- a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GremlinPythonSourceGenerator.groovy
+++ b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GremlinPythonSourceGenerator.groovy
@@ -19,21 +19,16 @@
package org.apache.tinkerpop.gremlin.python
-import org.apache.tinkerpop.gremlin.process.traversal.Operator
-import org.apache.tinkerpop.gremlin.process.traversal.Order
import org.apache.tinkerpop.gremlin.process.traversal.P
-import org.apache.tinkerpop.gremlin.process.traversal.Pop
-import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions
-import org.apache.tinkerpop.gremlin.process.traversal.Scope
import org.apache.tinkerpop.gremlin.process.traversal.Traversal
import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
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.structure.Column
-import org.apache.tinkerpop.gremlin.structure.Direction
-import org.apache.tinkerpop.gremlin.structure.T
-import org.apache.tinkerpop.gremlin.structure.VertexProperty
+import org.apache.tinkerpop.gremlin.python.util.SymbolHelper
+import org.apache.tinkerpop.gremlin.util.CoreImports
+
+import java.lang.reflect.Modifier
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -63,13 +58,6 @@ specific language governing permissions and limitations
under the License.
'''
""")
-
- final Map<String, String> methodMap = [global: "_global", as: "_as", in: "_in", and: "_and", or: "_or", is: "_is", not: "_not", from: "_from"]
- .withDefault { it }
- final Map<String, String> invertedMethodMap = [:].withDefault { it };
- methodMap.entrySet().forEach { invertedMethodMap.put(it.value, it.key) }
- final List<Class<? extends Enum>> enumList = [VertexProperty.Cardinality, Column, Direction, Operator, Order, Pop, SackFunctions.Barrier, Scope, T]
-
pythonClass.append("from collections import OrderedDict\n")
pythonClass.append("from aenum import Enum\n")
pythonClass.append("statics = OrderedDict()\n\n")
@@ -159,6 +147,18 @@ globalTranslator = None
return self.next()
def toList(self):
return list(iter(self))
+ def toSet(self):
+ return set(iter(self))
+ def next(self,amount):
+ count = 0
+ tempList = []
+ while count < amount:
+ count = count + 1
+ temp = next(self,None)
+ if None == temp:
+ break
+ tempList.append(temp)
+ return tempList
def next(self):
if self.results is None:
self.results = self.remote_connection.submit(self.translator.target_language, self.translator.traversal_script, self.bindings)
@@ -172,12 +172,12 @@ globalTranslator = None
""")
GraphTraversal.getMethods()
.findAll { !it.name.equals("clone") }
- .collect { methodMap[it.name] }
+ .collect { SymbolHelper.toPython(it.name) }
.unique()
.sort { a, b -> a <=> b }
.each { method ->
final Class<?> returnType = (GraphTraversal.getMethods() as Set).findAll {
- it.name.equals(invertedMethodMap[method])
+ it.name.equals(SymbolHelper.fromPython(method))
}.collect { it.returnType }[0]
if (null != returnType && Traversal.isAssignableFrom(returnType)) {
pythonClass.append(
@@ -200,7 +200,7 @@ globalTranslator = None
pythonClass.append("class __(object):\n");
__.getMethods()
.findAll { Traversal.isAssignableFrom(it.returnType) }
- .collect { methodMap[it.name] }
+ .collect { SymbolHelper.toPython(it.name) }
.unique()
.sort { a, b -> a <=> b }
.each { method ->
@@ -214,8 +214,9 @@ globalTranslator = None
__.class.getMethods()
.findAll { Traversal.class.isAssignableFrom(it.getReturnType()) }
- .findAll { !it.name.equals("__") && !it.name.equals("clone") }
- .collect { methodMap[it.name] }
+ .findAll { Modifier.isStatic(it.getModifiers()) }
+ .findAll { !it.name.equals("__") }
+ .collect { SymbolHelper.toPython(it.name) }
.unique()
.sort { a, b -> a <=> b }
.forEach {
@@ -227,14 +228,16 @@ globalTranslator = None
///////////
// Enums //
///////////
- for (final Class<? extends Enum> enumClass : enumList) {
+ for (final Class<? extends Enum> enumClass : CoreImports.getClassImports().findAll {
+ Enum.class.isAssignableFrom(it)
+ }.collect()) {
pythonClass.append("${enumClass.getSimpleName()} = Enum('${enumClass.getSimpleName()}', '");
enumClass.getEnumConstants().each { value ->
- pythonClass.append("${methodMap[value.name()]} ");
+ pythonClass.append("${SymbolHelper.toPython(value.name())} ");
}
pythonClass.deleteCharAt(pythonClass.length() - 1).append("')\n\n")
enumClass.getEnumConstants().each { value ->
- pythonClass.append("statics['${methodMap[value.name()]}'] = ${value.getDeclaringClass().getSimpleName()}.${methodMap[value.name()]}\n");
+ pythonClass.append("statics['${SymbolHelper.toPython(value.name())}'] = ${value.getDeclaringClass().getSimpleName()}.${SymbolHelper.toPython(value.name())}\n");
}
pythonClass.append("\n");
}
@@ -270,17 +273,17 @@ globalTranslator = None
self.value = value
self.other = other
""")
- P.getMethods()
+ P.class.getMethods()
+ .findAll { Modifier.isStatic(it.getModifiers()) }
.findAll { P.class.isAssignableFrom(it.returnType) }
- .findAll { !it.name.equals("or") && !it.name.equals("and") && !it.name.equals("clone") }
- .collect { methodMap[it.name] }
+ .collect { SymbolHelper.toPython(it.name) }
.unique()
.sort { a, b -> a <=> b }
.each { method ->
pythonClass.append(
""" @staticmethod
def ${method}(*args):
- return P("${invertedMethodMap[method]}", *args)
+ return P("${SymbolHelper.fromPython(method)}", *args)
""")
};
pythonClass.append(""" def _and(self, arg):
@@ -290,9 +293,10 @@ globalTranslator = None
""")
pythonClass.append("\n")
P.class.getMethods()
+ .findAll { Modifier.isStatic(it.getModifiers()) }
.findAll { !it.name.equals("clone") }
.findAll { P.class.isAssignableFrom(it.getReturnType()) }
- .collect { methodMap[it.name] }
+ .collect { SymbolHelper.toPython(it.name) }
.unique()
.sort { a, b -> a <=> b }
.forEach {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77b1bbdd/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java
index 090fa5c..bdf1cc1 100644
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java
+++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java
@@ -20,8 +20,8 @@
package org.apache.tinkerpop.gremlin.python.jsr223;
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.structure.Graph;
+import org.apache.tinkerpop.gremlin.python.util.SymbolHelper;
+import org.apache.tinkerpop.gremlin.util.CoreImports;
import org.python.jsr223.PyScriptEngine;
import org.python.jsr223.PyScriptEngineFactory;
@@ -31,7 +31,7 @@ import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import java.io.Reader;
-import java.util.Arrays;
+import java.lang.reflect.Method;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -43,17 +43,33 @@ public class GremlinJythonScriptEngine implements ScriptEngine {
public GremlinJythonScriptEngine() {
this.pyScriptEngine = (PyScriptEngine) new PyScriptEngineFactory().getScriptEngine();
try {
- // Groovy's AbstractImportCustomizer should pull from a common source
- for (final Class x : Arrays.asList(Graph.class, GraphTraversal.class, GraphTraversalSource.class)) {
- this.pyScriptEngine.eval("from " + x.getPackage().getName() + " import " + x.getSimpleName());
+ // CoreImports
+ for (final Class x : CoreImports.getClassImports()) {
+ if (null == x.getDeclaringClass())
+ this.pyScriptEngine.eval("from " + x.getPackage().getName() + " import " + x.getSimpleName());
+ else
+ this.pyScriptEngine.eval("from " + x.getPackage().getName() + "." + x.getDeclaringClass().getSimpleName() + " import " + x.getSimpleName());
}
+ for (final Method x : CoreImports.getMethodImports()) {
+ this.pyScriptEngine.eval(SymbolHelper.toPython(x.getName()) + " = " + x.getDeclaringClass().getSimpleName() + "." + x.getName());
+ // this.pyScriptEngine.eval("def " + SymbolHelper.toPython(x.getName()) + "(*args):\n return " + x.getDeclaringClass().getSimpleName() + "." + SymbolHelper.toPython(x.getName()) + "(*args)");
+ }
+ for (final Enum x : CoreImports.getEnumImports()) {
+ this.pyScriptEngine.eval(SymbolHelper.toPython(x.name()) + " = " + x.getDeclaringClass().getSimpleName() + "." + x.name());
+ }
+
+ // add sugar methods
+ this.pyScriptEngine.eval("def getitem_bypass(self, index):\n" +
+ " if isinstance(index,int):\n return self.range(index,index+1)\n" +
+ " elif isinstance(index,slice):\n return self.range(index.start,index.stop)\n" +
+ " else:\n return TypeError('Index must be int or slice')");
+ this.pyScriptEngine.eval(GraphTraversal.class.getSimpleName() + ".__getitem__ = getitem_bypass");
+ this.pyScriptEngine.eval(GraphTraversal.class.getSimpleName() + ".__getattr__ = lambda self, key: self.values(key)");
} catch (final ScriptException e) {
throw new IllegalStateException(e.getMessage(), e);
}
-
}
-
@Override
public Object eval(String script, ScriptContext context) throws ScriptException {
return this.pyScriptEngine.eval(script, context);
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77b1bbdd/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/util/SymbolHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/util/SymbolHelper.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/util/SymbolHelper.java
new file mode 100644
index 0000000..b1908ce
--- /dev/null
+++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/util/SymbolHelper.java
@@ -0,0 +1,58 @@
+/*
+ * 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.python.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class SymbolHelper {
+
+ private final static Map<String, String> TO_PYTHON_MAP = new HashMap<>();
+ private final static Map<String, String> FROM_PYTHON_MAP = new HashMap<>();
+
+ static {
+ TO_PYTHON_MAP.put("global", "_global");
+ TO_PYTHON_MAP.put("as", "_as");
+ TO_PYTHON_MAP.put("in", "_in");
+ TO_PYTHON_MAP.put("and", "_and");
+ TO_PYTHON_MAP.put("or", "_or");
+ TO_PYTHON_MAP.put("is", "_is");
+ TO_PYTHON_MAP.put("not", "_not");
+ TO_PYTHON_MAP.put("from", "_from");
+ //
+ TO_PYTHON_MAP.forEach((k, v) -> FROM_PYTHON_MAP.put(v, k));
+ }
+
+ private SymbolHelper() {
+ // static methods only, do not instantiate
+ }
+
+ public static String toPython(final String symbol) {
+ return TO_PYTHON_MAP.getOrDefault(symbol, symbol);
+ }
+
+ public static String fromPython(final String pythonSymbol) {
+ return FROM_PYTHON_MAP.getOrDefault(pythonSymbol, pythonSymbol);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77b1bbdd/gremlin-python/src/main/jython/gremlin_python/gremlin_python.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/gremlin_python.py b/gremlin-python/src/main/jython/gremlin_python/gremlin_python.py
index ab478d0..08be95c 100644
--- a/gremlin-python/src/main/jython/gremlin_python/gremlin_python.py
+++ b/gremlin-python/src/main/jython/gremlin_python/gremlin_python.py
@@ -166,6 +166,18 @@ class PythonGraphTraversal(object):
return self.next()
def toList(self):
return list(iter(self))
+ def toSet(self):
+ return set(iter(self))
+ def next(self,amount):
+ count = 0
+ tempList = []
+ while count < amount:
+ count = count + 1
+ temp = next(self,None)
+ if None == temp:
+ break
+ tempList.append(temp)
+ return tempList
def next(self):
if self.results is None:
self.results = self.remote_connection.submit(self.translator.target_language, self.translator.traversal_script, self.bindings)
@@ -1630,16 +1642,29 @@ def where(*args):
statics['where'] = where
+Pop = Enum('Pop', 'first last all')
+
+statics['first'] = Pop.first
+statics['last'] = Pop.last
+statics['all'] = Pop.all
+
Cardinality = Enum('Cardinality', 'single list set')
statics['single'] = Cardinality.single
statics['list'] = Cardinality.list
statics['set'] = Cardinality.set
-Column = Enum('Column', 'keys values')
+T = Enum('T', 'label id key value')
-statics['keys'] = Column.keys
-statics['values'] = Column.values
+statics['label'] = T.label
+statics['id'] = T.id
+statics['key'] = T.key
+statics['value'] = T.value
+
+Scope = Enum('Scope', '_global local')
+
+statics['_global'] = Scope._global
+statics['local'] = Scope.local
Direction = Enum('Direction', 'OUT IN BOTH')
@@ -1671,27 +1696,14 @@ statics['keyDecr'] = Order.keyDecr
statics['valueDecr'] = Order.valueDecr
statics['shuffle'] = Order.shuffle
-Pop = Enum('Pop', 'first last all')
-
-statics['first'] = Pop.first
-statics['last'] = Pop.last
-statics['all'] = Pop.all
-
Barrier = Enum('Barrier', 'normSack')
statics['normSack'] = Barrier.normSack
-Scope = Enum('Scope', '_global local')
-
-statics['_global'] = Scope._global
-statics['local'] = Scope.local
-
-T = Enum('T', 'label id key value')
+Column = Enum('Column', 'keys values')
-statics['label'] = T.label
-statics['id'] = T.id
-statics['key'] = T.key
-statics['value'] = T.value
+statics['keys'] = Column.keys
+statics['values'] = Column.values
class RawExpression(object):
def __init__(self, *args):
@@ -1742,9 +1754,6 @@ class P(object):
def lte(*args):
return P("lte", *args)
@staticmethod
- def negate(*args):
- return P("negate", *args)
- @staticmethod
def neq(*args):
return P("neq", *args)
@staticmethod
@@ -1764,18 +1773,10 @@ class P(object):
def _or(self, arg):
return P("_or", arg, self)
-def _and(*args):
- return P._and(*args)
-
-statics['_and'] = _and
def _not(*args):
return P._not(*args)
statics['_not'] = _not
-def _or(*args):
- return P._or(*args)
-
-statics['_or'] = _or
def between(*args):
return P.between(*args)
@@ -1804,10 +1805,6 @@ def lte(*args):
return P.lte(*args)
statics['lte'] = lte
-def negate(*args):
- return P.negate(*args)
-
-statics['negate'] = negate
def neq(*args):
return P.neq(*args)
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77b1bbdd/gremlin-python/src/main/jython/gremlin_python/groovy_translator.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/groovy_translator.py b/gremlin-python/src/main/jython/gremlin_python/groovy_translator.py
index 2cd60be..c31d858 100644
--- a/gremlin-python/src/main/jython/gremlin_python/groovy_translator.py
+++ b/gremlin-python/src/main/jython/gremlin_python/groovy_translator.py
@@ -30,7 +30,7 @@ if sys.version_info.major > 2:
__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-methodMap = {"_global": "global", "_as": "as", "_in": "in", "_and": "and", "_or": "or", "_is": "is", "_not": "not",
+symbolMap = {"_global": "global", "_as": "as", "_in": "in", "_and": "and", "_or": "or", "_is": "is", "_not": "not",
"_from": "from"}
enumMap = {"Cardinality": "VertexProperty.Cardinality", "Barrier": "SackFunctions.Barrier"}
@@ -65,8 +65,8 @@ class GroovyTranslator(Translator):
@staticmethod
def mapMethod(method):
- if (method in methodMap):
- return methodMap[method]
+ if (method in symbolMap):
+ return symbolMap[method]
else:
return method
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77b1bbdd/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java
index a4f431b..670ee7e 100644
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngineTest.java
@@ -19,10 +19,18 @@
package org.apache.tinkerpop.gremlin.python.jsr223;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
import org.junit.Test;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.HashSet;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -42,8 +50,44 @@ public class GremlinJythonScriptEngineTest {
}
@Test
- public void shouldHaveStandardImports() throws Exception {
+ public void shouldHaveCoreImports() throws Exception {
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("gremlin-jython");
assertTrue(engine.eval("Graph") instanceof Class);
+ assertTrue(engine.eval("__") instanceof Class);
+ assertTrue(engine.eval("T") instanceof Class);
+ assertTrue(engine.eval("label") instanceof T);
+ assertTrue(engine.eval("T.label") instanceof T);
+ assertTrue(engine.eval("out()") instanceof GraphTraversal);
+ assertTrue(engine.eval("__.out()") instanceof GraphTraversal);
+ }
+
+
+ @Test
+ public void shouldSupportJavaBasedGraphTraversal() throws Exception {
+ final ScriptEngine engine = new ScriptEngineManager().getEngineByName("gremlin-jython");
+ final Bindings bindings = engine.createBindings();
+ bindings.put("graph", TinkerFactory.createModern());
+ engine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);
+ engine.eval("g = graph.traversal()");
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(out()).times(2).values('name').toSet()"));
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).values('name').toSet()"));
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(out()).times(2).name.toSet()"));
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).name.toSet()"));
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2)[0:2].name.toSet()"));
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).name[0:3].toSet()"));
+ }
+
+ @Test
+ public void shouldSupportSugarMethods() throws Exception {
+ final ScriptEngine engine = new ScriptEngineManager().getEngineByName("gremlin-jython");
+ final Bindings bindings = engine.createBindings();
+ bindings.put("graph", TinkerFactory.createModern());
+ engine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);
+ engine.eval("g = graph.traversal()");
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2)[0:2].name.toSet()"));
+ assertEquals(new HashSet<>(Arrays.asList("ripple", "lop")), engine.eval("g.V().repeat(__.out()).times(2).name[0:3].toSet()"));
+ assertEquals(BigInteger.valueOf(1), engine.eval("g.V().repeat(__.out()).times(2).name[0:1].count().next()"));
+ assertEquals(BigInteger.valueOf(1), engine.eval("g.V().repeat(__.out()).times(2).name[0].count().next()"));
+ assertEquals(BigInteger.valueOf(0), engine.eval("g.V().repeat(__.out()).times(2).name[3].count().next()"));
}
}