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 2019/09/04 12:10:17 UTC

[tinkerpop] branch master updated (cb6aeaf -> c951abe)

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

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


    from cb6aeaf  Merge branch 'tp34'
     add 29e6131  TINKERPOP-2046 Gremlin-Python: Add support for custom request headers in WebSocket request
     add 5ab245c  Updated changelog CTR
     new 02834ba  Merge branch 'tp33' into tp34
     new c951abe  Merge branch 'tp34'

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CHANGELOG.asciidoc                                                | 1 +
 docs/src/reference/gremlin-variants.asciidoc                      | 8 +++++++-
 gremlin-python/src/main/jython/gremlin_python/driver/client.py    | 7 +++++--
 .../src/main/jython/gremlin_python/driver/connection.py           | 5 +++--
 .../main/jython/gremlin_python/driver/driver_remote_connection.py | 6 ++++--
 .../src/main/jython/gremlin_python/driver/tornado/transport.py    | 5 ++++-
 gremlin-python/src/main/jython/gremlin_python/driver/transport.py | 2 +-
 7 files changed, 25 insertions(+), 9 deletions(-)


[tinkerpop] 01/02: Merge branch 'tp33' into tp34

Posted by sp...@apache.org.
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

commit 02834ba9c74f974c7d14ed0a8f3000007bd04912
Merge: 37a7214 5ab245c
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Wed Sep 4 08:09:59 2019 -0400

    Merge branch 'tp33' into tp34

 CHANGELOG.asciidoc                                                | 1 +
 docs/src/reference/gremlin-variants.asciidoc                      | 8 +++++++-
 gremlin-python/src/main/jython/gremlin_python/driver/client.py    | 7 +++++--
 .../src/main/jython/gremlin_python/driver/connection.py           | 5 +++--
 .../main/jython/gremlin_python/driver/driver_remote_connection.py | 6 ++++--
 .../src/main/jython/gremlin_python/driver/tornado/transport.py    | 5 ++++-
 gremlin-python/src/main/jython/gremlin_python/driver/transport.py | 2 +-
 7 files changed, 25 insertions(+), 9 deletions(-)

diff --cc docs/src/reference/gremlin-variants.asciidoc
index a9db173,c356019..41b1c47
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@@ -328,336 -66,156 +328,342 @@@ g.V().out("knows").map(Lambda.function(
  g.V().out("knows").sideEffect(Lambda.consumer("println it"))
  g.V().as("a").out("knows").as("b").select("b").by(Lambda.<Vertex,Integer>function("it.value('name').length()"))
  
 -[[gremlin-groovy]]
 -== Gremlin-Groovy
 +Finally, Gremlin `Bytecode` that includes lambdas requires that the traversal be processed by the
 +`ScriptEngine`. To avoid continued recompilation costs, it supports the encoding of bindings, which allow Gremlin
 +Server to cache traversals that will be reused over and over again save that some parameterization may change. Thus,
 +instead of translating, compiling, and then executing each submitted bytecode request, it is possible to simply
 +execute. To express bindings in Java, use `Bindings`.
  
 -image:gremlin-groovy-drawing.png[width=130,float=right] Apache TinkerPop's Gremlin-Groovy implements Gremlin within the
 -link:http://groovy.apache.org[Apache Groovy] language. As a JVM-based language variant, Gremlin-Groovy is backed by
 -Gremlin-Java constructs. Moreover, given its scripting nature, Gremlin-Groovy serves as the language of
 -<<gremlin-console,Gremlin Console>>.
 +[source,java]
 +----
 +b = Bindings.instance()
 +g.V(b.of('id',1)).out('created').values('name').map{t -> "name: " + t.get() }
 +g.V(b.of('id',4)).out('created').values('name').map{t -> "name: " + t.get() }
 +g.V(b.of('id',4)).out('created').values('name').getBytecode()
 +g.V(b.of('id',4)).out('created').values('name').getBytecode().getBindings()
 +cluster.close()
 +----
  
 -WARNING: In Groovy, `as`, `in`, and `not` are reserved words. Gremlin-Groovy does not allow these steps to be called
 -statically from the anonymous traversal `+__+` and therefore, must always be prefixed with `+__+`. For instance:
 -`+g.V().as('a').in().as('b').where(__.not(__.as('a').out().as('b')))+`
 +Both traversals are abstractly defined as `g.V(id).out('created').values('name').map{t -> "name: " + t.get() }` and
 +thus, the first submission can be cached for faster evaluation on the next submission.
  
 -[[gremlin-python]]
 -== Gremlin-Python
 +WARNING: It is generally advised to avoid lambda usage. Please consider <<a-note-on-lambdas,A Note On Lambdas>> for
 +more information.
  
 -image:gremlin-python-drawing.png[width=130,float=right] Apache TinkerPop's Gremlin-Python implements Gremlin within
 -the link:https://www.python.org/[Python] language and can be used on any Python virtual machine including the popular
 -link:https://en.wikipedia.org/wiki/CPython[CPython] machine. Python's syntax has the same constructs as Java including
 -"dot notation" for function chaining (`a.b.c`), round bracket function arguments (`a(b,c)`), and support for global
 -namespaces (`a(b())` vs `a(__.b())`). As such, anyone familiar with Gremlin-Java will immediately be able to work
 -with Gremlin-Python. Moreover, there are a few added constructs to Gremlin-Python that make traversals a bit more succinct.
 +=== Submitting Scripts
  
 -WARNING: In Python, `and`, `as`, `from`, `global`, `in`, `is`, `not`, and `or` are reserved words. Gremlin-Python simply
 -postfixes `+_+` to the end of these terms for their use with graph traversal. For instance: `g.V().as_('a').in_().as_('b').select('a','b')`.
 +WARNING: TinkerPop does not recommend submitting script-based requests and generally continues to support this feature
 +for legacy reasons and corner use cases which are still not completely addressed by the Gremlin language. Please
 +consider using bytecode-based requests instead when possible.
  
 -To install Gremlin-Python, use Python's link:https://en.wikipedia.org/wiki/Pip_(package_manager)[pip] package manager.
 +image:gremlin-java.png[width=175,float=left] TinkerPop comes equipped with a reference client for Java-based
 +applications.  It is referred to as `gremlin-driver`, which enables applications to send requests to Gremlin Server
 +and get back results.
  
 -[source,bash]
 -pip install gremlinpython
 +Gremlin scripts are sent to the server from a `Client` instance.  A `Client` is created as follows:
  
 -Gremlin-Python users will typically make use of the following classes.
 +[source,java]
 +----
 +Cluster cluster = Cluster.open();  <1>
 +Client client = cluster.connect(); <2>
 +----
  
 -[source,python]
 ->>> from gremlin_python import statics
 ->>> from gremlin_python.process.anonymous_traversal import traversal
 ->>> from gremlin_python.process.graph_traversal import __
 ->>> from gremlin_python.process.strategies import *
 ->>> from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
 +<1> Opens a reference to `localhost` - note that there are many configuration options available in defining a `Cluster` object.
 +<2> Creates a `Client` given the configuration options of the `Cluster`.
  
 -In Gremlin-Python there exists `GraphTraversalSource`, `GraphTraversal`, and `__` which mirror the respective classes in Gremlin-Java.
 -The `GraphTraversalSource` requires a driver in order to communicate with <<gremlin-server,GremlinServer>> (or any
 -<<connecting-via-remotegraph,`RemoteConnection`>>-enabled server). The `gremlin_python.driver.driver_remote_connection`
 -is provided with Apache TinkerPop's Gremlin-Python distribution.
 +Once a `Client` instance is ready, it is possible to issue some Gremlin Groovy scripts:
  
 -IMPORTANT: For developers wishing to provide another *driver implementation*, be sure to extend `RemoteConnection` in
 -`gremlin_python.driver` so it can then be used by Gremlin-Python's `GraphTraversal`.
 +[source,java]
 +----
 +ResultSet results = client.submit("[1,2,3,4]");  <1>
 +results.stream().map(i -> i.get(Integer.class) * 2);       <2>
  
 -When Gremlin Server is running, Gremlin-Python can communicate with Gremlin Server. The `conf/gremlin-server-modern-py.yaml`
 -configuration maintains a `GremlinJythonScriptEngine` as well as the appropriate serializers for communicating `Bytecode`.
 +CompletableFuture<List<Result>> results = client.submit("[1,2,3,4]").all();  <3>
  
 -IMPORTANT: Gremlin-Python is not compatible with GraphSON 1.0.
 +CompletableFuture<ResultSet> future = client.submitAsync("[1,2,3,4]"); <4>
  
 -[source,bash]
 +Map<String,Object> params = new HashMap<>();
 +params.put("x",4);
 +client.submit("[1,2,3,x]", params); <5>
  ----
 -$ 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] Logger - 51 attributes loaded from 40 stream(s) in 16ms, 51 saved, 614 ignored: ["Ant-Version", "Archiver-Version", "Bnd-LastModified", "Boot-Class-Path", "Build-Jdk", "Build-Version", "Built-By", "Bundle-ClassPath", "Bundle-Description", "Bundle-DocURL", "Bundle-License", "Bundle-ManifestVersion", "Bundle-Name", "Bundle-RequiredExecutionEnvironment", "Bundle-SymbolicName", "Bundle-Vendor", "Bundle-Version", "Can-Redefine-Classes", "Created-By", "DynamicImport-Package", "Eclipse- [...]
 -[INFO] ScriptEngines - Loaded gremlin-jython ScriptEngine
 -[INFO] ScriptEngines - Loaded gremlin-python ScriptEngine
 -[INFO] ScriptEngines - Loaded gremlin-groovy ScriptEngine
 -[INFO] GremlinExecutor - Initialized gremlin-groovy ScriptEngine with scripts/generate-modern.groovy
 -[INFO] ServerGremlinExecutor - Initialized GremlinExecutor and configured ScriptEngines.
 -[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 - Loading 'modern' graph data.
 -[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
 -[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo-stringd with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
 -[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] GremlinServer$1 - Gremlin Server configured with worker thread pool of 1, gremlin pool of 4 and boss thread pool of 1.
 -[INFO] GremlinServer$1 - Channel started at port 8182.
 +<1> Submits a script that simply returns a `List` of integers.  This method blocks until the request is written to
 +the server and a `ResultSet` is constructed.
 +<2> Even though the `ResultSet` is constructed, it does not mean that the server has sent back the results (or even
 +evaluated the script potentially).  The `ResultSet` is just a holder that is awaiting the results from the server.
 +In this case, they are streamed from the server as they arrive.
 +<3> Submit a script, get a `ResultSet`, then return a `CompletableFuture` that will be called when all results have been returned.
 +<4> Submit a script asynchronously without waiting for the request to be written to the server.
 +<5> Parameterized request are considered the most efficient way to send Gremlin to the server as they can be cached,
 +which will boost performance and reduce resources required on the server.
 +
 +==== Per Request Settings
 +
 +There are a number of overloads to `Client.submit()` that accept a `RequestOptions` object. The `RequestOptions`
 +provide a way to include options that are specific to the request made with the call to `submit()`. A good use-case for
 +this feature is to set a per-request override to the `scriptEvaluationTimeout` so that it only applies to the current
 +request.
 +
 +[source,java]
 +----
 +Cluster cluster = Cluster.open();
 +Client client = cluster.connect();
 +RequestOptions options = RequestOptions.build().timeout(500).create();
 +List<Result> result = client.submit("g.V()", options).all().get();
  ----
  
 -NOTE: The command to use `install` need only be executed once to gather `gremlin-python` dependencies into Gremlin Servers'
 -path. Future starts of Gremlin Server will not require that command.
 +==== Aliases
  
 -Within CPython console, a `GraphTraversalSource` is created from the anonymous `traversal()` method where the "g"
 -provided to the `DriverRemoteConnection` corresponds to the name of a `GraphTraversalSource` on the remote end.
 +Scripts submitted to Gremlin Server automatically have the globally configured `Graph` and `TraversalSource` instances
 +made available to them.  Therefore, if Gremlin Server configures two `TraversalSource` instances called "g1" and "g2"
 +a script can simply reference them directly as:
  
 -[source,python]
 ->>> g = traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))
 +[source,java]
 +client.submit("g1.V()")
 +client.submit("g2.V()")
  
 -When a traversal from the `GraphTraversalSource` is iterated, the traversal's `Bytecode` is sent over the wire
 -via the registered `RemoteConnection`. The bytecode is used to construct the equivalent traversal at the remote traversal source.
 -Moreover, typically the bytecode is analyzed to determine which language the bytecode should be translated to. If the traversal
 -does not contain lambdas, the remote location (e.g. Gremlin Server) will typically
 -use Gremlin-Java. If it has lambdas written in Groovy, it will use Gremlin-Groovy (e.g. `GremlinGroovyScriptEngine`).
 -Likewise, if it has lambdas represented in Python, it will use Gremlin-Python (e.g. `GremlinJythonScriptEngine`).
 +While this is an acceptable way to submit scripts, it has the downside of forcing the client to encode the server-side
 +variable name directly into the script being sent.  If the server configuration ever changed such that "g1" became
 +"g100", the client-side code might have to see a significant amount of change.  Decoupling the script code from the
 +server configuration can be managed by the `alias` method on `Client` as follows:
  
 -IMPORTANT: Gremlin-Python's `Traversal` class supports the standard Gremlin methods such as `next()`, `nextTraverser()`,
 -`toSet()`, `toList()`, etc. Such "terminal" methods trigger the evaluation of the traversal.
 +[source,java]
 +Client g1Client = client.alias("g1")
 +Client g2Client = client.alias("g2")
 +g1Client.submit("g.V()")
 +g2Client.submit("g.V()")
  
 -=== RemoteConnection Submission
 +The above code demonstrates how the `alias` method can be used such that the script need only contain a reference
 +to "g" and "g1" and "g2" are automatically rebound into "g" on the server-side.
  
 -There are various ways to submit a traversal to a `RemoteConnection`. Just as in Gremlin-Java, there are various
 -"terminal/action methods" off of `Traversal`.
 +[[gremlin-java-dsl]]
 +=== Domain Specific Languages
  
 -* `Traversal.next()`
 -* `Traversal.nextTraverser()`
 -* `Traversal.toList()`
 -* `Traversal.toSet()`
 -* `Traversal.iterate()`
 +Creating a <<dsl,Domain Specific Language>> (DSL) in Java requires the `@GremlinDsl` Java annotation in `gremlin-core`.
 +This annotation should be applied to a "DSL interface" that extends `GraphTraversal.Admin`:
  
 -If you need to send additional headers in the websockets connection, you can pass an optional `headers` parameter
 -to the `DriverRemoteConnection` constructor.
 +[source,java]
 +----
 +@GremlinDsl
 +public interface SocialTraversalDsl<S, E> extends GraphTraversal.Admin<S, E> {
 +}
 +----
  
 -[source,python]
 -g = traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g',headers={'Header':'Value'}))
 +IMPORTANT: The name of the DSL interface should be suffixed with "TraversalDSL". All characters in the interface name
 +before that become the "name" of the DSL.
  
 +In this interface, define the methods that the DSL will be composed of:
  
 -=== Gremlin-Python Sugar
 +[source,java]
 +----
 +@GremlinDsl
 +public interface SocialTraversalDsl<S, E> extends GraphTraversal.Admin<S, E> {
 +    public default GraphTraversal<S, Vertex> knows(String personName) {
 +        return out("knows").hasLabel("person").has("name", personName);
 +    }
 +
 +    public default <E2 extends Number> GraphTraversal<S, E2> youngestFriendsAge() {
 +        return out("knows").hasLabel("person").values("age").min();
 +    }
 +
 +    public default GraphTraversal<S, Long> createdAtLeast(int number) {
 +        return outE("created").count().is(P.gte(number));
 +    }
 +}
 +----
  
 -Python supports meta-programming and operator overloading. There are three uses of these techniques in Gremlin-Python that
 -makes traversals a bit more concise.
 +IMPORTANT: Follow the TinkerPop convention of using `<S,E>` in naming generics as those conventions are taken into
 +account when generating the anonymous traversal class. The processor attempts to infer the appropriate type parameters
 +when generating the anonymous traversal class. If it cannot do it correctly, it is possible to avoid the inference by
 +using the `GremlinDsl.AnonymousMethod` annotation on the DSL method. It allows explicit specification of the types to
 +use.
  
 -[gremlin-python,modern]
 +The `@GremlinDsl` annotation is used by the link:https://docs.oracle.com/javase/8/docs/api/index.html?javax/annotation/processing/Processor.html[Java Annotation Processor]
 +to generate the boilerplate class structure required to properly use the DSL within the TinkerPop framework. These
 +classes can be generated and maintained by hand, but it would be time consuming, monotonous and error-prone to do so.
 +Typically, the Java compilation process is automatically configured to detect annotation processors on the classpath
 +and will automatically use them when found. If that does not happen, it may be necessary to make configuration changes
 +to the build to allow for the compilation process to be aware of the following `javax.annotation.processing.Processor`
 +implementation:
 +
 +[source,java]
  ----
 -g.V().both()[1:3].toList()
 -g.V().both()[1].toList()
 -g.V().both().name.toList()
 +org.apache.tinkerpop.gremlin.process.traversal.dsl.GremlinDslProcessor
 +----
 +
 +The annotation processor will generate several classes for the DSL:
 +
 +* `SocialTraversal` - A `Traversal` interface that extends the `SocialTraversalDsl` proxying methods to its underlying
 +interfaces (such as `GraphTraversal`) to instead return a `SocialTraversal`
 +* `DefaultSocialTraversal` - A default implementation of `SocialTraversal` (typically not used directly by the user)
 +* `SocialTraversalSource` - Spawns `DefaultSocialTraversal` instances.
 +* `__` - Spawns anonymous `DefaultSocialTraversal` instances.
 +
 +Using the DSL then just involves telling the `Graph` to use it:
 +
 +[source,java]
 +----
 +SocialTraversalSource social = graph.traversal(SocialTraversalSource.class);
 +social.V().has("name","marko").knows("josh");
 +----
 +
 +The `SocialTraversalSource` can also be customized with DSL functions. As an additional step, include a class that
 +extends from `GraphTraversalSource` and with a name that is suffixed with "TraversalSourceDsl". Include in this class,
 +any custom methods required by the DSL:
 +
 +[source,java]
 +----
 +public class SocialTraversalSourceDsl extends GraphTraversalSource {
 +
 +    public SocialTraversalSourceDsl(Graph graph, TraversalStrategies traversalStrategies) {
 +        super(graph, traversalStrategies);
 +    }
 +
 +    public SocialTraversalSourceDsl(Graph graph) {
 +        super(graph);
 +    }
 +
 +    public GraphTraversal<Vertex, Vertex> persons(String... names) {
 +        GraphTraversalSource clone = this.clone();
 +
 +        // Manually add a "start" step for the traversal in this case the equivalent of V(). GraphStep is marked
 +        // as a "start" step by passing "true" in the constructor.
 +        clone.getBytecode().addStep(GraphTraversal.Symbols.V);
 +        GraphTraversal<Vertex, Vertex> traversal = new DefaultGraphTraversal<>(clone);
 +        traversal.asAdmin().addStep(new GraphStep<>(traversal.asAdmin(), Vertex.class, true));
 +
 +        traversal = traversal.hasLabel("person");
 +        if (names.length > 0) traversal = traversal.has("name", P.within(names));
 +
 +        return traversal;
 +    }
 +}
 +----
 +
 +Then, back in the `SocialTraversal` interface, update the `GremlinDsl` annotation with the `traversalSource` argument
 +to point to the fully qualified class name of the `SocialTraversalSourceDsl`:
 +
 +[source,java]
 +----
 +@GremlinDsl(traversalSource = "com.company.SocialTraversalSourceDsl")
 +public interface SocialTraversalDsl<S, E> extends GraphTraversal.Admin<S, E> {
 +    ...
 +}
  ----
  
 -=== Static Enums and Methods
 +It is then possible to use the `persons()` method to start traversals:
 +
 +[source,java]
 +----
 +SocialTraversalSource social = graph.traversal(SocialTraversalSource.class);
 +social.persons("marko").knows("josh");
 +----
 +
 +NOTE: Using Maven, as shown in the `gremlin-archetype-dsl` module, makes developing DSLs with the annotation processor
 +straightforward in that it sets up appropriate paths to the generated code automatically.
 +
 +anchor:java-application-examples[]
 +[[gremlin-archetypes]]
 +=== Application Examples
 +
 +The available link:https://maven.apache.org/guides/introduction/introduction-to-archetypes.html[Maven archetypes] are
 +as follows:
 +
 +* `gremlin-archetype-dsl` - An example project that demonstrates how to build Domain Specific Languages with Gremlin
 +in Java.
 +* `gremlin-archetype-server` - An example project that demonstrates the basic structure of a
 +<<gremlin-server,Gremlin Server>> project, how to connect with the Gremlin Driver, and how to embed Gremlin Server in
 +a testing framework.
 +* `gremlin-archetype-tinkergraph` - A basic example of how to structure a TinkerPop project with Maven.
  
 -Gremlin has various tokens (e.g. `T`, `P`, `Order`, `Operator`, etc.) that are represented in Gremlin-Python as Python `Enums`.
 +Use Maven to generate these example projects with a command like:
 +
 +[source,shell]
 +$ mvn archetype:generate -DarchetypeGroupId=org.apache.tinkerpop -DarchetypeArtifactId=gremlin-archetype-server \
 +      -DarchetypeVersion=x.y.z -DgroupId=com.my -DartifactId=app -Dversion=0.1 -DinteractiveMode=false
 +
 +This command will generate a new Maven project in a directory called "app" with a `pom.xml` specifying a `groupId` of
 +`com.my`. Please see the `README.asciidoc` in the root of each generated project for information on how to build and
 +execute it.
 +
 +[[gremlin-groovy]]
 +== Gremlin-Groovy
 +
 +image:gremlin-groovy-drawing.png[width=130,float=right] Apache TinkerPop's Gremlin-Groovy implements Gremlin within the
 +link:http://groovy.apache.org[Apache Groovy] language. As a JVM-based language variant, Gremlin-Groovy is backed by
 +Gremlin-Java constructs. Moreover, given its scripting nature, Gremlin-Groovy serves as the language of
 +<<gremlin-console,Gremlin Console>> and <<gremlin-server,Gremlin Server>>.
 +
 +[source,groovy]
 +----
 +compile group: 'org.apache.tinkerpop', name: 'gremlin-core', version: '3.3.4'
 +compile group: 'org.apache.tinkerpop', name: 'gremlin-driver', version: '3.3.4'
- ---- 
++----
 +
 +[[gremlin-groovy-differences]]
 +=== Differences
 +
 +In Groovy, `as`, `in`, and `not` are reserved words. Gremlin-Groovy does not allow these steps to be called
 +statically from the anonymous traversal `+__+` and therefore, must always be prefixed with `+__.+` For instance:
 +`+g.V().as('a').in().as('b').where(__.not(__.as('a').out().as('b')))+`
 +
 +[[gremlin-python]]
 +== Gremlin-Python
 +
 +image:gremlin-python-drawing.png[width=130,float=right] Apache TinkerPop's Gremlin-Python implements Gremlin within
 +the link:https://www.python.org/[Python] language and can be used on any Python virtual machine including the popular
 +link:https://en.wikipedia.org/wiki/CPython[CPython] machine. Python's syntax has the same constructs as Java including
 +"dot notation" for function chaining (`a.b.c`), round bracket function arguments (`a(b,c)`), and support for global
 +namespaces (`a(b())` vs `a(__.b())`). As such, anyone familiar with Gremlin-Java will immediately be able to work
 +with Gremlin-Python. Moreover, there are a few added constructs to Gremlin-Python that make traversals a bit more
 +succinct.
 +
 +To install Gremlin-Python, use Python's link:https://en.wikipedia.org/wiki/Pip_(package_manager)[pip] package manager.
 +
 +[source,bash]
 +pip install gremlinpython
 +
 +=== Connecting
 +
 +The pattern for connecting is described in <<connecting-gremlin,Connecting Gremlin>> and it basically distills down to
 +creating a `GraphTraversalSource`. A `GraphTraversalSource` is created from the anonymous `traversal()` method where
 +the "g" provided to the `DriverRemoteConnection` corresponds to the name of a `GraphTraversalSource` on the remote end.
 +
 +[source,python]
 +g = traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))
 +
++If you need to send additional headers in the websockets connection, you can pass an optional `headers` parameter
++to the `DriverRemoteConnection` constructor.
+ 
+ [source,python]
 ->>> from gremlin_python.process.traversal import T
 ->>> from gremlin_python.process.traversal import Order
 ->>> from gremlin_python.process.traversal import Cardinality
 ->>> from gremlin_python.process.traversal import Column
 ->>> from gremlin_python.process.traversal import Direction
 ->>> from gremlin_python.process.traversal import Operator
 ->>> from gremlin_python.process.traversal import P
 ->>> from gremlin_python.process.traversal import Pop
 ->>> from gremlin_python.process.traversal import Scope
 ->>> from gremlin_python.process.traversal import Barrier
++g = traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g',headers={'Header':'Value'}))
++
 +[[python-imports]]
 +=== Common Imports
 +
 +There are a number of classes, functions and tokens that are typically used with Gremlin. The following imports
 +provide most of the typical functionality required to use Gremlin:
 +
 +[source,python]
 +----
 +from gremlin_python import statics
 +from gremlin_python.process.anonymous_traversal import traversal
 +from gremlin_python.process.graph_traversal import __
 +from gremlin_python.process.strategies import *
 +from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
 +from gremlin_python.process.traversal import T
 +from gremlin_python.process.traversal import Order
 +from gremlin_python.process.traversal import Cardinality
 +from gremlin_python.process.traversal import Column
 +from gremlin_python.process.traversal import Direction
 +from gremlin_python.process.traversal import Operator
 +from gremlin_python.process.traversal import P
 +from gremlin_python.process.traversal import Pop
 +from gremlin_python.process.traversal import Scope
 +from gremlin_python.process.traversal import Barrier
 +from gremlin_python.process.traversal import Bindings
 +from gremlin_python.process.traversal import WithOptions
 +----
  
  These can be used analogously to how they are used in Gremlin-Java.
  


[tinkerpop] 02/02: Merge branch 'tp34'

Posted by sp...@apache.org.
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

commit c951abe4a80a3df59e46f70c8265100f00cf22a3
Merge: cb6aeaf 02834ba
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Wed Sep 4 08:10:06 2019 -0400

    Merge branch 'tp34'

 CHANGELOG.asciidoc                                                | 1 +
 docs/src/reference/gremlin-variants.asciidoc                      | 8 +++++++-
 gremlin-python/src/main/jython/gremlin_python/driver/client.py    | 7 +++++--
 .../src/main/jython/gremlin_python/driver/connection.py           | 5 +++--
 .../main/jython/gremlin_python/driver/driver_remote_connection.py | 6 ++++--
 .../src/main/jython/gremlin_python/driver/tornado/transport.py    | 5 ++++-
 gremlin-python/src/main/jython/gremlin_python/driver/transport.py | 2 +-
 7 files changed, 25 insertions(+), 9 deletions(-)