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.
@@ -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, GType
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 # not supported - no tree object in Python yet
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
- elif isinstance(b, io.BufferedIOBase):
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 == DataType.null.value:
170
+ if bt == _NULL:
162
171
  if nullable:
163
172
  buff.read(1)
164
173
  return None
165
- return self.deserializers[DataType(bt)].objectify(buff, self, nullable)
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
- return self.deserializers[data_type].objectify(buff, self, nullable)
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 label as list here for now according to GraphBinaryV4
571
- ListIO.dictify([obj.label], writer, to_extend, True, False)
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
- ListIO.dictify([obj.inV.label], writer, to_extend, True, False)
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
- ListIO.dictify([obj.outV.label], writer, to_extend, True, False)
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 single string value for now according to GraphBinaryV4
589
- edgelbl = r.to_object(b, DataType.list, False)[0]
590
- inv = Vertex(r.read_object(b), r.to_object(b, DataType.list, False)[0])
591
- outv = Vertex(r.read_object(b), r.to_object(b, DataType.list, False)[0])
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, edgelbl, inv, properties)
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
- ListIO.dictify([v.label], writer, to_extend, True, False)
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
- ListIO.dictify([e.label], writer, to_extend, True, False)
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
- v_label = r.to_object(b, DataType.list, False)[0]
690
- vertex = Vertex(v_id, v_label)
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
- e_label = r.to_object(b, DataType.list, False)[0]
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], e_label, graph.vertices[in_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 label as list here for now according to GraphBinaryV4
736
- ListIO.dictify([obj.label], writer, to_extend, True, False)
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 single string value for now according to GraphBinaryV4
748
- vertex_label = r.to_object(b, DataType.list, False)[0]
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, vertex_label, properties)
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.0b2
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
- Requires-Python: >=3.10
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.8.0
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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (82.0.1)
2
+ Generator: setuptools (83.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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