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 2020/03/24 19:30:16 UTC

[tinkerpop] 01/01: TINKERPOP-2350 Fixed bug in Traversal.clone() in gremlin-python

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-2350
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit c00921e8fb925649b06c8026d11dec7412b20ab7
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Tue Mar 24 15:23:39 2020 -0400

    TINKERPOP-2350 Fixed bug in Traversal.clone() in gremlin-python
    
    Needed to deep copy bytecode.
---
 CHANGELOG.asciidoc                                    |  4 ++--
 gremlin-python/glv/GraphTraversalSource.template      |  3 ++-
 gremlin-python/glv/TraversalSource.template           | 16 +++++++++++++++-
 .../jython/gremlin_python/process/graph_traversal.py  |  3 ++-
 .../main/jython/gremlin_python/process/traversal.py   | 16 +++++++++++++++-
 .../src/main/jython/tests/process/test_traversal.py   | 19 +++++++++++++++++++
 6 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 7b9ec50..e0c512e 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -20,7 +20,6 @@ limitations under the License.
 
 image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/gremlin-mozart.png[width=185]
 
-
 [[release-3-3-11]]
 === TinkerPop 3.3.11 (Release Date: NOT OFFICIALLY RELEASED YET)
 
@@ -29,7 +28,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Modified Gremlin Server to close the session when the channel itself is closed.
 * Added `maxWaitForClose` configuration option to the Java driver.
 * Deprecated `maxWaitForSessionClose` in the Java driver.
-* Remove invalid service descriptors from gremlin-shaded
+* Remove invalid service descriptors from gremlin-shaded.
+* Fixed bug in Python traversal `clone()` where deep copies of bytecode were not occurring.
 
 [[release-3-3-10]]
 === TinkerPop 3.3.10 (Release Date: February 3, 2020)
diff --git a/gremlin-python/glv/GraphTraversalSource.template b/gremlin-python/glv/GraphTraversalSource.template
index fbb64a6..27d9e15 100644
--- a/gremlin-python/glv/GraphTraversalSource.template
+++ b/gremlin-python/glv/GraphTraversalSource.template
@@ -18,6 +18,7 @@
 #
 
 import sys
+import copy
 from .traversal import Traversal
 from .traversal import TraversalStrategies
 from .strategies import VertexProgramStrategy
@@ -87,7 +88,7 @@ class GraphTraversal(Traversal):
         return self.values(key)
 
     def clone(self):
-        return GraphTraversal(self.graph, self.traversal_strategies, self.bytecode)
+        return GraphTraversal(self.graph, self.traversal_strategies, copy.deepcopy(self.bytecode))
 <% graphStepMethods.each { method -> %>
     def <%= method %>(self, *args):
         self.bytecode.add_step("<%= toJava.call(method) %>", *args)
diff --git a/gremlin-python/glv/TraversalSource.template b/gremlin-python/glv/TraversalSource.template
index 05acd9f..d617308 100644
--- a/gremlin-python/glv/TraversalSource.template
+++ b/gremlin-python/glv/TraversalSource.template
@@ -17,11 +17,11 @@
 # under the License.
 #
 
+import copy
 from aenum import Enum
 from .. import statics
 from ..statics import long
 
-
 class Traversal(object):
     def __init__(self, graph, traversal_strategies, bytecode):
         self.graph = graph
@@ -315,6 +315,20 @@ class Bytecode(object):
         else:
             return False
 
+    def __copy__(self):
+        bb = Bytecode()
+        bb.source_instructions = self.source_instructions
+        bb.step_instructions = self.step_instructions
+        bb.bindings = self.bindings
+        return bb
+
+    def __deepcopy__(self, memo={}):
+        bb = Bytecode()
+        bb.source_instructions = copy.deepcopy(self.source_instructions, memo)
+        bb.step_instructions = copy.deepcopy(self.step_instructions, memo)
+        bb.bindings = copy.deepcopy(self.bindings, memo)
+        return bb
+
     def __convertArgument(self,arg):
         if isinstance(arg, Traversal):
             self.bindings.update(arg.bytecode.bindings)
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 c348d16..cac107d 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
@@ -18,6 +18,7 @@
 #
 
 import sys
+import copy
 from .traversal import Traversal
 from .traversal import TraversalStrategies
 from .strategies import VertexProgramStrategy
@@ -132,7 +133,7 @@ class GraphTraversal(Traversal):
         return self.values(key)
 
     def clone(self):
-        return GraphTraversal(self.graph, self.traversal_strategies, self.bytecode)
+        return GraphTraversal(self.graph, self.traversal_strategies, copy.deepcopy(self.bytecode))
 
     def V(self, *args):
         self.bytecode.add_step("V", *args)
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 fb99228..b942409 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -17,11 +17,11 @@
 # under the License.
 #
 
+import copy
 from aenum import Enum
 from .. import statics
 from ..statics import long
 
-
 class Traversal(object):
     def __init__(self, graph, traversal_strategies, bytecode):
         self.graph = graph
@@ -479,6 +479,20 @@ class Bytecode(object):
         else:
             return False
 
+    def __copy__(self):
+        bb = Bytecode()
+        bb.source_instructions = self.source_instructions
+        bb.step_instructions = self.step_instructions
+        bb.bindings = self.bindings
+        return bb
+
+    def __deepcopy__(self, memo={}):
+        bb = Bytecode()
+        bb.source_instructions = copy.deepcopy(self.source_instructions, memo)
+        bb.step_instructions = copy.deepcopy(self.step_instructions, memo)
+        bb.bindings = copy.deepcopy(self.bindings, memo)
+        return bb
+
     def __convertArgument(self,arg):
         if isinstance(arg, Traversal):
             self.bindings.update(arg.bytecode.bindings)
diff --git a/gremlin-python/src/main/jython/tests/process/test_traversal.py b/gremlin-python/src/main/jython/tests/process/test_traversal.py
index 8160dc9..1e907f5 100644
--- a/gremlin-python/src/main/jython/tests/process/test_traversal.py
+++ b/gremlin-python/src/main/jython/tests/process/test_traversal.py
@@ -82,3 +82,22 @@ class TestTraversal(object):
         assert 0 == len(bytecode.bindings.keys())
         assert 0 == len(bytecode.source_instructions)
         assert 0 == len(bytecode.step_instructions)
+
+    def test_clone_traversal(self):
+        g = Graph().traversal()
+        original = g.V().out("created")
+        clone = original.clone().out("knows")
+        cloneClone = clone.clone().out("created")
+
+        assert 2 == len(original.bytecode.step_instructions)
+        assert 3 == len(clone.bytecode.step_instructions)
+        assert 4 == len(cloneClone.bytecode.step_instructions)
+
+        original.has("person", "name", "marko")
+        clone.V().out()
+
+        assert 3 == len(original.bytecode.step_instructions)
+        assert 5 == len(clone.bytecode.step_instructions)
+        assert 4 == len(cloneClone.bytecode.step_instructions)
+
+