You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2021/04/15 19:42:46 UTC

[tinkerpop] branch master updated: Remove Gremlin Language Variants tutorial

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/master by this push:
     new 8b4667f  Remove Gremlin Language Variants tutorial
8b4667f is described below

commit 8b4667f4d1cc90ee1ff8f29fb73e3b21fa586cf3
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Thu Apr 15 15:41:18 2021 -0400

    Remove Gremlin Language Variants tutorial
    
    This content was a bit out of date. Wasn't much to migrate elsewhere that wasn't already being said. Added a redirect for the page to go to the Reference Docs. CTR
---
 docs/postprocessor/postprocess.sh                  |   4 +
 docs/site/home/gremlin.html                        |   2 +-
 docs/site/home/providers.html                      |   2 +-
 docs/site/home/template/header-footer.html         |   3 +-
 .../dev/developer/development-environment.asciidoc |   2 +-
 docs/src/dev/provider/index.asciidoc               |   4 +-
 docs/src/index.asciidoc                            |   2 -
 docs/src/reference/gremlin-variants.asciidoc       |  15 +-
 docs/src/reference/intro.asciidoc                  |   9 +-
 .../gremlin-language-variants/index.asciidoc       | 588 +--------------------
 10 files changed, 22 insertions(+), 609 deletions(-)

diff --git a/docs/postprocessor/postprocess.sh b/docs/postprocessor/postprocess.sh
index b2d4971..e7dca52 100755
--- a/docs/postprocessor/postprocess.sh
+++ b/docs/postprocessor/postprocess.sh
@@ -23,6 +23,10 @@ pushd "$(dirname $0)/../.." > /dev/null
 TP_VERSION=$(cat pom.xml | grep -A1 '<artifactId>tinkerpop</artifactId>' | grep -o 'version>[^<]*' | grep -o '>.*' | cut -d '>' -f2 | head -n1)
 
 if [ -d "target/docs" ]; then
+
+  # redirect the GLV Tutorial to reference docs
+  sed -i "s/<meta charset=\"UTF-8\">/<meta http-equiv=\"Refresh\" content=\"0; url='https:\/\/tinkerpop.apache.org\/docs\/x.y.z\/reference\/#gremlin-drivers-variants'\" \/>/" target/docs/htmlsingle/tutorials/gremlin-language-variants/index.html
+
   find target/docs -name index.html | while read file ; do
     awk -f "docs/postprocessor/processor.awk" "${file}" 2>/dev/null       \
       | perl -0777 -pe 's/<span class="comment">\/\*\n \*\/<\/span>//igs' \
diff --git a/docs/site/home/gremlin.html b/docs/site/home/gremlin.html
index 7c3e6aa..5fb5c2b 100644
--- a/docs/site/home/gremlin.html
+++ b/docs/site/home/gremlin.html
@@ -277,7 +277,7 @@ g.V().hasLabel("person").
           "programming languages" are not as great as we are taught to believe. Gremlin unifies this divide because traversals can be written in any
           programming language that supports function <a href="https://en.wikipedia.org/wiki/Function_composition">composition</a> and <a href="https://en.wikipedia.org/wiki/Nested_function">nesting</a> (which every major programming language supports). In this way, the user's
           Gremlin traversals are written along side their application code and benefit from the advantages afforded by the host language and its tooling
-          (e.g. type checking, syntax highlighting, dot completion, etc.). Various <a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin language variants</a> exist including: Gremlin-Java, Gremlin-Groovy, <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>,
+          (e.g. type checking, syntax highlighting, dot completion, etc.). Various <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-drivers-variants">Gremlin language variants</a> exist including: Gremlin-Java, Gremlin-Groovy, <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>,
           <a href="https://github.com/mpollmeier/gremlin-scala">Gremlin-Scala</a>, etc.
        </div>
        <div class="col-md-12">
diff --git a/docs/site/home/providers.html b/docs/site/home/providers.html
index 824b340..82ee621 100644
--- a/docs/site/home/providers.html
+++ b/docs/site/home/providers.html
@@ -253,7 +253,7 @@ limitations under the License.
       <br/>
       <div class="row">
          <div class="col-sm-7 col-md-8">
-            <strong>Gremlin language variants</strong>: There are various <a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin language variants</a> such as <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>. These languages
+            <strong>Gremlin language variants</strong>: There are various <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-drivers-variants">Gremlin language variants</a> such as <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-python">Gremlin-Python</a>. These languages
             generate Gremlin bytecode utilizing the same naming/style-conventions as Gremlin-Java. However, where appropriate, they can deviate from convention in order to take advantage of the unique expressive qualities of the host language. For instance, Gremlin-Python supports index slices, attribute access, etc.
          </div>
          <div class="col-sm-5 col-md-4">
diff --git a/docs/site/home/template/header-footer.html b/docs/site/home/template/header-footer.html
index e5a7c1f..ca90ee1 100644
--- a/docs/site/home/template/header-footer.html
+++ b/docs/site/home/template/header-footer.html
@@ -99,7 +99,6 @@ limitations under the License.
                      <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/getting-started/">Getting Started</a></li>
                      <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/">The Gremlin Console</a></li>
                      <li><a href="https://tinkerpop.apache.org/docs/current/recipes/">Gremlin Recipes</a></li>
-                     <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/">Gremlin Language Variants</a></li>
                      <li><a href="https://tinkerpop.apache.org/docs/current/tutorials/gremlins-anatomy/">Gremlin's Anatomy</a></li>
                      <li role="separator" class="divider"></li>
                      <li><a href="http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html">Book: Practical Gremlin by Kelvin Lawrence</a></li>
@@ -142,7 +141,7 @@ limitations under the License.
       !!!!!BODY!!!!!
       <div id="footer">
          <div class="container">
-            <p class="muted credit">Copyright © 2015-2019 The Apache Software Foundation.<br/>Apache TinkerPop, TinkerPop, Apache, Apache feather logo, and Apache TinkerPop project logo are either registered trademarks or trademarks of <a href="https://www.apache.org/">The Apache Software Foundation</a> in the United States and other countries.
+            <p class="muted credit">Copyright © 2015-2021 The Apache Software Foundation.<br/>Apache TinkerPop, TinkerPop, Apache, Apache feather logo, and Apache TinkerPop project logo are either registered trademarks or trademarks of <a href="https://www.apache.org/">The Apache Software Foundation</a> in the United States and other countries.
             </p>
          </div>
       </div>
diff --git a/docs/src/dev/developer/development-environment.asciidoc b/docs/src/dev/developer/development-environment.asciidoc
index 61b2af2..58764a1 100644
--- a/docs/src/dev/developer/development-environment.asciidoc
+++ b/docs/src/dev/developer/development-environment.asciidoc
@@ -30,7 +30,7 @@ At a minimum, development of TinkerPop requires link:https://openjdk.java.net/pr
 preferable to use link:https://openjdk.java.net/projects/jdk/11/[Java 11] cross-compiled to Java 8 (the
 cross-compilation happens automatically as part of the build). Maven (requiring a minimum of
 link:https://maven.apache.org/download.cgi[Maven 3.3.9+]) is used as the common build system, which even
-controls the builds of non-JVM link:https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/[GLVs]
+controls the builds of non-JVM link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[GLVs]
 such as `gremlin-python`. Java and Maven are described as a "minimum" for a development environment, because they
 will only build JVM portions of TinkerPop and many integration tests will not fire with this simple setup. It is
 possible to get a clean and successful build with this minimum, but it will not be possible to build non-JVM aspects
diff --git a/docs/src/dev/provider/index.asciidoc b/docs/src/dev/provider/index.asciidoc
index b83357a..1c928f6 100644
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@ -1076,7 +1076,7 @@ as attempts to close long run jobs can occur more rapidly. If not provided, this
 
 Both the Standard and Session OpProcessors allow for Gremlin scripts to be submitted to the server. The
 `TraversalOpProcessor` however allows Gremlin `Bytecode` to be submitted to the server. Supporting this `OpProcessor`
-makes it possible for a link:https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/[Gremlin Language Variant]
+makes it possible for a link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[Gremlin Language Variant]
 to submit a `Traversal` directly to Gremlin Server in the native language of the GLV without having to use a script in
 a different language.
 
@@ -1154,7 +1154,7 @@ single alias).
 Gremlin Server supports link:https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer[SASL-based]
 authentication.  A SASL implementation provides a series of challenges and responses that a driver must comply with
 in order to authenticate.  Gremlin Server supports the "PLAIN" SASL mechanism, which is a cleartext
-password system, for all link:https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/[Gremlin Language Variants].
+password system, for all link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[Gremlin Language Variants].
 Other SASL mechanisms supported for selected clients are listed in the
 link:https://tinkerpop.apache.org/docs/x.y.z/reference/#security[security section of the Gremlin Server reference documentation].
 
diff --git a/docs/src/index.asciidoc b/docs/src/index.asciidoc
index 549cb6d..baf1f5b 100644
--- a/docs/src/index.asciidoc
+++ b/docs/src/index.asciidoc
@@ -63,8 +63,6 @@ Provides a detailed look at The Gremlin Console and how it can be used when work
 Identifies and explains the component parts of a Gremlin traversal.
 ^|image:gremlin-chef.png[width=125] |link:https://tinkerpop.apache.org/docs/x.y.z/recipes/[Gremlin Recipes] +
 A collection of best practices and common traversal patterns for Gremlin.
-^|image:gremlin-house-of-mirrors-cropped.png[width=200] |link:https://tinkerpop.apache.org/docs/x.y.z/tutorials/gremlin-language-variants/[Gremlin Language Variants] +
-Instructs developers on the approach to building a Gremlin variant in their native programming language.
 |image:gremlin-lab-coat.png[width=200] |link:http://sql2gremlin.com/[Sql2Gremlin] +
 Learn Gremlin using typical patterns found when querying data with SQL. (*external*)
 ^|image:gremlin-standing.png[width=125] |link:https://academy.datastax.com/resources/getting-started-graph-databases[Getting Started with Graph Databases] +
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index d8a140c..74edc8e 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -27,22 +27,21 @@ the programming language they intend to use. The choice of programming language
 architecture and design of the application and the choice itself may have limits imposed upon it by the chosen graph
 provider. For example, a <<connecting-rgp,Remote Gremlin Provider>> will require the selection of a driver to interact
 with it. On the other hand, a graph system that is designed for embedded use, like TinkerGraph, needs the Java
-Virtual Machine (JVM) environment so will require <<connecting-gremlin-server,Gremlin Server>>, if using a programming
-language that is not on the JVM and will further require driver selection.
+Virtual Machine (JVM) environment which is easily accessed with a JVM programming language. If however the programming
+language is not built for the JVM then it will require <<connecting-gremlin-server,Gremlin Server>> in the architecture
+as well.
 
 TinkerPop provides an array of drivers in different programming languages as a way to connect to a remote Gremlin
 Server or Remote Gremlin Provider. Drivers allow the developer to make requests to that remote system and get back
 results from the TinkerPop-enabled graphs hosted within. A driver can submit Gremlin strings and Gremlin bytecode
 over this sub-protocol. Gremlin strings are written in the scripting language made available by the remote system that
 the driver is connecting to (typically, Groovy-based). This connection approach is quite similar to what developers
-are likely familiar with when using JDBC and SQL. While it is familiar, it is not recommended and for TinkerPop it is
-considered an out-dated concept and is largely still present for the purpose of supporting applications that might
-still be using that method of interaction.
+are likely familiar with when using JDBC and SQL.
 
 The preferred approach is to use bytecode-based requests, which essentially allows the ability to craft Gremlin
 directly in the programming language of choice. As Gremlin makes use of two fundamental programming constructs:
 link:https://en.wikipedia.org/wiki/Function_composition[function composition] and
-link:https://en.wikipedia.org/wiki/Nested_function[function nesting]. it is possible to embed the Gremlin language
+link:https://en.wikipedia.org/wiki/Nested_function[function nesting], it is possible to embed the Gremlin language
 in any modern programming language. It is a far more natural way to program, because it enables IDE interaction,
 compile time checks, and language level checks that can help prevent errors prior to execution. The differences
 between these two approaches were outlined in the <<connecting-via-drivers,Connecting Via Drivers>> Section, which
@@ -65,10 +64,6 @@ between development languages can easily adopt the Gremlin variant for that lang
 
 image::gremlin-variant-architecture.png[width=650,float=left]
 
-NOTE: The information herein describes how to use the Gremlin language variants distributed
-with Apache TinkerPop. For information on how to build a Gremlin language variant, please review the
-link:https://tinkerpop.apache.org/docs/x.y.z/tutorials/gremlin-language-variants/[Gremlin Language Variants] tutorial.
-
 The following sections describe each language variant and driver that is officially TinkerPop a part of the project,
 provided more detailed information about usage, configuration and known limitations.
 
diff --git a/docs/src/reference/intro.asciidoc b/docs/src/reference/intro.asciidoc
index d6a85df..6d6a1c7 100644
--- a/docs/src/reference/intro.asciidoc
+++ b/docs/src/reference/intro.asciidoc
@@ -469,10 +469,11 @@ of this documentation, so be sure to consult their documentation for more inform
 [[basic-gremlin]]
 == Basic Gremlin
 
-The `GraphTraversalSource` is basically the connection to a graph instance. That graph instance might be
-<<connecting-embedded,embedded>>, hosted in <<connecting-gremlin-server,Gremlin Server>> or hosted in a
-<<connecting-rgp,RGP>>, but the `GraphTraversalSource` is agnostic to that. Assuming "g" is the `GraphTraversalSource`,
-getting data into the graph regardless of programming language or mode of operation is just some basic Gremlin:
+image:language-variants.png[width=300,float=right] The `GraphTraversalSource` is basically the connection to a graph
+instance. That graph instance might be <<connecting-embedded,embedded>>, hosted in
+<<connecting-gremlin-server,Gremlin Server>> or hosted in a <<connecting-rgp,RGP>>, but the `GraphTraversalSource` is
+agnostic to that. Assuming "g" is the `GraphTraversalSource`, getting data into the graph regardless of programming
+language or mode of operation is just some basic Gremlin:
 
 [gremlin-groovy]
 ----
diff --git a/docs/src/tutorials/gremlin-language-variants/index.asciidoc b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
index 39fa04f..d26544c 100644
--- a/docs/src/tutorials/gremlin-language-variants/index.asciidoc
+++ b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
@@ -14,595 +14,11 @@ 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.
 ////
-
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
 
-== Gremlin Language Variants
-
-Gremlin is an embeddable query language that can be represented using the constructs of a host programming language.
-Any programming language that supports link:https://en.wikipedia.org/wiki/Function_composition[function composition]
-(e.g. fluent chaining) and link:https://en.wikipedia.org/wiki/Nested_function[function nesting] (e.g. call stacks)
-can support Gremlin. Nearly every modern programming language is capable of meeting both requirements.
-With Gremlin, the distinction between a programming language and a query language is not as large as they
-have historically been. For instance, with Gremlin-Java, the developer is able to have their application code and their
-graph database queries at the same level of abstraction -- both written in Java. A simple example is presented below
-where the `MyApplication` Java class contains both application-level and database-level code written in Java.
-
 image::gremlin-house-of-mirrors.png[width=1024]
 
-WARNING: This is an advanced tutorial intended for experts knowledgeable in Gremlin in particular and TinkerPop in
-general. Moreover, the audience should understand advanced programming language concepts such as reflection,
-meta-programming, source code generation, and virtual machines.
-
-[source,java]
-----
-public class MyApplication {
-
-  public static void run(String[] args) {
-
-    // assumes args[0] is a configuration file location
-    Graph graph = GraphFactory.open(args[0]);
-    GraphTraversalSource g = traversal().withEmbedded(graph);
-
-    // assumes that args[1] and args[2] are range boundaries
-    Iterator<Map<String,Double>> result =
-      g.V().hasLabel("product").
-        order().by("unitPrice", asc).
-        range(Integer.valueOf(args[1]), Integer.valueOf(args[2])).
-        valueMap("name", "unitPrice")
-
-    while(result.hasNext()) {
-      Map<String,Double> map = result.next();
-      System.out.println(map.get("name") + " " + map.get("unitPrice"));
-    }
-  }
-}
-----
-
-In query languages like link:https://en.wikipedia.org/wiki/SQL[SQL], the user must construct a string representation of
-their query and submit it to the database for evaluation. This is because SQL cannot be expressed in Java as they use
-fundamentally different constructs in their expression. The same example above is presented below using SQL and the
-link:https://en.wikipedia.org/wiki/Java_Database_Connectivity[JDBC] interface. The take home point is that Gremlin does
-not exist outside the programming language in which it will be used. Gremlin was designed to be able to be
-embedded in any modern programming language and thus, always free from the complexities of string manipulation as seen
-in other database and analytics query languages.
-
-[source,java]
-----
-public class MyApplication {
-
-  public static void run(final String[] args) {
-
-    // assumes args[0] is a URI to the database
-    Connection connection = DriverManager.getConnection(args[0])
-    Statement statement = connection.createStatement();
-
-    // assumes that args[1] and args[2] are range boundaries
-    ResultSet result = statement.executeQuery(
-      "SELECT Products.ProductName, Products.UnitPrice \n" +
-      "  FROM (SELECT ROW_NUMBER() \n" +
-      "                   OVER ( \n" +
-      "                     ORDER BY UnitPrice) AS [ROW_NUMBER], \n" +
-      "                 ProductID \n" +
-      "            FROM Products) AS SortedProducts \n" +
-      "      INNER JOIN Products \n" +
-      "              ON Products.ProductID = SortedProducts.ProductID \n" +
-      "   WHERE [ROW_NUMBER] BETWEEN " + args[1] + " AND " + args[2] + " \n" +
-      "ORDER BY [ROW_NUMBER]"
-
-    while(result.hasNext()) {
-      result.next();
-      System.out.println(result.getString("Products.ProductName") + " " + result.getDouble("Products.UnitPrice"));
-    }
-  }
-}
-----
-
-The purpose of this tutorial is to explain how to develop a _Gremlin language variant_. That is, for those developers
-who are interested in supporting Gremlin in their native language and there currently does not exist a (good) Gremlin
-variant in their language, they can develop one for the Apache TinkerPop community (and their language community in
-general). In this tutorial, link:https://www.python.org/[Python] will serve as the host language and two typical
-implementation models will be presented.
-
-1. <<using-jython-and-the-jvm,**Using Jython and the JVM**>>: This is perhaps the easiest way to produce a Gremlin
-language variant. With link:https://www.jcp.org/en/jsr/detail?id=223[JSR-223], any language compiler written for the JVM
-can directly access the JVM and any of its libraries (including Gremlin-Java).
-
-2. <<using-python-and-remoteconnection,**Using Python and GremlinServer**>>: This model requires that there exist a Python
-class that mimics Gremlin-Java's `GraphTraversal` API. With each method call of this Python class, Gremlin `Bytecode` is
-generated which is ultimately translated into a Gremlin variant that can execute the traversal (e.g. Gremlin-Java).
-
-IMPORTANT: Apache TinkerPop's Gremlin-Java is considered the idiomatic, standard implementation of Gremlin.
-Any Gremlin language variant, regardless of the implementation model chosen, **must**, within the constraints of the
-host language, be in 1-to-1 correspondence with Gremlin-Java. This ensures that language variants are collectively
-consistent and easily leveraged by anyone versed in Gremlin.
-
-IMPORTANT: The "Gremlin-Python" presented in this tutorial is basic and provided to show the primary techniques used to
-construct a Gremlin language variant. Apache TinkerPop distributes with a full fledged
-link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-python[Gremlin-Python] variant that uses many of the
-techniques presented in this tutorial.
-
-[[language-drivers-vs-language-variants]]
-== Language Drivers vs. Language Variants
-
-Before discussing how to implement a Gremlin language variant in Python, it is necessary to understand two concepts
-related to Gremlin language development. There is a difference between a _language driver_ and a _language variant_
-and it is important that these two concepts (and their respective implementations) remain separate.
-
-=== Language Drivers
-
-image:language-drivers.png[width=375,float=right] A Gremlin language driver is a software library that is able to
-communicate with a TinkerPop-enabled graph system whether directly via the JVM or indirectly via
-link:https://tinkerpop.apache.org/docs/x.y.z/reference/#connecting-gremlin-server[Gremlin Server] Gremlin Server or some
-other link:https://tinkerpop.apache.org/docs/x.y.z/reference/#connecting-rgp[RemoteConnection] enabled graph system.
-Language drivers are responsible for submitting Gremlin traversals to a TinkerPop-enabled graph system and
-returning results to the developer that are within the developer's language's type system.
-For instance, resultant doubles should be coerced to floats in Python.
-
-This tutorial is not about language drivers, but about language variants. Moreover, community libraries should make
-this distinction clear and **should not** develop libraries that serve both roles. Language drivers will be useful to
-a collection of Gremlin variants within a language community -- able to support `GraphTraversal`-variants as well as
-also other link:https://en.wikipedia.org/wiki/Domain-specific_language[DSL]-variants (e.g. `SocialTraversal`).
-
-NOTE: `GraphTraversal` is a particular Gremlin domain-specific language (link:https://en.wikipedia.org/wiki/Domain-specific_language[DSL]),
-albeit the most popular and foundational DSL. If another DSL is created, then the same techniques discussed in this
-tutorial for `GraphTraversal` apply to `XXXTraversal`.
-
-=== Language Variants
-
-image:language-variants.png[width=375,float=right] A Gremlin language variant is a software library that allows a
-developer to write a Gremlin traversal within their native programming language. The language variant is responsible
-for creating Gremlin `Bytecode` that will ultimately be translated and compiled to a `Traversal` by a
-TinkerPop-enabled graph system.
-
-Every language variant, regardless of the implementation details, will have to account for the four core concepts below:
-
-1. `Graph` (**data**): The source of the graph data to be traversed and the interface which enables the creation of a
-`GraphTraversalSource` (via `traversal().withEmbedded(graph)`).
-
-2. `GraphTraversalSource` (**compiler**): This is the typical `g` reference. A `GraphTraversalSource` maintains the
-`withXXX()`-strategy methods as well as the "traversal spawn"-methods such as `V()`, `E()`, `addV()`, etc.
-A traversal source's registered `TraversalStrategies` determine how the submitted traversal will be ultimately
-evaluated.
-
-3. `GraphTraversal` (**function composition**): A graph traversal maintains the computational steps such as `out()`, `groupCount()`,
-`match()`, etc. This fluent interface supports method chaining and thus, a linear "left-to-right" representation of a
-traversal/query.
-
-4. `__` (**function nesting**) : The anonymous traversal class is used for passing a traversal as an argument to a
-parent step. For example, in `+repeat(__.out())+`, `+__.out()+` is an anonymous traversal passed to the traversal parent
-`repeat()`. Anonymous traversals enable the "top-to-bottom" representation of a traversal.
-
-5. `Bytecode` (**language agnostic encoding**): The source and traversal steps and their arguments are encoded in a
-language agnostic representation called Gremlin bytecode. This representation is a nested list of the form
-`[step,[args*]]*`.
-
-Both `GraphTraversal` and `+__+` define the structure of the Gremlin language. Gremlin is a _two-dimensional language_
-supporting linear, nested step sequences. Historically, many Gremlin language variants have failed to make the
-distinctions above clear and in doing so, either complicate their implementations or yield variants that are not in
-1-to-1 correspondence with Gremlin-Java. By keeping these concepts clear when designing a language variant, the
-construction of the Gremlin bytecode representation is easy.
-
-IMPORTANT: The term "Gremlin-Java" denotes the language that is defined by `GraphTraversalSource`, `GraphTraversal`,
-and `__`. These three classes exist in `org.apache.tinkerpop.gremlin.process.traversal.dsl.graph` and form the
-definitive representation of the Gremlin traversal language.
-
-== Gremlin-Jython and Gremlin-Python
-
-[[using-jython-and-the-jvm]]
-=== Using Jython and the JVM
-
-image:jython-logo.png[width=200,float=left,link="http://www.jython.org/"] link:http://www.jython.org/[Jython] provides a
-link:https://www.jcp.org/en/jsr/detail?id=223[JSR-223] `ScriptEngine` implementation that enables the evaluation of
-Python on the link:https://en.wikipedia.org/wiki/Java_virtual_machine[Java virtual machine]. In other words, Jython's
-virtual machine is not the standard link:https://wiki.python.org/moin/CPython[CPython] reference implementation
-distributed with most operating systems, but instead the JVM. The benefit of Jython is that Python code and classes
-can easily interact with the Java API and any Java packages on the `CLASSPATH`. In general, any JSR-223 Gremlin language
-variant is trivial to "implement."
-
-[source,python]
-----
-Jython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)
-[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_40
-Type "help", "copyright", "credits" or "license" for more information.
->>> import sys
-# this list is longer than displayed, including all jars in lib/, not just Apache TinkerPop jars
-# there is probably a more convenient way of importing jars in Jython though, at the time of writing, no better solution was found.
->>> sys.path.append("/usr/local/apache-gremlin-console-x.y.z-standalone/lib/gremlin-console-x.y.z.jar")
->>> sys.path.append("/usr/local/apache-gremlin-console-x.y.z-standalone/lib/gremlin-core-x.y.z.jar")
->>> sys.path.append("/usr/local/apache-gremlin-console-x.y.z-standalone/lib/gremlin-driver-x.y.z.jar")
->>> sys.path.append("/usr/local/apache-gremlin-console-x.y.z-standalone/lib/gremlin-shaded-x.y.z.jar")
->>> sys.path.append("/usr/local/apache-gremlin-console-x.y.z-standalone/ext/tinkergraph-gremlin/lib/tinkergraph-gremlin-x.y.z.jar")
-# import Java classes
->>> from org.apache.tinkerpop.gremlin.tinkergraph.structure import TinkerFactory
->>> from org.apache.tinkerpop.gremlin.process.traversal.dsl.graph import __
->>> from org.apache.tinkerpop.gremlin.process.traversal import *
->>> from org.apache.tinkerpop.gremlin.structure import *
-# create the toy "modern" graph and spawn a GraphTraversalSource
->>> graph = TinkerFactory.createModern()
->>> g = graph.traversal()
-# The Jython shell does not automatically iterate Iterators like the GremlinConsole
->>> g.V().hasLabel("person").out("knows").out("created")
-[GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,[knows],vertex), VertexStep(OUT,[created],vertex)]
-# toList() will do the iteration and return the results as a list
->>> g.V().hasLabel("person").out("knows").out("created").toList()
-[v[5], v[3]]
->>> g.V().repeat(__.out()).times(2).values("name").toList()
-[ripple, lop]
-# results can be interacted with using Python
->>> g.V().repeat(__.out()).times(2).values("name").toList()[0]
-u'ripple'
->>> g.V().repeat(__.out()).times(2).values("name").toList()[0][0:3].upper()
-u'RIP'
->>>
-----
-
-Most every JSR-223 `ScriptEngine` language will allow the developer to immediately interact with `GraphTraversal`.
-The benefit of this model is that nearly every major programming language has a respective `ScriptEngine`:
-link:https://en.wikipedia.org/wiki/Nashorn_(JavaScript_engine)[JavaScript], link:http://groovy-lang.org/[Groovy],
-link:http://www.scala-lang.org/[Scala], Lisp (link:https://clojure.org/[Clojure]), link:http://jruby.org/[Ruby], etc. A
-list of implementations is provided link:https://en.wikipedia.org/wiki/List_of_JVM_languages[here].
-
-==== Traversal Wrappers
-
-While it is possible to simply interact with Java classes in a `ScriptEngine` implementation, such Gremlin language
-variants will not leverage the unique features of the host language. It is for this reason that JVM-based language
-variants such as link:https://github.com/mpollmeier/gremlin-scala[Gremlin-Scala] were developed. Scala provides many
-syntax niceties not available in Java. To leverage these niceties, Gremlin-Scala "wraps" `GraphTraversal` in order to
-provide Scala-idiomatic extensions. Another example is Apache TinkerPop's Gremlin-Groovy which does the same via the
-link:https://tinkerpop.apache.org/docs/x.y.z/reference/#sugar-plugin[Sugar plugin], but uses
-link:http://groovy-lang.org/metaprogramming.html[meta-programming] instead of object wrapping, where "behind the
-scenes," Groovy meta-programming is doing object wrapping.
-
-The Jython example below uses Python meta-programming to add functionality to `GraphTraversal`. In particular, the
-`+__getitem__+` and `+__getattr__+` "magic methods" are leveraged.
-
-[source,python]
-----
-def getitem_bypass(self, index):
-  if isinstance(index,int):
-    return self.range(index,index+1)
-  elif isinstance(index,slice):
-    return self.range(index.start,index.stop)
-  else:
-    return TypeError('Index must be int or slice')");
-GraphTraversal.__getitem__ = getitem_bypass
-GraphTraversal.__getattr__ = lambda self, key: self.values(key)
-----
-
-The two methods `+__getitem__+` and `+__getattr__+` support Python _slicing_ and _object attribute interception_,
-respectively. In this way, the host language is able to use its native constructs in a meaningful way within a
-Gremlin traversal.
-
-IMPORTANT: Gremlin-Java serves as the standard/default representation of the Gremlin traversal language. Any Gremlin
-language variant **must** provide all the same functionality (methods) as `GraphTraversal`, but **can** extend it
-with host language specific constructs. This means that the extensions **must** compile to `GraphTraversal`-specific
-steps. A Gremlin language variant **should not** add steps/methods that do not exist in `GraphTraversal`. If an extension
-is desired, the language variant designer should submit a proposal to link:https://tinkerpop.apache.org[Apache TinkerPop]
-to have the extension added to a future release of Gremlin.
-
-[[using-python-and-remoteconnection]]
-=== Using Python and RemoteConnection
-
-image:python-logo.png[width=125,float=left,link="https://www.python.org/"] The JVM is a powerful piece of technology
-that has, over the years, become a meeting ground for developers from numerous language communities. However, not all
-applications will use the JVM. Given that Apache TinkerPop is a Java-framework, there must be a way for two different
-virtual machines to communicate traversals and their results. This section presents the second Gremlin language
-variant implementation model which does just that.
-
-NOTE: Apache TinkerPop is a JVM-based graph computing framework. Most graph databases and processors today are built
-on the JVM. This makes it easy for these graph system providers to implement Apache TinkerPop. However, TinkerPop is more
-than its graph API and tools -- it is also the Gremlin traversal machine and language. While Apache's Gremlin traversal
-machine was written for the JVM, its constructs are simple and can/should be ported to other VMs for those graph systems
-that are not JVM-based. A theoretical review of the concepts behind the Gremlin traversal machine is provided in
-link:http://arxiv.org/abs/1508.03843[this article].
-
-This section's Gremlin language variant design model does not leverage the JVM directly. Instead, it constructs a
-`Bytecode` representation of a `Traversal` that will ultimately be evaluated by `RemoteConnection` (e.g. GremlinServer).
-It is up to the language variant designer to choose a _language driver_ to use for submitting the generated bytecode and
-coercing its results. The language driver is the means by which, for this example, the CPython
-VM communicates with the JVM.
-
-[source,bash]
-----
-# sudo easy_install pip
-$ pip install gremlinpython
-----
-
-The Groovy source code below uses Java reflection to generate a Python class that is in 1-to-1 correspondence with
-Gremlin-Java.
-
-[source,groovy]
-----
-class GraphTraversalSourceGenerator {
-
-    public static void create(final String graphTraversalSourceFile) {
-
-        final StringBuilder pythonClass = new StringBuilder()
-
-        pythonClass.append("from .traversal import Traversal\n")
-        pythonClass.append("from .traversal import TraversalStrategies\n")
-        pythonClass.append("from .traversal import Bytecode\n")
-        pythonClass.append("from ..driver.remote_connection import RemoteStrategy\n")
-        pythonClass.append("from .. import statics\n\n")
-
-//////////////////////////
-// GraphTraversalSource //
-//////////////////////////
-        pythonClass.append(
-                """class GraphTraversalSource(object):
-  def __init__(self, graph, traversal_strategies, bytecode=None):
-    self.graph = graph
-    self.traversal_strategies = traversal_strategies
-    if bytecode is None:
-      bytecode = Bytecode()
-    self.bytecode = bytecode
-  def __repr__(self):
-    return "graphtraversalsource[" + str(self.graph) + "]"
-""")
-        GraphTraversalSource.getMethods(). // SOURCE STEPS
-                findAll { GraphTraversalSource.class.equals(it.returnType) }.
-                findAll {
-                    !it.name.equals("clone") &&
-                            !it.name.equals(TraversalSource.Symbols.withRemote)
-                }.
-                collect { SymbolHelper.toPython(it.name) }.
-                unique().
-                sort { a, b -> a <=> b }.
-                forEach { method ->
-                    pythonClass.append(
-                            """  def ${method}(self, *args):
-    source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
-    source.bytecode.add_source("${SymbolHelper.toJava(method)}", *args)
-    return source
-""")
-                }
-        pythonClass.append(
-                """  def withRemote(self, remote_connection):
-    source = GraphTraversalSource(self.graph, TraversalStrategies(self.traversal_strategies), Bytecode(self.bytecode))
-    source.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
-    return source
-""")
-        GraphTraversalSource.getMethods(). // SPAWN STEPS
-                findAll { GraphTraversal.class.equals(it.returnType) }.
-                collect { SymbolHelper.toPython(it.name) }.
-                unique().
-                sort { a, b -> a <=> b }.
-                forEach { method ->
-                    pythonClass.append(
-                            """  def ${method}(self, *args):
-    traversal = GraphTraversal(self.graph, self.traversal_strategies, Bytecode(self.bytecode))
-    traversal.bytecode.add_step("${SymbolHelper.toJava(method)}", *args)
-    return traversal
-""")
-                }
-        pythonClass.append("\n\n")
-
-////////////////////
-// GraphTraversal //
-////////////////////
-        pythonClass.append(
-                """class GraphTraversal(Traversal):
-  def __init__(self, graph, traversal_strategies, bytecode):
-    Traversal.__init__(self, graph, traversal_strategies, bytecode)
-  def __getitem__(self, index):
-    if isinstance(index, int):
-        return self.range(index, index + 1)
-    elif isinstance(index, slice):
-        return self.range(index.start, index.stop)
-    else:
-        raise TypeError("Index must be int or slice")
-  def __getattr__(self, key):
-    return self.values(key)
-""")
-        GraphTraversal.getMethods().
-                findAll { GraphTraversal.class.equals(it.returnType) }.
-                findAll { !it.name.equals("clone") }.
-                collect { SymbolHelper.toPython(it.name) }.
-                unique().
-                sort { a, b -> a <=> b }.
-                forEach { method ->
-                    pythonClass.append(
-                            """  def ${method}(self, *args):
-    self.bytecode.add_step("${SymbolHelper.toJava(method)}", *args)
-    return self
-""")
-                };
-        pythonClass.append("\n\n")
-
-////////////////////////
-// AnonymousTraversal //
-////////////////////////
-        pythonClass.append("class __(object):\n");
-        __.class.getMethods().
-                findAll { GraphTraversal.class.equals(it.returnType) }.
-                findAll { Modifier.isStatic(it.getModifiers()) }.
-                collect { SymbolHelper.toPython(it.name) }.
-                unique().
-                sort { a, b -> a <=> b }.
-                forEach { method ->
-                    pythonClass.append(
-                            """  @staticmethod
-  def ${method}(*args):
-    return GraphTraversal(None, None, Bytecode()).${method}(*args)
-""")
-                };
-        pythonClass.append("\n\n")
-        // add to gremlin.python.statics
-        __.class.getMethods().
-                findAll { GraphTraversal.class.equals(it.returnType) }.
-                findAll { Modifier.isStatic(it.getModifiers()) }.
-                findAll { !it.name.equals("__") }.
-                collect { SymbolHelper.toPython(it.name) }.
-                unique().
-                sort { a, b -> a <=> b }.
-                forEach {
-                    pythonClass.append("def ${it}(*args):\n").append("      return __.${it}(*args)\n\n")
-                    pythonClass.append("statics.add_static('${it}', ${it})\n\n")
-                }
-        pythonClass.append("\n\n")
-
-// save to a python file
-        final File file = new File(graphTraversalSourceFile);
-        file.delete()
-        pythonClass.eachLine { file.append(it + "\n") }
-    }
-}
-----
-
-When the above Groovy script is evaluated (e.g. in GremlinConsole), **Gremlin-Python** is born. The generated Python
-file is similar to the one available at
-link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py[graph_traversal.py].
-It is important to note that there is a bit more to Gremlin-Python in that there also exists Python implementations
-of `TraversalStrategies`, `Traversal`, `Bytecode`, etc. Please review the full implementation of Gremlin-Python
-link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-python/src/main/jython/gremlin_python[here].
-
-NOTE: In practice, TinkerPop uses the Groovy's `GStringTemplateEngine` to help with the code generation task described
-above and automates that generation as part of the standard build with Maven using the `gmavenplus-plugin`. See the
-`gremlin-python` link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-python/pom.xml[pom.xml] for more details.
-
-Of particular importance is Gremlin-Python's implementation of `Bytecode`.
-
-[source,python]
-----
-class Bytecode(object):
-  def __init__(self, bytecode=None):
-    self.source_instructions = []
-    self.step_instructions = []
-    self.bindings = {}
-    if bytecode is not None:
-      self.source_instructions = list(bytecode.source_instructions)
-      self.step_instructions = list(bytecode.step_instructions)
-
-  def add_source(self, source_name, *args):
-    newArgs = ()
-    for arg in args:
-      newArgs = newArgs + (self.__convertArgument(arg),)
-    self.source_instructions.append((source_name, newArgs))
-    return
-
-  def add_step(self, step_name, *args):
-    newArgs = ()
-    for arg in args:
-      newArgs = newArgs + (self.__convertArgument(arg),)
-    self.step_instructions.append((step_name, newArgs))
-    return
-
-  def __convertArgument(self,arg):
-    if isinstance(arg, Traversal):
-      self.bindings.update(arg.bytecode.bindings)
-      return arg.bytecode
-    elif isinstance(arg, tuple) and 2 == len(arg) and isinstance(arg[0], str):
-      self.bindings[arg[0]] = arg[1]
-      return Binding(arg[0],arg[1])
-    else:
-      return arg
-----
-
-As `GraphTraversalSource` and `GraphTraversal` are manipulated, the step-by-step instructions are written to `Bytecode`.
-This bytecode is simply a list of lists. For instance, `g.V(1).repeat(out('knows').hasLabel('person')).times(2).name` has
-the `Bytecode` form:
-
-[source,json]
-----
-[
- ["V", [1]],
- ["repeat", [[
-   ["out", ["knows"]]
-   ["hasLabel", ["person"]]]]]
- ["times", [2]]
- ["values", ["name"]]
-]
-----
-
-This nested list representation is ultimately converted by the language variant into link:https://tinkerpop.apache.org/docs/x.y.z/reference/#graphson[GraphSON]
-for serialization to a `RemoteConnection` such as GremlinServer.
-
-[source,bash]
-----
-$ bin/gremlin-server.sh install org.apache.tinkerpop gremlin-python x.y.z
-$ bin/gremlin-server.sh conf/gremlin-server-modern-py.yaml
-[INFO] GremlinServer -
-       \,,,/
-       (o o)
----oOOo-(3)-oOOo---
-
-[INFO] GremlinServer - Configuring Gremlin Server from conf/gremlin-server-modern-py.yaml
-[INFO] MetricManager - Configured Metrics Slf4jReporter configured with interval=180000ms and loggerName=org.apache.tinkerpop.gremlin.server.Settings$Slf4jReporterMetrics
-[INFO] GraphManager - Graph [graph] was successfully configured via [conf/tinkergraph-empty.properties].
-[INFO] ServerGremlinExecutor - Initialized Gremlin thread pool.  Threads in pool named with pattern gremlin-*
-[INFO] ServerGremlinExecutor - Initialized GremlinExecutor and configured ScriptEngines.
-[INFO] Logger - 56 attributes loaded from 90 stream(s) in 21ms, 56 saved, 1150 ignored: ["Ant-Version", "Archiver-Version", "Bnd-LastModified", "Boot-Class-Path", "Build-Jdk", "Build-Version", "Built-By", "Bundle-Activator", "Bundle-BuddyPolicy", "Bundle-ClassPath", "Bundle-Description", "Bundle-DocURL", "Bundle-License", "Bundle-ManifestVersion", "Bundle-Name", "Bundle-RequiredExecutionEnvironment", "Bundle-SymbolicName", "Bundle-Vendor", "Bundle-Version", "Can-Redefine-Classes", "Creat [...]
-[INFO] ServerGremlinExecutor - A GraphTraversalSource is now bound to [g] with graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
-[INFO] OpLoader - Adding the standard OpProcessor.
-[INFO] OpLoader - Adding the session OpProcessor.
-[INFO] OpLoader - Adding the traversal OpProcessor.
-[INFO] TraversalOpProcessor - Initialized cache for TraversalOpProcessor with size 1000 and expiration time of 600000 ms
-[INFO] GremlinServer - Executing start up LifeCycleHook
-[INFO] Logger$info - Executed once at startup of Gremlin Server.
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
-[INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
-[INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0 with org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1
-[INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0-stringd with org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1
-[INFO] GremlinServer$1 - Gremlin Server configured with worker thread pool of 1, gremlin pool of 8 and boss thread pool of 1.
-[INFO] GremlinServer$1 - Channel started at port 8182.
-----
-
-Within the CPython console, it is possible to evaluate the following.
-
-[source,python]
-----
-Python 2.7.2 (default, Oct 11 2012, 20:14:37)
-[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
-Type "help", "copyright", "credits" or "license" for more information.
->>> from gremlin_python import statics
->>> from gremlin_python.structure.graph import Graph
->>> from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
-# loading statics enables __.out() to be out() and P.gt() to be gt()
->>> statics.load_statics(globals())
->>> graph = Graph()
->>> g = graph.traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))
-# nested traversal with Python slicing and attribute interception extensions
->>> g.V().hasLabel("person").repeat(both()).times(2).name[0:2].toList()
-[u'marko', u'marko']
->>> g = g.withComputer()
->>> g.V().hasLabel("person").repeat(both()).times(2).name[0:2].toList()
-[u'peter', u'peter']
-# a complex, nested multi-line traversal
->>> g.V().match( \
-...     as_("a").out("created").as_("b"), \
-...     as_("b").in_("created").as_("c"), \
-...     as_("a").out("knows").as_("c")). \
-...   select("c"). \
-...   union(in_("knows"),out("created")). \
-...   name.toList()
-[u'ripple', u'marko', u'lop']
->>>
-----
-
-IMPORTANT: Learn more about Apache TinkerPop's distribution of Gremlin-Python link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-python[here].
-
-[[gremlin-language-variant-conventions]]
-== Gremlin Language Variant Conventions
-
-Every programming language is different and a Gremlin language variant must ride the fine line between leveraging the
-conventions of the host language and ensuring consistency with Gremlin-Java. A collection of conventions for navigating
-this dual-language bridge are provided.
-
-* If camelCase is not an accepted method naming convention in the host language, then the host language's convention can be used instead. For instance, in a Gremlin-Ruby implementation, `outE("created")` may be `out_e("created")`.
-* If Gremlin-Java step names conflict with the host language's reserved words, then a consistent amelioration should be used. For instance, in Python `as` is a reserved word, thus, Gremlin-Python uses `as_`.
-* If the host language does not use dot-notion for method chaining, then its method chaining convention should be used instead of going the route of operator overloading. For instance, a Gremlin-PHP implementation should do `$g->V()->out()`.
-* If a programming language does not support method overloading, then varargs and type introspection should be used. In Gremlin-Python, `*args` does just that.
-
-== Conclusion
-
-Gremlin is a simple language because it uses two fundamental programming language constructs: *function composition*
-and *function nesting*. Because of this foundation, it is relatively easy to implement Gremlin in any modern programming
-language. Two ways of doing this for the Python language were presented in this tutorial. One using Jython (on the JVM) and one using Python
-(on CPython). It is strongly recommended that language variant designers leverage (especially when not on the JVM)
-the reflection-based source code generation technique presented. This method ensures that the language
-variant is always in sync with the corresponding Apache TinkerPop Gremlin-Java release version. Moreover, it reduces
-the chance of missing methods or creating poorly implemented methods. While Gremlin is simple, there are nearly 200
-step variations in `GraphTraversal`. As such, mechanical means of host language embedding are strongly advised.
+Please see the link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[Reference Documentation]
+for more information on Gremlin Language Variants.
\ No newline at end of file