TINKERPOP-1857 Improved handling of empty graph in python glv tests

Caches were hardcoded to the modern graph. For empty graph this caused hassles 
because the cache couldn't be initialized until after the graph initializer 
step was executed. Still a bit messy due to cut/paste issues. Need to clean 
that up at a later point.


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

Branch: refs/heads/TINKERPOP-1857
Commit: a1d040329e1da734f1af46513e36fd941f3e15b0
Parents: 1425f29
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Dec 28 11:18:38 2017 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Feb 14 15:34:09 2018 -0500

----------------------------------------------------------------------
 .../src/main/jython/radish/feature_steps.py     | 78 +++++++++++++++-----
 .../src/main/jython/radish/terrain.py           |  7 +-
 2 files changed, 63 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a1d04032/gremlin-python/src/main/jython/radish/feature_steps.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py 
b/gremlin-python/src/main/jython/radish/feature_steps.py
index 3de641e..e247b25 100644
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ b/gremlin-python/src/main/jython/radish/feature_steps.py
@@ -36,6 +36,11 @@ regex_or = re.compile(r"([(.,\s])or\(")
 regex_true = re.compile(r"(true)")
 regex_false = re.compile(r"(false)")
 
+outV = __.outV
+label = __.label
+inV = __.inV
+project = __.project
+tail = __.tail
 
 ignores = [
     "g.V(v1Id).out().inject(v2).values(\"name\")"  # bug in attachment won't 
connect v2
@@ -44,6 +49,7 @@ ignores = [
 
 @given("the {graph_name:w} graph")
 def choose_graph(step, graph_name):
+    step.context.graph_name = graph_name
     step.context.g = 
Graph().traversal().withRemote(step.context.remote_conn[graph_name])
 
 
@@ -54,7 +60,12 @@ def initialize_graph(step):
     # just be sure that the traversal returns something to prove that it 
worked to some degree. probably
     # is overkill to try to assert the complete success of this init 
operation. presumably the test
     # suite would fail elsewhere if this didn't work which would help identify 
a problem.
-    assert len(traversal.toList()) > 0
+    result = traversal.toList()
+    assert len(result) > 0
+
+    # add the first result - if a map - to the bindings. this is useful for 
cases when parameters for
+    # the test traversal need to come from the original graph initializer 
(i.e. a new graph is created
+    # and you need the id of a vertex from that graph)
 
 
 @given("an unsupported test")
@@ -127,37 +138,38 @@ def nothing_happening(step):
 
 
 def _convert(val, ctx):
-    if isinstance(val, dict):                                         # 
convert dictionary keys/values
+    graph_name = ctx.graph_name
+    if isinstance(val, dict):                                           # 
convert dictionary keys/values
         n = {}
         for key, value in val.items():
             n[_convert(key, ctx)] = _convert(value, ctx)
         return n
-    elif isinstance(val, unicode):                                    # 
convert annoying python 2.x unicode nonsense
+    elif isinstance(val, unicode):                                      # 
convert annoying python 2.x unicode nonsense
         return _convert(val.encode('utf-8'), ctx)
-    elif isinstance(val, str) and re.match("^l\[.*\]$", val):         # parse 
list
+    elif isinstance(val, str) and re.match("^l\[.*\]$", val):           # 
parse list
         return list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
-    elif isinstance(val, str) and re.match("^s\[.*\]$", val):         # parse 
set
+    elif isinstance(val, str) and re.match("^s\[.*\]$", val):           # 
parse set
         return set(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
     elif isinstance(val, str) and re.match("^d\[.*\]\.[ilfdm]$", val):  # 
parse numeric
         return float(val[2:-3]) if val[2:-3].__contains__(".") else 
long(val[2:-3])
-    elif isinstance(val, str) and re.match("^v\[.*\]\.id$", val):     # parse 
vertex id
-        return ctx.lookup_v["modern"][val[2:-4]].id
-    elif isinstance(val, str) and re.match("^v\[.*\]\.sid$", val):    # parse 
vertex id as string
-        return ctx.lookup_v["modern"][val[2:-5]].id
-    elif isinstance(val, str) and re.match("^v\[.*\]$", val):         # parse 
vertex
-        return ctx.lookup_v["modern"][val[2:-1]]
-    elif isinstance(val, str) and re.match("^e\[.*\]\.id$", val):     # parse 
edge id
-        return ctx.lookup_e["modern"][val[2:-4]].id
-    elif isinstance(val, str) and re.match("^e\[.*\]\.sid$", val):    # parse 
edge id as string
-        return ctx.lookup_e["modern"][val[2:-5]].id
-    elif isinstance(val, str) and re.match("^e\[.*\]$", val):         # parse 
edge
-        return ctx.lookup_e["modern"][val[2:-1]]
-    elif isinstance(val, str) and re.match("^m\[.*\]$", val):         # parse 
json as a map
+    elif isinstance(val, str) and re.match("^v\[.*\]\.id$", val):       # 
parse vertex id
+        return __find_cached_element(ctx, graph_name, val[2:-4], "v").id
+    elif isinstance(val, str) and re.match("^v\[.*\]\.sid$", val):      # 
parse vertex id as string
+        return __find_cached_element(ctx, graph_name, val[2:-5], "v").id
+    elif isinstance(val, str) and re.match("^v\[.*\]$", val):           # 
parse vertex
+        return __find_cached_element(ctx, graph_name, val[2:-1], "v")
+    elif isinstance(val, str) and re.match("^e\[.*\]\.id$", val):       # 
parse edge id
+        return __find_cached_element(ctx, graph_name, val[2:-4], "e").id
+    elif isinstance(val, str) and re.match("^e\[.*\]\.sid$", val):      # 
parse edge id as string
+        return __find_cached_element(ctx, graph_name, val[2:-5], "e").id
+    elif isinstance(val, str) and re.match("^e\[.*\]$", val):           # 
parse edge
+        return __find_cached_element(ctx, graph_name, val[2:-1], "e")
+    elif isinstance(val, str) and re.match("^m\[.*\]$", val):           # 
parse json as a map
         return _convert(json.loads(val[2:-1].replace('\\"', '"')), ctx)
-    elif isinstance(val, str) and re.match("^p\[.*\]$", val):         # parse 
path
+    elif isinstance(val, str) and re.match("^p\[.*\]$", val):           # 
parse path
         path_objects = list(map((lambda x: _convert(x, ctx)), 
val[2:-1].split(",")))
         return Path([set([])], path_objects)
-    elif isinstance(val, str) and re.match("^c\[.*\]$", val):         # parse 
lambda/closure
+    elif isinstance(val, str) and re.match("^c\[.*\]$", val):           # 
parse lambda/closure
         return lambda: (val[2:-1], "gremlin-groovy")
     elif isinstance(val, str) and re.match("^t\[.*\]$", val):         # parse 
instance of T enum
         return T[val[2:-1]]
@@ -165,6 +177,15 @@ def _convert(val, ctx):
         return val
 
 
+def __find_cached_element(ctx, graph_name, identifier, element_type):
+    if graph_name == "empty":
+        cache = __create_lookup_v(ctx.remote_conn["empty"]) if element_type == 
"v" else __create_lookup_e(ctx.remote_conn["empty"])
+    else:
+        cache = ctx.lookup_v[graph_name] if element_type == "v" else 
ctx.lookup_e[graph_name]
+
+    return cache[identifier]
+
+
 def _convert_results(val):
     if isinstance(val, Path):
         # kill out labels as they aren't in the assertion logic
@@ -234,3 +255,20 @@ def _make_traversal(g, traversal_string, params):
     b.update(params)
 
     return eval(_translate(traversal_string), b)
+
+
+def __create_lookup_v(remote):
+    g = Graph().traversal().withRemote(remote)
+
+    # hold a map of name/vertex for use in asserting results
+    return g.V().group().by('name').by(tail()).next()
+
+
+def __create_lookup_e(remote):
+    g = Graph().traversal().withRemote(remote)
+
+    # hold a map of the "name"/edge for use in asserting results - "name" in 
this context is in the form of
+    # outgoingV-label->incomingV
+    return g.E().group(). \
+        by(lambda: ("it.outVertex().value('name') + '-' + it.label() + '->' + 
it.inVertex().value('name')", "gremlin-groovy")). \
+        by(tail()).next()

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a1d04032/gremlin-python/src/main/jython/radish/terrain.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/radish/terrain.py 
b/gremlin-python/src/main/jython/radish/terrain.py
index 0c749eb..9aed647 100644
--- a/gremlin-python/src/main/jython/radish/terrain.py
+++ b/gremlin-python/src/main/jython/radish/terrain.py
@@ -17,7 +17,6 @@ specific language governing permissions and limitations
 under the License.
 '''
 
-import re
 from gremlin_python.structure.graph import Graph
 from gremlin_python.process.graph_traversal import __
 from gremlin_python.driver.driver_remote_connection import 
DriverRemoteConnection
@@ -58,6 +57,10 @@ def prepare_static_traversal_source(features, marker):
                 scenario.context.lookup_v[graph_name] = 
cache[graph_name]["lookup_v"]
                 scenario.context.lookup_e[graph_name] = 
cache[graph_name]["lookup_e"]
 
+            # setup the "empty" lookups as needed
+            scenario.context.lookup_v["empty"] = {}
+            scenario.context.lookup_e["empty"] = {}
+
 
 @before.each_scenario
 def prepare_traversal_source(scenario):
@@ -97,4 +100,4 @@ def __create_lookup_e(remote):
     # outgoingV-label->incomingV
     return g.E().group(). \
         by(lambda: ("it.outVertex().value('name') + '-' + it.label() + '->' + 
it.inVertex().value('name')", "gremlin-groovy")). \
-        by(tail()).next()
+        by(tail()).next()
\ No newline at end of file

Reply via email to