Skip to content

Commit

Permalink
Bytecode removal in gremlin-python (#2702)
Browse files Browse the repository at this point in the history
removed bytecode in gremlin-python, and replaced with gremlin lang scripts
  • Loading branch information
xiazcy authored and kenhuuu committed Nov 3, 2024
1 parent e48a0fb commit a5bf576
Show file tree
Hide file tree
Showing 14 changed files with 1,468 additions and 551 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Serialization support removed for `Bindings` and `Bytecode`.
* `EmbeddedRemoteConnection` will use `Gremlinlang`, not `JavaTranslator`.
* Java `Client` will no longer support submitting traversals. `DriverRemoteConnection` should be used instead.
* Removed usage of `Bytecode` from `gremlin-python`.
* Fixed `GremlinLangScriptEngine` handling for some strategies.
* Modified the `split()` step to split a string into a list of its characters if the given separator is an empty string.
Expand Down
22 changes: 16 additions & 6 deletions gremlin-python/src/main/python/gremlin_python/driver/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from gremlin_python.driver import connection, protocol, request, serializer
from gremlin_python.process import traversal
from gremlin_python.driver.request import TokensV4

log = logging.getLogger("gremlinpython")

Expand Down Expand Up @@ -154,20 +155,29 @@ def submit_async(self, message, bindings=None, request_options=None):

log.debug("message '%s'", str(message))
fields = {'g': self._traversal_source}
if isinstance(message, traversal.Bytecode):
fields['gremlinType'] = 'bytecode'
elif isinstance(message, str):
fields['gremlinType'] = 'eval'

# TODO: bindings is now part of request_options, evaluate the need to keep it separate in python.
# Note this bindings parameter only applies to string script submissions
if isinstance(message, str) and bindings:
fields['bindings'] = bindings

if isinstance(message, traversal.Bytecode) or isinstance(message, str):
if isinstance(message, str):
log.debug("fields='%s', gremlin='%s'", str(fields), str(message))
message = request.RequestMessageV4(fields=fields, gremlin=message)

conn = self._pool.get(True)
if request_options:
message.fields.update(request_options)
message.fields.update({token: request_options[token] for token in TokensV4
if token in request_options and token != 'bindings'})
if 'bindings' in request_options:
if 'bindings' in message.fields:
message.fields['bindings'].update(request_options['bindings'])
else:
message.fields['bindings'] = request_options['bindings']
if 'params' in request_options:
if 'bindings' in message.fields:
message.fields['bindings'].update(request_options['params'])
else:
message.fields['bindings'] = request_options['params']

return conn.write(message)
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
from gremlin_python.driver import client, serializer
from gremlin_python.driver.remote_connection import (
RemoteConnection, RemoteTraversal)
from gremlin_python.process.strategies import OptionsStrategy
from gremlin_python.process.traversal import Bytecode
import uuid
from gremlin_python.driver.request import TokensV4

log = logging.getLogger("gremlinpython")

Expand Down Expand Up @@ -74,9 +72,11 @@ def close(self):

self._client.close()

def submit(self, bytecode):
log.debug("submit with bytecode '%s'", str(bytecode))
result_set = self._client.submit(bytecode, request_options=self._extract_request_options(bytecode))
def submit(self, gremlin_lang):
log.debug("submit with gremlin lang script '%s'", gremlin_lang.get_gremlin())
gremlin_lang.add_g(self._traversal_source)
result_set = self._client.submit(gremlin_lang.get_gremlin(),
request_options=self.extract_request_options(gremlin_lang))
results = result_set.all().result()
return RemoteTraversal(iter(results))

Expand All @@ -87,10 +87,12 @@ def submitAsync(self, message, bindings=None, request_options=None):
DeprecationWarning)
self.submit_async(message, bindings, request_options)

def submit_async(self, bytecode):
log.debug("submit_async with bytecode '%s'", str(bytecode))
def submit_async(self, gremlin_lang):
log.debug("submit_async with gremlin lang script '%s'", gremlin_lang.get_gremlin())
future = Future()
future_result_set = self._client.submit_async(bytecode, request_options=self._extract_request_options(bytecode))
gremlin_lang.add_g(self._traversal_source)
future_result_set = self._client.submit_async(gremlin_lang.get_gremlin(),
request_options=self.extract_request_options(gremlin_lang))

def cb(f):
try:
Expand All @@ -106,22 +108,22 @@ def cb(f):
def is_closed(self):
return self._client.is_closed()

def commit(self):
log.info("Submitting commit graph operation.")
return self._client.submit(Bytecode.GraphOp.commit())

def rollback(self):
log.info("Submitting rollback graph operation.")
return self._client.submit(Bytecode.GraphOp.rollback())
# TODO remove or update once HTTP transaction is implemented
# def commit(self):
# log.info("Submitting commit graph operation.")
# return self._client.submit(Bytecode.GraphOp.commit())
#
# def rollback(self):
# log.info("Submitting rollback graph operation.")
# return self._client.submit(Bytecode.GraphOp.rollback())

@staticmethod
def _extract_request_options(bytecode):
options_strategy = next((x for x in bytecode.source_instructions
if x[0] == "withStrategies" and type(x[1]) is OptionsStrategy), None)
request_options = None
if options_strategy:
allowed_keys = ['evaluationTimeout', 'scriptEvaluationTimeout', 'batchSize', 'requestId', 'userAgent',
'materializeProperties']
request_options = {allowed: options_strategy[1].configuration[allowed] for allowed in allowed_keys
if allowed in options_strategy[1].configuration}
def extract_request_options(gremlin_lang):
request_options = {}
for os in gremlin_lang.options_strategies:
request_options.update({token: os.configuration[token] for token in TokensV4
if token in os.configuration})
if gremlin_lang.parameters is not None and len(gremlin_lang.parameters) > 0:
request_options["params"] = gremlin_lang.parameters

return request_options
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def traversal_source(self):
return self._traversal_source

@abc.abstractmethod
def submit(self, bytecode):
def submit(self, gremlin_lang):
pass

def is_closed(self):
Expand Down Expand Up @@ -69,10 +69,10 @@ def __init__(self, remote_connection):

def apply(self, traversal):
if traversal.traversers is None:
remote_traversal = self.remote_connection.submit(traversal.bytecode)
remote_traversal = self.remote_connection.submit(traversal.gremlin_lang)
traversal.remote_results = remote_traversal
traversal.traversers = remote_traversal.traversers

def apply_async(self, traversal):
if traversal.traversers is None:
traversal.remote_results = self.remote_connection.submit_async(traversal.bytecode)
traversal.remote_results = self.remote_connection.submit_async(traversal.gremlin_lang)
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@

RequestMessageV4 = collections.namedtuple(
'RequestMessageV4', ['fields', 'gremlin'])

TokensV4 = ['batchSize', 'bindings', 'g', 'gremlin', 'language',
'evaluationTimeout', 'materializeProperties', 'timeoutMs', 'userAgent']
Loading

0 comments on commit a5bf576

Please sign in to comment.