]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Delay decisions about transaction operations to __enter__
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 19 Nov 2020 18:50:53 +0000 (18:50 +0000)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 19 Nov 2020 18:50:53 +0000 (18:50 +0000)
The transaction status of the connection may change concurrently between
__init__ and __enter__.

psycopg3/psycopg3/transaction.py

index 3ef83ef12f4cd14db44bfa0cbd4c3d0d2607b429..30b482c956f550bde3b35fd470e33f440b248b68 100644 (file)
@@ -46,22 +46,10 @@ class BaseTransaction(Generic[ConnectionType]):
         force_rollback: bool = False,
     ):
         self._conn = connection
+        self._savepoint_name = savepoint_name or ""
         self.force_rollback = force_rollback
         self._yolo = True
 
-        if connection.pgconn.transaction_status == TransactionStatus.IDLE:
-            # outer transaction: if no name it's only a begin, else
-            # there will be an additional savepoint
-            self._outer_transaction = True
-            assert not connection._savepoints
-            self._savepoint_name = savepoint_name or ""
-        else:
-            # inner transaction: it always has a name
-            self._outer_transaction = False
-            self._savepoint_name = (
-                savepoint_name or f"_pg3_{len(self._conn._savepoints) + 1}"
-            )
-
     @property
     def connection(self) -> ConnectionType:
         """The connection the object is managing."""
@@ -70,6 +58,8 @@ class BaseTransaction(Generic[ConnectionType]):
     @property
     def savepoint_name(self) -> Optional[str]:
         """The name of the savepoint; `None` if handling the main transaction."""
+        # Yes, it may change on __enter__. No, I don't care, because the
+        # un-entered state is outside the public interface.
         return self._savepoint_name
 
     def __repr__(self) -> str:
@@ -84,6 +74,20 @@ class BaseTransaction(Generic[ConnectionType]):
         assert self._yolo
         self._yolo = False
 
+        self._outer_transaction = (
+            self._conn.pgconn.transaction_status == TransactionStatus.IDLE
+        )
+        if self._outer_transaction:
+            # outer transaction: if no name it's only a begin, else
+            # there will be an additional savepoint
+            assert not self._conn._savepoints
+        else:
+            # inner transaction: it always has a name
+            if not self._savepoint_name:
+                self._savepoint_name = (
+                    f"_pg3_{len(self._conn._savepoints) + 1}"
+                )
+
         commands = []
         if self._outer_transaction:
             assert not self._conn._savepoints, self._conn._savepoints