Skip to content

Commit afd2b16

Browse files
committed
sqlite3: add Connection exception attributes and fix autocommit ValueError
Add DB-API 2.0 optional extension: expose exception classes as attributes on Connection objects (Warning, Error, InterfaceError, DatabaseError, DataError, OperationalError, IntegrityError, InternalError, ProgrammingError, NotSupportedError). Also fix autocommit validation to raise ValueError (not TypeError) when an unsupported type is passed. Assisted-by: GitHub Copilot:claude-sonnet-4-6
1 parent 2274cef commit afd2b16

3 files changed

Lines changed: 42 additions & 4 deletions

File tree

Lib/test/test_sqlite3/test_dbapi.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,6 @@ def test_use_after_close(self):
364364
with self.cx:
365365
pass
366366

367-
@unittest.expectedFailure # TODO: RUSTPYTHON
368367
def test_exceptions(self):
369368
# Optional DB-API extension.
370369
self.assertEqual(self.cx.Warning, sqlite.Warning)
@@ -401,7 +400,6 @@ def test_in_transaction_ro(self):
401400
with self.assertRaises(AttributeError):
402401
self.cx.in_transaction = True
403402

404-
@unittest.expectedFailure # TODO: RUSTPYTHON
405403
def test_connection_exceptions(self):
406404
exceptions = [
407405
"DataError",

Lib/test/test_sqlite3/test_transactions.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,6 @@ def test_autocommit_setget(self):
387387
cx.autocommit = mode
388388
self.assertEqual(cx.autocommit, mode)
389389

390-
@unittest.expectedFailure # TODO: RUSTPYTHON; autocommit validation error messages differ
391390
def test_autocommit_setget_invalid(self):
392391
msg = "autocommit must be True, False, or.*LEGACY"
393392
for mode in "a", 12, (), None:

crates/stdlib/src/_sqlite3.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ mod _sqlite3 {
322322
)))
323323
}
324324
} else {
325-
Err(vm.new_type_error(format!(
325+
Err(vm.new_value_error(format!(
326326
"autocommit must be True, False, or sqlite3.LEGACY_TRANSACTION_CONTROL, not {}",
327327
obj.class().name()
328328
)))
@@ -1642,6 +1642,47 @@ mod _sqlite3 {
16421642
fn total_changes(&self, vm: &VirtualMachine) -> PyResult<c_int> {
16431643
self._db_lock(vm).map(|x| x.total_changes())
16441644
}
1645+
1646+
#[pygetset(name = "Warning")]
1647+
fn exc_warning(&self) -> PyTypeRef {
1648+
warning_type().to_owned()
1649+
}
1650+
#[pygetset(name = "Error")]
1651+
fn exc_error(&self) -> PyTypeRef {
1652+
error_type().to_owned()
1653+
}
1654+
#[pygetset(name = "InterfaceError")]
1655+
fn exc_interface_error(&self) -> PyTypeRef {
1656+
interface_error_type().to_owned()
1657+
}
1658+
#[pygetset(name = "DatabaseError")]
1659+
fn exc_database_error(&self) -> PyTypeRef {
1660+
database_error_type().to_owned()
1661+
}
1662+
#[pygetset(name = "DataError")]
1663+
fn exc_data_error(&self) -> PyTypeRef {
1664+
data_error_type().to_owned()
1665+
}
1666+
#[pygetset(name = "OperationalError")]
1667+
fn exc_operational_error(&self) -> PyTypeRef {
1668+
operational_error_type().to_owned()
1669+
}
1670+
#[pygetset(name = "IntegrityError")]
1671+
fn exc_integrity_error(&self) -> PyTypeRef {
1672+
integrity_error_type().to_owned()
1673+
}
1674+
#[pygetset(name = "InternalError")]
1675+
fn exc_internal_error(&self) -> PyTypeRef {
1676+
internal_error_type().to_owned()
1677+
}
1678+
#[pygetset(name = "ProgrammingError")]
1679+
fn exc_programming_error(&self) -> PyTypeRef {
1680+
programming_error_type().to_owned()
1681+
}
1682+
#[pygetset(name = "NotSupportedError")]
1683+
fn exc_not_supported_error(&self) -> PyTypeRef {
1684+
not_supported_error_type().to_owned()
1685+
}
16451686
}
16461687

16471688
#[pyattr]

0 commit comments

Comments
 (0)