diff --git a/Cargo.lock b/Cargo.lock index 245550c..e270f34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,7 +95,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -106,7 +106,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -215,7 +215,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.72", + "syn", "which", ] @@ -398,7 +398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -481,7 +481,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -591,6 +591,12 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -603,7 +609,7 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -663,7 +669,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -746,9 +752,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.9" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" [[package]] name = "inout" @@ -760,6 +766,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "libc", +] + [[package]] name = "itertools" version = "0.12.1" @@ -799,9 +816,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libloading" @@ -1022,7 +1039,7 @@ dependencies = [ "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1172,7 +1189,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -1187,6 +1204,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1200,7 +1223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.72", + "syn", ] [[package]] @@ -1232,7 +1255,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -1249,15 +1272,15 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.19.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" +checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a" dependencies = [ - "cfg-if", "indoc", "libc", "memoffset", - "parking_lot", + "once_cell", + "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", @@ -1266,9 +1289,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.19.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" +checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" dependencies = [ "once_cell", "target-lexicon", @@ -1276,9 +1299,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.19.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" +checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" dependencies = [ "libc", "pyo3-build-config", @@ -1286,25 +1309,27 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.19.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" +checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "pyo3-macros-backend" -version = "0.19.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" +checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" dependencies = [ + "heck", "proc-macro2", + "pyo3-build-config", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -1396,7 +1421,7 @@ dependencies = [ "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1421,7 +1446,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1496,7 +1521,7 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1545,7 +1570,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -1611,7 +1636,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", ] [[package]] @@ -1626,17 +1661,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.72" @@ -1656,9 +1680,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "target-lexicon" -version = "0.12.15" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" +checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" [[package]] name = "thiserror" @@ -1677,7 +1701,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -1692,20 +1716,22 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.1" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" +checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "slab", + "socket2 0.6.0", "tokio-macros", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1720,13 +1746,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -1883,7 +1909,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] @@ -1909,9 +1935,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "nu-ansi-term", "sharded-slab", @@ -1950,9 +1976,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unindent" -version = "0.1.11" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" [[package]] name = "untrusted" @@ -2019,7 +2045,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.72", + "syn", "wasm-bindgen-shared", ] @@ -2041,7 +2067,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2122,6 +2148,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -2204,7 +2239,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b157652..910a748 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "pylibsql" version = "0.1.6" -edition = "2021" +edition = "2024" [lib] crate-type = ["cdylib"] [dependencies] -pyo3 = "0.19.0" +pyo3 = "0.25.1" libsql = { version = "0.9.19", features = ["encryption"] } -tokio = { version = "1.29.1", features = [ "rt-multi-thread" ] } -tracing-subscriber = "0.3" +tokio = { version = "1.47.0", features = [ "rt-multi-thread" ] } +tracing-subscriber = "0.3.19" [build-dependencies] version_check = "0.9.5" # used where logic has to be version/distribution specific, e.g. pypy -pyo3-build-config = { version = "0.19.0" } +pyo3-build-config = { version = "0.25.1" } diff --git a/src/lib.rs b/src/lib.rs index a64d535..8cd8863 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ use ::libsql as libsql_core; use pyo3::create_exception; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; -use pyo3::types::{PyList, PyTuple}; +use pyo3::types::{PyList, PyModule, PyTuple}; use std::cell::RefCell; use std::sync::{Arc, OnceLock}; use std::time::Duration; @@ -10,14 +10,15 @@ use tokio::runtime::{Handle, Runtime}; const LEGACY_TRANSACTION_CONTROL: i32 = -1; +#[derive(Clone)] enum ListOrTuple<'py> { - List(&'py PyList), - Tuple(&'py PyTuple), + List(Bound<'py, PyList>), + Tuple(Bound<'py, PyTuple>), } struct ListOrTupleIterator<'py> { index: usize, - inner: &'py ListOrTuple<'py> + inner: ListOrTuple<'py>, } fn rt() -> Handle { @@ -227,6 +228,7 @@ pub struct Connection { // SAFETY: The libsql crate guarantees that `Connection` is thread-safe. unsafe impl Send for Connection {} +unsafe impl Sync for Connection {} #[pymethods] impl Connection { @@ -293,20 +295,22 @@ impl Connection { Ok(()) } + #[pyo3(signature = (sql, parameters=None))] fn execute( self_: PyRef<'_, Self>, sql: String, - parameters: Option, + parameters: Option>, ) -> PyResult { let cursor = Connection::cursor(&self_)?; rt().block_on(async { execute(&cursor, sql, parameters).await })?; Ok(cursor) } + #[pyo3(signature = (sql, parameters=None))] fn executemany( self_: PyRef<'_, Self>, sql: String, - parameters: Option<&PyList>, + parameters: Option<&Bound<'_, PyList>>, ) -> PyResult { let cursor = Connection::cursor(&self_)?; for parameters in parameters.unwrap().iter() { @@ -340,9 +344,7 @@ impl Connection { fn in_transaction(self_: PyRef<'_, Self>) -> PyResult { #[cfg(Py_3_12)] { - Ok( - !self_.conn.borrow().as_ref().unwrap().is_autocommit() || self_.autocommit == 0 - ) + Ok(!self_.conn.borrow().as_ref().unwrap().is_autocommit() || self_.autocommit == 0) } #[cfg(not(Py_3_12))] { @@ -372,11 +374,12 @@ impl Connection { Ok(slf) } + #[pyo3(signature = (exc_type=None, _exc_val=None, _exc_tb=None))] fn __exit__( self_: PyRef<'_, Self>, - exc_type: Option<&PyAny>, - _exc_val: Option<&PyAny>, - _exc_tb: Option<&PyAny>, + exc_type: Option<&Bound<'_, PyAny>>, + _exc_val: Option<&Bound<'_, PyAny>>, + _exc_tb: Option<&Bound<'_, PyAny>>, ) -> PyResult { if exc_type.is_none() { // Commit on clean exit @@ -404,6 +407,7 @@ pub struct Cursor { // SAFETY: The libsql crate guarantees that `Connection` is thread-safe. unsafe impl Send for Cursor {} +unsafe impl Sync for Cursor {} impl Drop for Cursor { fn drop(&mut self) { @@ -426,19 +430,21 @@ impl Cursor { Ok(()) } + #[pyo3(signature = (sql, parameters=None))] fn execute<'a>( self_: PyRef<'a, Self>, sql: String, - parameters: Option, + parameters: Option>, ) -> PyResult> { rt().block_on(async { execute(&self_, sql, parameters).await })?; Ok(self_) } + #[pyo3(signature = (sql, parameters=None))] fn executemany<'a>( self_: PyRef<'a, Self>, sql: String, - parameters: Option<&PyList>, + parameters: Option<&Bound<'_, PyList>>, ) -> PyResult> { for parameters in parameters.unwrap().iter() { let parameters = parameters.extract::()?; @@ -465,7 +471,7 @@ impl Cursor { } #[getter] - fn description(self_: PyRef<'_, Self>) -> PyResult> { + fn description(self_: PyRef<'_, Self>) -> PyResult>> { let stmt = self_.stmt.borrow(); let mut elements: Vec> = vec![]; match stmt.as_ref() { @@ -481,17 +487,18 @@ impl Cursor { self_.py().None(), self_.py().None(), ) - .to_object(self_.py()); - elements.push(element); + .into_pyobject(self_.py()) + .unwrap(); + elements.push(element.into()); } - let elements = PyTuple::new(self_.py(), elements); + let elements = PyTuple::new(self_.py(), elements)?; Ok(Some(elements)) } None => Ok(None), } } - fn fetchone(self_: PyRef<'_, Self>) -> PyResult> { + fn fetchone(self_: PyRef<'_, Self>) -> PyResult>> { let mut rows = self_.rows.borrow_mut(); match rows.as_mut() { Some(rows) => { @@ -508,7 +515,8 @@ impl Cursor { } } - fn fetchmany(self_: PyRef<'_, Self>, size: Option) -> PyResult> { + #[pyo3(signature = (size=None))] + fn fetchmany(self_: PyRef<'_, Self>, size: Option) -> PyResult>> { let mut rows = self_.rows.borrow_mut(); match rows.as_mut() { Some(rows) => { @@ -534,13 +542,13 @@ impl Cursor { } } } - Ok(Some(PyList::new(self_.py(), elements))) + Ok(Some(PyList::new(self_.py(), elements)?)) } None => Ok(None), } } - fn fetchall(self_: PyRef<'_, Self>) -> PyResult> { + fn fetchall(self_: PyRef<'_, Self>) -> PyResult>> { let mut rows = self_.rows.borrow_mut(); match rows.as_mut() { Some(rows) => { @@ -557,7 +565,7 @@ impl Cursor { None => break, } } - Ok(Some(PyList::new(self_.py(), elements))) + Ok(Some(PyList::new(self_.py(), elements)?)) } None => Ok(None), } @@ -669,36 +677,40 @@ fn stmt_is_dml(sql: &str) -> bool { sql.starts_with("INSERT") || sql.starts_with("UPDATE") || sql.starts_with("DELETE") } -fn convert_row(py: Python, row: libsql_core::Row, column_count: i32) -> PyResult<&PyTuple> { +fn convert_row( + py: Python, + row: libsql_core::Row, + column_count: i32, +) -> PyResult> { let mut elements: Vec> = vec![]; for col_idx in 0..column_count { let libsql_value = row.get_value(col_idx).map_err(to_py_err)?; let value = match libsql_value { libsql_core::Value::Integer(v) => { let value = v as i64; - value.into_py(py) + value.into_pyobject(py).unwrap().into() } - libsql_core::Value::Real(v) => v.into_py(py), - libsql_core::Value::Text(v) => v.into_py(py), + libsql_core::Value::Real(v) => v.into_pyobject(py).unwrap().into(), + libsql_core::Value::Text(v) => v.into_pyobject(py).unwrap().into(), libsql_core::Value::Blob(v) => { let value = v.as_slice(); - value.into_py(py) + value.into_pyobject(py).unwrap().into() } libsql_core::Value::Null => py.None(), }; elements.push(value); } - Ok(PyTuple::new(py, elements)) + Ok(PyTuple::new(py, elements)?) } create_exception!(libsql, Error, pyo3::exceptions::PyException); impl<'py> FromPyObject<'py> for ListOrTuple<'py> { - fn extract(ob: &'py PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { if let Ok(list) = ob.downcast::() { - Ok(ListOrTuple::List(list)) + Ok(ListOrTuple::List(list.clone())) } else if let Ok(tuple) = ob.downcast::() { - Ok(ListOrTuple::Tuple(tuple)) + Ok(ListOrTuple::Tuple(tuple.clone())) } else { Err(PyValueError::new_err( "Expected a list or tuple for parameters", @@ -708,19 +720,19 @@ impl<'py> FromPyObject<'py> for ListOrTuple<'py> { } impl<'py> ListOrTuple<'py> { - pub fn iter(&self) -> ListOrTupleIterator { - ListOrTupleIterator{ + pub fn iter(&self) -> ListOrTupleIterator<'py> { + ListOrTupleIterator { index: 0, - inner: self, + inner: self.clone(), } } } impl<'py> Iterator for ListOrTupleIterator<'py> { - type Item = &'py PyAny; + type Item = Bound<'py, PyAny>; fn next(&mut self) -> Option { - let rv = match self.inner { + let rv = match &self.inner { ListOrTuple::List(list) => list.get_item(self.index), ListOrTuple::Tuple(tuple) => tuple.get_item(self.index), }; @@ -732,7 +744,7 @@ impl<'py> Iterator for ListOrTupleIterator<'py> { } } #[pymodule] -fn libsql(py: Python, m: &PyModule) -> PyResult<()> { +fn libsql(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { let _ = tracing_subscriber::fmt::try_init(); m.add("LEGACY_TRANSACTION_CONTROL", LEGACY_TRANSACTION_CONTROL)?; m.add("paramstyle", "qmark")?;