diff --git a/goblin/driver/connection.py b/goblin/driver/connection.py index 3fbb2ac4849e63fa7a28df7440fbff4c83001dd0..468dda631da3ca9999622d07faf2e6c8671f7dba 100644 --- a/goblin/driver/connection.py +++ b/goblin/driver/connection.py @@ -77,6 +77,10 @@ class Connection(AbstractConnection): def force_close(self): return self._force_close + @property + def url(self): + return self._url + async def submit(self, gremlin, *, diff --git a/goblin/driver/graph.py b/goblin/driver/graph.py new file mode 100644 index 0000000000000000000000000000000000000000..7d6c70e5aa0ab90037f94062929158d1684a3281 --- /dev/null +++ b/goblin/driver/graph.py @@ -0,0 +1,45 @@ +from goblin.gremlin_python.process.graph_traversal import GraphTraversalSource, GraphTraversal +from goblin.gremlin_python.process.traversal import TraversalStrategy, TraversalStrategies + + +class AsyncGraphTraversal(GraphTraversal): + def __init__(self, graph, traversal_strategies, bytecode): + GraphTraversal.__init__(self, graph, traversal_strategies, bytecode) + + def __repr__(self): + return self.graph.translator.translate(self.bytecode) + + def toList(self): + raise NotImplementedError + + def toSet(self): + raise NotImplementedError + + async def next(self): + resp = await self.traversal_strategies.apply(self) + return resp + + +class AsyncRemoteStrategy(TraversalStrategy): + async def apply(self, traversal): + result = await traversal.graph.remote_connection.submit( + traversal.graph.translator.translate(traversal.bytecode), + bindings=traversal.bindings, + lang=traversal.graph.translator.target_language) + return result + + +class AsyncGraph(object): + def traversal(self): + return GraphTraversalSource(self, self.traversal_strategy, + graph_traversal=AsyncGraphTraversal) + + +class AsyncRemoteGraph(AsyncGraph): + def __init__(self, translator, remote_connection): + self.traversal_strategy = AsyncRemoteStrategy() # A single traversal strategy + self.translator = translator + self.remote_connection = remote_connection + + def __repr__(self): + return "remotegraph[" + self.remote_connection.url + "]" diff --git a/goblin/gremlin_python/__init__.py b/goblin/gremlin_python/__init__.py index cd21e560a3b04e53cdc4ddc4cb3d7ada20c24b47..518d8e008b256688b90e792343fd0cf1e7bb26e2 100644 --- a/goblin/gremlin_python/__init__.py +++ b/goblin/gremlin_python/__init__.py @@ -16,6 +16,6 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ''' -import statics +from . import statics __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)' diff --git a/goblin/gremlin_python/driver/__init__.py b/goblin/gremlin_python/driver/__init__.py index bb4e612a0bac6f452a6a677a0541cedf17d8dde2..7e1c0f1a812f96353a3b4b12daf4db66b2ce4a51 100644 --- a/goblin/gremlin_python/driver/__init__.py +++ b/goblin/gremlin_python/driver/__init__.py @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ''' -from remote_connection import RemoteConnection -from rest_remote_connection import RESTRemoteConnection +from .remote_connection import RemoteConnection +from .rest_remote_connection import RESTRemoteConnection __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)' diff --git a/goblin/gremlin_python/driver/rest_remote_connection.py b/goblin/gremlin_python/driver/rest_remote_connection.py index b827d0d5f1f3439dc638c7c2d0e7232f5be0cb36..b2034fd9e15988b53b52c76c610d47ea666e37f4 100644 --- a/goblin/gremlin_python/driver/rest_remote_connection.py +++ b/goblin/gremlin_python/driver/rest_remote_connection.py @@ -19,8 +19,8 @@ under the License. import json import requests -from gremlin_python.process.traversal import Traverser -from remote_connection import RemoteConnection +from goblin.gremlin_python.process.traversal import Traverser +from .remote_connection import RemoteConnection __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)' diff --git a/goblin/gremlin_python/process/__init__.py b/goblin/gremlin_python/process/__init__.py index d84b097ac1185a96a9f9a38164888447ee1f9ad8..e93356e95724d6eaab0892313c6744643294229b 100644 --- a/goblin/gremlin_python/process/__init__.py +++ b/goblin/gremlin_python/process/__init__.py @@ -17,22 +17,22 @@ specific language governing permissions and limitations under the License. ''' -from graph_traversal import GraphTraversal -from graph_traversal import GraphTraversalSource -from graph_traversal import __ -from groovy_translator import GroovyTranslator -from jython_translator import JythonTranslator -from traversal import Barrier -from traversal import Bytecode -from traversal import Cardinality -from traversal import Column -from traversal import Direction -from traversal import Operator -from traversal import Order -from traversal import P -from traversal import Pop -from traversal import Scope -from traversal import T -from traversal import Traversal +from .graph_traversal import GraphTraversal +from .graph_traversal import GraphTraversalSource +from .graph_traversal import __ +from .groovy_translator import GroovyTranslator +from .jython_translator import JythonTranslator +from .traversal import Barrier +from .traversal import Bytecode +from .traversal import Cardinality +from .traversal import Column +from .traversal import Direction +from .traversal import Operator +from .traversal import Order +from .traversal import P +from .traversal import Pop +from .traversal import Scope +from .traversal import T +from .traversal import Traversal __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)' diff --git a/goblin/gremlin_python/process/graph_traversal.py b/goblin/gremlin_python/process/graph_traversal.py index 2261e83acf54a87139fa522f15ac18901a8aa98a..b5d6a1733912eb742a743c59dbab647c4ac34922 100644 --- a/goblin/gremlin_python/process/graph_traversal.py +++ b/goblin/gremlin_python/process/graph_traversal.py @@ -16,20 +16,23 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ''' -from traversal import RawExpression -from traversal import Traversal -from traversal import Bytecode -from gremlin_python import statics +from .traversal import RawExpression +from .traversal import Traversal +from .traversal import Bytecode +from goblin.gremlin_python import statics class GraphTraversalSource(object): - def __init__(self, graph, traversal_strategies, bytecode=Bytecode()): + def __init__(self, graph, traversal_strategies, graph_traversal=None, bytecode=Bytecode()): self.graph = graph self.traversal_strategies = traversal_strategies + if graph_traversal is None: + graph_traversal = GraphTraversal + self.graph_traversal = graph_traversal self.bytecode = bytecode def __repr__(self): return "graphtraversalsource[" + str(self.graph) + "]" def E(self, *args): - traversal = GraphTraversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) + traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) traversal.bytecode.add_step("E", *args) for arg in args: if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str): @@ -38,7 +41,7 @@ class GraphTraversalSource(object): self.bindings.update(arg.bindings) return traversal def V(self, *args): - traversal = GraphTraversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) + traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) traversal.bytecode.add_step("V", *args) for arg in args: if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str): @@ -47,7 +50,7 @@ class GraphTraversalSource(object): self.bindings.update(arg.bindings) return traversal def addV(self, *args): - traversal = GraphTraversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) + traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) traversal.bytecode.add_step("addV", *args) for arg in args: if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str): @@ -56,7 +59,7 @@ class GraphTraversalSource(object): self.bindings.update(arg.bindings) return traversal def inject(self, *args): - traversal = GraphTraversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) + traversal = self.graph_traversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode)) traversal.bytecode.add_step("inject", *args) for arg in args: if isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str): @@ -1684,6 +1687,3 @@ def where(*args): return __.where(*args) statics.add_static('where', where) - - - diff --git a/goblin/gremlin_python/process/groovy_translator.py b/goblin/gremlin_python/process/groovy_translator.py index a05885d83d02ec3e997ba12c85ba23dacc72cf42..2c2d79a860da80b70bb427df6351793e06c8df45 100644 --- a/goblin/gremlin_python/process/groovy_translator.py +++ b/goblin/gremlin_python/process/groovy_translator.py @@ -20,11 +20,11 @@ under the License. import sys from aenum import Enum -from traversal import Bytecode -from traversal import P -from traversal import RawExpression -from traversal import SymbolHelper -from traversal import Translator +from .traversal import Bytecode +from .traversal import P +from .traversal import RawExpression +from .traversal import SymbolHelper +from .traversal import Translator if sys.version_info.major > 2: long = int diff --git a/goblin/gremlin_python/process/jython_translator.py b/goblin/gremlin_python/process/jython_translator.py index 0ffcaabf8a5f3fffb1f1fe8a11092ecc5a9c2bd1..c3169f07c71a0fb0e5a35a33ef2c60bf66e7b5e6 100644 --- a/goblin/gremlin_python/process/jython_translator.py +++ b/goblin/gremlin_python/process/jython_translator.py @@ -21,14 +21,14 @@ import inspect import sys from aenum import Enum -from traversal import Barrier -from traversal import Bytecode -from traversal import Cardinality -from traversal import Column -from traversal import P -from traversal import RawExpression -from traversal import SymbolHelper -from traversal import Translator +from .traversal import Barrier +from .traversal import Bytecode +from .traversal import Cardinality +from .traversal import Column +from .traversal import P +from .traversal import RawExpression +from .traversal import SymbolHelper +from .traversal import Translator if sys.version_info.major > 2: long = int @@ -57,7 +57,7 @@ class JythonTranslator(Translator): if isinstance(arg, str): return "\"" + arg + "\"" elif isinstance(arg, long): - return str(arg) + "L" if arg > 9223372036854775807L else "Long(" + str(arg) + ")" + return str(arg) elif isinstance(arg, Barrier): return "Barrier" + "." + SymbolHelper.toJava(str(arg.name)) elif isinstance(arg, Column): diff --git a/goblin/gremlin_python/process/traversal.py b/goblin/gremlin_python/process/traversal.py index 7558151f79f9ca7d837bc11e0c650c810eb52a19..c37c440f16b43279d138c64bfccf6168fbdd80ab 100644 --- a/goblin/gremlin_python/process/traversal.py +++ b/goblin/gremlin_python/process/traversal.py @@ -18,7 +18,7 @@ under the License. ''' from abc import abstractmethod from aenum import Enum -from gremlin_python import statics +from goblin.gremlin_python import statics class Traversal(object): def __init__(self, graph, traversal_strategies, bytecode): diff --git a/goblin/gremlin_python/structure/__init__.py b/goblin/gremlin_python/structure/__init__.py index fe9ad179920d5a82abe940c353fa8d516ffcefb2..1c69b5c0e00ef94926514351d5f58116fc30f5c6 100644 --- a/goblin/gremlin_python/structure/__init__.py +++ b/goblin/gremlin_python/structure/__init__.py @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ''' -from graph import Graph -from remote_graph import RemoteGraph +from .graph import Graph +from .remote_graph import RemoteGraph __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)' diff --git a/goblin/gremlin_python/structure/graph.py b/goblin/gremlin_python/structure/graph.py index 60b22113b57b5ac40156ad0a4adaaeded39b6586..82909f1b88c2400f23875c9f6fbcd48e3c0a49c6 100644 --- a/goblin/gremlin_python/structure/graph.py +++ b/goblin/gremlin_python/structure/graph.py @@ -19,8 +19,8 @@ under the License. __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)' -from gremlin_python.process.graph_traversal import GraphTraversalSource -from gremlin_python.process.traversal import TraversalStrategies +from goblin.gremlin_python.process.graph_traversal import GraphTraversalSource +from goblin.gremlin_python.process.traversal import TraversalStrategies class Graph(object): diff --git a/goblin/gremlin_python/structure/remote_graph.py b/goblin/gremlin_python/structure/remote_graph.py index bc2a11aef030d9207143134e85577354b4dfaf59..19125ea879c1a4414a95ede80f86b52b16328761 100644 --- a/goblin/gremlin_python/structure/remote_graph.py +++ b/goblin/gremlin_python/structure/remote_graph.py @@ -19,9 +19,9 @@ under the License. __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)' -from graph import Graph -from gremlin_python.process.traversal import TraversalStrategies -from gremlin_python.process.traversal import TraversalStrategy +from .graph import Graph +from goblin.gremlin_python.process.traversal import TraversalStrategies +from goblin.gremlin_python.process.traversal import TraversalStrategy class RemoteGraph(Graph): diff --git a/goblin/query.py b/goblin/query.py index 69b05f885cf24454ef2a91b29ddfacd2dcf1d0f5..41ce4495a6b00af8c31c50de87b6a3b3f0a2d4aa 100644 --- a/goblin/query.py +++ b/goblin/query.py @@ -2,7 +2,7 @@ import asyncio import logging -from goblin import gremlin_python +from goblin.gremlin_python import process from goblin import mapper @@ -35,7 +35,7 @@ class QueryResponse: raise StopAsyncIteration -class GoblinTraversal(gremlin_python.PythonGraphTraversal): +class GoblinTraversal(process.GraphTraversal): def __init__(self, translator, query, element_class): super().__init__(translator, remote_connection=None) @@ -57,7 +57,7 @@ class Query: def __init__(self, session, translator, loop): self._session = session self._translator = translator - self._traversal_source = gremlin_python.PythonGraphTraversalSource( + self._traversal_source = process.PythonGraphTraversalSource( self._translator) self._loop = loop self._binding = 0 diff --git a/setup.py b/setup.py index e5d6396dafbb4b5799549c1aadd68fa52fbba601..dc6daf40c01c25b55100bac7f0f261f2a5c820d5 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,8 @@ setup( author="davebshow", author_email="davebshow@gmail.com", description="Python driver for TP3 Gremlin Server", - packages=["goblin", "goblin.gremlin_python", + packages=["goblin", "goblin.gremlin_python", "goblin.gremlin_python.process", + "goblin.gremlin_python.driver", "goblin.gremlin_python.structure", "goblin.driver", "tests"], install_requires=[ "aenum==1.4.5", diff --git a/tests/test_driver.py b/tests/test_driver.py index 041733ce9caee20429721db0cd937684509b2543..0b486a8299cd48fb6a8d5950a5bb445138a10acf 100644 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -2,6 +2,8 @@ import asyncio import unittest from goblin import driver +from goblin.driver import graph +from goblin.gremlin_python import process class TestDriver(unittest.TestCase): @@ -42,3 +44,17 @@ class TestDriver(unittest.TestCase): await connection.close() self.loop.run_until_complete(go()) + + def test_async_graph(self): + + async def go(): + translator = process.GroovyTranslator('g') + connection = await driver.GremlinServer.open( + "http://localhost:8182/", self.loop) + g = graph.AsyncRemoteGraph(translator, connection) + traversal = g.traversal() + resp = await traversal.V().next() + async for msg in resp: + print(msg) + await connection.close() + self.loop.run_until_complete(go())