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/10/12 20:53:37 UTC

[10/10] tinkerpop git commit: merged the Gremlin Python work from @aholmberg. Fixed up the pom.xml and setup.cfg to include mock. Fixed up init-code-blocks.awk to account for the new GraphSONWriter/Reader model. Fixed a bug in ConnectiveStrategy around c

merged the Gremlin Python work from @aholmberg. Fixed up the pom.xml and setup.cfg to include mock. Fixed up init-code-blocks.awk to account for the new GraphSONWriter/Reader model. Fixed a bug in ConnectiveStrategy around choose() and HasNextStep -- added test cases to confirm proper behavior. Updated CHANGELOG.


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

Branch: refs/heads/master
Commit: e70a509a3bdcc69f4bbac3ed277b0c0d3a8d2854
Parents: c5b0883
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Oct 12 14:53:22 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Oct 12 14:53:22 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  4 +++-
 docs/preprocessor/awk/init-code-blocks.awk      |  4 ++--
 docs/src/reference/gremlin-variants.asciidoc    |  4 ++--
 .../process/traversal/step/map/HasNextStep.java |  8 +++----
 .../strategy/decoration/ConnectiveStrategy.java |  5 ++++-
 .../step/branch/GroovyChooseTest.groovy         |  5 +++++
 gremlin-python/pom.xml                          |  1 +
 .../gremlin_python/structure/io/graphson.py     | 22 ++++++++++----------
 gremlin-python/src/main/jython/setup.py         |  3 ++-
 .../driver/test_driver_remote_connection.py     |  6 +++---
 .../jython/tests/structure/io/test_graphson.py  |  6 +++---
 .../traversal/step/branch/ChooseTest.java       | 22 +++++++++++++++++++-
 12 files changed, 60 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 3741e11..714abc5 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,7 +26,9 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* Increased performance of `CredentialGraph` authentication
+* Restructured Gremlin-Python's GraphSON I/O package to make it easier for users to register serializers/deserializers. (*breaking*)
+* Fixed a bug in `ConnectiveStrategy` where infix and/or was not correctly reasoning on `choose()` `HasNextStep` injections.
+* Increased performance of `CredentialGraph` authentication.
 * Removed Java 8 stream usage from `TraversalHelper` for performance reasons.
 * Fixed a bug in `RepeatStep` where `emit().as('x')` wasn't adding the step labels to the emit-traverser.
 * Added `GraphComputing.atMaster(boolean)` to allow steps to know whether they are executing at master or distributed at workers.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/docs/preprocessor/awk/init-code-blocks.awk
----------------------------------------------------------------------
diff --git a/docs/preprocessor/awk/init-code-blocks.awk b/docs/preprocessor/awk/init-code-blocks.awk
index f9b020a..381c231 100644
--- a/docs/preprocessor/awk/init-code-blocks.awk
+++ b/docs/preprocessor/awk/init-code-blocks.awk
@@ -80,11 +80,11 @@ BEGIN {
     print "  jython.getContext().getBindings(GLOBAL_SCOPE).put('j', jython.eval(t.replace('.toList()','')))"
     print "  if(jython.eval('isinstance(j, Traversal)')) {"
     print "    mapper = GraphSONMapper.build().version(GraphSONVersion.V2_0).create().createMapper()"
-    print "    bytecode = mapper.readValue(jython.eval('GraphSONWriter.writeObject(j)').toString(), Bytecode.class)"
+    print "    bytecode = mapper.readValue(jython.eval('GraphSONWriter().writeObject(j)').toString(), Bytecode.class)"
     print "    language = BytecodeHelper.getLambdaLanguage(bytecode).orElse('gremlin-groovy')"
     print "    result = language.equals('gremlin-groovy') ? groovy.eval(GroovyTranslator.of(\"g\").translate(bytecode) + '.toList()').toString() : jython.eval(JythonTranslator.of(\"h\").translate(bytecode) + '.toList()').toString()"
     print "    jython.getContext().getBindings(GLOBAL_SCOPE).put('json', mapper.writeValueAsString(result))"
-    print "    return jython.eval('GraphSONReader.readObject(json)').toString()"
+    print "    return jython.eval('GraphSONReader().readObject(json)').toString()"
     print "  } else {"
     print "    j = jython.getContext().getBindings(GLOBAL_SCOPE).get('j')"
     print "    return null == j ? 'null' : j.toString()"

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/docs/src/reference/gremlin-variants.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index 0716ff1..4b65ab8 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -229,7 +229,7 @@ Traversal Strategies
 ~~~~~~~~~~~~~~~~~~~~
 
 In order to add and remove <<traversalstrategy,traversal strategies>> from a traversal source, Gremlin-Python has a
-`TraversalStrategy` class along with numerous subclasses that mirror the standard, distributed strategies.
+`TraversalStrategy` class along with a collection of subclasses that mirror the standard Gremlin-Java strategies.
 
 [gremlin-python,modern]
 ----
@@ -244,7 +244,7 @@ g.V().name.toList()
 g.V().outE().valueMap(True).toList()
 ----
 
-NOTE: Many of the `TraversalStrategy` classes in Gremlin-Python are proxies to the respective strategy on the
+NOTE: Many of the `TraversalStrategy` classes in Gremlin-Python are proxies to the respective strategy on
 Apache TinkerPop's JVM-based Gremlin traversal machine. As such, their `apply(Traversal)` method does nothing. However,
 the strategy is encoded in the Gremlin-Python bytecode and transmitted to the Gremlin traversal machine for
 re-construction machine-side.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/HasNextStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/HasNextStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/HasNextStep.java
index b1b6c6e..3f1350c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/HasNextStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/HasNextStep.java
@@ -36,10 +36,8 @@ public final class HasNextStep<S> extends AbstractStep<S, Boolean> {
 
     @Override
     protected Traverser.Admin<Boolean> processNextStart() throws NoSuchElementException {
-        if (this.starts.hasNext()) {
-            final Traverser.Admin<S> s = this.starts.next();
-            return s.split(Boolean.TRUE, this);
-        } else
-            return this.getTraversal().getTraverserGenerator().generate(Boolean.FALSE, (Step) this, 1l);
+        return this.starts.hasNext() ?
+                this.starts.next().split(Boolean.TRUE, this) :
+                this.getTraversal().getTraverserGenerator().generate(Boolean.FALSE, (Step) this, 1L);
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
index 754fb03..eb85c7b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.ConnectiveStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.HasNextStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ProfileSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
@@ -63,7 +64,9 @@ public final class ConnectiveStrategy extends AbstractTraversalStrategy<Traversa
     }
 
     private static boolean legalCurrentStep(final Step<?, ?> step) {
-        return !(step instanceof EmptyStep || step instanceof ProfileSideEffectStep || step instanceof ComputerAwareStep.EndStep || (step instanceof StartStep && !StartStep.isVariableStartStep(step)) || GraphStep.isStartStep(step));
+        return !(step instanceof EmptyStep || step instanceof ProfileSideEffectStep || step instanceof HasNextStep ||
+                step instanceof ComputerAwareStep.EndStep || (step instanceof StartStep && !StartStep.isVariableStartStep(step)) ||
+                GraphStep.isStartStep(step));
     }
 
     private static void processConnectiveMarker(final Traversal.Admin<?, ?> traversal) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy
index 509340c..b92ab9b 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy
@@ -38,5 +38,10 @@ public abstract class GroovyChooseTest {
         public Traversal<Vertex, String> get_g_V_chooseXlabel_eqXpersonX__outXknowsX__inXcreatedXX_name() {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V.choose({it.label() == 'person'}, out('knows'), __.in('created')).name")
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_chooseXhasLabelXpersonX_and_outXcreatedX__outXknowsX__identityX_name() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.choose(hasLabel('person').and().out('created'), out('knows'), identity()).name")
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/gremlin-python/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml
index 627b249..ac37cd6 100644
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@ -313,6 +313,7 @@
                                     <libraries>
                                         <param>aenum==1.4.5</param>
                                         <param>tornado==4.4.1</param>
+                                        <param>six==1.10.0</param>
                                     </libraries>
                                 </configuration>
                             </execution>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/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 45aec9d..002e401 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
@@ -41,7 +41,7 @@ class GraphSONTypeType(type):
         return cls
 
 
-class _GraphSONIO(object):
+class GraphSONUtil(object):
     TYPE_KEY = "@type"
     VALUE_KEY = "@value"
 
@@ -104,7 +104,7 @@ class GraphSONReader(object):
         """
         if isinstance(obj, dict):
             try:
-                return self.deserializers[obj[_GraphSONIO.TYPE_KEY]].objectify(obj[_GraphSONIO.VALUE_KEY], self)
+                return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
             except KeyError:
                 pass
             # list and map are treated as normal json objs (could be isolated deserializers)
@@ -155,7 +155,7 @@ class _BytecodeSerializer(_GraphSONTypeIO):
             out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
         if bytecode.step_instructions:
             out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
-        return _GraphSONIO.typedValue("Bytecode", out)
+        return GraphSONUtil.typedValue("Bytecode", out)
 
 
 class TraversalSerializer(_BytecodeSerializer):
@@ -171,7 +171,7 @@ class TraversalStrategySerializer(_GraphSONTypeIO):
 
     @classmethod
     def dictify(cls, strategy, writer):
-        return _GraphSONIO.typedValue(strategy.strategy_name, writer.toDict(strategy.configuration))
+        return GraphSONUtil.typedValue(strategy.strategy_name, writer.toDict(strategy.configuration))
 
 
 class TraverserIO(_GraphSONTypeIO):
@@ -180,7 +180,7 @@ class TraverserIO(_GraphSONTypeIO):
 
     @classmethod
     def dictify(cls, traverser, writer):
-        return _GraphSONIO.typedValue("Traverser", {"value": writer.toDict(traverser.object),
+        return GraphSONUtil.typedValue("Traverser", {"value": writer.toDict(traverser.object),
                                                      "bulk": writer.toDict(traverser.bulk)})
 
     @classmethod
@@ -194,8 +194,8 @@ class EnumSerializer(_GraphSONTypeIO):
 
     @classmethod
     def dictify(cls, enum, _):
-        return _GraphSONIO.typedValue(cls.unmangleKeyword(type(enum).__name__),
-                                      cls.unmangleKeyword(str(enum.name)))
+        return GraphSONUtil.typedValue(cls.unmangleKeyword(type(enum).__name__),
+                                       cls.unmangleKeyword(str(enum.name)))
 
 
 class PSerializer(_GraphSONTypeIO):
@@ -206,7 +206,7 @@ class PSerializer(_GraphSONTypeIO):
         out = {"predicate": p.operator,
                "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
                         writer.toDict(p.value)}
-        return _GraphSONIO.typedValue("P", out)
+        return GraphSONUtil.typedValue("P", out)
 
 
 class BindingSerializer(_GraphSONTypeIO):
@@ -216,7 +216,7 @@ class BindingSerializer(_GraphSONTypeIO):
     def dictify(cls, binding, writer):
         out = {"key": binding.key,
                "value": writer.toDict(binding.value)}
-        return _GraphSONIO.typedValue("Binding", out)
+        return GraphSONUtil.typedValue("Binding", out)
 
 
 class LambdaSerializer(_GraphSONTypeIO):
@@ -236,7 +236,7 @@ class LambdaSerializer(_GraphSONTypeIO):
             out["arguments"] = six.get_function_code(eval(out["script"])).co_argcount
         else:
             out["arguments"] = -1
-        return _GraphSONIO.typedValue("Lambda", out)
+        return GraphSONUtil.typedValue("Lambda", out)
 
 
 class TypeSerializer(_GraphSONTypeIO):
@@ -253,7 +253,7 @@ class _NumberIO(_GraphSONTypeIO):
     def dictify(cls, n, writer):
         if isinstance(n, bool):  # because isinstance(False, int) and isinstance(True, int)
             return n
-        return _GraphSONIO.typedValue(cls.graphson_base_type, n)
+        return GraphSONUtil.typedValue(cls.graphson_base_type, n)
 
     @classmethod
     def objectify(cls, v, _):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/gremlin-python/src/main/jython/setup.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/setup.py b/gremlin-python/src/main/jython/setup.py
index 08cfe37..57374a7 100644
--- a/gremlin-python/src/main/jython/setup.py
+++ b/gremlin-python/src/main/jython/setup.py
@@ -57,7 +57,8 @@ setup(
         'pytest-runner',
     ],
     tests_require=[
-        'pytest'
+        'pytest',
+        'mock'
     ],
     install_requires=[
         'aenum==1.4.5',

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/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 f65255b..80cf0c5 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
@@ -21,6 +21,7 @@ __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
 
 import unittest
 from unittest import TestCase
+from gremlin_python.structure.io.graphson import GraphSONWriter
 
 import pytest
 
@@ -78,14 +79,14 @@ class TestDriverRemoteConnection(TestCase):
         #
         g = Graph().traversal().withRemote(connection). \
             withStrategies(SubgraphStrategy(vertices=__.hasLabel("person"), edges=__.hasLabel("created")))
-        print GraphSONWriter.writeObject(g.bytecode)
+        print GraphSONWriter().writeObject(g.bytecode)
         assert 4 == g.V().count().next()
         assert 0 == g.E().count().next()
         assert 1 == g.V().label().dedup().count().next()
         assert "person" == g.V().label().dedup().next()
         #
         g = g.withoutStrategies(SubgraphStrategy). \
-            withComputer({"workers": 4, "vertices": __.has("name", "marko"), "edges": __.limit(0)})
+            withComputer(workers=4, vertices=__.has("name", "marko"), edges=__.limit(0))
         assert 1 == g.V().count().next()
         assert 0 == g.E().count().next()
         assert "person" == g.V().label().next()
@@ -150,7 +151,6 @@ class TestDriverRemoteConnection(TestCase):
             pass
         connection.close()
 
-
     def test_side_effect_close(self):
         connection = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
         g = Graph().traversal().withRemote(connection)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/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 a192cd2..f0e8130 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
@@ -29,7 +29,7 @@ import six
 from gremlin_python.statics import *
 from gremlin_python.structure.graph import Vertex
 from gremlin_python.structure.graph import Path
-from gremlin_python.structure.io.graphson import GraphSONWriter, GraphSONReader, _GraphSONIO
+from gremlin_python.structure.io.graphson import GraphSONWriter, GraphSONReader, GraphSONUtil
 import gremlin_python.structure.io.graphson
 from gremlin_python.process.traversal import P
 from gremlin_python.process.strategies import SubgraphStrategy
@@ -108,7 +108,7 @@ class TestGraphSONReader(TestCase):
         assert type_string not in gremlin_python.structure.io.graphson._deserializers
 
         x = X()
-        o = reader.toObject({_GraphSONIO.TYPE_KEY: type_string, _GraphSONIO.VALUE_KEY: x})
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
         serdes.objectify.assert_called_once_with(x, reader)
         assert o is serdes.objectify()
 
@@ -119,7 +119,7 @@ class TestGraphSONReader(TestCase):
         assert gremlin_python.structure.io.graphson._deserializers[type_string] is not reader.deserializers[type_string]
 
         value = 3
-        o = reader.toObject({_GraphSONIO.TYPE_KEY: type_string, _GraphSONIO.VALUE_KEY: value})
+        o = reader.toObject({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
         serdes.objectify.assert_called_once_with(value, reader)
         assert o is serdes.objectify()
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e70a509a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java
index 26bd466..bf050e4 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java
@@ -32,7 +32,12 @@ import java.util.HashMap;
 import java.util.Map;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasLabel;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.identity;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.valueMap;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
@@ -47,6 +52,8 @@ public abstract class ChooseTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, String> get_g_V_chooseXlabel_eqXpersonX__outXknowsX__inXcreatedXX_name();
 
+    public abstract Traversal<Vertex, String> get_g_V_chooseXhasLabelXpersonX_and_outXcreatedX__outXknowsX__identityX_name();
+
 
     @Test
     @LoadGraphWith(MODERN)
@@ -74,6 +81,14 @@ public abstract class ChooseTest extends AbstractGremlinProcessTest {
         checkResults(Arrays.asList("josh", "vadas", "josh", "josh", "marko", "peter"), traversal);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_chooseXhasLabelXpersonX_and_outXcreatedX__outXknowsX__identityX_name() {
+        final Traversal<Vertex, String> traversal = get_g_V_chooseXhasLabelXpersonX_and_outXcreatedX__outXknowsX__identityX_name();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList("lop", "ripple", "josh", "vadas", "vadas"), traversal);
+    }
+
     public static class Traversals extends ChooseTest {
 
         @Override
@@ -87,5 +102,10 @@ public abstract class ChooseTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, String> get_g_V_chooseXlabel_eqXpersonX__outXknowsX__inXcreatedXX_name() {
             return g.V().choose(v -> v.label().equals("person"), out("knows"), in("created")).values("name");
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_chooseXhasLabelXpersonX_and_outXcreatedX__outXknowsX__identityX_name() {
+            return g.V().choose(hasLabel("person").and().out("created"), out("knows"), identity()).values("name");
+        }
     }
 }
\ No newline at end of file