Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add RawExpression to gremlin_python #340

Merged
merged 4 commits into from Jun 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/src/reference/gremlin-variants.asciidoc
Expand Up @@ -157,3 +157,37 @@ g.V().both()[1]
g.V().both().name
----

Inserting arbitrary expressions with Gremlin-Python
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To make use of APIs provided by your graph system vendor that aren't part of
the gremlin traversal API, you can use `RawExpression`. `RawExpression` allows
you to construct arbitrary expressions that collect bindings. When you pass
strings and bindings to the `RawExpression` constructor, the arguments will
be concatenated in the script that is sent to gremlin-server.

The following example uses `RawExpression` to call the `Geoshape.point` static
constructor method on the `Geoshape` class provided by TitanDB.

[source,python]
g.V().has('location', RawExpression('Geoshape.point(', ('x', 45), ', ', ('y', -45), ')'))
# sends the following script to gremlin-server:
# g.V().has("location", Geoshape.point(x, y))
#
# with the following bindings: {'x': 45, 'y': -45}

To help readability, especially if you will be using the expression more than
once, it is recommended to use this in conjunction with a helper class as in
the following example:

[source,python]
class Geoshape(object):
@staticmethod
def point(latitude, longitude):
return RawExpression('Geoshape.point(', latitude, ', ', longitude, ')')

The previous traversal can now be written much more simply:

[source,python]
g.V().has('location', Geoshape.point(('x', 45), ('y', -45)))

Expand Up @@ -177,8 +177,10 @@ builtInRange = range
""" def ${method}(self, *args):
self.translator.addStep(self, "${method}", *args)
for arg in args:
if isinstance(arg, dict) and 1 == len(arg) and isinstance(arg.keys()[0],str):
self.bindings.update(arg)
if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
self.bindings[arg[0]] = arg[1]
elif isinstance(arg, RawExpression):
self.bindings.update(arg.bindings)
return self
""")
}
Expand Down Expand Up @@ -230,6 +232,31 @@ builtInRange = range
pythonClass.append("\n");
}
//////////////

pythonClass.append("""class RawExpression(object):
def __init__(self, *args):
self.bindings = dict()
self.parts = [self._process_arg(arg) for arg in args]

def _process_arg(self, arg):
if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
self.bindings[arg[0]] = arg[1]
return Raw(arg[0])
else:
return Raw(arg)
""")

pythonClass.append("\n")
pythonClass.append("""class Raw(object):
def __init__(self, value):
self.value = value

def __str__(self):
return str(self.value)
""")

pythonClass.append("\n")

pythonClass.append("""class P(object):
def __init__(self, operator, value, other=None):
self.operator = operator
Expand Down
2 changes: 2 additions & 0 deletions gremlin-variant/src/main/jython/gremlin_python/.gitignore
@@ -0,0 +1,2 @@
__pycache__/
*.py[cdo]