You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2018/09/07 17:25:41 UTC
tinkerpop git commit: TINKERPOP-1921 Added hasNext() in gremlin-python
Repository: tinkerpop
Updated Branches:
refs/heads/TINKERPOP-1921 [created] 9dbd2d28b
TINKERPOP-1921 Added hasNext() in gremlin-python
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9dbd2d28
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9dbd2d28
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9dbd2d28
Branch: refs/heads/TINKERPOP-1921
Commit: 9dbd2d28b624ae262b359a7320fdcb5d7b207476
Parents: c029eef
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 7 13:23:36 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Sep 7 13:23:36 2018 -0400
----------------------------------------------------------------------
CHANGELOG.asciidoc | 1 +
gremlin-python/glv/TraversalSource.template | 40 ++++++++++++++++++++
.../jython/gremlin_python/process/traversal.py | 40 ++++++++++++++++++++
.../driver/test_driver_remote_connection.py | 39 +++++++++++++++++++
4 files changed, 120 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9dbd2d28/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 158cc7a..8f14b8e 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -33,6 +33,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Match numbers in `choose()` options using `NumberHelper` (match values, ignore data type).
* Added support for GraphSON serialization of `Date` in Javascript.
* Added better internal processing of `Column` in `by(Function)`.
+* Added `hasNext()` support on `Traversal` for `gremlin-python`.
* Added support for additional extended types in Gremlin.Net with `decimal`, `TimeSpan`, `BigInteger`, `byte`, `byte[]`, `char` and `short`.
* Fixed bug in Java driver where an disorderly shutdown of the server would cause the client to hang.
* Added a dotnet template project that should make it easier to get started with Gremlin.Net.
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9dbd2d28/gremlin-python/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-python/glv/TraversalSource.template b/gremlin-python/glv/TraversalSource.template
index b6f5b9f..a6ab9ad 100644
--- a/gremlin-python/glv/TraversalSource.template
+++ b/gremlin-python/glv/TraversalSource.template
@@ -29,15 +29,19 @@ class Traversal(object):
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)
@@ -48,14 +52,18 @@ class Traversal(object):
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)
@@ -65,6 +73,15 @@ class Traversal(object):
temp = self.last_traverser
self.last_traverser = None
return temp
+
+ def hasNext(self):
+ if self.traversers is None:
+ self.traversal_strategies.apply_strategies(self)
+ if self.last_traverser is None:
+ try: self.last_traverser = next(self.traversers)
+ except StopIteration: return False
+ return not(self.last_traverser is None) and self.last_traverser.bulk > 0
+
def next(self, amount=None):
if amount is None:
return self.__next__()
@@ -77,6 +94,7 @@ class Traversal(object):
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
@@ -144,8 +162,10 @@ class Traverser(object):
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
@@ -156,10 +176,13 @@ 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())) + "]"
@@ -171,14 +194,18 @@ 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)
@@ -187,14 +214,19 @@ 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
@@ -210,21 +242,25 @@ class Bytecode(object):
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)
@@ -249,6 +285,7 @@ class Bytecode(object):
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 "")
@@ -268,9 +305,12 @@ 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) + "]"
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9dbd2d28/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 747ed81..73f8962 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -29,15 +29,19 @@ class Traversal(object):
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)
@@ -48,14 +52,18 @@ class Traversal(object):
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)
@@ -65,6 +73,15 @@ class Traversal(object):
temp = self.last_traverser
self.last_traverser = None
return temp
+
+ def hasNext(self):
+ if self.traversers is None:
+ self.traversal_strategies.apply_strategies(self)
+ if self.last_traverser is None:
+ try: self.last_traverser = next(self.traversers)
+ except StopIteration: return False
+ return not(self.last_traverser is None) and self.last_traverser.bulk > 0
+
def next(self, amount=None):
if amount is None:
return self.__next__()
@@ -77,6 +94,7 @@ class Traversal(object):
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
@@ -313,8 +331,10 @@ class Traverser(object):
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
@@ -325,10 +345,13 @@ 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())) + "]"
@@ -340,14 +363,18 @@ 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)
@@ -356,14 +383,19 @@ 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
@@ -379,21 +411,25 @@ class Bytecode(object):
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)
@@ -418,6 +454,7 @@ class Bytecode(object):
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 "")
@@ -437,9 +474,12 @@ 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) + "]"
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9dbd2d28/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
index 4d2409e..627fbe4 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
@@ -26,6 +26,7 @@ from gremlin_python.driver.driver_remote_connection import (
DriverRemoteConnection)
from gremlin_python.process.traversal import Traverser
from gremlin_python.process.traversal import TraversalStrategy
+from gremlin_python.process.traversal import P
from gremlin_python.process.graph_traversal import __
from gremlin_python.structure.graph import Graph
from gremlin_python.structure.graph import Vertex
@@ -82,6 +83,44 @@ class TestDriverRemoteConnection(object):
assert 'marko' in results
assert 'vadas' in results
+ def test_iteration(self, remote_connection):
+ statics.load_statics(globals())
+ assert "remoteconnection[ws://localhost:45940/gremlin,gmodern]" == str(remote_connection)
+ g = Graph().traversal().withRemote(remote_connection)
+
+ t = g.V().count()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert 6 == t.next()
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+
+ t = g.V().has('name', P.within('marko', 'peter')).values('name').order()
+ assert "marko" == t.next()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert t.hasNext()
+ assert "peter" == t.next()
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+ assert not(t.hasNext())
+
+ try:
+ t.next()
+ assert False
+ except StopIteration:
+ assert True
+
def test_strategies(self, remote_connection):
statics.load_statics(globals())
#