TINKERPOP-1618 Removed dependence on groovy for gremlin-python Executed code generation with the gmaven plugin and the Groovy templating library. This approach also gets the files generated in a much earlier (and more correct) phase of the maven life cycle which may be important to other GLVs using this as a pattern.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/894fc805 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/894fc805 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/894fc805 Branch: refs/heads/master Commit: 894fc8051e6464fbbd94d05631ac5cf420683881 Parents: 1d97c3d Author: Stephen Mallette <[email protected]> Authored: Fri May 19 14:37:27 2017 -0400 Committer: Stephen Mallette <[email protected]> Committed: Fri May 26 08:30:16 2017 -0400 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + gremlin-python/pom.xml | 120 +- .../python/GraphTraversalSourceGenerator.groovy | 207 -- .../python/TraversalSourceGenerator.groovy | 356 ---- .../gremlin/python/GenerateGremlinPython.java | 32 - .../gremlin_python/process/graph_traversal.py | 1764 ++++++++++-------- .../jython/gremlin_python/process/traversal.py | 192 +- .../resources/GraphTraversalSource.template | 96 + .../src/main/resources/TraversalSource.template | 282 +++ 9 files changed, 1515 insertions(+), 1535 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/894fc805/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index dd7616e..2067ea2 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -30,6 +30,7 @@ TinkerPop 3.2.5 (Release Date: NOT OFFICIALLY RELEASED YET) * Reduced memory usage for TinkerGraph deserialization in GraphSON by streaming vertices and edges. * Added the `gremlin-archetype-dsl` to demonstrate how to structure a Maven project for a DSL. * Developed and documented patterns for Domain Specific Language implementations. +* Removed the Groovy dependency from `gremlin-python` and used Groovy Templates and the `gmavenplus-plugin` to generate the python GLV classes. * Now using Groovy `[...]` map notation in `GroovyTranslator` instead of `new LinkedHashMap(){{ }}`. * Maintained type information on `Traversal.promise()`. * Propagated exception to `Future` instead of calling thread in `RemoteConnection`. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/894fc805/gremlin-python/pom.xml ---------------------------------------------------------------------- diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml index 19d3041..96cbc51 100644 --- a/gremlin-python/pom.xml +++ b/gremlin-python/pom.xml @@ -32,12 +32,6 @@ limitations under the License. <version>${project.version}</version> </dependency> <dependency> - <groupId>org.codehaus.groovy</groupId> - <artifactId>groovy</artifactId> - <version>${groovy.version}</version> - <classifier>indy</classifier> - </dependency> - <dependency> <groupId>org.python</groupId> <artifactId>jython-standalone</artifactId> <version>2.7.1b2</version> @@ -90,32 +84,6 @@ limitations under the License. </testResources> <plugins> <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>exec-maven-plugin</artifactId> - <version>1.2.1</version> - <executions> - <execution> - <id>generate-python</id> - <phase>generate-test-resources</phase> - <goals> - <goal>java</goal> - </goals> - <configuration> - <mainClass>org.apache.tinkerpop.gremlin.python.GenerateGremlinPython</mainClass> - <arguments> - <argument>${basedir}/src/main/jython/gremlin_python/process/traversal.py</argument> - <argument>${basedir}/src/main/jython/gremlin_python/process/graph_traversal.py - </argument> - </arguments> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <groupId>org.codehaus.gmavenplus</groupId> - <artifactId>gmavenplus-plugin</artifactId> - </plugin> - <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> @@ -511,6 +479,94 @@ limitations under the License. </dependencies> <executions> <execution> + <id>generate-dsl</id> + <phase>generate-sources</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <scripts> + <script><![CDATA[ +import org.apache.tinkerpop.gremlin.jsr223.CoreImports +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.P +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__ +import java.lang.reflect.Modifier + +// this is a bit of a copy of what's in SymbolHelper - no way around it because this code generation task occurs +// before the SymbolHelper is available to the plugin. +def toPythonMap = ["global": "global_", + "as": "as_", + "in": "in_", + "and": "and_", + "or": "or_", + "is": "is_", + "not": "not_", + "from": "from_", + "list": "list_", + "set": "set_", + "all": "all_"] +def toJavaMap = toPythonMap.collectEntries{k,v -> [(v):k]} + +def toPython = { symbol -> toPythonMap.getOrDefault(symbol, symbol) } +def toJava = { symbol -> toJavaMap.getOrDefault(symbol, symbol) } + +def binding = ["enums": CoreImports.getClassImports() + .findAll { Enum.class.isAssignableFrom(it) } + .sort { a, b -> a.getSimpleName() <=> b.getSimpleName() }, + "pmethods": P.class.getMethods(). + findAll { Modifier.isStatic(it.getModifiers()) }. + findAll { P.class.isAssignableFrom(it.returnType) }. + collect { toPython(it.name) }. + unique(). + sort { a, b -> a <=> b }, + "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS + findAll { GraphTraversalSource.class.equals(it.returnType) }. + findAll { + !it.name.equals("clone") && + !it.name.equals(TraversalSource.Symbols.withBindings) && + !it.name.equals(TraversalSource.Symbols.withRemote) && + !it.name.equals(TraversalSource.Symbols.withComputer) + }. + collect { toPython(it.name) }. + unique(). + sort { a, b -> a <=> b }, + "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS + findAll { GraphTraversal.class.equals(it.returnType) }. + collect { toPython(it.name) }. + unique(). + sort { a, b -> a <=> b }, + "graphStepMethods": GraphTraversal.getMethods(). + findAll { GraphTraversal.class.equals(it.returnType) }. + findAll { !it.name.equals("clone") && !it.name.equals("iterate") }. + collect { toPython(it.name) }. + unique(). + sort { a, b -> a <=> b }, + "anonStepMethods": __.class.getMethods(). + findAll { GraphTraversal.class.equals(it.returnType) }. + findAll { Modifier.isStatic(it.getModifiers()) }. + findAll { !it.name.equals("__") && !it.name.equals("start") }. + collect { toPython(it.name) }. + unique(). + sort { a, b -> a <=> b }, + "toPython": toPython, + "toJava": toJava] + +def engine = new groovy.text.GStringTemplateEngine() +def traversalTemplate = engine.createTemplate(new File('${project.basedir}/src/main/resources/TraversalSource.template')).make(binding) +def traversalFile = new File('${project.basedir}/src/main/jython/gremlin_python/process/traversal.py') +traversalFile.newWriter().withWriter{ it << traversalTemplate } + +def graphTraversalTemplate = engine.createTemplate(new File('${project.basedir}/src/main/resources/GraphTraversalSource.template')).make(binding) +def graphTraversalFile = new File('${project.basedir}/src/main/jython/gremlin_python/process/graph_traversal.py') +graphTraversalFile.newWriter().withWriter{ it << graphTraversalTemplate } +]]> </script> + </scripts> + </configuration> + </execution> + <execution> <id>gremlin-server-start</id> <phase>pre-integration-test</phase> <goals> http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/894fc805/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy deleted file mode 100644 index 086b8ea..0000000 --- a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/GraphTraversalSourceGenerator.groovy +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 - -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.python.jsr223.SymbolHelper - -import java.lang.reflect.Modifier - -/** - * @author Marko A. Rodriguez (http://markorodriguez.com) - */ -class GraphTraversalSourceGenerator { - - public static void create(final String graphTraversalSourceFile) { - - final StringBuilder pythonClass = new StringBuilder() - - pythonClass.append("""''' -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. -''' -""") - pythonClass.append("import sys\n") - pythonClass.append("from .traversal import Traversal\n") - pythonClass.append("from .traversal import TraversalStrategies\n") - pythonClass.append("from .strategies import VertexProgramStrategy\n") - pythonClass.append("from .traversal import Bytecode\n") - pythonClass.append("from ..driver.remote_connection import RemoteStrategy\n") - pythonClass.append("from .. import statics\n") - pythonClass.append("from ..statics import long\n\n") - -////////////////////////// -// GraphTraversalSource // -////////////////////////// - pythonClass.append( - """class GraphTraversalSource(object): - def __init__(self, graph, traversal_strategies, bytecode=None): - self.graph = graph - self.traversal_strategies = traversal_strategies - if bytecode is None: - bytecode = Bytecode() - self.bytecode = bytecode - self.graph_traversal = GraphTraversal - def __repr__(self): - return "graphtraversalsource[" + str(self.graph) + "]" - def get_graph_traversal_source(self): - return self.__class__(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode)) - def get_graph_traversal(self): - return self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) -""") - GraphTraversalSource.getMethods(). // SOURCE STEPS - findAll { GraphTraversalSource.class.equals(it.returnType) }. - findAll { - !it.name.equals("clone") && - !it.name.equals(TraversalSource.Symbols.withBindings) && - !it.name.equals(TraversalSource.Symbols.withRemote) && - !it.name.equals(TraversalSource.Symbols.withComputer) - }. - collect { SymbolHelper.toPython(it.name) }. - unique(). - sort { a, b -> a <=> b }. - forEach { method -> - pythonClass.append( - """ def ${method}(self, *args): - source = self.get_graph_traversal_source() - source.bytecode.add_source("${SymbolHelper.toJava(method)}", *args) - return source -""") - } - pythonClass.append( - """ def withRemote(self, remote_connection): - source = self.get_graph_traversal_source() - source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)]) - return source - def withComputer(self,graph_computer=None, workers=None, result=None, persist=None, vertices=None, edges=None, configuration=None): - return self.withStrategies(VertexProgramStrategy(graph_computer,workers,result,persist,vertices,edges,configuration)) -""") - GraphTraversalSource.getMethods(). // SPAWN STEPS - findAll { GraphTraversal.class.equals(it.returnType) }. - collect { SymbolHelper.toPython(it.name) }. - unique(). - sort { a, b -> a <=> b }. - forEach { method -> - pythonClass.append( - """ def ${method}(self, *args): - traversal = self.get_graph_traversal() - traversal.bytecode.add_step("${SymbolHelper.toJava(method)}", *args) - return traversal -""") - } - pythonClass.append("\n\n") - -//////////////////// -// GraphTraversal // -//////////////////// - pythonClass.append( - """class GraphTraversal(Traversal): - def __init__(self, graph, traversal_strategies, bytecode): - super(GraphTraversal, self).__init__(graph, traversal_strategies, bytecode) - def __getitem__(self, index): - if isinstance(index, int): - return self.range(long(index), long(index + 1)) - elif isinstance(index, slice): - return self.range(long(0) if index.start is None else long(index.start), long(sys.maxsize) if index.stop is None else long(index.stop)) - else: - raise TypeError("Index must be int or slice") - def __getattr__(self, key): - return self.values(key) -""") - GraphTraversal.getMethods(). - findAll { GraphTraversal.class.equals(it.returnType) }. - findAll { !it.name.equals("clone") && !it.name.equals("iterate") }. - collect { SymbolHelper.toPython(it.name) }. - unique(). - sort { a, b -> a <=> b }. - forEach { method -> - pythonClass.append( - """ def ${method}(self, *args): - self.bytecode.add_step("${SymbolHelper.toJava(method)}", *args) - return self -""") - }; - pythonClass.append("\n\n") - -//////////////////////// -// AnonymousTraversal // -//////////////////////// - pythonClass.append( - """class __(object): - graph_traversal = GraphTraversal - @classmethod - def start(cls): - return GraphTraversal(None, None, Bytecode()) - @classmethod - def __(cls, *args): - return __.inject(*args) -""") - __.class.getMethods(). - findAll { GraphTraversal.class.equals(it.returnType) }. - findAll { Modifier.isStatic(it.getModifiers()) }. - findAll { !it.name.equals("__") && !it.name.equals("start") }. - collect { SymbolHelper.toPython(it.name) }. - unique(). - sort { a, b -> a <=> b }. - forEach { method -> - pythonClass.append( - """ @classmethod - def ${method}(cls, *args): - return cls.graph_traversal(None, None, Bytecode()).${method}(*args) -""") - }; - pythonClass.append("\n\n") - // add to gremlin.python.statics - __.class.getMethods(). - findAll { GraphTraversal.class.equals(it.returnType) }. - findAll { Modifier.isStatic(it.getModifiers()) }. - findAll { !it.name.equals("__") && !it.name.equals("start") }. - collect { SymbolHelper.toPython(it.name) }. - unique(). - sort { a, b -> a <=> b }. - forEach { - pythonClass.append("def ${it}(*args):\n").append(" return __.${it}(*args)\n\n") - pythonClass.append("statics.add_static('${it}', ${it})\n\n") - } - pythonClass.append("\n\n") - -// save to a python file - final File file = new File(graphTraversalSourceFile); - file.delete() - pythonClass.eachLine { file.append(it + "\n") } - } -} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/894fc805/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy deleted file mode 100644 index 995fe80..0000000 --- a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy +++ /dev/null @@ -1,356 +0,0 @@ -/* - * 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 - -import org.apache.tinkerpop.gremlin.jsr223.CoreImports -import org.apache.tinkerpop.gremlin.process.traversal.P -import org.apache.tinkerpop.gremlin.python.jsr223.SymbolHelper - -import java.lang.reflect.Modifier - -/** - * @author Marko A. Rodriguez (http://markorodriguez.com) - */ -class TraversalSourceGenerator { - - public static void create(final String traversalSourceFile) { - - final StringBuilder pythonClass = new StringBuilder() - - pythonClass.append("""''' -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. -''' -""") - pythonClass.append("from aenum import Enum\n") - pythonClass.append("from .. import statics\n") - pythonClass.append("from ..statics import long\n\n") - - pythonClass.append(""" -class Traversal(object): - def __init__(self, graph, traversal_strategies, bytecode): - self.graph = graph - self.traversal_strategies = traversal_strategies - self.bytecode = bytecode - self.side_effects = TraversalSideEffects() - self.traversers = None - self.last_traverser = None - def __repr__(self): - return str(self.bytecode) - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.bytecode == other.bytecode - else: - return False - def __iter__(self): - return self - def __next__(self): - if self.traversers is None: - self.traversal_strategies.apply_strategies(self) - if self.last_traverser is None: - self.last_traverser = next(self.traversers) - object = self.last_traverser.object - self.last_traverser.bulk = self.last_traverser.bulk - 1 - if self.last_traverser.bulk <= 0: - self.last_traverser = None - return object - def toList(self): - return list(iter(self)) - def toSet(self): - return set(iter(self)) - def iterate(self): - while True: - try: self.nextTraverser() - except StopIteration: return self - def nextTraverser(self): - if self.traversers is None: - self.traversal_strategies.apply_strategies(self) - if self.last_traverser is None: - return next(self.traversers) - else: - temp = self.last_traverser - self.last_traverser = None - return temp - def next(self, amount=None): - if amount is None: - return self.__next__() - else: - count = 0 - tempList = [] - while count < amount: - count = count + 1 - try: temp = self.__next__() - except StopIteration: return tempList - tempList.append(temp) - return tempList - def promise(self, cb=None): - self.traversal_strategies.apply_async_strategies(self) - future_traversal = self.remote_results - future = type(future_traversal)() - def process(f): - try: - traversal = f.result() - except Exception as e: - future.set_exception(e) - else: - self.traversers = iter(traversal.traversers) - self.side_effects = traversal.side_effects - if cb: - try: - result = cb(self) - except Exception as e: - future.set_exception(e) - else: - future.set_result(result) - else: - future.set_result(self) - future_traversal.add_done_callback(process) - return future - - -""") - -/////////// -// Enums // -/////////// - for (final Class<? extends Enum> enumClass : CoreImports.getClassImports() - .findAll { Enum.class.isAssignableFrom(it) } - .sort { a, b -> a.getSimpleName() <=> b.getSimpleName() } - .collect()) { - pythonClass.append("${enumClass.getSimpleName()} = Enum('${enumClass.getSimpleName()}', '"); - enumClass.getEnumConstants() - .sort { a, b -> a.name() <=> b.name() } - .each { value -> pythonClass.append("${SymbolHelper.toPython(value.name())} "); } - pythonClass.deleteCharAt(pythonClass.length() - 1).append("')\n") - enumClass.getEnumConstants().each { value -> - pythonClass.append("statics.add_static('${SymbolHelper.toPython(value.name())}', ${value.getDeclaringClass().getSimpleName()}.${SymbolHelper.toPython(value.name())})\n"); - } - pythonClass.append("\n"); - } - ////////////// - - pythonClass.append("""class P(object): - def __init__(self, operator, value, other=None): - self.operator = operator - self.value = value - self.other = other -""") - P.class.getMethods(). - findAll { Modifier.isStatic(it.getModifiers()) }. - findAll { P.class.isAssignableFrom(it.returnType) }. - collect { SymbolHelper.toPython(it.name) }. - unique(). - sort { a, b -> a <=> b }. - each { method -> - pythonClass.append( - """ @staticmethod - def ${method}(*args): - return P("${SymbolHelper.toJava(method)}", *args) -""") - }; - pythonClass.append(""" def and_(self, arg): - return P("and", self, arg) - def or_(self, arg): - return P("or", self, arg) - def __eq__(self, other): - return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other - def __repr__(self): - return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")" -""") - pythonClass.append("\n") - P.class.getMethods(). - findAll { Modifier.isStatic(it.getModifiers()) }. - findAll { !it.name.equals("clone") }. - findAll { P.class.isAssignableFrom(it.getReturnType()) }. - collect { SymbolHelper.toPython(it.name) }. - unique(). - sort { a, b -> a <=> b }. - forEach { - pythonClass.append("def ${it}(*args):\n").append(" return P.${it}(*args)\n") - pythonClass.append("statics.add_static('${it}',${it})\n\n") - } - pythonClass.append("\n") - ////////////// - - pythonClass.append(""" -''' -TRAVERSER -''' - -class Traverser(object): - def __init__(self, object, bulk=None): - if bulk is None: - bulk = long(1) - self.object = object - self.bulk = bulk - def __repr__(self): - return str(self.object) - def __eq__(self, other): - return isinstance(other, self.__class__) and self.object == other.object - -''' -TRAVERSAL SIDE-EFFECTS -''' - -class TraversalSideEffects(object): - def keys(self): - return set() - def get(self, key): - raise KeyError(key) - def __getitem__(self, key): - return self.get(key) - def __repr__(self): - return "sideEffects[size:" + str(len(self.keys())) + "]" - -''' -TRAVERSAL STRATEGIES -''' - -class TraversalStrategies(object): - global_cache = {} - def __init__(self, traversal_strategies=None): - self.traversal_strategies = traversal_strategies.traversal_strategies if traversal_strategies is not None else [] - def add_strategies(self, traversal_strategies): - self.traversal_strategies = self.traversal_strategies + traversal_strategies - def apply_strategies(self, traversal): - for traversal_strategy in self.traversal_strategies: - traversal_strategy.apply(traversal) - def apply_async_strategies(self, traversal): - for traversal_strategy in self.traversal_strategies: - traversal_strategy.apply_async(traversal) - def __repr__(self): - return str(self.traversal_strategies) - - -class TraversalStrategy(object): - def __init__(self, strategy_name=None, configuration=None): - self.strategy_name = type(self).__name__ if strategy_name is None else strategy_name - self.configuration = {} if configuration is None else configuration - def apply(self, traversal): - return - def apply_async(self, traversal): - return - def __eq__(self, other): - return isinstance(other, self.__class__) - def __hash__(self): - return hash(self.strategy_name) - def __repr__(self): - return self.strategy_name - -''' -BYTECODE -''' - -class Bytecode(object): - def __init__(self, bytecode=None): - self.source_instructions = [] - self.step_instructions = [] - self.bindings = {} - if bytecode is not None: - self.source_instructions = list(bytecode.source_instructions) - self.step_instructions = list(bytecode.step_instructions) - def add_source(self, source_name, *args): - instruction = [source_name] - for arg in args: - instruction.append(self.__convertArgument(arg)) - self.source_instructions.append(instruction) - def add_step(self, step_name, *args): - instruction = [step_name] - for arg in args: - instruction.append(self.__convertArgument(arg)) - self.step_instructions.append(instruction) - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.source_instructions == other.source_instructions and self.step_instructions == other.step_instructions - else: - return False - def __convertArgument(self,arg): - if isinstance(arg, Traversal): - self.bindings.update(arg.bytecode.bindings) - return arg.bytecode - elif isinstance(arg, dict): - newDict = {} - for key in arg: - newDict[self.__convertArgument(key)] = self.__convertArgument(arg[key]) - return newDict - elif isinstance(arg, list): - newList = [] - for item in arg: - newList.append(self.__convertArgument(item)) - return newList - elif isinstance(arg, set): - newSet = set() - for item in arg: - newSet.add(self.__convertArgument(item)) - return newSet - elif isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str): - self.bindings[arg[0]] = arg[1] - return Binding(arg[0],self.__convertArgument(arg[1])) - else: - return arg - def __repr__(self): - return (str(self.source_instructions) if len(self.source_instructions) > 0 else "") + \\ - (str(self.step_instructions) if len(self.step_instructions) > 0 else "") - - -''' -BINDINGS -''' - -class Bindings(object): - def of(self,key,value): - if not isinstance(key, str): - raise TypeError("Key must be str") - return (key,value) - -class Binding(object): - def __init__(self,key,value): - self.key = key - self.value = value - def __eq__(self, other): - return isinstance(other, self.__class__) and self.key == other.key and self.value == other.value - def __hash__(self): - return hash(self.key) + hash(self.value) - def __repr__(self): - return "binding[" + self.key + "=" + str(self.value) + "]" - -""") - ////////////// - - // save to a python file - final File file = new File(traversalSourceFile); - file.delete() - pythonClass.eachLine { file.append(it + "\n") } - } -} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/894fc805/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/GenerateGremlinPython.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/GenerateGremlinPython.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/GenerateGremlinPython.java deleted file mode 100644 index 6d8f04d..0000000 --- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/GenerateGremlinPython.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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; - -public class GenerateGremlinPython { - - private GenerateGremlinPython() { - // just need the main method - } - - public static void main(String[] args) { - TraversalSourceGenerator.create(args[0]); - GraphTraversalSourceGenerator.create(args[1]); - } -}
