diff --git a/spanner/google/cloud/spanner/session.py b/spanner/google/cloud/spanner/session.py index 33a1a8b2838b..d513889053a7 100644 --- a/spanner/google/cloud/spanner/session.py +++ b/spanner/google/cloud/spanner/session.py @@ -249,6 +249,7 @@ def transaction(self): if self._transaction is not None: self._transaction._rolled_back = True + del self._transaction txn = self._transaction = Transaction(self) return txn diff --git a/spanner/google/cloud/spanner/transaction.py b/spanner/google/cloud/spanner/transaction.py index e440210bf122..7ac4251dea7d 100644 --- a/spanner/google/cloud/spanner/transaction.py +++ b/spanner/google/cloud/spanner/transaction.py @@ -24,12 +24,24 @@ class Transaction(_SnapshotBase, _BatchBase): - """Implement read-write transaction semantics for a session.""" + """Implement read-write transaction semantics for a session. + + :type session: :class:`~google.cloud.spanner.session.Session` + :param session: the session used to perform the commit + + :raises ValueError: if session has an existing transaction + """ committed = None """Timestamp at which the transaction was successfully committed.""" _rolled_back = False _multi_use = True + def __init__(self, session): + if session._transaction is not None: + raise ValueError("Session has existing transaction.") + + super(Transaction, self).__init__(session) + def _check_state(self): """Helper for :meth:`commit` et al. diff --git a/spanner/tests/unit/test_transaction.py b/spanner/tests/unit/test_transaction.py index 9bb36d1f5435..98b25186ff1e 100644 --- a/spanner/tests/unit/test_transaction.py +++ b/spanner/tests/unit/test_transaction.py @@ -47,6 +47,12 @@ def _make_one(self, session, *args, **kwargs): session._transaction = transaction return transaction + def test_ctor_session_w_existing_txn(self): + session = _Session() + session._transaction = object() + with self.assertRaises(ValueError): + transaction = self._make_one(session) + def test_ctor_defaults(self): session = _Session() transaction = self._make_one(session)