Skip to content

Commit

Permalink
All the Gremlin enums are now Python enums and thus, less 'string com…
Browse files Browse the repository at this point in the history
…pary' and the GroovyTranslator is much simpler/smaller. Drawback, for python2, you have to install the enum library.
  • Loading branch information
okram committed Jun 16, 2016
1 parent e348a95 commit 8ee2904
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 167 deletions.
Expand Up @@ -70,11 +70,14 @@ under the License.
.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")
pythonClass.append("""
globalTranslator = None
builtInRange = range
""").append("\n\n");

//////////////////////////
Expand Down Expand Up @@ -215,53 +218,18 @@ globalTranslator = None
///////////
// Enums //
///////////
pythonClass.append("class Cardinality(object):\n");
VertexProperty.Cardinality.values().each { value ->
pythonClass.append(" ${value} = \"VertexProperty.Cardinality.${value}\"\n");
}
pythonClass.append("\n");
//////////////
pythonClass.append("class Column(object):\n");
Column.values().each { value ->
pythonClass.append(" ${value} = \"${value.getDeclaringClass().getSimpleName()}.${value}\"\n");
}
pythonClass.append("\n");
Column.values().each { value ->
pythonClass.append("statics['${value}'] = ${value.getDeclaringClass().getSimpleName()}.${value}\n");
}
pythonClass.append("\n");
//////////////
pythonClass.append("class Direction(object):\n");
Direction.values().each { value ->
pythonClass.append(" ${value} = \"${value.getDeclaringClass().getSimpleName()}.${value}\"\n");
}
pythonClass.append("\n");
Direction.values().each { value ->
pythonClass.append("statics['${value}'] = ${value.getDeclaringClass().getSimpleName()}.${value}\n");
}
pythonClass.append("\n");
//////////////
pythonClass.append("class Operator(object):\n");
Operator.values().each { value ->
pythonClass.append(" ${methodMap[value.name()]} = \"${value.getDeclaringClass().getSimpleName()}.${value}\"\n");
}
pythonClass.append("\n");
Operator.values().each { value ->
pythonClass.append("statics['${methodMap[value.name()]}'] = ${value.getDeclaringClass().getSimpleName()}.${methodMap[value.name()]}\n");
}
pythonClass.append("\n");
//////////////
pythonClass.append("class Order(object):\n");
Order.values().each { value ->
pythonClass.append(" ${value} = \"${value.getDeclaringClass().getSimpleName()}.${value}\"\n");
}
pythonClass.append("\n");
Order.values().each { value ->
pythonClass.append("statics['${value}'] = ${value.getDeclaringClass().getSimpleName()}.${value}\n");
for (final Class<? extends Enum> enumClass : enumList) {
pythonClass.append("class ${enumClass.getSimpleName()}(Enum):\n ");
enumClass.getEnumConstants().each { value ->
pythonClass.append(" ${methodMap[value.name()]},");
}
pythonClass.deleteCharAt(pythonClass.length() - 1).append(" = builtInRange(${enumClass.getEnumConstants().length})\n\n")
enumClass.getEnumConstants().each { value ->
pythonClass.append("statics['${methodMap[value.name()]}'] = ${value.getDeclaringClass().getSimpleName()}.${methodMap[value.name()]}\n");
}
pythonClass.append("\n");
}
pythonClass.append("\n");
//////////////

pythonClass.append("""class P(object):
def __init__(self, operator, value, other=None):
self.operator = operator
Expand Down Expand Up @@ -299,41 +267,6 @@ globalTranslator = None
}
pythonClass.append("\n")
//////////////
pythonClass.append("class Pop(object):\n");
Pop.values().each { value ->
pythonClass.append(" ${value} = \"${value.getDeclaringClass().getSimpleName()}.${value}\"\n");
}
pythonClass.append("\n");
Pop.values().each { value ->
pythonClass.append("statics['${value}'] = ${value.getDeclaringClass().getSimpleName()}.${value.name()}\n");
}
pythonClass.append("\n");
//////////////
pythonClass.append("""class Barrier(object):
normSack = "SackFunctions.Barrier.normSack"
""");
pythonClass.append("\n")
pythonClass.append("statics['normSack'] = Barrier.normSack\n\n")
//////////////
pythonClass.append("class Scope(object):\n");
Scope.values().each { value ->
pythonClass.append(" ${methodMap[value.name()]} = \"${value.getDeclaringClass().getSimpleName()}.${value}\"\n");
}
pythonClass.append("\n");
Scope.values().each { value ->
pythonClass.append("statics['${methodMap[value.name()]}'] = ${value.getDeclaringClass().getSimpleName()}.${methodMap[value.name()]}\n");
}
pythonClass.append("\n");
//////////////
pythonClass.append("class T(object):\n");
T.values().each { value ->
pythonClass.append(" ${value} = \"${value.getDeclaringClass().getSimpleName()}.${value}\"\n");
}
pythonClass.append("\n");
T.values().each { value ->
pythonClass.append("statics['${value}'] = ${value.getDeclaringClass().getSimpleName()}.${value}\n");
}
pythonClass.append("\n");

pythonClass.append("statics = OrderedDict(reversed(list(statics.items())))\n")

Expand Down
1 change: 0 additions & 1 deletion gremlin-variant/src/main/jython/gremlin_python/__init__.py
Expand Up @@ -20,7 +20,6 @@
from gremlin_python import PythonGraphTraversalSource
from gremlin_python import __
from gremlin_python import statics
from gremlin_python import B
from gremlin_python import T
from gremlin_python import Order
from gremlin_python import Cardinality
Expand Down
105 changes: 42 additions & 63 deletions gremlin-variant/src/main/jython/gremlin_python/gremlin_python.py
Expand Up @@ -17,10 +17,12 @@
under the License.
'''
from collections import OrderedDict
from aenum import Enum
statics = OrderedDict()


globalTranslator = None
builtInRange = range


class PythonGraphTraversalSource(object):
Expand Down Expand Up @@ -1369,39 +1371,28 @@ def where(*args):
statics['where'] = where


class Cardinality(object):
single = "VertexProperty.Cardinality.single"
list = "VertexProperty.Cardinality.list"
set = "VertexProperty.Cardinality.set"
class Cardinality(Enum):
single, list, set = builtInRange(3)

class Column(object):
keys = "Column.keys"
values = "Column.values"
statics['single'] = Cardinality.single
statics['list'] = Cardinality.list
statics['set'] = Cardinality.set

class Column(Enum):
keys, values = builtInRange(2)

statics['keys'] = Column.keys
statics['values'] = Column.values

class Direction(object):
OUT = "Direction.OUT"
IN = "Direction.IN"
BOTH = "Direction.BOTH"
class Direction(Enum):
OUT, IN, BOTH = builtInRange(3)

statics['OUT'] = Direction.OUT
statics['IN'] = Direction.IN
statics['BOTH'] = Direction.BOTH

class Operator(object):
sum = "Operator.sum"
minus = "Operator.minus"
mult = "Operator.mult"
div = "Operator.div"
min = "Operator.min"
max = "Operator.max"
assign = "Operator.assign"
_and = "Operator.and"
_or = "Operator.or"
addAll = "Operator.addAll"
sumLong = "Operator.sumLong"
class Operator(Enum):
sum, minus, mult, div, min, max, assign, _and, _or, addAll, sumLong = builtInRange(11)

statics['sum'] = Operator.sum
statics['minus'] = Operator.minus
Expand All @@ -1415,14 +1406,8 @@ class Operator(object):
statics['addAll'] = Operator.addAll
statics['sumLong'] = Operator.sumLong

class Order(object):
incr = "Order.incr"
decr = "Order.decr"
keyIncr = "Order.keyIncr"
valueIncr = "Order.valueIncr"
keyDecr = "Order.keyDecr"
valueDecr = "Order.valueDecr"
shuffle = "Order.shuffle"
class Order(Enum):
incr, decr, keyIncr, valueIncr, keyDecr, valueDecr, shuffle = builtInRange(7)

statics['incr'] = Order.incr
statics['decr'] = Order.decr
Expand All @@ -1432,6 +1417,32 @@ class Order(object):
statics['valueDecr'] = Order.valueDecr
statics['shuffle'] = Order.shuffle

class Pop(Enum):
first, last, all = builtInRange(3)

statics['first'] = Pop.first
statics['last'] = Pop.last
statics['all'] = Pop.all

class Barrier(Enum):
normSack = builtInRange(1)

statics['normSack'] = Barrier.normSack

class Scope(Enum):
_global, local = builtInRange(2)

statics['_global'] = Scope._global
statics['local'] = Scope.local

class T(Enum):
label, id, key, value = builtInRange(4)

statics['label'] = T.label
statics['id'] = T.id
statics['key'] = T.key
statics['value'] = T.value

class P(object):
def __init__(self, operator, value, other=None):
self.operator = operator
Expand Down Expand Up @@ -1549,36 +1560,4 @@ def without(*args):

statics['without'] = without

class Pop(object):
first = "Pop.first"
last = "Pop.last"
all = "Pop.all"

statics['first'] = Pop.first
statics['last'] = Pop.last
statics['all'] = Pop.all

class Barrier(object):
normSack = "SackFunctions.Barrier.normSack"

statics['normSack'] = Barrier.normSack

class Scope(object):
_global = "Scope.global"
local = "Scope.local"

statics['_global'] = Scope._global
statics['local'] = Scope.local

class T(object):
label = "T.label"
id = "T.id"
key = "T.key"
value = "T.value"

statics['label'] = T.label
statics['id'] = T.id
statics['key'] = T.key
statics['value'] = T.value

statics = OrderedDict(reversed(list(statics.items())))
50 changes: 27 additions & 23 deletions gremlin-variant/src/main/jython/gremlin_python/groovy_translator.py
Expand Up @@ -18,6 +18,7 @@
'''

import sys
from aenum import Enum

from gremlin_python import P
from translator import Translator
Expand All @@ -30,6 +31,8 @@
methodMap = {"_global": "global", "_as": "as", "_in": "in", "_and": "and", "_or": "or", "_is": "is", "_not": "not",
"_from": "from"}

enumMap = {"Cardinality": "VertexProperty.Cardinality", "Barrier": "SackFunctions.Barrier"}


class GroovyTranslator(Translator):
def __init__(self, alias, script_engine="gremlin-groovy"):
Expand All @@ -56,48 +59,49 @@ def addSource(self, traversal_source, source_name, *args):
def getAnonymousTraversalTranslator(self):
return GroovyTranslator("__", self.script_engine)

### HELPER METHODS ###

@staticmethod
def mapMethod(method):
if (method in methodMap):
return methodMap[method]
else:
return method

@staticmethod
def mapEnum(enum):
if (enum in enumMap):
return enumMap[enum]
else:
return enum

@staticmethod
def stringOrObject(arg):
if (isinstance(arg, str) and
not (arg.startswith("SackFunctions.Barrier.")) and
not (arg.startswith("VertexProperty.Cardinality.")) and
not (arg.startswith("Column.")) and
not (arg.startswith("Computer.")) and
not (arg.startswith("Direction.")) and
not (arg.startswith("Operator.")) and
not (arg.startswith("Order.")) and
not (arg.startswith("Pop.")) and
not (arg.startswith("ReadOnlyStrategy.")) and
not (arg.startswith("Scope.")) and
not (arg.startswith("T.")) and
not (len(arg) == 0)):
not (arg.startswith("ReadOnlyStrategy."))):
return "\"" + arg + "\""
elif callable(arg): # closures
lambdaString = arg().strip()
if lambdaString.startswith("{"):
return lambdaString
else:
return "{" + lambdaString + "}"
elif isinstance(arg, bool):
return str(arg).lower()
elif isinstance(arg, long):
return str(arg) + "L"
elif isinstance(arg, float):
return str(arg) + "f"
elif isinstance(arg, Enum): # Column, Order, Direction, Scope, T, etc.
return GroovyTranslator.mapEnum(type(arg).__name__) + "." + GroovyTranslator.mapMethod(str(arg.name))
elif isinstance(arg, P):
if arg.other is None:
return "P." + GroovyTranslator.mapMethod(arg.operator) + "(" + GroovyTranslator.stringOrObject(
arg.value) + ")"
else:
return GroovyTranslator.stringOrObject(arg.other) + "." + GroovyTranslator.mapMethod(
arg.operator) + "(" + GroovyTranslator.stringOrObject(arg.value) + ")"
elif isinstance(arg, bool):
return str(arg).lower()
elif isinstance(arg, long):
return str(arg) + "L"
elif isinstance(arg, float):
return str(arg) + "f"
elif callable(arg): # closures
lambdaString = arg().strip()
if lambdaString.startswith("{"):
return lambdaString
else:
return "{" + lambdaString + "}"
elif isinstance(arg, dict) and 1 == len(arg) and isinstance(arg.keys()[0], str): # bindings
return arg.keys()[0]
else:
Expand Down
Expand Up @@ -47,6 +47,7 @@ public class PythonProvider extends VariantGraphProvider {
jythonEngine.eval("import sys");
jythonEngine.eval("sys.path.append('" + gremlinPythonPackageName + "')");
jythonEngine.eval("sys.path.append('" + gremlinDriverPackageName + "')");
jythonEngine.eval("sys.path.append('/Library/Python/2.7/site-packages')"); // TODO: require PYTHONPATH
jythonEngine.eval("from gremlin_python import *");
jythonEngine.eval("from gremlin_python import __");
jythonEngine.eval("from groovy_translator import GroovyTranslator");
Expand Down

0 comments on commit 8ee2904

Please sign in to comment.