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

andreac pushed a commit to branch 3.7-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/3.7-dev by this push:
     new 2cd2748aa4 Integrate Python driver examples into automated build 
process (#3231)
2cd2748aa4 is described below

commit 2cd2748aa408854edb004f8c21836432e28619b6
Author: kirill-stepanishin <[email protected]>
AuthorDate: Thu Nov 20 16:53:35 2025 -0800

    Integrate Python driver examples into automated build process (#3231)
    
    Integrates Python Gremlin examples into CI to ensure they remain functional 
in future releases. Examples now execute automatically after integration tests 
and fail the build if broken.
    
    Changes Made
    - Added example execution to gremlin-python-integration-tests container in 
docker-compose.yml
    - Made server URLs configurable via environment variables (replaces 
hardcoded localhost:8182)
    - Added configurable vertex labels and targeted cleanup using has_label()
    - Added graph binding detection - uses gmodern in CI, g locally for proper 
environment handling
---
 CHANGELOG.asciidoc                                 |  1 +
 gremlin-examples/gremlin-python/basic_gremlin.py   | 14 +++---
 gremlin-examples/gremlin-python/connections.py     | 32 +++++++------
 gremlin-python/docker-compose.yml                  |  8 +++-
 .../src/main/python/examples/basic_gremlin.py      | 16 ++++---
 .../src/main/python/examples/connections.py        | 53 ++++++++++++++++------
 .../src/main/python/examples/modern_traversals.py  | 12 ++++-
 7 files changed, 92 insertions(+), 44 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 72b4455741..b292f8939a 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -22,6 +22,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 [[release-3-7-6]]
 === TinkerPop 3.7.6 (NOT OFFICIALLY RELEASED YET)
+* Integrated Python driver examples into automated build process to ensure 
examples remain functional.
 
 [[release-3-7-5]]
 === TinkerPop 3.7.5 (Release Date: November 12, 2025)
diff --git a/gremlin-examples/gremlin-python/basic_gremlin.py 
b/gremlin-examples/gremlin-python/basic_gremlin.py
index 256ed98441..c351270de8 100644
--- a/gremlin-examples/gremlin-python/basic_gremlin.py
+++ b/gremlin-examples/gremlin-python/basic_gremlin.py
@@ -23,15 +23,17 @@ from gremlin_python.process.anonymous_traversal import 
traversal
 from gremlin_python.process.strategies import *
 from gremlin_python.driver.driver_remote_connection import 
DriverRemoteConnection
 
+VERTEX_LABEL = 'person'
 
 def main():
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
+    server_url = 'ws://localhost:8182/gremlin'
+    rc = DriverRemoteConnection(server_url, 'g')
     g = traversal().with_remote(rc)
 
     # basic Gremlin: adding and retrieving data
-    v1 = g.add_v('person').property('name', 'marko').next()
-    v2 = g.add_v('person').property('name', 'stephen').next()
-    v3 = g.add_v('person').property('name', 'vadas').next()
+    v1 = g.add_v(VERTEX_LABEL).property('name', 'marko').next()
+    v2 = g.add_v(VERTEX_LABEL).property('name', 'stephen').next()
+    v3 = g.add_v(VERTEX_LABEL).property('name', 'vadas').next()
 
     # be sure to use a terminating step like next() or iterate() so that the 
traversal "executes"
     # iterate() does not return any data and is used to just generate 
side-effects (i.e. write data to the database)
@@ -39,11 +41,11 @@ def main():
     g.V(v1).add_e('knows').to(v3).property('weight', 0.75).iterate()
 
     # retrieve the data from the "marko" vertex
-    marko = g.V().has('person', 'name', 'marko').values('name').next()
+    marko = g.V().has(VERTEX_LABEL, 'name', 'marko').values('name').next()
     print("name: " + marko)
 
     # find the "marko" vertex and then traverse to the people he "knows" and 
return their data
-    people_marko_knows = g.V().has('person', 'name', 
'marko').out('knows').values('name').to_list()
+    people_marko_knows = g.V().has(VERTEX_LABEL, 'name', 
'marko').out('knows').values('name').to_list()
     for person in people_marko_knows:
         print("marko knows " + person)
 
diff --git a/gremlin-examples/gremlin-python/connections.py 
b/gremlin-examples/gremlin-python/connections.py
index f268e6c27d..9997a181eb 100644
--- a/gremlin-examples/gremlin-python/connections.py
+++ b/gremlin-examples/gremlin-python/connections.py
@@ -24,6 +24,7 @@ from gremlin_python.process.strategies import *
 from gremlin_python.driver.driver_remote_connection import 
DriverRemoteConnection
 from gremlin_python.driver.serializer import GraphBinarySerializersV1
 
+VERTEX_LABEL = 'connection'
 
 def main():
     with_remote()
@@ -40,15 +41,13 @@ def with_remote():
     #
     # which starts it in "console" mode with an empty in-memory TinkerGraph 
ready to go bound to a
     # variable named "g" as referenced in the following line.
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
+    server_url = 'ws://localhost:8182/gremlin'
+    rc = DriverRemoteConnection(server_url, 'g')
     g = traversal().with_remote(rc)
 
-    # drop existing vertices
-    g.V().drop().iterate()
-
     # simple query to verify connection
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     # cleanup
@@ -57,11 +56,12 @@ def with_remote():
 
 # connecting with plain text authentication
 def with_auth():
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g', 
username='stephen', password='password')
+    server_url = 'ws://localhost:8182/gremlin'
+    rc = DriverRemoteConnection(server_url, 'g', username='stephen', 
password='password')
     g = traversal().with_remote(rc)
 
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     rc.close()
@@ -69,11 +69,12 @@ def with_auth():
 
 # connecting with Kerberos SASL authentication
 def with_kerberos():
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g', 
kerberized_service='[email protected]')
+    server_url = 'ws://localhost:8182/gremlin'
+    rc = DriverRemoteConnection(server_url, 'g', 
kerberized_service='[email protected]')
     g = traversal().with_remote(rc)
 
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     rc.close()
@@ -81,8 +82,9 @@ def with_kerberos():
 
 # connecting with customized configurations
 def with_configs():
+    server_url = 'ws://localhost:8182/gremlin'
     rc = DriverRemoteConnection(
-        'ws://localhost:8182/gremlin', 'g',
+        server_url, 'g',
         username="", password="", kerberized_service='',
         message_serializer=GraphBinarySerializersV1(), graphson_reader=None,
         graphson_writer=None, headers=None, session=None,
@@ -90,8 +92,8 @@ def with_configs():
     )
     g = traversal().with_remote(rc)
 
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     rc.close()
diff --git a/gremlin-python/docker-compose.yml 
b/gremlin-python/docker-compose.yml
index 9879ae8a0c..8b9ae9e2ac 100644
--- a/gremlin-python/docker-compose.yml
+++ b/gremlin-python/docker-compose.yml
@@ -72,7 +72,13 @@ services:
       && pip install .[test,kerberos]
       && pytest
       && radish -f dots -e -t -b ./radish ./gremlin-test 
--user-data='serializer=application/vnd.gremlin-v3.0+json'
-      && radish -f dots -e -t -b ./radish ./gremlin-test 
--user-data='serializer=application/vnd.graphbinary-v1.0';
+      && radish -f dots -e -t -b ./radish ./gremlin-test 
--user-data='serializer=application/vnd.graphbinary-v1.0'
+      && pip install .
+      && echo 'Running examples...'
+      && python3 examples/basic_gremlin.py
+      && python3 examples/connections.py
+      && python3 examples/modern_traversals.py
+      && echo 'All examples completed successfully';
       EXIT_CODE=$$?; chown -R `stat -c "%u:%g" .` .; exit $$EXIT_CODE"
     depends_on:
       gremlin-server-test-python:
diff --git a/gremlin-python/src/main/python/examples/basic_gremlin.py 
b/gremlin-python/src/main/python/examples/basic_gremlin.py
index 256ed98441..2c08621896 100644
--- a/gremlin-python/src/main/python/examples/basic_gremlin.py
+++ b/gremlin-python/src/main/python/examples/basic_gremlin.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import sys
+import os
 
 sys.path.append("..")
 
@@ -23,15 +24,18 @@ from gremlin_python.process.anonymous_traversal import 
traversal
 from gremlin_python.process.strategies import *
 from gremlin_python.driver.driver_remote_connection import 
DriverRemoteConnection
 
+VERTEX_LABEL = os.getenv('VERTEX_LABEL', 'person')
 
 def main():
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
+    # if there is a port placeholder in the env var then we are running with 
docker so set appropriate port 
+    server_url = os.getenv('GREMLIN_SERVER_URL', 
'ws://localhost:8182/gremlin').format(45940)
+    rc = DriverRemoteConnection(server_url, 'g')
     g = traversal().with_remote(rc)
 
     # basic Gremlin: adding and retrieving data
-    v1 = g.add_v('person').property('name', 'marko').next()
-    v2 = g.add_v('person').property('name', 'stephen').next()
-    v3 = g.add_v('person').property('name', 'vadas').next()
+    v1 = g.add_v(VERTEX_LABEL).property('name', 'marko').next()
+    v2 = g.add_v(VERTEX_LABEL).property('name', 'stephen').next()
+    v3 = g.add_v(VERTEX_LABEL).property('name', 'vadas').next()
 
     # be sure to use a terminating step like next() or iterate() so that the 
traversal "executes"
     # iterate() does not return any data and is used to just generate 
side-effects (i.e. write data to the database)
@@ -39,11 +43,11 @@ def main():
     g.V(v1).add_e('knows').to(v3).property('weight', 0.75).iterate()
 
     # retrieve the data from the "marko" vertex
-    marko = g.V().has('person', 'name', 'marko').values('name').next()
+    marko = g.V().has(VERTEX_LABEL, 'name', 'marko').values('name').next()
     print("name: " + marko)
 
     # find the "marko" vertex and then traverse to the people he "knows" and 
return their data
-    people_marko_knows = g.V().has('person', 'name', 
'marko').out('knows').values('name').to_list()
+    people_marko_knows = g.V().has(VERTEX_LABEL, 'name', 
'marko').out('knows').values('name').to_list()
     for person in people_marko_knows:
         print("marko knows " + person)
 
diff --git a/gremlin-python/src/main/python/examples/connections.py 
b/gremlin-python/src/main/python/examples/connections.py
index f268e6c27d..d4e36d4943 100644
--- a/gremlin-python/src/main/python/examples/connections.py
+++ b/gremlin-python/src/main/python/examples/connections.py
@@ -16,6 +16,9 @@
 # under the License.
 
 import sys
+import os
+import ssl
+import socket
 
 sys.path.append("..")
 
@@ -23,7 +26,9 @@ from gremlin_python.process.anonymous_traversal import 
traversal
 from gremlin_python.process.strategies import *
 from gremlin_python.driver.driver_remote_connection import 
DriverRemoteConnection
 from gremlin_python.driver.serializer import GraphBinarySerializersV1
+from gremlin_python.driver.aiohttp.transport import AiohttpTransport
 
+VERTEX_LABEL = os.getenv('VERTEX_LABEL', 'connection')
 
 def main():
     with_remote()
@@ -40,15 +45,14 @@ def with_remote():
     #
     # which starts it in "console" mode with an empty in-memory TinkerGraph 
ready to go bound to a
     # variable named "g" as referenced in the following line.
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
+    # if there is a port placeholder in the env var then we are running with 
docker so set appropriate port 
+    server_url = os.getenv('GREMLIN_SERVER_URL', 
'ws://localhost:8182/gremlin').format(45940)
+    rc = DriverRemoteConnection(server_url, 'g')
     g = traversal().with_remote(rc)
 
-    # drop existing vertices
-    g.V().drop().iterate()
-
     # simple query to verify connection
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     # cleanup
@@ -57,11 +61,23 @@ def with_remote():
 
 # connecting with plain text authentication
 def with_auth():
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g', 
username='stephen', password='password')
+    # if there is a port placeholder in the env var then we are running with 
docker so set appropriate port 
+    server_url = os.getenv('GREMLIN_SERVER_BASIC_AUTH_URL', 
'ws://localhost:8182/gremlin').format(45941)
+    
+    # disable SSL certificate verification for CI environments
+    if ':45941' in server_url:
+        ssl_opts = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+        ssl_opts.check_hostname = False
+        ssl_opts.verify_mode = ssl.CERT_NONE
+        rc = DriverRemoteConnection(server_url, 'g', username='stephen', 
password='password',
+                                    transport_factory=lambda: 
AiohttpTransport(ssl_options=ssl_opts))
+    else:
+        rc = DriverRemoteConnection(server_url, 'g', username='stephen', 
password='password')
+    
     g = traversal().with_remote(rc)
 
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     rc.close()
@@ -69,11 +85,16 @@ def with_auth():
 
 # connecting with Kerberos SASL authentication
 def with_kerberos():
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g', 
kerberized_service='[email protected]')
+    # if there is a port placeholder in the env var then we are running with 
docker so set appropriate port 
+    server_url = os.getenv('GREMLIN_SERVER_URL', 
'ws://localhost:8182/gremlin').format(45942)
+    kerberos_hostname = os.getenv('KRB_HOSTNAME', socket.gethostname())
+    kerberized_service = f'test-service@{kerberos_hostname}'
+    
+    rc = DriverRemoteConnection(server_url, 'g', 
kerberized_service=kerberized_service)
     g = traversal().with_remote(rc)
 
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     rc.close()
@@ -81,8 +102,10 @@ def with_kerberos():
 
 # connecting with customized configurations
 def with_configs():
+    # if there is a port placeholder in the env var then we are running with 
docker so set appropriate port 
+    server_url = os.getenv('GREMLIN_SERVER_URL', 
'ws://localhost:8182/gremlin').format(45940)
     rc = DriverRemoteConnection(
-        'ws://localhost:8182/gremlin', 'g',
+        server_url, 'g',
         username="", password="", kerberized_service='',
         message_serializer=GraphBinarySerializersV1(), graphson_reader=None,
         graphson_writer=None, headers=None, session=None,
@@ -90,8 +113,8 @@ def with_configs():
     )
     g = traversal().with_remote(rc)
 
-    v = g.add_v().iterate()
-    count = g.V().count().next()
+    v = g.add_v(VERTEX_LABEL).iterate()
+    count = g.V().has_label(VERTEX_LABEL).count().next()
     print("Vertex count: " + str(count))
 
     rc.close()
diff --git a/gremlin-python/src/main/python/examples/modern_traversals.py 
b/gremlin-python/src/main/python/examples/modern_traversals.py
index ae757b10b4..bbab62d110 100644
--- a/gremlin-python/src/main/python/examples/modern_traversals.py
+++ b/gremlin-python/src/main/python/examples/modern_traversals.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import sys
+import os
 
 sys.path.append("..")
 
@@ -31,7 +32,16 @@ def main():
     # This example requires the Modern toy graph to be preloaded upon 
launching the Gremlin server.
     # For details, see 
https://tinkerpop.apache.org/docs/current/reference/#gremlin-server-docker-image
 and use
     # conf/gremlin-server-modern.yaml.
-    rc = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
+    # if there is a port placeholder in the env var then we are running with 
docker so set appropriate port 
+    server_url = os.getenv('GREMLIN_SERVER_URL', 
'ws://localhost:8182/gremlin').format(45940)
+    
+    # CI uses port 45940 with gmodern binding, local uses 8182 with g binding
+    if ':45940' in server_url:
+        graph_binding = 'gmodern'  # CI environment
+    else:
+        graph_binding = 'g'        # Local environment
+    
+    rc = DriverRemoteConnection(server_url, graph_binding)
     g = traversal().with_remote(rc)
 
     e1 = g.V(1).both_e().to_list()  # (1)

Reply via email to