Skip to content

Commit 27f1ce6

Browse files
author
legolas.zhan
committed
fixed hobbit_core.db.transaction
1 parent a2754ce commit 27f1ce6

File tree

5 files changed

+20
-45
lines changed

5 files changed

+20
-45
lines changed

hobbit_core/db.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ def transaction(session: Session, nested: bool = False):
306306
"""SQLAlchemy 1.4 deprecates “autocommit mode.
307307
See more: https://docs.sqlalchemy.org/en/14/orm/session_transaction.html
308308
309-
2022-05-18 Updated: Use `nested=None` to prevent signal bug, See more:
309+
2024-09-25 ignore signal bug, See more:
310310
https://github.com/pallets-eco/flask-sqlalchemy/issues/645
311311
312312
Tips:
@@ -355,22 +355,15 @@ def create(username, password):
355355
def wrapper(func):
356356
@wraps(func)
357357
def inner(*args, **kwargs):
358-
if getattr(session, 'autocommit') is True and nested is False:
359-
session.begin() # start a transaction
360358
try:
361-
if nested is None:
362-
resp = func(*args, **kwargs)
363-
else:
359+
if nested:
364360
with session.begin_nested():
365-
resp = func(*args, **kwargs)
366-
if not nested:
367-
# commit - begin(), transaction finished
368-
session.commit()
361+
return func(*args, **kwargs)
362+
else:
363+
with session.begin():
364+
return func(*args, **kwargs)
369365
except Exception as e:
370-
if not nested:
371-
session.rollback()
372-
session.remove()
366+
session.rollback()
373367
raise e
374-
return resp
375368
return inner
376369
return wrapper

hobbit_core/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ def bulk_create_or_update_on_duplicate(
300300
while len(items) > 0:
301301
batch, items = items[:batch_size], items[batch_size:]
302302
try:
303-
result = db.session.execute(text(sql), batch, bind_arguments={'bind': engine})
303+
result = db.session.execute(
304+
text(sql), batch, bind_arguments={'bind': engine})
304305
except Exception as e:
305306
logger.error(e, exc_info=True)
306307
logger.info(sql)

tests/conftest.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ def assert_session(app):
2929
conn = tdb.engine.connect()
3030
options = dict(bind=conn, binds={})
3131
sess = tdb._make_scoped_session(options=options)
32-
assert sess.autocommit is False
3332
yield sess
3433
sess.remove()
3534

@@ -38,7 +37,6 @@ def assert_session(app):
3837
def db_session(app):
3938
with app.app_context():
4039
sess = tdb.session
41-
assert sess.autocommit is False
4240
return sess
4341

4442

tests/test_app/views.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,3 @@ def create_user():
6363

6464
create_user()
6565
return jsonify({})
66-
67-
68-
@bp.route('/create_user/failed/', methods=['POST'])
69-
@base_use_kwargs({'email': fields.Str()})
70-
def create_user_failed(email):
71-
@transaction(db.session)
72-
def create_user():
73-
user1 = User(username='signalling_test', email=email, password='1')
74-
db.session.add(user1)
75-
76-
create_user()
77-
return jsonify({})

tests/test_db.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import pytest
33
import random
44

5+
from sqlalchemy.exc import InvalidRequestError
6+
57
from hobbit_core.db import EnumExt, transaction
68
from hobbit_core.db import BaseModel, Column
79

@@ -119,10 +121,10 @@ def test_to_opts(self, TaskState):
119121
class TestTransaction(BaseTest):
120122

121123
def clear_user(self):
122-
User.query.delete()
123-
db.session.commit()
124-
db.session.remove()
125-
assert User.query.all() == []
124+
with db.session.begin():
125+
User.query.delete()
126+
with db.session.begin():
127+
assert User.query.all() == []
126128

127129
def test_transaction_decorator(self, session, assert_session):
128130
@transaction(session)
@@ -214,8 +216,8 @@ def view_func2():
214216
assert len(assert_session.query(User).all()) == 1
215217
assert assert_session.query(User).first().username == 'test1'
216218

217-
def test_nested_self_not_raise(self, session, assert_session):
218-
# > 1.4
219+
# v2.x should raise
220+
def test_nested_self_raise(self, session, assert_session):
219221
@transaction(session)
220222
def create_user():
221223
user = User(username='test1', email='[email protected]', password='1')
@@ -227,8 +229,9 @@ def view_func():
227229
db.session.add(user)
228230
create_user()
229231

230-
view_func()
231-
assert len(assert_session.query(User).all()) == 2
232+
with pytest.raises(InvalidRequestError, match='A transaction is already begun on this Session.'): # NOQA E501
233+
view_func()
234+
assert len(assert_session.query(User).all()) == 0
232235

233236
def test_nested_self_with_nested_arg_is_true(
234237
self, session, assert_session):
@@ -269,11 +272,3 @@ def test_transaction_signal_success(self, client, assert_session):
269272

270273
user = assert_session.query(User).filter(User.email == email).first()
271274
assert user and user.username == "signalling_ok"
272-
273-
def test_transaction_signal_dailed(self, client, assert_session):
274-
275-
resp = client.post('/create_user/failed/', json={"email": email})
276-
assert resp.status_code == 200
277-
278-
user = assert_session.query(User).filter(User.email == email).first()
279-
assert user and user.username != "signalling_ok"

0 commit comments

Comments
 (0)