From 4de7d411dea1fbe1a2be4eceaaab2105f0f6d18e Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 8 May 2024 09:37:42 -0400 Subject: [PATCH 01/11] WIP --- Cargo.lock | 20 ++-- Cargo.toml | 2 +- src/lib.rs | 267 +++++++++++++++++++++++++++++------------------------ 3 files changed, 156 insertions(+), 133 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1467e46..5159b40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.20.3" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bdbb96d49157e65d45cc287af5f32ffadd5f4761438b527b055fb0d4bb8233" +checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8" dependencies = [ "cfg-if", "indoc", @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.20.3" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deaa5745de3f5231ce10517a1f5dd97d53e5a2fd77aa6b5842292085831d48d7" +checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50" dependencies = [ "once_cell", "target-lexicon", @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.20.3" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b42531d03e08d4ef1f6e85a2ed422eb678b8cd62b762e53891c05faf0d4afa" +checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403" dependencies = [ "libc", "pyo3-build-config", @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.20.3" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7305c720fa01b8055ec95e484a6eca7a83c841267f0dd5280f0c8b8551d2c158" +checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.20.3" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7e9b68bb9c3149c5b0cade5d07f953d6d125eb4337723c4ccdb665f1f96185" +checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c" dependencies = [ "heck", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 13012d0..6e8be78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,5 @@ rpds = "1.1.0" archery = "1.2.0" [dependencies.pyo3] -version = "0.20.3" +version = "0.21.2" features = ["extension-module"] diff --git a/src/lib.rs b/src/lib.rs index ad3cce2..e49e870 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher}; use pyo3::exceptions::PyIndexError; use pyo3::pyclass::CompareOp; -use pyo3::types::{PyDict, PyIterator, PyNone, PyTuple, PyType}; +use pyo3::types::{PyDict, PyIterator, PyTuple, PyType}; use pyo3::{exceptions::PyKeyError, types::PyMapping}; use pyo3::{prelude::*, AsPyPointer, PyTypeInfo}; use rpds::{ @@ -48,10 +48,10 @@ unsafe impl AsPyPointer for Key { } impl<'source> FromPyObject<'source> for Key { - fn extract(ob: &'source PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { Ok(Key { hash: ob.hash()?, - inner: ob.into(), + inner: ob.unbind(), }) } } @@ -69,7 +69,7 @@ impl From> for HashTrieMapPy { } impl<'source> FromPyObject<'source> for HashTrieMapPy { - fn extract(ob: &'source PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { let mut ret = HashTrieMap::new_sync(); if let Ok(mapping) = ob.downcast::() { for each in mapping.items()?.iter()? { @@ -90,7 +90,7 @@ impl<'source> FromPyObject<'source> for HashTrieMapPy { impl HashTrieMapPy { #[new] #[pyo3(signature = (value=None, **kwds))] - fn init(value: Option, kwds: Option<&PyDict>) -> PyResult { + fn init(value: Option, kwds: Option<&Bound<'_, PyDict>>) -> PyResult { let mut map: HashTrieMapPy; if let Some(value) = value { map = value; @@ -101,7 +101,7 @@ impl HashTrieMapPy { } if let Some(kwds) = kwds { for (k, v) in kwds { - map.inner.insert_mut(Key::extract(k)?, v.into()); + map.inner.insert_mut(Key::extract_bound(&k)?, v.into()); } } Ok(map) @@ -169,9 +169,9 @@ impl HashTrieMapPy { } } - fn __reduce__(slf: PyRef) -> (&PyType, (Vec<(Key, PyObject)>,)) { + fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec<(Key, PyObject)>,)) { ( - HashTrieMapPy::type_object(slf.py()), + HashTrieMapPy::type_object_bound(slf.py()), (slf.inner .iter() .map(|(k, v)| (k.clone(), v.clone())) @@ -180,27 +180,31 @@ impl HashTrieMapPy { } #[classmethod] - fn convert(_cls: &PyType, value: &PyAny, py: Python) -> PyResult { + fn convert( + _cls: &Bound<'_, PyType>, + value: Bound<'_, PyAny>, + py: Python, + ) -> PyResult { if value.is_instance_of::() { - Ok(value.into()) + Ok(value.unbind()) } else { - Ok(HashTrieMapPy::extract(value)?.into_py(py)) + Ok(HashTrieMapPy::extract_bound(&value)?.into_py(py)) } } #[classmethod] fn fromkeys( - _cls: &PyType, - keys: &PyAny, - val: Option<&PyAny>, + _cls: &Bound<'_, PyType>, + keys: &Bound<'_, PyAny>, + val: Option<&Bound<'_, PyAny>>, py: Python, ) -> PyResult { let mut inner = HashTrieMap::new_sync(); - let none = py.None(); - let value = val.unwrap_or_else(|| none.as_ref(py)); + let none = py.None().into_bound(py); + let value = val.unwrap_or_else(|| &none); for each in keys.iter()? { - let key = Key::extract(each?)?.to_owned(); - inner.insert_mut(key, value.into()); + let key = Key::extract_bound(&each?)?.to_owned(); + inner.insert_mut(key, value.unbind()); } Ok(HashTrieMapPy { inner }) } @@ -242,9 +246,9 @@ impl HashTrieMapPy { } } - fn insert(&self, key: Key, value: &PyAny) -> HashTrieMapPy { + fn insert(&self, key: Key, value: Bound<'_, PyAny>) -> HashTrieMapPy { HashTrieMapPy { - inner: self.inner.insert(key, value.into()), + inner: self.inner.insert(key, value.unbind()), } } @@ -258,17 +262,21 @@ impl HashTrieMapPy { } #[pyo3(signature = (*maps, **kwds))] - fn update(&self, maps: &PyTuple, kwds: Option<&PyDict>) -> PyResult { + fn update( + &self, + maps: &Bound<'_, PyTuple>, + kwds: Option<&Bound<'_, PyDict>>, + ) -> PyResult { let mut inner = self.inner.clone(); for value in maps { - let map = HashTrieMapPy::extract(value)?; + let map = HashTrieMapPy::extract_bound(&value)?; for (k, v) in &map.inner { inner.insert_mut(k.to_owned(), v.to_owned()); } } if let Some(kwds) = kwds { for (k, v) in kwds { - inner.insert_mut(Key::extract(k)?, v.extract()?); + inner.insert_mut(Key::extract_bound(&k)?, v.extract()?); } } Ok(HashTrieMapPy { inner }) @@ -343,22 +351,22 @@ impl KeysView { self.inner.contains_key(&key) } - fn __eq__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? != slf.inner.size() { + fn __eq__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? != slf.inner.size() { return Ok(false); } for each in other.iter()? { - if !slf.inner.contains_key(&Key::extract(each?)?) { + if !slf.inner.contains_key(&Key::extract_bound(&each?)?) { return Ok(false); } } Ok(true) } - fn __lt__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { + fn __lt__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { return Ok(false); } for each in slf.inner.keys() { @@ -369,9 +377,9 @@ impl KeysView { Ok(true) } - fn __le__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? < slf.inner.size() { + fn __le__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? < slf.inner.size() { return Ok(false); } for each in slf.inner.keys() { @@ -382,26 +390,26 @@ impl KeysView { Ok(true) } - fn __gt__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? >= slf.inner.size() { + fn __gt__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? >= slf.inner.size() { return Ok(false); } for each in other.iter()? { - if !slf.inner.contains_key(&Key::extract(each?)?) { + if !slf.inner.contains_key(&Key::extract_bound(&each?)?) { return Ok(false); } } Ok(true) } - fn __ge__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? > slf.inner.size() { + fn __ge__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? > slf.inner.size() { return Ok(false); } for each in other.iter()? { - if !slf.inner.contains_key(&Key::extract(each?)?) { + if !slf.inner.contains_key(&Key::extract_bound(&each?)?) { return Ok(false); } } @@ -418,11 +426,11 @@ impl KeysView { slf.inner.size() } - fn __and__(slf: PyRef<'_, Self>, other: &PyAny) -> PyResult { + fn __and__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>) -> PyResult { KeysView::intersection(slf, other) } - fn __or__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { + fn __or__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { KeysView::union(slf, other, py) } @@ -438,11 +446,11 @@ impl KeysView { format!("keys_view({{{}}})", contents.collect::>().join(", ")) } - fn intersection(slf: PyRef<'_, Self>, other: &PyAny) -> PyResult { + fn intersection(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>) -> PyResult { // TODO: iterate over the shorter one if it's got a length let mut inner = HashTrieSet::new_sync(); for each in other.iter()? { - let key = Key::extract(each?)?; + let key = Key::extract_bound(&each?)?; if slf.inner.contains_key(&key) { inner.insert_mut(key); } @@ -450,13 +458,12 @@ impl KeysView { Ok(HashTrieSetPy { inner }) } - fn union(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { + fn union(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { // There doesn't seem to be a low-effort way to get a HashTrieSet out of a map, // so we just keep our map and add values we'll ignore. let mut inner = slf.inner.clone(); - let none = PyNone::get(py); for each in other.iter()? { - inner.insert_mut(Key::extract(each?)?, none.into()); + inner.insert_mut(Key::extract_bound(&each?)?, py.None()); } Ok(KeysView { inner }) } @@ -514,9 +521,9 @@ impl ItemsView { slf.inner.size() } - fn __eq__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? != slf.inner.size() { + fn __eq__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? != slf.inner.size() { return Ok(false); } for (k, v) in slf.inner.iter() { @@ -529,19 +536,19 @@ impl ItemsView { fn __repr__(&self, py: Python) -> String { let contents = self.inner.into_iter().map(|(k, v)| { - let tuple = PyTuple::new(py, [k.inner.to_owned(), v.to_owned()]); + let tuple = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); format!("{:?}", tuple) }); format!("items_view([{}])", contents.collect::>().join(", ")) } - fn __lt__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { + fn __lt__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { return Ok(false); } for (k, v) in slf.inner.iter() { - let pair = PyTuple::new(py, [k.inner.to_owned(), v.to_owned()]); + let pair = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); // FIXME: needs to compare if !other.contains(pair)? { return Ok(false); @@ -550,13 +557,13 @@ impl ItemsView { Ok(true) } - fn __le__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? < slf.inner.size() { + fn __le__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? < slf.inner.size() { return Ok(false); } for (k, v) in slf.inner.iter() { - let pair = PyTuple::new(py, [k.inner.to_owned(), v.to_owned()]); + let pair = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); // FIXME: needs to compare if !other.contains(pair)? { return Ok(false); @@ -565,17 +572,17 @@ impl ItemsView { Ok(true) } - fn __gt__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? >= slf.inner.size() { + fn __gt__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? >= slf.inner.size() { return Ok(false); } for each in other.iter()? { let kv = each?; let k = kv.get_item(0)?; - match slf.inner.get(&Key::extract(k)?) { + match slf.inner.get(&Key::extract_bound(&k)?) { Some(value) => { - let pair = PyTuple::new(py, [k, value.as_ref(py)]); + let pair = PyTuple::new_bound(py, [k, value.into_bound(py)]); if !pair.eq(kv)? { return Ok(false); } @@ -586,17 +593,17 @@ impl ItemsView { Ok(true) } - fn __ge__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? > slf.inner.size() { + fn __ge__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? > slf.inner.size() { return Ok(false); } for each in other.iter()? { let kv = each?; let k = kv.get_item(0)?; - match slf.inner.get(&Key::extract(k)?) { + match slf.inner.get(&Key::extract_bound(&k)?) { Some(value) => { - let pair = PyTuple::new(py, [k, value.as_ref(py)]); + let pair = PyTuple::new_bound(py, [k, value.into_bound(py)]); if !pair.eq(kv)? { return Ok(false); } @@ -607,39 +614,55 @@ impl ItemsView { Ok(true) } - fn __and__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { + fn __and__( + slf: PyRef<'_, Self>, + other: &Bound<'_, PyAny>, + py: Python, + ) -> PyResult { ItemsView::intersection(slf, other, py) } - fn __or__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { + fn __or__( + slf: PyRef<'_, Self>, + other: &Bound<'_, PyAny>, + py: Python, + ) -> PyResult { ItemsView::union(slf, other, py) } - fn intersection(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { + fn intersection( + slf: PyRef<'_, Self>, + other: &Bound<'_, PyAny>, + py: Python, + ) -> PyResult { // TODO: iterate over the shorter one if it's got a length let mut inner = HashTrieSet::new_sync(); for each in other.iter()? { let kv = each?; let k = kv.get_item(0)?; - if let Some(value) = slf.inner.get(&Key::extract(k)?) { - let pair = PyTuple::new(py, [k, value.as_ref(py)]); + if let Some(value) = slf.inner.get(&Key::extract_bound(&k)?) { + let pair = PyTuple::new_bound(py, [k, value.into_bound(py)]); if pair.eq(kv)? { - inner.insert_mut(Key::extract(pair)?); + inner.insert_mut(Key::extract_bound(&pair)?); } } } Ok(HashTrieSetPy { inner }) } - fn union(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { + fn union( + slf: PyRef<'_, Self>, + other: &Bound<'_, PyAny>, + py: Python, + ) -> PyResult { // TODO: this is very inefficient, but again can't seem to get a HashTrieSet out of ourself let mut inner = HashTrieSet::new_sync(); for (k, v) in slf.inner.iter() { - let pair = PyTuple::new(py, [k.inner.to_owned(), v.to_owned()]); - inner.insert_mut(Key::extract(pair)?); + let pair = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); + inner.insert_mut(Key::extract_bound(&pair)?); } for each in other.iter()? { - inner.insert_mut(Key::extract(each?)?); + inner.insert_mut(Key::extract_bound(&each?)?); } Ok(HashTrieSetPy { inner }) } @@ -652,7 +675,7 @@ struct HashTrieSetPy { } impl<'source> FromPyObject<'source> for HashTrieSetPy { - fn extract(ob: &'source PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { let mut ret = HashTrieSet::new_sync(); for each in ob.iter()? { let k: Key = each?.extract()?; @@ -719,22 +742,22 @@ impl HashTrieSetPy { ) } - fn __eq__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? != slf.inner.size() { + fn __eq__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? != slf.inner.size() { return Ok(false); } for each in other.iter()? { - if !slf.inner.contains(&Key::extract(each?)?) { + if !slf.inner.contains(&Key::extract_bound(&each?)?) { return Ok(false); } } Ok(true) } - fn __lt__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { + fn __lt__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { return Ok(false); } for each in slf.inner.iter() { @@ -745,9 +768,9 @@ impl HashTrieSetPy { Ok(true) } - fn __le__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? < slf.inner.size() { + fn __le__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? < slf.inner.size() { return Ok(false); } for each in slf.inner.iter() { @@ -758,35 +781,35 @@ impl HashTrieSetPy { Ok(true) } - fn __gt__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? >= slf.inner.size() { + fn __gt__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? >= slf.inner.size() { return Ok(false); } for each in other.iter()? { - if !slf.inner.contains(&Key::extract(each?)?) { + if !slf.inner.contains(&Key::extract_bound(&each?)?) { return Ok(false); } } Ok(true) } - fn __ge__(slf: PyRef<'_, Self>, other: &PyAny, py: Python) -> PyResult { - let abc = PyModule::import(py, "collections.abc")?; - if !other.is_instance(abc.getattr("Set")?)? || other.len()? > slf.inner.size() { + fn __ge__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { + let abc = PyModule::import_bound(py, "collections.abc")?; + if !other.is_instance(&abc.getattr("Set")?)? || other.len()? > slf.inner.size() { return Ok(false); } for each in other.iter()? { - if !slf.inner.contains(&Key::extract(each?)?) { + if !slf.inner.contains(&Key::extract_bound(&each?)?) { return Ok(false); } } Ok(true) } - fn __reduce__(slf: PyRef) -> (&PyType, (Vec,)) { + fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec,)) { ( - HashTrieSetPy::type_object(slf.py()), + HashTrieSetPy::type_object_bound(slf.py()), (slf.inner.iter().cloned().collect(),), ) } @@ -881,12 +904,12 @@ impl HashTrieSetPy { } #[pyo3(signature = (*iterables))] - fn update(&self, iterables: &PyTuple) -> PyResult { + fn update(&self, iterables: Bound<'_, PyTuple>) -> PyResult { let mut inner = self.inner.clone(); for each in iterables { let iter = each.iter()?; for value in iter { - inner.insert_mut(Key::extract(value?)?.to_owned()); + inner.insert_mut(Key::extract_bound(&value?)?.to_owned()); } } Ok(HashTrieSetPy { inner }) @@ -924,10 +947,10 @@ impl From> for ListPy { } impl<'source> FromPyObject<'source> for ListPy { - fn extract(ob: &'source PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { let mut ret = List::new_sync(); - let reversed = PyModule::import(ob.py(), "builtins")?.getattr("reversed")?; - let rob: &PyIterator = reversed.call1((ob,))?.iter()?; + let reversed = PyModule::import_bound(ob.py(), "builtins")?.getattr("reversed")?; + let rob: Bound<'_, PyIterator> = reversed.call1((ob,))?.iter()?; for each in rob { ret.push_front_mut(each?.extract()?); } @@ -939,7 +962,7 @@ impl<'source> FromPyObject<'source> for ListPy { impl ListPy { #[new] #[pyo3(signature = (*elements))] - fn init(elements: &PyTuple) -> PyResult { + fn init(elements: &Bound<'_, PyTuple>) -> PyResult { let mut ret: ListPy; if elements.len() == 1 { ret = elements.get_item(0)?.extract()?; @@ -1005,9 +1028,9 @@ impl ListPy { } } - fn __reduce__(slf: PyRef) -> (&PyType, (Vec,)) { + fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec,)) { ( - ListPy::type_object(slf.py()), + ListPy::type_object_bound(slf.py()), (slf.inner.iter().cloned().collect(),), ) } @@ -1090,7 +1113,7 @@ impl From> for QueuePy { } impl<'source> FromPyObject<'source> for QueuePy { - fn extract(ob: &'source PyAny) -> PyResult { + fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { let mut ret = Queue::new_sync(); for each in ob.iter()? { ret.enqueue_mut(each?.extract()?); @@ -1103,7 +1126,7 @@ impl<'source> FromPyObject<'source> for QueuePy { impl QueuePy { #[new] #[pyo3(signature = (*elements))] - fn init(elements: &PyTuple, py: Python<'_>) -> PyResult { + fn init(elements: &Bound<'_, PyTuple>, py: Python<'_>) -> PyResult { let mut ret: QueuePy; if elements.len() == 1 { ret = elements.get_item(0)?.extract()?; @@ -1131,7 +1154,7 @@ impl QueuePy { } fn __hash__(&self, py: Python<'_>) -> PyResult { - let hash = PyModule::import(py, "builtins")?.getattr("hash")?; + let hash = PyModule::import_bound(py, "builtins")?.getattr("hash")?; let mut hasher = DefaultHasher::new(); for each in &self.inner { let n: i64 = hash.call1((each.into_py(py),))?.extract()?; @@ -1185,7 +1208,7 @@ impl QueuePy { self.inner.is_empty() } - fn enqueue(&self, value: &PyAny) -> Self { + fn enqueue(&self, value: Bound<'_, PyAny>) -> Self { QueuePy { inner: self.inner.enqueue(value.into()), } @@ -1202,7 +1225,7 @@ impl QueuePy { #[pymodule] #[pyo3(name = "rpds")] -fn rpds_py(py: Python, m: &PyModule) -> PyResult<()> { +fn rpds_py(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; @@ -1210,24 +1233,24 @@ fn rpds_py(py: Python, m: &PyModule) -> PyResult<()> { PyMapping::register::(py)?; - let abc = PyModule::import(py, "collections.abc")?; + let abc = PyModule::import_bound(py, "collections.abc")?; abc.getattr("Set")? - .call_method1("register", (HashTrieSetPy::type_object(py),))?; + .call_method1("register", (HashTrieSetPy::type_object_bound(py),))?; abc.getattr("MappingView")? - .call_method1("register", (KeysView::type_object(py),))?; + .call_method1("register", (KeysView::type_object_bound(py),))?; abc.getattr("MappingView")? - .call_method1("register", (ValuesView::type_object(py),))?; + .call_method1("register", (ValuesView::type_object_bound(py),))?; abc.getattr("MappingView")? - .call_method1("register", (ItemsView::type_object(py),))?; + .call_method1("register", (ItemsView::type_object_bound(py),))?; abc.getattr("KeysView")? - .call_method1("register", (KeysView::type_object(py),))?; + .call_method1("register", (KeysView::type_object_bound(py),))?; abc.getattr("ValuesView")? - .call_method1("register", (ValuesView::type_object(py),))?; + .call_method1("register", (ValuesView::type_object_bound(py),))?; abc.getattr("ItemsView")? - .call_method1("register", (ItemsView::type_object(py),))?; + .call_method1("register", (ItemsView::type_object_bound(py),))?; Ok(()) } From fd520b766eb505c00144fcf20a770a1ad2e84e5a Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Wed, 3 Jul 2024 16:34:51 +0100 Subject: [PATCH 02/11] Bump pyo3 from 0.20.3 to 0.22.0 --- Cargo.lock | 159 +++++++---------------------------------------------- Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 139 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57d2a8a..a383eff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,12 +18,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "cfg-if" version = "1.0.0" @@ -32,9 +26,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indoc" @@ -48,16 +42,6 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "memoffset" version = "0.9.0" @@ -73,29 +57,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - [[package]] name = "portable-atomic" version = "1.6.0" @@ -104,24 +65,24 @@ checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" -version = "0.20.3" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bdbb96d49157e65d45cc287af5f32ffadd5f4761438b527b055fb0d4bb8233" +checksum = "1962a33ed2a201c637fc14a4e0fd4e06e6edfdeee6a5fede0dab55507ad74cf7" dependencies = [ "cfg-if", "indoc", "libc", "memoffset", - "parking_lot", + "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", @@ -131,9 +92,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.20.3" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deaa5745de3f5231ce10517a1f5dd97d53e5a2fd77aa6b5842292085831d48d7" +checksum = "ab7164b2202753bd33afc7f90a10355a719aa973d1f94502c50d06f3488bc420" dependencies = [ "once_cell", "target-lexicon", @@ -141,9 +102,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.20.3" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b42531d03e08d4ef1f6e85a2ed422eb678b8cd62b762e53891c05faf0d4afa" +checksum = "c6424906ca49013c0829c5c1ed405e20e2da2dc78b82d198564880a704e6a7b7" dependencies = [ "libc", "pyo3-build-config", @@ -151,9 +112,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.20.3" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7305c720fa01b8055ec95e484a6eca7a83c841267f0dd5280f0c8b8551d2c158" +checksum = "82b2f19e153122d64afd8ce7aaa72f06a00f52e34e1d1e74b6d71baea396460a" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -163,9 +124,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.20.3" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7e9b68bb9c3149c5b0cade5d07f953d6d125eb4337723c4ccdb665f1f96185" +checksum = "dd698c04cac17cf0fe63d47790ab311b8b25542f5cb976b65c374035c50f1eef" dependencies = [ "heck", "proc-macro2", @@ -176,22 +137,13 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - [[package]] name = "rpds" version = "1.1.0" @@ -210,18 +162,6 @@ dependencies = [ "rpds", ] -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - [[package]] name = "static_assertions" version = "1.1.0" @@ -230,9 +170,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "2.0.32" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -241,9 +181,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.9" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "triomphe" @@ -262,60 +202,3 @@ name = "unindent" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/Cargo.toml b/Cargo.toml index 13012d0..72fd5af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,5 @@ rpds = "1.1.0" archery = "1.2.0" [dependencies.pyo3] -version = "0.20.3" +version = "0.22.0" features = ["extension-module"] From 47cd96c57cb18f46e55c1e3c1849e0740a9ad159 Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Thu, 4 Jul 2024 03:41:23 +0100 Subject: [PATCH 03/11] WIP --- noxfile.py | 2 +- src/lib.rs | 124 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 74 insertions(+), 52 deletions(-) diff --git a/noxfile.py b/noxfile.py index cd1da6d..4b81a5e 100644 --- a/noxfile.py +++ b/noxfile.py @@ -17,7 +17,7 @@ path.parent / f"{path.stem}.in" for path in REQUIREMENTS.values() ] -SUPPORTED = ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3.10"] +SUPPORTED = ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.10"] LATEST = "3.12" nox.options.sessions = [] diff --git a/src/lib.rs b/src/lib.rs index e49e870..79bb51f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ use std::hash::{Hash, Hasher}; use pyo3::exceptions::PyIndexError; use pyo3::pyclass::CompareOp; use pyo3::types::{PyDict, PyIterator, PyTuple, PyType}; -use pyo3::{exceptions::PyKeyError, types::PyMapping}; +use pyo3::{exceptions::PyKeyError, types::PyMapping, types::PyTupleMethods}; use pyo3::{prelude::*, AsPyPointer, PyTypeInfo}; use rpds::{ HashTrieMap, HashTrieMapSync, HashTrieSet, HashTrieSetSync, List, ListSync, Queue, QueueSync, @@ -51,7 +51,7 @@ impl<'source> FromPyObject<'source> for Key { fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { Ok(Key { hash: ob.hash()?, - inner: ob.unbind(), + inner: ob.clone().unbind(), }) } } @@ -89,7 +89,7 @@ impl<'source> FromPyObject<'source> for HashTrieMapPy { #[pymethods] impl HashTrieMapPy { #[new] - #[pyo3(signature = (value=None, **kwds))] + #[pyo3(signature = (value = None, * * kwds))] fn init(value: Option, kwds: Option<&Bound<'_, PyDict>>) -> PyResult { let mut map: HashTrieMapPy; if let Some(value) = value { @@ -151,20 +151,24 @@ impl HashTrieMapPy { match op { CompareOp::Eq => Ok((self.inner.size() == other.inner.size() && self - .inner - .iter() - .map(|(k1, v1)| (v1, other.inner.get(k1))) - .map(|(v1, v2)| PyAny::eq(v1.extract(py)?, v2)) - .all(|r| r.unwrap_or(false))) - .into_py(py)), + .inner + .iter() + .map(|(k1, v1)| (v1, other.inner.get(k1))) + .map(|(v1, v2)| { + v1.bind(py).eq(v2) + }) + .all(|r| r.unwrap_or(false))) + .into_py(py)), CompareOp::Ne => Ok((self.inner.size() != other.inner.size() || self - .inner - .iter() - .map(|(k1, v1)| (v1, other.inner.get(k1))) - .map(|(v1, v2)| PyAny::ne(v1.extract(py)?, v2)) - .all(|r| r.unwrap_or(true))) - .into_py(py)), + .inner + .iter() + .map(|(k1, v1)| (v1, other.inner.get(k1))) + .map(|(v1, v2)| { + v1.bind(py).eq(v2) + }) + .all(|r| r.unwrap_or(true))) + .into_py(py)), _ => Ok(py.NotImplemented()), } } @@ -173,9 +177,9 @@ impl HashTrieMapPy { ( HashTrieMapPy::type_object_bound(slf.py()), (slf.inner - .iter() - .map(|(k, v)| (k.clone(), v.clone())) - .collect(),), + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(),), ) } @@ -204,7 +208,7 @@ impl HashTrieMapPy { let value = val.unwrap_or_else(|| &none); for each in keys.iter()? { let key = Key::extract_bound(&each?)?.to_owned(); - inner.insert_mut(key, value.unbind()); + inner.insert_mut(key, value.clone().unbind()); } Ok(HashTrieMapPy { inner }) } @@ -261,7 +265,7 @@ impl HashTrieMapPy { } } - #[pyo3(signature = (*maps, **kwds))] + #[pyo3(signature = (* maps, * * kwds))] fn update( &self, maps: &Bound<'_, PyTuple>, @@ -502,12 +506,30 @@ struct ItemsView { inner: HashTrieMapSync, } +struct ItemViewQuery(Key, PyObject); + +impl<'source> FromPyObject<'source> for ItemViewQuery { + fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { + let tuple_bound: &Bound<'source, PyTuple> = ob.downcast()?; + + let k = tuple_bound.get_item(0)?; + let v = tuple_bound.get_item(1)?; + + Python::with_gil(|py| { + Ok(ItemViewQuery(Key::extract_bound(&k)?, v.into_py(py))) + }) + } +} + #[pymethods] impl ItemsView { - fn __contains__(slf: PyRef<'_, Self>, item: (Key, &PyAny)) -> PyResult { + fn __contains__(slf: PyRef<'_, Self>, item: ItemViewQuery) -> PyResult { if let Some(value) = slf.inner.get(&item.0) { - return item.1.eq(value); + return Python::with_gil(|py| { + item.1.bind(py).eq(value) + }); } + Ok(false) } @@ -527,7 +549,7 @@ impl ItemsView { return Ok(false); } for (k, v) in slf.inner.iter() { - if !other.contains((k.inner.to_owned(), v))? { + if !other.contains((k.inner.to_owned(), v.clone()))? { return Ok(false); } } @@ -582,7 +604,7 @@ impl ItemsView { let k = kv.get_item(0)?; match slf.inner.get(&Key::extract_bound(&k)?) { Some(value) => { - let pair = PyTuple::new_bound(py, [k, value.into_bound(py)]); + let pair = PyTuple::new_bound(py, [k, value.clone().into_bound(py)]); if !pair.eq(kv)? { return Ok(false); } @@ -603,7 +625,7 @@ impl ItemsView { let k = kv.get_item(0)?; match slf.inner.get(&Key::extract_bound(&k)?) { Some(value) => { - let pair = PyTuple::new_bound(py, [k, value.into_bound(py)]); + let pair = PyTuple::new_bound(py, [k, value.clone().into_bound(py)]); if !pair.eq(kv)? { return Ok(false); } @@ -641,7 +663,7 @@ impl ItemsView { let kv = each?; let k = kv.get_item(0)?; if let Some(value) = slf.inner.get(&Key::extract_bound(&k)?) { - let pair = PyTuple::new_bound(py, [k, value.into_bound(py)]); + let pair = PyTuple::new_bound(py, [k, value.clone().into_bound(py)]); if pair.eq(kv)? { inner.insert_mut(Key::extract_bound(&pair)?); } @@ -903,7 +925,7 @@ impl HashTrieSetPy { HashTrieSetPy { inner } } - #[pyo3(signature = (*iterables))] + #[pyo3(signature = (* iterables))] fn update(&self, iterables: Bound<'_, PyTuple>) -> PyResult { let mut inner = self.inner.clone(); for each in iterables { @@ -961,7 +983,7 @@ impl<'source> FromPyObject<'source> for ListPy { #[pymethods] impl ListPy { #[new] - #[pyo3(signature = (*elements))] + #[pyo3(signature = (* elements))] fn init(elements: &Bound<'_, PyTuple>) -> PyResult { let mut ret: ListPy; if elements.len() == 1 { @@ -998,20 +1020,20 @@ impl ListPy { match op { CompareOp::Eq => Ok((self.inner.len() == other.inner.len() && self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| PyAny::eq(e1.extract(py)?, e2)) - .all(|r| r.unwrap_or(false))) - .into_py(py)), + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).eq(e2)) + .all(|r| r.unwrap_or(false))) + .into_py(py)), CompareOp::Ne => Ok((self.inner.len() != other.inner.len() || self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| PyAny::ne(e1.extract(py)?, e2)) - .any(|r| r.unwrap_or(true))) - .into_py(py)), + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).eq(e2)) + .any(|r| r.unwrap_or(true))) + .into_py(py)), _ => Ok(py.NotImplemented()), } } @@ -1125,7 +1147,7 @@ impl<'source> FromPyObject<'source> for QueuePy { #[pymethods] impl QueuePy { #[new] - #[pyo3(signature = (*elements))] + #[pyo3(signature = (* elements))] fn init(elements: &Bound<'_, PyTuple>, py: Python<'_>) -> PyResult { let mut ret: QueuePy; if elements.len() == 1 { @@ -1146,11 +1168,11 @@ impl QueuePy { fn __eq__(&self, other: &Self, py: Python<'_>) -> bool { (self.inner.len() == other.inner.len()) && self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| PyAny::eq(e1.extract(py)?, e2)) - .all(|r| r.unwrap_or(false)) + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).eq(e2)) + .all(|r| r.unwrap_or(false)) } fn __hash__(&self, py: Python<'_>) -> PyResult { @@ -1166,11 +1188,11 @@ impl QueuePy { fn __ne__(&self, other: &Self, py: Python<'_>) -> bool { (self.inner.len() != other.inner.len()) || self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| PyAny::ne(e1.extract(py)?, e2)) - .any(|r| r.unwrap_or(true)) + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).eq(e2)) + .any(|r| r.unwrap_or(true)) } fn __iter__(slf: PyRef<'_, Self>) -> QueueIterator { From 4d4c71cf96c9085e271bb11a65644a55bb7e2946 Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Thu, 4 Jul 2024 02:22:47 +0100 Subject: [PATCH 04/11] WIP --- src/lib.rs | 198 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 127 insertions(+), 71 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 79bb51f..004791f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ use rpds::{ HashTrieMap, HashTrieMapSync, HashTrieSet, HashTrieSetSync, List, ListSync, Queue, QueueSync, }; -#[derive(Clone, Debug)] +#[derive(Debug)] struct Key { hash: isize, inner: PyObject, @@ -35,6 +35,21 @@ impl PartialEq for Key { } } +impl Key { + fn clone_ref(&self, py: Python<'_>) -> Self { + Key { + hash: self.hash, + inner: self.inner.clone_ref(py), + } + } +} + +impl Clone for Key { + fn clone(&self) -> Self { + Python::with_gil(|py| self.clone_ref(py)) + } +} + impl IntoPy for Key { fn into_py(self, py: Python<'_>) -> PyObject { self.inner.into_py(py) @@ -119,7 +134,9 @@ impl HashTrieMapPy { fn __getitem__(&self, key: Key) -> PyResult { match self.inner.get(&key) { - Some(value) => Ok(value.to_owned()), + Some(value) => Python::with_gil(|py| { + Ok(value.clone_ref(py)) + }), None => Err(PyKeyError::new_err(key)), } } @@ -165,7 +182,7 @@ impl HashTrieMapPy { .iter() .map(|(k1, v1)| (v1, other.inner.get(k1))) .map(|(v1, v2)| { - v1.bind(py).eq(v2) + v1.bind(py).ne(v2) }) .all(|r| r.unwrap_or(true))) .into_py(py)), @@ -174,13 +191,15 @@ impl HashTrieMapPy { } fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec<(Key, PyObject)>,)) { - ( - HashTrieMapPy::type_object_bound(slf.py()), - (slf.inner - .iter() - .map(|(k, v)| (k.clone(), v.clone())) - .collect(),), - ) + Python::with_gil(|py| { + ( + HashTrieMapPy::type_object_bound(slf.py()), + (slf.inner + .iter() + .map(|(k, v)| (k.clone_ref(py), v.clone_ref(py))) + .collect(),), + ) + }) } #[classmethod] @@ -207,7 +226,7 @@ impl HashTrieMapPy { let none = py.None().into_bound(py); let value = val.unwrap_or_else(|| &none); for each in keys.iter()? { - let key = Key::extract_bound(&each?)?.to_owned(); + let key = Key::extract_bound(&each?)?; inner.insert_mut(key, value.clone().unbind()); } Ok(HashTrieMapPy { inner }) @@ -215,7 +234,9 @@ impl HashTrieMapPy { fn get(&self, key: Key, default: Option) -> Option { if let Some(value) = self.inner.get(&key) { - Some(value.to_owned()) + Python::with_gil(|py| { + Some(value.clone_ref(py)) + }) } else { default } @@ -274,9 +295,11 @@ impl HashTrieMapPy { let mut inner = self.inner.clone(); for value in maps { let map = HashTrieMapPy::extract_bound(&value)?; - for (k, v) in &map.inner { - inner.insert_mut(k.to_owned(), v.to_owned()); - } + Python::with_gil(|py| { + for (k, v) in &map.inner { + inner.insert_mut(k.clone_ref(py), v.clone_ref(py)); + } + }) } if let Some(kwds) = kwds { for (k, v) in kwds { @@ -318,7 +341,7 @@ impl ValuesIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { let kv = slf.inner.iter().next()?; - let value = kv.1.to_owned(); + let value = Python::with_gil(|py| { kv.1.clone_ref(py) }); slf.inner = slf.inner.remove(kv.0); Some(value) } @@ -338,8 +361,12 @@ impl ItemsIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<(Key, PyObject)> { let kv = slf.inner.iter().next()?; let key = kv.0.to_owned(); - let value = kv.1.to_owned(); + let value = Python::with_gil(|py| { + kv.1.clone_ref(py) + }); + slf.inner = slf.inner.remove(kv.0); + Some((key, value)) } } @@ -373,12 +400,15 @@ impl KeysView { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { return Ok(false); } - for each in slf.inner.keys() { - if !other.contains(each.inner.to_owned())? { - return Ok(false); + + Python::with_gil(|py| { + for each in slf.inner.keys() { + if !other.contains(each.inner.clone_ref(py))? { + return Ok(false); + } } - } - Ok(true) + Ok(true) + }) } fn __le__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { @@ -386,12 +416,15 @@ impl KeysView { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? < slf.inner.size() { return Ok(false); } - for each in slf.inner.keys() { - if !other.contains(each.inner.to_owned())? { - return Ok(false); + + Python::with_gil(|py| { + for each in slf.inner.keys() { + if !other.contains(each.inner.clone_ref(py))? { + return Ok(false); + } } - } - Ok(true) + Ok(true) + }) } fn __gt__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { @@ -548,17 +581,19 @@ impl ItemsView { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? != slf.inner.size() { return Ok(false); } - for (k, v) in slf.inner.iter() { - if !other.contains((k.inner.to_owned(), v.clone()))? { - return Ok(false); + Python::with_gil(|py| { + for (k, v) in slf.inner.iter() { + if !other.contains((k.inner.clone_ref(py), v))? { + return Ok(false); + } } - } - Ok(true) + Ok(true) + }) } fn __repr__(&self, py: Python) -> String { let contents = self.inner.into_iter().map(|(k, v)| { - let tuple = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); + let tuple = PyTuple::new_bound(py, [k.inner.clone_ref(py), v.clone_ref(py)]); format!("{:?}", tuple) }); format!("items_view([{}])", contents.collect::>().join(", ")) @@ -570,7 +605,7 @@ impl ItemsView { return Ok(false); } for (k, v) in slf.inner.iter() { - let pair = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); + let pair = PyTuple::new_bound(py, [k.inner.clone_ref(py), v.clone_ref(py)]); // FIXME: needs to compare if !other.contains(pair)? { return Ok(false); @@ -585,7 +620,7 @@ impl ItemsView { return Ok(false); } for (k, v) in slf.inner.iter() { - let pair = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); + let pair = PyTuple::new_bound(py, [k.inner.clone_ref(py), v.clone_ref(py)]); // FIXME: needs to compare if !other.contains(pair)? { return Ok(false); @@ -604,7 +639,7 @@ impl ItemsView { let k = kv.get_item(0)?; match slf.inner.get(&Key::extract_bound(&k)?) { Some(value) => { - let pair = PyTuple::new_bound(py, [k, value.clone().into_bound(py)]); + let pair = PyTuple::new_bound(py, [k, value.bind(py).clone()]); if !pair.eq(kv)? { return Ok(false); } @@ -625,7 +660,7 @@ impl ItemsView { let k = kv.get_item(0)?; match slf.inner.get(&Key::extract_bound(&k)?) { Some(value) => { - let pair = PyTuple::new_bound(py, [k, value.clone().into_bound(py)]); + let pair = PyTuple::new_bound(py, [k, value.bind(py).clone()]); if !pair.eq(kv)? { return Ok(false); } @@ -663,7 +698,7 @@ impl ItemsView { let kv = each?; let k = kv.get_item(0)?; if let Some(value) = slf.inner.get(&Key::extract_bound(&k)?) { - let pair = PyTuple::new_bound(py, [k, value.clone().into_bound(py)]); + let pair = PyTuple::new_bound(py, [k, value.bind(py).clone()]); if pair.eq(kv)? { inner.insert_mut(Key::extract_bound(&pair)?); } @@ -680,7 +715,7 @@ impl ItemsView { // TODO: this is very inefficient, but again can't seem to get a HashTrieSet out of ourself let mut inner = HashTrieSet::new_sync(); for (k, v) in slf.inner.iter() { - let pair = PyTuple::new_bound(py, [k.inner.to_owned(), v.to_owned()]); + let pair = PyTuple::new_bound(py, [k.inner.clone_ref(py), v.clone_ref(py)]); inner.insert_mut(Key::extract_bound(&pair)?); } for each in other.iter()? { @@ -782,12 +817,14 @@ impl HashTrieSetPy { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { return Ok(false); } - for each in slf.inner.iter() { - if !other.contains(each.inner.to_owned())? { - return Ok(false); + Python::with_gil(|py| { + for each in slf.inner.iter() { + if !other.contains(each.inner.clone_ref(py))? { + return Ok(false); + } } - } - Ok(true) + Ok(true) + }) } fn __le__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { @@ -795,12 +832,14 @@ impl HashTrieSetPy { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? < slf.inner.size() { return Ok(false); } - for each in slf.inner.iter() { - if !other.contains(each.inner.to_owned())? { - return Ok(false); + Python::with_gil(|py| { + for each in slf.inner.iter() { + if !other.contains(each.inner.clone_ref(py))? { + return Ok(false); + } } - } - Ok(true) + Ok(true) + }) } fn __gt__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { @@ -832,7 +871,9 @@ impl HashTrieSetPy { fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec,)) { ( HashTrieSetPy::type_object_bound(slf.py()), - (slf.inner.iter().cloned().collect(),), + (Python::with_gil(|py| { + slf.inner.iter().map(|e| e.clone_ref(py)).collect() + }),), ) } @@ -881,11 +922,13 @@ impl HashTrieSetPy { larger = &other.inner; iter = self.inner.iter(); } - for value in iter { - if larger.contains(value) { - inner.insert_mut(value.to_owned()); + Python::with_gil(|py| { + for value in iter { + if larger.contains(value) { + inner.insert_mut(value.clone_ref(py)); + } } - } + }); HashTrieSetPy { inner } } @@ -899,13 +942,15 @@ impl HashTrieSetPy { inner = other.inner.clone(); iter = self.inner.iter(); } - for value in iter { - if inner.contains(value) { - inner.remove_mut(value); - } else { - inner.insert_mut(value.to_owned()); + Python::with_gil(|py| { + for value in iter { + if inner.contains(value) { + inner.remove_mut(value); + } else { + inner.insert_mut(value.clone_ref(py)); + } } - } + }); HashTrieSetPy { inner } } @@ -919,9 +964,11 @@ impl HashTrieSetPy { inner = other.inner.clone(); iter = self.inner.iter(); } - for value in iter { - inner.insert_mut(value.to_owned()); - } + Python::with_gil(|py| { + for value in iter { + inner.insert_mut(value.clone_ref(py)); + } + }); HashTrieSetPy { inner } } @@ -1031,7 +1078,7 @@ impl ListPy { .inner .iter() .zip(other.inner.iter()) - .map(|(e1, e2)| e1.bind(py).eq(e2)) + .map(|(e1, e2)| e1.bind(py).ne(e2)) .any(|r| r.unwrap_or(true))) .into_py(py)), _ => Ok(py.NotImplemented()), @@ -1053,7 +1100,9 @@ impl ListPy { fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec,)) { ( ListPy::type_object_bound(slf.py()), - (slf.inner.iter().cloned().collect(),), + (Python::with_gil(|py| { + slf.inner.iter().map(|e| e.clone_ref(py)).collect() + }),), ) } @@ -1098,8 +1147,13 @@ impl ListIterator { } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { - let first = slf.inner.first()?.to_owned(); + let first_op = slf.inner.first()?; + let first = Python::with_gil(|py| { + first_op.clone_ref(py) + }); + slf.inner = slf.inner.drop_first()?; + Some(first) } } @@ -1116,7 +1170,10 @@ impl QueueIterator { } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { - let first = slf.inner.peek()?.to_owned(); + let first_op = slf.inner.peek()?; + let first = Python::with_gil(|py| { + first_op.clone_ref(py) + }); slf.inner = slf.inner.dequeue()?; Some(first) } @@ -1191,7 +1248,7 @@ impl QueuePy { .inner .iter() .zip(other.inner.iter()) - .map(|(e1, e2)| e1.bind(py).eq(e2)) + .map(|(e1, e2)| e1.bind(py).ne(e2)) .any(|r| r.unwrap_or(true)) } @@ -1207,8 +1264,7 @@ impl QueuePy { fn __repr__(&self, py: Python) -> String { let contents = self.inner.into_iter().map(|k| { - k.clone() - .into_py(py) + k.into_py(py) .call_method0(py, "__repr__") .and_then(|r| r.extract(py)) .unwrap_or("".to_owned()) @@ -1219,7 +1275,7 @@ impl QueuePy { #[getter] fn peek(&self) -> PyResult { if let Some(peeked) = self.inner.peek() { - Ok(peeked.to_owned()) + Ok(Python::with_gil(|py| peeked.clone_ref(py))) } else { Err(PyIndexError::new_err("peeked an empty queue")) } From 8ecb460fe14727cf3fdb8192aeb552da272c8d37 Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Thu, 4 Jul 2024 05:55:18 +0100 Subject: [PATCH 05/11] Fix formatting --- src/lib.rs | 118 +++++++++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 68 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 004791f..67f2af7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,7 +104,7 @@ impl<'source> FromPyObject<'source> for HashTrieMapPy { #[pymethods] impl HashTrieMapPy { #[new] - #[pyo3(signature = (value = None, * * kwds))] + #[pyo3(signature = (value=None, ** kwds))] fn init(value: Option, kwds: Option<&Bound<'_, PyDict>>) -> PyResult { let mut map: HashTrieMapPy; if let Some(value) = value { @@ -134,9 +134,7 @@ impl HashTrieMapPy { fn __getitem__(&self, key: Key) -> PyResult { match self.inner.get(&key) { - Some(value) => Python::with_gil(|py| { - Ok(value.clone_ref(py)) - }), + Some(value) => Python::with_gil(|py| Ok(value.clone_ref(py))), None => Err(PyKeyError::new_err(key)), } } @@ -168,24 +166,20 @@ impl HashTrieMapPy { match op { CompareOp::Eq => Ok((self.inner.size() == other.inner.size() && self - .inner - .iter() - .map(|(k1, v1)| (v1, other.inner.get(k1))) - .map(|(v1, v2)| { - v1.bind(py).eq(v2) - }) - .all(|r| r.unwrap_or(false))) - .into_py(py)), + .inner + .iter() + .map(|(k1, v1)| (v1, other.inner.get(k1))) + .map(|(v1, v2)| v1.bind(py).eq(v2)) + .all(|r| r.unwrap_or(false))) + .into_py(py)), CompareOp::Ne => Ok((self.inner.size() != other.inner.size() || self - .inner - .iter() - .map(|(k1, v1)| (v1, other.inner.get(k1))) - .map(|(v1, v2)| { - v1.bind(py).ne(v2) - }) - .all(|r| r.unwrap_or(true))) - .into_py(py)), + .inner + .iter() + .map(|(k1, v1)| (v1, other.inner.get(k1))) + .map(|(v1, v2)| v1.bind(py).ne(v2)) + .all(|r| r.unwrap_or(true))) + .into_py(py)), _ => Ok(py.NotImplemented()), } } @@ -195,9 +189,9 @@ impl HashTrieMapPy { ( HashTrieMapPy::type_object_bound(slf.py()), (slf.inner - .iter() - .map(|(k, v)| (k.clone_ref(py), v.clone_ref(py))) - .collect(),), + .iter() + .map(|(k, v)| (k.clone_ref(py), v.clone_ref(py))) + .collect(),), ) }) } @@ -234,9 +228,7 @@ impl HashTrieMapPy { fn get(&self, key: Key, default: Option) -> Option { if let Some(value) = self.inner.get(&key) { - Python::with_gil(|py| { - Some(value.clone_ref(py)) - }) + Python::with_gil(|py| Some(value.clone_ref(py))) } else { default } @@ -286,7 +278,7 @@ impl HashTrieMapPy { } } - #[pyo3(signature = (* maps, * * kwds))] + #[pyo3(signature = (*maps, **kwds))] fn update( &self, maps: &Bound<'_, PyTuple>, @@ -341,7 +333,7 @@ impl ValuesIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { let kv = slf.inner.iter().next()?; - let value = Python::with_gil(|py| { kv.1.clone_ref(py) }); + let value = Python::with_gil(|py| kv.1.clone_ref(py)); slf.inner = slf.inner.remove(kv.0); Some(value) } @@ -361,9 +353,7 @@ impl ItemsIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<(Key, PyObject)> { let kv = slf.inner.iter().next()?; let key = kv.0.to_owned(); - let value = Python::with_gil(|py| { - kv.1.clone_ref(py) - }); + let value = Python::with_gil(|py| kv.1.clone_ref(py)); slf.inner = slf.inner.remove(kv.0); @@ -548,9 +538,7 @@ impl<'source> FromPyObject<'source> for ItemViewQuery { let k = tuple_bound.get_item(0)?; let v = tuple_bound.get_item(1)?; - Python::with_gil(|py| { - Ok(ItemViewQuery(Key::extract_bound(&k)?, v.into_py(py))) - }) + Python::with_gil(|py| Ok(ItemViewQuery(Key::extract_bound(&k)?, v.into_py(py)))) } } @@ -558,9 +546,7 @@ impl<'source> FromPyObject<'source> for ItemViewQuery { impl ItemsView { fn __contains__(slf: PyRef<'_, Self>, item: ItemViewQuery) -> PyResult { if let Some(value) = slf.inner.get(&item.0) { - return Python::with_gil(|py| { - item.1.bind(py).eq(value) - }); + return Python::with_gil(|py| item.1.bind(py).eq(value)); } Ok(false) @@ -972,7 +958,7 @@ impl HashTrieSetPy { HashTrieSetPy { inner } } - #[pyo3(signature = (* iterables))] + #[pyo3(signature = (*iterables))] fn update(&self, iterables: Bound<'_, PyTuple>) -> PyResult { let mut inner = self.inner.clone(); for each in iterables { @@ -1030,7 +1016,7 @@ impl<'source> FromPyObject<'source> for ListPy { #[pymethods] impl ListPy { #[new] - #[pyo3(signature = (* elements))] + #[pyo3(signature = (*elements))] fn init(elements: &Bound<'_, PyTuple>) -> PyResult { let mut ret: ListPy; if elements.len() == 1 { @@ -1067,20 +1053,20 @@ impl ListPy { match op { CompareOp::Eq => Ok((self.inner.len() == other.inner.len() && self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| e1.bind(py).eq(e2)) - .all(|r| r.unwrap_or(false))) - .into_py(py)), + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).eq(e2)) + .all(|r| r.unwrap_or(false))) + .into_py(py)), CompareOp::Ne => Ok((self.inner.len() != other.inner.len() || self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| e1.bind(py).ne(e2)) - .any(|r| r.unwrap_or(true))) - .into_py(py)), + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).ne(e2)) + .any(|r| r.unwrap_or(true))) + .into_py(py)), _ => Ok(py.NotImplemented()), } } @@ -1148,9 +1134,7 @@ impl ListIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { let first_op = slf.inner.first()?; - let first = Python::with_gil(|py| { - first_op.clone_ref(py) - }); + let first = Python::with_gil(|py| first_op.clone_ref(py)); slf.inner = slf.inner.drop_first()?; @@ -1171,9 +1155,7 @@ impl QueueIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { let first_op = slf.inner.peek()?; - let first = Python::with_gil(|py| { - first_op.clone_ref(py) - }); + let first = Python::with_gil(|py| first_op.clone_ref(py)); slf.inner = slf.inner.dequeue()?; Some(first) } @@ -1204,7 +1186,7 @@ impl<'source> FromPyObject<'source> for QueuePy { #[pymethods] impl QueuePy { #[new] - #[pyo3(signature = (* elements))] + #[pyo3(signature = (*elements))] fn init(elements: &Bound<'_, PyTuple>, py: Python<'_>) -> PyResult { let mut ret: QueuePy; if elements.len() == 1 { @@ -1225,11 +1207,11 @@ impl QueuePy { fn __eq__(&self, other: &Self, py: Python<'_>) -> bool { (self.inner.len() == other.inner.len()) && self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| e1.bind(py).eq(e2)) - .all(|r| r.unwrap_or(false)) + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).eq(e2)) + .all(|r| r.unwrap_or(false)) } fn __hash__(&self, py: Python<'_>) -> PyResult { @@ -1245,11 +1227,11 @@ impl QueuePy { fn __ne__(&self, other: &Self, py: Python<'_>) -> bool { (self.inner.len() != other.inner.len()) || self - .inner - .iter() - .zip(other.inner.iter()) - .map(|(e1, e2)| e1.bind(py).ne(e2)) - .any(|r| r.unwrap_or(true)) + .inner + .iter() + .zip(other.inner.iter()) + .map(|(e1, e2)| e1.bind(py).ne(e2)) + .any(|r| r.unwrap_or(true)) } fn __iter__(slf: PyRef<'_, Self>) -> QueueIterator { From 19842001cb5155740099a67eac22bd08e621e55b Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Fri, 5 Jul 2024 00:34:48 +0100 Subject: [PATCH 06/11] Remove redundant Python::with_gil calls --- src/lib.rs | 106 ++++++++++++++++++++++------------------------------- 1 file changed, 44 insertions(+), 62 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 67f2af7..98463f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -185,15 +185,13 @@ impl HashTrieMapPy { } fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec<(Key, PyObject)>,)) { - Python::with_gil(|py| { - ( - HashTrieMapPy::type_object_bound(slf.py()), - (slf.inner - .iter() - .map(|(k, v)| (k.clone_ref(py), v.clone_ref(py))) - .collect(),), - ) - }) + ( + HashTrieMapPy::type_object_bound(slf.py()), + (slf.inner + .iter() + .map(|(k, v)| (k.clone_ref(slf.py()), v.clone_ref(slf.py()))) + .collect(),), + ) } #[classmethod] @@ -218,7 +216,7 @@ impl HashTrieMapPy { ) -> PyResult { let mut inner = HashTrieMap::new_sync(); let none = py.None().into_bound(py); - let value = val.unwrap_or_else(|| &none); + let value = val.unwrap_or(&none); for each in keys.iter()? { let key = Key::extract_bound(&each?)?; inner.insert_mut(key, value.clone().unbind()); @@ -287,11 +285,9 @@ impl HashTrieMapPy { let mut inner = self.inner.clone(); for value in maps { let map = HashTrieMapPy::extract_bound(&value)?; - Python::with_gil(|py| { - for (k, v) in &map.inner { - inner.insert_mut(k.clone_ref(py), v.clone_ref(py)); - } - }) + for (k, v) in &map.inner { + inner.insert_mut(k.clone_ref(value.py()), v.clone_ref(value.py())); + } } if let Some(kwds) = kwds { for (k, v) in kwds { @@ -333,7 +329,7 @@ impl ValuesIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { let kv = slf.inner.iter().next()?; - let value = Python::with_gil(|py| kv.1.clone_ref(py)); + let value = kv.1.clone_ref(slf.py()); slf.inner = slf.inner.remove(kv.0); Some(value) } @@ -353,7 +349,7 @@ impl ItemsIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<(Key, PyObject)> { let kv = slf.inner.iter().next()?; let key = kv.0.to_owned(); - let value = Python::with_gil(|py| kv.1.clone_ref(py)); + let value = kv.1.clone_ref(slf.py()); slf.inner = slf.inner.remove(kv.0); @@ -391,14 +387,12 @@ impl KeysView { return Ok(false); } - Python::with_gil(|py| { - for each in slf.inner.keys() { - if !other.contains(each.inner.clone_ref(py))? { - return Ok(false); - } + for each in slf.inner.keys() { + if !other.contains(each.inner.clone_ref(slf.py()))? { + return Ok(false); } - Ok(true) - }) + } + Ok(true) } fn __le__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { @@ -407,14 +401,12 @@ impl KeysView { return Ok(false); } - Python::with_gil(|py| { - for each in slf.inner.keys() { - if !other.contains(each.inner.clone_ref(py))? { - return Ok(false); - } + for each in slf.inner.keys() { + if !other.contains(each.inner.clone_ref(slf.py()))? { + return Ok(false); } - Ok(true) - }) + } + Ok(true) } fn __gt__(slf: PyRef<'_, Self>, other: &Bound<'_, PyAny>, py: Python) -> PyResult { @@ -538,7 +530,7 @@ impl<'source> FromPyObject<'source> for ItemViewQuery { let k = tuple_bound.get_item(0)?; let v = tuple_bound.get_item(1)?; - Python::with_gil(|py| Ok(ItemViewQuery(Key::extract_bound(&k)?, v.into_py(py)))) + Ok(ItemViewQuery(Key::extract_bound(&k)?, v.into_py(ob.py()))) } } @@ -546,7 +538,7 @@ impl<'source> FromPyObject<'source> for ItemViewQuery { impl ItemsView { fn __contains__(slf: PyRef<'_, Self>, item: ItemViewQuery) -> PyResult { if let Some(value) = slf.inner.get(&item.0) { - return Python::with_gil(|py| item.1.bind(py).eq(value)); + return item.1.bind(slf.py()).eq(value); } Ok(false) @@ -567,14 +559,12 @@ impl ItemsView { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? != slf.inner.size() { return Ok(false); } - Python::with_gil(|py| { - for (k, v) in slf.inner.iter() { - if !other.contains((k.inner.clone_ref(py), v))? { - return Ok(false); - } + for (k, v) in slf.inner.iter() { + if !other.contains((k.inner.clone_ref(slf.py()), v))? { + return Ok(false); } - Ok(true) - }) + } + Ok(true) } fn __repr__(&self, py: Python) -> String { @@ -803,14 +793,12 @@ impl HashTrieSetPy { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? <= slf.inner.size() { return Ok(false); } - Python::with_gil(|py| { - for each in slf.inner.iter() { - if !other.contains(each.inner.clone_ref(py))? { - return Ok(false); - } + for each in slf.inner.iter() { + if !other.contains(each.inner.clone_ref(py))? { + return Ok(false); } - Ok(true) - }) + } + Ok(true) } fn __le__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { @@ -818,14 +806,12 @@ impl HashTrieSetPy { if !other.is_instance(&abc.getattr("Set")?)? || other.len()? < slf.inner.size() { return Ok(false); } - Python::with_gil(|py| { - for each in slf.inner.iter() { - if !other.contains(each.inner.clone_ref(py))? { - return Ok(false); - } + for each in slf.inner.iter() { + if !other.contains(each.inner.clone_ref(slf.py()))? { + return Ok(false); } - Ok(true) - }) + } + Ok(true) } fn __gt__(slf: PyRef<'_, Self>, other: Bound<'_, PyAny>, py: Python) -> PyResult { @@ -857,9 +843,7 @@ impl HashTrieSetPy { fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec,)) { ( HashTrieSetPy::type_object_bound(slf.py()), - (Python::with_gil(|py| { - slf.inner.iter().map(|e| e.clone_ref(py)).collect() - }),), + (slf.inner.iter().map(|e| e.clone_ref(slf.py())).collect(),), ) } @@ -1086,9 +1070,7 @@ impl ListPy { fn __reduce__(slf: PyRef) -> (Bound<'_, PyType>, (Vec,)) { ( ListPy::type_object_bound(slf.py()), - (Python::with_gil(|py| { - slf.inner.iter().map(|e| e.clone_ref(py)).collect() - }),), + (slf.inner.iter().map(|e| e.clone_ref(slf.py())).collect(),), ) } @@ -1134,7 +1116,7 @@ impl ListIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { let first_op = slf.inner.first()?; - let first = Python::with_gil(|py| first_op.clone_ref(py)); + let first = first_op.clone_ref(slf.py()); slf.inner = slf.inner.drop_first()?; @@ -1155,7 +1137,7 @@ impl QueueIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { let first_op = slf.inner.peek()?; - let first = Python::with_gil(|py| first_op.clone_ref(py)); + let first = first_op.clone_ref(slf.py()); slf.inner = slf.inner.dequeue()?; Some(first) } From d462f1d84da927d658c946f66ee7d85a625fac2c Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Fri, 5 Jul 2024 00:37:44 +0100 Subject: [PATCH 07/11] Fix clippy warnings --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 98463f7..b2f729d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -208,6 +208,7 @@ impl HashTrieMapPy { } #[classmethod] + #[pyo3(signature = (keys, val=None))] fn fromkeys( _cls: &Bound<'_, PyType>, keys: &Bound<'_, PyAny>, @@ -224,6 +225,7 @@ impl HashTrieMapPy { Ok(HashTrieMapPy { inner }) } + #[pyo3(signature = (key, default=None))] fn get(&self, key: Key, default: Option) -> Option { if let Some(value) = self.inner.get(&key) { Python::with_gil(|py| Some(value.clone_ref(py))) @@ -721,6 +723,7 @@ impl<'source> FromPyObject<'source> for HashTrieSetPy { #[pymethods] impl HashTrieSetPy { #[new] + #[pyo3(signature = (value=None))] fn init(value: Option) -> Self { if let Some(value) = value { value From 5e986afc1734da575aa96965a28c8208448bb07d Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Fri, 5 Jul 2024 00:38:35 +0100 Subject: [PATCH 08/11] Add Python 3.13 to GitHub actions CI --- .github/workflows/CI.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9037d02..35eaadd 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -63,6 +63,7 @@ jobs: 3.10 3.11 3.12 + 3.13 pypy3.10 allow-prereleases: true - name: Set up nox From 6c7cdd241f149676ee5057a3c2dae6efdc8efb50 Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Fri, 5 Jul 2024 15:58:11 +0100 Subject: [PATCH 09/11] Remove redundant Python::wiht_gil calls --- src/lib.rs | 80 +++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b2f729d..beef11b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,12 +44,6 @@ impl Key { } } -impl Clone for Key { - fn clone(&self) -> Self { - Python::with_gil(|py| self.clone_ref(py)) - } -} - impl IntoPy for Key { fn into_py(self, py: Python<'_>) -> PyObject { self.inner.into_py(py) @@ -132,9 +126,9 @@ impl HashTrieMapPy { } } - fn __getitem__(&self, key: Key) -> PyResult { + fn __getitem__(&self, key: Key, py: Python) -> PyResult { match self.inner.get(&key) { - Some(value) => Python::with_gil(|py| Ok(value.clone_ref(py))), + Some(value) => Ok(value.clone_ref(py)), None => Err(PyKeyError::new_err(key)), } } @@ -226,9 +220,9 @@ impl HashTrieMapPy { } #[pyo3(signature = (key, default=None))] - fn get(&self, key: Key, default: Option) -> Option { + fn get(&self, key: Key, default: Option, py: Python) -> Option { if let Some(value) = self.inner.get(&key) { - Python::with_gil(|py| Some(value.clone_ref(py))) + Some(value.clone_ref(py)) } else { default } @@ -312,7 +306,7 @@ impl KeysIterator { } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { - let first = slf.inner.keys().next()?.to_owned(); + let first = slf.inner.keys().next()?.clone_ref(slf.py()); slf.inner = slf.inner.remove(&first); Some(first) } @@ -350,7 +344,7 @@ impl ItemsIterator { fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<(Key, PyObject)> { let kv = slf.inner.iter().next()?; - let key = kv.0.to_owned(); + let key = kv.0.clone_ref(slf.py()); let value = kv.1.clone_ref(slf.py()); slf.inner = slf.inner.remove(kv.0); @@ -457,7 +451,7 @@ impl KeysView { fn __repr__(&self, py: Python) -> String { let contents = self.inner.into_iter().map(|(k, _)| { - k.clone() + k.clone_ref(py) .inner .into_py(py) .call_method0(py, "__repr__") @@ -738,20 +732,20 @@ impl HashTrieSetPy { self.inner.contains(&key) } - fn __and__(&self, other: &Self) -> Self { - self.intersection(other) + fn __and__(&self, other: &Self, py: Python) -> Self { + self.intersection(other, py) } - fn __or__(&self, other: &Self) -> Self { - self.union(other) + fn __or__(&self, other: &Self, py: Python) -> Self { + self.union(other, py) } fn __sub__(&self, other: &Self) -> Self { self.difference(other) } - fn __xor__(&self, other: &Self) -> Self { - self.symmetric_difference(other) + fn __xor__(&self, other: &Self, py: Python) -> Self { + self.symmetric_difference(other, py) } fn __iter__(slf: PyRef<'_, Self>) -> SetIterator { @@ -766,7 +760,7 @@ impl HashTrieSetPy { fn __repr__(&self, py: Python) -> String { let contents = self.inner.into_iter().map(|k| { - k.clone() + k.clone_ref(py) .into_py(py) .call_method0(py, "__repr__") .and_then(|r| r.extract(py)) @@ -884,7 +878,7 @@ impl HashTrieSetPy { HashTrieSetPy { inner } } - fn intersection(&self, other: &Self) -> HashTrieSetPy { + fn intersection(&self, other: &Self, py: Python) -> HashTrieSetPy { let mut inner: HashTrieSetSync = HashTrieSet::new_sync(); let larger: &HashTrieSetSync; let iter; @@ -895,17 +889,15 @@ impl HashTrieSetPy { larger = &other.inner; iter = self.inner.iter(); } - Python::with_gil(|py| { - for value in iter { - if larger.contains(value) { - inner.insert_mut(value.clone_ref(py)); - } + for value in iter { + if larger.contains(value) { + inner.insert_mut(value.clone_ref(py)); } - }); + } HashTrieSetPy { inner } } - fn symmetric_difference(&self, other: &Self) -> HashTrieSetPy { + fn symmetric_difference(&self, other: &Self, py: Python) -> HashTrieSetPy { let mut inner: HashTrieSetSync; let iter; if self.inner.size() > other.inner.size() { @@ -915,19 +907,17 @@ impl HashTrieSetPy { inner = other.inner.clone(); iter = self.inner.iter(); } - Python::with_gil(|py| { - for value in iter { - if inner.contains(value) { - inner.remove_mut(value); - } else { - inner.insert_mut(value.clone_ref(py)); - } + for value in iter { + if inner.contains(value) { + inner.remove_mut(value); + } else { + inner.insert_mut(value.clone_ref(py)); } - }); + } HashTrieSetPy { inner } } - fn union(&self, other: &Self) -> HashTrieSetPy { + fn union(&self, other: &Self, py: Python) -> HashTrieSetPy { let mut inner: HashTrieSetSync; let iter; if self.inner.size() > other.inner.size() { @@ -937,11 +927,9 @@ impl HashTrieSetPy { inner = other.inner.clone(); iter = self.inner.iter(); } - Python::with_gil(|py| { - for value in iter { - inner.insert_mut(value.clone_ref(py)); - } - }); + for value in iter { + inner.insert_mut(value.clone_ref(py)); + } HashTrieSetPy { inner } } @@ -951,7 +939,7 @@ impl HashTrieSetPy { for each in iterables { let iter = each.iter()?; for value in iter { - inner.insert_mut(Key::extract_bound(&value?)?.to_owned()); + inner.insert_mut(Key::extract_bound(&value?)?); } } Ok(HashTrieSetPy { inner }) @@ -970,7 +958,7 @@ impl SetIterator { } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { - let first = slf.inner.iter().next()?.to_owned(); + let first = slf.inner.iter().next()?.clone_ref(slf.py()); slf.inner = slf.inner.remove(&first); Some(first) } @@ -1240,9 +1228,9 @@ impl QueuePy { } #[getter] - fn peek(&self) -> PyResult { + fn peek(&self, py: Python) -> PyResult { if let Some(peeked) = self.inner.peek() { - Ok(Python::with_gil(|py| peeked.clone_ref(py))) + Ok(peeked.clone_ref(py)) } else { Err(PyIndexError::new_err("peeked an empty queue")) } From 0c600b8dd0e959dde6f0c18e32447ec447ffc1fa Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Sun, 7 Jul 2024 00:32:54 +0100 Subject: [PATCH 10/11] Use #[derive(FromPyObject)] instead of manual impl --- src/lib.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index beef11b..8dae4aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -517,19 +517,9 @@ struct ItemsView { inner: HashTrieMapSync, } +#[derive(FromPyObject)] struct ItemViewQuery(Key, PyObject); -impl<'source> FromPyObject<'source> for ItemViewQuery { - fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { - let tuple_bound: &Bound<'source, PyTuple> = ob.downcast()?; - - let k = tuple_bound.get_item(0)?; - let v = tuple_bound.get_item(1)?; - - Ok(ItemViewQuery(Key::extract_bound(&k)?, v.into_py(ob.py()))) - } -} - #[pymethods] impl ItemsView { fn __contains__(slf: PyRef<'_, Self>, item: ItemViewQuery) -> PyResult { From 605215e7d41c4eb504d9b40bf101b828baf1a531 Mon Sep 17 00:00:00 2001 From: Heyuan Zeng Date: Sun, 7 Jul 2024 23:08:00 +0100 Subject: [PATCH 11/11] Update PyO3 from 0.22.0 to 0.22.1 --- Cargo.lock | 48 ++++++++++++++++++++++++------------------------ Cargo.toml | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a383eff..03a3cb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "cfg-if" @@ -32,9 +32,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indoc" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "libc" @@ -44,18 +44,18 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "memoffset" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "portable-atomic" @@ -74,9 +74,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1962a33ed2a201c637fc14a4e0fd4e06e6edfdeee6a5fede0dab55507ad74cf7" +checksum = "4e99090d12f6182924499253aaa1e73bf15c69cea8d2774c3c781e35badc3548" dependencies = [ "cfg-if", "indoc", @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab7164b2202753bd33afc7f90a10355a719aa973d1f94502c50d06f3488bc420" +checksum = "7879eb018ac754bba32cb0eec7526391c02c14a093121857ed09fbf1d1057d41" dependencies = [ "once_cell", "target-lexicon", @@ -102,9 +102,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6424906ca49013c0829c5c1ed405e20e2da2dc78b82d198564880a704e6a7b7" +checksum = "ce2baa5559a411fc1cf519295f24c34b53d5d725818bc96b5abf94762da09041" dependencies = [ "libc", "pyo3-build-config", @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2f19e153122d64afd8ce7aaa72f06a00f52e34e1d1e74b6d71baea396460a" +checksum = "049621c20a23f2def20f4fe67978d1da8d8a883d64b9c21362f3b776e254edc7" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -124,9 +124,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd698c04cac17cf0fe63d47790ab311b8b25542f5cb976b65c374035c50f1eef" +checksum = "0e969ee2e025435f1819d31a275ba4bb9cbbdf3ac535227fdbd85b9322ffe144" dependencies = [ "heck", "proc-macro2", @@ -170,9 +170,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "2.0.68" +version = "2.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6" dependencies = [ "proc-macro2", "quote", @@ -187,15 +187,15 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "triomphe" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unindent" diff --git a/Cargo.toml b/Cargo.toml index 72fd5af..a68c6d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,5 @@ rpds = "1.1.0" archery = "1.2.0" [dependencies.pyo3] -version = "0.22.0" +version = "0.22.1" features = ["extension-module"]