You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by xi...@apache.org on 2024/07/15 16:12:44 UTC
(tinkerpop) branch python-http-chunked updated: remove ws, switch to graphbinaryv4, complete support for chunked transfer & clean up
This is an automated email from the ASF dual-hosted git repository.
xiazcy pushed a commit to branch python-http-chunked
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/python-http-chunked by this push:
new 416bcf735f remove ws, switch to graphbinaryv4, complete support for chunked transfer & clean up
416bcf735f is described below
commit 416bcf735fa570716f12352c044b0dc0a414f36c
Author: Yang Xia <55...@users.noreply.github.com>
AuthorDate: Mon Jul 15 09:12:35 2024 -0700
remove ws, switch to graphbinaryv4, complete support for chunked transfer & clean up
---
CHANGELOG.asciidoc | 2 +
.../gremlin_python/driver/aiohttp/transport.py | 192 +---
.../main/python/gremlin_python/driver/client.py | 54 +-
.../python/gremlin_python/driver/connection.py | 10 +-
.../driver/driver_remote_connection.py | 68 +-
.../main/python/gremlin_python/driver/protocol.py | 210 +---
.../gremlin_python/driver/remote_connection.py | 6 -
.../python/gremlin_python/driver/serializer.py | 265 +----
.../gremlin_python/structure/io/graphbinaryV1.py | 1161 --------------------
.../gremlin_python/structure/io/graphsonV2d0.py | 664 -----------
.../gremlin_python/structure/io/graphsonV3d0.py | 784 -------------
gremlin-python/src/main/python/tests/conftest.py | 297 +----
.../src/main/python/tests/driver/test_client.py | 266 ++---
.../tests/driver/test_driver_remote_connection.py | 155 +--
.../driver/test_driver_remote_connection_http.py | 229 ----
.../test_driver_remote_connection_threaded.py | 16 +-
.../main/python/tests/driver/test_serializer.py | 2 -
.../tests/structure/io/test_functionalityio.py | 60 +-
.../tests/structure/io/test_graphbinaryV1.py | 235 ----
.../python/tests/structure/io/test_graphsonV2d0.py | 538 ---------
.../python/tests/structure/io/test_graphsonV3d0.py | 556 ----------
21 files changed, 359 insertions(+), 5411 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 00c4b8de81..5351366cea 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -40,6 +40,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Added `withoutStrategies()` syntax to the Gremlin ANTLR grammar.
* Modified the Gremlin ANTLR grammar to more dynamically interact with any strategies registered globally to the `TraversalStrategies` cache sets.
* Made `new` keyword optional in the Gremlin grammar.
+* Switched to HTTP protocol in `gremlin-python` and replaced GraphSONV2, GraphSONV2 & GraphBinaryV1 with GraphBinaryV4
+* Added support for chunked transfer in `gremlin-python`
* Added TypeScript & ECMAScript module support.
== TinkerPop 3.7.0 (Gremfir Master of the Pan Flute)
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/aiohttp/transport.py b/gremlin-python/src/main/python/gremlin_python/driver/aiohttp/transport.py
index 2ae80f7db7..2f4164f1ca 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/aiohttp/transport.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/aiohttp/transport.py
@@ -19,134 +19,18 @@
import aiohttp
import asyncio
import async_timeout
-from aiohttp import ClientResponseError
-
+from aiohttp import ClientPayloadError
+from gremlin_python.driver.protocol import GremlinServerError
from gremlin_python.driver.transport import AbstractBaseTransport
__author__ = 'Lyndon Bauto (lyndonb@bitquilltech.com)'
-# TODO: remove WS transport & refactor
-class AiohttpTransport(AbstractBaseTransport):
- nest_asyncio_applied = False
-
- def __init__(self, call_from_event_loop=None, read_timeout=None, write_timeout=None, **kwargs):
- if call_from_event_loop is not None and call_from_event_loop and not AiohttpTransport.nest_asyncio_applied:
- """
- The AiohttpTransport implementation uses the asyncio event loop. Because of this, it cannot be called
- within an event loop without nest_asyncio. If the code is ever refactored so that it can be called
- within an event loop this import and call can be removed. Without this, applications which use the
- event loop to call gremlin-python (such as Jupyter) will not work.
- """
- import nest_asyncio
- nest_asyncio.apply()
- AiohttpTransport.nest_asyncio_applied = True
-
- # Start event loop and initialize websocket and client to None
- self._loop = asyncio.new_event_loop()
- self._websocket = None
- self._client_session = None
-
- # Set all inner variables to parameters passed in.
- self._aiohttp_kwargs = kwargs
- self._write_timeout = write_timeout
- self._read_timeout = read_timeout
- if "max_content_length" in self._aiohttp_kwargs:
- self._aiohttp_kwargs["max_msg_size"] = self._aiohttp_kwargs.pop("max_content_length")
- if "ssl_options" in self._aiohttp_kwargs:
- self._aiohttp_kwargs["ssl"] = self._aiohttp_kwargs.pop("ssl_options")
-
- def __del__(self):
- # Close will only actually close if things are left open, so this is safe to call.
- # Clean up any connection resources and close the event loop.
- self.close()
-
- def connect(self, url, headers=None):
- # Inner function to perform async connect.
- async def async_connect():
- # Start client session and use it to create a websocket with all the connection options provided.
- self._client_session = aiohttp.ClientSession(loop=self._loop)
- try:
- self._websocket = await self._client_session.ws_connect(url, **self._aiohttp_kwargs, headers=headers)
- except ClientResponseError as err:
- # If 403, just send forbidden because in some cases this prints out a huge verbose message
- # that includes credentials.
- if err.status == 403:
- raise Exception('Failed to connect to server: HTTP Error code 403 - Forbidden.')
- else:
- raise
-
- # Execute the async connect synchronously.
- self._loop.run_until_complete(async_connect())
-
- def write(self, message):
- # Inner function to perform async write.
- async def async_write():
- async with async_timeout.timeout(self._write_timeout):
- await self._websocket.send_bytes(message)
-
- # Execute the async write synchronously.
- self._loop.run_until_complete(async_write())
-
- def read(self):
- # Inner function to perform async read.
- async def async_read():
- async with async_timeout.timeout(self._read_timeout):
- return await self._websocket.receive()
-
- # Execute the async read synchronously.
- msg = self._loop.run_until_complete(async_read())
-
- # Need to handle multiple potential message types.
- if msg.type == aiohttp.WSMsgType.close:
- # Server is closing connection, shutdown and throw exception.
- self.close()
- raise RuntimeError("Connection was closed by server.")
- elif msg.type == aiohttp.WSMsgType.closed:
- # Should not be possible since our loop and socket would be closed.
- raise RuntimeError("Connection was already closed.")
- elif msg.type == aiohttp.WSMsgType.error:
- # Error on connection, try to convert message to a string in error.
- raise RuntimeError("Received error on read: '" + str(msg.data) + "'")
- elif msg.type == aiohttp.WSMsgType.text:
- # Convert message to bytes.
- data = msg.data.strip().encode('utf-8')
- else:
- # General handle, return byte data.
- data = msg.data
- return data
-
- def close(self):
- # Inner function to perform async close.
- async def async_close():
- if self._websocket is not None and not self._websocket.closed:
- await self._websocket.close()
- self._websocket = None
-
- if self._client_session is not None and not self._client_session.closed:
- await self._client_session.close()
- self._client_session = None
-
- # If the loop is not closed (connection hasn't already been closed)
- if not self._loop.is_closed():
- # Execute the async close synchronously.
- self._loop.run_until_complete(async_close())
-
- # Close the event loop.
- self._loop.close()
-
- @property
- def closed(self):
- # Connection is closed if either the websocket or the client session is closed.
- return self._websocket.closed or self._client_session.closed
-
-
class AiohttpHTTPTransport(AbstractBaseTransport):
nest_asyncio_applied = False
- def __init__(self, message_serializer=None,
- call_from_event_loop=None, read_timeout=None, write_timeout=None, **kwargs):
- if call_from_event_loop is not None and call_from_event_loop and not AiohttpTransport.nest_asyncio_applied:
+ def __init__(self, call_from_event_loop=None, read_timeout=None, write_timeout=None, **kwargs):
+ if call_from_event_loop is not None and call_from_event_loop and not AiohttpHTTPTransport.nest_asyncio_applied:
"""
The AiohttpTransport implementation uses the asyncio event loop. Because of this, it cannot be called
within an event loop without nest_asyncio. If the code is ever refactored so that it can be called
@@ -155,19 +39,22 @@ class AiohttpHTTPTransport(AbstractBaseTransport):
"""
import nest_asyncio
nest_asyncio.apply()
- AiohttpTransport.nest_asyncio_applied = True
+ AiohttpHTTPTransport.nest_asyncio_applied = True
# Start event loop and initialize client session and response to None
self._loop = asyncio.new_event_loop()
self._client_session = None
self._http_req_resp = None
self._enable_ssl = False
- self._message_serializer = message_serializer
# Set all inner variables to parameters passed in.
self._aiohttp_kwargs = kwargs
self._write_timeout = write_timeout
self._read_timeout = read_timeout
+ if "max_content_length" in self._aiohttp_kwargs:
+ self._max_content_len = self._aiohttp_kwargs.pop("max_content_length")
+ else:
+ self._max_content_len = 10 * 1024 * 1024
if "ssl_options" in self._aiohttp_kwargs:
self._ssl_context = self._aiohttp_kwargs.pop("ssl_options")
self._enable_ssl = True
@@ -210,42 +97,35 @@ class AiohttpHTTPTransport(AbstractBaseTransport):
# Execute the async write synchronously.
self._loop.run_until_complete(async_write())
- def read(self):
+ def read(self, stream_chunk=None):
+ if not stream_chunk:
+ raise Exception('missing handling of streamed responses to protocol')
+
# Inner function to perform async read.
async def async_read():
- # TODO: set-up chunked reading
- # buffer = b""
- message = {'status': {'code': 0,
- 'message': '',
- 'exception': ''},
- 'result': {'meta': {},
- 'data': []}}
- is_first_chunk = True
-
- async for data, _ in self._http_req_resp.content.iter_chunks():
- chunk_msg = self._message_serializer.deserialize_message(data, is_first_chunk)
- if 'result' in chunk_msg:
- msg_data = message['result']['data']
- chunk_data = chunk_msg['result']['data']
- message['result']['data'] = [*msg_data, *chunk_data]
- if 'status' in chunk_msg:
- message.update({'status': chunk_msg['status']})
- is_first_chunk = False
-
- msg = {"content": message, #use deserialzed content
- "ok": self._http_req_resp.ok,
- "status": self._http_req_resp.status}
- return msg
-
- # async with async_timeout.timeout(self._read_timeout):
- # data = await self._http_req_resp.read()
- # print(self._http_req_resp.headers)
- # print(self._http_req_resp.status)
- # print(self._http_req_resp.ok)
- # print(len(data))
- # return {"content": data,
- # "ok": self._http_req_resp.ok,
- # "status": self._http_req_resp.status}
+ # TODO: potentially refactor to just use streaming and remove transport/protocol
+ async with async_timeout.timeout(self._read_timeout):
+ read_completed = False
+ # aiohttp streaming may not iterate through one whole chunk if it's too large, need to buffer it
+ data_buffer = b""
+ async for data, end_of_http_chunk in self._http_req_resp.content.iter_chunks():
+ try:
+ data_buffer += data
+ if end_of_http_chunk:
+ if self._max_content_len and len(
+ data_buffer) > self._max_content_len:
+ raise Exception( # TODO: do we need proper exception class for this?
+ f'Response size {len(data_buffer)} exceeds limit {self._max_content_len} bytes')
+ stream_chunk(data_buffer, read_completed, self._http_req_resp.ok)
+ data_buffer = b""
+ except ClientPayloadError:
+ # server disconnect during streaming will cause ClientPayLoadError from aiohttp
+ # TODO: double check during refactoring
+ raise GremlinServerError({'code': 500,
+ 'message': 'Server disconnected - please try to reconnect',
+ 'exception': ClientPayloadError})
+ read_completed = True
+ stream_chunk(data_buffer, read_completed, self._http_req_resp.ok)
return self._loop.run_until_complete(async_read())
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/client.py b/gremlin-python/src/main/python/gremlin_python/driver/client.py
index c6b0bc1f1e..a1d1137afe 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/client.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/client.py
@@ -43,8 +43,7 @@ class Client:
def __init__(self, url, traversal_source, protocol_factory=None,
transport_factory=None, pool_size=None, max_workers=None,
- message_serializer=None, username="", password="",
- kerberized_service="", headers=None, session=None,
+ message_serializer=None, username="", password="", headers=None,
enable_user_agent_on_connect=True, **transport_kwargs):
log.info("Creating Client with url '%s'", url)
@@ -56,7 +55,7 @@ class Client:
self._headers = headers
self._enable_user_agent_on_connect = enable_user_agent_on_connect
self._traversal_source = traversal_source
- if not self._use_http and "max_content_length" not in transport_kwargs:
+ if "max_content_length" not in transport_kwargs:
transport_kwargs["max_content_length"] = 10 * 1024 * 1024
if message_serializer is None:
message_serializer = serializer.GraphBinarySerializersV4()
@@ -64,42 +63,28 @@ class Client:
self._message_serializer = message_serializer
self._username = username
self._password = password
- self._session = session
- self._session_enabled = (session is not None and session != "")
+
if transport_factory is None:
try:
- from gremlin_python.driver.aiohttp.transport import (
- AiohttpTransport, AiohttpHTTPTransport)
+ from gremlin_python.driver.aiohttp.transport import AiohttpHTTPTransport
except ImportError:
raise Exception("Please install AIOHTTP or pass "
"custom transport factory")
else:
def transport_factory():
- if self._use_http:
- return AiohttpHTTPTransport(self._message_serializer, **transport_kwargs)
- else:
- return AiohttpTransport(**transport_kwargs)
+ if self._protocol_factory is None:
+ self._protocol_factory = protocol_factory
+ return AiohttpHTTPTransport(**transport_kwargs)
self._transport_factory = transport_factory
+
if protocol_factory is None:
def protocol_factory():
- if self._use_http:
- return protocol.GremlinServerHTTPProtocol(
- self._message_serializer,
- username=self._username,
- password=self._password)
- else:
- return protocol.GremlinServerWSProtocol(
- self._message_serializer,
- username=self._username,
- password=self._password,
- kerberized_service=kerberized_service,
- max_content_length=transport_kwargs["max_content_length"])
+ return protocol.GremlinServerHTTPProtocol(
+ self._message_serializer,
+ username=self._username,
+ password=self._password)
self._protocol_factory = protocol_factory
- if self._session_enabled:
- if pool_size is None:
- pool_size = 1
- elif pool_size != 1:
- raise Exception("PoolSize must be 1 on session mode!")
+
if pool_size is None:
pool_size = 8
self._pool_size = pool_size
@@ -139,8 +124,6 @@ class Client:
if self._closed:
return
- if self._session_enabled:
- self._close_session()
log.info("Closing Client with url '%s'", self._url)
while not self._pool.empty():
conn = self._pool.get(True)
@@ -148,17 +131,6 @@ class Client:
self._executor.shutdown()
self._closed = True
- def _close_session(self):
- message = request.RequestMessage(
- processor='session', op='close',
- args={'session': str(self._session)})
- conn = self._pool.get(True)
- try:
- write_result_set = conn.write(message).result()
- return write_result_set.all().result() # wait for _receive() to finish
- except protocol.GremlinServerError:
- pass
-
def _get_connection(self):
protocol = self._protocol_factory()
return connection.Connection(
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/connection.py b/gremlin-python/src/main/python/gremlin_python/driver/connection.py
index 94a3c63cd3..de9a81034d 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/connection.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/connection.py
@@ -14,7 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-import uuid
import queue
from concurrent.futures import Future
@@ -81,10 +80,9 @@ class Connection:
def _receive(self):
try:
- while True:
- data = self._transport.read()
- status_code = self._protocol.data_received(data, self._result_set)
- if status_code != 206:
- break
+ self._transport.read(self.stream_chunk)
finally:
self._pool.put_nowait(self)
+
+ def stream_chunk(self, chunk_data, read_completed=None, http_req_resp=None):
+ self._protocol.data_received(chunk_data, self._result_set, read_completed, http_req_resp)
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py b/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
index 6058a6ba4b..f1fd19d0e8 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py
@@ -36,9 +36,8 @@ class DriverRemoteConnection(RemoteConnection):
def __init__(self, url, traversal_source="g", protocol_factory=None,
transport_factory=None, pool_size=None, max_workers=None,
- username="", password="", kerberized_service='',
- message_serializer=None, graphson_reader=None,
- graphson_writer=None, headers=None, session=None,
+ username="", password="",
+ message_serializer=None, headers=None,
enable_user_agent_on_connect=True, **transport_kwargs):
log.info("Creating DriverRemoteConnection with url '%s'", str(url))
self.__url = url
@@ -49,23 +48,13 @@ class DriverRemoteConnection(RemoteConnection):
self.__max_workers = max_workers
self.__username = username
self.__password = password
- self.__kerberized_service = kerberized_service
self.__message_serializer = message_serializer
- self.__graphson_reader = graphson_reader
- self.__graphson_writer = graphson_writer
self.__headers = headers
- self.__session = session
self.__enable_user_agent_on_connect = enable_user_agent_on_connect
self.__transport_kwargs = transport_kwargs
- # keeps a list of sessions that have been spawned from this DriverRemoteConnection
- # so that they can be closed if this parent session is closed.
- self.__spawned_sessions = []
-
- if message_serializer is None and graphson_reader is not None and graphson_writer is not None:
- message_serializer = serializer.GraphSONMessageSerializer(
- reader=graphson_reader,
- writer=graphson_writer)
+ if message_serializer is None:
+ message_serializer = serializer.GraphBinarySerializersV4()
self._client = client.Client(url, traversal_source,
protocol_factory=protocol_factory,
transport_factory=transport_factory,
@@ -74,28 +63,14 @@ class DriverRemoteConnection(RemoteConnection):
message_serializer=message_serializer,
username=username,
password=password,
- kerberized_service=kerberized_service,
headers=headers,
- session=session,
enable_user_agent_on_connect=enable_user_agent_on_connect,
**transport_kwargs)
self._url = self._client._url
self._traversal_source = self._client._traversal_source
def close(self):
- # close this client and any DriverRemoteConnection instances spawned from this one
- # for a session
- if len(self.__spawned_sessions) > 0:
- log.info("closing spawned sessions from DriverRemoteConnection with url '%s'", str(self._url))
- for spawned_session in self.__spawned_sessions:
- spawned_session.close()
- self.__spawned_sessions.clear()
-
- if self.__session:
- log.info("closing DriverRemoteConnection with url '%s' with session '%s'",
- str(self._url), str(self.__session))
- else:
- log.info("closing DriverRemoteConnection with url '%s'", str(self._url))
+ log.info("closing DriverRemoteConnection with url '%s'", str(self._url))
self._client.close()
@@ -131,36 +106,6 @@ class DriverRemoteConnection(RemoteConnection):
def is_closed(self):
return self._client.is_closed()
- def is_session_bound(self):
- return self.__session is not None
-
- def create_session(self):
- log.info("Creating session based connection")
- if self.is_session_bound():
- raise Exception('Connection is already bound to a session - child sessions are not allowed')
- conn = DriverRemoteConnection(self.__url,
- traversal_source=self.__traversal_source,
- protocol_factory=self.__protocol_factory,
- transport_factory=self.__transport_factory,
- pool_size=self.__pool_size,
- max_workers=self.__max_workers,
- username=self.__username,
- password=self.__password,
- kerberized_service=self.__kerberized_service,
- message_serializer=self.__message_serializer,
- graphson_reader=self.__graphson_reader,
- graphson_writer=self.__graphson_writer,
- headers=self.__headers,
- session=uuid.uuid4(),
- enable_user_agent_on_connect=self.__enable_user_agent_on_connect,
- **self.__transport_kwargs)
- self.__spawned_sessions.append(conn)
- return conn
-
- def remove_session(self, session_based_connection):
- session_based_connection.close()
- self.__spawned_sessions.remove(session_based_connection)
-
def commit(self):
log.info("Submitting commit graph operation.")
return self._client.submit(Bytecode.GraphOp.commit())
@@ -175,7 +120,8 @@ class DriverRemoteConnection(RemoteConnection):
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']
+ 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}
return request_options
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/protocol.py b/gremlin-python/src/main/python/gremlin_python/driver/protocol.py
index 0ed263f6c6..a35c004a2a 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/protocol.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/protocol.py
@@ -19,15 +19,6 @@
import json
import logging
import abc
-import base64
-import struct
-
-# import kerberos Optional dependency imported in relevant codeblock
-
-from gremlin_python.driver import request
-from gremlin_python.driver.resultset import ResultSet
-from gremlin_python.process.translator import Translator
-from gremlin_python.process.traversal import Bytecode
log = logging.getLogger("gremlinpython")
@@ -37,13 +28,9 @@ __author__ = 'David M. Brown (davebshow@gmail.com)'
class GremlinServerError(Exception):
def __init__(self, status):
super(GremlinServerError, self).__init__('{0}: {1}'.format(status['code'], status['message']))
- self._status_attributes = status['attributes']
self.status_code = status['code']
self.status_message = status['message']
-
- @property
- def status_attributes(self):
- return self._status_attributes
+ self.status_exception = status['exception']
class ConfigurationError(Exception):
@@ -65,136 +52,6 @@ class AbstractBaseProtocol(metaclass=abc.ABCMeta):
pass
-# TODO: remove WS protocol & refactor
-class GremlinServerWSProtocol(AbstractBaseProtocol):
- QOP_AUTH_BIT = 1
- _kerberos_context = None
- _max_content_length = 10 * 1024 * 1024
-
- def __init__(self,
- message_serializer,
- username='', password='',
- kerberized_service='',
- max_content_length=10 * 1024 * 1024):
- self._message_serializer = message_serializer
- self._username = username
- self._password = password
- self._kerberized_service = kerberized_service
- self._max_content_length = max_content_length
-
- def connection_made(self, transport):
- super(GremlinServerWSProtocol, self).connection_made(transport)
-
- def write(self, request_id, request_message):
- message = self._message_serializer.serialize_message(request_id, request_message)
- self._transport.write(message)
-
- def data_received(self, message, results_dict):
- # if Gremlin Server cuts off then we get a None for the message
- if message is None:
- log.error("Received empty message from server.")
- raise GremlinServerError({'code': 500,
- 'message': 'Server disconnected - please try to reconnect', 'attributes': {}})
-
- message = self._message_serializer.deserialize_message(message)
- request_id = message['requestId']
- result_set = results_dict[request_id] if request_id in results_dict else ResultSet(None, None)
- status_code = message['status']['code']
- aggregate_to = message['result']['meta'].get('aggregateTo', 'list')
- data = message['result']['data']
- result_set.aggregate_to = aggregate_to
- if status_code == 407:
- if self._username and self._password:
- auth_bytes = b''.join([b'\x00', self._username.encode('utf-8'),
- b'\x00', self._password.encode('utf-8')])
- auth = base64.b64encode(auth_bytes)
- request_message = request.RequestMessage(
- 'traversal', 'authentication', {'sasl': auth.decode()})
- elif self._kerberized_service:
- request_message = self._kerberos_received(message)
- else:
- error_message = 'Gremlin server requires authentication credentials in DriverRemoteConnection. ' \
- 'For basic authentication provide username and password. ' \
- 'For kerberos authentication provide the kerberized_service parameter.'
- log.error(error_message)
- raise ConfigurationError(error_message)
- self.write(request_id, request_message)
- data = self._transport.read()
- # Allow for auth handshake with multiple steps
- return self.data_received(data, results_dict)
- elif status_code == 204:
- result_set.stream.put_nowait([])
- del results_dict[request_id]
- return status_code
- elif status_code in [200, 206]:
- result_set.stream.put_nowait(data)
- if status_code == 200:
- result_set.status_attributes = message['status']['attributes']
- del results_dict[request_id]
- return status_code
- else:
- # This message is going to be huge and kind of hard to read, but in the event of an error,
- # it can provide invaluable info, so space it out appropriately.
- log.error("\r\nReceived error message '%s'\r\n\r\nWith results dictionary '%s'",
- str(message), str(results_dict))
- del results_dict[request_id]
- raise GremlinServerError(message['status'])
-
- def _kerberos_received(self, message):
- # Inspired by: https://github.com/thobbs/pure-sasl/blob/0.6.2/puresasl/mechanisms.py
- # https://github.com/thobbs/pure-sasl/blob/0.6.2/LICENSE
- try:
- import kerberos
- except ImportError:
- raise ImportError('Please install gremlinpython[kerberos].')
-
- # First pass: get service granting ticket and return it to gremlin-server
- if not self._kerberos_context:
- try:
- _, kerberos_context = kerberos.authGSSClientInit(
- self._kerberized_service, gssflags=kerberos.GSS_C_MUTUAL_FLAG)
- kerberos.authGSSClientStep(kerberos_context, '')
- auth = kerberos.authGSSClientResponse(kerberos_context)
- self._kerberos_context = kerberos_context
- except kerberos.KrbError as e:
- raise ConfigurationError(
- 'Kerberos authentication requires a valid service name in DriverRemoteConnection, '
- 'as well as a valid tgt (export KRB5CCNAME) or keytab (export KRB5_KTNAME): ' + str(e))
- return request.RequestMessage('', 'authentication', {'sasl': auth})
-
- # Second pass: completion of authentication
- sasl_response = message['status']['attributes']['sasl']
- if not self._username:
- result_code = kerberos.authGSSClientStep(self._kerberos_context, sasl_response)
- if result_code == kerberos.AUTH_GSS_COMPLETE:
- self._username = kerberos.authGSSClientUserName(self._kerberos_context)
- return request.RequestMessage('', 'authentication', {'sasl': ''})
-
- # Third pass: sasl quality of protection (qop) handshake
-
- # Gremlin-server Krb5Authenticator only supports qop=QOP_AUTH; use ssl for confidentiality.
- # Handshake content format:
- # byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf
- # byte 1-3: the max length for any buffer sent back and forth on this connection. (big endian)
- # the rest of the buffer: the authorization user name in UTF-8 - not null terminated.
- kerberos.authGSSClientUnwrap(self._kerberos_context, sasl_response)
- data = kerberos.authGSSClientResponse(self._kerberos_context)
- plaintext_data = base64.b64decode(data)
- assert len(plaintext_data) == 4, "Unexpected response from gremlin server sasl handshake"
- word, = struct.unpack('!I', plaintext_data)
- qop_bits = word >> 24
- assert self.QOP_AUTH_BIT & qop_bits, "Unexpected sasl qop level received from gremlin server"
-
- name_length = len(self._username)
- fmt = '!I' + str(name_length) + 's'
- word = self.QOP_AUTH_BIT << 24 | self._max_content_length
- out = struct.pack(fmt, word, self._username.encode("utf-8"), )
- encoded = base64.b64encode(out).decode('ascii')
- kerberos.authGSSClientWrap(self._kerberos_context, encoded)
- auth = kerberos.authGSSClientResponse(self._kerberos_context)
- return request.RequestMessage('', 'authentication', {'sasl': auth})
-
-
class GremlinServerHTTPProtocol(AbstractBaseProtocol):
def __init__(self,
@@ -203,6 +60,12 @@ class GremlinServerHTTPProtocol(AbstractBaseProtocol):
self._message_serializer = message_serializer
self._username = username
self._password = password
+ self._response_msg = {'status': {'code': 0,
+ 'message': '',
+ 'exception': ''},
+ 'result': {'meta': {},
+ 'data': []}}
+ self._is_first_chunk = True
def connection_made(self, transport):
super(GremlinServerHTTPProtocol, self).connection_made(transport)
@@ -224,35 +87,50 @@ class GremlinServerHTTPProtocol(AbstractBaseProtocol):
self._transport.write(message)
- def data_received(self, response, result_set):
- # if Gremlin Server cuts off then we get a None for the message
- if response is None:
- log.error("Received empty message from server.")
- raise GremlinServerError({'code': 500,
- 'message': 'Server disconnected - please try to reconnect', 'attributes': {}})
-
- if response['ok']:
- message = response['content']
- status_code = message['status']['code']
- aggregate_to = message['result']['meta'].get('aggregateTo', 'list')
- data = message['result']['data']
+ # data is received in chunks
+ def data_received(self, response_chunk, result_set, read_completed=None, http_req_resp=None):
+ # we shouldn't need to use the http_req_resp code as status is sent in response message, but leaving it for now
+ if read_completed:
+ status_code = self._response_msg['status']['code']
+ aggregate_to = self._response_msg['result']['meta'].get('aggregateTo', 'list')
+ data = self._response_msg['result']['data']
result_set.aggregate_to = aggregate_to
+ # reset response message
+ self._response_msg = {'status': {'code': 0,
+ 'message': '',
+ 'exception': ''},
+ 'result': {'meta': {},
+ 'data': []}}
+ self._is_first_chunk = True
+
if status_code == 204 and len(data) == 0:
result_set.stream.put_nowait([])
- return status_code
elif status_code in [200, 204, 206]:
result_set.stream.put_nowait(data)
- return status_code
else:
log.error("\r\nReceived error message '%s'\r\n\r\nWith result set '%s'",
- str(message), str(result_set))
+ str(self._response_msg), str(result_set))
raise GremlinServerError({'code': status_code,
- 'message': message['status']['message'],
- 'attributes': {}})
+ 'message': self._response_msg['status']['message'],
+ 'exception': self._response_msg['status']['exception']})
else:
- # TODO check error deserialization after chunking implementation
- log.error("\r\nReceived error message '%s'\r\n\r\nWith result set '%s'",
- str(response['content']), str(result_set))
- body = json.loads(response['content'])
- raise GremlinServerError({'code': response['status'], 'message': body['message'], 'attributes': {}})
+ self._response_msg = self._decode_chunk(self._response_msg, response_chunk, self._is_first_chunk)
+ self._is_first_chunk = False
+
+ def _decode_chunk(self, message, data_buffer, is_first_chunk):
+ chunk_msg = self._message_serializer.deserialize_message(data_buffer, is_first_chunk)
+
+ if 'result' in chunk_msg:
+ msg_data = message['result']['data']
+ chunk_data = chunk_msg['result']['data']
+ message['result']['data'] = [*msg_data, *chunk_data]
+ if 'status' in chunk_msg:
+ status_code = chunk_msg['status']['code']
+ if status_code in [200, 204, 206]:
+ message.update({'status': chunk_msg['status']})
+ else:
+ raise GremlinServerError({'code': status_code,
+ 'message': chunk_msg['status']['message'],
+ 'exception': chunk_msg['status']['exception']})
+ return message
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/remote_connection.py b/gremlin-python/src/main/python/gremlin_python/driver/remote_connection.py
index 11d4fa9a43..74a0fabd15 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/remote_connection.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/remote_connection.py
@@ -43,12 +43,6 @@ class RemoteConnection(object, metaclass=abc.ABCMeta):
def is_closed(self):
raise Exception('is_closed() must be implemented')
- def is_session_bound(self):
- return False
-
- def create_session(self):
- raise Exception('createSession() must be implemented');
-
def commit(self):
raise Exception('commit() must be implemented')
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/serializer.py b/gremlin-python/src/main/python/gremlin_python/driver/serializer.py
index b85a776c03..2e4622a699 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/serializer.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/serializer.py
@@ -20,7 +20,6 @@
import base64
import logging
import struct
-import uuid
import io
try:
import ujson as json
@@ -29,274 +28,12 @@ try:
except ImportError:
import json
-from gremlin_python.structure.io import graphbinaryV1
from gremlin_python.structure.io import graphbinaryV4
-from gremlin_python.structure.io import graphsonV2d0
-from gremlin_python.structure.io import graphsonV3d0
from gremlin_python.structure.io.util import Marker
__author__ = 'David M. Brown (davebshow@gmail.com), Lyndon Bauto (lyndonb@bitquilltech.com)'
-# TODO: remove all classes except for GraphBinarySerializersV4
-class Processor:
- """Base class for OpProcessor serialization system."""
-
- def __init__(self, writer):
- self._writer = writer
-
- def get_op_args(self, op, args):
- op_method = getattr(self, op, None)
- if not op_method:
- raise Exception("Processor does not support op: {}".format(op))
- return op_method(args)
-
-
-class Standard(Processor):
-
- def authentication(self, args):
- return args
-
- def eval(self, args):
- return args
-
-
-class Session(Processor):
-
- def authentication(self, args):
- return args
-
- def eval(self, args):
- return args
-
- def close(self, args):
- return args
-
- def bytecode(self, args):
- gremlin = args['gremlin']
- args['gremlin'] = self._writer.to_dict(gremlin)
- aliases = args.get('aliases', '')
- if not aliases:
- aliases = {'g': 'g'}
- args['aliases'] = aliases
- return args
-
-
-class Traversal(Processor):
-
- def authentication(self, args):
- return args
-
- def bytecode(self, args):
- gremlin = args['gremlin']
- args['gremlin'] = self._writer.to_dict(gremlin)
- aliases = args.get('aliases', '')
- if not aliases:
- aliases = {'g': 'g'}
- args['aliases'] = aliases
- return args
-
-
-class GraphSONMessageSerializer(object):
- """
- Message serializer for GraphSON. Allow users to pass custom reader,
- writer, and version kwargs for custom serialization. Otherwise,
- use current GraphSON version as default.
- """
-
- # KEEP TRACK OF CURRENT DEFAULTS
- DEFAULT_READER_CLASS = graphsonV3d0.GraphSONReader
- DEFAULT_WRITER_CLASS = graphsonV3d0.GraphSONWriter
- DEFAULT_VERSION = b"application/vnd.gremlin-v3.0+json"
-
- def __init__(self, reader=None, writer=None, version=None):
- if not version:
- version = self.DEFAULT_VERSION
- self._version = version
- if not reader:
- reader = self.DEFAULT_READER_CLASS()
- self._graphson_reader = reader
- if not writer:
- writer = self.DEFAULT_WRITER_CLASS()
- self.standard = Standard(writer)
- self.traversal = Traversal(writer)
- self.session = Session(writer)
-
- @property
- def version(self):
- """Read only property"""
- return self._version
-
- def get_processor(self, processor):
- processor = getattr(self, processor, None)
- if not processor:
- raise Exception("Unknown processor")
- return processor
-
- def serialize_message(self, request_id, request_message):
- processor = request_message.processor
- op = request_message.op
- args = request_message.args
- if not processor:
- processor_obj = self.get_processor('standard')
- else:
- processor_obj = self.get_processor(processor)
- args = processor_obj.get_op_args(op, args)
- message = self.build_message(request_id, processor, op, args)
- return message
-
- def build_message(self, request_id, processor, op, args):
- message = {
- 'requestId': {'@type': 'g:UUID', '@value': request_id},
- 'processor': processor,
- 'op': op,
- 'args': args
- }
- return self.finalize_message(message, b"\x21", self.version)
-
- def finalize_message(self, message, mime_len, mime_type):
- message = json.dumps(message)
- message = b''.join([mime_len, mime_type, message.encode('utf-8')])
- return message
-
- def deserialize_message(self, message):
- # for parsing string message via HTTP connections
- msg = json.loads(message if isinstance(message, str) else message.decode('utf-8'))
- return self._graphson_reader.to_object(msg)
-
-
-class GraphSONSerializersV2d0(GraphSONMessageSerializer):
- """Message serializer for GraphSON 2.0"""
- def __init__(self):
- reader = graphsonV2d0.GraphSONReader()
- writer = graphsonV2d0.GraphSONWriter()
- version = b"application/vnd.gremlin-v2.0+json"
- super(GraphSONSerializersV2d0, self).__init__(reader, writer, version)
-
-
-class GraphSONSerializersV3d0(GraphSONMessageSerializer):
- """Message serializer for GraphSON 3.0"""
- def __init__(self):
- reader = graphsonV3d0.GraphSONReader()
- writer = graphsonV3d0.GraphSONWriter()
- version = b"application/vnd.gremlin-v3.0+json"
- super(GraphSONSerializersV3d0, self).__init__(reader, writer, version)
-
-
-class GraphBinarySerializersV1(object):
- DEFAULT_READER_CLASS = graphbinaryV1.GraphBinaryReader
- DEFAULT_WRITER_CLASS = graphbinaryV1.GraphBinaryWriter
- DEFAULT_VERSION = b"application/vnd.graphbinary-v1.0"
-
- max_int64 = 0xFFFFFFFFFFFFFFFF
- header_struct = struct.Struct('>b32sBQQ')
- header_pack = header_struct.pack
- int_pack = graphbinaryV1.int32_pack
- int32_unpack = struct.Struct(">i").unpack
-
- def __init__(self, reader=None, writer=None, version=None):
- if not version:
- version = self.DEFAULT_VERSION
- self._version = version
- if not reader:
- reader = self.DEFAULT_READER_CLASS()
- self._graphbinary_reader = reader
- if not writer:
- writer = self.DEFAULT_WRITER_CLASS()
- self._graphbinary_writer = writer
- self.standard = Standard(writer)
- self.traversal = Traversal(writer)
- self.session = Session(writer)
-
- @property
- def version(self):
- """Read only property"""
- return self._version
-
- def get_processor(self, processor):
- processor = getattr(self, processor, None)
- if not processor:
- raise Exception("Unknown processor")
- return processor
-
- def serialize_message(self, request_id, request_message):
- processor = request_message.processor
- op = request_message.op
- args = request_message.args
- if not processor:
- processor_obj = self.get_processor('standard')
- else:
- processor_obj = self.get_processor(processor)
- args = processor_obj.get_op_args(op, args)
- message = self.build_message(request_id, processor, op, args)
- return message
-
- def build_message(self, request_id, processor, op, args):
- message = {
- 'requestId': request_id,
- 'processor': processor,
- 'op': op,
- 'args': args
- }
- return self.finalize_message(message, 0x20, self.version)
-
- def finalize_message(self, message, mime_len, mime_type):
- ba = bytearray()
-
- request_id = uuid.UUID(str(message['requestId']))
- ba.extend(self.header_pack(mime_len, mime_type, 0x81,
- (request_id.int >> 64) & self.max_int64, request_id.int & self.max_int64))
-
- op_bytes = message['op'].encode("utf-8")
- ba.extend(self.int_pack(len(op_bytes)))
- ba.extend(op_bytes)
-
- processor_bytes = message['processor'].encode("utf-8")
- ba.extend(self.int_pack(len(processor_bytes)))
- ba.extend(processor_bytes)
-
- args = message["args"]
- ba.extend(self.int_pack(len(args)))
- for k, v in args.items():
- self._graphbinary_writer.to_dict(k, ba)
-
- # processor_obj.get_op_args in serialize_message() seems to already handle bytecode. in python 3
- # because bytearray isn't bound to a type in graphbinary it falls through the writeObject() and
- # just works but python 2 bytearray is bound to ByteBufferType so it writes DataType.bytebuffer
- # rather than DataType.bytecode and the server gets confused. special casing this for now until
- # it can be refactored
- if k == "gremlin" and isinstance(v, bytearray):
- ba.extend(v)
- else:
- self._graphbinary_writer.to_dict(v, ba)
-
- return bytes(ba)
-
- def deserialize_message(self, message):
- # for parsing string message via HTTP connections
- b = io.BytesIO(base64.b64decode(message) if isinstance(message, str) else message)
-
- b.read(1) # version
-
- request_id = str(self._graphbinary_reader.to_object(b, graphbinaryV1.DataType.uuid))
- status_code = self.int32_unpack(b.read(4))[0]
- status_msg = self._graphbinary_reader.to_object(b, graphbinaryV1.DataType.string)
- status_attrs = self._graphbinary_reader.to_object(b, graphbinaryV1.DataType.map, nullable=False)
- meta_attrs = self._graphbinary_reader.to_object(b, graphbinaryV1.DataType.map, nullable=False)
- result = self._graphbinary_reader.to_object(b)
-
- b.close()
-
- msg = {'requestId': request_id,
- 'status': {'code': status_code,
- 'message': status_msg,
- 'attributes': status_attrs},
- 'result': {'meta': meta_attrs,
- 'data': result}}
-
- return msg
-
-
"""
GraphBinaryV4
"""
@@ -392,7 +129,7 @@ class GraphBinarySerializersV4(object):
def read_payload(self, buffer):
results = []
- readable = True;
+ readable = True
while buffer.readable(): # find method or way to access readable bytes without using buffer.getvalue()
# print(buffer.tell())
if buffer.tell() == len(buffer.getvalue()):
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
deleted file mode 100644
index 1cc487bc3e..0000000000
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
+++ /dev/null
@@ -1,1161 +0,0 @@
-"""
-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.
-"""
-
-import datetime
-import calendar
-import uuid
-import math
-import io
-import struct
-from collections import OrderedDict
-import logging
-
-from struct import pack, unpack
-from aenum import Enum
-from datetime import timedelta
-from gremlin_python import statics
-from gremlin_python.statics import FloatType, BigDecimal, FunctionType, ShortType, IntType, LongType, BigIntType, \
- TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, GremlinType, \
- SingleChar
-from gremlin_python.process.traversal import Barrier, Binding, Bytecode, Cardinality, Column, Direction, DT, Merge, \
- Operator, Order, Pick, Pop, P, Scope, TextP, Traversal, Traverser, \
- TraversalStrategy, T
-from gremlin_python.process.graph_traversal import GraphTraversal
-from gremlin_python.structure.graph import Graph, Edge, Property, Vertex, VertexProperty, Path
-from gremlin_python.structure.io.util import HashableDict, SymbolUtil
-
-log = logging.getLogger(__name__)
-
-# When we fall back to a superclass's serializer, we iterate over this map.
-# We want that iteration order to be consistent, so we use an OrderedDict,
-# not a dict.
-_serializers = OrderedDict()
-_deserializers = {}
-
-
-# TODO: to be removed
-class DataType(Enum):
- null = 0xfe
- int = 0x01
- long = 0x02
- string = 0x03
- date = 0x04
- timestamp = 0x05
- clazz = 0x06
- double = 0x07
- float = 0x08
- list = 0x09
- map = 0x0a
- set = 0x0b
- uuid = 0x0c
- edge = 0x0d
- path = 0x0e
- property = 0x0f
- graph = 0x10 # not supported - no graph object in python yet
- vertex = 0x11
- vertexproperty = 0x12
- barrier = 0x13
- binding = 0x14
- bytecode = 0x15
- cardinality = 0x16
- column = 0x17
- direction = 0x18
- operator = 0x19
- order = 0x1a
- pick = 0x1b
- pop = 0x1c
- lambda_ = 0x1d
- p = 0x1e
- scope = 0x1f
- t = 0x20
- traverser = 0x21
- bigdecimal = 0x22
- biginteger = 0x23
- byte = 0x24
- bytebuffer = 0x25
- short = 0x26
- boolean = 0x27
- textp = 0x28
- traversalstrategy = 0x29
- bulkset = 0x2a
- tree = 0x2b # not supported - no tree object in Python yet
- metrics = 0x2c
- traversalmetrics = 0x2d
- merge = 0x2e
- dt = 0x2f
- char = 0x80
- duration = 0x81
- inetaddress = 0x82 # todo
- instant = 0x83 # todo
- localdate = 0x84 # todo
- localdatetime = 0x85 # todo
- localtime = 0x86 # todo
- monthday = 0x87 # todo
- offsetdatetime = 0x88 # todo
- offsettime = 0x89 # todo
- period = 0x8a # todo
- year = 0x8b # todo
- yearmonth = 0x8c # todo
- zonedatetime = 0x8d # todo
- zoneoffset = 0x8e # todo
- custom = 0x00 # todo
-
-
-NULL_BYTES = [DataType.null.value, 0x01]
-
-
-def _make_packer(format_string):
- packer = struct.Struct(format_string)
- pack = packer.pack
- unpack = lambda s: packer.unpack(s)[0]
- return pack, unpack
-
-
-int64_pack, int64_unpack = _make_packer('>q')
-int32_pack, int32_unpack = _make_packer('>i')
-int16_pack, int16_unpack = _make_packer('>h')
-int8_pack, int8_unpack = _make_packer('>b')
-uint64_pack, uint64_unpack = _make_packer('>Q')
-uint8_pack, uint8_unpack = _make_packer('>B')
-float_pack, float_unpack = _make_packer('>f')
-double_pack, double_unpack = _make_packer('>d')
-
-
-class GraphBinaryTypeType(type):
- def __new__(mcs, name, bases, dct):
- cls = super(GraphBinaryTypeType, mcs).__new__(mcs, name, bases, dct)
- if not name.startswith('_'):
- if cls.python_type:
- _serializers[cls.python_type] = cls
- if cls.graphbinary_type:
- _deserializers[cls.graphbinary_type] = cls
- return cls
-
-
-class GraphBinaryWriter(object):
- def __init__(self, serializer_map=None):
- self.serializers = _serializers.copy()
- if serializer_map:
- self.serializers.update(serializer_map)
-
- def write_object(self, object_data):
- return self.to_dict(object_data)
-
- def to_dict(self, obj, to_extend=None):
- if to_extend is None:
- to_extend = bytearray()
-
- if obj is None:
- to_extend.extend(NULL_BYTES)
- return
-
- try:
- t = type(obj)
- return self.serializers[t].dictify(obj, self, to_extend)
- except KeyError:
- for key, serializer in self.serializers.items():
- if isinstance(obj, key):
- return serializer.dictify(obj, self, to_extend)
-
- if isinstance(obj, dict):
- return dict((self.to_dict(k, to_extend), self.to_dict(v, to_extend)) for k, v in obj.items())
- elif isinstance(obj, set):
- return set([self.to_dict(o, to_extend) for o in obj])
- elif isinstance(obj, list):
- return [self.to_dict(o, to_extend) for o in obj]
- else:
- return obj
-
-
-class GraphBinaryReader(object):
- def __init__(self, deserializer_map=None):
- self.deserializers = _deserializers.copy()
- if deserializer_map:
- self.deserializers.update(deserializer_map)
-
- def read_object(self, b):
- if isinstance(b, bytearray):
- return self.to_object(io.BytesIO(b))
- elif isinstance(b, io.BufferedIOBase):
- return self.to_object(b)
-
- def to_object(self, buff, data_type=None, nullable=True):
- if data_type is None:
- bt = uint8_unpack(buff.read(1))
- if bt == DataType.null.value:
- if nullable:
- buff.read(1)
- return None
- return self.deserializers[DataType(bt)].objectify(buff, self, nullable)
- else:
- return self.deserializers[data_type].objectify(buff, self, nullable)
-
-
-class _GraphBinaryTypeIO(object, metaclass=GraphBinaryTypeType):
- python_type = None
- graphbinary_type = None
-
- @classmethod
- def prefix_bytes(cls, graphbin_type, as_value=False, nullable=True, to_extend=None):
- if to_extend is None:
- to_extend = bytearray()
-
- if not as_value:
- to_extend += uint8_pack(graphbin_type.value)
-
- if nullable:
- to_extend += int8_pack(0)
-
- return to_extend
-
- @classmethod
- def read_int(cls, buff):
- return int32_unpack(buff.read(4))
-
- @classmethod
- def is_null(cls, buff, reader, else_opt, nullable=True):
- return None if nullable and buff.read(1)[0] == 0x01 else else_opt(buff, reader)
-
- def dictify(self, obj, writer, to_extend, as_value=False, nullable=True):
- raise NotImplementedError()
-
- def objectify(self, d, reader, nullable=True):
- raise NotImplementedError()
-
-
-class LongIO(_GraphBinaryTypeIO):
-
- python_type = LongType
- graphbinary_type = DataType.long
- byte_format_pack = int64_pack
- byte_format_unpack = int64_unpack
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- if obj < -9223372036854775808 or obj > 9223372036854775807:
- raise Exception("Value too big, please use bigint Gremlin type")
- else:
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(cls.byte_format_pack(obj))
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: int64_unpack(buff.read(8)), nullable)
-
-
-class IntIO(LongIO):
-
- python_type = IntType
- graphbinary_type = DataType.int
- byte_format_pack = int32_pack
- byte_format_unpack = int32_unpack
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: cls.read_int(b), nullable)
-
-
-class ShortIO(LongIO):
-
- python_type = ShortType
- graphbinary_type = DataType.short
- byte_format_pack = int16_pack
- byte_format_unpack = int16_unpack
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: int16_unpack(buff.read(2)), nullable)
-
-
-class BigIntIO(_GraphBinaryTypeIO):
-
- python_type = BigIntType
- graphbinary_type = DataType.biginteger
-
- @classmethod
- def write_bigint(cls, obj, to_extend):
- length = (obj.bit_length() + 7) // 8
- if obj > 0:
- b = obj.to_bytes(length, byteorder='big')
- to_extend.extend(int32_pack(length + 1))
- to_extend.extend(int8_pack(0))
- to_extend.extend(b)
- else:
- # handle negative
- b = obj.to_bytes(length, byteorder='big', signed=True)
- to_extend.extend(int32_pack(length))
- to_extend.extend(b)
- return to_extend
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- return cls.write_bigint(obj, to_extend)
-
- @classmethod
- def read_bigint(cls, buff):
- size = cls.read_int(buff)
- return int.from_bytes(buff.read(size), byteorder='big', signed=True)
-
- @classmethod
- def objectify(cls, buff, reader, nullable=False):
- return cls.is_null(buff, reader, lambda b, r: cls.read_bigint(b), nullable)
-
-
-class DateIO(_GraphBinaryTypeIO):
-
- python_type = datetime.datetime
- graphbinary_type = DataType.date
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- try:
- timestamp_seconds = calendar.timegm(obj.utctimetuple())
- pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
- except AttributeError:
- pts = calendar.timegm(obj.timetuple()) * 1e3
-
- ts = int(round(pts))
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int64_pack(ts))
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader,
- lambda b, r: datetime.datetime.utcfromtimestamp(int64_unpack(b.read(8)) / 1000.0),
- nullable)
-
-
-# Based on current implementation, this class must always be declared before FloatIO.
-# Seems pretty fragile for future maintainers. Maybe look into this.
-class TimestampIO(_GraphBinaryTypeIO):
- python_type = statics.timestamp
- graphbinary_type = DataType.timestamp
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- # Java timestamp expects milliseconds integer - Have to use int because of legacy Python
- ts = int(round(obj * 1000))
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int64_pack(ts))
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- # Python timestamp expects seconds
- return cls.is_null(buff, reader, lambda b, r: statics.timestamp(int64_unpack(b.read(8)) / 1000.0),
- nullable)
-
-
-def _long_bits_to_double(bits):
- return unpack('d', pack('Q', bits))[0]
-
-
-NAN = _long_bits_to_double(0x7ff8000000000000)
-POSITIVE_INFINITY = _long_bits_to_double(0x7ff0000000000000)
-NEGATIVE_INFINITY = _long_bits_to_double(0xFff0000000000000)
-
-
-class FloatIO(LongIO):
-
- python_type = FloatType
- graphbinary_type = DataType.float
- graphbinary_base_type = DataType.float
- byte_format_pack = float_pack
- byte_format_unpack = float_unpack
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- if math.isnan(obj):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(cls.byte_format_pack(NAN))
- elif math.isinf(obj) and obj > 0:
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(cls.byte_format_pack(POSITIVE_INFINITY))
- elif math.isinf(obj) and obj < 0:
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(cls.byte_format_pack(NEGATIVE_INFINITY))
- else:
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(cls.byte_format_pack(obj))
-
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: float_unpack(b.read(4)), nullable)
-
-
-class DoubleIO(FloatIO):
- """
- Floats basically just fall through to double serialization.
- """
-
- graphbinary_type = DataType.double
- graphbinary_base_type = DataType.double
- byte_format_pack = double_pack
- byte_format_unpack = double_unpack
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: double_unpack(b.read(8)), nullable)
-
-
-class BigDecimalIO(_GraphBinaryTypeIO):
-
- python_type = BigDecimal
- graphbinary_type = DataType.bigdecimal
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int32_pack(obj.scale))
- return BigIntIO.write_bigint(obj.unscaled_value, to_extend)
-
- @classmethod
- def _read(cls, buff):
- scale = int32_unpack(buff.read(4))
- unscaled_value = BigIntIO.read_bigint(buff)
- return BigDecimal(scale, unscaled_value)
-
- @classmethod
- def objectify(cls, buff, reader, nullable=False):
- return cls.is_null(buff, reader, lambda b, r: cls._read(b), nullable)
-
-
-class CharIO(_GraphBinaryTypeIO):
- python_type = SingleChar
- graphbinary_type = DataType.char
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(obj.encode("utf-8"))
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_char, nullable)
-
- @classmethod
- def _read_char(cls, b, r):
- max_bytes = 4
- x = b.read(1)
- while max_bytes > 0:
- max_bytes = max_bytes - 1
- try:
- return x.decode("utf-8")
- except UnicodeDecodeError:
- x += b.read(1)
-
-
-class StringIO(_GraphBinaryTypeIO):
-
- python_type = str
- graphbinary_type = DataType.string
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- str_bytes = obj.encode("utf-8")
- to_extend += int32_pack(len(str_bytes))
- to_extend += str_bytes
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: b.read(cls.read_int(b)).decode("utf-8"), nullable)
-
-
-class ListIO(_GraphBinaryTypeIO):
-
- python_type = list
- graphbinary_type = DataType.list
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int32_pack(len(obj)))
- for item in obj:
- writer.to_dict(item, to_extend)
-
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_list, nullable)
-
- @classmethod
- def _read_list(cls, b, r):
- size = cls.read_int(b)
- the_list = []
- while size > 0:
- the_list.append(r.read_object(b))
- size = size - 1
-
- return the_list
-
-
-class SetDeserializer(ListIO):
-
- python_type = SetType
- graphbinary_type = DataType.set
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return set(ListIO.objectify(buff, reader, nullable))
-
-
-class MapIO(_GraphBinaryTypeIO):
-
- python_type = DictType
- graphbinary_type = DataType.map
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
- to_extend.extend(int32_pack(len(obj)))
- for k, v in obj.items():
- writer.to_dict(k, to_extend)
- writer.to_dict(v, to_extend)
-
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_map, nullable)
-
- @classmethod
- def _read_map(cls, b, r):
- size = cls.read_int(b)
- the_dict = {}
- while size > 0:
- k = HashableDict.of(r.read_object(b))
- v = r.read_object(b)
- the_dict[k] = v
- size = size - 1
-
- return the_dict
-
-
-class UuidIO(_GraphBinaryTypeIO):
-
- python_type = uuid.UUID
- graphbinary_type = DataType.uuid
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(obj.bytes)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: uuid.UUID(bytes=b.read(16)), nullable)
-
-
-class EdgeIO(_GraphBinaryTypeIO):
-
- python_type = Edge
- graphbinary_type = DataType.edge
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
- writer.to_dict(obj.id, to_extend)
- StringIO.dictify(obj.label, writer, to_extend, True, False)
- writer.to_dict(obj.inV.id, to_extend)
- StringIO.dictify(obj.inV.label, writer, to_extend, True, False)
- writer.to_dict(obj.outV.id, to_extend)
- StringIO.dictify(obj.outV.label, writer, to_extend, True, False)
- to_extend.extend(NULL_BYTES)
- to_extend.extend(NULL_BYTES)
-
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_edge, nullable)
-
- @classmethod
- def _read_edge(cls, b, r):
- edgeid = r.read_object(b)
- edgelbl = r.to_object(b, DataType.string, False)
- inv = Vertex(r.read_object(b), r.to_object(b, DataType.string, False))
- outv = Vertex(r.read_object(b), r.to_object(b, DataType.string, False))
- b.read(2)
- properties = r.read_object(b)
- edge = Edge(edgeid, outv, edgelbl, inv, properties)
- return edge
-
-
-class PathIO(_GraphBinaryTypeIO):
-
- python_type = Path
- graphbinary_type = DataType.path
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- writer.to_dict(obj.labels, to_extend)
- writer.to_dict(obj.objects, to_extend)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: Path(r.read_object(b), r.read_object(b)), nullable)
-
-
-class PropertyIO(_GraphBinaryTypeIO):
-
- python_type = Property
- graphbinary_type = DataType.property
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- StringIO.dictify(obj.key, writer, to_extend, True, False)
- writer.to_dict(obj.value, to_extend)
- to_extend.extend(NULL_BYTES)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_property, nullable)
-
- @classmethod
- def _read_property(cls, b, r):
- p = Property(r.to_object(b, DataType.string, False), r.read_object(b), None)
- b.read(2)
- return p
-
-
-class TinkerGraphIO(_GraphBinaryTypeIO):
-
- python_type = Graph
- graphbinary_type = DataType.graph
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- raise AttributeError("TinkerGraph serialization is not currently supported by gremlin-python")
-
- @classmethod
- def objectify(cls, b, reader, as_value=False):
- raise AttributeError("TinkerGraph deserialization is not currently supported by gremlin-python")
-
-
-class VertexIO(_GraphBinaryTypeIO):
-
- python_type = Vertex
- graphbinary_type = DataType.vertex
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- writer.to_dict(obj.id, to_extend)
- StringIO.dictify(obj.label, writer, to_extend, True, False)
- to_extend.extend(NULL_BYTES)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_vertex, nullable)
-
- @classmethod
- def _read_vertex(cls, b, r):
- vertex = Vertex(r.read_object(b), r.to_object(b, DataType.string, False), r.read_object(b))
- return vertex
-
-
-class VertexPropertyIO(_GraphBinaryTypeIO):
-
- python_type = VertexProperty
- graphbinary_type = DataType.vertexproperty
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- writer.to_dict(obj.id, to_extend)
- StringIO.dictify(obj.label, writer, to_extend, True, False)
- writer.to_dict(obj.value, to_extend)
- to_extend.extend(NULL_BYTES)
- to_extend.extend(NULL_BYTES)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_vertexproperty, nullable)
-
- @classmethod
- def _read_vertexproperty(cls, b, r):
- vp = VertexProperty(r.read_object(b), r.to_object(b, DataType.string, False), r.read_object(b), None)
- b.read(2)
- vp.properties = r.read_object(b)
- return vp
-
-
-class _EnumIO(_GraphBinaryTypeIO):
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- StringIO.dictify(SymbolUtil.to_camel_case(str(obj.name)), writer, to_extend)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_enumval, nullable)
-
- @classmethod
- def _read_enumval(cls, b, r):
- enum_name = r.to_object(b)
- return cls.python_type[SymbolUtil.to_snake_case(enum_name)]
-
-
-class BarrierIO(_EnumIO):
- graphbinary_type = DataType.barrier
- python_type = Barrier
-
-
-class CardinalityIO(_EnumIO):
- graphbinary_type = DataType.cardinality
- python_type = Cardinality
-
-
-class ColumnIO(_EnumIO):
- graphbinary_type = DataType.column
- python_type = Column
-
-
-class DirectionIO(_EnumIO):
- graphbinary_type = DataType.direction
- python_type = Direction
-
- @classmethod
- def _read_enumval(cls, b, r):
- # Direction needs to retain all CAPS. note that to_/from_ are really just aliases of IN/OUT
- # so they don't need to be accounted for in serialization
- enum_name = r.to_object(b)
- return cls.python_type[enum_name]
-
-
-class OperatorIO(_EnumIO):
- graphbinary_type = DataType.operator
- python_type = Operator
-
-
-class OrderIO(_EnumIO):
- graphbinary_type = DataType.order
- python_type = Order
-
-
-class PickIO(_EnumIO):
- graphbinary_type = DataType.pick
- python_type = Pick
-
-
-class PopIO(_EnumIO):
- graphbinary_type = DataType.pop
- python_type = Pop
-
-
-class BindingIO(_GraphBinaryTypeIO):
-
- python_type = Binding
- graphbinary_type = DataType.binding
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- StringIO.dictify(obj.key, writer, to_extend, True, False)
- writer.to_dict(obj.value, to_extend)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, lambda b, r: Binding(r.to_object(b, DataType.string, False),
- reader.read_object(b)), nullable)
-
-
-class BytecodeIO(_GraphBinaryTypeIO):
- python_type = Bytecode
- graphbinary_type = DataType.bytecode
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- bc = obj.bytecode if isinstance(obj, Traversal) else obj
- to_extend.extend(int32_pack(len(bc.step_instructions)))
- for inst in bc.step_instructions:
- inst_name, inst_args = inst[0], inst[1:] if len(inst) > 1 else []
- StringIO.dictify(inst_name, writer, to_extend, True, False)
- to_extend.extend(int32_pack(len(inst_args)))
- for arg in inst_args:
- writer.to_dict(arg, to_extend)
-
- to_extend.extend(int32_pack(len(bc.source_instructions)))
- for inst in bc.source_instructions:
- inst_name, inst_args = inst[0], inst[1:] if len(inst) > 1 else []
- StringIO.dictify(inst_name, writer, to_extend, True, False)
- to_extend.extend(int32_pack(len(inst_args)))
- for arg in inst_args:
- if isinstance(arg, TypeType):
- writer.to_dict(GremlinType(arg().fqcn), to_extend)
- else:
- writer.to_dict(arg, to_extend)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_bytecode, nullable)
-
- @classmethod
- def _read_bytecode(cls, b, r):
- bytecode = Bytecode()
-
- step_count = cls.read_int(b)
- ix = 0
- while ix < step_count:
- inst = [r.to_object(b, DataType.string, False)]
- inst_ct = cls.read_int(b)
- iy = 0
- while iy < inst_ct:
- inst.append(r.read_object(b))
- iy += 1
- bytecode.step_instructions.append(inst)
- ix += 1
-
- source_count = cls.read_int(b)
- ix = 0
- while ix < source_count:
- inst = [r.to_object(b, DataType.string, False)]
- inst_ct = cls.read_int(b)
- iy = 0
- while iy < inst_ct:
- inst.append(r.read_object(b))
- iy += 1
- bytecode.source_instructions.append(inst)
- ix += 1
-
- return bytecode
-
-
-class TraversalIO(BytecodeIO):
- python_type = GraphTraversal
-
-
-class LambdaSerializer(_GraphBinaryTypeIO):
-
- python_type = FunctionType
- graphbinary_type = DataType.lambda_
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
- lambda_result = obj()
- script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
- language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
-
- StringIO.dictify(language, writer, to_extend, True, False)
-
- script_cleaned = script
- script_args = -1
-
- if language == "gremlin-groovy" and "->" in script:
- # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
- # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
- args = script[0:script.find("->")]
- script_args = 2 if "," in args else 1
-
- StringIO.dictify(script_cleaned, writer, to_extend, True, False)
- to_extend.extend(int32_pack(script_args))
-
- return to_extend
-
-
-class PSerializer(_GraphBinaryTypeIO):
- graphbinary_type = DataType.p
- python_type = P
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
- StringIO.dictify(obj.operator, writer, to_extend, True, False)
-
- args = []
- if obj.other is None:
- if isinstance(obj.value, ListType):
- args = obj.value
- else:
- args.append(obj.value)
- else:
- args.append(obj.value)
- args.append(obj.other)
-
- to_extend.extend(int32_pack(len(args)))
- for a in args:
- writer.to_dict(a, to_extend)
-
- return to_extend
-
-
-class DTIO(_EnumIO):
- graphbinary_type = DataType.dt
- python_type = DT
-
-
-class MergeIO(_EnumIO):
- graphbinary_type = DataType.merge
- python_type = Merge
-
-
-class ScopeIO(_EnumIO):
- graphbinary_type = DataType.scope
- python_type = Scope
-
-
-class TIO(_EnumIO):
- graphbinary_type = DataType.t
- python_type = T
-
-
-class TraverserIO(_GraphBinaryTypeIO):
- graphbinary_type = DataType.traverser
- python_type = Traverser
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int64_pack(obj.bulk))
- writer.to_dict(obj.object, to_extend)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_traverser, nullable)
-
- @classmethod
- def _read_traverser(cls, b, r):
- bulk = int64_unpack(b.read(8))
- obj = r.read_object(b)
- return Traverser(obj, bulk=bulk)
-
-
-class ByteIO(_GraphBinaryTypeIO):
- python_type = SingleByte
- graphbinary_type = DataType.byte
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int8_pack(obj))
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader,
- lambda b, r: int.__new__(SingleByte, int8_unpack(b.read(1))),
- nullable)
-
-
-class ByteBufferIO(_GraphBinaryTypeIO):
- python_type = ByteBufferType
- graphbinary_type = DataType.bytebuffer
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int32_pack(len(obj)))
- to_extend.extend(obj)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_bytebuffer, nullable)
-
- @classmethod
- def _read_bytebuffer(cls, b, r):
- size = cls.read_int(b)
- return ByteBufferType(b.read(size))
-
-
-class BooleanIO(_GraphBinaryTypeIO):
- python_type = bool
- graphbinary_type = DataType.boolean
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- to_extend.extend(int8_pack(0x01 if obj else 0x00))
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader,
- lambda b, r: True if int8_unpack(b.read(1)) == 0x01 else False,
- nullable)
-
-
-class TextPSerializer(_GraphBinaryTypeIO):
- graphbinary_type = DataType.textp
- python_type = TextP
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
- StringIO.dictify(obj.operator, writer, to_extend, True, False)
-
- args = []
- if obj.other is None:
- if isinstance(obj.value, ListType):
- args = obj.value
- else:
- args.append(obj.value)
- else:
- args.append(obj.value)
- args.append(obj.other)
-
- to_extend.extend(int32_pack(len(args)))
- for a in args:
- writer.to_dict(a, to_extend)
-
- return to_extend
-
-
-class BulkSetDeserializer(_GraphBinaryTypeIO):
-
- graphbinary_type = DataType.bulkset
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_bulkset, nullable)
-
- @classmethod
- def _read_bulkset(cls, b, r):
- size = cls.read_int(b)
- the_list = []
- while size > 0:
- itm = r.read_object(b)
- bulk = int64_unpack(b.read(8))
- for y in range(bulk):
- the_list.append(itm)
- size = size - 1
-
- return the_list
-
-
-class MetricsDeserializer(_GraphBinaryTypeIO):
-
- graphbinary_type = DataType.metrics
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_metrics, nullable)
-
- @classmethod
- def _read_metrics(cls, b, r):
- metricid = r.to_object(b, DataType.string, False)
- name = r.to_object(b, DataType.string, False)
- duration = r.to_object(b, DataType.long, nullable=False)
- counts = r.to_object(b, DataType.map, nullable=False)
- annotations = r.to_object(b, DataType.map, nullable=False)
- metrics = r.to_object(b, DataType.list, nullable=False)
-
- return {"id": metricid,
- "name": name,
- "dur": duration,
- "counts": counts,
- "annotations": annotations,
- "metrics": metrics}
-
-
-class TraversalMetricsDeserializer(_GraphBinaryTypeIO):
-
- graphbinary_type = DataType.traversalmetrics
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_traversalmetrics, nullable)
-
- @classmethod
- def _read_traversalmetrics(cls, b, r):
- duration = r.to_object(b, DataType.long, nullable=False)
- metrics = r.to_object(b, DataType.list, nullable=False)
-
- return {"dur": duration,
- "metrics": metrics}
-
-
-class ClassSerializer(_GraphBinaryTypeIO):
- graphbinary_type = DataType.clazz
- python_type = GremlinType
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- StringIO.dictify(obj.gremlin_type, writer, to_extend, True, False)
- return to_extend
-
-
-class TraversalStrategySerializer(_GraphBinaryTypeIO):
- graphbinary_type = DataType.traversalstrategy
- python_type = TraversalStrategy
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
-
- ClassSerializer.dictify(GremlinType(obj.fqcn), writer, to_extend, True, False)
- conf = {k: cls._convert(v) for k, v in obj.configuration.items()}
- MapIO.dictify(conf, writer, to_extend, True, False)
-
- return to_extend
-
- @classmethod
- def _convert(cls, v):
- return v.bytecode if isinstance(v, Traversal) else v
-
-
-class DurationIO(_GraphBinaryTypeIO):
- python_type = timedelta
- graphbinary_type = DataType.duration
-
- @classmethod
- def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
- cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
- LongIO.dictify(obj.seconds, writer, to_extend, True, False)
- IntIO.dictify(obj.microseconds * 1000, writer, to_extend, True, False)
- return to_extend
-
- @classmethod
- def objectify(cls, buff, reader, nullable=True):
- return cls.is_null(buff, reader, cls._read_duration, nullable)
-
- @classmethod
- def _read_duration(cls, b, r):
- seconds = r.to_object(b, DataType.long, False)
- nanos = r.to_object(b, DataType.int, False)
- return timedelta(seconds=seconds, microseconds=nanos / 1000)
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py
deleted file mode 100644
index 3e18ec6ac1..0000000000
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py
+++ /dev/null
@@ -1,664 +0,0 @@
-#
-# 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.
-#
-
-import calendar
-import datetime
-import json
-import uuid
-import math
-from collections import OrderedDict
-from decimal import *
-from datetime import timedelta
-
-from aenum import Enum
-from isodate import parse_duration, duration_isoformat
-
-from gremlin_python import statics
-from gremlin_python.statics import FloatType, FunctionType, ShortType, IntType, LongType, TypeType, SingleByte, ByteBufferType, SingleChar
-from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy
-from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
-from gremlin_python.structure.io.util import SymbolUtil
-
-# When we fall back to a superclass's serializer, we iterate over this map.
-# We want that iteration order to be consistent, so we use an OrderedDict,
-# not a dict.
-_serializers = OrderedDict()
-_deserializers = {}
-
-
-# TODO: to be removed
-class GraphSONTypeType(type):
- def __new__(mcs, name, bases, dct):
- cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
- if not name.startswith('_'):
- if cls.python_type:
- _serializers[cls.python_type] = cls
- if cls.graphson_type:
- _deserializers[cls.graphson_type] = cls
- return cls
-
-
-class GraphSONUtil(object):
- TYPE_KEY = "@type"
- VALUE_KEY = "@value"
-
- @classmethod
- def typed_value(cls, type_name, value, prefix="g"):
- out = {cls.TYPE_KEY: cls.format_type(prefix, type_name)}
- if value is not None:
- out[cls.VALUE_KEY] = value
- return out
-
- @classmethod
- def format_type(cls, prefix, type_name):
- return "%s:%s" % (prefix, type_name)
-
-
-# Read/Write classes split to follow precedence of the Java API
-class GraphSONWriter(object):
- def __init__(self, serializer_map=None):
- """
- :param serializer_map: map from Python type to serializer instance implementing `dictify`
- """
- self.serializers = _serializers.copy()
- if serializer_map:
- self.serializers.update(serializer_map)
-
- def write_object(self, objectData):
- # to JSON
- return json.dumps(self.to_dict(objectData), separators=(',', ':'))
-
- def to_dict(self, obj):
- """
- Encodes python objects in GraphSON type-tagged dict values
- """
- try:
- return self.serializers[type(obj)].dictify(obj, self)
- except KeyError:
- for key, serializer in self.serializers.items():
- if isinstance(obj, key):
- return serializer.dictify(obj, self)
-
- # list and map are treated as normal json objs (could be isolated serializers)
- if isinstance(obj, (list, set)):
- return [self.to_dict(o) for o in obj]
- elif isinstance(obj, dict):
- return dict((self.to_dict(k), self.to_dict(v)) for k, v in obj.items())
- else:
- return obj
-
-
-class GraphSONReader(object):
- def __init__(self, deserializer_map=None):
- """
- :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
- """
- self.deserializers = _deserializers.copy()
- if deserializer_map:
- self.deserializers.update(deserializer_map)
-
- def read_object(self, json_data):
- # from JSON
- return self.to_object(json.loads(json_data))
-
- def to_object(self, obj):
- """
- Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
- """
- if isinstance(obj, dict):
- try:
- return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
- except KeyError:
- pass
- # list and map are treated as normal json objs (could be isolated deserializers)
- return dict((self.to_object(k), self.to_object(v)) for k, v in obj.items())
- elif isinstance(obj, list):
- return [self.to_object(o) for o in obj]
- else:
- return obj
-
-
-class _GraphSONTypeIO(object, metaclass=GraphSONTypeType):
- python_type = None
- graphson_type = None
-
- def dictify(self, obj, writer):
- raise NotImplementedError()
-
- def objectify(self, d, reader):
- raise NotImplementedError()
-
-
-class _BytecodeSerializer(_GraphSONTypeIO):
- @classmethod
- def _dictify_instructions(cls, instructions, writer):
- out = []
- for instruction in instructions:
- inst = [instruction[0]]
- inst.extend(writer.to_dict(arg) for arg in instruction[1:])
- out.append(inst)
- return out
-
- @classmethod
- def dictify(cls, bytecode, writer):
- if isinstance(bytecode, Traversal):
- bytecode = bytecode.bytecode
- out = {}
- if bytecode.source_instructions:
- out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
- if bytecode.step_instructions:
- out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
- return GraphSONUtil.typed_value("Bytecode", out)
-
-class TraversalSerializer(_BytecodeSerializer):
- python_type = Traversal
-
-
-class BytecodeSerializer(_BytecodeSerializer):
- python_type = Bytecode
-
-
-class VertexSerializer(_GraphSONTypeIO):
- python_type = Vertex
- graphson_type = "g:Vertex"
-
- @classmethod
- def dictify(cls, vertex, writer):
- return GraphSONUtil.typed_value("Vertex", {"id": writer.to_dict(vertex.id),
- "label": writer.to_dict(vertex.label)})
-
-
-class EdgeSerializer(_GraphSONTypeIO):
- python_type = Edge
- graphson_type = "g:Edge"
-
- @classmethod
- def dictify(cls, edge, writer):
- return GraphSONUtil.typed_value("Edge", {"id": writer.to_dict(edge.id),
- "outV": writer.to_dict(edge.outV.id),
- "outVLabel": writer.to_dict(edge.outV.label),
- "label": writer.to_dict(edge.label),
- "inV": writer.to_dict(edge.inV.id),
- "inVLabel": writer.to_dict(edge.inV.label)})
-
-
-class VertexPropertySerializer(_GraphSONTypeIO):
- python_type = VertexProperty
- graphson_type = "g:VertexProperty"
-
- @classmethod
- def dictify(cls, vertex_property, writer):
- return GraphSONUtil.typed_value("VertexProperty", {"id": writer.to_dict(vertex_property.id),
- "label": writer.to_dict(vertex_property.label),
- "value": writer.to_dict(vertex_property.value),
- "vertex": writer.to_dict(vertex_property.vertex.id)})
-
-
-class PropertySerializer(_GraphSONTypeIO):
- python_type = Property
- graphson_type = "g:Property"
-
- @classmethod
- def dictify(cls, property, writer):
- element_dict = writer.to_dict(property.element)
- if element_dict is not None:
- value_dict = element_dict["@value"]
- if "outVLabel" in value_dict:
- del value_dict["outVLabel"]
- if "inVLabel" in value_dict:
- del value_dict["inVLabel"]
- if "properties" in value_dict:
- del value_dict["properties"]
- if "value" in value_dict:
- del value_dict["value"]
- return GraphSONUtil.typed_value("Property", {"key": writer.to_dict(property.key),
- "value": writer.to_dict(property.value),
- "element": element_dict})
-
-
-class TraversalStrategySerializer(_GraphSONTypeIO):
- python_type = TraversalStrategy
-
- @classmethod
- def dictify(cls, strategy, writer):
- return GraphSONUtil.typed_value(strategy.strategy_name, writer.to_dict(strategy.configuration))
-
-
-class TraverserIO(_GraphSONTypeIO):
- python_type = Traverser
- graphson_type = "g:Traverser"
-
- @classmethod
- def dictify(cls, traverser, writer):
- return GraphSONUtil.typed_value("Traverser", {"value": writer.to_dict(traverser.object),
- "bulk": writer.to_dict(traverser.bulk)})
-
- @classmethod
- def objectify(cls, d, reader):
- return Traverser(reader.to_object(d["value"]),
- reader.to_object(d["bulk"]))
-
-
-class EnumSerializer(_GraphSONTypeIO):
- python_type = Enum
-
- @classmethod
- def dictify(cls, enum, _):
- return GraphSONUtil.typed_value(SymbolUtil.to_camel_case(type(enum).__name__),
- SymbolUtil.to_camel_case(str(enum.name)))
-
-
-class PSerializer(_GraphSONTypeIO):
- python_type = P
-
- @classmethod
- def dictify(cls, p, writer):
- out = {"predicate": p.operator,
- "value": [writer.to_dict(p.value), writer.to_dict(p.other)] if p.other is not None else
- writer.to_dict(p.value)}
- return GraphSONUtil.typed_value("P", out)
-
-
-class TextPSerializer(_GraphSONTypeIO):
- python_type = TextP
-
- @classmethod
- def dictify(cls, p, writer):
- out = {"predicate": p.operator,
- "value": [writer.to_dict(p.value), writer.to_dict(p.other)] if p.other is not None else
- writer.to_dict(p.value)}
- return GraphSONUtil.typed_value("TextP", out)
-
-
-class BindingSerializer(_GraphSONTypeIO):
- python_type = Binding
-
- @classmethod
- def dictify(cls, binding, writer):
- out = {"key": binding.key,
- "value": writer.to_dict(binding.value)}
- return GraphSONUtil.typed_value("Binding", out)
-
-
-class LambdaSerializer(_GraphSONTypeIO):
- python_type = FunctionType
-
- @classmethod
- def dictify(cls, lambda_object, writer):
- lambda_result = lambda_object()
- script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
- language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
- out = {"script": script,
- "language": language}
- if language == "gremlin-groovy" and "->" in script:
- # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
- # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
- args = script[0:script.find("->")]
- out["arguments"] = 2 if "," in args else 1
- else:
- out["arguments"] = -1
-
- return GraphSONUtil.typed_value("Lambda", out)
-
-
-class TypeSerializer(_GraphSONTypeIO):
- python_type = TypeType
-
- @classmethod
- def dictify(cls, typ, writer):
- return writer.to_dict(typ())
-
-
-class UUIDIO(_GraphSONTypeIO):
- python_type = uuid.UUID
- graphson_type = "g:UUID"
- graphson_base_type = "UUID"
-
- @classmethod
- def dictify(cls, obj, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, str(obj))
-
- @classmethod
- def objectify(cls, d, reader):
- return cls.python_type(d)
-
-
-class DateIO(_GraphSONTypeIO):
- python_type = datetime.datetime
- graphson_type = "g:Date"
- graphson_base_type = "Date"
-
- @classmethod
- def dictify(cls, obj, writer):
- try:
- timestamp_seconds = calendar.timegm(obj.utctimetuple())
- pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
- except AttributeError:
- pts = calendar.timegm(obj.timetuple()) * 1e3
-
- ts = int(round(pts))
- return GraphSONUtil.typed_value(cls.graphson_base_type, ts)
-
- @classmethod
- def objectify(cls, ts, reader):
- # Python timestamp expects seconds
- return datetime.datetime.utcfromtimestamp(ts / 1000.0)
-
-
-# Based on current implementation, this class must always be declared before FloatIO.
-# Seems pretty fragile for future maintainers. Maybe look into this.
-class TimestampIO(_GraphSONTypeIO):
- """A timestamp in Python is type float"""
- python_type = statics.timestamp
- graphson_type = "g:Timestamp"
- graphson_base_type = "Timestamp"
-
- @classmethod
- def dictify(cls, obj, writer):
- # Java timestamp expects milliseconds integer
- # Have to use int because of legacy Python
- ts = int(round(obj * 1000))
- return GraphSONUtil.typed_value(cls.graphson_base_type, ts)
-
- @classmethod
- def objectify(cls, ts, reader):
- # Python timestamp expects seconds
- return cls.python_type(ts / 1000.0)
-
-
-class _NumberIO(_GraphSONTypeIO):
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
- @classmethod
- def objectify(cls, v, _):
- return cls.python_type(v)
-
-
-class FloatIO(_NumberIO):
- python_type = FloatType
- graphson_type = "g:Float"
- graphson_base_type = "Float"
-
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- elif math.isnan(n):
- return GraphSONUtil.typed_value(cls.graphson_base_type, "NaN")
- elif math.isinf(n) and n > 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "Infinity")
- elif math.isinf(n) and n < 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "-Infinity")
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
- @classmethod
- def objectify(cls, v, _):
- if isinstance(v, str):
- if v == 'NaN':
- return float('nan')
- elif v == "Infinity":
- return float('inf')
- elif v == "-Infinity":
- return float('-inf')
-
- return cls.python_type(v)
-
-
-class BigDecimalIO(_NumberIO):
- python_type = Decimal
- graphson_type = "gx:BigDecimal"
- graphson_base_type = "BigDecimal"
-
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- elif math.isnan(n):
- return GraphSONUtil.typed_value(cls.graphson_base_type, "NaN", "gx")
- elif math.isinf(n) and n > 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "Infinity", "gx")
- elif math.isinf(n) and n < 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "-Infinity", "gx")
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, str(n), "gx")
-
- @classmethod
- def objectify(cls, v, _):
- if isinstance(v, str):
- if v == 'NaN':
- return Decimal('nan')
- elif v == "Infinity":
- return Decimal('inf')
- elif v == "-Infinity":
- return Decimal('-inf')
-
- return Decimal(v)
-
-
-class DoubleIO(FloatIO):
- graphson_type = "g:Double"
- graphson_base_type = "Double"
-
-
-class Int64IO(_NumberIO):
- python_type = LongType
- graphson_type = "g:Int64"
- graphson_base_type = "Int64"
-
- @classmethod
- def dictify(cls, n, writer):
- # if we exceed Java long range then we need a BigInteger
- if isinstance(n, bool):
- return n
- elif n < -9223372036854775808 or n > 9223372036854775807:
- return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
-
-class BigIntegerIO(Int64IO):
- graphson_type = "gx:BigInteger"
-
-
-class Int32IO(Int64IO):
- python_type = IntType
- graphson_type = "g:Int32"
- graphson_base_type = "Int32"
-
- @classmethod
- def dictify(cls, n, writer):
- # if we exceed Java int range then we need a long
- if isinstance(n, bool):
- return n
- elif n < -9223372036854775808 or n > 9223372036854775807:
- return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
- elif n < -2147483648 or n > 2147483647:
- return GraphSONUtil.typed_value("Int64", n)
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
-
-class Int16IO(Int64IO):
- python_type = ShortType
- graphson_type = "gx:Int16"
- graphson_base_type = "Int16"
-
- @classmethod
- def dictify(cls, n, writer):
- # if we exceed Java int range then we need a long
- if isinstance(n, bool):
- return n
- elif n < -9223372036854775808 or n > 9223372036854775807:
- return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
- elif n < -2147483648 or n > 2147483647:
- return GraphSONUtil.typed_value("Int64", n)
- elif n < -32768 or n > 32767:
- return GraphSONUtil.typed_value("Int32", n)
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return int.__new__(ShortType, v)
-
-
-class ByteIO(_NumberIO):
- python_type = SingleByte
- graphson_type = "gx:Byte"
- graphson_base_type = "Byte"
-
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return int.__new__(SingleByte, v)
-
-
-class ByteBufferIO(_GraphSONTypeIO):
- python_type = ByteBufferType
- graphson_type = "gx:ByteBuffer"
- graphson_base_type = "ByteBuffer"
-
- @classmethod
- def dictify(cls, n, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, "".join(chr(x) for x in n), "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return cls.python_type(v, "utf8")
-
-
-class CharIO(_GraphSONTypeIO):
- python_type = SingleChar
- graphson_type = "gx:Char"
- graphson_base_type = "Char"
-
- @classmethod
- def dictify(cls, n, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return str.__new__(SingleChar, v)
-
-
-class DurationIO(_GraphSONTypeIO):
- python_type = timedelta
- graphson_type = "gx:Duration"
- graphson_base_type = "Duration"
-
- @classmethod
- def dictify(cls, n, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, duration_isoformat(n), "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return parse_duration(v)
-
-
-class VertexDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Vertex"
-
- @classmethod
- def objectify(cls, d, reader):
- properties = None
- if "properties" in d:
- properties = reader.to_object(d["properties"])
- if properties is not None:
- properties = [item for sublist in properties.values() for item in sublist]
- return Vertex(reader.to_object(d["id"]), d.get("label", "vertex"), properties)
-
-
-class EdgeDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Edge"
-
- @classmethod
- def objectify(cls, d, reader):
- properties = None
- if "properties" in d:
- properties = reader.to_object(d["properties"])
- if properties is not None:
- properties = list(properties.values())
- return Edge(reader.to_object(d["id"]),
- Vertex(reader.to_object(d["outV"]), d.get("outVLabel", "vertex")),
- d.get("label", "edge"),
- Vertex(reader.to_object(d["inV"]), d.get("inVLabel", "vertex")),
- properties)
-
-
-class VertexPropertyDeserializer(_GraphSONTypeIO):
- graphson_type = "g:VertexProperty"
-
- @classmethod
- def objectify(cls, d, reader):
- properties = None
- if "properties" in d:
- properties = reader.to_object(d["properties"])
- if properties is not None:
- properties = list(map(lambda x: Property(x[0], x[1], None), properties.items()))
- vertex = Vertex(reader.to_object(d.get("vertex"))) if "vertex" in d else None
- return VertexProperty(reader.to_object(d["id"]),
- d["label"],
- reader.to_object(d["value"]),
- vertex,
- properties)
-
-
-class PropertyDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Property"
-
- @classmethod
- def objectify(cls, d, reader):
- element = reader.to_object(d["element"]) if "element" in d else None
- return Property(d["key"], reader.to_object(d["value"]), element)
-
-
-class PathDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Path"
-
- @classmethod
- def objectify(cls, d, reader):
- labels = [set(label) for label in d["labels"]]
- objects = [reader.to_object(o) for o in d["objects"]]
- return Path(labels, objects)
-
-
-class TraversalMetricsDeserializer(_GraphSONTypeIO):
- graphson_type = "g:TraversalMetrics"
-
- @classmethod
- def objectify(cls, d, reader):
- return reader.to_object(d)
-
-
-class MetricsDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Metrics"
-
- @classmethod
- def objectify(cls, d, reader):
- return reader.to_object(d)
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py
deleted file mode 100644
index 932d17088a..0000000000
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py
+++ /dev/null
@@ -1,784 +0,0 @@
-# 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.
-
-import calendar
-import datetime
-import json
-import uuid
-import math
-from collections import OrderedDict
-from decimal import *
-import logging
-from datetime import timedelta
-
-from aenum import Enum
-from isodate import parse_duration, duration_isoformat
-
-from gremlin_python import statics
-from gremlin_python.statics import FloatType, FunctionType, ShortType, IntType, LongType, TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, SingleChar
-from gremlin_python.process.traversal import Binding, Bytecode, Direction, P, TextP, Traversal, Traverser, TraversalStrategy, T
-from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
-from gremlin_python.structure.io.util import HashableDict, SymbolUtil
-
-log = logging.getLogger(__name__)
-
-# When we fall back to a superclass's serializer, we iterate over this map.
-# We want that iteration order to be consistent, so we use an OrderedDict,
-# not a dict.
-_serializers = OrderedDict()
-_deserializers = {}
-
-
-# TODO: to be removed
-class GraphSONTypeType(type):
- def __new__(mcs, name, bases, dct):
- cls = super(GraphSONTypeType, mcs).__new__(mcs, name, bases, dct)
- if not name.startswith('_'):
- if cls.python_type:
- _serializers[cls.python_type] = cls
- if cls.graphson_type:
- _deserializers[cls.graphson_type] = cls
- return cls
-
-
-class GraphSONUtil(object):
- TYPE_KEY = "@type"
- VALUE_KEY = "@value"
-
- @classmethod
- def typed_value(cls, type_name, value, prefix="g"):
- out = {cls.TYPE_KEY: cls.format_type(prefix, type_name)}
- if value is not None:
- out[cls.VALUE_KEY] = value
- return out
-
- @classmethod
- def format_type(cls, prefix, type_name):
- return "%s:%s" % (prefix, type_name)
-
-
-# Read/Write classes split to follow precedence of the Java API
-class GraphSONWriter(object):
- def __init__(self, serializer_map=None):
- """
- :param serializer_map: map from Python type to serializer instance implementing `dictify`
- """
- self.serializers = _serializers.copy()
- if serializer_map:
- self.serializers.update(serializer_map)
-
- def write_object(self, objectData):
- # to JSON
- return json.dumps(self.to_dict(objectData), separators=(',', ':'))
-
- def to_dict(self, obj):
- """
- Encodes python objects in GraphSON type-tagged dict values
- """
- try:
- return self.serializers[type(obj)].dictify(obj, self)
- except KeyError:
- for key, serializer in self.serializers.items():
- if isinstance(obj, key):
- return serializer.dictify(obj, self)
-
- if isinstance(obj, dict):
- return dict((self.to_dict(k), self.to_dict(v)) for k, v in obj.items())
- elif isinstance(obj, set):
- return set([self.to_dict(o) for o in obj])
- elif isinstance(obj, list):
- return [self.to_dict(o) for o in obj]
- else:
- return obj
-
-
-class GraphSONReader(object):
- def __init__(self, deserializer_map=None):
- """
- :param deserializer_map: map from GraphSON type tag to deserializer instance implementing `objectify`
- """
- self.deserializers = _deserializers.copy()
- if deserializer_map:
- self.deserializers.update(deserializer_map)
-
- def read_object(self, json_data):
- # from JSON
- return self.to_object(json.loads(json_data))
-
- def to_object(self, obj):
- """
- Unpacks GraphSON type-tagged dict values into objects mapped in self.deserializers
- """
- if isinstance(obj, dict):
- try:
- return self.deserializers[obj[GraphSONUtil.TYPE_KEY]].objectify(obj[GraphSONUtil.VALUE_KEY], self)
- except KeyError:
- pass
- return dict((self.to_object(k), self.to_object(v)) for k, v in obj.items())
- elif isinstance(obj, set):
- return set([self.to_object(o) for o in obj])
- elif isinstance(obj, list):
- return [self.to_object(o) for o in obj]
- else:
- return obj
-
-
-class _GraphSONTypeIO(object, metaclass=GraphSONTypeType):
- python_type = None
- graphson_type = None
-
- def dictify(self, obj, writer):
- raise NotImplementedError()
-
- def objectify(self, d, reader):
- raise NotImplementedError()
-
-
-class _BytecodeSerializer(_GraphSONTypeIO):
- @classmethod
- def _dictify_instructions(cls, instructions, writer):
- out = []
- for instruction in instructions:
- inst = [instruction[0]]
- inst.extend(writer.to_dict(arg) for arg in instruction[1:])
- out.append(inst)
- return out
-
- @classmethod
- def dictify(cls, bytecode, writer):
- if isinstance(bytecode, Traversal):
- bytecode = bytecode.bytecode
- out = {}
- if bytecode.source_instructions:
- out["source"] = cls._dictify_instructions(bytecode.source_instructions, writer)
- if bytecode.step_instructions:
- out["step"] = cls._dictify_instructions(bytecode.step_instructions, writer)
- return GraphSONUtil.typed_value("Bytecode", out)
-
-
-class TraversalSerializer(_BytecodeSerializer):
- python_type = Traversal
-
-
-class BytecodeSerializer(_BytecodeSerializer):
- python_type = Bytecode
-
-
-class VertexSerializer(_GraphSONTypeIO):
- python_type = Vertex
- graphson_type = "g:Vertex"
-
- @classmethod
- def dictify(cls, vertex, writer):
- return GraphSONUtil.typed_value("Vertex", {"id": writer.to_dict(vertex.id),
- "label": writer.to_dict(vertex.label)})
-
-
-class EdgeSerializer(_GraphSONTypeIO):
- python_type = Edge
- graphson_type = "g:Edge"
-
- @classmethod
- def dictify(cls, edge, writer):
- return GraphSONUtil.typed_value("Edge", {"id": writer.to_dict(edge.id),
- "outV": writer.to_dict(edge.outV.id),
- "outVLabel": writer.to_dict(edge.outV.label),
- "label": writer.to_dict(edge.label),
- "inV": writer.to_dict(edge.inV.id),
- "inVLabel": writer.to_dict(edge.inV.label)})
-
-
-class VertexPropertySerializer(_GraphSONTypeIO):
- python_type = VertexProperty
- graphson_type = "g:VertexProperty"
-
- @classmethod
- def dictify(cls, vertex_property, writer):
- return GraphSONUtil.typed_value("VertexProperty", {"id": writer.to_dict(vertex_property.id),
- "label": writer.to_dict(vertex_property.label),
- "value": writer.to_dict(vertex_property.value),
- "vertex": writer.to_dict(vertex_property.vertex.id)})
-
-
-class PropertySerializer(_GraphSONTypeIO):
- python_type = Property
- graphson_type = "g:Property"
-
- @classmethod
- def dictify(cls, property, writer):
- elementDict = writer.to_dict(property.element)
- if elementDict is not None:
- valueDict = elementDict["@value"]
- if "outVLabel" in valueDict:
- del valueDict["outVLabel"]
- if "inVLabel" in valueDict:
- del valueDict["inVLabel"]
- if "properties" in valueDict:
- del valueDict["properties"]
- if "value" in valueDict:
- del valueDict["value"]
- return GraphSONUtil.typed_value("Property", {"key": writer.to_dict(property.key),
- "value": writer.to_dict(property.value),
- "element": elementDict})
-
-
-class TraversalStrategySerializer(_GraphSONTypeIO):
- python_type = TraversalStrategy
-
- @classmethod
- def dictify(cls, strategy, writer):
- configuration = {}
- for key in strategy.configuration:
- configuration[key] = writer.to_dict(strategy.configuration[key])
- return GraphSONUtil.typed_value(strategy.strategy_name, configuration)
-
-
-class TraverserIO(_GraphSONTypeIO):
- python_type = Traverser
- graphson_type = "g:Traverser"
-
- @classmethod
- def dictify(cls, traverser, writer):
- return GraphSONUtil.typed_value("Traverser", {"value": writer.to_dict(traverser.object),
- "bulk": writer.to_dict(traverser.bulk)})
-
- @classmethod
- def objectify(cls, d, reader):
- return Traverser(reader.to_object(d["value"]),
- reader.to_object(d["bulk"]))
-
-
-class EnumSerializer(_GraphSONTypeIO):
- python_type = Enum
-
- @classmethod
- def dictify(cls, enum, _):
- return GraphSONUtil.typed_value(SymbolUtil.to_camel_case(type(enum).__name__),
- SymbolUtil.to_camel_case(str(enum.name)))
-
-
-class PSerializer(_GraphSONTypeIO):
- python_type = P
-
- @classmethod
- def dictify(cls, p, writer):
- out = {"predicate": p.operator,
- "value": [writer.to_dict(p.value), writer.to_dict(p.other)] if p.other is not None else
- writer.to_dict(p.value)}
- return GraphSONUtil.typed_value("P", out)
-
-
-class TextPSerializer(_GraphSONTypeIO):
- python_type = TextP
-
- @classmethod
- def dictify(cls, p, writer):
- out = {"predicate": p.operator,
- "value": [writer.to_dict(p.value), writer.to_dict(p.other)] if p.other is not None else
- writer.to_dict(p.value)}
- return GraphSONUtil.typed_value("TextP", out)
-
-
-class BindingSerializer(_GraphSONTypeIO):
- python_type = Binding
-
- @classmethod
- def dictify(cls, binding, writer):
- out = {"key": binding.key,
- "value": writer.to_dict(binding.value)}
- return GraphSONUtil.typed_value("Binding", out)
-
-
-class LambdaSerializer(_GraphSONTypeIO):
- python_type = FunctionType
-
- @classmethod
- def dictify(cls, lambda_object, writer):
- lambda_result = lambda_object()
- script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
- language = statics.default_lambda_language if isinstance(lambda_result, str) else lambda_result[1]
- out = {"script": script,
- "language": language}
- if language == "gremlin-groovy" and "->" in script:
- # if the user has explicitly added parameters to the groovy closure then we can easily detect one or two
- # arg lambdas - if we can't detect 1 or 2 then we just go with "unknown"
- args = script[0:script.find("->")]
- out["arguments"] = 2 if "," in args else 1
- else:
- out["arguments"] = -1
-
- return GraphSONUtil.typed_value("Lambda", out)
-
-
-class TypeSerializer(_GraphSONTypeIO):
- python_type = TypeType
-
- @classmethod
- def dictify(cls, typ, writer):
- return writer.to_dict(typ())
-
-
-class UUIDIO(_GraphSONTypeIO):
- python_type = uuid.UUID
- graphson_type = "g:UUID"
- graphson_base_type = "UUID"
-
- @classmethod
- def dictify(cls, obj, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, str(obj))
-
- @classmethod
- def objectify(cls, d, reader):
- return cls.python_type(d)
-
-
-class DateIO(_GraphSONTypeIO):
- python_type = datetime.datetime
- graphson_type = "g:Date"
- graphson_base_type = "Date"
-
- @classmethod
- def dictify(cls, obj, writer):
- try:
- timestamp_seconds = calendar.timegm(obj.utctimetuple())
- pts = timestamp_seconds * 1e3 + getattr(obj, 'microsecond', 0) / 1e3
- except AttributeError:
- pts = calendar.timegm(obj.timetuple()) * 1e3
-
- ts = int(round(pts))
- return GraphSONUtil.typed_value(cls.graphson_base_type, ts)
-
- @classmethod
- def objectify(cls, ts, reader):
- # Python timestamp expects seconds
- return datetime.datetime.utcfromtimestamp(ts / 1000.0)
-
-
-# Based on current implementation, this class must always be declared before FloatIO.
-# Seems pretty fragile for future maintainers. Maybe look into this.
-class TimestampIO(_GraphSONTypeIO):
- """A timestamp in Python is type float"""
- python_type = statics.timestamp
- graphson_type = "g:Timestamp"
- graphson_base_type = "Timestamp"
-
- @classmethod
- def dictify(cls, obj, writer):
- # Java timestamp expects milliseconds integer
- # Have to use int because of legacy Python
- ts = int(round(obj * 1000))
- return GraphSONUtil.typed_value(cls.graphson_base_type, ts)
-
- @classmethod
- def objectify(cls, ts, reader):
- # Python timestamp expects seconds
- return cls.python_type(ts / 1000.0)
-
-
-class _NumberIO(_GraphSONTypeIO):
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
- @classmethod
- def objectify(cls, v, _):
- return cls.python_type(v)
-
-
-class ListIO(_GraphSONTypeIO):
- python_type = ListType
- graphson_type = "g:List"
-
- @classmethod
- def dictify(cls, l, writer):
- new_list = []
- for obj in l:
- new_list.append(writer.to_dict(obj))
- return GraphSONUtil.typed_value("List", new_list)
-
- @classmethod
- def objectify(cls, l, reader):
- new_list = []
- for obj in l:
- new_list.append(reader.to_object(obj))
- return new_list
-
-
-class SetIO(_GraphSONTypeIO):
- python_type = SetType
- graphson_type = "g:Set"
-
- @classmethod
- def dictify(cls, s, writer):
- new_list = []
- for obj in s:
- new_list.append(writer.to_dict(obj))
- return GraphSONUtil.typed_value("Set", new_list)
-
- @classmethod
- def objectify(cls, s, reader):
- """
- By default, returns a python set
-
- In case Java returns numeric values of different types which
- python don't recognize, coerce and return a list.
- See comments of TINKERPOP-1844 for more details
- """
- new_list = [reader.to_object(obj) for obj in s]
- new_set = set(new_list)
- if len(new_list) != len(new_set):
- log.warning("Coercing g:Set to list due to java numeric values. "
- "See TINKERPOP-1844 for more details.")
- return new_list
-
- return new_set
-
-
-class MapType(_GraphSONTypeIO):
- python_type = DictType
- graphson_type = "g:Map"
-
- @classmethod
- def dictify(cls, d, writer):
- l = []
- for key in d:
- l.append(writer.to_dict(key))
- l.append(writer.to_dict(d[key]))
- return GraphSONUtil.typed_value("Map", l)
-
- @classmethod
- def objectify(cls, l, reader):
- new_dict = {}
- if len(l) > 0:
- x = 0
- while x < len(l):
- new_dict[HashableDict.of(reader.to_object(l[x]))] = reader.to_object(l[x + 1])
- x = x + 2
- return new_dict
-
-
-class BulkSetIO(_GraphSONTypeIO):
- graphson_type = "g:BulkSet"
-
- @classmethod
- def objectify(cls, l, reader):
- new_list = []
-
- # this approach basically mimics what currently existed in 3.3.4 and prior versions where BulkSet is
- # basically just coerced to list. the limitation here is that if the value of a bulk exceeds the size of
- # a list (into the long space) then stuff won't work nice.
- if len(l) > 0:
- x = 0
- while x < len(l):
- obj = reader.to_object(l[x])
- bulk = reader.to_object(l[x + 1])
- for y in range(bulk):
- new_list.append(obj)
- x = x + 2
- return new_list
-
-
-class FloatIO(_NumberIO):
- python_type = FloatType
- graphson_type = "g:Float"
- graphson_base_type = "Float"
-
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- elif math.isnan(n):
- return GraphSONUtil.typed_value(cls.graphson_base_type, "NaN")
- elif math.isinf(n) and n > 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "Infinity")
- elif math.isinf(n) and n < 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "-Infinity")
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
- @classmethod
- def objectify(cls, v, _):
- if isinstance(v, str):
- if v == 'NaN':
- return float('nan')
- elif v == "Infinity":
- return float('inf')
- elif v == "-Infinity":
- return float('-inf')
-
- return cls.python_type(v)
-
-
-class BigDecimalIO(_NumberIO):
- python_type = Decimal
- graphson_type = "gx:BigDecimal"
- graphson_base_type = "BigDecimal"
-
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- elif math.isnan(n):
- return GraphSONUtil.typed_value(cls.graphson_base_type, "NaN", "gx")
- elif math.isinf(n) and n > 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "Infinity", "gx")
- elif math.isinf(n) and n < 0:
- return GraphSONUtil.typed_value(cls.graphson_base_type, "-Infinity", "gx")
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, str(n), "gx")
-
- @classmethod
- def objectify(cls, v, _):
- if isinstance(v, str):
- if v == 'NaN':
- return Decimal('nan')
- elif v == "Infinity":
- return Decimal('inf')
- elif v == "-Infinity":
- return Decimal('-inf')
-
- return Decimal(v)
-
-
-class DoubleIO(FloatIO):
- graphson_type = "g:Double"
- graphson_base_type = "Double"
-
-
-class Int64IO(_NumberIO):
- python_type = LongType
- graphson_type = "g:Int64"
- graphson_base_type = "Int64"
-
- @classmethod
- def dictify(cls, n, writer):
- # if we exceed Java long range then we need a BigInteger
- if isinstance(n, bool):
- return n
- elif n < -9223372036854775808 or n > 9223372036854775807:
- return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
-
-class BigIntegerIO(Int64IO):
- graphson_type = "gx:BigInteger"
-
-
-class Int32IO(Int64IO):
- python_type = IntType
- graphson_type = "g:Int32"
- graphson_base_type = "Int32"
-
- @classmethod
- def dictify(cls, n, writer):
- # if we exceed Java int range then we need a long
- if isinstance(n, bool):
- return n
- elif n < -9223372036854775808 or n > 9223372036854775807:
- return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
- elif n < -2147483648 or n > 2147483647:
- return GraphSONUtil.typed_value("Int64", n)
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n)
-
-
-class Int16IO(Int64IO):
- python_type = ShortType
- graphson_type = "gx:Int16"
- graphson_base_type = "Int16"
-
- @classmethod
- def dictify(cls, n, writer):
- # if we exceed Java int range then we need a long
- if isinstance(n, bool):
- return n
- elif n < -9223372036854775808 or n > 9223372036854775807:
- return GraphSONUtil.typed_value("BigInteger", str(n), "gx")
- elif n < -2147483648 or n > 2147483647:
- return GraphSONUtil.typed_value("Int64", n)
- elif n < -32768 or n > 32767:
- return GraphSONUtil.typed_value("Int32", n)
- else:
- return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return int.__new__(ShortType, v)
-
-
-class ByteIO(_NumberIO):
- python_type = SingleByte
- graphson_type = "gx:Byte"
- graphson_base_type = "Byte"
-
- @classmethod
- def dictify(cls, n, writer):
- if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int)
- return n
- return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return int.__new__(SingleByte, v)
-
-
-class ByteBufferIO(_GraphSONTypeIO):
- python_type = ByteBufferType
- graphson_type = "gx:ByteBuffer"
- graphson_base_type = "ByteBuffer"
-
- @classmethod
- def dictify(cls, n, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, "".join(chr(x) for x in n), "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return cls.python_type(v, "utf8")
-
-
-class CharIO(_GraphSONTypeIO):
- python_type = SingleChar
- graphson_type = "gx:Char"
- graphson_base_type = "Char"
-
- @classmethod
- def dictify(cls, n, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, n, "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return str.__new__(SingleChar, v)
-
-
-class DurationIO(_GraphSONTypeIO):
- python_type = timedelta
- graphson_type = "gx:Duration"
- graphson_base_type = "Duration"
-
- @classmethod
- def dictify(cls, n, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, duration_isoformat(n), "gx")
-
- @classmethod
- def objectify(cls, v, _):
- return parse_duration(v)
-
-
-class VertexDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Vertex"
-
- @classmethod
- def objectify(cls, d, reader):
- properties = None
- if "properties" in d:
- properties = reader.to_object(d["properties"])
- if properties is not None:
- properties = [item for sublist in properties.values() for item in sublist]
- return Vertex(reader.to_object(d["id"]), d.get("label", "vertex"), properties)
-
-
-class EdgeDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Edge"
-
- @classmethod
- def objectify(cls, d, reader):
- properties = None
- if "properties" in d:
- properties = reader.to_object(d["properties"])
- if properties is not None:
- properties = list(properties.values())
- return Edge(reader.to_object(d["id"]),
- Vertex(reader.to_object(d["outV"]), d.get("outVLabel", "vertex")),
- d.get("label", "edge"),
- Vertex(reader.to_object(d["inV"]), d.get("inVLabel", "vertex")),
- properties)
-
-
-class VertexPropertyDeserializer(_GraphSONTypeIO):
- graphson_type = "g:VertexProperty"
-
- @classmethod
- def objectify(cls, d, reader):
- properties = None
- if "properties" in d:
- properties = reader.to_object(d["properties"])
- if properties is not None:
- properties = list(map(lambda x: Property(x[0], x[1], None), properties.items()))
- vertex = Vertex(reader.to_object(d.get("vertex"))) if "vertex" in d else None
- return VertexProperty(reader.to_object(d["id"]),
- d["label"],
- reader.to_object(d["value"]),
- vertex,
- properties)
-
-
-class PropertyDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Property"
-
- @classmethod
- def objectify(cls, d, reader):
- element = reader.to_object(d["element"]) if "element" in d else None
- return Property(d["key"], reader.to_object(d["value"]), element)
-
-
-class PathDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Path"
-
- @classmethod
- def objectify(cls, d, reader):
- return Path(reader.to_object(d["labels"]), reader.to_object(d["objects"]))
-
-
-class TDeserializer(_GraphSONTypeIO):
- graphson_type = "g:T"
-
- @classmethod
- def objectify(cls, d, reader):
- return T[d]
-
-
-class DirectionIO(_GraphSONTypeIO):
- graphson_type = "g:Direction"
- graphson_base_type = "Direction"
- python_type = Direction
-
- @classmethod
- def dictify(cls, d, writer):
- return GraphSONUtil.typed_value(cls.graphson_base_type, d.name, "g")
-
- @classmethod
- def objectify(cls, d, reader):
- return Direction[d]
-
-
-class TraversalMetricsDeserializer(_GraphSONTypeIO):
- graphson_type = "g:TraversalMetrics"
-
- @classmethod
- def objectify(cls, d, reader):
- return reader.to_object(d)
-
-
-class MetricsDeserializer(_GraphSONTypeIO):
- graphson_type = "g:Metrics"
-
- @classmethod
- def objectify(cls, d, reader):
- return reader.to_object(d)
diff --git a/gremlin-python/src/main/python/tests/conftest.py b/gremlin-python/src/main/python/tests/conftest.py
index c09237d608..f362a1f515 100644
--- a/gremlin-python/src/main/python/tests/conftest.py
+++ b/gremlin-python/src/main/python/tests/conftest.py
@@ -21,42 +21,23 @@ import concurrent.futures
import os
import ssl
import pytest
-import socket
import logging
import queue
-import yaml
from gremlin_python.driver.client import Client
from gremlin_python.driver.connection import Connection
-from gremlin_python.driver import serializer
-from gremlin_python.driver.driver_remote_connection import (
- DriverRemoteConnection)
-from gremlin_python.driver.protocol import GremlinServerWSProtocol, GremlinServerHTTPProtocol
-from gremlin_python.driver.serializer import (
- GraphSONMessageSerializer, GraphSONSerializersV2d0, GraphSONSerializersV3d0,
- GraphBinarySerializersV1, GraphBinarySerializersV4)
-from gremlin_python.driver.aiohttp.transport import AiohttpTransport, AiohttpHTTPTransport
+from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
+from gremlin_python.driver.protocol import GremlinServerHTTPProtocol
+from gremlin_python.driver.serializer import GraphBinarySerializersV4
+from gremlin_python.driver.aiohttp.transport import AiohttpHTTPTransport
-# TODO: update or remove once all implementations are finalized
-gremlin_server_url = os.environ.get('GREMLIN_SERVER_URL', 'ws://localhost:{}/gremlin')
-gremlin_basic_auth_url = os.environ.get('GREMLIN_SERVER_BASIC_AUTH_URL', 'wss://localhost:{}/gremlin')
-gremlin_socket_server_url = os.environ.get('GREMLIN_SOCKET_SERVER_URL', 'ws://localhost:{}/gremlin')
-gremlin_socket_server_config_path = os.environ.get("GREMLIN_SOCKET_SERVER_CONFIG_PATH",
- "../../../../../../gremlin-tools/gremlin-socket-server/conf/"
- "test-ws-gremlin.yaml")
-kerberos_hostname = os.environ.get('KRB_HOSTNAME', socket.gethostname())
+"""HTTP server testing variables"""
+gremlin_server_url = os.environ.get('GREMLIN_SERVER_URL_HTTP', 'http://localhost:{}/')
+gremlin_basic_auth_url = os.environ.get('GREMLIN_SERVER_BASIC_AUTH_URL_HTTP', 'https://localhost:{}/')
anonymous_url = gremlin_server_url.format(45940)
basic_url = gremlin_basic_auth_url.format(45941)
-kerberos_url = gremlin_server_url.format(45942)
-kerberized_service = 'test-service@{}'.format(kerberos_hostname)
-
-"""HTTP server testing variables"""
-gremlin_server_url_http = os.environ.get('GREMLIN_SERVER_URL_HTTP', 'http://localhost:{}/')
-gremlin_basic_auth_url_http = os.environ.get('GREMLIN_SERVER_BASIC_AUTH_URL_HTTP', 'https://localhost:{}/')
-anonymous_url_http = gremlin_server_url_http.format(45940)
-basic_url_http = gremlin_basic_auth_url_http.format(45941)
verbose_logging = False
@@ -64,254 +45,18 @@ logging.basicConfig(format='%(asctime)s [%(levelname)8s] [%(filename)15s:%(linen
level=logging.DEBUG if verbose_logging else logging.INFO)
-@pytest.fixture
-def connection(request):
- protocol = GremlinServerWSProtocol(
- GraphSONMessageSerializer(),
- username='stephen', password='password')
- executor = concurrent.futures.ThreadPoolExecutor(5)
- pool = queue.Queue()
- try:
- conn = Connection(anonymous_url, 'gmodern', protocol,
- lambda: AiohttpTransport(), executor, pool)
- except OSError:
- executor.shutdown()
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- executor.shutdown()
- conn.close()
-
- request.addfinalizer(fin)
- return conn
-
-
-@pytest.fixture
-def client(request):
- try:
- client = Client(anonymous_url, 'gmodern')
- except OSError:
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- client.close()
-
- request.addfinalizer(fin)
- return client
-
-
-@pytest.fixture
-def gremlin_socket_server_serializer(socket_server_settings):
- if socket_server_settings["SERIALIZER"] == "GraphBinaryV1":
- return serializer.GraphBinarySerializersV1()
- elif socket_server_settings["SERIALIZER"] == "GraphSONV2":
- return serializer.GraphSONSerializersV2d0()
- elif socket_server_settings["SERIALIZER"] == "GraphSONV3":
- return serializer.GraphSONSerializersV3d0()
- else:
- return serializer.GraphBinarySerializersV1()
-
-
-@pytest.fixture
-def socket_server_client(request, socket_server_settings, gremlin_socket_server_serializer):
- url = gremlin_socket_server_url.format(socket_server_settings["PORT"])
- try:
- client = Client(url, 'g', pool_size=1, message_serializer=gremlin_socket_server_serializer)
- except OSError:
- pytest.skip('Gremlin Socket Server is not running')
- else:
- def fin():
- client.close()
-
- request.addfinalizer(fin)
- return client
-
-
-@pytest.fixture
-def socket_server_client_no_user_agent(request, socket_server_settings, gremlin_socket_server_serializer):
- url = gremlin_socket_server_url.format(socket_server_settings["PORT"])
- try:
- client = Client(url, 'g', pool_size=1, message_serializer=gremlin_socket_server_serializer,
- enable_user_agent_on_connect=False)
- except OSError:
- pytest.skip('Gremlin Socket Server is not running')
- else:
- def fin():
- client.close()
-
- request.addfinalizer(fin)
- return client
-
-
-@pytest.fixture
-def socket_server_settings():
- with open(gremlin_socket_server_config_path, mode="rb") as file:
- settings = yaml.safe_load(file)
- return settings
-
-@pytest.fixture(params=['basic', 'kerberos'])
-def authenticated_client(request):
- try:
- if request.param == 'basic':
- # turn off certificate verification for testing purposes only
- ssl_opts = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
- ssl_opts.verify_mode = ssl.CERT_NONE
- client = Client(basic_url, 'gmodern', username='stephen', password='password',
- transport_factory=lambda: AiohttpTransport(ssl_options=ssl_opts))
- elif request.param == 'kerberos':
- client = Client(kerberos_url, 'gmodern', kerberized_service=kerberized_service)
- else:
- raise ValueError("Invalid authentication option - " + request.param)
- except OSError:
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- client.close()
-
- request.addfinalizer(fin)
- return client
-
-
-@pytest.fixture(params=['graphsonv2', 'graphsonv3', 'graphbinaryv1'])
-def remote_connection(request):
- try:
- if request.param == 'graphbinaryv1':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gmodern',
- message_serializer=serializer.GraphBinarySerializersV1())
- elif request.param == 'graphsonv2':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gmodern',
- message_serializer=serializer.GraphSONSerializersV2d0())
- elif request.param == 'graphsonv3':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gmodern',
- message_serializer=serializer.GraphSONSerializersV3d0())
- else:
- raise ValueError("Invalid serializer option - " + request.param)
- except OSError:
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- remote_conn.close()
-
- request.addfinalizer(fin)
- return remote_conn
-
-
-@pytest.fixture(params=['graphsonv2', 'graphsonv3', 'graphbinaryv1'])
-def remote_connection_crew(request):
- try:
- if request.param == 'graphbinaryv1':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gcrew',
- message_serializer=serializer.GraphBinarySerializersV1())
- elif request.param == 'graphsonv2':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gcrew',
- message_serializer=serializer.GraphSONSerializersV2d0())
- elif request.param == 'graphsonv3':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gcrew',
- message_serializer=serializer.GraphSONSerializersV3d0())
- else:
- raise ValueError("Invalid serializer option - " + request.param)
- except OSError:
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- remote_conn.close()
-
- request.addfinalizer(fin)
- return remote_conn
-
-
-@pytest.fixture(params=['graphsonv2', 'graphsonv3', 'graphbinaryv1'])
-def remote_transaction_connection(request):
- try:
- if request.param == 'graphbinaryv1':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gtx',
- message_serializer=serializer.GraphBinarySerializersV1())
- elif request.param == 'graphsonv2':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gtx',
- message_serializer=serializer.GraphSONSerializersV2d0())
- elif request.param == 'graphsonv3':
- remote_conn = DriverRemoteConnection(anonymous_url, 'gtx',
- message_serializer=serializer.GraphSONSerializersV3d0())
- else:
- raise ValueError("Invalid serializer option - " + request.param)
- except OSError:
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- remote_conn.close()
-
- request.addfinalizer(fin)
- return remote_conn
-
-
-@pytest.fixture(params=['basic', 'kerberos'])
-def remote_connection_authenticated(request):
- try:
- if request.param == 'basic':
- # turn off certificate verification for testing purposes only
- ssl_opts = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
- ssl_opts.verify_mode = ssl.CERT_NONE
- remote_conn = DriverRemoteConnection(basic_url, 'gmodern',
- username='stephen', password='password',
- message_serializer=serializer.GraphSONSerializersV2d0(),
- transport_factory=lambda: AiohttpTransport(ssl_options=ssl_opts))
- elif request.param == 'kerberos':
- remote_conn = DriverRemoteConnection(kerberos_url, 'gmodern', kerberized_service=kerberized_service,
- message_serializer=serializer.GraphSONSerializersV2d0())
- else:
- raise ValueError("Invalid authentication option - " + request.param)
- except OSError:
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- remote_conn.close()
-
- request.addfinalizer(fin)
- return remote_conn
-
-
-@pytest.fixture
-def remote_connection_graphsonV2(request):
- try:
- remote_conn = DriverRemoteConnection(anonymous_url,
- message_serializer=serializer.GraphSONSerializersV2d0())
- except OSError:
- pytest.skip('Gremlin Server is not running')
- else:
- def fin():
- remote_conn.close()
-
- request.addfinalizer(fin)
- return remote_conn
-
-
-@pytest.fixture
-def graphson_serializer_v2(request):
- return GraphSONSerializersV2d0()
-
-
-@pytest.fixture
-def graphson_serializer_v3(request):
- return GraphSONSerializersV3d0()
-
-
-@pytest.fixture
-def graphbinary_serializer_v1(request):
- return GraphBinarySerializersV1()
-
-
"""
Tests below are for the HTTP server with GraphBinaryV4
"""
@pytest.fixture
-def connection_http(request):
+def connection(request):
protocol = GremlinServerHTTPProtocol(
GraphBinarySerializersV4(),
username='stephen', password='password')
executor = concurrent.futures.ThreadPoolExecutor(5)
pool = queue.Queue()
try:
- conn = Connection(anonymous_url_http, 'gmodern', protocol,
+ conn = Connection(anonymous_url, 'gmodern', protocol,
lambda: AiohttpHTTPTransport(), executor, pool)
except OSError:
executor.shutdown()
@@ -326,9 +71,9 @@ def connection_http(request):
@pytest.fixture
-def client_http(request):
+def client(request):
try:
- client = Client(anonymous_url_http, 'gmodern')
+ client = Client(anonymous_url, 'gmodern')
except OSError:
pytest.skip('Gremlin Server is not running')
else:
@@ -340,13 +85,13 @@ def client_http(request):
@pytest.fixture(params=['basic'])
-def authenticated_client_http(request):
+def authenticated_client(request):
try:
if request.param == 'basic':
# turn off certificate verification for testing purposes only
ssl_opts = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_opts.verify_mode = ssl.CERT_NONE
- client = Client(basic_url_http, 'gmodern', username='stephen', password='password',
+ client = Client(basic_url, 'gmodern', username='stephen', password='password',
transport_factory=lambda: AiohttpHTTPTransport(ssl_options=ssl_opts))
else:
raise ValueError("Invalid authentication option - " + request.param)
@@ -366,10 +111,10 @@ def graphbinary_serializer_v4(request):
@pytest.fixture(params=['graphbinaryv4'])
-def remote_connection_http(request):
+def remote_connection(request):
try:
if request.param == 'graphbinaryv4':
- remote_conn = DriverRemoteConnection(anonymous_url_http, 'gmodern')
+ remote_conn = DriverRemoteConnection(anonymous_url, 'gmodern')
else:
raise ValueError("Invalid serializer option - " + request.param)
except OSError:
@@ -383,10 +128,10 @@ def remote_connection_http(request):
@pytest.fixture(params=['graphbinaryv4'])
-def remote_connection_http_crew(request):
+def remote_connection_crew(request):
try:
if request.param == 'graphbinaryv4':
- remote_conn = DriverRemoteConnection(anonymous_url_http, 'gcrew')
+ remote_conn = DriverRemoteConnection(anonymous_url, 'gcrew')
else:
raise ValueError("Invalid serializer option - " + request.param)
except OSError:
@@ -401,13 +146,13 @@ def remote_connection_http_crew(request):
# TODO: revisit once auth is updated
@pytest.fixture(params=['basic'])
-def remote_connection_http_authenticated(request):
+def remote_connection_authenticated(request):
try:
if request.param == 'basic':
# turn off certificate verification for testing purposes only
ssl_opts = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_opts.verify_mode = ssl.CERT_NONE
- remote_conn = DriverRemoteConnection(basic_url_http, 'gmodern',
+ remote_conn = DriverRemoteConnection(basic_url, 'gmodern',
username='stephen', password='password',
transport_factory=lambda: AiohttpHTTPTransport(ssl_options=ssl_opts))
else:
@@ -423,10 +168,10 @@ def remote_connection_http_authenticated(request):
@pytest.fixture(params=['graphbinaryv4'])
-def invalid_alias_remote_connection_http(request):
+def invalid_alias_remote_connection(request):
try:
if request.param == 'graphbinaryv4':
- remote_conn = DriverRemoteConnection(anonymous_url_http, 'does_not_exist')
+ remote_conn = DriverRemoteConnection(anonymous_url, 'does_not_exist')
else:
raise ValueError("Invalid serializer option - " + request.param)
except OSError:
diff --git a/gremlin-python/src/main/python/tests/driver/test_client.py b/gremlin-python/src/main/python/tests/driver/test_client.py
index d83788ed4c..560a08129a 100644
--- a/gremlin-python/src/main/python/tests/driver/test_client.py
+++ b/gremlin-python/src/main/python/tests/driver/test_client.py
@@ -22,7 +22,6 @@ import threading
import uuid
import pytest
-from gremlin_python.driver import serializer
from gremlin_python.driver.client import Client
from gremlin_python.driver.protocol import GremlinServerError
from gremlin_python.driver.request import RequestMessageV4
@@ -30,142 +29,157 @@ from gremlin_python.process.graph_traversal import __, GraphTraversalSource
from gremlin_python.process.traversal import TraversalStrategies
from gremlin_python.process.strategies import OptionsStrategy
from gremlin_python.structure.graph import Graph, Vertex
-from gremlin_python.driver.aiohttp.transport import AiohttpTransport, AiohttpHTTPTransport
+from gremlin_python.driver.aiohttp.transport import AiohttpHTTPTransport
from gremlin_python.statics import *
from asyncio import TimeoutError
__author__ = 'David M. Brown (davebshow@gmail.com)'
-gremlin_server_url_http = os.environ.get('GREMLIN_SERVER_URL_HTTP', 'http://localhost:{}/')
-test_no_auth_http_url = gremlin_server_url_http.format(45940)
+gremlin_server_url = os.environ.get('GREMLIN_SERVER_URL_HTTP', 'http://localhost:{}/')
+test_no_auth_url = gremlin_server_url.format(45940)
def create_basic_request_message(traversal, source='gmodern', type='bytecode'):
return RequestMessageV4(fields={'g': source, 'gremlinType': type}, gremlin=traversal.bytecode)
-@pytest.mark.skip(reason="needs additional updates")
-def test_connection(connection_http):
+def test_connection(connection):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V()
message = create_basic_request_message(t)
- results_set = connection_http.write(message).result()
+ results_set = connection.write(message).result()
future = results_set.all()
results = future.result()
assert len(results) == 6
assert isinstance(results, list)
assert results_set.done.done()
- assert 'host' in results_set.status_attributes
-@pytest.mark.skip(reason="needs additional updates")
-def test_client_message_too_big(client_http):
+def test_client_message_too_big(client):
try:
- client_http = Client(test_no_auth_http_url, 'g', max_content_length=4096)
- client_http.submit("\" \"*8000").all().result()
+ client = Client(test_no_auth_url, 'g', max_content_length=4096)
+ client.submit("\" \"*8000").all().result()
assert False
except Exception as ex:
- assert ex.args[0].startswith("Received error on read: 'Message size") \
- and ex.args[0].endswith("exceeds limit 4096'")
+ assert ex.args[0].startswith('Response size') \
+ and ex.args[0].endswith('exceeds limit 4096 bytes')
# confirm the client instance is still usable and not closed
- assert ["test"] == client_http.submit("'test'").all().result()
+ assert ["test"] == client.submit("'test'").all().result()
finally:
- client_http.close()
+ client.close()
-def test_client_script_submission(client_http):
- assert len(client_http.submit("new int[100]").all().result()) == 100
+def test_client_large_result(client):
+ result_set = client.submit("[\" \".repeat(200000), \" \".repeat(100000)]").all().result()
+ assert len(result_set[0]) == 200000
+ assert len(result_set[1]) == 100000
-def test_client_script_submission_inject(client_http):
- assert len(client_http.submit("g.inject(new int[100])").all().result()) == 100
+def test_client_script_submission(client):
+ assert len(client.submit("new int[100]").all().result()) == 100
-def test_client_simple_eval(client_http):
- assert client_http.submit('1 + 1').all().result()[0] == 2
+def test_client_script_submission_inject(client):
+ assert len(client.submit("g.inject(new int[100])").all().result()) == 100
-def test_client_simple_eval_bindings(client_http):
- assert client_http.submit('x + x', {'x': 2}).all().result()[0] == 4
+def test_client_simple_eval(client):
+ assert client.submit('1 + 1').all().result()[0] == 2
-def test_client_eval_traversal(client_http):
- assert len(client_http.submit('g.V()').all().result()) == 6
+def test_client_simple_eval_bindings(client):
+ assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
-@pytest.mark.skip(reason="needs additional updates")
-def test_client_error(client_http):
+def test_client_eval_traversal(client):
+ assert len(client.submit('g.V()').all().result()) == 6
+
+
+def test_client_error(client):
try:
# should fire an exception
- client_http.submit('1/0').all().result()
+ client.submit('1/0').all().result()
+ assert False
+ except GremlinServerError as ex:
+ assert ex.status_message.endswith('Division by zero')
+ assert ex.status_exception
+ assert str(ex) == f"{ex.status_code}: {ex.status_message}"
+
+ # still can submit after failure
+ assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
+
+
+def test_bad_serialization(client):
+ try:
+ # should timeout
+ client.submit('java.awt.Color.RED').all().result()
assert False
except GremlinServerError as ex:
- assert 'exceptions' in ex.status_attributes
- assert 'stackTrace' in ex.status_attributes
+ assert ex.status_message
+ assert ex.status_exception
assert str(ex) == f"{ex.status_code}: {ex.status_message}"
# still can submit after failure
- assert client_http.submit('x + x', {'x': 2}).all().result()[0] == 4
+ assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
-@pytest.mark.skip(reason="needs additional updates")
-def test_client_connection_pool_after_error(client_http):
+def test_client_connection_pool_after_error(client):
# Overwrite fixture with pool_size=1 client
- client_http = Client(test_no_auth_http_url, 'gmodern', pool_size=1)
+ client = Client(test_no_auth_url, 'gmodern', pool_size=1)
try:
# should fire an exception
- client_http.submit('1/0').all().result()
+ client.submit('1/0').all().result()
assert False
except GremlinServerError as gse:
# expecting the pool size to be 1 again after query returned
- assert gse.status_code == 597
- assert client_http.available_pool_size == 1
+ assert gse.status_code == 500
+ assert client.available_pool_size == 1
# still can submit after failure
- assert client_http.submit('x + x', {'x': 2}).all().result()[0] == 4
+ assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
-def test_client_no_hang_if_submit_on_closed(client_http):
- assert client_http.submit('1 + 1').all().result()[0] == 2
- client_http.close()
+def test_client_no_hang_if_submit_on_closed(client):
+ assert client.submit('1 + 1').all().result()[0] == 2
+ client.close()
try:
# should fail since not hang if closed
- client_http.submit('1 + 1').all().result()
+ client.submit('1 + 1').all().result()
assert False
except Exception as ex:
assert True
-def test_client_close_all_connection_in_pool(client_http):
- client_http = Client(test_no_auth_http_url, 'g', pool_size=1)
- assert client_http.available_pool_size == 1
- client_http.submit('2+2').all().result()
- client_http.close()
- assert client_http.available_pool_size == 0
+def test_client_close_all_connection_in_pool(client):
+ client = Client(test_no_auth_url, 'g', pool_size=1)
+ assert client.available_pool_size == 1
+ client.submit('2+2').all().result()
+ client.close()
+ assert client.available_pool_size == 0
-def test_client_side_timeout_set_for_aiohttp(client_http):
- client_http = Client(test_no_auth_http_url, 'gmodern',
- transport_factory=lambda: AiohttpHTTPTransport(read_timeout=1, write_timeout=1))
+def test_client_side_timeout_set_for_aiohttp(client):
+ client = Client(test_no_auth_url, 'gmodern',
+ transport_factory=lambda: AiohttpHTTPTransport(read_timeout=1, write_timeout=1))
try:
# should fire an exception
- client_http.submit('Thread.sleep(2000);1').all().result()
+ client.submit('Thread.sleep(2000);1').all().result()
assert False
except TimeoutError as err:
# asyncio TimeoutError has no message.
assert str(err) == ""
# still can submit after failure
- assert client_http.submit('x + x', {'x': 2}).all().result()[0] == 4
+ assert client.submit('x + x', {'x': 2}).all().result()[0] == 4
async def async_connect(enable):
try:
transport = AiohttpHTTPTransport(call_from_event_loop=enable)
- transport.connect(test_no_auth_http_url)
+ transport.connect(test_no_auth_url)
transport.close()
return True
except RuntimeError:
@@ -177,8 +191,8 @@ def test_from_event_loop():
assert asyncio.get_event_loop().run_until_complete(async_connect(True))
-def test_client_gremlin(client_http):
- result_set = client_http.submit('g.V(1)')
+def test_client_gremlin(client):
+ result_set = client.submit('g.V(1)')
result = result_set.all().result()
assert 1 == len(result)
vertex = result[0]
@@ -188,7 +202,7 @@ def test_client_gremlin(client_http):
assert 'name' == vertex.properties[0].key
assert 'marko' == vertex.properties[0].value
##
- result_set = client_http.submit('g.with("materializeProperties", "tokens").V(1)')
+ result_set = client.submit('g.with("materializeProperties", "tokens").V(1)')
result = result_set.all().result()
assert 1 == len(result)
vertex = result[0]
@@ -196,58 +210,58 @@ def test_client_gremlin(client_http):
assert 0 == len(vertex.properties)
-def test_client_bytecode(client_http):
+def test_client_bytecode(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V()
message = create_basic_request_message(t)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
assert len(result_set.all().result()) == 6
-def test_client_bytecode_options(client_http):
+def test_client_bytecode_options(client):
# smoke test to validate serialization of OptionsStrategy. no way to really validate this from an integration
# test perspective because there's no way to access the internals of the strategy via bytecode
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.with_strategies(OptionsStrategy(options={"x": "test", "y": True})).V()
message = create_basic_request_message(t)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
assert len(result_set.all().result()) == 6
##
t = g.with_("x", "test").with_("y", True).V()
message = create_basic_request_message(t)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
assert len(result_set.all().result()) == 6
-def test_iterate_result_set(client_http):
+def test_iterate_result_set(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V()
message = create_basic_request_message(t)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
assert len(results) == 6
-def test_client_async(client_http):
+def test_client_async(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V()
message = create_basic_request_message(t)
- future = client_http.submit_async(message)
+ future = client.submit_async(message)
result_set = future.result()
assert len(result_set.all().result()) == 6
-def test_connection_share(client_http):
+def test_connection_share(client):
# Overwrite fixture with pool_size=1 client
- client_http = Client(test_no_auth_http_url, 'gmodern', pool_size=1)
+ client = Client(test_no_auth_url, 'gmodern', pool_size=1)
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V()
message = create_basic_request_message(t)
message2 = create_basic_request_message(t)
- future = client_http.submit_async(message)
- future2 = client_http.submit_async(message2)
+ future = client.submit_async(message)
+ future2 = client.submit_async(message2)
result_set2 = future2.result()
assert len(result_set2.all().result()) == 6
@@ -258,14 +272,14 @@ def test_connection_share(client_http):
assert len(result_set.all().result()) == 6
-def test_multi_conn_pool(client_http):
+def test_multi_conn_pool(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V()
message = create_basic_request_message(t)
message2 = create_basic_request_message(t)
- client_http = Client(test_no_auth_http_url, 'g', pool_size=1)
- future = client_http.submit_async(message)
- future2 = client_http.submit_async(message2)
+ client = Client(test_no_auth_url, 'g', pool_size=1)
+ future = client.submit_async(message)
+ future2 = client.submit_async(message2)
result_set2 = future2.result()
assert len(result_set2.all().result()) == 6
@@ -275,7 +289,7 @@ def test_multi_conn_pool(client_http):
assert len(result_set.all().result()) == 6
-def test_multi_thread_pool(client_http):
+def test_multi_thread_pool(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
traversals = [g.V(),
g.V().count(),
@@ -292,7 +306,7 @@ def test_multi_thread_pool(client_http):
message = create_basic_request_message(tr)
with condition:
condition.wait(5)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
for result in result_set:
result_list.append(result)
@@ -316,44 +330,44 @@ def test_multi_thread_pool(client_http):
assert results[3][0][0].object == 6
-def test_client_bytecode_with_short(client_http):
+def test_client_bytecode_with_short(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V().has('age', short(16)).count()
message = create_basic_request_message(t)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
assert len(results) == 1
-def test_client_bytecode_with_long(client_http):
+def test_client_bytecode_with_long(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V().has('age', long(851401972585122)).count()
message = create_basic_request_message(t)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
assert len(results) == 1
-def test_client_bytecode_with_bigint(client_http):
+def test_client_bytecode_with_bigint(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.V().has('age', bigint(0x1000_0000_0000_0000_0000)).count()
message = create_basic_request_message(t)
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
assert len(results) == 1
-def test_big_result_set(client_http):
+def test_big_result_set(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.inject(1).repeat(__.add_v('person').property('name', __.loops())).times(20000).count()
message = create_basic_request_message(t, source='g')
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
@@ -361,7 +375,7 @@ def test_big_result_set(client_http):
t = g.V().limit(10)
message = create_basic_request_message(t, source='g')
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
@@ -369,7 +383,7 @@ def test_big_result_set(client_http):
t = g.V().limit(100)
message = create_basic_request_message(t, source='g')
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
@@ -377,28 +391,27 @@ def test_big_result_set(client_http):
t = g.V().limit(1000)
message = create_basic_request_message(t, source='g')
- result_set = client_http.submit(message)
+ result_set = client.submit(message)
results = []
for result in result_set:
results += result
assert len(results) == 1000
- # TODO: enable after setting up docker for GitHub or cleaning up server-side locally
- # t = g.V().limit(10000)
- # message = create_basic_request_message(t, source='g')
- # result_set = client_http.submit(message)
- # results = []
- # for result in result_set:
- # results += result
- # assert len(results) == 10000
+ t = g.V().limit(10000)
+ message = create_basic_request_message(t, source='g')
+ result_set = client.submit(message)
+ results = []
+ for result in result_set:
+ results += result
+ assert len(results) == 10000
@pytest.mark.skip(reason="enable after making sure authenticated testing server is set up in docker")
-def test_big_result_set_secure(authenticated_client_http):
+def test_big_result_set_secure(authenticated_client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
t = g.inject(1).repeat(__.add_v('person').property('name', __.loops())).times(20000).count()
message = create_basic_request_message(t, source='g')
- result_set = authenticated_client_http.submit(message)
+ result_set = authenticated_client.submit(message)
results = []
for result in result_set:
results += result
@@ -406,7 +419,7 @@ def test_big_result_set_secure(authenticated_client_http):
t = g.V().limit(10)
message = create_basic_request_message(t, source='g')
- result_set = authenticated_client_http.submit(message)
+ result_set = authenticated_client.submit(message)
results = []
for result in result_set:
results += result
@@ -414,7 +427,7 @@ def test_big_result_set_secure(authenticated_client_http):
t = g.V().limit(100)
message = create_basic_request_message(t, source='g')
- result_set = authenticated_client_http.submit(message)
+ result_set = authenticated_client.submit(message)
results = []
for result in result_set:
results += result
@@ -422,27 +435,26 @@ def test_big_result_set_secure(authenticated_client_http):
t = g.V().limit(1000)
message = create_basic_request_message(t, source='g')
- result_set = authenticated_client_http.submit(message)
+ result_set = authenticated_client.submit(message)
results = []
for result in result_set:
results += result
assert len(results) == 1000
- # TODO: enable after setting up docker for GitHub or cleaning up server-side locally
- # t = g.V().limit(10000)
- # message = create_basic_request_message(t, source='g')
- # result_set = authenticated_client_http.submit(message)
- # results = []
- # for result in result_set:
- # results += result
- # assert len(results) == 10000
+ t = g.V().limit(10000)
+ message = create_basic_request_message(t, source='g')
+ result_set = authenticated_client.submit(message)
+ results = []
+ for result in result_set:
+ results += result
+ assert len(results) == 10000
async def asyncio_func():
return 1
-def test_asyncio(client_http):
+def test_asyncio(client):
try:
asyncio.get_event_loop().run_until_complete(asyncio_func())
except RuntimeError:
@@ -451,48 +463,48 @@ def test_asyncio(client_http):
# TODO: tests pass because requestID is now generated on HTTP server and this option gets ignored, tests to be removed
# or updated depending on if we still want to use requestID or not
-def test_client_custom_invalid_request_id_graphson_script(client_http):
- client = Client(test_no_auth_http_url, 'gmodern')
+def test_client_custom_invalid_request_id_graphson_script(client):
+ client = Client(test_no_auth_url, 'gmodern')
try:
client.submit('g.V()', request_options={"requestId": "malformed"}).all().result()
except Exception as ex:
assert "badly formed hexadecimal UUID string" in str(ex)
-def test_client_custom_invalid_request_id_graphbinary_script(client_http):
- client_http = Client(test_no_auth_http_url, 'gmodern')
+def test_client_custom_invalid_request_id_graphbinary_script(client):
+ client = Client(test_no_auth_url, 'gmodern')
try:
- client_http.submit('g.V()', request_options={"requestId": "malformed"}).all().result()
+ client.submit('g.V()', request_options={"requestId": "malformed"}).all().result()
except Exception as ex:
assert "badly formed hexadecimal UUID string" in str(ex)
-def test_client_custom_valid_request_id_script_uuid(client_http):
- assert len(client_http.submit('g.V()', request_options={"requestId": uuid.uuid4()}).all().result()) == 6
+def test_client_custom_valid_request_id_script_uuid(client):
+ assert len(client.submit('g.V()', request_options={"requestId": uuid.uuid4()}).all().result()) == 6
-def test_client_custom_valid_request_id_script_string(client_http):
- assert len(client_http.submit('g.V()', request_options={"requestId": str(uuid.uuid4())}).all().result()) == 6
+def test_client_custom_valid_request_id_script_string(client):
+ assert len(client.submit('g.V()', request_options={"requestId": str(uuid.uuid4())}).all().result()) == 6
-def test_client_custom_invalid_request_id_graphson_bytecode(client_http):
- client_http = Client(test_no_auth_http_url, 'gmodern')
+def test_client_custom_invalid_request_id_graphson_bytecode(client):
+ client = Client(test_no_auth_url, 'gmodern')
query = GraphTraversalSource(Graph(), TraversalStrategies()).V().bytecode
try:
- client_http.submit(query, request_options={"requestId": "malformed"}).all().result()
+ client.submit(query, request_options={"requestId": "malformed"}).all().result()
except Exception as ex:
assert "badly formed hexadecimal UUID string" in str(ex)
-def test_client_custom_invalid_request_id_graphbinary_bytecode(client_http):
- client_http = Client(test_no_auth_http_url, 'gmodern')
+def test_client_custom_invalid_request_id_graphbinary_bytecode(client):
+ client = Client(test_no_auth_url, 'gmodern')
query = GraphTraversalSource(Graph(), TraversalStrategies()).V().bytecode
try:
- client_http.submit(query, request_options={"requestId": "malformed"}).all().result()
+ client.submit(query, request_options={"requestId": "malformed"}).all().result()
except Exception as ex:
assert "badly formed hexadecimal UUID string" in str(ex)
-def test_client_custom_valid_request_id_bytecode(client_http):
+def test_client_custom_valid_request_id_bytecode(client):
query = GraphTraversalSource(Graph(), TraversalStrategies()).V().bytecode
- assert len(client_http.submit(query).all().result()) == 6
+ assert len(client.submit(query).all().result()) == 6
diff --git a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
index 1e459297b8..19eac9eef2 100644
--- a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
@@ -20,7 +20,6 @@ import os
import pytest
from gremlin_python import statics
-from gremlin_python.driver.protocol import GremlinServerError
from gremlin_python.statics import long
from gremlin_python.process.traversal import Traverser
from gremlin_python.process.traversal import TraversalStrategy
@@ -29,19 +28,16 @@ from gremlin_python.process.traversal import P, Order, T
from gremlin_python.process.graph_traversal import __
from gremlin_python.process.anonymous_traversal import traversal
from gremlin_python.structure.graph import Vertex
-from gremlin_python.process.strategies import SubgraphStrategy, ReservedKeysVerificationStrategy, SeedStrategy
+from gremlin_python.process.strategies import SubgraphStrategy, SeedStrategy
from gremlin_python.structure.io.util import HashableDict
-from gremlin_python.driver.serializer import GraphSONSerializersV2d0
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
+from gremlin_python.driver.protocol import GremlinServerError
-gremlin_server_url = os.environ.get('GREMLIN_SERVER_URL', 'ws://localhost:{}/gremlin')
+gremlin_server_url = os.environ.get('GREMLIN_SERVER_URL_HTTP', 'http://localhost:{}/')
test_no_auth_url = gremlin_server_url.format(45940)
-# TODO: WS tests to be removed
-@pytest.mark.skip(reason="disabling all WS tests as we move to HTTP")
class TestDriverRemoteConnection(object):
+
def test_traversals(self, remote_connection):
statics.load_statics(globals())
g = traversal().with_(remote_connection)
@@ -66,7 +62,8 @@ class TestDriverRemoteConnection(object):
assert 4 == g.V()[2:].count().next()
assert 2 == g.V()[:2].count().next()
# #
- results = g.withSideEffect('a', ['josh', 'peter']).V(1).out('created').in_('created').values('name').where(P.within('a')).toList()
+ results = g.withSideEffect('a', ['josh', 'peter']).V(1).out('created').in_('created').values('name').where(
+ P.within('a')).toList()
assert 2 == len(results)
assert 'josh' in results
assert 'peter' in results
@@ -77,7 +74,7 @@ class TestDriverRemoteConnection(object):
assert 'dur' in results[0]
# #
results = g.V().has('name', 'peter').as_('a').out('created').as_('b').select('a', 'b').by(
- __.valueMap()).toList()
+ __.value_map()).toList()
assert 1 == len(results)
assert 'peter' == results[0]['a']['name'][0]
assert 35 == results[0]['a']['age'][0]
@@ -91,7 +88,8 @@ class TestDriverRemoteConnection(object):
assert 'marko' in results
assert 'vadas' in results
# #
- results = g.V().has('person', 'name', 'marko').map(lambda: ("it.get().value('name')", "gremlin-groovy")).toList()
+ results = g.V().has('person', 'name', 'marko').map(
+ lambda: ("it.get().value('name')", "gremlin-groovy")).toList()
assert 1 == len(results)
assert 'marko' in results
# #
@@ -105,25 +103,12 @@ class TestDriverRemoteConnection(object):
results = g.V().has('person', 'age', Bindings.of('x', P.lt(30))).count().next()
assert 2 == results
# #
- # test dict keys which can only work on GraphBinary and GraphSON3 which include specific serialization
+ # test dict keys
# types for dict
- if not isinstance(remote_connection._client._message_serializer, GraphSONSerializersV2d0):
- results = g.V().has('person', 'name', 'marko').elementMap("name").groupCount().next()
- assert {HashableDict.of({T.id: 1, T.label: 'person', 'name': 'marko'}): 1} == results
- if not isinstance(remote_connection._client._message_serializer, GraphSONSerializersV2d0):
- results = g.V().has('person', 'name', 'marko').both('knows').groupCount().by(__.values('name').fold()).next()
- assert {tuple(['vadas']): 1, tuple(['josh']): 1} == results
-
- def test_lambda_traversals(self, remote_connection):
- statics.load_statics(globals())
- assert "remoteconnection[{},gmodern]".format(test_no_auth_url) == str(remote_connection)
- g = traversal().with_(remote_connection)
-
- assert 24.0 == g.withSack(1.0, lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum_().next()
- assert 24.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum_().next()
-
- assert 48.0 == g.withSack(1.0, lambda: ("x, y -> x + y + 1", "gremlin-groovy")).V().both().sack().sum_().next()
- assert 48.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"), lambda: ("x, y -> x + y + 1", "gremlin-groovy")).V().both().sack().sum_().next()
+ results = g.V().has('person', 'name', 'marko').elementMap("name").groupCount().next()
+ assert {HashableDict.of({T.id: 1, T.label: 'person', 'name': 'marko'}): 1} == results
+ results = g.V().has('person', 'name', 'marko').both('knows').groupCount().by(__.values('name').fold()).next()
+ assert {tuple(['vadas']): 1, tuple(['josh']): 1} == results
def test_iteration(self, remote_connection):
statics.load_statics(globals())
@@ -136,11 +121,11 @@ class TestDriverRemoteConnection(object):
assert t.hasNext()
assert t.hasNext()
assert 6 == t.next()
- assert not(t.hasNext())
- assert not(t.hasNext())
- assert not(t.hasNext())
- assert not(t.hasNext())
- assert not(t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
t = g.V().has('name', P.within('marko', 'peter')).values('name').order()
assert "marko" == t.next()
@@ -150,11 +135,11 @@ class TestDriverRemoteConnection(object):
assert t.hasNext()
assert t.hasNext()
assert "peter" == t.next()
- assert not(t.hasNext())
- assert not(t.hasNext())
- assert not(t.hasNext())
- assert not(t.hasNext())
- assert not(t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
+ assert not (t.hasNext())
try:
t.next()
@@ -162,13 +147,26 @@ class TestDriverRemoteConnection(object):
except StopIteration:
assert True
+ def test_lambda_traversals(self, remote_connection):
+ statics.load_statics(globals())
+ assert "remoteconnection[{},gmodern]".format(test_no_auth_url) == str(remote_connection)
+ g = traversal().with_(remote_connection)
+
+ assert 24.0 == g.withSack(1.0, lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum_().next()
+ assert 24.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"),
+ lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum_().next()
+
+ assert 48.0 == g.withSack(1.0, lambda: ("x, y -> x + y + 1", "gremlin-groovy")).V().both().sack().sum_().next()
+ assert 48.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"),
+ lambda: ("x, y -> x + y + 1", "gremlin-groovy")).V().both().sack().sum_().next()
+
def test_strategies(self, remote_connection):
statics.load_statics(globals())
g = traversal().with_(remote_connection). \
withStrategies(TraversalStrategy("SubgraphStrategy",
- {"vertices": __.hasLabel("person"),
- "edges": __.hasLabel("created")},
- "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy"))
+ {"vertices": __.has_label("person"),
+ "edges": __.has_label("created")},
+ "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy"))
assert 4 == g.V().count().next()
assert 0 == g.E().count().next()
assert 1 == g.V().label().dedup().count().next()
@@ -176,14 +174,14 @@ class TestDriverRemoteConnection(object):
assert "person" == g.V().label().dedup().next()
#
g = traversal().with_(remote_connection). \
- withStrategies(SubgraphStrategy(vertices=__.hasLabel("person"), edges=__.hasLabel("created")))
+ withStrategies(SubgraphStrategy(vertices=__.has_label("person"), edges=__.has_label("created")))
assert 4 == g.V().count().next()
assert 0 == g.E().count().next()
assert 1 == g.V().label().dedup().count().next()
assert "person" == g.V().label().dedup().next()
#
g = traversal().with_(remote_connection). \
- withStrategies(SubgraphStrategy(edges=__.hasLabel("created")))
+ withStrategies(SubgraphStrategy(edges=__.has_label("created")))
assert 6 == g.V().count().next()
assert 4 == g.E().count().next()
assert 1 == g.E().label().dedup().count().next()
@@ -205,63 +203,6 @@ class TestDriverRemoteConnection(object):
assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
- #
- g = traversal().with_(remote_connection). \
- withStrategies(ReservedKeysVerificationStrategy(throw_exception=True))
- try:
- g.addV("person").property("id", "please-don't-use-id").iterate()
- assert False
- except GremlinServerError as gse:
- assert gse.status_code == 500
- #
- g = traversal().with_(remote_connection).with_("x", True).with_('evaluationTimeout', 10)
- try:
- g.inject(1).sideEffect(lambda: ("Thread.sleep(1000)", "gremlin-groovy")).iterate()
- assert False
- except GremlinServerError as gse:
- assert gse.status_code == 598
-
- def test_close_sessions(self, remote_transaction_connection):
- g = traversal().with_(remote_transaction_connection)
- tx = g.tx()
- gtx = tx.begin()
- # session created for new transaction
- assert 1 == len(remote_transaction_connection._DriverRemoteConnection__spawned_sessions)
- gtx.addV("person").iterate()
- tx.rollback()
- # after closing transaction we should remove spawned_session
- assert 0 == len(remote_transaction_connection._DriverRemoteConnection__spawned_sessions)
-
- def test_tx_on_graph_without_tx_support(self, remote_connection):
- g = traversal().withRemote(remote_connection)
- tx = g.tx()
- try:
- # tx is just a session, so no exception here
- gtx = tx.begin()
- # read operation is ok for sessioned connection
- assert 6 == gtx.V().count().next()
- tx.commit().all().result()
- assert False
- except GremlinServerError as ex:
- assert "500: Graph does not support transactions" == str(ex)
-
- def test_tx_commit_on_graph_without_tx_support(self, remote_connection):
- g = traversal().withRemote(remote_connection)
- tx = g.tx()
- try:
- tx.commit()
- assert False
- except Exception as ex:
- assert "Cannot commit a transaction that is not started." == str(ex)
-
- def test_tx_rollback_on_graph_without_tx_support(self, remote_connection):
- g = traversal().withRemote(remote_connection)
- tx = g.tx()
- try:
- tx.rollback()
- assert False
- except Exception as ex:
- assert "Cannot rollback a transaction that is not started." == str(ex)
def test_clone(self, remote_connection):
g = traversal().with_(remote_connection)
@@ -270,6 +211,18 @@ class TestDriverRemoteConnection(object):
assert 5 == t.clone().limit(5).count().next()
assert 10 == t.clone().limit(10).count().next()
+ def test_receive_error(self, invalid_alias_remote_connection):
+ g = traversal().with_(invalid_alias_remote_connection)
+
+ try:
+ g.V().next()
+ assert False
+ except GremlinServerError as err:
+ assert err.status_code == 400
+ assert 'The traversal source [does_not_exist] for alias [g] is not configured on the server.' \
+ in err.status_message
+
+ @pytest.mark.skip(reason="enable after making sure authenticated testing server is set up in docker")
def test_authenticated(self, remote_connection_authenticated):
statics.load_statics(globals())
g = traversal().with_(remote_connection_authenticated)
diff --git a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_http.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_http.py
deleted file mode 100644
index 7b6d324559..0000000000
--- a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_http.py
+++ /dev/null
@@ -1,229 +0,0 @@
-#
-# 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.
-#
-import os
-
-import pytest
-from gremlin_python import statics
-from gremlin_python.statics import long
-from gremlin_python.process.traversal import Traverser
-from gremlin_python.process.traversal import TraversalStrategy
-from gremlin_python.process.traversal import Bindings
-from gremlin_python.process.traversal import P, Order, T
-from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.anonymous_traversal import traversal
-from gremlin_python.structure.graph import Vertex
-from gremlin_python.process.strategies import SubgraphStrategy, SeedStrategy
-from gremlin_python.structure.io.util import HashableDict
-from gremlin_python.driver.protocol import GremlinServerError
-
-gremlin_server_url_http = os.environ.get('GREMLIN_SERVER_URL_HTTP', 'http://localhost:{}/')
-test_no_auth_http_url = gremlin_server_url_http.format(45940)
-
-
-class TestDriverRemoteConnectionHttp(object):
- def test_traversals(self, remote_connection_http):
- statics.load_statics(globals())
- g = traversal().with_(remote_connection_http)
-
- assert long(6) == g.V().count().toList()[0]
- # #
- assert Vertex(1) == g.V(1).next()
- assert Vertex(1) == g.V(Vertex(1)).next()
- assert 1 == g.V(1).id_().next()
- assert Traverser(Vertex(1)) == g.V(1).nextTraverser()
- assert 1 == len(g.V(1).toList())
- assert isinstance(g.V(1).toList(), list)
- results = g.V().repeat(__.out()).times(2).name
- results = results.toList()
- assert 2 == len(results)
- assert "lop" in results
- assert "ripple" in results
- # #
- assert 10 == g.V().repeat(__.both()).times(5)[0:10].count().next()
- assert 1 == g.V().repeat(__.both()).times(5)[0:1].count().next()
- assert 0 == g.V().repeat(__.both()).times(5)[0:0].count().next()
- assert 4 == g.V()[2:].count().next()
- assert 2 == g.V()[:2].count().next()
- # #
- results = g.withSideEffect('a', ['josh', 'peter']).V(1).out('created').in_('created').values('name').where(
- P.within('a')).toList()
- assert 2 == len(results)
- assert 'josh' in results
- assert 'peter' in results
- # #
- results = g.V().out().profile().toList()
- assert 1 == len(results)
- assert 'metrics' in results[0]
- assert 'dur' in results[0]
- # #
- results = g.V().has('name', 'peter').as_('a').out('created').as_('b').select('a', 'b').by(
- __.value_map()).toList()
- assert 1 == len(results)
- assert 'peter' == results[0]['a']['name'][0]
- assert 35 == results[0]['a']['age'][0]
- assert 'lop' == results[0]['b']['name'][0]
- assert 'java' == results[0]['b']['lang'][0]
- assert 2 == len(results[0]['a'])
- assert 2 == len(results[0]['b'])
- # #
- results = g.V(1).inject(g.V(2).next()).values('name').toList()
- assert 2 == len(results)
- assert 'marko' in results
- assert 'vadas' in results
- # #
- results = g.V().has('person', 'name', 'marko').map(
- lambda: ("it.get().value('name')", "gremlin-groovy")).toList()
- assert 1 == len(results)
- assert 'marko' in results
- # #
- # this test just validates that the underscored versions of steps conflicting with Gremlin work
- # properly and can be removed when the old steps are removed - TINKERPOP-2272
- results = g.V().filter_(__.values('age').sum_().and_(
- __.max_().is_(P.gt(0)), __.min_().is_(P.gt(0)))).range_(0, 1).id_().next()
- assert 1 == results
- # #
- # test binding in P
- results = g.V().has('person', 'age', Bindings.of('x', P.lt(30))).count().next()
- assert 2 == results
- # #
- # test dict keys
- # types for dict
- results = g.V().has('person', 'name', 'marko').elementMap("name").groupCount().next()
- assert {HashableDict.of({T.id: 1, T.label: 'person', 'name': 'marko'}): 1} == results
- results = g.V().has('person', 'name', 'marko').both('knows').groupCount().by(__.values('name').fold()).next()
- assert {tuple(['vadas']): 1, tuple(['josh']): 1} == results
-
- def test_iteration(self, remote_connection_http):
- statics.load_statics(globals())
- g = traversal().with_(remote_connection_http)
-
- t = g.V().count()
- assert t.hasNext()
- assert t.hasNext()
- assert t.hasNext()
- assert t.hasNext()
- assert t.hasNext()
- assert 6 == t.next()
- assert not (t.hasNext())
- assert not (t.hasNext())
- assert not (t.hasNext())
- assert not (t.hasNext())
- assert not (t.hasNext())
-
- t = g.V().has('name', P.within('marko', 'peter')).values('name').order()
- assert "marko" == t.next()
- assert t.hasNext()
- assert t.hasNext()
- assert t.hasNext()
- assert t.hasNext()
- assert t.hasNext()
- assert "peter" == t.next()
- assert not (t.hasNext())
- assert not (t.hasNext())
- assert not (t.hasNext())
- assert not (t.hasNext())
- assert not (t.hasNext())
-
- try:
- t.next()
- assert False
- except StopIteration:
- assert True
-
- def test_lambda_traversals(self, remote_connection_http):
- statics.load_statics(globals())
- assert "remoteconnection[{},gmodern]".format(test_no_auth_http_url) == str(remote_connection_http)
- g = traversal().with_(remote_connection_http)
-
- assert 24.0 == g.withSack(1.0, lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum_().next()
- assert 24.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"),
- lambda: ("x -> x + 1", "gremlin-groovy")).V().both().sack().sum_().next()
-
- assert 48.0 == g.withSack(1.0, lambda: ("x, y -> x + y + 1", "gremlin-groovy")).V().both().sack().sum_().next()
- assert 48.0 == g.withSack(lambda: ("{1.0d}", "gremlin-groovy"),
- lambda: ("x, y -> x + y + 1", "gremlin-groovy")).V().both().sack().sum_().next()
-
- def test_strategies(self, remote_connection_http):
- statics.load_statics(globals())
- g = traversal().with_(remote_connection_http). \
- withStrategies(TraversalStrategy("SubgraphStrategy",
- {"vertices": __.has_label("person"),
- "edges": __.has_label("created")},
- "org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy"))
- assert 4 == g.V().count().next()
- assert 0 == g.E().count().next()
- assert 1 == g.V().label().dedup().count().next()
- assert 4 == g.V().filter_(lambda: ("x -> true", "gremlin-groovy")).count().next()
- assert "person" == g.V().label().dedup().next()
- #
- g = traversal().with_(remote_connection_http). \
- withStrategies(SubgraphStrategy(vertices=__.has_label("person"), edges=__.has_label("created")))
- assert 4 == g.V().count().next()
- assert 0 == g.E().count().next()
- assert 1 == g.V().label().dedup().count().next()
- assert "person" == g.V().label().dedup().next()
- #
- g = traversal().with_(remote_connection_http). \
- withStrategies(SubgraphStrategy(edges=__.has_label("created")))
- assert 6 == g.V().count().next()
- assert 4 == g.E().count().next()
- assert 1 == g.E().label().dedup().count().next()
- assert "created" == g.E().label().dedup().next()
- #
- g = g.withoutStrategies(SubgraphStrategy). \
- withComputer(vertices=__.has("name", "marko"), edges=__.limit(0))
- assert 1 == g.V().count().next()
- assert 0 == g.E().count().next()
- assert "person" == g.V().label().next()
- assert "marko" == g.V().name.next()
- #
- g = traversal().with_(remote_connection_http).withComputer()
- assert 6 == g.V().count().next()
- assert 6 == g.E().count().next()
- #
- g = traversal().with_(remote_connection_http).withStrategies(SeedStrategy(12345))
- shuffledResult = g.V().values("name").order().by(Order.shuffle).toList()
- assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
- assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
- assert shuffledResult == g.V().values("name").order().by(Order.shuffle).toList()
-
- def test_clone(self, remote_connection_http):
- g = traversal().with_(remote_connection_http)
- t = g.V().both()
- assert 12 == len(t.toList())
- assert 5 == t.clone().limit(5).count().next()
- assert 10 == t.clone().limit(10).count().next()
-
- def test_receive_error(self, invalid_alias_remote_connection_http):
- g = traversal().with_(invalid_alias_remote_connection_http)
-
- try:
- g.V().next()
- assert False
- except GremlinServerError as err:
- assert err.status_code == 400
- assert 'The traversal source [does_not_exist] for alias [g] is not configured on the server.' \
- in err.status_message
-
- @pytest.mark.skip(reason="enable after making sure authenticated testing server is set up in docker")
- def test_authenticated(self, remote_connection_http_authenticated):
- statics.load_statics(globals())
- g = traversal().with_(remote_connection_http_authenticated)
-
- assert long(6) == g.V().count().toList()[0]
diff --git a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_threaded.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_threaded.py
index ec1a118509..3f016a739d 100644
--- a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_threaded.py
+++ b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection_threaded.py
@@ -27,11 +27,11 @@ from gremlin_python.process.anonymous_traversal import traversal
__author__ = 'David M. Brown (davebshow@gmail.com)'
-gremlin_server_url_http = 'http://localhost:{}'
-test_no_auth_http_url = gremlin_server_url_http.format(45940)
+gremlin_server_url = 'http://localhost:{}'
+test_no_auth_url = gremlin_server_url.format(45940)
-def test_conns_in_threads(remote_connection_http):
+def test_conns_in_threads(remote_connection):
q = queue.Queue()
child = Thread(target=_executor, args=(q, None))
child2 = Thread(target=_executor, args=(q, None))
@@ -44,10 +44,10 @@ def test_conns_in_threads(remote_connection_http):
child2.join()
-def test_conn_in_threads(remote_connection_http):
+def test_conn_in_threads(remote_connection):
q = queue.Queue()
- child = Thread(target=_executor, args=(q, remote_connection_http))
- child2 = Thread(target=_executor, args=(q, remote_connection_http))
+ child = Thread(target=_executor, args=(q, remote_connection))
+ child2 = Thread(target=_executor, args=(q, remote_connection))
child.start()
child2.start()
for x in range(2):
@@ -62,7 +62,7 @@ def _executor(q, conn):
if not conn:
# This isn't a fixture so close manually
close = True
- conn = DriverRemoteConnection(test_no_auth_http_url, 'gmodern', pool_size=4)
+ conn = DriverRemoteConnection(test_no_auth_url, 'gmodern', pool_size=4)
try:
g = traversal().with_(conn)
future = g.V().promise()
@@ -79,7 +79,7 @@ def _executor(q, conn):
def handle_request():
try:
- remote_connection = DriverRemoteConnection(test_no_auth_http_url, "gmodern")
+ remote_connection = DriverRemoteConnection(test_no_auth_url, "gmodern")
g = traversal().with_(remote_connection)
g.V().limit(1).toList()
remote_connection.close()
diff --git a/gremlin-python/src/main/python/tests/driver/test_serializer.py b/gremlin-python/src/main/python/tests/driver/test_serializer.py
index bff69c941e..16e4371c16 100644
--- a/gremlin-python/src/main/python/tests/driver/test_serializer.py
+++ b/gremlin-python/src/main/python/tests/driver/test_serializer.py
@@ -25,5 +25,3 @@ __author__ = 'David M. Brown'
def test_graphbinary_serializer_v4(graphbinary_serializer_v4):
assert graphbinary_serializer_v4.version == b"application/vnd.graphbinary-v4.0"
assert isinstance(graphbinary_serializer_v4._graphbinary_reader, graphbinaryV4.GraphBinaryReader)
- assert isinstance(graphbinary_serializer_v4.standard._writer, graphbinaryV4.GraphBinaryWriter)
- assert isinstance(graphbinary_serializer_v4.traversal._writer, graphbinaryV4.GraphBinaryWriter)
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py b/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py
index 38c3c3602b..7c0be29c1d 100644
--- a/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py
+++ b/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py
@@ -25,8 +25,8 @@ from gremlin_python.process.anonymous_traversal import traversal
from gremlin_python.statics import *
-def test_vertex(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_vertex(remote_connection):
+ g = traversal().with_(remote_connection)
vertex = g.V(1).next()
assert vertex.id == 1
assert vertex.label == 'person'
@@ -37,8 +37,8 @@ def test_vertex(remote_connection_http):
assert vertex.properties[1].value == 29
-def test_vertex_without_properties(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_vertex_without_properties(remote_connection):
+ g = traversal().with_(remote_connection)
vertex = g.with_('materializeProperties', 'tokens').V(1).next()
assert vertex.id == 1
assert vertex.label == 'person'
@@ -46,8 +46,8 @@ def test_vertex_without_properties(remote_connection_http):
assert vertex.properties is None or len(vertex.properties) == 0
-def test_edge(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_edge(remote_connection):
+ g = traversal().with_(remote_connection)
edge = g.E(7).next()
assert edge.id == 7
assert edge.label == 'knows'
@@ -56,8 +56,8 @@ def test_edge(remote_connection_http):
assert edge.properties[0].value == 0.5
-def test_edge_without_properties(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_edge_without_properties(remote_connection):
+ g = traversal().with_(remote_connection)
edge = g.with_('materializeProperties', 'tokens').E(7).next()
assert edge.id == 7
assert edge.label == 'knows'
@@ -65,8 +65,8 @@ def test_edge_without_properties(remote_connection_http):
assert edge.properties is None or len(edge.properties) == 0
-def test_vertex_vertex_properties(remote_connection_http_crew):
- g = traversal().with_(remote_connection_http_crew)
+def test_vertex_vertex_properties(remote_connection_crew):
+ g = traversal().with_(remote_connection_crew)
vertex = g.V(7).next()
assert vertex.id == 7
assert vertex.label == 'person'
@@ -80,8 +80,8 @@ def test_vertex_vertex_properties(remote_connection_http_crew):
assert vertex.properties[1].properties[1].value == 2000
-def test_timestamp(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_timestamp(remote_connection):
+ g = traversal().with_(remote_connection)
ts = timestamp(1481750076295 / 1000)
resp = g.addV('test_vertex').property('ts', ts)
resp = resp.toList()
@@ -94,8 +94,8 @@ def test_timestamp(remote_connection_http):
g.V(vid).drop().iterate()
-def test_datetime(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_datetime(remote_connection):
+ g = traversal().with_(remote_connection)
dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000)
resp = g.addV('test_vertex').property('dt', dt).toList()
vid = resp[0].id
@@ -107,8 +107,8 @@ def test_datetime(remote_connection_http):
g.V(vid).drop().iterate()
-def test_uuid(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_uuid(remote_connection):
+ g = traversal().with_(remote_connection)
uid = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
resp = g.addV('test_vertex').property('uuid', uid).toList()
vid = resp[0].id
@@ -120,11 +120,11 @@ def test_uuid(remote_connection_http):
g.V(vid).drop().iterate()
-def test_short(remote_connection_http):
- if not isinstance(remote_connection_http._client._message_serializer, GraphBinarySerializersV4):
+def test_short(remote_connection):
+ if not isinstance(remote_connection._client._message_serializer, GraphBinarySerializersV4):
return
- g = traversal().with_(remote_connection_http)
+ g = traversal().with_(remote_connection)
num = short(1111)
resp = g.addV('test_vertex').property('short', num).toList()
vid = resp[0].id
@@ -136,11 +136,11 @@ def test_short(remote_connection_http):
g.V(vid).drop().iterate()
-def test_bigint_positive(remote_connection_http):
- if not isinstance(remote_connection_http._client._message_serializer, GraphBinarySerializersV4):
+def test_bigint_positive(remote_connection):
+ if not isinstance(remote_connection._client._message_serializer, GraphBinarySerializersV4):
return
- g = traversal().with_(remote_connection_http)
+ g = traversal().with_(remote_connection)
big = bigint(0x1000_0000_0000_0000_0000)
resp = g.addV('test_vertex').property('bigint', big).toList()
vid = resp[0].id
@@ -152,11 +152,11 @@ def test_bigint_positive(remote_connection_http):
g.V(vid).drop().iterate()
-def test_bigint_negative(remote_connection_http):
- if not isinstance(remote_connection_http._client._message_serializer, GraphBinarySerializersV4):
+def test_bigint_negative(remote_connection):
+ if not isinstance(remote_connection._client._message_serializer, GraphBinarySerializersV4):
return
- g = traversal().with_(remote_connection_http)
+ g = traversal().with_(remote_connection)
big = bigint(-0x1000_0000_0000_0000_0000)
resp = g.addV('test_vertex').property('bigint', big).toList()
vid = resp[0].id
@@ -168,11 +168,11 @@ def test_bigint_negative(remote_connection_http):
g.V(vid).drop().iterate()
-def test_bigdecimal(remote_connection_http):
- if not isinstance(remote_connection_http._client._message_serializer, GraphBinarySerializersV4):
+def test_bigdecimal(remote_connection):
+ if not isinstance(remote_connection._client._message_serializer, GraphBinarySerializersV4):
return
- g = traversal().with_(remote_connection_http)
+ g = traversal().with_(remote_connection)
bigdecimal = BigDecimal(101, 235)
resp = g.addV('test_vertex').property('bigdecimal', bigdecimal).toList()
vid = resp[0].id
@@ -185,8 +185,8 @@ def test_bigdecimal(remote_connection_http):
g.V(vid).drop().iterate()
-def test_odd_bits(remote_connection_http):
- g = traversal().with_(remote_connection_http)
+def test_odd_bits(remote_connection):
+ g = traversal().with_(remote_connection)
char_lower = str.__new__(SingleChar, chr(78))
resp = g.addV('test_vertex').property('char_lower', char_lower).toList()
vid = resp[0].id
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py b/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py
deleted file mode 100644
index e3f678ebab..0000000000
--- a/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV1.py
+++ /dev/null
@@ -1,235 +0,0 @@
-"""
-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.
-"""
-
-import datetime
-import uuid
-import math
-
-from gremlin_python.statics import timestamp, long, bigint, BigDecimal, SingleByte, SingleChar, ByteBufferType
-from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Path
-from gremlin_python.structure.io.graphbinaryV1 import GraphBinaryWriter, GraphBinaryReader
-from gremlin_python.process.traversal import Barrier, Binding, Bytecode, Merge, Direction
-
-
-# TODO: to be removed
-class TestGraphBinaryV1(object):
- graphbinary_writer = GraphBinaryWriter()
- graphbinary_reader = GraphBinaryReader()
-
- def test_null(self):
- c = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(None))
- assert c is None
-
- def test_int(self):
- x = 100
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_long(self):
- x = long(100)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_bigint(self):
- x = bigint(0x1000_0000_0000_0000_0000)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_float(self):
- x = float(100.001)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- x = float('nan')
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert math.isnan(output)
-
- x = float('-inf')
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert math.isinf(output) and output < 0
-
- x = float('inf')
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert math.isinf(output) and output > 0
-
- def test_double(self):
- x = 100.001
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_bigdecimal(self):
- x = BigDecimal(100, 234)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x.scale == output.scale
- assert x.unscaled_value == output.unscaled_value
-
- def test_date(self):
- x = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_timestamp(self):
- x = timestamp(1481750076295 / 1000)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_string(self):
- x = "serialize this!"
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_homogeneous_list(self):
- x = ["serialize this!", "serialize that!", "serialize that!","stop telling me what to serialize"]
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_heterogeneous_list(self):
- x = ["serialize this!", 0, "serialize that!", "serialize that!", 1, "stop telling me what to serialize", 2]
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_heterogeneous_list_with_none(self):
- x = ["serialize this!", 0, "serialize that!", "serialize that!", 1, "stop telling me what to serialize", 2, None]
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_homogeneous_set(self):
- x = {"serialize this!", "serialize that!", "stop telling me what to serialize"}
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_heterogeneous_set(self):
- x = {"serialize this!", 0, "serialize that!", 1, "stop telling me what to serialize", 2}
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_dict(self):
- x = {"yo": "what?",
- "go": "no!",
- "number": 123,
- 321: "crazy with the number for a key",
- 987: ["go", "deep", {"here": "!"}]}
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- x = {"marko": [666], "noone": ["blah"]}
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- x = {"ripple": [], "peter": ["created"], "noone": ["blah"], "vadas": [],
- "josh": ["created", "created"], "lop": [], "marko": [666, "created", "knows", "knows"]}
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_uuid(self):
- x = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_edge(self):
- x = Edge(123, Vertex(1, 'person'), "developed", Vertex(10, "software"))
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
- assert x.inV == output.inV
- assert x.outV == output.outV
-
- def test_path(self):
- x = Path(["x", "y", "z"], [1, 2, 3])
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_property(self):
- x = Property("name", "stephen", None)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_vertex(self):
- x = Vertex(123, "person")
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_vertexproperty(self):
- x = VertexProperty(123, "name", "stephen", None)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_barrier(self):
- x = Barrier.norm_sack
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_merge(self):
- x = Merge.on_match
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_direction(self):
- x = Direction.OUT
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- x = Direction.from_
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_binding(self):
- x = Binding("name", "marko")
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_bytecode(self):
- x = Bytecode()
- x.source_instructions.append(["withStrategies", "SubgraphStrategy"])
- x.step_instructions.append(["V", 1, 2, 3])
- x.step_instructions.append(["out"])
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_byte(self):
- x = int.__new__(SingleByte, 1)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_bytebuffer(self):
- x = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_boolean(self):
- x = True
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- x = False
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_char(self):
- x = str.__new__(SingleChar, chr(76))
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- x = str.__new__(SingleChar, chr(57344))
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
-
- def test_duration(self):
- x = datetime.timedelta(seconds=1000, microseconds=1000)
- output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x))
- assert x == output
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
deleted file mode 100644
index 013fcf8a25..0000000000
--- a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
+++ /dev/null
@@ -1,538 +0,0 @@
-#
-# 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.
-#
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-import datetime
-import calendar
-import json
-import uuid
-import math
-from decimal import *
-
-from mock import Mock
-
-from gremlin_python.statics import *
-from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Graph, Path
-from gremlin_python.structure.io.graphsonV2d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
-import gremlin_python.structure.io.graphsonV2d0
-from gremlin_python.process.traversal import P, Merge, Operator, Order, Barrier, Direction
-from gremlin_python.process.strategies import SubgraphStrategy
-from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.anonymous_traversal import traversal
-
-
-# TODO: to be removed
-class TestGraphSONReader(object):
- graphson_reader = GraphSONReader()
-
- def test_number_input(self):
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:Byte",
- "@value": 1
- }))
- assert isinstance(x, SingleByte)
- assert 1 == x
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:Int16",
- "@value": 16
- }))
- assert isinstance(x, short)
- assert 16 == x
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Int32",
- "@value": 31
- }))
- assert isinstance(x, int)
- assert 31 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Int64",
- "@value": 31
- }))
- assert isinstance(x, long)
- assert long(31) == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Float",
- "@value": 31.3
- }))
- assert isinstance(x, float)
- assert 31.3 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": 31.2
- }))
- assert isinstance(x, float)
- assert 31.2 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": "NaN"
- }))
- assert isinstance(x, float)
- assert math.isnan(x)
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": "Infinity"
- }))
- assert isinstance(x, float)
- assert math.isinf(x) and x > 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": "-Infinity"
- }))
- assert isinstance(x, float)
- assert math.isinf(x) and x < 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": 31.2
- }))
- assert isinstance(x, Decimal)
- assert Decimal(31.2) == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": 123456789987654321123456789987654321
- }))
- assert isinstance(x, Decimal)
- assert Decimal('123456789987654321123456789987654321') == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": "NaN"
- }))
- assert isinstance(x, Decimal)
- assert math.isnan(x)
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": "Infinity"
- }))
- assert isinstance(x, Decimal)
- assert math.isinf(x) and x > 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": "-Infinity"
- }))
- assert isinstance(x, Decimal)
- assert math.isinf(x) and x < 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigInteger",
- "@value": 31
- }))
- assert isinstance(x, long)
- assert 31 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigInteger",
- "@value": 123456789987654321123456789987654321
- }))
- assert isinstance(x, long)
- assert 123456789987654321123456789987654321 == x
-
- def test_graph(self):
- vertex = self.graphson_reader.read_object("""
- {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type" [...]
- assert isinstance(vertex, Vertex)
- assert "person" == vertex.label
- assert 1 == vertex.id
- assert isinstance(vertex.id, int)
- assert vertex == Vertex(1)
- assert 2 == len(vertex.properties)
- ##
- vertex = self.graphson_reader.read_object("""
- {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
- assert isinstance(vertex, Vertex)
- assert 45.23 == vertex.id
- assert isinstance(vertex.id, FloatType)
- assert "vertex" == vertex.label
- assert vertex == Vertex(45.23)
- ##
- vertex_property = self.graphson_reader.read_object("""
- {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
- assert isinstance(vertex_property, VertexProperty)
- assert "anId" == vertex_property.id
- assert "aKey" == vertex_property.label
- assert vertex_property.value
- assert vertex_property.vertex == Vertex(9)
- ##
- vertex_property = self.graphson_reader.read_object("""
- {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
- assert isinstance(vertex_property, VertexProperty)
- assert 1 == vertex_property.id
- assert "name" == vertex_property.label
- assert "marko" == vertex_property.value
- assert vertex_property.vertex is None
- ##
- edge = self.graphson_reader.read_object("""
- {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
- # print edge
- assert isinstance(edge, Edge)
- assert 17 == edge.id
- assert "knows" == edge.label
- assert edge.inV == Vertex("x", "xLabel")
- assert edge.outV == Vertex("y", "vertex")
- ##
- property = self.graphson_reader.read_object("""
- {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
- # print property
- assert isinstance(property, Property)
- assert "aKey" == property.key
- assert 17 == property.value
- assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
-
- def test_path(self):
- path = self.graphson_reader.read_object(
- """{"@type":"g:Path","@value":{"labels":[["a"],["b","c"],[]],"objects":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32", [...]
- )
- assert isinstance(path, Path)
- assert "path[v[1], v[3], lop]" == str(path)
- assert Vertex(1) == path[0]
- assert Vertex(1) == path["a"]
- assert "lop" == path[2]
- assert 3 == len(path)
-
- def test_custom_mapping(self):
-
- # extended mapping
- class X(object):
- pass
-
- type_string = "test:Xtype"
- override_string = "g:Int64"
- serdes = Mock()
-
- reader = GraphSONReader(deserializer_map={type_string: serdes})
- assert type_string in reader.deserializers
-
- # base dicts are not modified
- assert type_string not in gremlin_python.structure.io.graphsonV2d0._deserializers
-
- x = X()
- o = reader.to_object({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
- serdes.objectify.assert_called_once_with(x, reader)
- assert o is serdes.objectify()
-
- # overridden mapping
- type_string = "g:Int64"
- serdes = Mock()
- reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
- assert gremlin_python.structure.io.graphsonV2d0._deserializers[type_string] is not reader.deserializers[type_string]
-
- value = 3
- o = reader.to_object({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
- serdes.objectify.assert_called_once_with(value, reader)
- assert o is serdes.objectify()
-
- def test_datetime(self):
- expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
- pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
- ts = int(round(pts * 1000))
- dt = self.graphson_reader.read_object(json.dumps({"@type": "g:Date", "@value": ts}))
- assert isinstance(dt, datetime.datetime)
- # TINKERPOP-1848
- assert dt == expected
-
- def test_timestamp(self):
- dt = self.graphson_reader.read_object(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
- assert isinstance(dt, timestamp)
- assert float(dt) == 1481750076.295
-
- def test_duration(self):
- d = self.graphson_reader.read_object(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
- assert isinstance(d, datetime.timedelta)
- assert d == datetime.timedelta(hours=120)
-
- def test_uuid(self):
- prop = self.graphson_reader.read_object(
- json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
- assert isinstance(prop, uuid.UUID)
- assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
-
- def test_metrics(self):
- prop = self.graphson_reader.read_object(
- json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
- {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
- {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
- ]}}]))
- assert isinstance(prop, list)
- assert prop == [{'dur': 1.468594, 'metrics': [
- {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
- {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
- ]}]
-
- def test_bytebuffer(self):
- bb = self.graphson_reader.read_object(
- json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
- assert isinstance(bb, ByteBufferType)
- assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
-
- def test_char(self):
- c = self.graphson_reader.read_object(json.dumps({"@type": "gx:Char", "@value": "L"}))
- assert isinstance(c, SingleChar)
- assert chr(76) == c
-
- def test_null(self):
- c = self.graphson_reader.read_object(json.dumps(None))
- assert c is None
-
-
-class TestGraphSONWriter(object):
- graphson_writer = GraphSONWriter()
- graphson_reader = GraphSONReader()
-
- def test_numbers(self):
- assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.write_object(int.__new__(SingleByte, 1)))
- assert {"@type": "gx:Int16", "@value": 16} == json.loads(self.graphson_writer.write_object(short(16)))
- assert {"@type": "gx:Int16", "@value": -16} == json.loads(self.graphson_writer.write_object(short(-16)))
- assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.write_object(long(2)))
- assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.write_object(long(851401972585122)))
- assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.write_object(long(-2)))
- assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.write_object(long(-851401972585122)))
- assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.write_object(1))
- assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.write_object(-1))
- assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.write_object(851401972585122))
- assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.write_object(3.2))
- assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.write_object(float('nan')))
- assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.write_object(float('inf')))
- assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.write_object(float('-inf')))
- assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.write_object(Decimal('123456789987654321123456789987654321')))
- assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.write_object(Decimal('nan')))
- assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.write_object(Decimal('inf')))
- assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.write_object(Decimal('-inf')))
- assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.write_object(long(123456789987654321123456789987654321)))
- assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.write_object(123456789987654321123456789987654321))
- assert """true""" == self.graphson_writer.write_object(True)
-
- def test_enum(self):
- assert {"@type": "g:Merge", "@value": "onMatch"} == json.loads(self.graphson_writer.write_object(Merge.on_match))
- assert {"@type": "g:Order", "@value": "shuffle"} == json.loads(self.graphson_writer.write_object(Order.shuffle))
- assert {"@type": "g:Barrier", "@value": "normSack"} == json.loads(self.graphson_writer.write_object(Barrier.norm_sack))
- assert {"@type": "g:Operator", "@value": "sum"} == json.loads(self.graphson_writer.write_object(Operator.sum_))
- assert {"@type": "g:Operator", "@value": "sumLong"} == json.loads(self.graphson_writer.write_object(Operator.sum_long))
- assert {"@type": "g:Direction", "@value": "OUT"} == json.loads(self.graphson_writer.write_object(Direction.OUT))
- assert {"@type": "g:Direction", "@value": "OUT"} == json.loads(self.graphson_writer.write_object(Direction.from_))
-
- def test_P(self):
- result = {'@type': 'g:P',
- '@value': {
- 'predicate': 'and',
- 'value': [{
- '@type': 'g:P',
- '@value': {
- 'predicate': 'or',
- 'value': [{
- '@type': 'g:P',
- '@value': {'predicate': 'lt', 'value': 'b'}
- },
- {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
- ]
- }
- },
- {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
-
- assert result == json.loads(
- self.graphson_writer.write_object(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
-
- result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1},{"@type": "g:Int32", "@value": 2}]}}
- assert result == json.loads(self.graphson_writer.write_object(P.within([1, 2])))
- assert result == json.loads(self.graphson_writer.write_object(P.within(1, 2)))
-
- result = {'@type': 'g:P', '@value': {'predicate':'within','value': [{"@type": "g:Int32", "@value": 1}]}}
- assert result == json.loads(self.graphson_writer.write_object(P.within([1])))
- assert result == json.loads(self.graphson_writer.write_object(P.within(1)))
-
- def test_strategies(self):
- # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the Gremlin traversal machine (yet)
- assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
- self.graphson_writer.write_object(SubgraphStrategy))
- assert {"@type": "g:SubgraphStrategy", "@value": {
- "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
- self.graphson_writer.write_object(SubgraphStrategy(vertices=__.has("name", "marko"))))
-
- def test_graph(self):
- # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
- assert {"@type": "g:Vertex", "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(self.graphson_writer.write_object(Vertex(long(12), "person")))
-
- assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
- "outV": {"@type": "g:Int32", "@value": 0},
- "outVLabel": "person",
- "label": "knows",
- "inV": {"@type": "g:Int32", "@value": 1},
- "inVLabel": "dog"}} == json.loads(
- self.graphson_writer.write_object(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
- assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
- "vertex": "stephen"}} == json.loads(
- self.graphson_writer.write_object(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
-
- assert {"@type": "g:Property",
- "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
- "@value": {
- "vertex": "vertexId",
- "id": {"@type": "g:Int32", "@value": 1234},
- "label": "aKey"}}}} == json.loads(
- self.graphson_writer.write_object(
- Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
-
- vertex = self.graphson_reader.read_object(self.graphson_writer.write_object(Vertex(1, "person")))
- assert 1 == vertex.id
- assert "person" == vertex.label
-
- edge = self.graphson_reader.read_object(
- self.graphson_writer.write_object(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
- assert "knows" == edge.label
- assert 3 == edge.id
- assert 1 == edge.outV.id
- assert 2 == edge.inV.id
-
- vertex_property = self.graphson_reader.read_object(
- self.graphson_writer.write_object(VertexProperty(1, "age", 32, Vertex(1))))
- assert 1 == vertex_property.id
- assert "age" == vertex_property.key
- assert 32 == vertex_property.value
-
- property = self.graphson_reader.read_object(self.graphson_writer.write_object(Property("age", 32.2, Edge(1, Vertex(2), "knows", Vertex(3)))))
- assert "age" == property.key
- assert 32.2 == property.value
-
- def test_custom_mapping(self):
- # extended mapping
- class X(object):
- pass
-
- serdes = Mock()
- writer = GraphSONWriter(serializer_map={X: serdes})
- assert X in writer.serializers
-
- # base dicts are not modified
- assert X not in gremlin_python.structure.io.graphsonV2d0._serializers
-
- obj = X()
- d = writer.to_dict(obj)
- serdes.dictify.assert_called_once_with(obj, writer)
- assert d is serdes.dictify()
-
- # overridden mapping
- serdes = Mock()
- writer = GraphSONWriter(serializer_map={int: serdes})
- assert gremlin_python.structure.io.graphsonV2d0._serializers[int] is not writer.serializers[int]
-
- value = 3
- d = writer.to_dict(value)
- serdes.dictify.assert_called_once_with(value, writer)
- assert d is serdes.dictify()
-
- def test_write_long(self):
- mapping = self.graphson_writer.to_dict(1)
- assert mapping['@type'] == 'g:Int32'
- assert mapping['@value'] == 1
-
- mapping = self.graphson_writer.to_dict(long(1))
- assert mapping['@type'] == 'g:Int64'
- assert mapping['@value'] == 1
-
- def test_datetime(self):
- expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
- dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
- output = self.graphson_writer.write_object(dt)
- assert expected == output
-
- def test_timestamp(self):
- expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
- ts = timestamp(1481750076295 / 1000.0)
- output = self.graphson_writer.write_object(ts)
- assert expected == output
-
- def test_duration(self):
- expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
- d = datetime.timedelta(hours=120)
- output = self.graphson_writer.write_object(d)
- assert expected == output
-
- def test_uuid(self):
- expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
- prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
- output = self.graphson_writer.write_object(prop)
- assert expected == output
-
- def test_bytebuffer(self):
- expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
- bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
- output = self.graphson_writer.write_object(bb)
- assert expected == output
-
- def test_char(self):
- expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
- c = str.__new__(SingleChar, chr(76))
- output = self.graphson_writer.write_object(c)
- assert expected == output
-
-
-class TestFunctionalGraphSONIO(object):
- """Functional IO tests"""
-
- def test_timestamp(self, remote_connection_graphsonV2):
- g = traversal().with_(remote_connection_graphsonV2)
- ts = timestamp(1481750076295 / 1000)
- resp = g.addV('test_vertex').property('ts', ts)
- resp = resp.toList()
- vid = resp[0].id
- try:
- ts_prop = g.V(vid).properties('ts').toList()[0]
- assert isinstance(ts_prop.value, timestamp)
- assert ts_prop.value == ts
- except OSError:
- assert False, "Error making request"
- finally:
- g.V(vid).drop().iterate()
-
- def test_datetime(self, remote_connection_graphsonV2):
- g = traversal().with_(remote_connection_graphsonV2)
- dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000)
- resp = g.addV('test_vertex').property('dt', dt).toList()
- vid = resp[0].id
- try:
- dt_prop = g.V(vid).properties('dt').toList()[0]
- assert isinstance(dt_prop.value, datetime.datetime)
- assert dt_prop.value == dt
- except OSError:
- assert False, "Error making request"
- finally:
- g.V(vid).drop().iterate()
-
- def test_uuid(self, remote_connection_graphsonV2):
- g = traversal().with_(remote_connection_graphsonV2)
- uid = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
- resp = g.addV('test_vertex').property('uuid', uid).toList()
- vid = resp[0].id
- try:
- uid_prop = g.V(vid).properties('uuid').toList()[0]
- assert isinstance(uid_prop.value, uuid.UUID)
- assert uid_prop.value == uid
- except OSError:
- assert False, "Error making request"
- finally:
- g.V(vid).drop().iterate()
diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py
deleted file mode 100644
index 88837a0d2e..0000000000
--- a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV3d0.py
+++ /dev/null
@@ -1,556 +0,0 @@
-#
-# 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.
-#
-
-__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
-
-import datetime
-import calendar
-import json
-import uuid
-import math
-from decimal import *
-
-from mock import Mock
-
-from gremlin_python.statics import *
-from gremlin_python.structure.graph import Vertex, Edge, Property, VertexProperty, Path
-from gremlin_python.structure.io.graphsonV3d0 import GraphSONWriter, GraphSONReader, GraphSONUtil
-import gremlin_python.structure.io.graphsonV3d0
-from gremlin_python.process.traversal import P, Merge, Barrier, Order, Operator, Direction
-from gremlin_python.process.strategies import SubgraphStrategy
-from gremlin_python.process.graph_traversal import __
-
-
-# TODO: to be removed
-class TestGraphSONReader(object):
- graphson_reader = GraphSONReader()
-
- def test_collections(self):
- x = self.graphson_reader.read_object(
- json.dumps({"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
- {"@type": "g:Int32", "@value": 2},
- "3"]}))
- assert isinstance(x, list)
- assert x[0] == 1
- assert x[1] == 2
- assert x[2] == "3"
- ##
-
- x = self.graphson_reader.read_object(
- json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
- {"@type": "g:Int32", "@value": 2},
- "3"]}))
- # return a set as normal
- assert isinstance(x, set)
- assert x == set([1, 2, "3"])
-
- x = self.graphson_reader.read_object(
- json.dumps({"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
- {"@type": "g:Int32", "@value": 2},
- {"@type": "g:Float", "@value": 2.0},
- "3"]}))
- # coerce to list here because Java might return numerics of different types which python won't recognize
- # see comments of TINKERPOP-1844 for more details
- assert isinstance(x, list)
- assert x == list([1, 2, 2.0, "3"])
- ##
- x = self.graphson_reader.read_object(
- json.dumps({"@type": "g:Map",
- "@value": ['a', {"@type": "g:Int32", "@value": 1}, 'b', "marko"]}))
- assert isinstance(x, dict)
- assert x['a'] == 1
- assert x['b'] == "marko"
- assert len(x) == 2
-
- # BulkSet gets coerced to a List - both have the same behavior
- x = self.graphson_reader.read_object(
- json.dumps({"@type": "g:BulkSet",
- "@value": ["marko", {"@type": "g:Int64", "@value": 1}, "josh", {"@type": "g:Int64", "@value": 3}]}))
- assert isinstance(x, list)
- assert len(x) == 4
- assert x.count("marko") == 1
- assert x.count("josh") == 3
-
- def test_number_input(self):
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:Byte",
- "@value": 1
- }))
- assert isinstance(x, SingleByte)
- assert 1 == x
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:Int16",
- "@value": 16
- }))
- assert isinstance(x, short)
- assert 16 == x
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Int32",
- "@value": 31
- }))
- assert isinstance(x, int)
- assert 31 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Int64",
- "@value": 31
- }))
- assert isinstance(x, long)
- assert long(31) == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Float",
- "@value": 31.3
- }))
- assert isinstance(x, float)
- assert 31.3 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": 31.2
- }))
- assert isinstance(x, float)
- assert 31.2 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": "NaN"
- }))
- assert isinstance(x, float)
- assert math.isnan(x)
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": "Infinity"
- }))
- assert isinstance(x, float)
- assert math.isinf(x) and x > 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "g:Double",
- "@value": "-Infinity"
- }))
- assert isinstance(x, float)
- assert math.isinf(x) and x < 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": 31.2
- }))
- assert isinstance(x, Decimal)
- assert Decimal(31.2) == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": 123456789987654321123456789987654321
- }))
- assert isinstance(x, Decimal)
- assert Decimal('123456789987654321123456789987654321') == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": "NaN"
- }))
- assert isinstance(x, Decimal)
- assert math.isnan(x)
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": "Infinity"
- }))
- assert isinstance(x, Decimal)
- assert math.isinf(x) and x > 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigDecimal",
- "@value": "-Infinity"
- }))
- assert isinstance(x, Decimal)
- assert math.isinf(x) and x < 0
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigInteger",
- "@value": 31
- }))
- assert isinstance(x, long)
- assert 31 == x
- ##
- x = self.graphson_reader.read_object(json.dumps({
- "@type": "gx:BigInteger",
- "@value": 123456789987654321123456789987654321
- }))
- assert isinstance(x, long)
- assert 123456789987654321123456789987654321 == x
-
- def test_graph(self):
- vertex = self.graphson_reader.read_object("""
- {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","outE":{"created":[{"id":{"@type":"g:Int32","@value":9},"inV":{"@type":"g:Int32","@value":3},"properties":{"weight":{"@type":"g:Double","@value":0.4}}}],"knows":[{"id":{"@type":"g:Int32","@value":7},"inV":{"@type":"g:Int32","@value":2},"properties":{"weight":{"@type":"g:Double","@value":0.5}}},{"id":{"@type":"g:Int32","@value":8},"inV":{"@type":"g:Int32","@value":4},"properties":{"weight":{"@type" [...]
- assert isinstance(vertex, Vertex)
- assert "person" == vertex.label
- assert 1 == vertex.id
- assert isinstance(vertex.id, int)
- assert vertex == Vertex(1)
- ##
- vertex = self.graphson_reader.read_object("""
- {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
- assert isinstance(vertex, Vertex)
- assert 45.23 == vertex.id
- assert isinstance(vertex.id, FloatType)
- assert "vertex" == vertex.label
- assert vertex == Vertex(45.23)
- ##
- vertex_property = self.graphson_reader.read_object("""
- {"@type":"g:VertexProperty", "@value":{"id":"anId","label":"aKey","value":true,"vertex":{"@type":"g:Int32","@value":9}}}""")
- assert isinstance(vertex_property, VertexProperty)
- assert "anId" == vertex_property.id
- assert "aKey" == vertex_property.label
- assert vertex_property.value
- assert vertex_property.vertex == Vertex(9)
- ##
- vertex_property = self.graphson_reader.read_object("""
- {"@type":"g:VertexProperty", "@value":{"id":{"@type":"g:Int32","@value":1},"label":"name","value":"marko"}}""")
- assert isinstance(vertex_property, VertexProperty)
- assert 1 == vertex_property.id
- assert "name" == vertex_property.label
- assert "marko" == vertex_property.value
- assert vertex_property.vertex is None
- ##
- edge = self.graphson_reader.read_object("""
- {"@type":"g:Edge", "@value":{"id":{"@type":"g:Int64","@value":17},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab","properties":{"aKey":"aValue","bKey":true}}}""")
- # print edge
- assert isinstance(edge, Edge)
- assert 17 == edge.id
- assert "knows" == edge.label
- assert edge.inV == Vertex("x", "xLabel")
- assert edge.outV == Vertex("y", "vertex")
- ##
- property = self.graphson_reader.read_object("""
- {"@type":"g:Property", "@value":{"key":"aKey","value":{"@type":"g:Int64","@value":17},"element":{"@type":"g:Edge","@value":{"id":{"@type":"g:Int64","@value":122},"label":"knows","inV":"x","outV":"y","inVLabel":"xLab"}}}}""")
- # print property
- assert isinstance(property, Property)
- assert "aKey" == property.key
- assert 17 == property.value
- assert Edge(122, Vertex("x"), "knows", Vertex("y")) == property.element
-
- def test_path(self):
- path = self.graphson_reader.read_object(
- """{"@type":"g:Path","@value":{"labels":{"@type":"g:List","@value":[{"@type":"g:Set","@value":["a"]},{"@type":"g:Set","@value":["b","c"]},{"@type":"g:Set","@value":[]}]},"objects":{"@type":"g:List","@value":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type": [...]
- )
- assert isinstance(path, Path)
- assert "path[v[1], v[3], lop]" == str(path)
- assert Vertex(1) == path[0]
- assert Vertex(1) == path["a"]
- assert "lop" == path[2]
- assert 3 == len(path)
-
- def test_custom_mapping(self):
-
- # extended mapping
- class X(object):
- pass
-
- type_string = "test:Xtype"
- override_string = "g:Int64"
- serdes = Mock()
-
- reader = GraphSONReader(deserializer_map={type_string: serdes})
- assert type_string in reader.deserializers
-
- # base dicts are not modified
- assert type_string not in gremlin_python.structure.io.graphsonV3d0._deserializers
-
- x = X()
- o = reader.to_object({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: x})
- serdes.objectify.assert_called_once_with(x, reader)
- assert o is serdes.objectify()
-
- # overridden mapping
- type_string = "g:Int64"
- serdes = Mock()
- reader = GraphSONReader(deserializer_map={type_string: serdes, override_string: serdes})
- assert gremlin_python.structure.io.graphsonV3d0._deserializers[type_string] is not reader.deserializers[
- type_string]
-
- value = 3
- o = reader.to_object({GraphSONUtil.TYPE_KEY: type_string, GraphSONUtil.VALUE_KEY: value})
- serdes.objectify.assert_called_once_with(value, reader)
- assert o is serdes.objectify()
-
- def test_datetime(self):
- expected = datetime.datetime(2016, 12, 14, 16, 14, 36, 295000)
- pts = calendar.timegm(expected.utctimetuple()) + expected.microsecond / 1e6
- ts = int(round(pts * 1000))
- dt = self.graphson_reader.read_object(json.dumps({"@type": "g:Date", "@value": ts}))
- assert isinstance(dt, datetime.datetime)
- # TINKERPOP-1848
- assert dt == expected
-
- def test_timestamp(self):
- dt = self.graphson_reader.read_object(json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}))
- assert isinstance(dt, timestamp)
- assert float(dt) == 1481750076.295
-
- def test_duration(self):
- d = self.graphson_reader.read_object(json.dumps({"@type": "gx:Duration", "@value": "PT120H"}))
- assert isinstance(d, datetime.timedelta)
- assert d == datetime.timedelta(hours=120)
-
- def test_uuid(self):
- prop = self.graphson_reader.read_object(
- json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}))
- assert isinstance(prop, uuid.UUID)
- assert str(prop) == '41d2e28a-20a4-4ab0-b379-d810dede3786'
-
- def test_metrics(self):
- prop = self.graphson_reader.read_object(
- json.dumps([{'@type': 'g:TraversalMetrics', '@value': {'dur': 1.468594, 'metrics': [
- {'@type': 'g:Metrics', '@value': {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'}},
- {'@type': 'g:Metrics', '@value': {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}}
- ]}}]))
- assert isinstance(prop, list)
- assert prop == [{'dur': 1.468594, 'metrics': [
- {'dur': 1.380957, 'counts': {}, 'name': 'GraphStep(__.V())', 'annotations': {'percentDur': 94.03259171697556}, 'id': '4.0.0()'},
- {'dur': 0.087637, 'counts': {}, 'name': 'ReferenceElementStep', 'annotations': {'percentDur': 5.967408283024444}, 'id': '3.0.0()'}
- ]}]
-
- def test_bytebuffer(self):
- bb = self.graphson_reader.read_object(
- json.dumps({"@type": "gx:ByteBuffer", "@value": "c29tZSBieXRlcyBmb3IgeW91"}))
- assert isinstance(bb, ByteBufferType)
- assert ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8") == bb
-
- def test_char(self):
- c = self.graphson_reader.read_object(json.dumps({"@type": "gx:Char", "@value": "L"}))
- assert isinstance(c, SingleChar)
- assert chr(76) == c
-
- def test_null(self):
- c = self.graphson_reader.read_object(json.dumps(None))
- assert c is None
-
-
-class TestGraphSONWriter(object):
- graphson_writer = GraphSONWriter()
- graphson_reader = GraphSONReader()
-
- def test_collections(self):
- assert {"@type": "g:List", "@value": [{"@type": "g:Int32", "@value": 1},
- {"@type": "g:Int32", "@value": 2},
- {"@type": "g:Int32", "@value": 3}]} == json.loads(
- self.graphson_writer.write_object([1, 2, 3]))
- assert {"@type": "g:Set", "@value": [{"@type": "g:Int32", "@value": 1},
- {"@type": "g:Int32", "@value": 2},
- {"@type": "g:Int32", "@value": 3}]} == json.loads(
- self.graphson_writer.write_object(set([1, 2, 3, 3])))
- assert {"@type": "g:Map",
- "@value": ['a', {"@type": "g:Int32", "@value": 1}]} == json.loads(
- self.graphson_writer.write_object({'a': 1}))
-
- def test_numbers(self):
- assert {"@type": "gx:Byte", "@value": 1} == json.loads(self.graphson_writer.write_object(int.__new__(SingleByte, 1)))
- assert {"@type": "gx:Int16", "@value": 16} == json.loads(self.graphson_writer.write_object(short(16)))
- assert {"@type": "gx:Int16", "@value": -16} == json.loads(self.graphson_writer.write_object(short(-16)))
- assert {"@type": "g:Int64", "@value": 2} == json.loads(self.graphson_writer.write_object(long(2)))
- assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.write_object(long(851401972585122)))
- assert {"@type": "g:Int64", "@value": -2} == json.loads(self.graphson_writer.write_object(long(-2)))
- assert {"@type": "g:Int64", "@value": -851401972585122} == json.loads(self.graphson_writer.write_object(long(-851401972585122)))
- assert {"@type": "g:Int32", "@value": 1} == json.loads(self.graphson_writer.write_object(1))
- assert {"@type": "g:Int32", "@value": -1} == json.loads(self.graphson_writer.write_object(-1))
- assert {"@type": "g:Int64", "@value": 851401972585122} == json.loads(self.graphson_writer.write_object(851401972585122))
- assert {"@type": "g:Double", "@value": 3.2} == json.loads(self.graphson_writer.write_object(3.2))
- assert {"@type": "g:Double", "@value": "NaN"} == json.loads(self.graphson_writer.write_object(float('nan')))
- assert {"@type": "g:Double", "@value": "Infinity"} == json.loads(self.graphson_writer.write_object(float('inf')))
- assert {"@type": "g:Double", "@value": "-Infinity"} == json.loads(self.graphson_writer.write_object(float('-inf')))
- assert {"@type": "gx:BigDecimal", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.write_object(Decimal('123456789987654321123456789987654321')))
- assert {"@type": "gx:BigDecimal", "@value": "NaN"} == json.loads(self.graphson_writer.write_object(Decimal('nan')))
- assert {"@type": "gx:BigDecimal", "@value": "Infinity"} == json.loads(self.graphson_writer.write_object(Decimal('inf')))
- assert {"@type": "gx:BigDecimal", "@value": "-Infinity"} == json.loads(self.graphson_writer.write_object(Decimal('-inf')))
- assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.write_object(long(123456789987654321123456789987654321)))
- assert {"@type": "gx:BigInteger", "@value": "123456789987654321123456789987654321"} == json.loads(self.graphson_writer.write_object(123456789987654321123456789987654321))
- assert """true""" == self.graphson_writer.write_object(True)
-
- def test_enum(self):
- assert {"@type": "g:Merge", "@value": "onMatch"} == json.loads(self.graphson_writer.write_object(Merge.on_match))
- assert {"@type": "g:Order", "@value": "shuffle"} == json.loads(self.graphson_writer.write_object(Order.shuffle))
- assert {"@type": "g:Barrier", "@value": "normSack"} == json.loads(self.graphson_writer.write_object(Barrier.norm_sack))
- assert {"@type": "g:Operator", "@value": "sum"} == json.loads(self.graphson_writer.write_object(Operator.sum_))
- assert {"@type": "g:Operator", "@value": "sumLong"} == json.loads(self.graphson_writer.write_object(Operator.sum_long))
- assert {"@type": "g:Direction", "@value": "OUT"} == json.loads(self.graphson_writer.write_object(Direction.OUT))
- assert {"@type": "g:Direction", "@value": "OUT"} == json.loads(self.graphson_writer.write_object(Direction.from_))
-
- def test_P(self):
- result = {'@type': 'g:P',
- '@value': {
- 'predicate': 'and',
- 'value': [{
- '@type': 'g:P',
- '@value': {
- 'predicate': 'or',
- 'value': [{
- '@type': 'g:P',
- '@value': {'predicate': 'lt', 'value': 'b'}
- },
- {'@type': 'g:P', '@value': {'predicate': 'gt', 'value': 'c'}}
- ]
- }
- },
- {'@type': 'g:P', '@value': {'predicate': 'neq', 'value': 'd'}}]}}
-
- assert result == json.loads(
- self.graphson_writer.write_object(P.lt("b").or_(P.gt("c")).and_(P.neq("d"))))
-
- result = {'@type': 'g:P', '@value': {'predicate': 'within', 'value': {'@type': 'g:List', '@value': [
- {"@type": "g:Int32", "@value": 1}, {"@type": "g:Int32", "@value": 2}]}}}
- assert result == json.loads(self.graphson_writer.write_object(P.within([1, 2])))
- assert result == json.loads(self.graphson_writer.write_object(P.within({1, 2})))
- assert result == json.loads(self.graphson_writer.write_object(P.within(1, 2)))
-
- result = {'@type': 'g:P', '@value': {'predicate': 'within', 'value': {'@type': 'g:List', '@value': [
- {"@type": "g:Int32", "@value": 1}]}}}
- assert result == json.loads(self.graphson_writer.write_object(P.within([1])))
- assert result == json.loads(self.graphson_writer.write_object(P.within({1})))
- assert result == json.loads(self.graphson_writer.write_object(P.within(1)))
-
- def test_strategies(self):
- # we have a proxy model for now given that we don't want to have to have g:XXX all registered on the
- # Gremlin traversal machine (yet)
- assert {"@type": "g:SubgraphStrategy", "@value": {}} == json.loads(
- self.graphson_writer.write_object(SubgraphStrategy))
- assert {"@type": "g:SubgraphStrategy", "@value": {
- "vertices": {"@type": "g:Bytecode", "@value": {"step": [["has", "name", "marko"]]}}}} == json.loads(
- self.graphson_writer.write_object(SubgraphStrategy(vertices=__.has("name", "marko"))))
-
- def test_graph(self):
- # TODO: this assert is not compatible with python 3 and now that we test with both 2 and 3 it fails
- assert {"@type": "g:Vertex",
- "@value": {"id": {"@type": "g:Int64", "@value": 12}, "label": "person"}} == json.loads(
- self.graphson_writer.write_object(Vertex(long(12), "person")))
-
- assert {"@type": "g:Edge", "@value": {"id": {"@type": "g:Int32", "@value": 7},
- "outV": {"@type": "g:Int32", "@value": 0},
- "outVLabel": "person",
- "label": "knows",
- "inV": {"@type": "g:Int32", "@value": 1},
- "inVLabel": "dog"}} == json.loads(
- self.graphson_writer.write_object(Edge(7, Vertex(0, "person"), "knows", Vertex(1, "dog"))))
- assert {"@type": "g:VertexProperty", "@value": {"id": "blah", "label": "keyA", "value": True,
- "vertex": "stephen"}} == json.loads(
- self.graphson_writer.write_object(VertexProperty("blah", "keyA", True, Vertex("stephen"))))
-
- assert {"@type": "g:Property",
- "@value": {"key": "name", "value": "marko", "element": {"@type": "g:VertexProperty",
- "@value": {
- "vertex": "vertexId",
- "id": {"@type": "g:Int32", "@value": 1234},
- "label": "aKey"}}}} == json.loads(
- self.graphson_writer.write_object(
- Property("name", "marko", VertexProperty(1234, "aKey", 21345, Vertex("vertexId")))))
-
- vertex = self.graphson_reader.read_object(self.graphson_writer.write_object(Vertex(1, "person")))
- assert 1 == vertex.id
- assert "person" == vertex.label
-
- edge = self.graphson_reader.read_object(
- self.graphson_writer.write_object(Edge(3, Vertex(1, "person"), "knows", Vertex(2, "dog"))))
- assert "knows" == edge.label
- assert 3 == edge.id
- assert 1 == edge.outV.id
- assert 2 == edge.inV.id
-
- vertex_property = self.graphson_reader.read_object(
- self.graphson_writer.write_object(VertexProperty(1, "age", 32, Vertex(1))))
- assert 1 == vertex_property.id
- assert "age" == vertex_property.key
- assert 32 == vertex_property.value
-
- property = self.graphson_reader.read_object(self.graphson_writer.write_object(Property("age", 32.2, Edge(1, Vertex(2), "knows", Vertex(3)))))
- assert "age" == property.key
- assert 32.2 == property.value
-
- def test_custom_mapping(self):
- # extended mapping
- class X(object):
- pass
-
- serdes = Mock()
- writer = GraphSONWriter(serializer_map={X: serdes})
- assert X in writer.serializers
-
- # base dicts are not modified
- assert X not in gremlin_python.structure.io.graphsonV3d0._serializers
-
- obj = X()
- d = writer.to_dict(obj)
- serdes.dictify.assert_called_once_with(obj, writer)
- assert d is serdes.dictify()
-
- # overridden mapping
- serdes = Mock()
- writer = GraphSONWriter(serializer_map={int: serdes})
- assert gremlin_python.structure.io.graphsonV3d0._serializers[int] is not writer.serializers[int]
-
- value = 3
- d = writer.to_dict(value)
- serdes.dictify.assert_called_once_with(value, writer)
- assert d is serdes.dictify()
-
- def test_write_long(self):
- mapping = self.graphson_writer.to_dict(1)
- assert mapping['@type'] == 'g:Int32'
- assert mapping['@value'] == 1
-
- mapping = self.graphson_writer.to_dict(long(1))
- assert mapping['@type'] == 'g:Int64'
- assert mapping['@value'] == 1
-
- def test_datetime(self):
- expected = json.dumps({"@type": "g:Date", "@value": 1481750076295}, separators=(',', ':'))
- dt = datetime.datetime.utcfromtimestamp(1481750076295 / 1000.0)
- output = self.graphson_writer.write_object(dt)
- assert expected == output
-
- def test_timestamp(self):
- expected = json.dumps({"@type": "g:Timestamp", "@value": 1481750076295}, separators=(',', ':'))
- ts = timestamp(1481750076295 / 1000.0)
- output = self.graphson_writer.write_object(ts)
- assert expected == output
-
- def test_duration(self):
- expected = json.dumps({"@type": "gx:Duration", "@value": "P5D"}, separators=(',', ':'))
- d = datetime.timedelta(hours=120)
- output = self.graphson_writer.write_object(d)
- assert expected == output
-
- def test_uuid(self):
- expected = json.dumps({'@type': 'g:UUID', '@value': "41d2e28a-20a4-4ab0-b379-d810dede3786"}, separators=(',', ':'))
- prop = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786")
- output = self.graphson_writer.write_object(prop)
- assert expected == output
-
- def test_bytebuffer(self):
- expected = json.dumps({'@type': 'gx:ByteBuffer', '@value': 'c29tZSBieXRlcyBmb3IgeW91'}, separators=(',', ':'))
- bb = ByteBufferType("c29tZSBieXRlcyBmb3IgeW91", "utf8")
- output = self.graphson_writer.write_object(bb)
- assert expected == output
-
- def test_char(self):
- expected = json.dumps({'@type': 'gx:Char', '@value': 'L'}, separators=(',', ':'))
- c = str.__new__(SingleChar, chr(76))
- output = self.graphson_writer.write_object(c)
- assert expected == output