added where().by() semantics to Gremlin and fixed a severe bug in 
Gremlin-Python's P object. Optimized TraversalRing for non-existent modulators.


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

Branch: refs/heads/TINKERPOP-1442-master
Commit: 68ecda40486650cb9f209b61570485d3c24eed37
Parents: a2ddf8f
Author: Marko A. Rodriguez <okramma...@gmail.com>
Authored: Wed Sep 14 15:30:34 2016 -0600
Committer: Marko A. Rodriguez <okramma...@gmail.com>
Committed: Thu Sep 15 09:58:53 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   4 +
 .../step/filter/WherePredicateStep.java         |  54 ++++++++--
 .../process/traversal/step/map/PathStep.java    |   2 +-
 .../process/traversal/step/map/ProjectStep.java |   2 +-
 .../process/traversal/step/map/SelectStep.java  |   2 +-
 .../process/traversal/step/map/TreeStep.java    |   2 +-
 .../step/sideEffect/TreeSideEffectStep.java     |   2 +-
 .../process/traversal/util/TraversalRing.java   |   2 +-
 .../traversal/step/filter/WhereStepTest.java    |   6 +-
 .../step/filter/GroovyWhereTest.groovy          |  15 +++
 .../python/TraversalSourceGenerator.groovy      |   8 +-
 .../gremlin/python/jsr223/PythonTranslator.java |   2 +-
 .../jython/gremlin_python/process/traversal.py  |   8 +-
 .../main/jython/tests/process/test_traversal.py |   8 ++
 .../jython/tests/structure/io/test_graphson.py  |   5 +
 .../io/graphson/GraphSONWriterTest.java         |   2 +-
 .../traversal/step/filter/WhereTest.java        | 104 ++++++++++++++++---
 17 files changed, 188 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index cf1cae8..2210ecf 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,10 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Fixed a bug in Gremlin-Python `P` where predicates reversed the order of the 
predicates.
+* Fixed a naming bug in Gremlin-Python where `P._and` and `P._or` should be 
`P.and_` and `P.or_`. (*breaking*)
+* `where()` predicate-based steps now support `by()`-modulation.
+* `TraversalRing` returns an null if it does not contain traversals 
(previously `IdentityTraversal`).
 * Fixed a `JavaTranslator` bug where `Bytecode` instructions were being 
mutated during translation.
 * Added `Path` to Gremlin-Python with respective GraphSON 2.0 deserializer.
 * VertexPrograms can now declare traverser requirements, e.g. to have access 
to the path when used with `.program()`.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
index 898a42a..05637f6 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
@@ -22,19 +22,30 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class WherePredicateStep<S> extends FilterStep<S> implements 
Scoping, PathProcessor {
+public final class WherePredicateStep<S> extends FilterStep<S> implements 
Scoping, PathProcessor, ByModulating, TraversalParent {
 
     protected String startKey;
     protected List<String> selectKeys;
@@ -42,6 +53,8 @@ public final class WherePredicateStep<S> extends 
FilterStep<S> implements Scopin
     protected final Set<String> scopeKeys = new HashSet<>();
     protected Set<String> keepLabels;
 
+    protected TraversalRing<S, ?> traversalRing = new TraversalRing<>();
+
     public WherePredicateStep(final Traversal.Admin traversal, final 
Optional<String> startKey, final P<String> predicate) {
         super(traversal);
         this.startKey = startKey.orElse(null);
@@ -66,7 +79,7 @@ public final class WherePredicateStep<S> extends 
FilterStep<S> implements Scopin
         if (predicate instanceof ConnectiveP)
             ((ConnectiveP<Object>) predicate).getPredicates().forEach(p -> 
this.setPredicateValues(p, traverser, selectKeysIterator));
         else
-            predicate.setValue(this.getScopeValue(Pop.last, 
selectKeysIterator.next(), traverser));
+            predicate.setValue(TraversalUtil.applyNullable((S) 
this.getScopeValue(Pop.last, selectKeysIterator.next(), traverser), 
this.traversalRing.next()));
     }
 
     public Optional<P<?>> getPredicate() {
@@ -84,14 +97,18 @@ public final class WherePredicateStep<S> extends 
FilterStep<S> implements Scopin
 
     @Override
     protected boolean filter(final Traverser.Admin<S> traverser) {
+        final Object value = null == this.startKey ?
+                TraversalUtil.applyNullable(traverser, 
this.traversalRing.next()) :
+                TraversalUtil.applyNullable((S) this.getScopeValue(Pop.last, 
this.startKey, traverser), this.traversalRing.next());
         this.setPredicateValues(this.predicate, traverser, 
this.selectKeys.iterator());
-        return this.predicate.test(null == this.startKey ? traverser.get() : 
this.getScopeValue(Pop.last, this.startKey, traverser));
+        this.traversalRing.reset();
+        return this.predicate.test(value);
     }
 
     @Override
     public String toString() {
         // TODO: revert the predicates to their string form?
-        return StringFactory.stepString(this, this.startKey, this.predicate);
+        return StringFactory.stepString(this, this.startKey, this.predicate, 
this.traversalRing);
     }
 
     @Override
@@ -103,19 +120,33 @@ public final class WherePredicateStep<S> extends 
FilterStep<S> implements Scopin
     public WherePredicateStep<S> clone() {
         final WherePredicateStep<S> clone = (WherePredicateStep<S>) 
super.clone();
         clone.predicate = this.predicate.clone();
+        clone.traversalRing = this.traversalRing.clone();
         return clone;
     }
 
     @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.traversalRing.getTraversals().forEach(this::integrateChild);
+    }
+
+    @Override
     public int hashCode() {
-        return super.hashCode() ^ (null == this.startKey ? "null".hashCode() : 
this.startKey.hashCode()) ^ this.predicate.hashCode();
+        return super.hashCode() ^ this.traversalRing.hashCode() ^ (null == 
this.startKey ? "null".hashCode() : this.startKey.hashCode()) ^ 
this.predicate.hashCode();
     }
 
     @Override
     public Set<TraverserRequirement> getRequirements() {
-        return 
TraversalHelper.getLabels(TraversalHelper.getRootTraversal(this.traversal)).stream().filter(this.scopeKeys::contains).findAny().isPresent()
 ?
-                TYPICAL_GLOBAL_REQUIREMENTS :
-                TYPICAL_LOCAL_REQUIREMENTS;
+        final Set<TraverserRequirement> requirements =
+                
TraversalHelper.getLabels(TraversalHelper.getRootTraversal(this.traversal)).stream().filter(this.scopeKeys::contains).findAny().isPresent()
 ?
+                        TYPICAL_GLOBAL_REQUIREMENTS :
+                        TYPICAL_LOCAL_REQUIREMENTS;
+        return this.getSelfAndChildRequirements(requirements.toArray(new 
TraverserRequirement[requirements.size()]));
+    }
+
+    @Override
+    public List<Traversal.Admin<S, ?>> getLocalChildren() {
+        return (List) this.traversalRing.getTraversals();
     }
 
     @Override
@@ -132,4 +163,9 @@ public final class WherePredicateStep<S> extends 
FilterStep<S> implements Scopin
     public Set<String> getKeepLabels() {
         return this.keepLabels;
     }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> traversal) throws 
UnsupportedOperationException {
+        this.traversalRing.addTraversal(this.integrateChild(traversal));
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
index 6dca028..705cf0c 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
@@ -53,7 +53,7 @@ public final class PathStep<S> extends MapStep<S, Path> 
implements TraversalPare
             path = traverser.path();
         else {
             path = MutablePath.make();
-            traverser.path().forEach((object, labels) -> 
path.extend(TraversalUtil.apply(object, this.traversalRing.next()), labels));
+            traverser.path().forEach((object, labels) -> 
path.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), 
labels));
         }
         this.traversalRing.reset();
         return path;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
index 2e586b7..83e095a 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
@@ -52,7 +52,7 @@ public final class ProjectStep<S, E> extends MapStep<S, 
Map<String, E>> implemen
     protected Map<String, E> map(final Traverser.Admin<S> traverser) {
         final Map<String, E> end = new 
LinkedHashMap<>(this.projectKeys.size(), 1.0f);
         for (final String projectKey : this.projectKeys) {
-            end.put(projectKey, TraversalUtil.apply(traverser, 
this.traversalRing.next()));
+            end.put(projectKey, TraversalUtil.applyNullable(traverser, 
this.traversalRing.next()));
         }
         this.traversalRing.reset();
         return end;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
index 7c54708..77db60f 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
@@ -66,7 +66,7 @@ public final class SelectStep<S, E> extends MapStep<S, 
Map<String, E>> implement
         for (final String selectKey : this.selectKeys) {
             final E end = this.getNullableScopeValue(this.pop, selectKey, 
traverser);
             if (null != end)
-                bindings.put(selectKey, TraversalUtil.apply(end, 
this.traversalRing.next()));
+                bindings.put(selectKey, TraversalUtil.applyNullable(end, 
this.traversalRing.next()));
             else {
                 this.traversalRing.reset();
                 return null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
index 8bdc692..ac1fa07 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
@@ -73,7 +73,7 @@ public final class TreeStep<S> extends ReducingBarrierStep<S, 
Tree> implements T
         Tree depth = topTree;
         final Path path = traverser.path();
         for (int i = 0; i < path.size(); i++) {
-            final Object object = TraversalUtil.apply(path.<Object>get(i), 
this.traversalRing.next());
+            final Object object = 
TraversalUtil.applyNullable(path.<Object>get(i), this.traversalRing.next());
             if (!depth.containsKey(object))
                 depth.put(object, new Tree<>());
             depth = (Tree) depth.get(object);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
index 9996c83..15756d2 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
@@ -59,7 +59,7 @@ public final class TreeSideEffectStep<S> extends 
SideEffectStep<S> implements Si
         Tree depth = root;
         final Path path = traverser.path();
         for (int i = 0; i < path.size(); i++) {
-            final Object object = TraversalUtil.apply(path.<Object>get(i), 
this.traversalRing.next());
+            final Object object = 
TraversalUtil.applyNullable(path.<Object>get(i), this.traversalRing.next());
             if (!depth.containsKey(object))
                 depth.put(object, new Tree<>());
             depth = (Tree) depth.get(object);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
index 841f280..d6d10c0 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalRing.java
@@ -42,7 +42,7 @@ public final class TraversalRing<A, B> implements 
Serializable, Cloneable {
 
     public Traversal.Admin<A, B> next() {
         if (this.traversals.size() == 0) {
-            return this.identityTraversal;    // TODO: return null and 
TraversalUtil.applyNullable()?
+            return null;
         } else {
             this.currentTraversal = (this.currentTraversal + 1) % 
this.traversals.size();
             return this.traversals.get(this.currentTraversal);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStepTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStepTest.java
index cb1795d..7f65f23 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStepTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStepTest.java
@@ -43,7 +43,11 @@ public class WhereStepTest extends StepTest {
                 as("a").out().as("b").where(as("a").out()),
                 as("a").out().as("b").where(as("a").out().as("b")),
                 as("a").out().as("b").where("a", P.neq("b")),
-                as("a").out().as("b").where("a", P.neq("c"))
+                as("a").out().as("b").where("a", P.neq("c")),
+                as("a").out().as("b").where("a", P.neq("b")).by("name"),
+                as("a").out().as("b").where("a", 
P.neq("b")).by("name").by("age"),
+                as("a").out().as("b").where("a", P.neq("b")).by("age"),
+                as("a").out().as("b").where("a", 
P.neq("b").and(P.neq("a"))).by("age")
         );
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
----------------------------------------------------------------------
diff --git 
a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
 
b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
index fc0aca9..a28c3dc 100644
--- 
a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
+++ 
b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
@@ -132,5 +132,20 @@ public abstract class GroovyWhereTest {
             new ScriptTraversal<>(g, "gremlin-groovy", 
"g.V.as('a').out.as('b').where(__.as('b').in.count.is(eq(3)).or.where(__.as('b').out('created').and.as('b').has(label,'person'))).select('a','b')")
         }
 
+        @Override
+        public Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_gtXbXX_byXageX_selectXa_bX_byXnameX()
 {
+            new ScriptTraversal<>(g, "gremlin-groovy", 
"g.V.as('a').out('created').in('created').as('b').where('a', 
gt('b')).by('age').select('a', 'b').by('name')")
+        }
+
+        @Override
+        public Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_whereXa_gtXbX_orXeqXbXXX_byXageX_byXweightX_byXweightX_selectXa_cX_byXnameX()
 {
+            new ScriptTraversal<>(g, "gremlin-groovy", 
"g.V.as('a').outE('created').as('b').inV().as('c').where('a', 
gt('b').or(eq('b'))).by('age').by('weight').by('weight').select('a', 
'c').by('name')")
+        }
+
+        @Override
+        public Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX()
 {
+            new ScriptTraversal<>(g, "gremlin-groovy", 
"g.V().as('a').outE('created').as('b').inV().as('c').in('created').as('d').where('a',
 
lt('b').or(gt('c')).and(neq('d'))).by('age').by('weight').by(__.in('created').values('age').min()).select('a',
 'c', 'd').by('name')")
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
----------------------------------------------------------------------
diff --git 
a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
 
b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
index 79a1a4e..95bfdbf 100644
--- 
a/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
+++ 
b/gremlin-python/src/main/groovy/org/apache/tinkerpop/gremlin/python/TraversalSourceGenerator.groovy
@@ -152,10 +152,10 @@ class Traversal(object):
       return P("${SymbolHelper.toJava(method)}", *args)
 """)
                 };
-        pythonClass.append("""   def _and(self, arg):
-      return P("and", arg, self)
-   def _or(self, arg):
-      return P("or", arg, self)
+        pythonClass.append("""   def and_(self, arg):
+      return P("and", self, arg)
+   def or_(self, arg):
+      return P("or", self, arg)
    def __eq__(self, other):
         return isinstance(other, self.__class__) and self.operator == 
other.operator and self.value == other.value and self.other == other.other
    def __repr__(self):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
----------------------------------------------------------------------
diff --git 
a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
 
b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
index 08295e0..90d29e8 100644
--- 
a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
+++ 
b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
@@ -175,7 +175,7 @@ public class PythonTranslator implements 
Translator.ScriptTranslator {
             for (int i = 0; i < list.size(); i++) {
                 convertPToString(list.get(i), current);
                 if (i < list.size() - 1)
-                    current.append(p instanceof OrP ? "._or(" : "._and(");
+                    current.append(p instanceof OrP ? ".or_(" : ".and_(");
             }
             current.append(")");
         } else

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/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 0302047..05739da 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -172,10 +172,10 @@ class P(object):
    @staticmethod
    def without(*args):
       return P("without", *args)
-   def _and(self, arg):
-      return P("and", arg, self)
-   def _or(self, arg):
-      return P("or", arg, self)
+   def and_(self, arg):
+      return P("and", self, arg)
+   def or_(self, arg):
+      return P("or", self, arg)
    def __eq__(self, other):
         return isinstance(other, self.__class__) and self.operator == 
other.operator and self.value == other.value and self.other == other.other
    def __repr__(self):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-python/src/main/jython/tests/process/test_traversal.py
----------------------------------------------------------------------
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 fe72ac1..0f25190 100644
--- a/gremlin-python/src/main/jython/tests/process/test_traversal.py
+++ b/gremlin-python/src/main/jython/tests/process/test_traversal.py
@@ -23,6 +23,7 @@ import unittest
 from unittest import TestCase
 
 from gremlin_python.structure.graph import Graph
+from gremlin_python.process.traversal import P
 
 
 class TestTraversal(TestCase):
@@ -52,6 +53,13 @@ class TestTraversal(TestCase):
         assert 1 == len(bytecode.step_instructions[1])
         assert 2 == len(bytecode.step_instructions[2])
 
+    def test_P(self):
+        # verify that the order of operations is respected
+        assert "and(eq(a),lt(b))" == str(P.eq("a").and_(P.lt("b")))
+        assert "and(or(lt(b),gt(c)),neq(d))" == 
str(P.lt("b").or_(P.gt("c")).and_(P.neq("d")))
+        assert "and(or(lt(b),gt(c)),or(neq(d),gte(e)))" == str(
+            P.lt("b").or_(P.gt("c")).and_(P.neq("d").or_(P.gte("e"))))
+
 
 if __name__ == '__main__':
     unittest.main()

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/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 cae1a53..6f244f5 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
@@ -27,6 +27,7 @@ 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
+from gremlin_python.process.traversal import P
 
 
 class TestGraphSONReader(TestCase):
@@ -87,6 +88,10 @@ class TestGraphSONWriter(TestCase):
         assert """{"@type":"g:Float","@value":3.2}""" == 
GraphSONWriter.writeObject(3.2)
         assert """true""" == GraphSONWriter.writeObject(True)
 
+    def test_P(self):
+        assert 
"""{"@type":"g:P","@value":{"predicate":"and","value":[{"@type":"g:P","@value":{"predicate":"or","value":[{"@type":"g:P","@value":{"predicate":"lt","value":"b"}},{"@type":"g:P","@value":{"predicate":"gt","value":"c"}}]}},{"@type":"g:P","@value":{"predicate":"neq","value":"d"}}]}}"""
 == GraphSONWriter.writeObject(
+            P.lt("b").or_(P.gt("c")).and_(P.neq("d")))
+
 
 if __name__ == '__main__':
     unittest.main()

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
 
b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
index 0e0bcb3..0ef3158 100644
--- 
a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
+++ 
b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/structure/io/graphson/GraphSONWriterTest.java
@@ -91,7 +91,7 @@ public class GraphSONWriterTest {
     public void shouldSerializeBytecode() throws Exception {
         assertEquals(P.eq(7L), 
mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(P.eq(7L))").toString(),
 Object.class));
         // TODO: assertEquals(mapper.writeValueAsString(P.between(1, 
2).and(P.eq(7L))), 
jythonEngine.eval("GraphSONWriter.writeObject(P.eq(7L)._and(P.between(1,2)))").toString().replace("
 ",""));
-        assertEquals(AndP.class, 
mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(P.eq(7L)._and(P.between(1,2)))").toString(),
 Object.class).getClass());
+        assertEquals(AndP.class, 
mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(P.eq(7L).and_(P.between(1,2)))").toString(),
 Object.class).getClass());
         //
         assertEquals(new Bytecode.Binding<>("a", 5L), 
mapper.readValue(jythonEngine.eval("GraphSONWriter.writeObject(Binding('a',5L))").toString(),
 Object.class));
         //

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68ecda40/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
index a3ba0cc..03f76b7 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
@@ -21,24 +21,39 @@ package 
org.apache.tinkerpop.gremlin.process.traversal.step.filter;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
-import org.apache.tinkerpop.gremlin.process.IgnoreEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.*;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.not;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.within;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.without;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.and;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.not;
-import static org.junit.Assert.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.or;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -94,6 +109,14 @@ public abstract class WhereTest extends 
AbstractGremlinProcessTest {
 
     //public abstract Traversal<Vertex, String> 
get_g_V_asXaX_outXknowsX_asXbX_whereXasXa__bX_outXcreatedX_hasXname__rippleX_name();
 
+    // where()-by
+
+    public abstract Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_gtXbXX_byXageX_selectXa_bX_byXnameX();
+
+    public abstract Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_whereXa_gtXbX_orXeqXbXXX_byXageX_byXweightX_byXweightX_selectXa_cX_byXnameX();
+
+    public abstract Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void 
g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_eqXbXX() {
@@ -317,28 +340,64 @@ public abstract class WhereTest extends 
AbstractGremlinProcessTest {
                 "a", convertToVertex(graph, "josh"), "b", 
convertToVertex(graph, "lop")), traversal);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void 
g_V_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_gtXbXX_byXageX_selectXa_bX_byXnameX()
 {
+        final Traversal<Vertex, Map<String, String>> traversal = 
get_g_V_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_gtXbXX_byXageX_selectXa_bX_byXnameX();
+        printTraversalForm(traversal);
+        checkResults(makeMapList(2,
+                "a", "peter", "b", "josh",
+                "a", "peter", "b", "marko",
+                "a", "josh", "b", "marko"), traversal);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void 
g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_whereXa_gtXbX_orXeqXbXXX_byXageX_byXweightX_byXweightX_selectXa_cX_byXnameX()
 {
+        final Traversal<Vertex, Map<String, String>> traversal = 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_whereXa_gtXbX_orXeqXbXXX_byXageX_byXweightX_byXweightX_selectXa_cX_byXnameX();
+        printTraversalForm(traversal);
+        checkResults(makeMapList(2,
+                "a", "peter", "c", "lop",
+                "a", "josh", "c", "lop",
+                "a", "josh", "c", "ripple",
+                "a", "marko", "c", "lop"), traversal);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void 
g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX()
 {
+        final Traversal<Vertex, Map<String, String>> traversal = 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX();
+        printTraversalForm(traversal);
+        checkResults(makeMapList(3,
+                "a", "peter", "c", "lop", "d", "josh",
+                "a", "peter", "c", "lop", "d", "marko",
+                "a", "josh", "c", "lop", "d", "marko",
+                "a", "josh", "c", "lop", "d", "peter"), traversal);
+    }
+
+
     public static class Traversals extends WhereTest {
 
         /// where(local)
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_eqXbXX() {
-            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a","b").where("a",
 eq("b"));
+            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a", 
"b").where("a", eq("b"));
         }
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_neqXbXX() {
-            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a","b").where("a",
 neq("b"));
+            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a", 
"b").where("a", neq("b"));
         }
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXb_hasXname_markoXX()
 {
-            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a","b").where(as("b").has("name",
 "marko"));
+            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a", 
"b").where(as("b").has("name", "marko"));
         }
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_outXknowsX_bX()
 {
-            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a","b").where(as("a").out("knows").as("b"));
+            return 
g.V().has("age").as("a").out().in().has("age").as("b").select("a", 
"b").where(as("a").out("knows").as("b"));
         }
 
         /// where(global)
@@ -391,7 +450,7 @@ public abstract class WhereTest extends 
AbstractGremlinProcessTest {
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_asXaX_out_asXbX_whereXandXasXaX_outXknowsX_asXbX__orXasXbX_outXcreatedX_hasXname_rippleX__asXbX_inXknowsX_count_isXnotXeqX0XXXXX_selectXa_bX()
 {
-            return 
g.V().as("a").out().as("b").where(and(as("a").out("knows").as("b"), 
or(as("b").out("created").has("name", "ripple"), 
as("b").in("knows").count().is(not(eq(0)))))).select("a","b");
+            return 
g.V().as("a").out().as("b").where(and(as("a").out("knows").as("b"), 
or(as("b").out("created").has("name", "ripple"), 
as("b").in("knows").count().is(not(eq(0)))))).select("a", "b");
         }
 
         @Override
@@ -401,17 +460,34 @@ public abstract class WhereTest extends 
AbstractGremlinProcessTest {
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_asXaX_outXcreatedX_asXbX_whereXandXasXbX_in__notXasXaX_outXcreatedX_hasXname_rippleXXX_selectXa_bX()
 {
-            return 
g.V().as("a").out("created").as("b").where(and(as("b").in(), 
not(as("a").out("created").has("name", "ripple")))).select("a","b");
+            return 
g.V().as("a").out("created").as("b").where(and(as("b").in(), 
not(as("a").out("created").has("name", "ripple")))).select("a", "b");
         }
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_bothXknowsX_bothXknowsX_asXdX_whereXc__notXeqXaX_orXeqXdXXXX_selectXa_b_c_dX()
 {
-            return 
g.V().as("a").out("created").as("b").in("created").as("c").both("knows").both("knows").as("d").where("c",
 P.not(P.eq("a").or(P.eq("d")))).select("a","b","c","d");
+            return 
g.V().as("a").out("created").as("b").in("created").as("c").both("knows").both("knows").as("d").where("c",
 P.not(P.eq("a").or(P.eq("d")))).select("a", "b", "c", "d");
         }
 
         @Override
         public Traversal<Vertex, Map<String, Object>> 
get_g_V_asXaX_out_asXbX_whereXin_count_isXeqX3XX_or_whereXoutXcreatedX_and_hasXlabel_personXXX_selectXa_bX()
 {
-            return 
g.V().as("a").out().as("b").where(as("b").in().count().is(eq(3)).or().where(as("b").out("created").and().as("b").has(T.label,
 "person"))).select("a","b");
+            return 
g.V().as("a").out().as("b").where(as("b").in().count().is(eq(3)).or().where(as("b").out("created").and().as("b").has(T.label,
 "person"))).select("a", "b");
+        }
+
+        // where()-by
+
+        @Override
+        public Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_gtXbXX_byXageX_selectXa_bX_byXnameX()
 {
+            return 
g.V().as("a").out("created").in("created").as("b").where("a", 
gt("b")).by("age").<String>select("a", "b").by("name");
+        }
+
+        @Override
+        public Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_whereXa_gtXbX_orXeqXbXXX_byXageX_byXweightX_byXweightX_selectXa_cX_byXnameX()
 {
+            return 
g.V().as("a").outE("created").as("b").inV().as("c").where("a", 
gt("b").or(eq("b"))).by("age").by("weight").by("weight").<String>select("a", 
"c").by("name");
+        }
+
+        @Override
+        public Traversal<Vertex, Map<String, String>> 
get_g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX()
 {
+            return 
g.V().as("a").outE("created").as("b").inV().as("c").in("created").as("d").where("a",
 
lt("b").or(gt("c")).and(neq("d"))).by("age").by("weight").by(in("created").values("age").min()).<String>select("a",
 "c", "d").by("name");
         }
     }
 }
\ No newline at end of file

Reply via email to