Skip to content

Commit cf523be

Browse files
bcaudell951st1
authored andcommitted
Add Connection.is_in_transaction() (#297)
1 parent e9802aa commit cf523be

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

asyncpg/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
__all__ = ('connect', 'create_pool', 'Record', 'Connection') + \
1616
exceptions.__all__ # NOQA
1717

18-
__version__ = '0.16.0.dev0'
18+
__version__ = '0.16.0.dev1'

asyncpg/connection.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,14 @@ def transaction(self, *, isolation='read_committed', readonly=False,
204204
self._check_open()
205205
return transaction.Transaction(self, isolation, readonly, deferrable)
206206

207+
def is_in_transaction(self):
208+
"""Return True if Connection is currently inside a transaction.
209+
210+
:return bool: True if inside transaction, False otherwise.
211+
.. versionadded:: 0.16.0
212+
"""
213+
return self._protocol.is_in_transaction()
214+
207215
async def execute(self, query: str, *args, timeout: float=None) -> str:
208216
"""Execute an SQL command (or commands).
209217

tests/test_transaction.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ class TestTransaction(tb.ConnectedTestCase):
1414

1515
async def test_transaction_regular(self):
1616
self.assertIsNone(self.con._top_xact)
17+
self.assertFalse(self.con.is_in_transaction())
1718
tr = self.con.transaction()
1819
self.assertIsNone(self.con._top_xact)
20+
self.assertFalse(self.con.is_in_transaction())
1921

2022
with self.assertRaises(ZeroDivisionError):
2123
async with tr as with_tr:
2224
self.assertIs(self.con._top_xact, tr)
25+
self.assertTrue(self.con.is_in_transaction())
2326

2427
# We don't return the transaction object from __aenter__,
2528
# to make it harder for people to use '.rollback()' and
@@ -33,6 +36,7 @@ async def test_transaction_regular(self):
3336
1 / 0
3437

3538
self.assertIsNone(self.con._top_xact)
39+
self.assertFalse(self.con.is_in_transaction())
3640

3741
with self.assertRaisesRegex(asyncpg.PostgresError,
3842
'"mytab" does not exist'):
@@ -42,31 +46,39 @@ async def test_transaction_regular(self):
4246

4347
async def test_transaction_nested(self):
4448
self.assertIsNone(self.con._top_xact)
49+
self.assertFalse(self.con.is_in_transaction())
50+
4551
tr = self.con.transaction()
52+
4653
self.assertIsNone(self.con._top_xact)
54+
self.assertFalse(self.con.is_in_transaction())
4755

4856
with self.assertRaises(ZeroDivisionError):
4957
async with tr:
5058
self.assertIs(self.con._top_xact, tr)
59+
self.assertTrue(self.con.is_in_transaction())
5160

5261
await self.con.execute('''
5362
CREATE TABLE mytab (a int);
5463
''')
5564

5665
async with self.con.transaction():
5766
self.assertIs(self.con._top_xact, tr)
67+
self.assertTrue(self.con.is_in_transaction())
5868

5969
await self.con.execute('''
6070
INSERT INTO mytab (a) VALUES (1), (2);
6171
''')
6272

6373
self.assertIs(self.con._top_xact, tr)
74+
self.assertTrue(self.con.is_in_transaction())
6475

6576
with self.assertRaises(ZeroDivisionError):
6677
in_tr = self.con.transaction()
6778
async with in_tr:
6879

6980
self.assertIs(self.con._top_xact, tr)
81+
self.assertTrue(self.con.is_in_transaction())
7082

7183
await self.con.execute('''
7284
INSERT INTO mytab (a) VALUES (3), (4);
@@ -85,10 +97,12 @@ async def test_transaction_nested(self):
8597
self.assertEqual(recs[1][0], 2)
8698

8799
self.assertIs(self.con._top_xact, tr)
100+
self.assertTrue(self.con.is_in_transaction())
88101

89102
1 / 0
90103

91104
self.assertIs(self.con._top_xact, None)
105+
self.assertFalse(self.con.is_in_transaction())
92106

93107
with self.assertRaisesRegex(asyncpg.PostgresError,
94108
'"mytab" does not exist'):
@@ -98,6 +112,7 @@ async def test_transaction_nested(self):
98112

99113
async def test_transaction_interface_errors(self):
100114
self.assertIsNone(self.con._top_xact)
115+
self.assertFalse(self.con.is_in_transaction())
101116

102117
tr = self.con.transaction(readonly=True, isolation='serializable')
103118
with self.assertRaisesRegex(asyncpg.InterfaceError,
@@ -109,13 +124,15 @@ async def test_transaction_interface_errors(self):
109124
'<asyncpg.Transaction state:rolledback serializable readonly'))
110125

111126
self.assertIsNone(self.con._top_xact)
127+
self.assertFalse(self.con.is_in_transaction())
112128

113129
with self.assertRaisesRegex(asyncpg.InterfaceError,
114130
'cannot start; .* already rolled back'):
115131
async with tr:
116132
pass
117133

118134
self.assertIsNone(self.con._top_xact)
135+
self.assertFalse(self.con.is_in_transaction())
119136

120137
tr = self.con.transaction()
121138
with self.assertRaisesRegex(asyncpg.InterfaceError,
@@ -124,6 +141,7 @@ async def test_transaction_interface_errors(self):
124141
await tr.commit()
125142

126143
self.assertIsNone(self.con._top_xact)
144+
self.assertFalse(self.con.is_in_transaction())
127145

128146
tr = self.con.transaction()
129147
with self.assertRaisesRegex(asyncpg.InterfaceError,
@@ -132,6 +150,7 @@ async def test_transaction_interface_errors(self):
132150
await tr.rollback()
133151

134152
self.assertIsNone(self.con._top_xact)
153+
self.assertFalse(self.con.is_in_transaction())
135154

136155
tr = self.con.transaction()
137156
with self.assertRaisesRegex(asyncpg.InterfaceError,
@@ -142,11 +161,13 @@ async def test_transaction_interface_errors(self):
142161

143162
async def test_transaction_within_manual_transaction(self):
144163
self.assertIsNone(self.con._top_xact)
164+
self.assertFalse(self.con.is_in_transaction())
145165

146166
await self.con.execute('BEGIN')
147167

148168
tr = self.con.transaction()
149169
self.assertIsNone(self.con._top_xact)
170+
self.assertTrue(self.con.is_in_transaction())
150171

151172
with self.assertRaisesRegex(asyncpg.InterfaceError,
152173
'cannot use Connection.transaction'):
@@ -157,3 +178,4 @@ async def test_transaction_within_manual_transaction(self):
157178
await self.con.reset()
158179

159180
self.assertIsNone(self.con._top_xact)
181+
self.assertFalse(self.con.is_in_transaction())

0 commit comments

Comments
 (0)