You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2018/08/01 19:29:32 UTC

[08/50] [abbrv] tinkerpop git commit: TINKERPOP-1996 Added support/testing for io() in GLVs

TINKERPOP-1996 Added support/testing for io() in GLVs

Had to revert to using iterate() and stop read/write() from terminating the traversal. Kinda stinks, but we rely on iterate() quite heavily and for remoting allowing read()/write() to terminate means that the traversal will execute during traversal construction in the translator (which is early and potentially bad).


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

Branch: refs/heads/TINKERPOP-1990
Commit: 048ea21c0adf9297233d06222e75c64dbe1fa1ca
Parents: f8e3b8a
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Jul 19 13:30:02 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Jul 19 13:41:01 2018 -0400

----------------------------------------------------------------------
 .../traversal/dsl/graph/GraphTraversal.java     | 11 +--
 gremlin-dotnet/glv/IO.template                  | 46 +++++++++++
 gremlin-dotnet/glv/generate.groovy              |  8 ++
 .../src/Gremlin.Net/Process/Traversal/IO.cs     | 54 +++++++++++++
 .../Gherkin/TraversalEvaluation/IOParameter.cs  | 82 +++++++++++++++++++
 .../TraversalEvaluation/TraversalParser.cs      |  7 ++
 gremlin-javascript/glv/TraversalSource.template |  9 +++
 gremlin-javascript/glv/generate.groovy          |  4 +
 .../gremlin-javascript/lib/process/traversal.js | 25 ++++++
 .../test/cucumber/feature-steps.js              |  2 +
 gremlin-python/glv/TraversalSource.template     | 11 +++
 gremlin-python/glv/generate.groovy              |  4 +
 .../jython/gremlin_python/process/traversal.py  | 19 +++++
 .../src/main/jython/radish/feature_steps.py     |  5 +-
 gremlin-test/features/sideEffect/Read.feature   | 84 ++++++++++++++++++++
 gremlin-test/features/sideEffect/Write.feature  | 60 ++++++++++++++
 .../gremlin/AbstractGraphProvider.java          |  2 +-
 .../process/traversal/step/map/ReadTest.java    | 57 ++++++++++---
 18 files changed, 471 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 20f8996..a675ad1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -124,6 +124,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCount
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IoStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.LambdaSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ProfileSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
@@ -2734,13 +2735,13 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
 
     ////
 
-    ///////////////////// IO TERMINATOR STEPS /////////////////////
+    ///////////////////// IO STEPS /////////////////////
 
     /**
      * This step is technically a step modulator for the the {@link GraphTraversalSource#io(String)} step which
      * instructs the step to perform a read with its given configuration.
      *
-     * @return the traversal that has been iterated with the read IO action executed
+     * @return the traversal with the {@link IoStep} modulated to read
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#io-step" target="_blank">Reference Documentation - IO Step</a>
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#read-step" target="_blank">Reference Documentation - Read Step</a>
      * @since 3.4.0
@@ -2748,14 +2749,14 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     public default GraphTraversal<S,E> read() {
         this.asAdmin().getBytecode().addStep(Symbols.read);
         ((ReadWriting) this.asAdmin().getEndStep()).setMode(ReadWriting.Mode.READING);
-        return this.iterate();
+        return this;
     }
 
     /**
      * This step is technically a step modulator for the the {@link GraphTraversalSource#io(String)} step which
      * instructs the step to perform a write with its given configuration.
      *
-     * @return the traversal that has been iterated with the write IO action executed
+     * @return the traversal with the {@link IoStep} modulated to write
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#io-step" target="_blank">Reference Documentation - IO Step</a>
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#write-step" target="_blank">Reference Documentation - Write Step</a>
      * @since 3.4.0
@@ -2763,7 +2764,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     public default GraphTraversal<S,E> write() {
         this.asAdmin().getBytecode().addStep(Symbols.write);
         ((ReadWriting) this.asAdmin().getEndStep()).setMode(ReadWriting.Mode.WRITING);
-        return this.iterate();
+        return this;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-dotnet/glv/IO.template
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/glv/IO.template b/gremlin-dotnet/glv/IO.template
new file mode 100644
index 0000000..7b25c88
--- /dev/null
+++ b/gremlin-dotnet/glv/IO.template
@@ -0,0 +1,46 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     <see cref="IO" /> keeps configuration options for the io() step.
+    /// </summary>
+    public class IO
+    {
+        <% io.each {k,v -> %>
+            public const String <%= k %> = "<%= v %>";
+        <% } %>
+    }
+
+#pragma warning restore 1591
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-dotnet/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/glv/generate.groovy b/gremlin-dotnet/glv/generate.groovy
index bd2d9d7..58a5026 100644
--- a/gremlin-dotnet/glv/generate.groovy
+++ b/gremlin-dotnet/glv/generate.groovy
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
+import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import org.apache.tinkerpop.gremlin.structure.Direction
 import java.lang.reflect.Modifier
@@ -303,6 +304,9 @@ def binding = ["pmethods": P.class.getMethods().
                             def graphTraversalT2 = getGraphTraversalT2ForT2(t2)
                             return ["methodName": javaMethod.name, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "callGenericTypeArg":callGenericTypeArg, "graphTraversalT2":graphTraversalT2]
                         },
+               "io": IO.class.getFields().
+                       sort{ a, b -> a.name <=> b.name }.
+                       collectEntries{ f -> [(f.name) : f.get(null)]},
                "toCSharpMethodName": toCSharpMethodName]
 
 def engine = new groovy.text.GStringTemplateEngine()
@@ -322,6 +326,10 @@ def pTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/P.template
 def pFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/P.cs")
 pFile.newWriter().withWriter{ it << pTemplate }
 
+def ioTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/IO.template")).make(binding)
+def ioFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/IO.cs")
+ioFile.newWriter().withWriter{ it << ioTemplate }
+
 
 def createEnum = { enumClass ->
     def b = ["enumClass": enumClass,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs
new file mode 100644
index 0000000..288f7e3
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/IO.cs
@@ -0,0 +1,54 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     <see cref="IO" /> keeps configuration options for the io() step.
+    /// </summary>
+    public class IO
+    {
+        
+            public const String graphml = "graphml";
+        
+            public const String graphson = "graphson";
+        
+            public const String gryo = "gryo";
+        
+            public const String reader = "~tinkerpop.io.reader";
+        
+            public const String writer = "~tinkerpop.io.writer";
+        
+    }
+
+#pragma warning restore 1591
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/IOParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/IOParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/IOParameter.cs
new file mode 100644
index 0000000..513e589
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/IOParameter.cs
@@ -0,0 +1,82 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Reflection;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    /// <summary>
+    /// Represents a parameter for the io() step - (e.g. IO.graphml)
+    /// </summary>
+    internal class IOParameter : ITokenParameter, IEquatable<IOParameter>
+    {
+        private readonly string _text;
+        private readonly string _value;
+        
+        public IOParameter(string text)
+        {
+            _text = text;
+            var separatorIndex = text.IndexOf('.');
+            _value = text.Substring(separatorIndex + 1);
+        }
+
+        public bool Equals(IOParameter other)
+        {
+            return _text == other._text;
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((IOParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return _text.GetHashCode();
+        }
+
+        public object GetValue()
+        {
+            var field = typeof(IO).GetField(_value, BindingFlags.Static | BindingFlags.Public);
+            return field.GetValue(null);
+        }
+
+        public void SetContextParameterValues(IDictionary<string, object> parameterValues)
+        {
+
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(String);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
index e3f6a3f..f8e4095 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -44,6 +44,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 
         private static readonly Regex RegexEnum = new Regex(@"\w+\.\w+", RegexOptions.Compiled);
 
+        private static readonly Regex RegexIO = new Regex(@"IO.\w+", RegexOptions.Compiled);
+
         private static readonly Regex RegexParam = new Regex(@"\w+", RegexOptions.Compiled);
         
         private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
@@ -424,6 +426,11 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
                 i += parameterText.Length - 1;
                 return LiteralParameter.Create(Convert.ToBoolean(parameterText));
             }
+            if (RegexIO.IsMatch(parameterText))
+            {
+                i += parameterText.Length - 1;
+                return new IOParameter(parameterText);
+            }
             if (RegexEnum.IsMatch(parameterText))
             {
                 i += parameterText.Length - 1;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-javascript/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-javascript/glv/TraversalSource.template b/gremlin-javascript/glv/TraversalSource.template
index 6965110..321956c 100644
--- a/gremlin-javascript/glv/TraversalSource.template
+++ b/gremlin-javascript/glv/TraversalSource.template
@@ -111,6 +111,14 @@ class Traversal {
   };
 }
 
+class IO {
+<% io.each {k,v -> %>
+    static get <%= k %>() {
+        return "<%= v %>"
+    }
+<% } %>
+}
+
 class P {
   /**
    * Represents an operation.
@@ -190,6 +198,7 @@ class EnumValue {
 module.exports = {
   EnumValue,
   P,
+  IO,
   Traversal,
   TraversalSideEffects,
   Traverser<%

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-javascript/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-javascript/glv/generate.groovy b/gremlin-javascript/glv/generate.groovy
index 8778e89..a339689 100644
--- a/gremlin-javascript/glv/generate.groovy
+++ b/gremlin-javascript/glv/generate.groovy
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
+import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import java.lang.reflect.Modifier
 
@@ -88,6 +89,9 @@ def binding = ["enums": CoreImports.getClassImports()
                        collect { it.name }.
                        unique().
                        sort { a, b -> a <=> b },
+               "io": IO.class.getFields().
+                       sort{ a, b -> a.name <=> b.name }.
+                       collectEntries{ f -> [(f.name) : f.get(null)]},
                "toJs": toJs,
                "version": determineVersion(),
                "decapitalize": decapitalize]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index d39ccf0..3f69fb1 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -111,6 +111,30 @@ class Traversal {
   };
 }
 
+class IO {
+
+    static get graphml() {
+        return "graphml"
+    }
+
+    static get graphson() {
+        return "graphson"
+    }
+
+    static get gryo() {
+        return "gryo"
+    }
+
+    static get reader() {
+        return "~tinkerpop.io.reader"
+    }
+
+    static get writer() {
+        return "~tinkerpop.io.writer"
+    }
+
+}
+
 class P {
   /**
    * Represents an operation.
@@ -250,6 +274,7 @@ class EnumValue {
 module.exports = {
   EnumValue,
   P,
+  IO,
   Traversal,
   TraversalSideEffects,
   Traverser,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index 16aae78..320d3f4 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -187,6 +187,7 @@ function getSandbox(g, parameters) {
     },
     Order: traversalModule.order,
     P: traversalModule.P,
+    IO: traversalModule.IO,
     Pick: traversalModule.pick,
     Pop: traversalModule.pop,
     Scope: traversalModule.scope,
@@ -207,6 +208,7 @@ function translate(traversalText) {
   // Change according to naming convention
   traversalText = traversalText.replace(/\.in\(/g, '.in_(');
   traversalText = traversalText.replace(/\.from\(/g, '.from_(');
+  traversalText = traversalText.replace(/\.with\(/g, '.with_(');
   return traversalText;
 }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-python/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-python/glv/TraversalSource.template b/gremlin-python/glv/TraversalSource.template
index b6f5b9f..3ca2786 100644
--- a/gremlin-python/glv/TraversalSource.template
+++ b/gremlin-python/glv/TraversalSource.template
@@ -135,6 +135,17 @@ statics.add_static('<%= method %>',<%= method %>)
 <% } %>
 
 '''
+IO
+'''
+
+
+class IO(object):
+<% io.each {k,v -> %>
+    <%= k %> = "<%= v %>"
+<% } %>
+
+
+'''
 TRAVERSER
 '''
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-python/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-python/glv/generate.groovy b/gremlin-python/glv/generate.groovy
index 57cc9c9..f810e10 100644
--- a/gremlin-python/glv/generate.groovy
+++ b/gremlin-python/glv/generate.groovy
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
+import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import java.lang.reflect.Modifier
 // this is a bit of a copy of what's in SymbolHelper - no way around it because this code generation task occurs
@@ -78,6 +79,9 @@ def binding = ["enums": CoreImports.getClassImports()
                        collect { toPython(it.name) }.
                        unique().
                        sort { a, b -> a <=> b },
+               "io": IO.class.getFields().
+                       sort{ a, b -> a.name <=> b.name }.
+                       collectEntries{ f -> [(f.name) : f.get(null)]},
                "toPython": toPython,
                "toJava": toJava]
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/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 068c865..d9fb4d9 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -305,6 +305,25 @@ statics.add_static('without',without)
 
 
 '''
+IO
+'''
+
+
+class IO(object):
+
+    graphml = "graphml"
+
+    graphson = "graphson"
+
+    gryo = "gryo"
+
+    reader = "~tinkerpop.io.reader"
+
+    writer = "~tinkerpop.io.writer"
+
+
+
+'''
 TRAVERSER
 '''
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/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 5067d1b..99022a0 100644
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ b/gremlin-python/src/main/jython/radish/feature_steps.py
@@ -21,7 +21,7 @@ import json
 import re
 from gremlin_python.structure.graph import Graph, Path
 from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.traversal import Barrier, Cardinality, P, Pop, Scope, Column, Order, Direction, T, Pick, Operator
+from gremlin_python.process.traversal import Barrier, Cardinality, P, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO
 from radish import given, when, then
 from hamcrest import *
 
@@ -34,6 +34,7 @@ regex_in = re.compile(r"([(.,\s])in\(")
 regex_is = re.compile(r"([(.,\s])is\(")
 regex_not = re.compile(r"([(.,\s])not\(")
 regex_or = re.compile(r"([(.,\s])or\(")
+regex_with = re.compile(r"([(.,\s])with\(")
 regex_true = re.compile(r"(true)")
 regex_false = re.compile(r"(false)")
 
@@ -241,6 +242,7 @@ def _translate(traversal):
     replaced = regex_not.sub(r"\1not_(", replaced)
     replaced = regex_or.sub(r"\1or_(", replaced)
     replaced = regex_in.sub(r"\1in_(", replaced)
+    replaced = regex_with.sub(r"\1with_(", replaced)
     replaced = regex_true.sub(r"True", replaced)
     return regex_false.sub(r"False", replaced)
 
@@ -254,6 +256,7 @@ def _make_traversal(g, traversal_string, params):
          "Direction": Direction,
          "Order": Order,
          "P": P,
+         "IO": IO,
          "Pick": Pick,
          "Pop": Pop,
          "Scope": Scope,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-test/features/sideEffect/Read.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/sideEffect/Read.feature b/gremlin-test/features/sideEffect/Read.feature
new file mode 100644
index 0000000..ae96102
--- /dev/null
+++ b/gremlin-test/features/sideEffect/Read.feature
@@ -0,0 +1,84 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+Feature: Step - read()
+
+  Scenario: g_io_readXkryoX
+    Given the empty graph
+    And the traversal of
+      """
+      g.io("data/tinkerpop-modern.kryo").read()
+      """
+    When iterated to list
+    Then the result should be empty
+    And the graph should return 6 for count of "g.V()"
+    And the graph should return 6 for count of "g.E()"
+
+  Scenario: g_io_read_withXreader_gryoX
+    Given the empty graph
+    And the traversal of
+      """
+      g.io("data/tinkerpop-modern.kryo").with(IO.reader, IO.gryo).read()
+      """
+    When iterated to list
+    Then the result should be empty
+    And the graph should return 6 for count of "g.V()"
+    And the graph should return 6 for count of "g.E()"
+
+  Scenario: g_io_readXgraphsonX
+    Given the empty graph
+    And the traversal of
+      """
+      g.io("data/tinkerpop-modern.json").read()
+      """
+    When iterated to list
+    Then the result should be empty
+    And the graph should return 6 for count of "g.V()"
+    And the graph should return 6 for count of "g.E()"
+
+  Scenario: g_io_read_withXreader_graphsonX
+    Given the empty graph
+    And the traversal of
+      """
+      g.io("data/tinkerpop-modern.json").with(IO.reader, IO.graphson).read()
+      """
+    When iterated to list
+    Then the result should be empty
+    And the graph should return 6 for count of "g.V()"
+    And the graph should return 6 for count of "g.E()"
+
+  Scenario: g_io_readXgraphmlX
+    Given the empty graph
+    And the traversal of
+      """
+      g.io("data/tinkerpop-modern.xml").read()
+      """
+    When iterated to list
+    Then the result should be empty
+    And the graph should return 6 for count of "g.V()"
+    And the graph should return 6 for count of "g.E()"
+
+  Scenario: g_io_read_withXreader_graphmlX
+    Given the empty graph
+    And the traversal of
+      """
+      g.io("data/tinkerpop-modern.xml").with(IO.reader, IO.graphml).read()
+      """
+    When iterated to list
+    Then the result should be empty
+    And the graph should return 6 for count of "g.V()"
+    And the graph should return 6 for count of "g.E()"
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-test/features/sideEffect/Write.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/sideEffect/Write.feature b/gremlin-test/features/sideEffect/Write.feature
new file mode 100644
index 0000000..9a774e8
--- /dev/null
+++ b/gremlin-test/features/sideEffect/Write.feature
@@ -0,0 +1,60 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+Feature: Step - write()
+
+  Scenario: g_io_writeXkryoX
+    Given an unsupported test
+    Then nothing should happen because
+      """
+      We don't have a nice way to assert the remotely written file with this framework - just testing compilation.
+      """
+
+  Scenario: g_io_write_withXwriter_gryoX
+    Given an unsupported test
+    Then nothing should happen because
+      """
+      We don't have a nice way to assert the remotely written file with this framework - just testing compilation.
+      """
+
+  Scenario: g_io_writeXgraphsonX
+    Given an unsupported test
+    Then nothing should happen because
+      """
+      We don't have a nice way to assert the remotely written file with this framework - just testing compilation.
+      """
+
+  Scenario: g_io_write_withXwriter_graphsonX
+    Given an unsupported test
+    Then nothing should happen because
+      """
+      We don't have a nice way to assert the remotely written file with this framework - just testing compilation.
+      """
+
+  Scenario: g_io_writeXgraphmlX
+    Given an unsupported test
+    Then nothing should happen because
+      """
+      We don't have a nice way to assert the remotely written file with this framework - just testing compilation.
+      """
+
+  Scenario: g_io_write_withXwriter_graphmlX
+    Given an unsupported test
+    Then nothing should happen because
+      """
+      We don't have a nice way to assert the remotely written file with this framework - just testing compilation.
+      """
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java
index b6fc43c..9774411 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGraphProvider.java
@@ -145,6 +145,6 @@ public abstract class AbstractGraphProvider implements GraphProvider {
     protected void readIntoGraph(final Graph graph, final String path) throws IOException {
         final String dataFile = TestHelper.generateTempFileFromResource(graph.getClass(),
                 GryoResourceAccess.class, path.substring(path.lastIndexOf(File.separator) + 1), "", false).getAbsolutePath();
-        graph.traversal().io(dataFile).read();
+        graph.traversal().io(dataFile).read().iterate();
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/048ea21c/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
index ab59194..24bacbb 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.FeatureRequirementSet;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.remote.RemoteGraph;
 import org.apache.tinkerpop.gremlin.process.traversal.IO;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -34,8 +35,10 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.io.IOException;
+import java.util.function.Supplier;
 
 import static org.apache.tinkerpop.gremlin.structure.Graph.Features.GraphFeatures.FEATURE_IO_READ;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
 /**
@@ -62,9 +65,14 @@ public abstract class ReadTest extends AbstractGremlinProcessTest {
         final String fileToRead = TestHelper.generateTempFileFromResource(ReadTest.class, GryoResourceAccess.class, "tinkerpop-modern-v3d0.kryo", "").getAbsolutePath().replace('\\', '/');
         final Traversal<Object,Object> traversal = get_g_io_readXkryoX(fileToRead);
         printTraversalForm(traversal);
-        assertFalse(traversal.hasNext());
+        traversal.iterate();
 
-        IoTest.assertModernGraph(graph, false, true);
+        if (graph instanceof RemoteGraph) {
+            assertEquals(6L, g.V().count().next().longValue());
+            assertEquals(6L, g.E().count().next().longValue());
+        } else {
+            IoTest.assertModernGraph(graph, false, true);
+        }
     }
 
     @Test
@@ -73,9 +81,14 @@ public abstract class ReadTest extends AbstractGremlinProcessTest {
         final String fileToRead = TestHelper.generateTempFileFromResource(ReadTest.class, GryoResourceAccess.class, "tinkerpop-modern-v3d0.kryo", "").getAbsolutePath().replace('\\', '/');
         final Traversal<Object,Object> traversal = get_g_io_read_withXreader_gryoX(fileToRead);
         printTraversalForm(traversal);
-        assertFalse(traversal.hasNext());
+        traversal.iterate();
 
-        IoTest.assertModernGraph(graph, false, true);
+        if (graph instanceof RemoteGraph) {
+            assertEquals(6L, g.V().count().next().longValue());
+            assertEquals(6L, g.E().count().next().longValue());
+        } else {
+            IoTest.assertModernGraph(graph, false, true);
+        }
     }
 
     @Test
@@ -84,9 +97,14 @@ public abstract class ReadTest extends AbstractGremlinProcessTest {
         final String fileToRead = TestHelper.generateTempFileFromResource(ReadTest.class, GraphSONResourceAccess.class, "tinkerpop-modern-v3d0.json", "").getAbsolutePath().replace('\\', '/');
         final Traversal<Object,Object> traversal = get_g_io_readXjsonX(fileToRead);
         printTraversalForm(traversal);
-        assertFalse(traversal.hasNext());
+        traversal.iterate();
 
-        IoTest.assertModernGraph(graph, false, true);
+        if (graph instanceof RemoteGraph) {
+            assertEquals(6L, g.V().count().next().longValue());
+            assertEquals(6L, g.E().count().next().longValue());
+        } else {
+            IoTest.assertModernGraph(graph, false, true);
+        }
     }
 
     @Test
@@ -95,9 +113,14 @@ public abstract class ReadTest extends AbstractGremlinProcessTest {
         final String fileToRead = TestHelper.generateTempFileFromResource(ReadTest.class, GraphSONResourceAccess.class, "tinkerpop-modern-v3d0.json", "").getAbsolutePath().replace('\\', '/');
         final Traversal<Object,Object> traversal = get_g_io_read_withXreader_graphsonX(fileToRead);
         printTraversalForm(traversal);
-        assertFalse(traversal.hasNext());
+        traversal.iterate();
 
-        IoTest.assertModernGraph(graph, false, true);
+        if (graph instanceof RemoteGraph) {
+            assertEquals(6L, g.V().count().next().longValue());
+            assertEquals(6L, g.E().count().next().longValue());
+        } else {
+            IoTest.assertModernGraph(graph, false, true);
+        }
     }
 
     @Test
@@ -106,9 +129,14 @@ public abstract class ReadTest extends AbstractGremlinProcessTest {
         final String fileToRead = TestHelper.generateTempFileFromResource(ReadTest.class, GraphMLResourceAccess.class, "tinkerpop-modern.xml", "").getAbsolutePath().replace('\\', '/');
         final Traversal<Object,Object> traversal = get_g_io_readXxmlX(fileToRead);
         printTraversalForm(traversal);
-        assertFalse(traversal.hasNext());
+        traversal.iterate();
 
-        IoTest.assertModernGraph(graph, false, true);
+        if (graph instanceof RemoteGraph) {
+            assertEquals(6L, g.V().count().next().longValue());
+            assertEquals(6L, g.E().count().next().longValue());
+        } else {
+            IoTest.assertModernGraph(graph, false, true);
+        }
     }
 
     @Test
@@ -117,9 +145,14 @@ public abstract class ReadTest extends AbstractGremlinProcessTest {
         final String fileToRead = TestHelper.generateTempFileFromResource(ReadTest.class, GraphMLResourceAccess.class, "tinkerpop-modern.xml", "").getAbsolutePath().replace('\\', '/');
         final Traversal<Object,Object> traversal = get_g_io_read_withXreader_graphmlX(fileToRead);
         printTraversalForm(traversal);
-        assertFalse(traversal.hasNext());
+        traversal.iterate();
 
-        IoTest.assertModernGraph(graph, false, true);
+        if (graph instanceof RemoteGraph) {
+            assertEquals(6L, g.V().count().next().longValue());
+            assertEquals(6L, g.E().count().next().longValue());
+        } else {
+            IoTest.assertModernGraph(graph, false, true);
+        }
     }
 
     public static class Traversals extends ReadTest {