gremlinpython 3.6.8__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 +20 -0
- gremlin_python/__version__.py +20 -0
- gremlin_python/driver/__init__.py +20 -0
- gremlin_python/driver/aiohttp/__init__.py +18 -0
- gremlin_python/driver/aiohttp/transport.py +242 -0
- gremlin_python/driver/client.py +206 -0
- gremlin_python/driver/connection.py +106 -0
- gremlin_python/driver/driver_remote_connection.py +183 -0
- gremlin_python/driver/protocol.py +259 -0
- gremlin_python/driver/remote_connection.py +84 -0
- gremlin_python/driver/request.py +25 -0
- gremlin_python/driver/resultset.py +100 -0
- gremlin_python/driver/serializer.py +294 -0
- gremlin_python/driver/transport.py +45 -0
- gremlin_python/driver/useragent.py +37 -0
- gremlin_python/process/__init__.py +20 -0
- gremlin_python/process/anonymous_traversal.py +64 -0
- gremlin_python/process/graph_traversal.py +2301 -0
- gremlin_python/process/strategies.py +239 -0
- gremlin_python/process/translator.py +297 -0
- gremlin_python/process/traversal.py +875 -0
- gremlin_python/statics.py +117 -0
- gremlin_python/structure/__init__.py +20 -0
- gremlin_python/structure/graph.py +134 -0
- gremlin_python/structure/io/__init__.py +20 -0
- gremlin_python/structure/io/graphbinaryV1.py +1153 -0
- gremlin_python/structure/io/graphsonV2d0.py +646 -0
- gremlin_python/structure/io/graphsonV3d0.py +766 -0
- gremlin_python/structure/io/util.py +60 -0
- gremlinpython-3.6.8.data/data/LICENSE +202 -0
- gremlinpython-3.6.8.data/data/NOTICE +5 -0
- gremlinpython-3.6.8.dist-info/LICENSE +202 -0
- gremlinpython-3.6.8.dist-info/METADATA +147 -0
- gremlinpython-3.6.8.dist-info/NOTICE +5 -0
- gremlinpython-3.6.8.dist-info/RECORD +37 -0
- gremlinpython-3.6.8.dist-info/WHEEL +5 -0
- gremlinpython-3.6.8.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,239 @@
|
|
|
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
|
+
|
|
20
|
+
__author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
|
|
21
|
+
|
|
22
|
+
from gremlin_python.process.traversal import TraversalStrategy
|
|
23
|
+
|
|
24
|
+
base_namespace = 'org.apache.tinkerpop.gremlin.process.traversal.strategy.'
|
|
25
|
+
decoration_namespace = base_namespace + 'decoration.'
|
|
26
|
+
finalization_namespace = base_namespace + 'finalization.'
|
|
27
|
+
optimization_namespace = base_namespace + 'optimization.'
|
|
28
|
+
verification_namespace = base_namespace + 'verification.'
|
|
29
|
+
computer_decoration_namespace = 'org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.'
|
|
30
|
+
|
|
31
|
+
#########################
|
|
32
|
+
# DECORATION STRATEGIES #
|
|
33
|
+
#########################
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ConnectiveStrategy(TraversalStrategy):
|
|
37
|
+
def __init__(self):
|
|
38
|
+
TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'ConnectiveStrategy')
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ElementIdStrategy(TraversalStrategy):
|
|
42
|
+
def __init__(self):
|
|
43
|
+
TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'ElementIdStrategy')
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# EventStrategy doesn't make sense outside JVM traversal machine
|
|
47
|
+
|
|
48
|
+
class HaltedTraverserStrategy(TraversalStrategy):
|
|
49
|
+
def __init__(self, halted_traverser_factory=None):
|
|
50
|
+
TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'HaltedTraverserStrategy')
|
|
51
|
+
if halted_traverser_factory is not None:
|
|
52
|
+
self.configuration["haltedTraverserFactory"] = halted_traverser_factory
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class OptionsStrategy(TraversalStrategy):
|
|
56
|
+
def __init__(self, options=None):
|
|
57
|
+
TraversalStrategy.__init__(self, configuration=options, fqcn=decoration_namespace + 'OptionsStrategy')
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class PartitionStrategy(TraversalStrategy):
|
|
61
|
+
def __init__(self, partition_key=None, write_partition=None, read_partitions=None, include_meta_properties=None):
|
|
62
|
+
TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'PartitionStrategy')
|
|
63
|
+
if partition_key is not None:
|
|
64
|
+
self.configuration["partitionKey"] = partition_key
|
|
65
|
+
if write_partition is not None:
|
|
66
|
+
self.configuration["writePartition"] = write_partition
|
|
67
|
+
if read_partitions is not None:
|
|
68
|
+
self.configuration["readPartitions"] = read_partitions
|
|
69
|
+
if include_meta_properties is not None:
|
|
70
|
+
self.configuration["includeMetaProperties"] = include_meta_properties
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class SeedStrategy(TraversalStrategy):
|
|
74
|
+
def __init__(self, seed):
|
|
75
|
+
TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy")
|
|
76
|
+
self.configuration["seed"] = seed
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class SubgraphStrategy(TraversalStrategy):
|
|
80
|
+
|
|
81
|
+
def __init__(self, vertices=None, edges=None, vertex_properties=None, check_adjacent_vertices=None):
|
|
82
|
+
TraversalStrategy.__init__(self, fqcn=decoration_namespace + 'SubgraphStrategy')
|
|
83
|
+
if vertices is not None:
|
|
84
|
+
self.configuration["vertices"] = vertices
|
|
85
|
+
if edges is not None:
|
|
86
|
+
self.configuration["edges"] = edges
|
|
87
|
+
if vertex_properties is not None:
|
|
88
|
+
self.configuration["vertexProperties"] = vertex_properties
|
|
89
|
+
if check_adjacent_vertices is not None:
|
|
90
|
+
self.configuration["checkAdjacentProperties"] = check_adjacent_vertices
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class VertexProgramStrategy(TraversalStrategy):
|
|
94
|
+
def __init__(self, graph_computer=None, workers=None, persist=None, result=None, vertices=None, edges=None,
|
|
95
|
+
configuration=None):
|
|
96
|
+
TraversalStrategy.__init__(self, fqcn=computer_decoration_namespace + 'VertexProgramStrategy')
|
|
97
|
+
if graph_computer is not None:
|
|
98
|
+
self.configuration["graphComputer"] = graph_computer
|
|
99
|
+
if workers is not None:
|
|
100
|
+
self.configuration["workers"] = workers
|
|
101
|
+
if persist is not None:
|
|
102
|
+
self.configuration["persist"] = persist
|
|
103
|
+
if result is not None:
|
|
104
|
+
self.configuration["result"] = result
|
|
105
|
+
if vertices is not None:
|
|
106
|
+
self.configuration["vertices"] = vertices
|
|
107
|
+
if edges is not None:
|
|
108
|
+
self.configuration["edges"] = edges
|
|
109
|
+
if configuration is not None:
|
|
110
|
+
self.configuration.update(configuration)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
###########################
|
|
114
|
+
# FINALIZATION STRATEGIES #
|
|
115
|
+
###########################
|
|
116
|
+
|
|
117
|
+
class MatchAlgorithmStrategy(TraversalStrategy):
|
|
118
|
+
def __init__(self, match_algorithm=None):
|
|
119
|
+
TraversalStrategy.__init__(self, fqcn=finalization_namespace + 'MatchAlgorithmStrategy')
|
|
120
|
+
if match_algorithm is not None:
|
|
121
|
+
self.configuration["matchAlgorithm"] = match_algorithm
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
###########################
|
|
125
|
+
# OPTIMIZATION STRATEGIES #
|
|
126
|
+
###########################
|
|
127
|
+
|
|
128
|
+
class AdjacentToIncidentStrategy(TraversalStrategy):
|
|
129
|
+
def __init__(self):
|
|
130
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'AdjacentToIncidentStrategy')
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class ByModulatorOptimizationStrategy(TraversalStrategy):
|
|
134
|
+
def __init__(self):
|
|
135
|
+
TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ByModulatorOptimizationStrategy")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class CountStrategy(TraversalStrategy):
|
|
139
|
+
def __init__(self):
|
|
140
|
+
TraversalStrategy.__init__(self, fqcn="org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class FilterRankingStrategy(TraversalStrategy):
|
|
144
|
+
def __init__(self):
|
|
145
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'FilterRankingStrategy')
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class IdentityRemovalStrategy(TraversalStrategy):
|
|
149
|
+
def __init__(self):
|
|
150
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'IdentityRemovalStrategy')
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class IncidentToAdjacentStrategy(TraversalStrategy):
|
|
154
|
+
def __init__(self):
|
|
155
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'IncidentToAdjacentStrategy')
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class InlineFilterStrategy(TraversalStrategy):
|
|
159
|
+
def __init__(self):
|
|
160
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'InlineFilterStrategy')
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class LazyBarrierStrategy(TraversalStrategy):
|
|
164
|
+
def __init__(self):
|
|
165
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'LazyBarrierStrategy')
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class MatchPredicateStrategy(TraversalStrategy):
|
|
169
|
+
def __init__(self):
|
|
170
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'MatchPredicateStrategy')
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class OrderLimitStrategy(TraversalStrategy):
|
|
174
|
+
def __init__(self):
|
|
175
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'OrderLimitStrategy')
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class PathProcessorStrategy(TraversalStrategy):
|
|
179
|
+
def __init__(self):
|
|
180
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'PathProcessorStrategy')
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class PathRetractionStrategy(TraversalStrategy):
|
|
184
|
+
def __init__(self):
|
|
185
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'PathRetractionStrategy')
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class ProductiveByStrategy(TraversalStrategy):
|
|
189
|
+
def __init__(self, productiveKeys=None):
|
|
190
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'ProductiveByStrategy')
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class CountStrategy(TraversalStrategy):
|
|
194
|
+
def __init__(self):
|
|
195
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'CountStrategy')
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class RepeatUnrollStrategy(TraversalStrategy):
|
|
199
|
+
def __init__(self):
|
|
200
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'RepeatUnrollStrategy')
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class GraphFilterStrategy(TraversalStrategy):
|
|
204
|
+
def __init__(self):
|
|
205
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'GraphFilterStrategy')
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class EarlyLimitStrategy(TraversalStrategy):
|
|
210
|
+
def __init__(self):
|
|
211
|
+
TraversalStrategy.__init__(self, fqcn=optimization_namespace + 'EarlyLimitStrategy')
|
|
212
|
+
|
|
213
|
+
###########################
|
|
214
|
+
# VERIFICATION STRATEGIES #
|
|
215
|
+
###########################
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class LambdaRestrictionStrategy(TraversalStrategy):
|
|
219
|
+
def __init__(self):
|
|
220
|
+
TraversalStrategy.__init__(self, fqcn=verification_namespace + 'LambdaRestrictionStrategy')
|
|
221
|
+
|
|
222
|
+
class ReadOnlyStrategy(TraversalStrategy):
|
|
223
|
+
def __init__(self):
|
|
224
|
+
TraversalStrategy.__init__(self, fqcn=verification_namespace + 'ReadOnlyStrategy')
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class EdgeLabelVerificationStrategy(TraversalStrategy):
|
|
228
|
+
def __init__(self, log_warning=False, throw_exception=False):
|
|
229
|
+
TraversalStrategy.__init__(self, fqcn=verification_namespace + 'EdgeLabelVerificationStrategy')
|
|
230
|
+
self.configuration["logWarning"] = log_warning
|
|
231
|
+
self.configuration["throwException"] = throw_exception
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class ReservedKeysVerificationStrategy(TraversalStrategy):
|
|
235
|
+
def __init__(self, log_warning=False, throw_exception=False, keys=["id", "label"]):
|
|
236
|
+
TraversalStrategy.__init__(self, fqcn=verification_namespace + 'ReservedKeysVerificationStrategy')
|
|
237
|
+
self.configuration["logWarning"] = log_warning
|
|
238
|
+
self.configuration["throwException"] = throw_exception
|
|
239
|
+
self.configuration["keys"] = keys
|
|
@@ -0,0 +1,297 @@
|
|
|
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
|
+
|
|
20
|
+
"""
|
|
21
|
+
Class that can turn traversals back into Gremlin Groovy format text queries.
|
|
22
|
+
Those queries can then be run in the Gremlin console or using the GLV submit(<String>) API or
|
|
23
|
+
sent to any TinkerPop compliant HTTP endpoint.
|
|
24
|
+
"""
|
|
25
|
+
__author__ = 'Kelvin R. Lawrence (gfxman)'
|
|
26
|
+
|
|
27
|
+
import math
|
|
28
|
+
import numbers
|
|
29
|
+
import re
|
|
30
|
+
|
|
31
|
+
from gremlin_python.process.traversal import *
|
|
32
|
+
from gremlin_python.process.strategies import *
|
|
33
|
+
from gremlin_python.structure.graph import Vertex, Edge, VertexProperty
|
|
34
|
+
from datetime import datetime
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Translator:
|
|
38
|
+
"""
|
|
39
|
+
Turn a bytecode object back into a textual query (Gremlin Groovy script).
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
# Dictionary used to reverse-map token IDs to strings
|
|
43
|
+
options = {
|
|
44
|
+
WithOptions.tokens: 'tokens',
|
|
45
|
+
WithOptions.none: 'none',
|
|
46
|
+
WithOptions.ids: 'ids',
|
|
47
|
+
WithOptions.labels: 'labels',
|
|
48
|
+
WithOptions.keys: 'keys',
|
|
49
|
+
WithOptions.values: 'values',
|
|
50
|
+
WithOptions.all: 'all',
|
|
51
|
+
WithOptions.indexer: 'indexer',
|
|
52
|
+
WithOptions.list: 'list',
|
|
53
|
+
WithOptions.map: 'map'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
conn_p = ['and', 'or']
|
|
57
|
+
|
|
58
|
+
def __init__(self, traversal_source=None):
|
|
59
|
+
self.traversal_source = traversal_source
|
|
60
|
+
|
|
61
|
+
def get_traversal_source(self):
|
|
62
|
+
return self.traversal_source
|
|
63
|
+
|
|
64
|
+
def get_target_language(self):
|
|
65
|
+
return "gremlin-groovy"
|
|
66
|
+
|
|
67
|
+
def of(self, traversal_source):
|
|
68
|
+
self.traversal_source = traversal_source
|
|
69
|
+
return self
|
|
70
|
+
|
|
71
|
+
# Do any needed special processing for the representation
|
|
72
|
+
# of strings and dates and boolean.
|
|
73
|
+
def fixup(self, v):
|
|
74
|
+
if isinstance(v, str):
|
|
75
|
+
return f'{v!r}' # use repr() format for canonical string rep
|
|
76
|
+
elif type(v) == datetime:
|
|
77
|
+
return self.process_date(v)
|
|
78
|
+
elif type(v) == bool:
|
|
79
|
+
return 'true' if v else 'false'
|
|
80
|
+
elif isinstance(v, numbers.Number):
|
|
81
|
+
return self.process_number(v)
|
|
82
|
+
elif isinstance(v, set):
|
|
83
|
+
return f'[{str(v)[1:-1]}]'
|
|
84
|
+
elif isinstance(v, P):
|
|
85
|
+
return self.process_predicate(v)
|
|
86
|
+
elif type(v) == Vertex:
|
|
87
|
+
return self.process_vertex(v)
|
|
88
|
+
elif type(v) == Edge:
|
|
89
|
+
return self.process_edge(v)
|
|
90
|
+
elif type(v) in [Merge]: # on_create on_match out_v in_v
|
|
91
|
+
tmp = str(v)
|
|
92
|
+
return f'{tmp.split("_")[0]}{tmp.split("_")[1].capitalize()}' if tmp.find('_') else tmp
|
|
93
|
+
elif v is None:
|
|
94
|
+
return 'null'
|
|
95
|
+
else:
|
|
96
|
+
return str(v)
|
|
97
|
+
|
|
98
|
+
# Turn a Python datetime into the equivalent new Date(...)
|
|
99
|
+
def process_date(self, date):
|
|
100
|
+
y = date.year - 1900
|
|
101
|
+
mo = date.month
|
|
102
|
+
d = date.day
|
|
103
|
+
h = date.hour
|
|
104
|
+
mi = date.minute
|
|
105
|
+
s = date.second
|
|
106
|
+
return f'new Date({y},{mo},{d},{h},{mi},{s})'
|
|
107
|
+
|
|
108
|
+
# Do special processing needed to format predicates that come in
|
|
109
|
+
# such as "gt(a)" correctly.
|
|
110
|
+
def process_predicate(self, p):
|
|
111
|
+
res = ''
|
|
112
|
+
if p.operator in self.conn_p:
|
|
113
|
+
res += f'{self.process_predicate(p.value)}.{p.operator}({self.process_predicate(p.other)})'
|
|
114
|
+
else:
|
|
115
|
+
res += f'{self.process_p_value(p)}'
|
|
116
|
+
return res
|
|
117
|
+
|
|
118
|
+
# process the value of the predicates
|
|
119
|
+
def process_p_value(self, p):
|
|
120
|
+
res = str(p).split('(')[0] + '('
|
|
121
|
+
if type(p.value) == list:
|
|
122
|
+
res += '['
|
|
123
|
+
for v in p.value:
|
|
124
|
+
res += self.fixup(v) + ','
|
|
125
|
+
res = (res[0:-1] + ']') if len(p.value) > 0 else (res + ']')
|
|
126
|
+
else:
|
|
127
|
+
res += self.fixup(p.value)
|
|
128
|
+
if p.other is not None:
|
|
129
|
+
res += f',{self.fixup(p.other)}'
|
|
130
|
+
res += ')'
|
|
131
|
+
return res
|
|
132
|
+
|
|
133
|
+
# Special processing to handle strategies
|
|
134
|
+
def process_strategy(self, s):
|
|
135
|
+
c = 0
|
|
136
|
+
res = ''
|
|
137
|
+
# if parameter is empty, only pass class name (referenced GroovyTranslator.java)
|
|
138
|
+
if not s.configuration:
|
|
139
|
+
res += s.strategy_name
|
|
140
|
+
else:
|
|
141
|
+
res = f'new {str(s)}('
|
|
142
|
+
for key in s.configuration:
|
|
143
|
+
res += ',' if c > 0 else ''
|
|
144
|
+
res += key + ':'
|
|
145
|
+
val = s.configuration[key]
|
|
146
|
+
if isinstance(val, Traversal):
|
|
147
|
+
res += self.translate(val.bytecode, child=True)
|
|
148
|
+
else:
|
|
149
|
+
res += self.fixup(val)
|
|
150
|
+
c += 1
|
|
151
|
+
res += ')'
|
|
152
|
+
return res
|
|
153
|
+
pass
|
|
154
|
+
|
|
155
|
+
# Special processing to handle vertices
|
|
156
|
+
def process_vertex(self, vertex):
|
|
157
|
+
return f'new ReferenceVertex({self.fixup(vertex.id)},\'{vertex.label}\')'
|
|
158
|
+
|
|
159
|
+
# Special processing to handle edges
|
|
160
|
+
def process_edge(self, edge):
|
|
161
|
+
return f'new ReferenceEdge({str(edge.id)},\'{edge.label}\',' \
|
|
162
|
+
f'new ReferenceVertex({str(edge.inV.id)},\'{edge.inV.label}\'),' \
|
|
163
|
+
f'new ReferenceVertex({str(edge.outV.id)},\'{edge.outV.label}\'))'
|
|
164
|
+
|
|
165
|
+
# Special processing to handle vertex property
|
|
166
|
+
def process_vertex_property(self, vp):
|
|
167
|
+
return f'new ReferenceVertexProperty({str(vp.id)},\'{vp.label}\',{self.fixup(vp.value)})'
|
|
168
|
+
|
|
169
|
+
# Special processing to handle lambda
|
|
170
|
+
def process_lambda(self, lam):
|
|
171
|
+
lambda_result = lam()
|
|
172
|
+
script = lambda_result if isinstance(lambda_result, str) else lambda_result[0]
|
|
173
|
+
return f'{script}' if re.match(r"^\{.*\}$", script, flags=re.DOTALL) else f'{{{script}}}'
|
|
174
|
+
|
|
175
|
+
def process_dict(self, d):
|
|
176
|
+
c = 0
|
|
177
|
+
res = '['
|
|
178
|
+
if len(d) == 0:
|
|
179
|
+
res += ':'
|
|
180
|
+
else:
|
|
181
|
+
for k, v in d.items():
|
|
182
|
+
wrap = not isinstance(k, str)
|
|
183
|
+
res += ',' if c > 0 else ''
|
|
184
|
+
res += '(' if wrap else ''
|
|
185
|
+
res += self.fixup(k)
|
|
186
|
+
res += ')' if wrap else ''
|
|
187
|
+
res += f':{self.fixup(v)}'
|
|
188
|
+
c += 1
|
|
189
|
+
res += ']'
|
|
190
|
+
return res
|
|
191
|
+
|
|
192
|
+
def process_number(self, n):
|
|
193
|
+
if isinstance(n, float):
|
|
194
|
+
# converting floats into doubles for script since python doesn't distinguish and java defaults to double
|
|
195
|
+
if math.isnan(n):
|
|
196
|
+
return "Double.NaN"
|
|
197
|
+
elif math.isinf(n) and n > 0:
|
|
198
|
+
return "Double.POSITIVE_INFINITY"
|
|
199
|
+
elif math.isinf(n) and n < 0:
|
|
200
|
+
return "Double.NEGATIVE_INFINITY"
|
|
201
|
+
else:
|
|
202
|
+
return f'{n}d'
|
|
203
|
+
return f'{n}'
|
|
204
|
+
|
|
205
|
+
def process_list(self, l):
|
|
206
|
+
c = 0
|
|
207
|
+
res = '['
|
|
208
|
+
for i in l:
|
|
209
|
+
res += ',' if c > 0 else ''
|
|
210
|
+
res += self.fixup(i)
|
|
211
|
+
c += 1
|
|
212
|
+
res += ']'
|
|
213
|
+
return res
|
|
214
|
+
|
|
215
|
+
# Special processing to handle bindings inside of traversals
|
|
216
|
+
def process_binding(self, binding):
|
|
217
|
+
return f'Bindings.instance().of(\'{binding.key}\', {str(binding.value)})'
|
|
218
|
+
|
|
219
|
+
# Main driver of the translation. Different parts of
|
|
220
|
+
# a Traversal are handled appropriately.
|
|
221
|
+
def do_translation(self, step):
|
|
222
|
+
script = ''
|
|
223
|
+
params = step[1:]
|
|
224
|
+
script += '.' + step[0] + '('
|
|
225
|
+
if len(params) > 0:
|
|
226
|
+
c = 0
|
|
227
|
+
with_opts = False
|
|
228
|
+
is_merge_op = (step[0] == 'mergeV') or (step[0] == 'mergeE')
|
|
229
|
+
for p in params:
|
|
230
|
+
script += ',' if c > 0 else ''
|
|
231
|
+
if with_opts:
|
|
232
|
+
script += f'WithOptions.{self.options[p]}'
|
|
233
|
+
elif type(p) == Bytecode:
|
|
234
|
+
script += self.translate(p, True)
|
|
235
|
+
elif isinstance(p, P):
|
|
236
|
+
script += self.process_predicate(p)
|
|
237
|
+
elif type(p) == Vertex:
|
|
238
|
+
script += self.process_vertex(p)
|
|
239
|
+
elif type(p) == Edge:
|
|
240
|
+
script += self.process_edge(p)
|
|
241
|
+
elif type(p) == VertexProperty:
|
|
242
|
+
script += self.process_vertex_property(p)
|
|
243
|
+
elif type(p) in [Cardinality, Pop, Operator, Scope, T]:
|
|
244
|
+
tmp = str(p)
|
|
245
|
+
script += tmp[0:-1] if tmp.endswith('_') else tmp
|
|
246
|
+
elif type(p) in [Merge]: # on_create on_match out_v in_v
|
|
247
|
+
is_merge_op = True
|
|
248
|
+
tmp = str(p)
|
|
249
|
+
script += f'{tmp.split("_")[0]}{tmp.split("_")[1].capitalize()}' if tmp.find('_') else tmp
|
|
250
|
+
elif isinstance(p, TraversalStrategy): # this will capture all strategies
|
|
251
|
+
script += self.process_strategy(p)
|
|
252
|
+
elif type(p) == datetime:
|
|
253
|
+
script += self.process_date(p)
|
|
254
|
+
elif p == WithOptions.tokens:
|
|
255
|
+
script += 'WithOptions.tokens'
|
|
256
|
+
with_opts = True
|
|
257
|
+
elif isinstance(p, str):
|
|
258
|
+
script += f'{p!r}' # use repr() format for canonical string rep
|
|
259
|
+
elif type(p) == bool:
|
|
260
|
+
script += 'true' if p else 'false'
|
|
261
|
+
elif isinstance(p, type(lambda: None)) and p.__name__ == (lambda: None).__name__:
|
|
262
|
+
script += self.process_lambda(p)
|
|
263
|
+
elif type(p) == Binding:
|
|
264
|
+
script += self.process_binding(p)
|
|
265
|
+
elif p is None:
|
|
266
|
+
script += '(Traversal) null' if is_merge_op else 'null'
|
|
267
|
+
elif isinstance(p, type):
|
|
268
|
+
script += p.__name__
|
|
269
|
+
elif isinstance(p, dict):
|
|
270
|
+
script += self.process_dict(p)
|
|
271
|
+
elif isinstance(p, numbers.Number):
|
|
272
|
+
script += self.process_number(p)
|
|
273
|
+
elif isinstance(p, set):
|
|
274
|
+
script += f'[{str(p)[1:-1]}] as Set' if len(p) > 0 else '[] as Set'
|
|
275
|
+
elif isinstance(p, list):
|
|
276
|
+
script += self.process_list(p)
|
|
277
|
+
else:
|
|
278
|
+
script += str(p)
|
|
279
|
+
c += 1
|
|
280
|
+
script += ')'
|
|
281
|
+
return script
|
|
282
|
+
|
|
283
|
+
# Translation starts here. There are two main parts to a
|
|
284
|
+
# traversal. Source instructions such as "withSideEffect"
|
|
285
|
+
# and "withStrategies", and step instructions such as
|
|
286
|
+
# "addV" and "repeat". If child is True we will generate
|
|
287
|
+
# anonymous traversal style syntax.
|
|
288
|
+
def translate(self, bytecode, child=False):
|
|
289
|
+
script = '__' if child else self.traversal_source
|
|
290
|
+
|
|
291
|
+
for step in bytecode.source_instructions:
|
|
292
|
+
script += self.do_translation(step)
|
|
293
|
+
|
|
294
|
+
for step in bytecode.step_instructions:
|
|
295
|
+
script += self.do_translation(step)
|
|
296
|
+
|
|
297
|
+
return script
|