gremlinpython 3.6.5__py2.py3-none-any.whl → 3.6.7__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,5 +16,5 @@ KIND, either express or implied. See the License for the
16
16
  specific language governing permissions and limitations
17
17
  under the License.
18
18
  '''
19
- version = '3.6.5'
20
- timestamp = 1691177118
19
+ version = '3.6.7'
20
+ timestamp = 1713192014
@@ -138,3 +138,101 @@ class AiohttpTransport(AbstractBaseTransport):
138
138
  def closed(self):
139
139
  # Connection is closed if either the websocket or the client session is closed.
140
140
  return self._websocket.closed or self._client_session.closed
141
+
142
+
143
+ class AiohttpHTTPTransport(AbstractBaseTransport):
144
+ nest_asyncio_applied = False
145
+
146
+ def __init__(self, call_from_event_loop=None, read_timeout=None, write_timeout=None, **kwargs):
147
+ if call_from_event_loop is not None and call_from_event_loop and not AiohttpTransport.nest_asyncio_applied:
148
+ """
149
+ The AiohttpTransport implementation uses the asyncio event loop. Because of this, it cannot be called
150
+ within an event loop without nest_asyncio. If the code is ever refactored so that it can be called
151
+ within an event loop this import and call can be removed. Without this, applications which use the
152
+ event loop to call gremlin-python (such as Jupyter) will not work.
153
+ """
154
+ import nest_asyncio
155
+ nest_asyncio.apply()
156
+ AiohttpTransport.nest_asyncio_applied = True
157
+
158
+ # Start event loop and initialize client session and response to None
159
+ self._loop = asyncio.new_event_loop()
160
+ self._client_session = None
161
+ self._http_req_resp = None
162
+ self._enable_ssl = False
163
+
164
+ # Set all inner variables to parameters passed in.
165
+ self._aiohttp_kwargs = kwargs
166
+ self._write_timeout = write_timeout
167
+ self._read_timeout = read_timeout
168
+ if "ssl_options" in self._aiohttp_kwargs:
169
+ self._ssl_context = self._aiohttp_kwargs.pop("ssl_options")
170
+ self._enable_ssl = True
171
+
172
+ def __del__(self):
173
+ # Close will only actually close if things are left open, so this is safe to call.
174
+ # Clean up any connection resources and close the event loop.
175
+ self.close()
176
+
177
+ def connect(self, url, headers=None):
178
+ # Inner function to perform async connect.
179
+ async def async_connect():
180
+ # Start client session and use it to send all HTTP requests. Base url is the endpoint, headers are set here
181
+ # Base url can only parse basic url with no path, see https://github.com/aio-libs/aiohttp/issues/6647
182
+ if self._enable_ssl:
183
+ # ssl context is established through tcp connector
184
+ tcp_conn = aiohttp.TCPConnector(ssl_context=self._ssl_context)
185
+ self._client_session = aiohttp.ClientSession(connector=tcp_conn,
186
+ base_url=url, headers=headers, loop=self._loop)
187
+ else:
188
+ self._client_session = aiohttp.ClientSession(base_url=url, headers=headers, loop=self._loop)
189
+
190
+ # Execute the async connect synchronously.
191
+ self._loop.run_until_complete(async_connect())
192
+
193
+ def write(self, message):
194
+ # Inner function to perform async write.
195
+ async def async_write():
196
+ basic_auth = None
197
+ # basic password authentication for https connections
198
+ if message['auth']:
199
+ basic_auth = aiohttp.BasicAuth(message['auth']['username'], message['auth']['password'])
200
+ async with async_timeout.timeout(self._write_timeout):
201
+ self._http_req_resp = await self._client_session.post(url="/gremlin",
202
+ auth=basic_auth,
203
+ data=message['payload'],
204
+ headers=message['headers'],
205
+ **self._aiohttp_kwargs)
206
+
207
+ # Execute the async write synchronously.
208
+ self._loop.run_until_complete(async_write())
209
+
210
+ def read(self):
211
+ # Inner function to perform async read.
212
+ async def async_read():
213
+ async with async_timeout.timeout(self._read_timeout):
214
+ return {"content": await self._http_req_resp.read(),
215
+ "ok": self._http_req_resp.ok,
216
+ "status": self._http_req_resp.status}
217
+
218
+ return self._loop.run_until_complete(async_read())
219
+
220
+ def close(self):
221
+ # Inner function to perform async close.
222
+ async def async_close():
223
+ if self._client_session is not None and not self._client_session.closed:
224
+ await self._client_session.close()
225
+ self._client_session = None
226
+
227
+ # If the loop is not closed (connection hasn't already been closed)
228
+ if not self._loop.is_closed():
229
+ # Execute the async close synchronously.
230
+ self._loop.run_until_complete(async_close())
231
+
232
+ # Close the event loop.
233
+ self._loop.close()
234
+
235
+ @property
236
+ def closed(self):
237
+ # Connection is closed when client session is closed.
238
+ return self._client_session.closed
@@ -19,6 +19,7 @@
19
19
  import logging
20
20
  import warnings
21
21
  import queue
22
+ import re
22
23
  from concurrent.futures import ThreadPoolExecutor
23
24
 
24
25
  from gremlin_python.driver import connection, protocol, request, serializer
@@ -45,12 +46,16 @@ class Client:
45
46
  kerberized_service="", headers=None, session=None,
46
47
  enable_user_agent_on_connect=True, **transport_kwargs):
47
48
  log.info("Creating Client with url '%s'", url)
49
+
50
+ # check via url that we are using http protocol
51
+ self._use_http = re.search('^http', url)
52
+
48
53
  self._closed = False
49
54
  self._url = url
50
55
  self._headers = headers
51
56
  self._enable_user_agent_on_connect = enable_user_agent_on_connect
52
57
  self._traversal_source = traversal_source
53
- if "max_content_length" not in transport_kwargs:
58
+ if not self._use_http and "max_content_length" not in transport_kwargs:
54
59
  transport_kwargs["max_content_length"] = 10 * 1024 * 1024
55
60
  if message_serializer is None:
56
61
  message_serializer = serializer.GraphBinarySerializersV1()
@@ -63,21 +68,31 @@ class Client:
63
68
  if transport_factory is None:
64
69
  try:
65
70
  from gremlin_python.driver.aiohttp.transport import (
66
- AiohttpTransport)
71
+ AiohttpTransport, AiohttpHTTPTransport)
67
72
  except ImportError:
68
73
  raise Exception("Please install AIOHTTP or pass "
69
74
  "custom transport factory")
70
75
  else:
71
76
  def transport_factory():
72
- return AiohttpTransport(**transport_kwargs)
77
+ if self._use_http:
78
+ return AiohttpHTTPTransport(**transport_kwargs)
79
+ else:
80
+ return AiohttpTransport(**transport_kwargs)
73
81
  self._transport_factory = transport_factory
74
82
  if protocol_factory is None:
75
- def protocol_factory(): return protocol.GremlinServerWSProtocol(
76
- self._message_serializer,
77
- username=self._username,
78
- password=self._password,
79
- kerberized_service=kerberized_service,
80
- max_content_length=transport_kwargs["max_content_length"])
83
+ def protocol_factory():
84
+ if self._use_http:
85
+ return protocol.GremlinServerHTTPProtocol(
86
+ self._message_serializer,
87
+ username=self._username,
88
+ password=self._password)
89
+ else:
90
+ return protocol.GremlinServerWSProtocol(
91
+ self._message_serializer,
92
+ username=self._username,
93
+ password=self._password,
94
+ kerberized_service=kerberized_service,
95
+ max_content_length=transport_kwargs["max_content_length"])
81
96
  self._protocol_factory = protocol_factory
82
97
  if self._session_enabled:
83
98
  if pool_size is None:
@@ -58,9 +58,11 @@ class Connection:
58
58
  def write(self, request_message):
59
59
  if not self._inited:
60
60
  self.connect()
61
- request_id = str(uuid.uuid4())
62
61
  if request_message.args.get("requestId"):
63
- request_id = request_message.args.get("requestId")
62
+ request_id = str(request_message.args.get("requestId"))
63
+ uuid.UUID(request_id) # Checks for proper UUID or else server will return an error.
64
+ else:
65
+ request_id = str(uuid.uuid4())
64
66
  result_set = resultset.ResultSet(queue.Queue(), request_id)
65
67
  self._results[request_id] = result_set
66
68
  # Create write task
@@ -16,6 +16,7 @@
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
18
  #
19
+ import json
19
20
  import logging
20
21
  import abc
21
22
  import base64
@@ -25,6 +26,8 @@ import struct
25
26
 
26
27
  from gremlin_python.driver import request
27
28
  from gremlin_python.driver.resultset import ResultSet
29
+ from gremlin_python.process.translator import Translator
30
+ from gremlin_python.process.traversal import Bytecode
28
31
 
29
32
  log = logging.getLogger("gremlinpython")
30
33
 
@@ -63,7 +66,6 @@ class AbstractBaseProtocol(metaclass=abc.ABCMeta):
63
66
 
64
67
 
65
68
  class GremlinServerWSProtocol(AbstractBaseProtocol):
66
-
67
69
  QOP_AUTH_BIT = 1
68
70
  _kerberos_context = None
69
71
  _max_content_length = 10 * 1024 * 1024
@@ -133,7 +135,7 @@ class GremlinServerWSProtocol(AbstractBaseProtocol):
133
135
  # This message is going to be huge and kind of hard to read, but in the event of an error,
134
136
  # it can provide invaluable info, so space it out appropriately.
135
137
  log.error("\r\nReceived error message '%s'\r\n\r\nWith results dictionary '%s'",
136
- str(message), str(results_dict))
138
+ str(message), str(results_dict))
137
139
  del results_dict[request_id]
138
140
  raise GremlinServerError(message['status'])
139
141
 
@@ -185,8 +187,73 @@ class GremlinServerWSProtocol(AbstractBaseProtocol):
185
187
  name_length = len(self._username)
186
188
  fmt = '!I' + str(name_length) + 's'
187
189
  word = self.QOP_AUTH_BIT << 24 | self._max_content_length
188
- out = struct.pack(fmt, word, self._username.encode("utf-8"),)
190
+ out = struct.pack(fmt, word, self._username.encode("utf-8"), )
189
191
  encoded = base64.b64encode(out).decode('ascii')
190
192
  kerberos.authGSSClientWrap(self._kerberos_context, encoded)
191
193
  auth = kerberos.authGSSClientResponse(self._kerberos_context)
192
194
  return request.RequestMessage('', 'authentication', {'sasl': auth})
195
+
196
+
197
+ class GremlinServerHTTPProtocol(AbstractBaseProtocol):
198
+
199
+ def __init__(self,
200
+ message_serializer,
201
+ username='', password=''):
202
+ self._message_serializer = message_serializer
203
+ self._username = username
204
+ self._password = password
205
+
206
+ def connection_made(self, transport):
207
+ super(GremlinServerHTTPProtocol, self).connection_made(transport)
208
+
209
+ def write(self, request_id, request_message):
210
+
211
+ basic_auth = {}
212
+ if self._username and self._password:
213
+ basic_auth['username'] = self._username
214
+ basic_auth['password'] = self._password
215
+
216
+ content_type = str(self._message_serializer.version, encoding='utf-8')
217
+ message = {
218
+ 'headers': {'CONTENT-TYPE': content_type,
219
+ 'ACCEPT': content_type},
220
+ 'payload': self._message_serializer.serialize_message(request_id, request_message),
221
+ 'auth': basic_auth
222
+ }
223
+
224
+ self._transport.write(message)
225
+
226
+ def data_received(self, response, results_dict):
227
+ # if Gremlin Server cuts off then we get a None for the message
228
+ if response is None:
229
+ log.error("Received empty message from server.")
230
+ raise GremlinServerError({'code': 500,
231
+ 'message': 'Server disconnected - please try to reconnect', 'attributes': {}})
232
+
233
+ if response['ok']:
234
+ message = self._message_serializer.deserialize_message(response['content'])
235
+ request_id = message['requestId']
236
+ result_set = results_dict[request_id] if request_id in results_dict else ResultSet(None, None)
237
+ status_code = message['status']['code']
238
+ aggregate_to = message['result']['meta'].get('aggregateTo', 'list')
239
+ data = message['result']['data']
240
+ result_set.aggregate_to = aggregate_to
241
+
242
+ if status_code == 204:
243
+ result_set.stream.put_nowait([])
244
+ del results_dict[request_id]
245
+ return status_code
246
+ elif status_code in [200, 206]:
247
+ result_set.stream.put_nowait(data)
248
+ if status_code == 200:
249
+ result_set.status_attributes = message['status']['attributes']
250
+ del results_dict[request_id]
251
+ return status_code
252
+ else:
253
+ # This message is going to be huge and kind of hard to read, but in the event of an error,
254
+ # it can provide invaluable info, so space it out appropriately.
255
+ log.error("\r\nReceived error message '%s'\r\n\r\nWith results dictionary '%s'",
256
+ str(response['content']), str(results_dict))
257
+ body = json.loads(response['content'])
258
+ del results_dict[body['requestId']]
259
+ raise GremlinServerError({'code': response['status'], 'message': body['message'], 'attributes': {}})
@@ -17,6 +17,7 @@
17
17
  # under the License.
18
18
  #
19
19
 
20
+ import base64
20
21
  import logging
21
22
  import struct
22
23
  import uuid
@@ -156,7 +157,8 @@ class GraphSONMessageSerializer(object):
156
157
  return message
157
158
 
158
159
  def deserialize_message(self, message):
159
- msg = json.loads(message.decode('utf-8'))
160
+ # for parsing string message via HTTP connections
161
+ msg = json.loads(message if isinstance(message, str) else message.decode('utf-8'))
160
162
  return self._graphson_reader.to_object(msg)
161
163
 
162
164
 
@@ -238,7 +240,7 @@ class GraphBinarySerializersV1(object):
238
240
  def finalize_message(self, message, mime_len, mime_type):
239
241
  ba = bytearray()
240
242
 
241
- request_id = uuid.UUID(message['requestId'])
243
+ request_id = uuid.UUID(str(message['requestId']))
242
244
  ba.extend(self.header_pack(mime_len, mime_type, 0x81,
243
245
  (request_id.int >> 64) & self.max_int64, request_id.int & self.max_int64))
244
246
 
@@ -268,7 +270,8 @@ class GraphBinarySerializersV1(object):
268
270
  return bytes(ba)
269
271
 
270
272
  def deserialize_message(self, message):
271
- b = io.BytesIO(message)
273
+ # for parsing string message via HTTP connections
274
+ b = io.BytesIO(base64.b64decode(message) if isinstance(message, str) else message)
272
275
 
273
276
  b.read(1) # version
274
277
 
@@ -18,7 +18,7 @@
18
18
  #
19
19
  import platform
20
20
 
21
- gremlin_version = "3.6.5" # DO NOT MODIFY - Configured automatically by Maven Replacer Plugin
21
+ gremlin_version = "3.6.7" # DO NOT MODIFY - Configured automatically by Maven Replacer Plugin
22
22
 
23
23
  def _generate_user_agent():
24
24
  application_name = "NotAvailable"
@@ -1538,7 +1538,7 @@ class Transaction:
1538
1538
  def rollback(self):
1539
1539
  with self.__mutex:
1540
1540
  # Verify transaction is open, close session and return result of transaction's rollback.
1541
- self.__verify_transaction_state(True, "Cannot commit a transaction that is not started.")
1541
+ self.__verify_transaction_state(True, "Cannot rollback a transaction that is not started.")
1542
1542
  return self.__close_session(self._session_based_connection.rollback())
1543
1543
 
1544
1544
  # Commits the current transaction.
@@ -24,11 +24,13 @@ sent to any TinkerPop compliant HTTP endpoint.
24
24
  """
25
25
  __author__ = 'Kelvin R. Lawrence (gfxman)'
26
26
 
27
- from gremlin_python.process.graph_traversal import __
28
- from gremlin_python.process.anonymous_traversal import traversal
27
+ import math
28
+ import numbers
29
+ import re
30
+
29
31
  from gremlin_python.process.traversal import *
30
- from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
31
32
  from gremlin_python.process.strategies import *
33
+ from gremlin_python.structure.graph import Vertex, Edge, VertexProperty
32
34
  from datetime import datetime
33
35
 
34
36
 
@@ -39,18 +41,20 @@ class Translator:
39
41
 
40
42
  # Dictionary used to reverse-map token IDs to strings
41
43
  options = {
42
- WithOptions.tokens: 'tokens',
43
- WithOptions.none: 'none',
44
- WithOptions.ids: 'ids',
45
- WithOptions.labels: 'labels',
46
- WithOptions.keys: 'keys',
47
- WithOptions.values: 'values',
48
- WithOptions.all: 'all',
49
- WithOptions.indexer: 'indexer',
50
- WithOptions.list: 'list',
51
- WithOptions.map: 'map'
44
+ WithOptions.tokens: 'tokens',
45
+ WithOptions.none: 'none',
46
+ WithOptions.ids: 'ids',
47
+ WithOptions.labels: 'labels',
48
+ WithOptions.keys: 'keys',
49
+ WithOptions.values: 'values',
50
+ WithOptions.all: 'all',
51
+ WithOptions.indexer: 'indexer',
52
+ WithOptions.list: 'list',
53
+ WithOptions.map: 'map'
52
54
  }
53
55
 
56
+ conn_p = ['and', 'or']
57
+
54
58
  def __init__(self, traversal_source=None):
55
59
  self.traversal_source = traversal_source
56
60
 
@@ -60,20 +64,37 @@ class Translator:
60
64
  def get_target_language(self):
61
65
  return "gremlin-groovy"
62
66
 
63
- def of(self,traversal_source):
67
+ def of(self, traversal_source):
64
68
  self.traversal_source = traversal_source
65
69
  return self
66
70
 
67
71
  # Do any needed special processing for the representation
68
- # of strings and dates.
72
+ # of strings and dates and boolean.
69
73
  def fixup(self, v):
70
74
  if isinstance(v, str):
71
- return f'\'{v}\''
75
+ return f'{v!r}' # use repr() format for canonical string rep
72
76
  elif type(v) == datetime:
73
77
  return self.process_date(v)
78
+ elif type(v) == bool:
79
+ return 'true' if v else 'false'
80
+ elif isinstance(v, numbers.Number):
81
+ return self.process_number(v)
82
+ elif isinstance(v, set):
83
+ return f'[{str(v)[1:-1]}]'
84
+ elif isinstance(v, P):
85
+ return self.process_predicate(v)
86
+ elif type(v) == Vertex:
87
+ return self.process_vertex(v)
88
+ elif type(v) == Edge:
89
+ return self.process_edge(v)
90
+ elif type(v) in [Merge]: # on_create on_match out_v in_v
91
+ tmp = str(v)
92
+ return f'{tmp.split("_")[0]}{tmp.split("_")[1].capitalize()}' if tmp.find('_') else tmp
93
+ elif v is None:
94
+ return 'null'
74
95
  else:
75
96
  return str(v)
76
-
97
+
77
98
  # Turn a Python datetime into the equivalent new Date(...)
78
99
  def process_date(self, date):
79
100
  y = date.year - 1900
@@ -87,36 +108,113 @@ class Translator:
87
108
  # Do special processing needed to format predicates that come in
88
109
  # such as "gt(a)" correctly.
89
110
  def process_predicate(self, p):
90
- res = str(p).split('(')[0] + '('
111
+ res = ''
112
+ if p.operator in self.conn_p:
113
+ res += f'{self.process_predicate(p.value)}.{p.operator}({self.process_predicate(p.other)})'
114
+ else:
115
+ res += f'{self.process_p_value(p)}'
116
+ return res
91
117
 
118
+ # process the value of the predicates
119
+ def process_p_value(self, p):
120
+ res = str(p).split('(')[0] + '('
92
121
  if type(p.value) == list:
93
122
  res += '['
94
123
  for v in p.value:
95
124
  res += self.fixup(v) + ','
96
- res = res[0:-1] + ']'
125
+ res = (res[0:-1] + ']') if len(p.value) > 0 else (res + ']')
97
126
  else:
98
127
  res += self.fixup(p.value)
99
128
  if p.other is not None:
100
- res+= ',' + self.fixup(p.other)
129
+ res += f',{self.fixup(p.other)}'
101
130
  res += ')'
102
131
  return res
103
132
 
104
133
  # Special processing to handle strategies
105
134
  def process_strategy(self, s):
106
135
  c = 0
107
- res = f'new {str(s)}('
108
- for key in s.configuration:
109
- res += ',' if c > 0 else ''
110
- res += key + ':'
111
- val = s.configuration[key]
112
- if isinstance(val, Traversal):
113
- res += self.translate(val.bytecode, child=True)
136
+ res = ''
137
+ # if parameter is empty, only pass class name (referenced GroovyTranslator.java)
138
+ if not s.configuration:
139
+ res += s.strategy_name
140
+ else:
141
+ res = f'new {str(s)}('
142
+ for key in s.configuration:
143
+ res += ',' if c > 0 else ''
144
+ res += key + ':'
145
+ val = s.configuration[key]
146
+ if isinstance(val, Traversal):
147
+ res += self.translate(val.bytecode, child=True)
148
+ else:
149
+ res += self.fixup(val)
150
+ c += 1
151
+ res += ')'
152
+ return res
153
+ pass
154
+
155
+ # Special processing to handle vertices
156
+ def process_vertex(self, vertex):
157
+ return f'new ReferenceVertex({self.fixup(vertex.id)},\'{vertex.label}\')'
158
+
159
+ # Special processing to handle edges
160
+ def process_edge(self, edge):
161
+ return f'new ReferenceEdge({str(edge.id)},\'{edge.label}\',' \
162
+ f'new ReferenceVertex({str(edge.inV.id)},\'{edge.inV.label}\'),' \
163
+ f'new ReferenceVertex({str(edge.outV.id)},\'{edge.outV.label}\'))'
164
+
165
+ # Special processing to handle vertex property
166
+ def process_vertex_property(self, vp):
167
+ return f'new ReferenceVertexProperty({str(vp.id)},\'{vp.label}\',{self.fixup(vp.value)})'
168
+
169
+ # Special processing to handle lambda
170
+ def process_lambda(self, lam):
171
+ lambda_result = lam()
172
+ script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
173
+ return f'{script}' if re.match(r"^\{.*\}$", script, flags=re.DOTALL) else f'{{{script}}}'
174
+
175
+ def process_dict(self, d):
176
+ c = 0
177
+ res = '['
178
+ if len(d) == 0:
179
+ res += ':'
180
+ else:
181
+ for k, v in d.items():
182
+ wrap = not isinstance(k, str)
183
+ res += ',' if c > 0 else ''
184
+ res += '(' if wrap else ''
185
+ res += self.fixup(k)
186
+ res += ')' if wrap else ''
187
+ res += f':{self.fixup(v)}'
188
+ c += 1
189
+ res += ']'
190
+ return res
191
+
192
+ def process_number(self, n):
193
+ if isinstance(n, float):
194
+ # converting floats into doubles for script since python doesn't distinguish and java defaults to double
195
+ if math.isnan(n):
196
+ return "Double.NaN"
197
+ elif math.isinf(n) and n > 0:
198
+ return "Double.POSITIVE_INFINITY"
199
+ elif math.isinf(n) and n < 0:
200
+ return "Double.NEGATIVE_INFINITY"
114
201
  else:
115
- res += self.fixup(val)
202
+ return f'{n}d'
203
+ return f'{n}'
204
+
205
+ def process_list(self, l):
206
+ c = 0
207
+ res = '['
208
+ for i in l:
209
+ res += ',' if c > 0 else ''
210
+ res += self.fixup(i)
116
211
  c += 1
117
- res += ')'
212
+ res += ']'
118
213
  return res
119
- pass
214
+
215
+ # Special processing to handle bindings inside of traversals
216
+ def process_binding(self, binding):
217
+ return f'Bindings.instance().of(\'{binding.key}\', {str(binding.value)})'
120
218
 
121
219
  # Main driver of the translation. Different parts of
122
220
  # a Traversal are handled appropriately.
@@ -127,19 +225,29 @@ class Translator:
127
225
  if len(params) > 0:
128
226
  c = 0
129
227
  with_opts = False
228
+ is_merge_op = (step[0] == 'mergeV') or (step[0] == 'mergeE')
130
229
  for p in params:
131
230
  script += ',' if c > 0 else ''
132
231
  if with_opts:
133
- script += f'WithOptions.{self.options[p]}'
232
+ script += f'WithOptions.{self.options[p]}'
134
233
  elif type(p) == Bytecode:
135
234
  script += self.translate(p, True)
136
235
  elif isinstance(p, P):
137
236
  script += self.process_predicate(p)
138
- elif type(p) in [Cardinality, Pop, Operator]:
237
+ elif type(p) == Vertex:
238
+ script += self.process_vertex(p)
239
+ elif type(p) == Edge:
240
+ script += self.process_edge(p)
241
+ elif type(p) == VertexProperty:
242
+ script += self.process_vertex_property(p)
243
+ elif type(p) in [Cardinality, Pop, Operator, Scope, T]:
244
+ tmp = str(p)
245
+ script += tmp[0:-1] if tmp.endswith('_') else tmp
246
+ elif type(p) in [Merge]: # on_create on_match out_v in_v
247
+ is_merge_op = True
139
248
  tmp = str(p)
140
- script += tmp[0:-1] if tmp.endswith('_') else tmp
141
- elif type(p) in [ReadOnlyStrategy, SubgraphStrategy, VertexProgramStrategy,
142
- OptionsStrategy, PartitionStrategy]:
249
+ script += f'{tmp.split("_")[0]}{tmp.split("_")[1].capitalize()}' if tmp.find('_') else tmp
250
+ elif isinstance(p, TraversalStrategy): # this will capture all strategies
143
251
  script += self.process_strategy(p)
144
252
  elif type(p) == datetime:
145
253
  script += self.process_date(p)
@@ -147,11 +255,25 @@ class Translator:
147
255
  script += 'WithOptions.tokens'
148
256
  with_opts = True
149
257
  elif isinstance(p, str):
150
- script += f'\'{p}\''
258
+ script += f'{p!r}' # use repr() format for canonical string rep
151
259
  elif type(p) == bool:
152
260
  script += 'true' if p else 'false'
261
+ elif isinstance(p, type(lambda: None)) and p.__name__ == (lambda: None).__name__:
262
+ script += self.process_lambda(p)
263
+ elif type(p) == Binding:
264
+ script += self.process_binding(p)
153
265
  elif p is None:
154
- script += 'null'
266
+ script += '(Traversal) null' if is_merge_op else 'null'
267
+ elif isinstance(p, type):
268
+ script += p.__name__
269
+ elif isinstance(p, dict):
270
+ script += self.process_dict(p)
271
+ elif isinstance(p, numbers.Number):
272
+ script += self.process_number(p)
273
+ elif isinstance(p, set):
274
+ script += f'[{str(p)[1:-1]}] as Set' if len(p) > 0 else '[] as Set'
275
+ elif isinstance(p, list):
276
+ script += self.process_list(p)
155
277
  else:
156
278
  script += str(p)
157
279
  c += 1
@@ -165,11 +287,11 @@ class Translator:
165
287
  # anonymous traversal style syntax.
166
288
  def translate(self, bytecode, child=False):
167
289
  script = '__' if child else self.traversal_source
168
-
290
+
169
291
  for step in bytecode.source_instructions:
170
292
  script += self.do_translation(step)
171
293
 
172
294
  for step in bytecode.step_instructions:
173
295
  script += self.do_translation(step)
174
-
296
+
175
297
  return script
@@ -207,9 +207,9 @@ statics.add_static('shuffle', Order.shuffle)
207
207
  statics.add_static('asc', Order.asc)
208
208
  statics.add_static('desc', Order.desc)
209
209
 
210
- Pick = Enum('Pick', ' any none')
210
+ Pick = Enum('Pick', ' any_ none')
211
211
 
212
- statics.add_static('any', Pick.any)
212
+ statics.add_static('any_', Pick.any_)
213
213
  statics.add_static('none', Pick.none)
214
214
 
215
215
  Pop = Enum('Pop', ' all_ first last mixed')
@@ -30,7 +30,7 @@ from aenum import Enum
30
30
  from isodate import parse_duration, duration_isoformat
31
31
 
32
32
  from gremlin_python import statics
33
- from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, SingleByte, ByteBufferType, SingleChar
33
+ from gremlin_python.statics import FloatType, FunctionType, ShortType, IntType, LongType, TypeType, SingleByte, ByteBufferType, SingleChar
34
34
  from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy
35
35
  from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
36
36
  from gremlin_python.structure.io.util import SymbolUtil
@@ -498,6 +498,30 @@ class Int32IO(Int64IO):
498
498
  return GraphSONUtil.typed_value(cls.graphson_base_type, n)
499
499
 
500
500
 
501
+ class Int16IO(Int64IO):
502
+ python_type = ShortType
503
+ graphson_type = "gx:Int16"
504
+ graphson_base_type = "Int16"
505
+
506
+ @classmethod
507
+ def dictify(cls, n, writer):
508
+ # if we exceed Java int range then we need a long
509
+ if isinstance(n, bool):
510
+ return n
511
+ elif n < -9223372036854775808 or n > 9223372036854775807:
512
+ return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
513
+ elif n < -2147483648 or n > 2147483647:
514
+ return GraphSONUtil.typed_value("Int64", n)
515
+ elif n < -32768 or n > 32767:
516
+ return GraphSONUtil.typed_value("Int32", n)
517
+ else:
518
+ return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
519
+
520
+ @classmethod
521
+ def objectify(cls, v, _):
522
+ return int.__new__(ShortType, v)
523
+
524
+
501
525
  class ByteIO(_NumberIO):
502
526
  python_type = SingleByte
503
527
  graphson_type = "gx:Byte"
@@ -14,6 +14,7 @@
14
14
  # KIND, either express or implied. See the License for the
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
+
17
18
  import calendar
18
19
  import datetime
19
20
  import json
@@ -28,7 +29,7 @@ from aenum import Enum
28
29
  from isodate import parse_duration, duration_isoformat
29
30
 
30
31
  from gremlin_python import statics
31
- from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, SingleChar
32
+ from gremlin_python.statics import FloatType, FunctionType, ShortType, IntType, LongType, TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, SingleChar
32
33
  from gremlin_python.process.traversal import Binding, Bytecode, Direction, P, TextP, Traversal, Traverser, TraversalStrategy, T
33
34
  from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
34
35
  from gremlin_python.structure.io.util import HashableDict, SymbolUtil
@@ -596,6 +597,31 @@ class Int32IO(Int64IO):
596
597
  else:
597
598
  return GraphSONUtil.typed_value(cls.graphson_base_type, n)
598
599
 
600
+
601
+ class Int16IO(Int64IO):
602
+ python_type = ShortType
603
+ graphson_type = "gx:Int16"
604
+ graphson_base_type = "Int16"
605
+
606
+ @classmethod
607
+ def dictify(cls, n, writer):
608
+ # if we exceed Java int range then we need a long
609
+ if isinstance(n, bool):
610
+ return n
611
+ elif n < -9223372036854775808 or n > 9223372036854775807:
612
+ return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
613
+ elif n < -2147483648 or n > 2147483647:
614
+ return GraphSONUtil.typed_value("Int64", n)
615
+ elif n < -32768 or n > 32767:
616
+ return GraphSONUtil.typed_value("Int32", n)
617
+ else:
618
+ return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
619
+
620
+ @classmethod
621
+ def objectify(cls, v, _):
622
+ return int.__new__(ShortType, v)
623
+
624
+
599
625
  class ByteIO(_NumberIO):
600
626
  python_type = SingleByte
601
627
  graphson_type = "gx:Byte"
@@ -0,0 +1,5 @@
1
+ Apache TinkerPop
2
+ Copyright 2015-2024 The Apache Software Foundation.
3
+
4
+ This product includes software developed at
5
+ The Apache Software Foundation (http://www.apache.org/).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gremlinpython
3
- Version: 3.6.5
3
+ Version: 3.6.7
4
4
  Summary: Gremlin-Python for Apache TinkerPop
5
5
  Home-page: http://tinkerpop.apache.org
6
6
  License: Apache 2
@@ -0,0 +1,5 @@
1
+ Apache TinkerPop
2
+ Copyright 2015-2024 The Apache Software Foundation.
3
+
4
+ This product includes software developed at
5
+ The Apache Software Foundation (http://www.apache.org/).
@@ -0,0 +1,37 @@
1
+ gremlin_python/__init__.py,sha256=rbOOdo_19nz_mHTXVc5p8ZXLI5pUGMfXLKQiw7Olu7g,850
2
+ gremlin_python/__version__.py,sha256=X4Pu5VP_o7Q8F5n4DXqgkUTvf5eG4J9rvnhZqx_HWu8,804
3
+ gremlin_python/statics.py,sha256=BXnrfx25Todku_U0ddd-zB4eyQMf2paT5uuN9znK2fQ,2849
4
+ gremlin_python/driver/__init__.py,sha256=rbOOdo_19nz_mHTXVc5p8ZXLI5pUGMfXLKQiw7Olu7g,850
5
+ gremlin_python/driver/client.py,sha256=D5JfgxOBvOkZZX10CZ_uVbA14Ez2SW_nWl7gRXrd7qw,8030
6
+ gremlin_python/driver/connection.py,sha256=KXcSUjs1QJVL0XqkDSNgHoaM3_Bi34wdv_ISext4Bsc,3515
7
+ gremlin_python/driver/driver_remote_connection.py,sha256=YK4_se8Md57Dq-P6VwcLag0vH-AOoGqayQA9suG-_fM,8670
8
+ gremlin_python/driver/protocol.py,sha256=SqDZWeu3p2WHCzv8k1u2Q1icg2AIl03OhkWsB4KoBnw,11785
9
+ gremlin_python/driver/remote_connection.py,sha256=DtglObhiyLDIgLKIcv7enDuXd9KiCJVLXWAvreBQ4wA,3014
10
+ gremlin_python/driver/request.py,sha256=IlqBmQlT2UU95xbY6z1ajlmNQeDZ4ePzT4uF8M0USFk,953
11
+ gremlin_python/driver/resultset.py,sha256=_-13igfH1zQ72mgreDptPmUaXnadnprERVQTSZWeIl4,2669
12
+ gremlin_python/driver/serializer.py,sha256=wFCPAltRB2F0p9ZFyD0x2thoBmI81gPFZhAkV5XLBOQ,10244
13
+ gremlin_python/driver/transport.py,sha256=aEXb9oS1SMI9oKWYINnWuYhYaosi6FdsOJ7oj6FzkkY,1246
14
+ gremlin_python/driver/useragent.py,sha256=J7mBrRZnC7-cBKdoPsJ35dzTqNQo8jJ05aRNenHM-eU,1588
15
+ gremlin_python/driver/aiohttp/__init__.py,sha256=xzdixoKYCJCe4aRILYqdartQi4Py5fcQWqif3zzyUC8,787
16
+ gremlin_python/driver/aiohttp/transport.py,sha256=DifMZ5LJRoV_THI8_zik5EvgVNTha_ubLthNyr2pYHs,10971
17
+ gremlin_python/process/__init__.py,sha256=rbOOdo_19nz_mHTXVc5p8ZXLI5pUGMfXLKQiw7Olu7g,850
18
+ gremlin_python/process/anonymous_traversal.py,sha256=A8evyPIAciRGiauDqUbyo4XnG3QTdO28l-TF2K7Ir2g,2448
19
+ gremlin_python/process/graph_traversal.py,sha256=f_k1Jw9wZ5CN155lBzz497uGffZkh_OAEHN45IzKdZ4,61094
20
+ gremlin_python/process/strategies.py,sha256=95WIhzvvqejCEDOlhICGji9HgkwTUySGKt-yNCBTTh8,9474
21
+ gremlin_python/process/translator.py,sha256=NuaA2WfepvgDm3DrNa_u2Qvz70s9t6ICbFltPglQwBI,11147
22
+ gremlin_python/process/traversal.py,sha256=m4oHkVKxzXM4YD03cRljbzskEwClZP58XB4djpzL7Sw,22454
23
+ gremlin_python/structure/__init__.py,sha256=zo5zR3kruv1h4_A80IxZ1IZrS0Ud5lVjpGm0PxBAP20,852
24
+ gremlin_python/structure/graph.py,sha256=JdyP2yiZKK2EnkTn4wIiy-bZb8iGLCvneC8T_VaZgvo,4365
25
+ gremlin_python/structure/io/__init__.py,sha256=zo5zR3kruv1h4_A80IxZ1IZrS0Ud5lVjpGm0PxBAP20,852
26
+ gremlin_python/structure/io/graphbinaryV1.py,sha256=Ti_eR70jOmJnapiyTq1qhkt90CKfXPWEhqwnhBef5tY,37104
27
+ gremlin_python/structure/io/graphsonV2d0.py,sha256=qylO27tVWE3GmCFBL0rC27T456enGJqkB358Ly4BypQ,21405
28
+ gremlin_python/structure/io/graphsonV3d0.py,sha256=cP7BdkD7gnhD_lWPpq9VzozxSpBZ5SXsoJymMpjzSUc,24727
29
+ gremlin_python/structure/io/util.py,sha256=x0OEkGGX2ajgOuSbz1j3dO3_IlOPnPLV4m6SGAmNAeM,1846
30
+ gremlinpython-3.6.7.data/data/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
31
+ gremlinpython-3.6.7.data/data/NOTICE,sha256=h-5PKu8VoRZYtIoIbQYwvbtBWDK16kNDtp0e1Lu-WXc,170
32
+ gremlinpython-3.6.7.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
33
+ gremlinpython-3.6.7.dist-info/METADATA,sha256=_JfMfGxWSGHEKvbQaUScIiZQIq740hcXDMqV4g9u_mo,6351
34
+ gremlinpython-3.6.7.dist-info/NOTICE,sha256=h-5PKu8VoRZYtIoIbQYwvbtBWDK16kNDtp0e1Lu-WXc,170
35
+ gremlinpython-3.6.7.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
36
+ gremlinpython-3.6.7.dist-info/top_level.txt,sha256=VVeR1g-oOCZBmKIaVzZ7fF2BYrnqOWpw7C2H71ksTAU,15
37
+ gremlinpython-3.6.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.0)
2
+ Generator: bdist_wheel (0.37.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -1,5 +0,0 @@
1
- Apache TinkerPop
2
- Copyright 2015-2023 The Apache Software Foundation.
3
-
4
- This product includes software developed at
5
- The Apache Software Foundation (http://www.apache.org/).
@@ -1,5 +0,0 @@
1
- Apache TinkerPop
2
- Copyright 2015-2023 The Apache Software Foundation.
3
-
4
- This product includes software developed at
5
- The Apache Software Foundation (http://www.apache.org/).
@@ -1,37 +0,0 @@
1
- gremlin_python/__init__.py,sha256=rbOOdo_19nz_mHTXVc5p8ZXLI5pUGMfXLKQiw7Olu7g,850
2
- gremlin_python/__version__.py,sha256=0ziu1yIjAcHDwuwTnKTPaUR9LVforR8SYbIrFTwGNjg,804
3
- gremlin_python/statics.py,sha256=BXnrfx25Todku_U0ddd-zB4eyQMf2paT5uuN9znK2fQ,2849
4
- gremlin_python/driver/__init__.py,sha256=rbOOdo_19nz_mHTXVc5p8ZXLI5pUGMfXLKQiw7Olu7g,850
5
- gremlin_python/driver/client.py,sha256=HJZmYGsxb4tzVmEfM3QQGuqK--kxmcd0Y255pBo6-Rc,7399
6
- gremlin_python/driver/connection.py,sha256=LKrslNCXf5Gu8um1b2pBiZ84zKZ_HsJ-dQh4DouDd-U,3395
7
- gremlin_python/driver/driver_remote_connection.py,sha256=YK4_se8Md57Dq-P6VwcLag0vH-AOoGqayQA9suG-_fM,8670
8
- gremlin_python/driver/protocol.py,sha256=LmzvTMjQEmRd2GRWN2CSishbtOKvD11376wZ2Todpe4,8746
9
- gremlin_python/driver/remote_connection.py,sha256=DtglObhiyLDIgLKIcv7enDuXd9KiCJVLXWAvreBQ4wA,3014
10
- gremlin_python/driver/request.py,sha256=IlqBmQlT2UU95xbY6z1ajlmNQeDZ4ePzT4uF8M0USFk,953
11
- gremlin_python/driver/resultset.py,sha256=_-13igfH1zQ72mgreDptPmUaXnadnprERVQTSZWeIl4,2669
12
- gremlin_python/driver/serializer.py,sha256=dMKXL9YYFK2DJKQfIQ2Y-R-_DoyqjRBSPTn4k5SID0M,10009
13
- gremlin_python/driver/transport.py,sha256=aEXb9oS1SMI9oKWYINnWuYhYaosi6FdsOJ7oj6FzkkY,1246
14
- gremlin_python/driver/useragent.py,sha256=zBm9UgIIUtnZH0IzF8_40aWKa5ATii37_Q7wSkLciuc,1588
15
- gremlin_python/driver/aiohttp/__init__.py,sha256=xzdixoKYCJCe4aRILYqdartQi4Py5fcQWqif3zzyUC8,787
16
- gremlin_python/driver/aiohttp/transport.py,sha256=qKSvgWZw8Gv2OYnriycphs2Nb2zoaw2tPzol0aMtp3Q,6228
17
- gremlin_python/process/__init__.py,sha256=rbOOdo_19nz_mHTXVc5p8ZXLI5pUGMfXLKQiw7Olu7g,850
18
- gremlin_python/process/anonymous_traversal.py,sha256=A8evyPIAciRGiauDqUbyo4XnG3QTdO28l-TF2K7Ir2g,2448
19
- gremlin_python/process/graph_traversal.py,sha256=XDTC1rcKe0FcqUrchqPVRUnoTkYTa2xVY-dH3c7BSCw,61092
20
- gremlin_python/process/strategies.py,sha256=95WIhzvvqejCEDOlhICGji9HgkwTUySGKt-yNCBTTh8,9474
21
- gremlin_python/process/translator.py,sha256=wQUFDmex8g7paYfUreWKhTY3bUnM0nF4bnZOm6H2zbs,6159
22
- gremlin_python/process/traversal.py,sha256=kt_2HlRTIvMEnkOR9654eAJESP4bcMFt9BfWlKjQgu8,22451
23
- gremlin_python/structure/__init__.py,sha256=zo5zR3kruv1h4_A80IxZ1IZrS0Ud5lVjpGm0PxBAP20,852
24
- gremlin_python/structure/graph.py,sha256=JdyP2yiZKK2EnkTn4wIiy-bZb8iGLCvneC8T_VaZgvo,4365
25
- gremlin_python/structure/io/__init__.py,sha256=zo5zR3kruv1h4_A80IxZ1IZrS0Ud5lVjpGm0PxBAP20,852
26
- gremlin_python/structure/io/graphbinaryV1.py,sha256=Ti_eR70jOmJnapiyTq1qhkt90CKfXPWEhqwnhBef5tY,37104
27
- gremlin_python/structure/io/graphsonV2d0.py,sha256=t63IZ6UIVngvQcH8fnnLDmWm0KoCuDrwB5lprM2dFuw,20598
28
- gremlin_python/structure/io/graphsonV3d0.py,sha256=bEiZcJduPNGmf5rHdl0Yq9QFwAmnvADDBytmBAAirQM,23918
29
- gremlin_python/structure/io/util.py,sha256=x0OEkGGX2ajgOuSbz1j3dO3_IlOPnPLV4m6SGAmNAeM,1846
30
- gremlinpython-3.6.5.data/data/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
31
- gremlinpython-3.6.5.data/data/NOTICE,sha256=cQwbCsygJy_LcRskXIJSOhUxEZWiR_QM6xpJCS1v0_o,170
32
- gremlinpython-3.6.5.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
33
- gremlinpython-3.6.5.dist-info/METADATA,sha256=zCuAXXMo6jPGSIPzmUdh39F4bKGvUQLbD9D1lY93C0w,6351
34
- gremlinpython-3.6.5.dist-info/NOTICE,sha256=cQwbCsygJy_LcRskXIJSOhUxEZWiR_QM6xpJCS1v0_o,170
35
- gremlinpython-3.6.5.dist-info/WHEEL,sha256=k3vXr0c0OitO0k9eCWBlI2yTYnpb_n_I2SGzrrfY7HY,110
36
- gremlinpython-3.6.5.dist-info/top_level.txt,sha256=VVeR1g-oOCZBmKIaVzZ7fF2BYrnqOWpw7C2H71ksTAU,15
37
- gremlinpython-3.6.5.dist-info/RECORD,,