.. 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.

=================================
Apache TinkerPop - Gremlin Python
=================================

`Apache TinkerPop™ <https://tinkerpop.apache.org>`_
is a graph computing framework for both graph databases (OLTP) and
graph analytic systems (OLAP). `Gremlin <https://tinkerpop.apache.org/gremlin.html>`_
is the graph traversal language of
TinkerPop. It can be described as a functional, data-flow language that enables users to succinctly express complex
traversals on (or queries of) their application's property graph.

Gremlin-Python implements Gremlin within the Python language and can be used on any Python virtual machine including
the popular 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.

Gremlin-Python is designed to connect to a "server" that is hosting a TinkerPop-enabled graph system. That "server"
could be `Gremlin Server <https://tinkerpop.apache.org/docs/current/reference/#gremlin-server>`_ or a
`remote Gremlin provider <https://tinkerpop.apache.org/docs/current/reference/#connecting-rgp>`_ that exposes
protocols by which Gremlin-Python can connect.

A typical connection to a server running on "localhost" that supports the Gremlin Server protocol using websockets
from the Python shell looks like this:

    >>> from gremlin_python.process.anonymous_traversal import traversal
    >>> from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
    >>> g = traversal().with_remote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))

Once "g" has been created using a connection, it is then possible to start writing Gremlin traversals to query the
remote graph:

    >>> g.V().both()[1:3].to_list()
    [v[2], v[4]]
    >>> g.V().both()[1].to_list()
    [v[2]]
    >>> g.V().both().name.to_list()
    [lop, vadas, josh, marko, marko, josh, peter, ripple, lop, marko, josh, lop]

-----------------
Sample Traversals
-----------------

The Gremlin language allows users to write highly expressive graph traversals and has a broad list of functions that
cover a wide body of features. The `Reference Documentation <https://tinkerpop.apache.org/docs/current/reference/#graph-traversal-steps>`_
describes these functions and other aspects of the TinkerPop ecosystem including some specifics on
`Gremlin in Python <https://tinkerpop.apache.org/docs/current/reference/#gremlin-python>`_ itself. Most of the
examples found in the documentation use Groovy language syntax in the
`Gremlin Console <https://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/>`_.
For the most part, these examples should generally translate to Python with
`some modification <https://tinkerpop.apache.org/docs/current/reference/#gremlin-python-differences>`_. Given the
strong correspondence between canonical Gremlin in Java and its variants like Python, there is a limited amount of
Python-specific documentation and examples. This strong correspondence among variants ensures that the general
Gremlin reference documentation is applicable to all variants and that users moving between development languages can
easily adopt the Gremlin variant for that language.

Create Vertex
^^^^^^^^^^^^^

.. code:: python

    from gremlin_python.process.traversal import T
    from gremlin_python.process.traversal import Cardinality

    id = T.id
    single = Cardinality.single

    def create_vertex(self, vid, vlabel):
        # default database cardinality is used when Cardinality argument is not specified
        g.add_v(vlabel).property(id, vid). \
          property(single, 'name', 'Apache'). \
          property('lastname', 'Tinkerpop'). \
          next()

Find Vertices
^^^^^^^^^^^^^

.. code:: python

    def list_all(self, limit=500):
        g.V().limit(limit).element_map().to_list()

    def find_vertex(self, vid):
        g.V(vid).element_map().next()

    def list_by_label_name(self, vlabel, name):
        g.V().has(vlabel, 'name', name).element_map().to_list()

Update Vertex
^^^^^^^^^^^^^

.. code:: python

    from gremlin_python.process.traversal import Cardinality

    single = Cardinality.single

    def update_vertex(self, vid, name):
        g.V(vid).property(single, 'name', name).next()

NOTE that versions suffixed with "rc" are considered release candidates (i.e. pre-alpha, alpha, beta, etc.) and
thus for early testing purposes only. These releases are not suitable for production.