This is an automated email from the ASF dual-hosted git repository. xiazcy pushed a commit to branch python-graphsonv4 in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 697c2065516bcd9ebca406a0a18b3113f28bd92c Author: Yang Xia <[email protected]> AuthorDate: Tue Oct 22 14:18:23 2024 -0700 enable basic GraphSONV4 connectivity in python --- .../python/gremlin_python/driver/serializer.py | 54 +- .../gremlin_python/structure/io/graphsonV4.py | 730 +++++++++++++++++++++ .../tests/driver/test_driver_remote_connection.py | 22 + 3 files changed, 805 insertions(+), 1 deletion(-) 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 94099f4c5d..9aa4a7c0cc 100644 --- a/gremlin-python/src/main/python/gremlin_python/driver/serializer.py +++ b/gremlin-python/src/main/python/gremlin_python/driver/serializer.py @@ -31,11 +31,63 @@ try: except ImportError: import json -from gremlin_python.structure.io import graphbinaryV4 +from gremlin_python.structure.io import graphbinaryV4, graphsonV4 from gremlin_python.structure.io.util import Marker __author__ = 'David M. Brown ([email protected]), Lyndon Bauto ([email protected])' +""" +GraphSONV4 +""" + +class GraphSONSerializerV4(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 = graphsonV4.GraphSONReader + DEFAULT_WRITER_CLASS = graphsonV4.GraphSONWriter + DEFAULT_VERSION = b"application/vnd.gremlin-v4.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._graphson_writer = writer + + @property + def version(self): + """Read only property""" + return self._version + + def serialize_message(self, request_message): + message = self.build_message(request_message.fields, request_message.gremlin) + return message + + def build_message(self, fields, gremlin): + message = fields + message['gremlin'] = gremlin + return self.finalize_message(message) + + def finalize_message(self, message): + message = json.dumps(message) + return message + + def deserialize_message(self, message, is_first_chunk=False): + if is_first_chunk: + msg = json.loads(message if isinstance(message, str) else message.decode('utf-8')) + return self._graphson_reader.to_object(msg) + else: + # graphSON does not stream, the first chunk contains all info + return "" """ GraphBinaryV4 diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV4.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV4.py new file mode 100644 index 0000000000..b4aa99bf8e --- /dev/null +++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV4.py @@ -0,0 +1,730 @@ +# 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 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 = {} + + +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 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), + "label": writer.to_dict([edge.label]), + "inV": writer.to_dict(edge.inV), + "outV": writer.to_dict(edge.outV)}) + + # "outV": writer.to_dict(edge.outV.id), + # "outVLabel": writer.to_dict([edge.outV.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 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) + + +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")[0], 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")[0]), + d.get("label", "edge")[0], + Vertex(reader.to_object(d["inV"]), d.get("inVLabel", "vertex")[0]), + 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"][0], + 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/driver/test_driver_remote_connection.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py index 607501935a..c2cb65af0f 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,6 +20,7 @@ import os from datetime import datetime from gremlin_python import statics +from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection from gremlin_python.statics import long from gremlin_python.process.traversal import TraversalStrategy, P, Order, T, DT, Parameter, Cardinality from gremlin_python.process.graph_traversal import __ @@ -28,6 +29,7 @@ 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 +from gremlin_python.driver import serializer gremlin_server_url = os.environ.get('GREMLIN_SERVER_URL_HTTP', 'http://localhost:{}/') test_no_auth_url = gremlin_server_url.format(45940) @@ -35,6 +37,26 @@ test_no_auth_url = gremlin_server_url.format(45940) class TestDriverRemoteConnection(object): + # this is a temporary test for basic graphSONV4 connectivity, once all types are implemented, enable graphSON testing + # in conftest.py and remove this + def test_graphSONV4_temp(self): + remote_conn = DriverRemoteConnection(test_no_auth_url, 'gmodern', + message_serializer=serializer.GraphSONSerializerV4()) + g = traversal().with_(remote_conn) + assert long(6) == g.V().count().to_list()[0] + # # + 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.with_side_effect('a', ['josh', 'peter']).V(1).out('created').in_('created').values('name').where( + P.within('a')).to_list() + assert 2 == len(results) + assert 'josh' in results + assert 'peter' in results + def test_bulked_request_option(self, remote_connection): g = traversal().with_(remote_connection) result = g.inject(1,2,3,2,1).to_list()
