Database() now accepts all three Python transaction handling modes and
behaves identically in each. For autocommit=False connections - where
the driver holds an implicit transaction open at all times - the
library tracks transaction ownership itself:
- A new _explicit_transaction flag distinguishes transactions opened
with begin()/atomic() from the driver's implicit one, exposed as a
new db.in_transaction property (conn.in_transaction is always True
in this mode)
- begin() claims the driver's implicit transaction instead of
executing BEGIN, which the driver would reject; BEGIN/COMMIT/
ROLLBACK passed to db.execute() are routed through begin()/commit()/
rollback()
- Writes outside a user transaction commit the implicit transaction
immediately, preserving the library's auto-commit contract
- Row-returning statements outside a transaction fetch eagerly and
commit, so the implicit read transaction does not hold a shared
lock that blocks writes from other connections
- PRAGMA and VACUUM run in temporary driver autocommit mode
(ensure_autocommit_on() now flips conn.autocommit), since PRAGMAs
are silently ignored and VACUUM refused inside the implicit
transaction
A new pytest --sqlite-autocommit-false option runs the entire suite
in this mode, wired into CI alongside --sqlite-autocommit. Tests that
asserted on conn.in_transaction or wrote through db.conn without
committing now use the mode-aware library API instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PFkrS2nuP8mo1jmT594VCd