diff --git a/AUTHORS.txt b/AUTHORS.txt index 92fbe13..28f78c3 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -12,4 +12,4 @@ # Please keep the list sorted. -Google +Peter M. diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 4908967..e31df2e 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -24,3 +24,4 @@ # Please keep the list sorted. +Peter M. \ No newline at end of file diff --git a/README.md b/README.md index 5d8f384..174bf50 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,19 @@ from gremlin_python.driver.driver_remote_connection import DriverRemoteConnectio from janusgraph_python.driver.serializer import JanusGraphSONSerializersV3d0 connection = DriverRemoteConnection( - 'ws://localhost:8182/gremlin', 'g', - message_serializer=JanusGraphSONSerializersV3d0()) + 'ws://localhost:8182/gremlin', 'g', + message_serializer=JanusGraphSONSerializersV3d0()) +``` + +This can be done like this for GraphBinary: + +```python +from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection +from janusgraph_python.driver.serializer import JanusGraphBinarySerializersV1 + +connection = DriverRemoteConnection( + 'ws://localhost:8182/gremlin', 'g', + message_serializer=JanusGraphBinarySerializersV1()) ``` Note that the client should be disposed on shut down to release resources and @@ -76,15 +87,14 @@ version. ## Serialization Formats -JanusGraph-Python supports GraphSON 3 only. GraphBinary is not yet -supported. +JanusGraph-Python supports GraphSON 3 as well as GraphBinary. Not all of the JanusGraph-specific types are already supported by the formats: | Format | RelationIdentifier | Text predicates | Geoshapes | Geo predicates | | ----------- | ------------------ | --------------- | --------- | -------------- | | GraphSON3 | x | x | - | - | -| GraphBinary | - | - | - | - | +| GraphBinary | x | x | - | - | ## Community diff --git a/janusgraph_python/driver/serializer.py b/janusgraph_python/driver/serializer.py index 7a0449a..2181bc1 100644 --- a/janusgraph_python/driver/serializer.py +++ b/janusgraph_python/driver/serializer.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,12 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -from gremlin_python.driver.serializer import GraphSONSerializersV3d0 -from janusgraph_python.structure.io import graphsonV3d0 +from gremlin_python.driver.serializer import GraphSONSerializersV3d0, GraphBinarySerializersV1 +from janusgraph_python.structure.io import graphsonV3d0, graphbinaryV1 class JanusGraphSONSerializersV3d0(GraphSONSerializersV3d0): """Message serializer for GraphSON 3.0 extended with JanusGraph-specific types""" def __init__(self): reader = graphsonV3d0.JanusGraphSONReader() writer = graphsonV3d0.JanusGraphSONWriter() - super(GraphSONSerializersV3d0, self).__init__(reader, writer) \ No newline at end of file + super(GraphSONSerializersV3d0, self).__init__(reader, writer) + +class JanusGraphBinarySerializersV1(GraphBinarySerializersV1): + """Message serializer for GraphBinary 1.0 extended with JanusGraph-specific types""" + def __init__(self): + reader = graphbinaryV1.JanusGraphBinaryReader() + writer = graphbinaryV1.JanusGraphBinaryWriter() + super().__init__(reader, writer) \ No newline at end of file diff --git a/janusgraph_python/process/traversal.py b/janusgraph_python/process/traversal.py index f624a83..b60a3b8 100644 --- a/janusgraph_python/process/traversal.py +++ b/janusgraph_python/process/traversal.py @@ -1,5 +1,5 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/janusgraph_python/structure/io/graphbinaryV1.py b/janusgraph_python/structure/io/graphbinaryV1.py new file mode 100644 index 0000000..e2ab630 --- /dev/null +++ b/janusgraph_python/structure/io/graphbinaryV1.py @@ -0,0 +1,240 @@ +# Copyright 2024 JanusGraph-Python Authors +# +# Licensed 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. + +from gremlin_python.structure.io.graphbinaryV1 import ( + _GraphBinaryTypeIO, StringIO, GraphBinaryReader, GraphBinaryWriter, DataType, + _make_packer, + uint64_pack, uint64_unpack, uint8_pack, uint8_unpack, +) +from janusgraph_python.process.traversal import _JanusGraphP, RelationIdentifier + +uint16_pack, uint16_unpack = _make_packer('>H') +uint32_pack, uint32_unpack = _make_packer('>I') + +class JanusGraphBinaryReader(GraphBinaryReader): + def __init__(self): + # register JanusGraph-specific deserializer for custom type code + deserializer_map = { + DataType.custom: JanusGraphBinaryTypeIO + } + + GraphBinaryReader.__init__(self, deserializer_map) + +class JanusGraphBinaryWriter(GraphBinaryWriter): + def __init__(self): + # register JanusGraph-specific RelationIdentifier and text-predicate serializer + serializer_map = [ + (RelationIdentifier, JanusGraphRelationIdentifierIO), + (_JanusGraphP, JanusGraphPSerializer) + ] + + GraphBinaryWriter.__init__(self, serializer_map) + +class JanusGraphBinaryTypeIO(_GraphBinaryTypeIO): + # registry of JanusGraph-specific types with their type_id, type_name and class for deserialization + io_registry = {} + + @classmethod + def register_deserializer(cls, type_class): + """ + Method to register a deserializer for a JanusGraph-specific type + """ + cls.io_registry[type_class.graphbinary_type_id] = (type_class.graphbinary_type_name, type_class) + + @classmethod + def objectify(cls, buff, reader, nullable=True): + """ + Method used for deserialization of JanusGraph-specific type + """ + return cls.is_null(buff, reader, cls._read_data, nullable) + + @classmethod + def _read_data(cls, b, r): + """ + Method used for identifying a JanusGraph-specific type and + find a deserializer class for it + """ + # check if first byte is custom type code byte + if uint8_unpack(b.read(1)) != DataType.custom.value: + return None + + # get the custom type name length + custom_type_name_length = uint16_unpack(b.read(2)) + custom_type_name = b.read(custom_type_name_length).decode() + + # read the custom type id + custom_type_id = uint32_unpack(b.read(4)) + + # try to get a deserializer class for the JanusGraph-specific type + custom_serializer = cls.io_registry.get(custom_type_id) + if not custom_serializer: + raise NotImplementedError(f"No deserializer found for JanusGraph type with id: {custom_type_id}") + + # check the type name + if custom_serializer[0] != custom_type_name: + raise NotImplementedError(f"No deserializer found for JanusGraph type with name: {custom_type_name}") + + return custom_serializer[1].objectify(b, r) + + @classmethod + def prefix_bytes_custom_type(cls, writer, to_extend, as_value=False): + """ + Helper method to add a specific byte array prefix while serializing + JanusGraph-specific type as custom type + """ + if to_extend is None: + to_extend = bytearray() + + # use the custom type code + if not as_value: + to_extend += uint8_pack(DataType.custom.value) + + # add the name of the custom JanusGraph type + StringIO.dictify(cls.graphbinary_type_name, writer, to_extend, True, False) + + # add the id of the custom JanusGraph type + to_extend += uint32_pack(cls.graphbinary_type_id) + + # use the custom type code + if not as_value: + to_extend += uint8_pack(DataType.custom.value) + +class JanusGraphPSerializer(JanusGraphBinaryTypeIO): + graphbinary_type_id = 0x1002 + graphbinary_type_name = "janusgraph.P" + python_type = _JanusGraphP + + @classmethod + def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True): + """ + Method to serialize JanusGraph-specific Text predicate + """ + cls.prefix_bytes_custom_type(writer, to_extend, as_value) + + # serialize the custom JanusGraph operator + StringIO.dictify(obj.operator, writer, to_extend, True, False) + + # serialize the value + writer.to_dict(obj.value, to_extend) + + return to_extend + +class JanusGraphRelationIdentifierIO(JanusGraphBinaryTypeIO): + graphbinary_type_id = 0x1001 + graphbinary_type_name = "janusgraph.RelationIdentifier" + python_type = RelationIdentifier + + long_marker = 0 + string_marker = 1 + + @classmethod + def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True): + """ + Method to serialize JanusGraph-specific RelationIdentifier + """ + cls.prefix_bytes_custom_type(writer, to_extend, as_value) + + # serialize out vertex ID + if isinstance(obj.out_vertex_id, int): + to_extend += uint8_pack(cls.long_marker) + to_extend += uint64_pack(obj.out_vertex_id) + else: + to_extend += uint8_pack(cls.string_marker) + cls._write_string(obj.out_vertex_id, writer, to_extend) + + # serialize edge type ID and relation ID + to_extend += uint64_pack(obj.type_id) + to_extend += uint64_pack(obj.relation_id) + + # serialize in vertex ID + if obj.in_vertex_id is None: + to_extend += uint8_pack(cls.long_marker) + to_extend += uint64_pack(0) + elif isinstance(obj.in_vertex_id, int): + to_extend += uint8_pack(cls.long_marker) + to_extend += uint64_pack(obj.in_vertex_id) + else: + to_extend += uint8_pack(cls.string_marker) + cls._write_string(obj.in_vertex_id, writer, to_extend) + + return to_extend + + @classmethod + def objectify(cls, b, r): + """ + Method to deserialize JanusGraph-specific RelationIdentifier + """ + if uint8_unpack(b.read(1)) != DataType.custom.value: + raise Exception("Unexpected type while deserializing JanusGraph RelationIdentifier") + + # read the next byte that shows if the out vertex id is string or long + out_vertex_id_marker = uint8_unpack(b.read(1)) + + # deserialize out vertex ID + if out_vertex_id_marker == cls.string_marker: + out_vertex_id = cls._read_string(b) + else: + out_vertex_id = uint64_unpack(b.read(8)) + + # deserialize edge type ID and relation ID + type_id = uint64_unpack(b.read(8)) + relation_id = uint64_unpack(b.read(8)) + + # deserialize in vertex ID + in_vertex_id_marker = uint8_unpack(b.read(1)) + if in_vertex_id_marker == cls.string_marker: + in_vertex_id = cls._read_string(b) + else: + in_vertex_id = uint64_unpack(b.read(8)) + if in_vertex_id == 0: + in_vertex_id = None + + return RelationIdentifier.from_ids(out_vertex_id, type_id, relation_id, in_vertex_id) + + @classmethod + def _read_string(cls, buff): + """ + Helper method to read a string represented as byte array. + The length of the string is not known upfront so the byte + array needs to be red until a byte occurs that is marked + with a special end marker + """ + final_string = "" + while True: + c = 0xFF & uint8_unpack(buff.read(1)) + final_string += chr(c & 0x7F) + + # check if the character is marked with end marker + # if yes that is the end of the string + if c & 0x80 > 0: + break + + return final_string + + @classmethod + def _write_string(cls, string, writer, to_extend): + """ + Helper method to create a byte array from a string and + mark the string's last character with special end marker + """ + b = bytearray() + b.extend(map(ord, string)) + + # add end marker to the last character + b[-1] |= 0x80 + + to_extend += b + +# register the JanusGraph-specific RelationIdentifier as deserializer +JanusGraphBinaryTypeIO.register_deserializer(JanusGraphRelationIdentifierIO) \ No newline at end of file diff --git a/janusgraph_python/structure/io/graphsonV3d0.py b/janusgraph_python/structure/io/graphsonV3d0.py index d94aab8..42a355e 100644 --- a/janusgraph_python/structure/io/graphsonV3d0.py +++ b/janusgraph_python/structure/io/graphsonV3d0.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/janusgraph_python/structure/io/util.py b/janusgraph_python/structure/io/util.py index 0d88016..d99f02c 100644 --- a/janusgraph_python/structure/io/util.py +++ b/janusgraph_python/structure/io/util.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/integration/RelationIdentifier_test.py b/tests/integration/RelationIdentifier_test.py index e66442a..5d3de5b 100644 --- a/tests/integration/RelationIdentifier_test.py +++ b/tests/integration/RelationIdentifier_test.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,20 +12,39 @@ # See the License for the specific language governing permissions and # limitations under the License. +from pytest import mark, param from janusgraph_python.process.traversal import RelationIdentifier class _RelationIdentifierSerializer(object): # g is expected to be set once this class is inherited g = None - def test_RelationIdentifier_as_edge_id(self): - edge_id = self.g.E().id_().next() + @mark.parametrize( + 'vertex_id,edge_type', + [ + param(1280, 'mother', id='long in and out vertex ID'), + param('jupiter', 'lives', id='long in vertex ID, string out vertex ID'), + param('jupiter', 'brother', id='string in and out vertex ID'), + param(1024, 'father', id='string in vertex ID, long out vertex ID'), + ] + ) + def test_RelationIdentifier_as_edge_id(self, vertex_id, edge_type): + edge_id = self.g.V(vertex_id).both_e(edge_type).id_().next() count = self.g.E(edge_id).count().next() assert count == 1 - def test_Edge(self): - edge = self.g.E().next() + @mark.parametrize( + 'vertex_id,edge_type', + [ + param(1280, 'mother', id='long in and out vertex ID'), + param('jupiter', 'lives', id='long in vertex ID, string out vertex ID'), + param('jupiter', 'brother', id='string in and out vertex ID'), + param(1024, 'father', id='string in vertex ID, long out vertex ID'), + ] + ) + def test_Edge(self, vertex_id, edge_type): + edge = self.g.V(vertex_id).both_e(edge_type).next() count = self.g.E(edge).count().next() assert count == 1 @@ -34,12 +53,30 @@ class _RelationIdentifierDeserializer(object): # g is expected to be set once this class is inherited g = None - def test_valid_RelationIdentifier(self): - relation_identifier = self.g.V().has('demigod', 'name', 'hercules').out_e('father').id_().next() + @mark.parametrize( + 'vertex_id,edge_type', + [ + param(1280, 'mother', id='long in and out vertex ID'), + param('jupiter', 'lives', id='long in vertex ID, string out vertex ID'), + param('jupiter', 'brother', id='string in and out vertex ID'), + param(1024, 'father', id='string in vertex ID, long out vertex ID'), + ] + ) + def test_valid_RelationIdentifier(self, vertex_id, edge_type): + relation_identifier = self.g.V(vertex_id).both_e(edge_type).id_().next() assert type(relation_identifier) is RelationIdentifier - def test_Edge(self): - edge = self.g.V().has('demigod', 'name', 'hercules').out_e('father').next() + @mark.parametrize( + 'vertex_id,edge_type', + [ + param(1280, 'mother', id='long in and out vertex ID'), + param('jupiter', 'lives', id='long in vertex ID, string out vertex ID'), + param('jupiter', 'brother', id='string in and out vertex ID'), + param(1024, 'father', id='string in vertex ID, long out vertex ID'), + ] + ) + def test_Edge(self, vertex_id, edge_type): + edge = self.g.V(vertex_id).both_e(edge_type).next() assert type(edge.id) is RelationIdentifier \ No newline at end of file diff --git a/tests/integration/Text_test.py b/tests/integration/Text_test.py index b09c63a..d8aa22d 100644 --- a/tests/integration/Text_test.py +++ b/tests/integration/Text_test.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 06c202c..d2e77f5 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,11 +22,12 @@ from testcontainers.core.container import DockerContainer from gremlin_python.process.anonymous_traversal import traversal from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection -from janusgraph_python.driver.serializer import JanusGraphSONSerializersV3d0 +from janusgraph_python.driver.serializer import JanusGraphSONSerializersV3d0, JanusGraphBinarySerializersV1 current_path = pathlib.Path(__file__).parent.resolve() JANUSGRAPH_REPOSITORY = None JANUSGRAPH_VERSION_PARAMS = [] +CONTAINER_REGISTRY = {} # read integration tests config from JSON with open(os.path.join(current_path, "config.json")) as f: @@ -87,6 +88,17 @@ def graph_connection_graphson(request, graph_container): container = graph_container(request) return graph_connection(request, container, JanusGraphSONSerializersV3d0()) +@fixture(scope='session') +def graph_connection_graphbinary(request, graph_container): + """ + Fixture for creating connection with JanusGraphBinarySerializersV1 serializer + to the JanusGraph container + """ + # NOTE: this is a workaround to be able to pass the session fixture param + # to the graph_container fixture + container = graph_container(request) + return graph_connection(request, container, JanusGraphBinarySerializersV1()) + def graph_connection(request, graph_container, serializer): """ Fixture for creating connection with given serializer to the @@ -150,11 +162,17 @@ def is_server_ready(): tag = passed_request.param image = f"{JANUSGRAPH_REPOSITORY}:{tag}" + # if a container for the same image already exist, let's reuse it + if image in CONTAINER_REGISTRY: + return CONTAINER_REGISTRY.get(image) + container = ( DockerContainer(image) .with_name(f'janusgraph_{tag}') .with_exposed_ports(8182) .with_volume_mapping(os.path.join(current_path, 'load_data.groovy'), '/docker-entrypoint-initdb.d/load_data.groovy') + # use custom janusgraph.properties that configures inmemory graph and enables string vertex IDs + .with_volume_mapping(os.path.join(current_path, 'janusgraph.properties'), '/etc/opt/janusgraph/janusgraph.properties') .start() ) is_server_ready() @@ -164,5 +182,7 @@ def drop_container(): request.addfinalizer(drop_container) + CONTAINER_REGISTRY[image] = container + return container return create_container \ No newline at end of file diff --git a/tests/integration/io/test_graphbinaryV1.py b/tests/integration/io/test_graphbinaryV1.py new file mode 100644 index 0000000..b44d4ae --- /dev/null +++ b/tests/integration/io/test_graphbinaryV1.py @@ -0,0 +1,42 @@ +# Copyright 2024 JanusGraph-Python Authors +# +# Licensed 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. + +from pytest import fixture, mark + +from integration.RelationIdentifier_test import _RelationIdentifierSerializer, _RelationIdentifierDeserializer +from integration.Text_test import _TextTests +from ..conftest import JANUSGRAPH_VERSION_PARAMS + +# parametrize all integration tests to run against various JanusGraph versions +pytestmark = mark.parametrize( + "graph_connection_graphbinary", JANUSGRAPH_VERSION_PARAMS, indirect=True +) + +class TestGraphBinaryRelationIdentifierSerializer(_RelationIdentifierSerializer): + @fixture(autouse=True) + def _graph_connection_graphson(self, graph_connection_graphbinary): + # setting up 'g' variable so parent class's methods can use it + self.g = graph_connection_graphbinary + +class TestGraphBinaryRelationIdentifierDeserializer(_RelationIdentifierDeserializer): + @fixture(autouse=True) + def _graph_connection_graphson(self, graph_connection_graphbinary): + # setting up 'g' variable so parent class's methods can use it + self.g = graph_connection_graphbinary + +class TestGraphBinaryText(_TextTests): + @fixture(autouse=True) + def _graph_connection_graphbinary(self, graph_connection_graphbinary): + # setting up 'g' variable so parent class's methods can use it + self.g = graph_connection_graphbinary \ No newline at end of file diff --git a/tests/integration/io/test_graphsonV3d0.py b/tests/integration/io/test_graphsonV3d0.py index 0fec8e2..52123c0 100644 --- a/tests/integration/io/test_graphsonV3d0.py +++ b/tests/integration/io/test_graphsonV3d0.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/integration/janusgraph.properties b/tests/integration/janusgraph.properties new file mode 100644 index 0000000..0d487aa --- /dev/null +++ b/tests/integration/janusgraph.properties @@ -0,0 +1,24 @@ +# +# Copyright 2024 JanusGraph-Python Authors +# +# Licensed 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. + +gremlin.graph = org.janusgraph.core.JanusGraphFactory +storage.backend = inmemory +storage.directory = /var/lib/janusgraph/data +index.search.backend = lucene +index.search.directory = /var/lib/janusgraph/index + +# enable custom string vertex IDs +graph.set-vertex-id = true +graph.allow-custom-vid-types = true \ No newline at end of file diff --git a/tests/integration/load_data.groovy b/tests/integration/load_data.groovy index 5173b6a..e4a8d46 100644 --- a/tests/integration/load_data.groovy +++ b/tests/integration/load_data.groovy @@ -1,4 +1,4 @@ -// Copyright 2019 JanusGraph Authors +// Copyright 2024 JanusGraph-Python Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,18 +14,19 @@ g = traversal().withRemote('conf/remote-graph.properties') -g.addV('titan').property('name', 'saturn').property('age', 10000).as('saturn'). - addV('location').property('name', 'sky').as('sky'). - addV('location').property('name', 'sea').as('sea'). - addV('god').property('name', 'jupiter').property('age', 5000).as('jupiter'). - addV('god').property('name', 'neptune').property('age', 4500).as('neptune'). - addV('demigod').property('name', 'hercules').property('age', 30).as('hercules'). - addV('human').property('name', 'alcmene').property('age', 45).as('alcmene'). - addV('god').property('name', 'pluto').property('age', 4000).as('pluto'). - addV('monster').property('name', 'nemean').as('nemean'). - addV('monster').property('name', 'hydra').as('hydra'). - addV('monster').property('name', 'cerberus').as('cerberus'). - addV('location').property('name', 'tartarus').as('tartarus'). +// create nodes with defined string and long IDs +g.addV('titan').property(T.id, 'saturn').property('name', 'saturn').property('age', 10000).as('saturn'). + addV('location').property(T.id, 256).property('name', 'sky').as('sky'). + addV('location').property(T.id, 512).property('name', 'sea').as('sea'). + addV('god').property(T.id, 'jupiter').property('name', 'jupiter').property('age', 5000).as('jupiter'). + addV('god').property(T.id, 'neptune').property('name', 'neptune').property('age', 4500).as('neptune'). + addV('demigod').property(T.id, 1024).property('name', 'hercules').property('age', 30).as('hercules'). + addV('human').property(T.id, 1280).property('name', 'alcmene').property('age', 45).as('alcmene'). + addV('god').property(T.id, 'pluto').property('name', 'pluto').property('age', 4000).as('pluto'). + addV('monster').property(T.id, 1536).property('name', 'nemean').as('nemean'). + addV('monster').property(T.id, 1792).property('name', 'hydra').as('hydra'). + addV('monster').property(T.id, 2048).property('name', 'cerberus').as('cerberus'). + addV('location').property(T.id, 2304).property('name', 'tartarus').as('tartarus'). addE('father').from('jupiter').to('saturn'). addE('lives').from('jupiter').to('sky').property('reason', 'loves fresh breezes'). addE('brother').from('jupiter').to('neptune'). diff --git a/tests/unit/driver/test_serializer.py b/tests/unit/driver/test_serializer.py index 68a3a04..498c91b 100644 --- a/tests/unit/driver/test_serializer.py +++ b/tests/unit/driver/test_serializer.py @@ -1,11 +1,33 @@ -from janusgraph_python.driver.serializer import JanusGraphSONSerializersV3d0 -from janusgraph_python.structure.io import graphsonV3d0 +# Copyright 2024 JanusGraph-Python Authors +# +# Licensed 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. + +from janusgraph_python.driver.serializer import JanusGraphSONSerializersV3d0, JanusGraphBinarySerializersV1 +from janusgraph_python.structure.io import graphsonV3d0, graphbinaryV1 def test_graphson_serializer_v3(): graphson_serializer_v3 = JanusGraphSONSerializersV3d0() - + assert graphson_serializer_v3.version == b"application/vnd.gremlin-v3.0+json" assert isinstance(graphson_serializer_v3._graphson_reader, graphsonV3d0.JanusGraphSONReader) assert isinstance(graphson_serializer_v3.standard._writer, graphsonV3d0.JanusGraphSONWriter) - assert isinstance(graphson_serializer_v3.traversal._writer, graphsonV3d0.JanusGraphSONWriter) \ No newline at end of file + assert isinstance(graphson_serializer_v3.traversal._writer, graphsonV3d0.JanusGraphSONWriter) + +def test_graphbinary_serializer_v1(): + graphbinary_serializer_v1 = JanusGraphBinarySerializersV1() + + assert graphbinary_serializer_v1.version == b"application/vnd.graphbinary-v1.0" + assert isinstance(graphbinary_serializer_v1._graphbinary_reader, graphbinaryV1.JanusGraphBinaryReader) + assert isinstance(graphbinary_serializer_v1.standard._writer, graphbinaryV1.JanusGraphBinaryWriter) + assert isinstance(graphbinary_serializer_v1.traversal._writer, graphbinaryV1.JanusGraphBinaryWriter) \ No newline at end of file diff --git a/tests/unit/process/test_traversal.py b/tests/unit/process/test_traversal.py index 51aa4ff..64254f2 100644 --- a/tests/unit/process/test_traversal.py +++ b/tests/unit/process/test_traversal.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/structure/io/test_graphsonV3d0.py b/tests/unit/structure/io/test_graphsonV3d0.py index ab28365..3431cb7 100644 --- a/tests/unit/structure/io/test_graphsonV3d0.py +++ b/tests/unit/structure/io/test_graphsonV3d0.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/structure/io/test_util.py b/tests/unit/structure/io/test_util.py index 9f0a8dd..d4d882e 100644 --- a/tests/unit/structure/io/test_util.py +++ b/tests/unit/structure/io/test_util.py @@ -1,4 +1,4 @@ -# Copyright 2023 JanusGraph-Python Authors +# Copyright 2024 JanusGraph-Python Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License.