Skip to content

Commit dc44a46

Browse files
authored
Merge pull request #81 from kraken-tech/meshy/docs/docstrings
Rework docstrings to improve generated API docs
2 parents 23043c4 + 75242e4 commit dc44a46

File tree

3 files changed

+45
-27
lines changed

3 files changed

+45
-27
lines changed

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,6 @@ plugins:
5555
show_signature_type_parameters: true
5656
- api-autonav:
5757
modules: ['src/django_subatomic']
58+
- autorefs
5859
- search
5960
- mike

src/django_subatomic/db.py

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ def transaction(*, using: str | None = None) -> Generator[None]:
3333
"""
3434
Create a database transaction.
3535
36+
Can be used as a decorator or a context manager.
37+
3638
Nested calls are not allowed because SQL does not support nested transactions.
3739
Consider this like Django's `atomic(durable=True)`, but with added after-commit callback support in tests.
3840
39-
This wraps Django's 'atomic' function.
40-
4141
Raises:
4242
RuntimeError: if we call this from inside another existing transaction.
4343
"""
@@ -55,14 +55,28 @@ def transaction_if_not_already(*, using: str | None = None) -> Generator[None]:
5555
"""
5656
Create a transaction if one isn't already open.
5757
58+
Can be used as a decorator or a context manager.
59+
5860
Use of this hints at code which lacks control over the state it's called in.
5961
60-
Suggested alternatives:
62+
Note:
63+
This has a bit of a clunky name. This is a deliberate attempt to
64+
discourage its use. It acts as a code-smell to highlight that places
65+
which use it may need further work to achieve full control over how
66+
transactions are managed.
67+
68+
Warning:
69+
If this function is called when a transaction is already open, errors raised
70+
through it will invalidate the current transaction, regardless of where
71+
it was opened.
6172
62-
- In functions which should not control transactions, use `transaction_required`.
63-
This ensures they are handled by the caller.
73+
Tip: Suggested alternatives
74+
- In functions which should not control transactions,
75+
use [`transaction_required`][django_subatomic.db.transaction_required].
76+
This ensures they are handled by the caller.
6477
65-
- In functions which can unambiguously control transactions, use `transaction`.
78+
- In functions which can unambiguously control transactions,
79+
use [`transaction`][django_subatomic.db.transaction].
6680
"""
6781
# If the innermost atomic block is from a test case, we should create a SAVEPOINT here.
6882
# This allows for a rollback when an exception propagates out of this block, and so
@@ -81,21 +95,21 @@ def savepoint(*, using: str | None = None) -> Generator[None]:
8195
"""
8296
Create a database savepoint.
8397
84-
Must be called inside an active transaction.
98+
Can be used as a context manager, but _not_ as a decorator.
8599
86-
Tips:
100+
Must be called inside an active transaction.
87101
88-
- You should only create a savepoint if you may roll back to it before
89-
continuing with your transaction. If your intention is to ensure that
90-
your code is committed atomically, consider using `transaction_required`
91-
instead.
92-
- We believe savepoint rollback should be handled where the savepoint is created.
93-
That locality is not possible with a decorator, so this function
94-
deliberately does not work as one.
102+
Tip: Recommended usage
103+
- You should only create a savepoint if you may roll back to it before
104+
continuing with your transaction. If your intention is to ensure that
105+
your code is committed atomically, consider using [`transaction_required`][django_subatomic.db.transaction_required]
106+
instead.
107+
- We believe savepoint rollback should be handled where the savepoint is created.
108+
That locality is not possible with a decorator, so this function
109+
deliberately does not work as one.
95110
96111
Raises:
97112
_MissingRequiredTransaction: if we are not in a transaction
98-
See Note [_MissingRequiredTransaction in tests]
99113
"""
100114
with (
101115
transaction_required(using=using),
@@ -115,8 +129,6 @@ def transaction_required(*, using: str | None = None) -> Generator[None]:
115129
because we don't want to run the risk of allowing code to pass tests
116130
but fail in production.
117131
118-
See Note [_MissingRequiredTransaction in tests]
119-
120132
Raises:
121133
_MissingRequiredTransaction: if we are not in a transaction.
122134
"""
@@ -132,6 +144,8 @@ def durable[**P, R](func: Callable[P, R]) -> Callable[P, R]:
132144
"""
133145
Enforce durability with this decorator.
134146
147+
Can be used as a decorator, but _not_ as a context manager.
148+
135149
"Durability" means that the function's work cannot be rolled back after it completes,
136150
and is not to be confused with "atomicity" (which is about ensuring that the function
137151
either completes all its work or none of it).
@@ -307,13 +321,18 @@ def run_after_commit(
307321
"""
308322
Register a callback to be called after the current transaction is committed.
309323
324+
(Transactions created by the test suite are deliberately ignored.)
325+
310326
If the current transaction is rolled back, the callback will not be called.
327+
311328
By default, an error will be raised if there is no transaction open.
312-
The transaction opened by tests is ignored for this purpose.
329+
While you are transitioning your codebase to stricter transaction handling,
330+
you may disable this with [`settings.SUBATOMIC_AFTER_COMMIT_NEEDS_TRANSACTION`][subatomic_after_commit_needs_transaction].
313331
314-
Note that Django's `on_commit` has a `robust` parameter, which allows a callback to fail silently.
315-
Kraken has a convention to "not allow code to fail silently"
316-
so this behaviour is not available from this function.
332+
Note:
333+
Django's `on_commit` has a `robust` parameter, which allows a callback
334+
to fail silently. Kraken has a convention to "not allow code to fail
335+
silently" so this behaviour is not available from this function.
317336
"""
318337
if using is None:
319338
using = django_db.DEFAULT_DB_ALIAS

src/django_subatomic/test.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
@contextlib.contextmanager
1818
def part_of_a_transaction(using: str | None = None) -> Generator[None]:
1919
"""
20-
Allow calling `transaction_required` code without an explicit transaction.
20+
Allow calling "transaction required" code without an explicit transaction.
2121
22-
This is useful for directly testing code marked with `db.transaction_required()`
22+
This is useful for directly testing code marked with [`transaction_required`][django_subatomic.db.transaction_required]
2323
without going through other code which is responsible for managing a transaction.
2424
2525
This works by entering a new "atomic" block, so that the inner-most "atomic"
@@ -30,9 +30,7 @@ def part_of_a_transaction(using: str | None = None) -> Generator[None]:
3030
than by calling this.
3131
3232
Note that this does not handle after-commit callback simulation. If you need that,
33-
consider using `django_subatomic.db.transaction` instead.
34-
35-
See Note [_MissingRequiredTransaction in tests]
33+
use [`transaction`][django_subatomic.db.transaction] instead.
3634
"""
3735
with transaction.atomic(using=using):
3836
yield

0 commit comments

Comments
 (0)