From b2d6594bd9cc7a91b85cfe107d0e4ce7916bae62 Mon Sep 17 00:00:00 2001 From: Jiseok CHOI Date: Fri, 1 Aug 2025 13:39:45 +0900 Subject: [PATCH 1/2] Prevent direct instantiation of sqlite3.{Statement,Blob} --- Lib/test/test_sqlite3/test_dbapi.py | 2 -- stdlib/src/sqlite.rs | 24 ++++++++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 7a16f75655f..b6a1c05594e 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -346,8 +346,6 @@ def test_extended_error_code_on_exception(self): sqlite.SQLITE_CONSTRAINT_CHECK) self.assertEqual(exc.sqlite_errorname, "SQLITE_CONSTRAINT_CHECK") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_disallow_instantiation(self): cx = sqlite.connect(":memory:") check_disallow_instantiation(self, type(cx("select 1"))) diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 964da64bcfa..abcacae03f9 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -2036,7 +2036,7 @@ mod _sqlite { } #[pyattr] - #[pyclass(name, traverse)] + #[pyclass(module = "sqlite3", name = "Blob", traverse)] #[derive(Debug, PyPayload)] struct Blob { connection: PyRef, @@ -2044,6 +2044,14 @@ mod _sqlite { inner: PyMutex>, } + impl Constructor for Blob { + type Args = FuncArgs; + + fn py_new(_cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { + Err(vm.new_type_error("cannot create 'sqlite3.Blob' instances")) + } + } + #[derive(Debug)] struct BlobInner { blob: SqliteBlob, @@ -2056,7 +2064,7 @@ mod _sqlite { } } - #[pyclass(with(AsMapping))] + #[pyclass(with(AsMapping, Constructor))] impl Blob { #[pymethod] fn close(&self) { @@ -2356,7 +2364,7 @@ mod _sqlite { impl PrepareProtocol {} #[pyattr] - #[pyclass(name)] + #[pyclass(module = "sqlite3", name = "Statement")] #[derive(PyPayload)] struct Statement { st: PyMutex, @@ -2373,7 +2381,15 @@ mod _sqlite { } } - #[pyclass()] + impl Constructor for Statement { + type Args = FuncArgs; + + fn py_new(_cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { + Err(vm.new_type_error("cannot create 'sqlite3.Statement' instances")) + } + } + + #[pyclass(with(Constructor))] impl Statement { fn new( connection: &Connection, From ec0a2325e4e246f27caba06aea0a1f8d5bb3d5bc Mon Sep 17 00:00:00 2001 From: Jiseok CHOI Date: Fri, 1 Aug 2025 18:04:15 +0900 Subject: [PATCH 2/2] Use `Unconstructible` trait for internal types --- stdlib/src/sqlite.rs | 22 +++++----------------- vm/src/types/slot.rs | 2 +- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index abcacae03f9..157a8e5aeb3 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -71,7 +71,7 @@ mod _sqlite { sliceable::{SaturatedSliceIter, SliceableSequenceOp}, types::{ AsMapping, AsSequence, Callable, Comparable, Constructor, Hashable, IterNext, Iterable, - PyComparisonOp, SelfIter, + PyComparisonOp, SelfIter, Unconstructible, }, utils::ToCString, }; @@ -2044,13 +2044,7 @@ mod _sqlite { inner: PyMutex>, } - impl Constructor for Blob { - type Args = FuncArgs; - - fn py_new(_cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { - Err(vm.new_type_error("cannot create 'sqlite3.Blob' instances")) - } - } + impl Unconstructible for Blob {} #[derive(Debug)] struct BlobInner { @@ -2064,7 +2058,7 @@ mod _sqlite { } } - #[pyclass(with(AsMapping, Constructor))] + #[pyclass(with(AsMapping, Unconstructible))] impl Blob { #[pymethod] fn close(&self) { @@ -2381,15 +2375,9 @@ mod _sqlite { } } - impl Constructor for Statement { - type Args = FuncArgs; - - fn py_new(_cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { - Err(vm.new_type_error("cannot create 'sqlite3.Statement' instances")) - } - } + impl Unconstructible for Statement {} - #[pyclass(with(Constructor))] + #[pyclass(with(Unconstructible))] impl Statement { fn new( connection: &Connection, diff --git a/vm/src/types/slot.rs b/vm/src/types/slot.rs index eec15d9631f..54ad667b8c7 100644 --- a/vm/src/types/slot.rs +++ b/vm/src/types/slot.rs @@ -802,7 +802,7 @@ pub trait DefaultConstructor: PyPayload + Default { pub trait Unconstructible: PyPayload { #[pyslot] fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult { - Err(vm.new_type_error(format!("cannot create {} instances", cls.slot_name()))) + Err(vm.new_type_error(format!("cannot create '{}' instances", cls.slot_name()))) } }