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())
         #