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/08/17 20:17:52 UTC
tinkerpop git commit: RemoteGraph.py no longer exists. Its now just
Graph().traversal().withRemote(). Found a severe bug in
TraversalStrategies.py that has now been fixed. Updated the
gremlin-variants.asciidoc with latest changes and combed through it fu
Repository: tinkerpop
Updated Branches:
refs/heads/TINKERPOP-1278 b4c613981 -> 4a6645517
RemoteGraph.py no longer exists. Its now just Graph().traversal().withRemote(). Found a severe bug in TraversalStrategies.py that has now been fixed. Updated the gremlin-variants.asciidoc with latest changes and combed through it fully to clean up the text and examples as best as possible. Updated gremlin-server-modern-py.yaml to include both gremlin-jython and gremlin-python ScriptEngines as there truly is a difference and they need to be kept distinct even if they point to the same ultimate GremlinJythonScriptEngine.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/4a664551
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/4a664551
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/4a664551
Branch: refs/heads/TINKERPOP-1278
Commit: 4a6645517325612faa78b6a6f86417e318fc0b89
Parents: b4c6139
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Aug 17 14:17:47 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Aug 17 14:17:47 2016 -0600
----------------------------------------------------------------------
docs/preprocessor/awk/init-code-blocks.awk | 7 +-
docs/src/reference/gremlin-variants.asciidoc | 98 +++++++++++---------
.../process/traversal/TraversalSource.java | 1 +
.../python/GraphTraversalSourceGenerator.groovy | 15 ++-
.../python/TraversalSourceGenerator.groovy | 7 +-
.../jython/gremlin_python/driver/__init__.py | 7 +-
.../gremlin_python/driver/remote_connection.py | 13 +++
.../gremlin_python/process/graph_traversal.py | 24 ++---
.../jython/gremlin_python/process/traversal.py | 7 +-
.../jython/gremlin_python/structure/__init__.py | 1 -
.../jython/gremlin_python/structure/graph.py | 6 ++
.../gremlin_python/structure/remote_graph.py | 45 ---------
.../driver/WebSocketRemoteConnectionTest.java | 4 +-
.../python/jsr223/JythonScriptEngineSetup.java | 2 +-
.../jsr223/PythonGraphSONJavaTranslator.java | 2 +-
.../conf/gremlin-server-modern-py.yaml | 4 +-
16 files changed, 124 insertions(+), 119 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/docs/preprocessor/awk/init-code-blocks.awk
----------------------------------------------------------------------
diff --git a/docs/preprocessor/awk/init-code-blocks.awk b/docs/preprocessor/awk/init-code-blocks.awk
index 4b52acd..7065df8a 100644
--- a/docs/preprocessor/awk/init-code-blocks.awk
+++ b/docs/preprocessor/awk/init-code-blocks.awk
@@ -60,16 +60,13 @@ BEGIN {
print "jython.eval('sys.path.append(\"" TP_HOME "/gremlin-python/target/test-classes/Lib\")')"
print "jython.eval('from gremlin_python import statics')"
print "jython.eval('from gremlin_python.process.traversal import *')"
- print "jython.eval('from gremlin_python.process.graph_traversal import GraphTraversal')"
- print "jython.eval('from gremlin_python.process.graph_traversal import GraphTraversalSource')"
- print "jython.eval('from gremlin_python.process.graph_traversal import __')"
- print "jython.eval('from gremlin_python.structure.remote_graph import RemoteGraph')"
+ print "jython.eval('from gremlin_python.structure.graph import Graph')"
print "jython.eval('from gremlin_python.process.graphson import GraphSONWriter')"
# print "jython.eval('from gremlin_python.process.graphson import serializers')"
# print "jython.eval('from gremlin_python.driver.websocket_remote_connection import WebSocketRemoteConnection')"
print "jython.eval('statics.load_statics(globals())')"
print "jythonBindings = jython.createBindings()"
- print "jythonBindings.put('g', jython.eval('RemoteGraph(None).traversal()'))"
+ print "jythonBindings.put('g', jython.eval('Graph().traversal()'))"
print "jythonBindings.put('h', g)"
print "jython.getContext().setBindings(jythonBindings, GLOBAL_SCOPE)"
print "groovy = new org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine()"
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/docs/src/reference/gremlin-variants.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index dd1577a..0d4ab03 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -28,7 +28,7 @@ Gremlin in any modern programming language.
IMPORTANT: Gremlin-Java is the canonical representation of Gremlin and any (proper) Gremlin language variant will emulate its
structure as best as possible given the constructs of the host language. A strong correspondence between variants ensures
that the general Gremlin reference documentation is applicable to all variants and that users moving between development
-languages can easily adopt the Gremlin language variant for that language.
+languages can easily adopt the Gremlin variant for that language.
image::gremlin-variant-architecture.png[width=650,float=left]
@@ -48,26 +48,23 @@ link:https://en.wikipedia.org/wiki/CPython[CPython] machine. Python's syntax has
namespaces (`a(b())` vs `a(__.b())`). As such, anyone familiar with Gremlin-Java will immediately be able to work
with Gremlin-Python. Moreover, there are a few added constructs to Gremlin-Python that make traversals a bit more succinct.
-CAUTION: Python has `as`, `in`, `and`, `or`, `is`, `not`, `from`, and `global` as reserved words. Gremlin-Python simply
+CAUTION: In Python, `as`, `in`, `and`, `or`, `is`, `not`, `from`, and `global` are reserved words. Gremlin-Python simply
prefixes `_` in front of these terms for their use with graph traversal. For instance: `g.V()._as('a')._in()._as('b').select('a','b')`.
-To install Gremlin-Python, simply use Python's link:https://en.wikipedia.org/wiki/Pip_(package_manager)[pip] package manager.
+To install Gremlin-Python, use Python's link:https://en.wikipedia.org/wiki/Pip_(package_manager)[pip] package manager.
[source,bash]
pip install gremlin_python
-There are three primary classes distributed with Gremlin-Python: `GraphTraversalSource`, `GraphTraversal`, and `__`.
+Gremlin-Python users will typically make use of the following classes.
[source,python]
-from gremlin_python import statics
-from gremlin_python.structure.remote_graph import RemoteGraph
-from gremlin_python.process.graph_traversal import GraphTraversalSource
-from gremlin_python.process.graph_traversal import GraphTraversal
-from gremlin_python.process.graph_traversal import __
-from gremlin_python.driver.websocket_remote_connection import WebSocketRemoteConnection
-
-These classes mirror `GraphTraversalSource`, `GraphTraversal`, and `__`, respectively in Gremlin-Java. The `GraphTraversalSource`
-requires a driver in order to communicate with <<gremlin-server,GremlinServer>> (or any <<connecting-via-remotegraph,`RemoteConnection`>>-enabled server).
+>>> from gremlin_python import statics
+>>> from gremlin_python.structure.graph import Graph
+>>> from gremlin_python.driver.websocket_remote_connection import WebSocketRemoteConnection
+
+In Gremlin-Python there exists `GraphTraversalSource`, `GraphTraversal`, and `__` which mirror the respective classes in Gremlin-Java.
+The `GraphTraversalSource` requires a driver in order to communicate with <<gremlin-server,GremlinServer>> (or any <<connecting-via-remotegraph,`RemoteConnection`>>-enabled server).
The `gremlin_rest_driver` is provided with Apache TinkerPop and it serves as a simple (though verbose) driver that sends traversals to GremlinServer
via HTTP POST (using link:http://docs.python-requests.org/[requests]) and in return, is provided <<graphson-reader-writer,GraphSON>>-encoded results.
`WebSocketRemoteConnection` extends the abstract class `RemoteConnection` in `gremlin_python.driver`.
@@ -75,22 +72,26 @@ via HTTP POST (using link:http://docs.python-requests.org/[requests]) and in ret
IMPORTANT: For developers wishing to provide another *driver implementation*, be sure to extend `RemoteConnection` in
`gremlin_python.driver` so it can then be used by Gremlin-Python's `GraphTraversal`.
-When GremlinServer is running, Gremlin-Python can communicate with GremlinServer. The `conf/gremlin-server-rest.modern.yaml`
-configuration is used to expose GremlinServer's REST interface.
+When GremlinServer is running, Gremlin-Python can communicate with GremlinServer. The `conf/gremlin-server-modern-py.yaml`
+configuration maintains a `GremlinJythonScriptEngine` as well as the appropriate serializers for communicating `Bytecode`.
[source,bash]
----
-$ bin/gremlin-server.sh conf/gremlin-server-rest-modern.yaml
+$ bin/gremlin-server.sh -i org.apache.tinkerpop gremlin-python x.y.z
+$ bin/gremlin-server.sh conf/gremlin-server-modern-py.yaml
[INFO] GremlinServer -
\,,,/
(o o)
---oOOo-(3)-oOOo---
-[INFO] GremlinServer - Configuring Gremlin Server from conf/gremlin-server-rest-modern.yaml
+[INFO] GremlinServer - Configuring Gremlin Server from conf/gremlin-server-modern-py.yaml
[INFO] GraphManager - Graph [graph] was successfully configured via [conf/tinkergraph-empty.properties].
+[INFO] ScriptEngines - Loaded gremlin-jython ScriptEngine
[INFO] ScriptEngines - Loaded gremlin-groovy ScriptEngine
-[INFO] GremlinExecutor - Initialized gremlin-groovy ScriptEngine with scripts/generate-modern.groovy
+[INFO] ServerGremlinExecutor - Initialized GremlinExecutor and configured ScriptEngines.
[INFO] ServerGremlinExecutor - A GraphTraversalSource is now bound to [g] with graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
+[INFO] TraversalOpProcessor - Initialized cache for TraversalOpProcessor with size 1000 and expiration time of 600000 ms
+[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v1.0+json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0
[INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0
[INFO] GremlinServer$1 - Channel started at port 8182.
----
@@ -98,14 +99,18 @@ $ bin/gremlin-server.sh conf/gremlin-server-rest-modern.yaml
Within the CPython console, it is possible to evaluate the following.
[source,python]
-graph = RemoteGraph(WebSocketsRemoteConnection('ws://localhost:8182','g'))
-g = graph.traversal()
+>>> graph = Graph()
+>>> g = graph.traversal().withRemote(WebSocketRemoteConnection('ws://localhost:8182','g'))
+
+When a traversal spawned from the `GraphTraversalSource` above is iterated, the traveral's `Bytecode` is sent over the wire
+via the registered `RemoteConnection`. The bytecode is used to construct the equivalent traversal at the remote traversal source.
+Moreover, typically the bytecode is analyzed to determine which language the bytecode should be translated to. If the traversal
+does not contain lambdas, the remote location (e.g. GremlinServer) will typically
+use Gremlin-Java. If it has lambdas written in Groovy, it will use Gremlin-Groovy (e.g. `GremlinGroovyScriptEngine`).
+Likewise, if it has lambdas represented in Python, it will use Gremlin-Python (e.g. `GremlinJythonScriptEngine`).
-When the traversal above is submitted to the `RemoteConnection`, it's `Bytecode` is sent in order to construct the equivalent traversal
-in GremlinServer (thus, remotely). The bytecode is analyzed to determine which language the bytecode should be translated to.
-If the traversal does not have lambdas, it will typically use Gremlin-Java. If it has lambdas written in Groovy,
-it will use Gremlin-Groovy (e.g. `GremlinGroovyScriptEngine`). Likewise, if it has lambdas represented in Python, it will use
-Gremlin-Python (e.g. `GremlinJythonScriptEngine`).
+IMPORTANT: Gremlin-Python's `Traversal` class supports the standard Gremlin methods such as `next()`, `nextTraverser()`,
+`toSet()`, `toList()`, etc. Such "terminal" methods trigger the evaluation of the traversal.
Gremlin-Python Sugar
~~~~~~~~~~~~~~~~~~~~
@@ -126,16 +131,16 @@ Static Enums and Methods
Gremlin has various tokens (e.g. `T`, `P`, `Order`, `Operator`, etc.) that are represented in Gremlin-Python as Python `Enums`.
[source,python]
-from gremlin_python.process.traversal import T
-from gremlin_python.process.traversal import Order
-from gremlin_python.process.traversal import Cardinality
-from gremlin_python.process.traversal import Column
-from gremlin_python.process.traversal import Direction
-from gremlin_python.process.traversal import Operator
-from gremlin_python.process.traversal import P
-from gremlin_python.process.traversal import Pop
-from gremlin_python.process.traversal import Scope
-from gremlin_python.process.traversal import Barrier
+>>> from gremlin_python.process.traversal import T
+>>> from gremlin_python.process.traversal import Order
+>>> from gremlin_python.process.traversal import Cardinality
+>>> from gremlin_python.process.traversal import Column
+>>> from gremlin_python.process.traversal import Direction
+>>> from gremlin_python.process.traversal import Operator
+>>> from gremlin_python.process.traversal import P
+>>> from gremlin_python.process.traversal import Pop
+>>> from gremlin_python.process.traversal import Scope
+>>> from gremlin_python.process.traversal import Barrier
These can be used analogously to how they are used in Gremlin-Java.
@@ -147,7 +152,7 @@ g.V().hasLabel('person').has('age',P.gt(30)).order().by('age',Order.decr).toList
Moreover, by importing the `statics` of Gremlin-Python, the class prefixes can be removed.
[source,python]
-statics.load_statics(globals())
+>>> statics.load_statics(globals())
With statics loaded its possible to represent the above traversal as below.
@@ -167,11 +172,11 @@ g.V().repeat(out()).times(2).name.fold().toList()
RemoteConnection Bindings
~~~~~~~~~~~~~~~~~~~~~~~~~
-When a traversal bytecode is sent over a `RemoteConnection` (e.g. GremlinServer), it will be translated, compiled, and executed accordingly.
-If the same traversal is sent again, translation and compilation can be skipped as the previously compiled version is typically cached.
+When a traversal bytecode is sent over a `RemoteConnection` (e.g. GremlinServer), it will be translated, compiled, and then executed.
+If the same traversal is sent again, translation and compilation can be skipped as the previously compiled version should be cached.
Many traversals are unique up to some parameterization. For instance, `g.V(1).out('created').name` is considered different
-from `g.V(4).out('created').name'` as they are different scripts. However, `g.V(x).out('created').name` with bindings of `{x : 1}` and
-`{x : 4}` are the same. If a traversal is going to be executed repeatedly, but with different parameters, then bindings should be used.
+from `g.V(4).out('created').name'` as they are different "string" scripts. However, `g.V(x).out('created').name` with bindings of `{x : 1}` and
+`{x : 4}` are considered the same. If a traversal is going to be executed repeatedly, but with different parameters, then bindings should be used.
In Gremlin-Python, bindings are 2-tuples and used as follows.
[gremlin-python,modern]
@@ -180,15 +185,18 @@ g.V(('id',1)).out('created').name.toList()
g.V(('id',4)).out('created').name.toList()
----
+IMPORTANT: The Gremlin-Java `withBindings()` traversal source step is not needed. Gremlin-Java's model is only required
+in statically typed languages where bindings need to have the same typing as the `Traversal` API.
+
The Lambda Solution
~~~~~~~~~~~~~~~~~~~
Supporting link:https://en.wikipedia.org/wiki/Anonymous_function[anonymous functions] across languages is extremely difficult.
-As a simple solution, it is up to the Gremlin variant to decide lambdas (in any language) should be expressed and ultimately
-encoded in the standard `Bytecode` format. In Gremlin-Python, a link:https://docs.python.org/2/reference/expressions.html#lambda[Python lambda]
-should be a zero-arg callable that returns a string representation of a lambda. The default lambda language is `gremlin-python`
-and can be changed via `gremlin_python.statics.default_lambda_language.` When the lambda is represented in `Bytecode` its language is encoded
-such that the remote connection host can infer which translator to use.
+In Gremlin-Python, a link:https://docs.python.org/2/reference/expressions.html#lambda[Python lambda]
+should be represented as a zero-arg callable that returns a string representation of a lambda.
+The default lambda language is `gremlin-python` and can be changed via `gremlin_python.statics.default_lambda_language.`
+When the lambda is represented in `Bytecode` its language is encoded such that the remote connection host can infer
+which translator and ultimate execution engine to use.
[gremlin-python,modern]
----
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
index 5e82716..7c9557c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
@@ -93,6 +93,7 @@ public interface TraversalSource extends Cloneable {
public static final String withoutStrategies = "withoutStrategies";
public static final String withComputer = "withComputer";
public static final String withSideEffect = "withSideEffect";
+ public static final String withRemote = "withRemote";
}
/////////////////////////////
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/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
index f076da9..4619c18 100644
--- 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
@@ -57,7 +57,9 @@ under the License.
'''
""")
pythonClass.append("from .traversal import Traversal\n")
+ pythonClass.append("from .traversal import TraversalStrategies\n")
pythonClass.append("from .traversal import Bytecode\n")
+ pythonClass.append("from ..driver.remote_connection import RemoteStrategy\n")
pythonClass.append("from .. import statics\n\n")
//////////////////////////
@@ -75,7 +77,11 @@ under the License.
return "graphtraversalsource[" + str(self.graph) + "]"
""")
GraphTraversalSource.getMethods()
- .findAll { !it.name.equals("clone") && !it.name.equals(TraversalSource.Symbols.withBindings) }
+ .findAll {
+ !it.name.equals("clone") &&
+ !it.name.equals(TraversalSource.Symbols.withBindings) &&
+ !it.name.equals(TraversalSource.Symbols.withRemote)
+ }
.collect { it.name }
.unique()
.sort { a, b -> a <=> b }
@@ -96,13 +102,18 @@ under the License.
} else if (TraversalSource.isAssignableFrom(returnType)) {
pythonClass.append(
""" def ${method}(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("${method}", *args)
return source
""")
}
}
}
+ pythonClass.append(""" def withRemote(self, remote_connection):
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
+ source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
+ return source
+""")
pythonClass.append("\n\n")
////////////////////
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/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
index 9845595..65dcabc 100644
--- 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
@@ -192,10 +192,13 @@ TRAVERSAL STRATEGIES
class TraversalStrategies(object):
global_cache = {}
- def __init__(self, traversal_strategies):
- self.traversal_strategies = traversal_strategies
+ def __init__(self, traversal_strategies=None):
+ self.traversal_strategies = traversal_strategies.traversal_strategies if traversal_strategies is not None else []
return
+ 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)
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/main/jython/gremlin_python/driver/__init__.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/__init__.py b/gremlin-python/src/main/jython/gremlin_python/driver/__init__.py
index c9f1586..4f06e4e 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/__init__.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/__init__.py
@@ -17,7 +17,12 @@ specific language governing permissions and limitations
under the License.
'''
from .remote_connection import RemoteConnection
+from .remote_connection import RemoteStrategy
from .remote_connection import RemoteTraversal
-from .websocket_remote_connection import WebSocketRemoteConnection
+
+try:
+ from .websocket_remote_connection import WebSocketRemoteConnection
+except ImportError:
+ pass
__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
index fffa677..43fed53 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
@@ -20,6 +20,7 @@ import abc
import six
from ..process.traversal import Traversal
+from ..process.traversal import TraversalStrategy
__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
@@ -49,3 +50,15 @@ class RemoteTraversal(Traversal):
Traversal.__init__(self, None, None, None)
self.traversers = traversers
self.side_effects = side_effects
+
+
+class RemoteStrategy(TraversalStrategy):
+ def __init__(self, remote_connection):
+ self.remote_connection = remote_connection
+
+ def apply(self, traversal):
+ if traversal.traversers is None:
+ remote_traversal = self.remote_connection.submit(traversal.bytecode)
+ traversal.side_effects = remote_traversal.side_effects
+ traversal.traversers = remote_traversal.traversers
+ return
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
index 43d9b91..8b3ff88 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
@@ -17,7 +17,9 @@ specific language governing permissions and limitations
under the License.
'''
from .traversal import Traversal
+from .traversal import TraversalStrategies
from .traversal import Bytecode
+from ..driver.remote_connection import RemoteStrategy
from .. import statics
class GraphTraversalSource(object):
@@ -46,37 +48,37 @@ class GraphTraversalSource(object):
traversal.bytecode.add_step("inject", *args)
return traversal
def withBulk(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("withBulk", *args)
return source
def withComputer(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("withComputer", *args)
return source
def withPath(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("withPath", *args)
return source
- def withRemote(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
- source.bytecode.add_source("withRemote", *args)
- return source
def withSack(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("withSack", *args)
return source
def withSideEffect(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("withSideEffect", *args)
return source
def withStrategies(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("withStrategies", *args)
return source
def withoutStrategies(self, *args):
- source = GraphTraversalSource(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
source.bytecode.add_source("withoutStrategies", *args)
return source
+ def withRemote(self, remote_connection):
+ source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
+ source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
+ return source
class GraphTraversal(Traversal):
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
index 46b7faa..3347034 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -272,10 +272,13 @@ TRAVERSAL STRATEGIES
class TraversalStrategies(object):
global_cache = {}
- def __init__(self, traversal_strategies):
- self.traversal_strategies = traversal_strategies
+ def __init__(self, traversal_strategies=None):
+ self.traversal_strategies = traversal_strategies.traversal_strategies if traversal_strategies is not None else []
return
+ 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)
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/main/jython/gremlin_python/structure/__init__.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/__init__.py b/gremlin-python/src/main/jython/gremlin_python/structure/__init__.py
index 1c69b5c..cb2d3b6 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/__init__.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/__init__.py
@@ -17,6 +17,5 @@ specific language governing permissions and limitations
under the License.
'''
from .graph import Graph
-from .remote_graph import RemoteGraph
__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/graph.py b/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
index 60b2211..b451ec6 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
@@ -24,5 +24,11 @@ from gremlin_python.process.traversal import TraversalStrategies
class Graph(object):
+ def __init__(self):
+ TraversalStrategies.global_cache[self.__class__] = TraversalStrategies()
+
def traversal(self):
return GraphTraversalSource(self, TraversalStrategies.global_cache[self.__class__])
+
+ def __repr__(self):
+ return "graph[]"
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py b/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py
deleted file mode 100644
index fa2fdb1..0000000
--- a/gremlin-python/src/main/jython/gremlin_python/structure/remote_graph.py
+++ /dev/null
@@ -1,45 +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.
-'''
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-from gremlin_python.process.traversal import TraversalStrategies
-from gremlin_python.process.traversal import TraversalStrategy
-from .graph import Graph
-
-
-class RemoteGraph(Graph):
- def __init__(self, remote_connection):
- TraversalStrategies.global_cache[self.__class__] = TraversalStrategies([RemoteStrategy()])
- self.remote_connection = remote_connection
-
- def __repr__(self):
- return "remotegraph[" + self.remote_connection.url + "]"
-
-
-class RemoteStrategy(TraversalStrategy):
- def apply(self, traversal):
- if not (traversal.graph.__class__.__name__ == "RemoteGraph"):
- raise BaseException(
- "RemoteStrategy can only be used with a RemoteGraph: " + traversal.graph.__class__.__name__)
- if traversal.traversers is None:
- remote_traversal = traversal.graph.remote_connection.submit(traversal.bytecode)
- traversal.side_effects = remote_traversal.side_effects
- traversal.traversers = remote_traversal.traversers
- return
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/driver/WebSocketRemoteConnectionTest.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/driver/WebSocketRemoteConnectionTest.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/driver/WebSocketRemoteConnectionTest.java
index 434056d..aa595c3 100644
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/driver/WebSocketRemoteConnectionTest.java
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/driver/WebSocketRemoteConnectionTest.java
@@ -49,9 +49,9 @@ public class WebSocketRemoteConnectionTest {
try {
JythonScriptEngineSetup.setup();
jython.getContext().getBindings(ScriptContext.ENGINE_SCOPE)
- .put("g", jython.eval("RemoteGraph(WebSocketRemoteConnection('ws://localhost:8182','g')).traversal()"));
+ .put("g", jython.eval("Graph().traversal().withRemote(WebSocketRemoteConnection('ws://localhost:8182','g'))"));
jython.getContext().getBindings(ScriptContext.ENGINE_SCOPE)
- .put("j", jython.eval("RemoteGraph(WebSocketRemoteConnection('ws://localhost:8182','g')).traversal()"));
+ .put("j", jython.eval("Graph().traversal().withRemote(WebSocketRemoteConnection('ws://localhost:8182','g'))"));
new GremlinServer(Settings.read(WebSocketRemoteConnectionTest.class.getResourceAsStream("gremlin-server-rest-modern.yaml"))).start().join();
} catch (final Exception ex) {
ex.printStackTrace();
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
index 618c488..75e9ce0 100644
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/JythonScriptEngineSetup.java
@@ -45,7 +45,7 @@ public class JythonScriptEngineSetup {
jythonEngine.eval("from gremlin_python.process.graph_traversal import __");
// jythonEngine.eval("from gremlin_python.driver.websocket_remote_connection import WebSocketRemoteConnection");
jythonEngine.eval("from gremlin_python.process.traversal import Bytecode");
- jythonEngine.eval("from gremlin_python.structure.remote_graph import RemoteGraph");
+ jythonEngine.eval("from gremlin_python.structure.graph import Graph");
jythonEngine.eval("from gremlin_python.process.graphson import GraphSONWriter");
} catch (final ScriptException e) {
throw new IllegalStateException(e.getMessage(), e);
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java
index 2a3e2b9..9f46bea 100644
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java
@@ -62,7 +62,7 @@ final class PythonGraphSONJavaTranslator<S extends TraversalSource, T extends Tr
final ScriptEngine jythonEngine = ScriptEngineCache.get("jython");
final Bindings bindings = jythonEngine.createBindings();
bindings.putAll(jythonEngine.getBindings(ScriptContext.ENGINE_SCOPE));
- bindings.put(this.pythonTranslator.getTraversalSource(), jythonEngine.eval("RemoteGraph(None).traversal()"));
+ bindings.put(this.pythonTranslator.getTraversalSource(), jythonEngine.eval("Graph().traversal()"));
bindings.putAll(bytecode.getBindings());
final String graphsonBytecode = jythonEngine.eval("GraphSONWriter.writeObject(" + this.pythonTranslator.translate(bytecode) + ")", bindings).toString();
return this.javaTranslator.translate(this.reader.readObject(new ByteArrayInputStream(graphsonBytecode.getBytes()), Bytecode.class));
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4a664551/gremlin-server/conf/gremlin-server-modern-py.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-modern-py.yaml b/gremlin-server/conf/gremlin-server-modern-py.yaml
index 44f7fe4..5c7a9c5 100644
--- a/gremlin-server/conf/gremlin-server-modern-py.yaml
+++ b/gremlin-server/conf/gremlin-server-modern-py.yaml
@@ -39,7 +39,9 @@ scriptEngines: {
imports: [java.lang.Math],
staticImports: [java.lang.Math.PI],
scripts: [scripts/generate-modern.groovy]},
- gremlin-jython: {}}
+ gremlin-jython: {},
+ gremlin-python: {}
+}
serializers:
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { useMapperFromGraph: graph }} # application/vnd.gremlin-v1.0+gryo
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0, config: { useMapperFromGraph: graph }} # application/vnd.gremlin-v1.0+gryo-lite