gremlinpython 4.0.0b2__py3-none-any.whl → 4.0.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gremlin_python/__init__.py +1 -1
- gremlin_python/driver/aiohttp/transport.py +257 -85
- gremlin_python/driver/auth.py +46 -21
- gremlin_python/driver/client.py +89 -61
- gremlin_python/driver/connection.py +123 -19
- gremlin_python/driver/driver_remote_connection.py +16 -39
- gremlin_python/driver/{transport.py → exceptions.py} +10 -24
- gremlin_python/driver/http_request.py +65 -0
- gremlin_python/driver/request.py +3 -2
- gremlin_python/driver/resultset.py +11 -5
- gremlin_python/driver/serializer.py +50 -130
- gremlin_python/driver/transaction.py +178 -0
- gremlin_python/driver/useragent.py +1 -1
- gremlin_python/process/graph_traversal.py +210 -93
- gremlin_python/process/traversal.py +114 -51
- gremlin_python/structure/graph.py +450 -5
- gremlin_python/structure/io/graphbinaryV4.py +177 -37
- {gremlinpython-4.0.0b2.dist-info → gremlinpython-4.0.0.dev1.dist-info}/METADATA +7 -5
- gremlinpython-4.0.0.dev1.dist-info/RECORD +33 -0
- {gremlinpython-4.0.0b2.dist-info → gremlinpython-4.0.0.dev1.dist-info}/WHEEL +1 -1
- gremlin_python/driver/protocol.py +0 -175
- gremlin_python/structure/io/graphsonV4.py +0 -599
- gremlinpython-4.0.0b2.dist-info/RECORD +0 -33
- {gremlinpython-4.0.0b2.dist-info → gremlinpython-4.0.0.dev1.dist-info}/licenses/LICENSE +0 -0
- {gremlinpython-4.0.0b2.dist-info → gremlinpython-4.0.0.dev1.dist-info}/licenses/NOTICE +0 -0
- {gremlinpython-4.0.0b2.dist-info → gremlinpython-4.0.0.dev1.dist-info}/top_level.txt +0 -0
|
@@ -27,10 +27,11 @@ from datetime import datetime, timedelta, timezone
|
|
|
27
27
|
from struct import pack, unpack
|
|
28
28
|
|
|
29
29
|
from aenum import Enum
|
|
30
|
-
from gremlin_python.process.traversal import Direction, T, Merge
|
|
30
|
+
from gremlin_python.process.traversal import Direction, T, Merge
|
|
31
31
|
from gremlin_python.statics import FloatType, BigDecimal, ShortType, IntType, LongType, BigIntType, \
|
|
32
32
|
DictType, SetType, SingleByte, SingleChar
|
|
33
|
-
from gremlin_python.structure.graph import Graph, Edge, Property, Vertex, VertexProperty, Path
|
|
33
|
+
from gremlin_python.structure.graph import Graph, Edge, Property, Vertex, VertexProperty, Path, CompositePDT, \
|
|
34
|
+
PrimitivePDT, Tree, _pdt_decorated_types
|
|
34
35
|
from gremlin_python.structure.io.util import HashableDict, SymbolUtil, Marker
|
|
35
36
|
|
|
36
37
|
log = logging.getLogger(__name__)
|
|
@@ -69,16 +70,19 @@ class DataType(Enum):
|
|
|
69
70
|
binary = 0x25
|
|
70
71
|
short = 0x26
|
|
71
72
|
boolean = 0x27
|
|
72
|
-
tree = 0x2b
|
|
73
|
-
gtype = 0x30
|
|
73
|
+
tree = 0x2b
|
|
74
74
|
char = 0x80
|
|
75
75
|
duration = 0x81
|
|
76
|
+
composite_pdt = 0xf0
|
|
77
|
+
primitive_pdt = 0xf1
|
|
76
78
|
marker = 0xfd
|
|
77
|
-
custom = 0x00 # todo
|
|
78
79
|
|
|
79
80
|
|
|
80
81
|
NULL_BYTES = [DataType.null.value, 0x01]
|
|
81
82
|
|
|
83
|
+
# null type code as a plain int, so the per-read null check skips the aenum lookup
|
|
84
|
+
_NULL = DataType.null.value
|
|
85
|
+
|
|
82
86
|
|
|
83
87
|
def _make_packer(format_string):
|
|
84
88
|
packer = struct.Struct(format_string)
|
|
@@ -144,27 +148,65 @@ class GraphBinaryWriter(object):
|
|
|
144
148
|
|
|
145
149
|
|
|
146
150
|
class GraphBinaryReader(object):
|
|
147
|
-
def __init__(self, deserializer_map=None):
|
|
151
|
+
def __init__(self, deserializer_map=None, pdt_registry=None):
|
|
148
152
|
self.deserializers = _deserializers.copy()
|
|
149
153
|
if deserializer_map:
|
|
150
154
|
self.deserializers.update(deserializer_map)
|
|
155
|
+
self.pdt_registry = pdt_registry
|
|
156
|
+
# Mirror of self.deserializers keyed by int type code instead of DataType.
|
|
157
|
+
# Avoids the per-read DataType(bt) call, whose aenum construction negatively affects performance on large results.
|
|
158
|
+
self._deserializer_by_type_code = {dt.value: des.objectify for dt, des in self.deserializers.items()}
|
|
151
159
|
|
|
152
160
|
def read_object(self, b):
|
|
161
|
+
if b is None:
|
|
162
|
+
return None
|
|
153
163
|
if isinstance(b, bytearray):
|
|
154
164
|
return self.to_object(io.BytesIO(b))
|
|
155
|
-
|
|
156
|
-
return self.to_object(b)
|
|
165
|
+
return self.to_object(b)
|
|
157
166
|
|
|
158
167
|
def to_object(self, buff, data_type=None, nullable=True):
|
|
159
168
|
if data_type is None:
|
|
160
169
|
bt = uint8_unpack(buff.read(1))
|
|
161
|
-
if bt ==
|
|
170
|
+
if bt == _NULL:
|
|
162
171
|
if nullable:
|
|
163
172
|
buff.read(1)
|
|
164
173
|
return None
|
|
165
|
-
|
|
174
|
+
try:
|
|
175
|
+
objectify = self._deserializer_by_type_code[bt]
|
|
176
|
+
except KeyError:
|
|
177
|
+
raise ValueError("%r is not a valid DataType" % bt) from None
|
|
178
|
+
result = objectify(buff, self, nullable)
|
|
166
179
|
else:
|
|
167
|
-
|
|
180
|
+
result = self.deserializers[data_type].objectify(buff, self, nullable)
|
|
181
|
+
if self.pdt_registry is not None and isinstance(result, PrimitivePDT):
|
|
182
|
+
hydrated = self.pdt_registry.hydrate_primitive(result)
|
|
183
|
+
if not isinstance(hydrated, PrimitivePDT):
|
|
184
|
+
return hydrated
|
|
185
|
+
result = hydrated
|
|
186
|
+
if self.pdt_registry is not None and isinstance(result, CompositePDT):
|
|
187
|
+
hydrated = self.pdt_registry.hydrate(result)
|
|
188
|
+
if not isinstance(hydrated, CompositePDT):
|
|
189
|
+
return hydrated
|
|
190
|
+
result = hydrated
|
|
191
|
+
if isinstance(result, CompositePDT) and result.name in _pdt_decorated_types:
|
|
192
|
+
return self._hydrate_decorated(result)
|
|
193
|
+
return result
|
|
194
|
+
|
|
195
|
+
def _hydrate_decorated(self, pdt):
|
|
196
|
+
"""Hydrate a CompositePDT using a @provider_defined decorated class."""
|
|
197
|
+
cls = _pdt_decorated_types[pdt.name]
|
|
198
|
+
fields = {}
|
|
199
|
+
for k, v in pdt.fields.items():
|
|
200
|
+
if isinstance(v, CompositePDT) and v.name in _pdt_decorated_types:
|
|
201
|
+
fields[k] = self._hydrate_decorated(v)
|
|
202
|
+
elif self.pdt_registry is not None and isinstance(v, CompositePDT):
|
|
203
|
+
fields[k] = self.pdt_registry.hydrate(v)
|
|
204
|
+
else:
|
|
205
|
+
fields[k] = v
|
|
206
|
+
obj = cls.__new__(cls)
|
|
207
|
+
for k, v in fields.items():
|
|
208
|
+
setattr(obj, k, v)
|
|
209
|
+
return obj
|
|
168
210
|
|
|
169
211
|
|
|
170
212
|
class _GraphBinaryTypeIO(object, metaclass=GraphBinaryTypeType):
|
|
@@ -567,12 +609,21 @@ class EdgeIO(_GraphBinaryTypeIO):
|
|
|
567
609
|
cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
|
|
568
610
|
|
|
569
611
|
writer.to_dict(obj.id, to_extend)
|
|
570
|
-
# serializing
|
|
571
|
-
|
|
612
|
+
# serializing labels as list according to GraphBinaryV4
|
|
613
|
+
if hasattr(obj, '_labels'):
|
|
614
|
+
ListIO.dictify(list(obj._labels), writer, to_extend, True, False)
|
|
615
|
+
else:
|
|
616
|
+
ListIO.dictify([obj.label], writer, to_extend, True, False)
|
|
572
617
|
writer.to_dict(obj.inV.id, to_extend)
|
|
573
|
-
|
|
618
|
+
if hasattr(obj.inV, '_labels'):
|
|
619
|
+
ListIO.dictify(list(obj.inV._labels), writer, to_extend, True, False)
|
|
620
|
+
else:
|
|
621
|
+
ListIO.dictify([obj.inV.label], writer, to_extend, True, False)
|
|
574
622
|
writer.to_dict(obj.outV.id, to_extend)
|
|
575
|
-
|
|
623
|
+
if hasattr(obj.outV, '_labels'):
|
|
624
|
+
ListIO.dictify(list(obj.outV._labels), writer, to_extend, True, False)
|
|
625
|
+
else:
|
|
626
|
+
ListIO.dictify([obj.outV.label], writer, to_extend, True, False)
|
|
576
627
|
to_extend.extend(NULL_BYTES)
|
|
577
628
|
to_extend.extend(NULL_BYTES)
|
|
578
629
|
|
|
@@ -585,15 +636,19 @@ class EdgeIO(_GraphBinaryTypeIO):
|
|
|
585
636
|
@classmethod
|
|
586
637
|
def _read_edge(cls, b, r):
|
|
587
638
|
edgeid = r.read_object(b)
|
|
588
|
-
# reading
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
639
|
+
# reading label list according to GraphBinaryV4
|
|
640
|
+
edge_labels = r.to_object(b, DataType.list, False)
|
|
641
|
+
inv_id = r.read_object(b)
|
|
642
|
+
inv_labels = r.to_object(b, DataType.list, False)
|
|
643
|
+
inv = Vertex(inv_id, labels=inv_labels)
|
|
644
|
+
outv_id = r.read_object(b)
|
|
645
|
+
outv_labels = r.to_object(b, DataType.list, False)
|
|
646
|
+
outv = Vertex(outv_id, labels=outv_labels)
|
|
592
647
|
b.read(2)
|
|
593
648
|
props = r.read_object(b)
|
|
594
649
|
# null properties are returned as empty lists
|
|
595
650
|
properties = [] if props is None else props
|
|
596
|
-
edge = Edge(edgeid, outv,
|
|
651
|
+
edge = Edge(edgeid, outv, edge_labels[0] if edge_labels else "edge", inv, properties, labels=edge_labels)
|
|
597
652
|
return edge
|
|
598
653
|
|
|
599
654
|
|
|
@@ -614,6 +669,42 @@ class PathIO(_GraphBinaryTypeIO):
|
|
|
614
669
|
return cls.is_null(buff, reader, lambda b, r: Path(r.read_object(b), r.read_object(b)), nullable)
|
|
615
670
|
|
|
616
671
|
|
|
672
|
+
class TreeIO(_GraphBinaryTypeIO):
|
|
673
|
+
|
|
674
|
+
python_type = Tree
|
|
675
|
+
graphbinary_type = DataType.tree
|
|
676
|
+
|
|
677
|
+
@classmethod
|
|
678
|
+
def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
|
|
679
|
+
# when as_value (a nested/bare child tree) prefix_bytes writes nothing:
|
|
680
|
+
# no type-id and no null flag. As a root value it writes {type-id}{null flag}.
|
|
681
|
+
cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
|
|
682
|
+
root_nodes = obj.root_nodes()
|
|
683
|
+
to_extend.extend(int32_pack(len(root_nodes)))
|
|
684
|
+
for key in root_nodes:
|
|
685
|
+
child = obj.child_at(key)
|
|
686
|
+
# key is written fully-qualified (its own type-id + null flag + value)
|
|
687
|
+
writer.to_dict(key, to_extend)
|
|
688
|
+
# child is written as a BARE tree value: no type-id, no null flag
|
|
689
|
+
cls.dictify(child, writer, to_extend, as_value=True, nullable=False)
|
|
690
|
+
return to_extend
|
|
691
|
+
|
|
692
|
+
@classmethod
|
|
693
|
+
def objectify(cls, buff, reader, nullable=True):
|
|
694
|
+
return cls.is_null(buff, reader, cls._read_tree, nullable)
|
|
695
|
+
|
|
696
|
+
@classmethod
|
|
697
|
+
def _read_tree(cls, b, r):
|
|
698
|
+
size = cls.read_int(b)
|
|
699
|
+
tree = Tree()
|
|
700
|
+
while size > 0:
|
|
701
|
+
key = r.read_object(b)
|
|
702
|
+
child = cls.objectify(b, r, False)
|
|
703
|
+
tree.get_or_create_child(key).add_tree(child)
|
|
704
|
+
size = size - 1
|
|
705
|
+
return tree
|
|
706
|
+
|
|
707
|
+
|
|
617
708
|
class PropertyIO(_GraphBinaryTypeIO):
|
|
618
709
|
|
|
619
710
|
python_type = Property
|
|
@@ -653,7 +744,10 @@ class TinkerGraphIO(_GraphBinaryTypeIO):
|
|
|
653
744
|
IntIO.dictify(len(vertices), writer, to_extend, True, False)
|
|
654
745
|
for v in vertices:
|
|
655
746
|
writer.to_dict(v.id, to_extend)
|
|
656
|
-
|
|
747
|
+
if hasattr(v, '_labels'):
|
|
748
|
+
ListIO.dictify(list(v._labels), writer, to_extend, True, False)
|
|
749
|
+
else:
|
|
750
|
+
ListIO.dictify([v.label], writer, to_extend, True, False)
|
|
657
751
|
v_props = v.properties
|
|
658
752
|
IntIO.dictify(len(v_props), writer, to_extend, True, False)
|
|
659
753
|
for vp in v_props:
|
|
@@ -666,7 +760,10 @@ class TinkerGraphIO(_GraphBinaryTypeIO):
|
|
|
666
760
|
IntIO.dictify(len(edges), writer, to_extend, True, False)
|
|
667
761
|
for e in edges:
|
|
668
762
|
writer.to_dict(e.id, to_extend)
|
|
669
|
-
|
|
763
|
+
if hasattr(e, '_labels'):
|
|
764
|
+
ListIO.dictify(list(e._labels), writer, to_extend, True, False)
|
|
765
|
+
else:
|
|
766
|
+
ListIO.dictify([e.label], writer, to_extend, True, False)
|
|
670
767
|
writer.to_dict(e.inV.id, to_extend)
|
|
671
768
|
writer.to_dict(None, to_extend)
|
|
672
769
|
writer.to_dict(e.outV.id, to_extend)
|
|
@@ -686,8 +783,8 @@ class TinkerGraphIO(_GraphBinaryTypeIO):
|
|
|
686
783
|
vertex_count = r.to_object(b, DataType.int, False)
|
|
687
784
|
for _ in range(vertex_count):
|
|
688
785
|
v_id = r.read_object(b)
|
|
689
|
-
|
|
690
|
-
vertex = Vertex(v_id,
|
|
786
|
+
v_labels = r.to_object(b, DataType.list, False)
|
|
787
|
+
vertex = Vertex(v_id, v_labels[0] if v_labels else "vertex", labels=v_labels)
|
|
691
788
|
graph.vertices[v_id] = vertex
|
|
692
789
|
|
|
693
790
|
vp_count = r.to_object(b, DataType.int, False)
|
|
@@ -706,14 +803,15 @@ class TinkerGraphIO(_GraphBinaryTypeIO):
|
|
|
706
803
|
edge_count = r.to_object(b, DataType.int, False)
|
|
707
804
|
for _ in range(edge_count):
|
|
708
805
|
e_id = r.read_object(b)
|
|
709
|
-
|
|
806
|
+
e_labels = r.to_object(b, DataType.list, False)
|
|
710
807
|
in_v_id = r.read_object(b)
|
|
711
808
|
r.read_object(b) # discard in-v label
|
|
712
809
|
out_v_id = r.read_object(b)
|
|
713
810
|
r.read_object(b) # discard out-v label
|
|
714
811
|
r.read_object(b) # discard parent
|
|
715
812
|
|
|
716
|
-
edge = Edge(e_id, graph.vertices[out_v_id],
|
|
813
|
+
edge = Edge(e_id, graph.vertices[out_v_id], e_labels[0] if e_labels else "edge",
|
|
814
|
+
graph.vertices[in_v_id], labels=e_labels)
|
|
717
815
|
graph.edges[e_id] = edge
|
|
718
816
|
|
|
719
817
|
edge_props = r.to_object(b, DataType.list, False)
|
|
@@ -732,8 +830,11 @@ class VertexIO(_GraphBinaryTypeIO):
|
|
|
732
830
|
def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
|
|
733
831
|
cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
|
|
734
832
|
writer.to_dict(obj.id, to_extend)
|
|
735
|
-
# serializing
|
|
736
|
-
|
|
833
|
+
# serializing labels as list according to GraphBinaryV4
|
|
834
|
+
if hasattr(obj, '_labels'):
|
|
835
|
+
ListIO.dictify(list(obj._labels), writer, to_extend, True, False)
|
|
836
|
+
else:
|
|
837
|
+
ListIO.dictify([obj.label], writer, to_extend, True, False)
|
|
737
838
|
to_extend.extend(NULL_BYTES)
|
|
738
839
|
return to_extend
|
|
739
840
|
|
|
@@ -744,12 +845,12 @@ class VertexIO(_GraphBinaryTypeIO):
|
|
|
744
845
|
@classmethod
|
|
745
846
|
def _read_vertex(cls, b, r):
|
|
746
847
|
vertex_id = r.read_object(b)
|
|
747
|
-
# reading
|
|
748
|
-
|
|
848
|
+
# reading label list according to GraphBinaryV4
|
|
849
|
+
vertex_labels = r.to_object(b, DataType.list, False)
|
|
749
850
|
props = r.read_object(b)
|
|
750
851
|
# null properties are returned as empty lists
|
|
751
852
|
properties = [] if props is None else props
|
|
752
|
-
vertex = Vertex(vertex_id,
|
|
853
|
+
vertex = Vertex(vertex_id, properties=properties, labels=vertex_labels)
|
|
753
854
|
return vertex
|
|
754
855
|
|
|
755
856
|
|
|
@@ -824,11 +925,6 @@ class MergeIO(_EnumIO):
|
|
|
824
925
|
python_type = Merge
|
|
825
926
|
|
|
826
927
|
|
|
827
|
-
class GTYPEIO(_EnumIO):
|
|
828
|
-
graphbinary_type = DataType.gtype
|
|
829
|
-
python_type = GType
|
|
830
|
-
|
|
831
|
-
|
|
832
928
|
class ByteIO(_GraphBinaryTypeIO):
|
|
833
929
|
python_type = SingleByte
|
|
834
930
|
graphbinary_type = DataType.byte
|
|
@@ -920,4 +1016,48 @@ class MarkerIO(_GraphBinaryTypeIO):
|
|
|
920
1016
|
def objectify(cls, buff, reader, nullable=True):
|
|
921
1017
|
return cls.is_null(buff, reader,
|
|
922
1018
|
lambda b, r: Marker.of(int8_unpack(b.read(1))),
|
|
923
|
-
nullable)
|
|
1019
|
+
nullable)
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
class CompositePDTIO(_GraphBinaryTypeIO):
|
|
1023
|
+
python_type = CompositePDT
|
|
1024
|
+
graphbinary_type = DataType.composite_pdt
|
|
1025
|
+
|
|
1026
|
+
@classmethod
|
|
1027
|
+
def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
|
|
1028
|
+
cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
|
|
1029
|
+
StringIO.dictify(obj.name, writer, to_extend)
|
|
1030
|
+
MapIO.dictify(obj.fields, writer, to_extend)
|
|
1031
|
+
return to_extend
|
|
1032
|
+
|
|
1033
|
+
@classmethod
|
|
1034
|
+
def objectify(cls, buff, reader, nullable=True):
|
|
1035
|
+
return cls.is_null(buff, reader, cls._read_pdt, nullable)
|
|
1036
|
+
|
|
1037
|
+
@classmethod
|
|
1038
|
+
def _read_pdt(cls, b, r):
|
|
1039
|
+
name = r.read_object(b)
|
|
1040
|
+
fields = r.read_object(b)
|
|
1041
|
+
return CompositePDT(name, fields)
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
class PrimitivePDTIO(_GraphBinaryTypeIO):
|
|
1045
|
+
python_type = PrimitivePDT
|
|
1046
|
+
graphbinary_type = DataType.primitive_pdt
|
|
1047
|
+
|
|
1048
|
+
@classmethod
|
|
1049
|
+
def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
|
|
1050
|
+
cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
|
|
1051
|
+
StringIO.dictify(obj.name, writer, to_extend)
|
|
1052
|
+
StringIO.dictify(obj.value, writer, to_extend)
|
|
1053
|
+
return to_extend
|
|
1054
|
+
|
|
1055
|
+
@classmethod
|
|
1056
|
+
def objectify(cls, buff, reader, nullable=True):
|
|
1057
|
+
return cls.is_null(buff, reader, cls._read_primitive_pdt, nullable)
|
|
1058
|
+
|
|
1059
|
+
@classmethod
|
|
1060
|
+
def _read_primitive_pdt(cls, b, r):
|
|
1061
|
+
name = r.read_object(b)
|
|
1062
|
+
value = r.read_object(b)
|
|
1063
|
+
return PrimitivePDT(name, value)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gremlinpython
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.0.dev1
|
|
4
4
|
Summary: Gremlin-Python for Apache TinkerPop
|
|
5
5
|
Maintainer-email: Apache TinkerPop <dev@tinkerpop.apache.org>
|
|
6
6
|
License: Apache 2
|
|
@@ -9,19 +9,21 @@ Classifier: Intended Audience :: Developers
|
|
|
9
9
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
10
|
Classifier: Natural Language :: English
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Requires-Python: <3.14,>=3.10
|
|
13
17
|
Description-Content-Type: text/x-rst
|
|
14
18
|
License-File: LICENSE
|
|
15
19
|
License-File: NOTICE
|
|
16
20
|
Requires-Dist: nest_asyncio
|
|
17
|
-
Requires-Dist: aiohttp<4.0.0,>=3.
|
|
21
|
+
Requires-Dist: aiohttp<4.0.0,>=3.11.0
|
|
18
22
|
Requires-Dist: aenum<4.0.0,>=1.4.5
|
|
19
23
|
Requires-Dist: isodate<1.0.0,>=0.6.0
|
|
20
24
|
Requires-Dist: boto3
|
|
21
25
|
Requires-Dist: botocore
|
|
22
26
|
Requires-Dist: async-timeout<5.0,>=4.0.3; python_version < "3.11"
|
|
23
|
-
Provides-Extra: kerberos
|
|
24
|
-
Requires-Dist: kerberos<2.0.0,>=1.3.0; sys_platform != "win32" and extra == "kerberos"
|
|
25
27
|
Provides-Extra: ujson
|
|
26
28
|
Requires-Dist: ujson>=2.0.0; extra == "ujson"
|
|
27
29
|
Provides-Extra: test
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
gremlin_python/__init__.py,sha256=GlU7Dg8EuxYt0pBbBD1c7mk2-AUzaoVN05ZBl9UHoR4,879
|
|
2
|
+
gremlin_python/statics.py,sha256=V8YHxJrE7M7JtgOSICMUbsOCu7bHk4n63fdFbbf8M1Q,4110
|
|
3
|
+
gremlin_python/driver/__init__.py,sha256=g6RXUex0JTxx26nFwkID-1pxZN8qw-08ddWjeHrLd0Y,852
|
|
4
|
+
gremlin_python/driver/auth.py,sha256=a7hWbx5yavb34mJpovJvIJQxMnvBmjcLTlc76E6EZDY,3226
|
|
5
|
+
gremlin_python/driver/client.py,sha256=9tVwym-kESbhu-PcLLjMXv0h-3NvwyDSav6FkL9ypQE,8381
|
|
6
|
+
gremlin_python/driver/connection.py,sha256=ADkFYdRbFHtNhc8oQDVFrMrB4ssZ21uXmgr1HogOHhY,8586
|
|
7
|
+
gremlin_python/driver/driver_remote_connection.py,sha256=M_6WMFKd1WJww0hUOMMFn19IlGEWQGKSO-MxOCk2_FU,4814
|
|
8
|
+
gremlin_python/driver/exceptions.py,sha256=z52kqnfepr8wHb9k-I2j3yBczmec6aU4YnTu3vWPlcg,1446
|
|
9
|
+
gremlin_python/driver/http_request.py,sha256=uUG_PzwTbNSNJOdI7EdbY2fbEC6VzpHuXc_S0c7COXc,2332
|
|
10
|
+
gremlin_python/driver/remote_connection.py,sha256=Q8iNH0Mp7y-yl_RdeQbpMZa3Q5Lbf3f8CmrAI_JdSVQ,2879
|
|
11
|
+
gremlin_python/driver/request.py,sha256=UniNng8kxLO8W8cbqfHwpamu6YHwAqzkKLHWE-esEUI,1121
|
|
12
|
+
gremlin_python/driver/resultset.py,sha256=wAMc_zhIw4vDIAmQXlJIKWf3660OG2ODWAupgUAEc7A,2421
|
|
13
|
+
gremlin_python/driver/serializer.py,sha256=LIUErqUR1mhqFGPc5HUez-nWYEokITGhZfKE9TfI5b0,5271
|
|
14
|
+
gremlin_python/driver/transaction.py,sha256=meoaLLZwSuCzt92H6w35v0NSN-uA4qRIsUlzBWL1QYg,6993
|
|
15
|
+
gremlin_python/driver/useragent.py,sha256=LbXVrLUSEhhINxMUW9rU-hk2HQZHB9Uxw4-YqUvQtZw,1597
|
|
16
|
+
gremlin_python/driver/aiohttp/__init__.py,sha256=Mnk4pWa5nTIrU_VYGdGJYftxPjA9MRZjFVYtvbDjH18,789
|
|
17
|
+
gremlin_python/driver/aiohttp/transport.py,sha256=TkYUTwG-_KYxtA3FLpYUsiRChrrZCwVM5FE8dBm9Z2A,16091
|
|
18
|
+
gremlin_python/process/__init__.py,sha256=g6RXUex0JTxx26nFwkID-1pxZN8qw-08ddWjeHrLd0Y,852
|
|
19
|
+
gremlin_python/process/anonymous_traversal.py,sha256=VKJGNXxJ7nE8NShZLE3Cq7u35yB6KLwfatQSxnaNRVQ,2344
|
|
20
|
+
gremlin_python/process/graph_traversal.py,sha256=gLsFNeV-hxgxPolyn9tV8sDng49uiO-l4ZFuvyq7yxQ,76339
|
|
21
|
+
gremlin_python/process/strategies.py,sha256=lw7csIHrOUajzlEN_6YDRcIW27xXZ0kxw7SghHJJd28,10837
|
|
22
|
+
gremlin_python/process/traversal.py,sha256=ufi5MG1UOpNihgIGxUmjzFpfwCa-WkjlLQgMh1pG2Ac,36215
|
|
23
|
+
gremlin_python/structure/__init__.py,sha256=g6RXUex0JTxx26nFwkID-1pxZN8qw-08ddWjeHrLd0Y,852
|
|
24
|
+
gremlin_python/structure/graph.py,sha256=TF_6JrqEKLem7Mw7gzflpaFNYCt4YK7MHu-ICHJWEkY,20233
|
|
25
|
+
gremlin_python/structure/io/__init__.py,sha256=g6RXUex0JTxx26nFwkID-1pxZN8qw-08ddWjeHrLd0Y,852
|
|
26
|
+
gremlin_python/structure/io/graphbinaryV4.py,sha256=0J1Ocm4PAdG_SIUwssYp1DbPPPjFKQyw6FSh8RCOZjQ,36717
|
|
27
|
+
gremlin_python/structure/io/util.py,sha256=ysIZze-kLzR-DH-o-yJHk-bOulD0gjpUOuC2_OyBEdo,2801
|
|
28
|
+
gremlinpython-4.0.0.dev1.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
29
|
+
gremlinpython-4.0.0.dev1.dist-info/licenses/NOTICE,sha256=FMjmoj_l2-AVGy2DCS85d0V5rk2A9R9ODI1qiWMJ0-Q,170
|
|
30
|
+
gremlinpython-4.0.0.dev1.dist-info/METADATA,sha256=WzJ9WcELzcv_ujVVdNPSaq-IK02SW7JoiChkRpYcpGc,6913
|
|
31
|
+
gremlinpython-4.0.0.dev1.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
32
|
+
gremlinpython-4.0.0.dev1.dist-info/top_level.txt,sha256=VVeR1g-oOCZBmKIaVzZ7fF2BYrnqOWpw7C2H71ksTAU,15
|
|
33
|
+
gremlinpython-4.0.0.dev1.dist-info/RECORD,,
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
-
# or more contributor license agreements. See the NOTICE file
|
|
4
|
-
# distributed with this work for additional information
|
|
5
|
-
# regarding copyright ownership. The ASF licenses this file
|
|
6
|
-
# to you under the Apache License, Version 2.0 (the
|
|
7
|
-
# "License"); you may not use this file except in compliance
|
|
8
|
-
# with the License. You may obtain a copy of the License at
|
|
9
|
-
#
|
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
#
|
|
12
|
-
# Unless required by applicable law or agreed to in writing,
|
|
13
|
-
# software distributed under the License is distributed on an
|
|
14
|
-
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
-
# KIND, either express or implied. See the License for the
|
|
16
|
-
# specific language governing permissions and limitations
|
|
17
|
-
# under the License.
|
|
18
|
-
#
|
|
19
|
-
import logging
|
|
20
|
-
import abc
|
|
21
|
-
|
|
22
|
-
log = logging.getLogger("gremlinpython")
|
|
23
|
-
|
|
24
|
-
__author__ = 'David M. Brown (davebshow@gmail.com)'
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class GremlinServerError(Exception):
|
|
28
|
-
def __init__(self, status):
|
|
29
|
-
super(GremlinServerError, self).__init__('{0}: {1}'.format(status['code'], status['message']))
|
|
30
|
-
self.status_code = status['code']
|
|
31
|
-
self.status_message = status['message']
|
|
32
|
-
self.status_exception = status['exception']
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class ConfigurationError(Exception):
|
|
36
|
-
pass
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class AbstractBaseProtocol(metaclass=abc.ABCMeta):
|
|
40
|
-
|
|
41
|
-
@abc.abstractmethod
|
|
42
|
-
def connection_made(self, transport):
|
|
43
|
-
self._transport = transport
|
|
44
|
-
|
|
45
|
-
@abc.abstractmethod
|
|
46
|
-
def data_received(self, message, result_set):
|
|
47
|
-
pass
|
|
48
|
-
|
|
49
|
-
@abc.abstractmethod
|
|
50
|
-
def write(self, request_message):
|
|
51
|
-
pass
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class GremlinServerHTTPProtocol(AbstractBaseProtocol):
|
|
55
|
-
|
|
56
|
-
def __init__(self, request_serializer, response_serializer,
|
|
57
|
-
interceptors=None, auth=None):
|
|
58
|
-
if callable(interceptors):
|
|
59
|
-
interceptors = [interceptors]
|
|
60
|
-
elif not (isinstance(interceptors, tuple)
|
|
61
|
-
or isinstance(interceptors, list)
|
|
62
|
-
or interceptors is None):
|
|
63
|
-
raise TypeError("interceptors must be a callable, tuple, list or None")
|
|
64
|
-
|
|
65
|
-
self._auth = auth
|
|
66
|
-
self._interceptors = interceptors
|
|
67
|
-
self._request_serializer = request_serializer
|
|
68
|
-
self._response_serializer = response_serializer
|
|
69
|
-
self._response_msg = {'status': {'code': 0,
|
|
70
|
-
'message': '',
|
|
71
|
-
'exception': ''},
|
|
72
|
-
'result': {'meta': {},
|
|
73
|
-
'data': []}}
|
|
74
|
-
self._is_first_chunk = True
|
|
75
|
-
|
|
76
|
-
def connection_made(self, transport):
|
|
77
|
-
super(GremlinServerHTTPProtocol, self).connection_made(transport)
|
|
78
|
-
|
|
79
|
-
def write(self, request_message):
|
|
80
|
-
accept = str(self._response_serializer.version, encoding='utf-8')
|
|
81
|
-
message = {
|
|
82
|
-
'headers': {'accept': accept},
|
|
83
|
-
'payload': self._request_serializer.serialize_message(request_message)
|
|
84
|
-
if self._request_serializer is not None else request_message,
|
|
85
|
-
'auth': self._auth
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
# The user may not want the payload to be serialized if they are using an interceptor.
|
|
89
|
-
if self._request_serializer is not None:
|
|
90
|
-
content_type = str(self._request_serializer.version, encoding='utf-8')
|
|
91
|
-
message['headers']['content-type'] = content_type
|
|
92
|
-
|
|
93
|
-
for interceptor in self._interceptors or []:
|
|
94
|
-
message = interceptor(message)
|
|
95
|
-
|
|
96
|
-
self._transport.write(message)
|
|
97
|
-
|
|
98
|
-
'''
|
|
99
|
-
GraphSON does not support streaming deserialization, we are aggregating data and bypassing streamed
|
|
100
|
-
deserialization while GraphSON is enabled for testing. Remove after GraphSON is removed.
|
|
101
|
-
'''
|
|
102
|
-
def data_received_aggregate(self, response, result_set):
|
|
103
|
-
response_msg = {'status': {'code': 0,
|
|
104
|
-
'message': '',
|
|
105
|
-
'exception': ''},
|
|
106
|
-
'result': {'meta': {},
|
|
107
|
-
'data': []}}
|
|
108
|
-
|
|
109
|
-
response_msg = self._decode_chunk(response_msg, response, self._is_first_chunk)
|
|
110
|
-
|
|
111
|
-
self._is_first_chunk = False
|
|
112
|
-
status_code = response_msg['status']['code']
|
|
113
|
-
aggregate_to = response_msg['result']['meta'].get('aggregateTo', 'list')
|
|
114
|
-
data = response_msg['result']['data']
|
|
115
|
-
result_set.aggregate_to = aggregate_to
|
|
116
|
-
self._is_first_chunk = True
|
|
117
|
-
|
|
118
|
-
if status_code == 204 and len(data) == 0:
|
|
119
|
-
result_set.stream.put_nowait([])
|
|
120
|
-
elif status_code in [200, 204, 206]:
|
|
121
|
-
result_set.stream.put_nowait(data)
|
|
122
|
-
else:
|
|
123
|
-
log.error("\r\nReceived error message '%s'\r\n\r\nWith result set '%s'",
|
|
124
|
-
str(self._response_msg), str(result_set))
|
|
125
|
-
raise GremlinServerError({'code': status_code,
|
|
126
|
-
'message': self._response_msg['status']['message'],
|
|
127
|
-
'exception': self._response_msg['status']['exception']})
|
|
128
|
-
|
|
129
|
-
# data is received in chunks
|
|
130
|
-
def data_received(self, response_chunk, result_set, read_completed=None, http_req_resp=None):
|
|
131
|
-
# we shouldn't need to use the http_req_resp code as status is sent in response message, but leaving it for now
|
|
132
|
-
if read_completed:
|
|
133
|
-
status_code = self._response_msg['status']['code']
|
|
134
|
-
aggregate_to = self._response_msg['result']['meta'].get('aggregateTo', 'list')
|
|
135
|
-
data = self._response_msg['result']['data']
|
|
136
|
-
result_set.aggregate_to = aggregate_to
|
|
137
|
-
|
|
138
|
-
# reset response message
|
|
139
|
-
self._response_msg = {'status': {'code': 0,
|
|
140
|
-
'message': '',
|
|
141
|
-
'exception': ''},
|
|
142
|
-
'result': {'meta': {},
|
|
143
|
-
'data': []}}
|
|
144
|
-
self._is_first_chunk = True
|
|
145
|
-
|
|
146
|
-
if status_code == 204 and len(data) == 0:
|
|
147
|
-
result_set.stream.put_nowait([])
|
|
148
|
-
elif status_code in [200, 204, 206]:
|
|
149
|
-
result_set.stream.put_nowait(data)
|
|
150
|
-
else:
|
|
151
|
-
log.error("\r\nReceived error message '%s'\r\n\r\nWith result set '%s'",
|
|
152
|
-
str(self._response_msg), str(result_set))
|
|
153
|
-
raise GremlinServerError({'code': status_code,
|
|
154
|
-
'message': self._response_msg['status']['message'],
|
|
155
|
-
'exception': self._response_msg['status']['exception']})
|
|
156
|
-
else:
|
|
157
|
-
self._response_msg = self._decode_chunk(self._response_msg, response_chunk, self._is_first_chunk)
|
|
158
|
-
self._is_first_chunk = False
|
|
159
|
-
|
|
160
|
-
def _decode_chunk(self, message, data_buffer, is_first_chunk):
|
|
161
|
-
chunk_msg = self._response_serializer.deserialize_message(data_buffer, is_first_chunk)
|
|
162
|
-
|
|
163
|
-
if 'result' in chunk_msg:
|
|
164
|
-
msg_data = message['result']['data']
|
|
165
|
-
chunk_data = chunk_msg['result']['data']
|
|
166
|
-
message['result']['data'] = [*msg_data, *chunk_data]
|
|
167
|
-
if 'status' in chunk_msg:
|
|
168
|
-
status_code = chunk_msg['status']['code']
|
|
169
|
-
if status_code in [200, 204, 206]:
|
|
170
|
-
message.update({'status': chunk_msg['status']})
|
|
171
|
-
else:
|
|
172
|
-
raise GremlinServerError({'code': status_code,
|
|
173
|
-
'message': chunk_msg['status']['message'],
|
|
174
|
-
'exception': chunk_msg['status']['exception']})
|
|
175
|
-
return message
|