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/09/13 15:04:05 UTC

[1/3] tinkerpop git commit: added Path object and GraphSON desrialization for g:Path in Gremlin-Python. Added test cases to ensure both Path semantics and Path deserialization.

Repository: tinkerpop
Updated Branches:
  refs/heads/master a879702d2 -> d659e15be


added Path object and GraphSON desrialization for g:Path in Gremlin-Python. Added test cases to ensure both Path semantics and Path deserialization.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/144a7cdd
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/144a7cdd
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/144a7cdd

Branch: refs/heads/master
Commit: 144a7cdde6fa04c8a2897445cbea005d8a692869
Parents: 0e4e8a1
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Sep 12 16:13:27 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Sep 12 16:13:27 2016 -0600

----------------------------------------------------------------------
 .../jython/gremlin_python/structure/graph.py    | 32 ++++++++++++++++++++
 .../gremlin_python/structure/io/graphson.py     | 16 +++++++++-
 .../jython/tests/structure/io/test_graphson.py  | 13 ++++++++
 .../main/jython/tests/structure/test_graph.py   | 27 ++++++++++++++++-
 4 files changed, 86 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/144a7cdd/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 22403b6..b60dc65 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
@@ -88,3 +88,35 @@ class Property(object):
 
     def __hash__(self):
         return hash(self.key) + hash(self.value)
+
+
+class Path(object):
+    def __init__(self, labels, objects):
+        self.labels = labels
+        self.objects = objects
+
+    def __repr__(self):
+        return str(self.objects)
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.objects == other.objects and self.labels == other.labels
+
+    def __hash__(self):
+        return hash(str(self.objects)) + hash(str(self.labels))
+
+    def __getitem__(self, key):
+        if isinstance(key, str):
+            objects = []
+            for i, labels in enumerate(self.labels):
+                if key in labels:
+                    objects.append(self.objects[i])
+            if 0 == len(objects):
+                raise Error("The step with label " + key + " does not exist")
+            return objects if len(objects) > 1 else objects[0]
+        elif isinstance(key, int):
+            return self.objects[key]
+        else:
+            raise Error("The step with label " + key + " does not exist")
+
+    def __len__(self):
+        return len(self.objects)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/144a7cdd/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
index dcc6976..fd13ae9 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphson.py
@@ -37,6 +37,7 @@ from gremlin_python.structure.graph import Edge
 from gremlin_python.structure.graph import Property
 from gremlin_python.structure.graph import Vertex
 from gremlin_python.structure.graph import VertexProperty
+from gremlin_python.structure.graph import Path
 
 
 class GraphSONWriter(object):
@@ -247,6 +248,18 @@ class PropertyDeserializer(GraphSONDeserializer):
         return Property(value["key"], GraphSONReader._objectify(value["value"]))
 
 
+class PathDeserializer(GraphSONDeserializer):
+    def _objectify(self, dict):
+        value = dict[_SymbolHelper._VALUE]
+        labels = []
+        objects = []
+        for label in value["labels"]:
+            labels.append(set(label))
+        for object in value["objects"]:
+            objects.append(GraphSONReader._objectify(object))
+        return Path(labels, objects)
+
+
 class _SymbolHelper(object):
     symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
                  "or_": "or", "is_": "is", "not_": "not", "from_": "from",
@@ -286,5 +299,6 @@ deserializers = {
     "g:Vertex": VertexDeserializer(),
     "g:Edge": EdgeDeserializer(),
     "g:VertexProperty": VertexPropertyDeserializer(),
-    "g:Property": PropertyDeserializer()
+    "g:Property": PropertyDeserializer(),
+    "g:Path": PathDeserializer()
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/144a7cdd/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py
index 3153fd6..cae1a53 100644
--- a/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py
+++ b/gremlin-python/src/main/jython/tests/structure/io/test_graphson.py
@@ -24,6 +24,7 @@ import unittest
 from unittest import TestCase
 
 from gremlin_python.structure.graph import Vertex
+from gremlin_python.structure.graph import Path
 from gremlin_python.structure.io.graphson import GraphSONReader
 from gremlin_python.structure.io.graphson import GraphSONWriter
 
@@ -67,6 +68,18 @@ class TestGraphSONReader(TestCase):
         assert isinstance(vertex.id, int)
         assert vertex == Vertex(1)
 
+    def test_path(self):
+        path = GraphSONReader.readObject(
+            """{"@type":"g:Path","@value":{"labels":[["a"],["b","c"],[]],"objects":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":3},"label":"software","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":4},"value":"lop","label":"name"}}],"lang":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":5},"value":"java","label":"lang"}}]}}},"lop"]}}"""
+        )
+        assert isinstance(path, Path)
+        assert "[v[1], v[3], u'lop']" == str(path)
+        assert Vertex(1) == path[0]
+        assert Vertex(1) == path["a"]
+        assert "lop" == path[2]
+        assert 3 == len(path)
+
+
 class TestGraphSONWriter(TestCase):
     def test_numbers(self):
         assert """{"@type":"g:Int32","@value":1}""" == GraphSONWriter.writeObject(1)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/144a7cdd/gremlin-python/src/main/jython/tests/structure/test_graph.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/structure/test_graph.py b/gremlin-python/src/main/jython/tests/structure/test_graph.py
index 6025802..bb0d284 100644
--- a/gremlin-python/src/main/jython/tests/structure/test_graph.py
+++ b/gremlin-python/src/main/jython/tests/structure/test_graph.py
@@ -26,10 +26,11 @@ from gremlin_python.structure.graph import Edge
 from gremlin_python.structure.graph import Property
 from gremlin_python.structure.graph import Vertex
 from gremlin_python.structure.graph import VertexProperty
+from gremlin_python.structure.graph import Path
 
 
 class TestGraph(TestCase):
-    def testGraphObjects(self):
+    def test_graph_objects(self):
         vertex = Vertex(1)
         assert "v[1]" == str(vertex)
         assert "vertex" == vertex.label
@@ -69,6 +70,30 @@ class TestGraph(TestCase):
                     assert i == j
                     assert i.__hash__() == hash(i)
 
+    def test_path(self):
+        path = Path([set(["a", "b"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
+        assert "[1, v[1], 'hello']" == str(path)
+        assert 1 == path["a"]
+        assert Vertex(1) == path["c"]
+        assert [1, Vertex(1)] == path["b"]
+        assert path[0] == 1
+        assert path[1] == Vertex(1)
+        assert path[2] == "hello"
+        assert 3 == len(path)
+        try:
+            temp = path[3]
+            raise Exception("Accessing beyond the list index should throw an error")
+        except IndexError:
+            pass
+        #
+        assert path == path
+        assert hash(path) == hash(path)
+        path2 = Path([set(["a", "b"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
+        assert path == path2
+        assert hash(path) == hash(path2)
+        assert path != Path([set(["a"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])
+        assert path != Path([set(["a", "b"]), set(["c", "b"]), set([])], [3, Vertex(1), "hello"])
+
 
 if __name__ == '__main__':
     unittest.main()


[3/3] tinkerpop git commit: Merge branch 'TINKERPOP-1440'

Posted by ok...@apache.org.
Merge branch 'TINKERPOP-1440'


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/d659e15b
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/d659e15b
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/d659e15b

Branch: refs/heads/master
Commit: d659e15beb7366bf8ca555e0e4e4ab6f88b9dbeb
Parents: a879702 9050ad1
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Sep 13 09:03:50 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Sep 13 09:03:50 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 docs/src/reference/gremlin-variants.asciidoc    | 12 +++---
 docs/src/reference/intro.asciidoc               | 14 +++----
 .../jython/gremlin_python/structure/graph.py    | 32 ++++++++++++++
 .../gremlin_python/structure/io/graphson.py     | 16 ++++++-
 .../jython/tests/structure/io/test_graphson.py  | 13 ++++++
 .../main/jython/tests/structure/test_graph.py   | 44 +++++++++++++++++++-
 7 files changed, 117 insertions(+), 15 deletions(-)
----------------------------------------------------------------------



[2/3] tinkerpop git commit: added more test cases and better error handling for Gremlin-Python test. Also went through the Gremlin-Python docs and tweaked a little here and there. Path is lookin' good.

Posted by ok...@apache.org.
added more test cases and better error handling for Gremlin-Python test. Also went through the Gremlin-Python docs and tweaked a little here and there. Path is lookin' good.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9050ad1b
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9050ad1b
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9050ad1b

Branch: refs/heads/master
Commit: 9050ad1b1d17ac60d260411720f4e46a716dbe64
Parents: 144a7cd
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Sep 13 09:03:41 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Sep 13 09:03:41 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                               |  1 +
 docs/src/reference/gremlin-variants.asciidoc     | 12 ++++++------
 docs/src/reference/intro.asciidoc                | 14 +++++++-------
 .../jython/gremlin_python/structure/graph.py     |  4 ++--
 .../main/jython/tests/structure/test_graph.py    | 19 ++++++++++++++++++-
 5 files changed, 34 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9050ad1b/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 7035b5e..9998a24 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Added `Path` to Gremlin-Python with respective GraphSON 2.0 deserializer.
 * Added missing `InetAddress` to GraphSON extension module.
 
 [[release-3-2-2]]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9050ad1b/docs/src/reference/gremlin-variants.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index 0673867..bf9df2e 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -118,13 +118,13 @@ $ bin/gremlin-server.sh conf/gremlin-server-modern-py.yaml
 NOTE: The command to use `-i` need only be executed once to gather `gremlin-python` dependencies into Gremlin Servers'
 path. Future starts of Gremlin Server will not require that command.
 
-Within the CPython console, it is possible to evaluate the following.
+Within the CPython console, an empty `Graph` is created and a traversal source is spawned with `RemoteStrategy`.
 
 [source,python]
 >>> graph = Graph()
 >>> g = graph.traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))
 
-When a traversal spawned from the `GraphTraversalSource` above is iterated, the traveral's `Bytecode` is sent over the wire
+When a traversal from the `GraphTraversalSource` is iterated, the traversal'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. Gremlin Server) will typically
@@ -138,7 +138,7 @@ RemoteConnection Submission
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 There are various ways to submit a traversal to a `RemoteConnection`. Just as in Gremlin-Java, there are various
-"action methods" off of `Traversal`.
+"terminal/action methods" off of `Traversal`.
 
 * `Traversal.next()`
 * `Traversal.nextTraverser()`
@@ -183,7 +183,7 @@ These can be used analogously to how they are used in Gremlin-Java.
 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.
+Moreover, by importing the `statics` of Gremlin-Python, the class prefixes can be ommitted.
 
 [source,python]
 >>> statics.load_statics(globals())
@@ -209,7 +209,7 @@ Bindings
 When a traversal bytecode is sent over a `RemoteConnection` (e.g. Gremlin Server), 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 "string" scripts. However, `g.V(x).out('created').name` with bindings of `{x : 1}` and
+from `g.V(4).out('created').name'` as they have different script "string" representations. 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.
 
@@ -219,7 +219,7 @@ g.V(('id',1)).out('created').name.toList()
 g.V(('id',4)).out('created').name.toList()
 ----
 
-NOTE: The Gremlin `withBindings()` traversal source step is not needed. This is only required
+NOTE: The Gremlin `withBindings()` traversal source step is not needed. Typically `withBindings()` is only required
 in statically typed languages where bindings need to have the same typing as the `Traversal` API. However, if desired,
 it is possible to use the `withBindings()`-model as Gremlin-Python's `Bindings.of()` simply returns a 2-tuple of `(str,object)`
 (see <<connecting-via-remotegraph,`Bindings`>>).

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9050ad1b/docs/src/reference/intro.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/intro.asciidoc b/docs/src/reference/intro.asciidoc
index d38e23b..f7a32ce 100644
--- a/docs/src/reference/intro.asciidoc
+++ b/docs/src/reference/intro.asciidoc
@@ -342,17 +342,17 @@ On Gremlin Language Variants
 ----------------------------
 
 Gremlin is written in Java 8. There are various language variants of Gremlin such as Gremlin-Groovy (packaged with
-TinkerPop3), link:https://github.com/mpollmeier/gremlin-scala[Gremlin-Scala], Gremlin-JavaScript, Gremlin-Clojure
-(known as link:https://github.com/clojurewerkz/ogre[Ogre]), etc. It is best to think of Gremlin as a style of graph
-traversing that is not bound to a particular programming language per se. Within a programming language familiar to
-the developer, there is a Gremlin variant that they can use that leverages the idioms of that language. At minimum,
-a programming language providing a Gremlin implementation must support
+TinkerPop3), Gremlin-Python (packaged with TinkerPop3), link:https://github.com/mpollmeier/gremlin-scala[Gremlin-Scala],
+Gremlin-JavaScript, Gremlin-Clojure (known as link:https://github.com/clojurewerkz/ogre[Ogre]), etc.
+It is best to think of Gremlin as a style of graph traversing that is not bound to a particular programming language per se.
+Within a programming language familiar to the developer, there is a Gremlin variant that they can use that leverages
+the idioms of that language. At minimum, a programming language providing a Gremlin implementation must support
 link:http://en.wikipedia.org/wiki/Method_chaining[function chaining] (with
 link:http://en.wikipedia.org/wiki/Anonymous_function[lambdas/anonymous functions] being a "nice to have" if the
-variant wishes to offer arbitrary computations beyond the provided Gremlin steps).
+variants wishes to offer arbitrary computations beyond the provided Gremlin steps).
 
 Throughout the documentation, the examples provided are primarily written in Gremlin-Groovy. The reason for this is
-the <<gremlin-console,Gremlin Console>> whereby an interactive programming environment exists that does not require
+the <<gremlin-console,Gremlin Console>> -- an interactive programming environment exists that does not require
 code compilation. For learning TinkerPop3 and interacting with a live graph system in an ad hoc manner, the Gremlin
 Console is invaluable. However, for developers interested in working with Gremlin-Java, a few Groovy-to-Java patterns
 are presented below.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9050ad1b/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 b60dc65..d77cde1 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/graph.py
@@ -111,12 +111,12 @@ class Path(object):
                 if key in labels:
                     objects.append(self.objects[i])
             if 0 == len(objects):
-                raise Error("The step with label " + key + " does not exist")
+                raise KeyError("The step with label " + key + " does not exist")
             return objects if len(objects) > 1 else objects[0]
         elif isinstance(key, int):
             return self.objects[key]
         else:
-            raise Error("The step with label " + key + " does not exist")
+            raise TypeError("The path access key must be either a string label or integer index")
 
     def __len__(self):
         return len(self.objects)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9050ad1b/gremlin-python/src/main/jython/tests/structure/test_graph.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/structure/test_graph.py b/gremlin-python/src/main/jython/tests/structure/test_graph.py
index bb0d284..72b4b79 100644
--- a/gremlin-python/src/main/jython/tests/structure/test_graph.py
+++ b/gremlin-python/src/main/jython/tests/structure/test_graph.py
@@ -80,12 +80,29 @@ class TestGraph(TestCase):
         assert path[1] == Vertex(1)
         assert path[2] == "hello"
         assert 3 == len(path)
+        assert "hello" in path
+        assert "goodbye" not in path
+        assert Vertex(1) in path
+        assert Vertex(123) not in path
+        #
         try:
             temp = path[3]
-            raise Exception("Accessing beyond the list index should throw an error")
+            raise Exception("Accessing beyond the list index should throw an index error")
         except IndexError:
             pass
         #
+        try:
+            temp = path["zz"]
+            raise Exception("Accessing nothing should throw a key error")
+        except KeyError:
+            pass
+        #
+        try:
+            temp = path[1:2]
+            raise Exception("Accessing using slices should throw a type error")
+        except TypeError:
+            pass
+        #
         assert path == path
         assert hash(path) == hash(path)
         path2 = Path([set(["a", "b"]), set(["c", "b"]), set([])], [1, Vertex(1), "hello"])