Skip to content

Commit d436d0b

Browse files
Disallow nesting of part_of_a_transaction
Add durable=True to the atomic call inside part_of_a_transaction so that nesting is explicitly disallowed. This prevents tests from looking like they nest partial-transaction behaviour, which does not reflect real-world usage. Fixes #150 Co-authored-by: Charlie Denton <charlie@meshy.co.uk>
1 parent d0977ae commit d436d0b

3 files changed

Lines changed: 42 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
88
## [Unreleased]
99

1010
- Added MariaDB and SQLite to the test matrix.
11+
- Disallowed nesting of `part_of_a_transaction` to prevent nonsense
12+
implication of nested partial transactions in tests. Fixes #150.
1113

1214
## [1.0.0] - 2026-04-16
1315

src/django_subatomic/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ def part_of_a_transaction(using: str | None = None) -> Generator[None]:
3232
Note that this does not handle after-commit callback simulation. If you need that,
3333
use [`transaction`][django_subatomic.db.transaction] instead.
3434
"""
35-
with transaction.atomic(using=using):
35+
with transaction.atomic(using=using, durable=True):
3636
yield

tests/test_test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
from __future__ import annotations
22

3+
import re
4+
from typing import TYPE_CHECKING
5+
36
import pytest
7+
from django.db import transaction as django_transaction
48

59
from django_subatomic import db, test
610

711

12+
if TYPE_CHECKING:
13+
import contextlib
14+
from typing import Protocol
15+
16+
class DBContextManager(Protocol):
17+
def __call__(
18+
self, *, using: str | None = None
19+
) -> contextlib.AbstractContextManager[None, None]: ...
20+
21+
822
DEFAULT = "default"
923
pytestmark = [pytest.mark.django_db(databases=[DEFAULT])]
1024

@@ -35,3 +49,28 @@ def _callback_which_should_not_be_called() -> None:
3549

3650
with test.part_of_a_transaction():
3751
db.run_after_commit(_callback_which_should_not_be_called)
52+
53+
@pytest.mark.parametrize(
54+
"transaction_manager",
55+
(
56+
db.transaction,
57+
db.transaction_if_not_already,
58+
django_transaction.atomic,
59+
test.part_of_a_transaction,
60+
),
61+
)
62+
def test_fails_when_nested_inside_an_atomic_block(
63+
self, transaction_manager: DBContextManager
64+
) -> None:
65+
"""
66+
`part_of_a_transaction` cannot be nested inside another atomic block.
67+
"""
68+
with transaction_manager():
69+
with pytest.raises(
70+
RuntimeError,
71+
match=re.escape(
72+
"A durable atomic block cannot be nested within another atomic block."
73+
),
74+
):
75+
with test.part_of_a_transaction():
76+
...

0 commit comments

Comments
 (0)