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.
@@ -46,6 +46,8 @@ class GraphTraversalSource(object):
46
46
  self.graph_traversal = GraphTraversal
47
47
  if remote_connection:
48
48
  self.traversal_strategies.add_strategies([RemoteStrategy(remote_connection)])
49
+ if hasattr(remote_connection, 'pdt_registry') and remote_connection.pdt_registry is not None:
50
+ self.gremlin_lang.pdt_registry = remote_connection.pdt_registry
49
51
  self.remote_connection = remote_connection
50
52
 
51
53
  def __repr__(self):
@@ -141,26 +143,83 @@ class GraphTraversalSource(object):
141
143
  else:
142
144
  options_strategy[1].configuration[k] = val
143
145
 
146
+ # Render multilabel/singlelabel in gremlin text (temporary until these options are removed)
147
+ if k == 'multilabel' or k == 'singlelabel':
148
+ source.gremlin_lang.gremlin.extend(['.', 'with', '(', f'"{k}"', ')'])
149
+
144
150
  return source
145
151
 
146
- # TODO remove or update once HTTP transaction is implemented
147
- # def tx(self):
148
- # # In order to keep the constructor unchanged within 3.5.x we can try to pop the RemoteConnection out of the
149
- # # TraversalStrategies. keeping this unchanged will allow user DSLs to not take a break.
150
- # # This is the same strategy as gremlin-javascript.
151
- # # TODO https://issues.apache.org/jira/browse/TINKERPOP-2664: refactor this to be nicer in 3.6.0 when
152
- # # we can take a breaking change
153
- # remote_connection = next((x.remote_connection for x in self.traversal_strategies.traversal_strategies if
154
- # x.fqcn == "py:RemoteStrategy"), None)
155
- #
156
- # if remote_connection is None:
157
- # raise Exception("Error, remote connection is required for transaction.")
158
- #
159
- # # You can't do g.tx().begin().tx() i.e child transactions are not supported.
160
- # if remote_connection and remote_connection.is_session_bound():
161
- # raise Exception("This TraversalSource is already bound to a transaction - child transactions are not "
162
- # "supported")
163
- # return Transaction(self, remote_connection)
152
+ def tx(self):
153
+ """Spawns a Transaction or returns the existing one if this GTS is
154
+ already bound to a transaction. Requires a RemoteConnection backed by a Client.
155
+ """
156
+ from gremlin_python.driver.remote_connection import RemoteStrategy
157
+ remote_connection = next((x.remote_connection for x in self.traversal_strategies.traversal_strategies if
158
+ x.fqcn == "py:RemoteStrategy"), None)
159
+
160
+ if remote_connection is None:
161
+ raise Exception("Remote connection is required for transactions")
162
+
163
+ # If this GTS is already bound to a transaction, return that transaction.
164
+ from gremlin_python.driver.transaction import TransactionRemoteConnection
165
+ if isinstance(remote_connection, TransactionRemoteConnection):
166
+ return remote_connection._transaction
167
+
168
+ from gremlin_python.driver.transaction import Transaction
169
+ return Transaction(remote_connection._client)
170
+
171
+ def execute_in_tx(self, tx_work):
172
+ """Runs a unit of work inside a transaction, managing its lifecycle.
173
+
174
+ The transaction is started automatically via tx().begin() and the
175
+ transaction-bound GraphTraversalSource (gtx) is passed to tx_work as its
176
+ sole argument. Only gtx should be used inside the body; the
177
+ non-transactional g is not in scope. On normal completion the
178
+ transaction is committed and the body's return value is returned
179
+ (None if the body returns nothing). If the body raises, the
180
+ transaction is rolled back and the exact original exception is
181
+ re-raised unchanged.
182
+
183
+ This is single-shot: exactly one begin -> run -> commit/rollback
184
+ attempt is made; there is no automatic retry. If the body raises and
185
+ the follow-up rollback also fails, a warning is logged and the original
186
+ body exception still propagates. If commit() fails (e.g. the server
187
+ already rolled the transaction back), a rollback is attempted for
188
+ server-side hygiene and the commit error propagates as the primary
189
+ error.
190
+
191
+ For example, g.execute_in_tx(lambda gtx: gtx.addV('person').iterate())
192
+ runs the body and commits, while
193
+ count = g.execute_in_tx(lambda gtx: gtx.V().count().next()) returns the
194
+ body's value.
195
+ """
196
+ tx = self.tx()
197
+ gtx = tx.begin()
198
+ # Phase 1: run the user's work. If it raises, roll back and re-raise the body error - the
199
+ # bare `raise` exits the method, so a failed body never reaches the commit in phase 2.
200
+ try:
201
+ result = tx_work(gtx)
202
+ except BaseException:
203
+ # Catch BaseException so any abnormal exit (including KeyboardInterrupt) rolls back.
204
+ try:
205
+ tx.rollback()
206
+ except BaseException as rollback_error:
207
+ # The cleanup rollback failure is only logged - the bare `raise` below re-raises
208
+ # the original body error unchanged so it always stays the primary error.
209
+ log.warning("Rollback failed after transaction body error: %s", rollback_error)
210
+ raise
211
+ # Phase 2: the body succeeded, so commit. A separate try because this failure mode is
212
+ # distinct (commit, not body): we still roll back for server-side hygiene, then re-raise
213
+ # the commit error as the primary error.
214
+ try:
215
+ tx.commit()
216
+ except Exception:
217
+ try:
218
+ tx.rollback()
219
+ except BaseException as rollback_error:
220
+ log.warning("Rollback failed after commit failure: %s", rollback_error)
221
+ raise
222
+ return result
164
223
 
165
224
  def withComputer(self, graph_computer=None, workers=None, result=None, persist=None, vertices=None,
166
225
  edges=None, configuration=None):
@@ -234,6 +293,14 @@ class GraphTraversalSource(object):
234
293
  traversal.gremlin_lang.add_step("call", *args)
235
294
  return traversal
236
295
 
296
+ def match(self, match_query, params=None):
297
+ traversal = self.get_graph_traversal()
298
+ if params is not None:
299
+ traversal.gremlin_lang.add_step("match", match_query, params)
300
+ else:
301
+ traversal.gremlin_lang.add_step("match", match_query)
302
+ return traversal
303
+
237
304
  def union(self, *args):
238
305
  traversal = self.get_graph_traversal()
239
306
  traversal.gremlin_lang.add_step("union", *args)
@@ -296,6 +363,17 @@ class GraphTraversal(Traversal):
296
363
  self.gremlin_lang.add_step("addV", *args)
297
364
  return self
298
365
 
366
+ def addLabel(self, *args):
367
+ warnings.warn(
368
+ "gremlin_python.process.GraphTraversal.addLabel will be replaced by "
369
+ "gremlin_python.process.GraphTraversal.add_label.",
370
+ DeprecationWarning)
371
+ return self.add_label(*args)
372
+
373
+ def add_label(self, *args):
374
+ self.gremlin_lang.add_step("addLabel", *args)
375
+ return self
376
+
299
377
  def aggregate(self, *args):
300
378
  self.gremlin_lang.add_step("aggregate", *args)
301
379
  return self
@@ -460,6 +538,28 @@ class GraphTraversal(Traversal):
460
538
  self.gremlin_lang.add_step("drop", *args)
461
539
  return self
462
540
 
541
+ def dropLabel(self, *args):
542
+ warnings.warn(
543
+ "gremlin_python.process.GraphTraversal.dropLabel will be replaced by "
544
+ "gremlin_python.process.GraphTraversal.drop_label.",
545
+ DeprecationWarning)
546
+ return self.drop_label(*args)
547
+
548
+ def drop_label(self, *args):
549
+ self.gremlin_lang.add_step("dropLabel", *args)
550
+ return self
551
+
552
+ def dropLabels(self, *args):
553
+ warnings.warn(
554
+ "gremlin_python.process.GraphTraversal.dropLabels will be replaced by "
555
+ "gremlin_python.process.GraphTraversal.drop_labels.",
556
+ DeprecationWarning)
557
+ return self.drop_labels(*args)
558
+
559
+ def drop_labels(self, *args):
560
+ self.gremlin_lang.add_step("dropLabels", *args)
561
+ return self
562
+
463
563
  def element(self, *args):
464
564
  self.gremlin_lang.add_step("element", *args)
465
565
  return self
@@ -652,6 +752,10 @@ class GraphTraversal(Traversal):
652
752
  self.gremlin_lang.add_step("label", *args)
653
753
  return self
654
754
 
755
+ def labels(self, *args):
756
+ self.gremlin_lang.add_step("labels", *args)
757
+ return self
758
+
655
759
  def length(self, *args):
656
760
  self.gremlin_lang.add_step("length", *args)
657
761
  return self
@@ -681,6 +785,12 @@ class GraphTraversal(Traversal):
681
785
  return self
682
786
 
683
787
  def match(self, *args):
788
+ if len(args) > 0 and not isinstance(args[0], str):
789
+ warnings.warn(
790
+ "Passing Traversal objects to match() is deprecated as of TinkerPop 4.0.0 "
791
+ "and will be removed in a future release. Use match(str) for declarative "
792
+ "pattern matching instead.",
793
+ DeprecationWarning, stacklevel=2)
684
794
  self.gremlin_lang.add_step("match", *args)
685
795
  return self
686
796
 
@@ -1087,6 +1197,18 @@ class __(object, metaclass=MagicType):
1087
1197
  def add_v(cls, *args):
1088
1198
  return cls.graph_traversal(None, None, GremlinLang()).add_v(*args)
1089
1199
 
1200
+ @classmethod
1201
+ def addLabel(cls, *args):
1202
+ warnings.warn(
1203
+ "gremlin_python.process.__.addLabel will be replaced by "
1204
+ "gremlin_python.process.__.add_label.",
1205
+ DeprecationWarning)
1206
+ return cls.add_label(*args)
1207
+
1208
+ @classmethod
1209
+ def add_label(cls, *args):
1210
+ return cls.graph_traversal(None, None, GremlinLang()).add_label(*args)
1211
+
1090
1212
  @classmethod
1091
1213
  def aggregate(cls, *args):
1092
1214
  return cls.graph_traversal(None, None, GremlinLang()).aggregate(*args)
@@ -1239,6 +1361,30 @@ class __(object, metaclass=MagicType):
1239
1361
  def drop(cls, *args):
1240
1362
  return cls.graph_traversal(None, None, GremlinLang()).drop(*args)
1241
1363
 
1364
+ @classmethod
1365
+ def dropLabel(cls, *args):
1366
+ warnings.warn(
1367
+ "gremlin_python.process.__.dropLabel will be replaced by "
1368
+ "gremlin_python.process.__.drop_label.",
1369
+ DeprecationWarning)
1370
+ return cls.drop_label(*args)
1371
+
1372
+ @classmethod
1373
+ def drop_label(cls, *args):
1374
+ return cls.graph_traversal(None, None, GremlinLang()).drop_label(*args)
1375
+
1376
+ @classmethod
1377
+ def dropLabels(cls, *args):
1378
+ warnings.warn(
1379
+ "gremlin_python.process.__.dropLabels will be replaced by "
1380
+ "gremlin_python.process.__.drop_labels.",
1381
+ DeprecationWarning)
1382
+ return cls.drop_labels(*args)
1383
+
1384
+ @classmethod
1385
+ def drop_labels(cls, *args):
1386
+ return cls.graph_traversal(None, None, GremlinLang()).drop_labels(*args)
1387
+
1242
1388
  @classmethod
1243
1389
  def element(cls, *args):
1244
1390
  return cls.graph_traversal(None, None, GremlinLang()).element(*args)
@@ -1435,6 +1581,10 @@ class __(object, metaclass=MagicType):
1435
1581
  def label(cls, *args):
1436
1582
  return cls.graph_traversal(None, None, GremlinLang()).label(*args)
1437
1583
 
1584
+ @classmethod
1585
+ def labels(cls, *args):
1586
+ return cls.graph_traversal(None, None, GremlinLang()).labels(*args)
1587
+
1438
1588
  @classmethod
1439
1589
  def length(cls, *args):
1440
1590
  return cls.graph_traversal(None, None, GremlinLang()).length(*args)
@@ -1776,81 +1926,6 @@ class __(object, metaclass=MagicType):
1776
1926
  return cls.graph_traversal(None, None, GremlinLang()).where(*args)
1777
1927
 
1778
1928
 
1779
- # Class to handle transactions.
1780
- # class Transaction:
1781
- #
1782
- # def __init__(self, g, remote_connection):
1783
- # self._g = g
1784
- # self._session_based_connection = None
1785
- # self._remote_connection = remote_connection
1786
- # self.__is_open = False
1787
- # self.__mutex = Lock()
1788
- #
1789
- # # Begins transaction.
1790
- # def begin(self):
1791
- # with self.__mutex:
1792
- # # Verify transaction is not open.
1793
- # self.__verify_transaction_state(False, "Transaction already started on this object")
1794
- #
1795
- # # Create new session using the remote connection.
1796
- # self._session_based_connection = self._remote_connection.create_session()
1797
- # self.__is_open = True
1798
- #
1799
- # # Set the session as a remote strategy within the traversal strategy.
1800
- # traversal_strategy.py = TraversalStrategies()
1801
- # traversal_strategy.py.add_strategies([RemoteStrategy(self._session_based_connection)])
1802
- #
1803
- # # Return new GraphTraversalSource.
1804
- # return GraphTraversalSource(self._g.graph, traversal_strategy.py, self._g.bytecode)
1805
- #
1806
- # # Rolls transaction back.
1807
- # def rollback(self):
1808
- # with self.__mutex:
1809
- # # Verify transaction is open, close session and return result of transaction's rollback.
1810
- # self.__verify_transaction_state(True, "Cannot rollback a transaction that is not started.")
1811
- # return self.__close_session(self._session_based_connection.rollback())
1812
- #
1813
- # # Commits the current transaction.
1814
- # def commit(self):
1815
- # with self.__mutex:
1816
- # # Verify transaction is open, close session and return result of transaction's commit.
1817
- # self.__verify_transaction_state(True, "Cannot commit a transaction that is not started.")
1818
- # return self.__close_session(self._session_based_connection.commit())
1819
- #
1820
- # # Closes session.
1821
- # def close(self):
1822
- # with self.__mutex:
1823
- # # Verify transaction is open.
1824
- # self.__verify_transaction_state(True, "Cannot close a transaction that has previously been closed.")
1825
- # self.__close_session(None)
1826
- #
1827
- # # Return whether or not transaction is open.
1828
- # # Allow camelcase function here to keep api consistent with other languages.
1829
- # def isOpen(self):
1830
- # warnings.warn(
1831
- # "gremlin_python.process.Transaction.isOpen will be replaced by "
1832
- # "gremlin_python.process.Transaction.is_open.",
1833
- # DeprecationWarning)
1834
- # return self.is_open()
1835
- #
1836
- # def is_open(self):
1837
- # # if the underlying DriverRemoteConnection is closed then the Transaction can't be open
1838
- # if (self._session_based_connection and self._session_based_connection.is_closed()) or \
1839
- # self._remote_connection.is_closed():
1840
- # self.__is_open = False
1841
- #
1842
- # return self.__is_open
1843
- #
1844
- # def __verify_transaction_state(self, state, error_message):
1845
- # if self.__is_open != state:
1846
- # raise Exception(error_message)
1847
- #
1848
- # def __close_session(self, session):
1849
- # self.__is_open = False
1850
- # self._remote_connection.remove_session(self._session_based_connection)
1851
- # return session
1852
-
1853
-
1854
1929
  def E(*args):
1855
1930
  return __.E(*args)
1856
1931
 
@@ -1875,6 +1950,14 @@ def add_v(*args):
1875
1950
  return __.add_v(*args)
1876
1951
 
1877
1952
 
1953
+ def addLabel(*args):
1954
+ return __.add_label(*args)
1955
+
1956
+
1957
+ def add_label(*args):
1958
+ return __.add_label(*args)
1959
+
1960
+
1878
1961
  def aggregate(*args):
1879
1962
  return __.aggregate(*args)
1880
1963
 
@@ -2015,6 +2098,22 @@ def drop(*args):
2015
2098
  return __.drop(*args)
2016
2099
 
2017
2100
 
2101
+ def dropLabel(*args):
2102
+ return __.drop_label(*args)
2103
+
2104
+
2105
+ def drop_label(*args):
2106
+ return __.drop_label(*args)
2107
+
2108
+
2109
+ def dropLabels(*args):
2110
+ return __.drop_labels(*args)
2111
+
2112
+
2113
+ def drop_labels(*args):
2114
+ return __.drop_labels(*args)
2115
+
2116
+
2018
2117
  def element(*args):
2019
2118
  return __.element(*args)
2020
2119
 
@@ -2165,6 +2264,10 @@ def label(*args):
2165
2264
  return __.label(*args)
2166
2265
 
2167
2266
 
2267
+ def labels(*args):
2268
+ return __.labels(*args)
2269
+
2270
+
2168
2271
  def length(*args):
2169
2272
  return __.length(*args)
2170
2273
 
@@ -2468,6 +2571,10 @@ statics.add_static('addV', addV)
2468
2571
 
2469
2572
  statics.add_static('add_v', add_v)
2470
2573
 
2574
+ statics.add_static('addLabel', addLabel)
2575
+
2576
+ statics.add_static('add_label', add_label)
2577
+
2471
2578
  statics.add_static('aggregate', aggregate)
2472
2579
 
2473
2580
  statics.add_static('all_', all_)
@@ -2538,6 +2645,14 @@ statics.add_static('disjunct', disjunct)
2538
2645
 
2539
2646
  statics.add_static('drop', drop)
2540
2647
 
2648
+ statics.add_static('dropLabel', dropLabel)
2649
+
2650
+ statics.add_static('drop_label', drop_label)
2651
+
2652
+ statics.add_static('dropLabels', dropLabels)
2653
+
2654
+ statics.add_static('drop_labels', drop_labels)
2655
+
2541
2656
  statics.add_static('element', element)
2542
2657
 
2543
2658
  statics.add_static('elementMap', elementMap)
@@ -2610,6 +2725,8 @@ statics.add_static('key', key)
2610
2725
 
2611
2726
  statics.add_static('label', label)
2612
2727
 
2728
+ statics.add_static('labels', labels)
2729
+
2613
2730
  statics.add_static('length', length)
2614
2731
 
2615
2732
  statics.add_static('limit', limit)