diff --git a/Cargo.toml b/Cargo.toml index 57741ee..e245050 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ anyhow = "1.0.82" chrono = "0.4.38" indexmap = "2.2.6" nom = "7.1.3" -pyo3 = { version = "=0.20.3", features = ["chrono"] } +pyo3 = { version = "=0.22.2", features = ["chrono"] } rayon = "1.10.0" regex = "1.10.4" serde = { version = "1.0.200", features = ["derive"] } diff --git a/src/config.rs b/src/config.rs index c52697d..7c44853 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,7 +11,7 @@ use std::path::PathBuf; use crate::fsutil::to_lexical_normal; /// Flags to change reclass-rs behavior to be compaible with Python reclass -#[pyclass] +#[pyclass(eq, eq_int)] #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub enum CompatFlag { /// This flag enables Python Reclass-compatible rendering of fields `path` and `parts` in @@ -137,19 +137,18 @@ impl Config { let vstr = vstr.trim(); match k { "nodes_uri" => { - let npath = cfg_path + cfg_path .with_file_name(vstr) .to_str() .ok_or(anyhow!("Can't create nodes path from config file"))? - .to_owned(); - self.nodes_path = npath; + .clone_into(&mut self.nodes_path); } "classes_uri" => { - self.classes_path = cfg_path + cfg_path .with_file_name(vstr) .to_str() .ok_or(anyhow!("Can't create nodes path from config file"))? - .to_owned(); + .clone_into(&mut self.classes_path); } "ignore_class_notfound" => { self.ignore_class_notfound = v.as_bool().ok_or(anyhow!( @@ -281,9 +280,9 @@ impl Config { #[classmethod] #[pyo3(signature = (inventory_path, config, verbose=false))] fn from_dict( - _cls: &PyType, + _cls: &Bound<'_, PyType>, inventory_path: &str, - config: &PyDict, + config: &Bound<'_, PyDict>, verbose: bool, ) -> PyResult { let mut cfg = Config::new(Some(inventory_path), None, None, None).map_err(|e| { diff --git a/src/inventory.rs b/src/inventory.rs index 96b9551..a5d9f68 100644 --- a/src/inventory.rs +++ b/src/inventory.rs @@ -77,16 +77,16 @@ impl Inventory { /// The structure of the returned dict should match Python reclass the structure of the dict /// returned by Python reclass's `inventory()` method. fn as_dict(&self, py: Python<'_>) -> PyResult> { - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); dict.set_item("applications", self.applications.clone().into_py(py))?; dict.set_item("classes", self.classes.clone().into_py(py))?; - let nodes_dict = PyDict::new(py); + let nodes_dict = PyDict::new_bound(py); for (name, info) in &self.nodes { nodes_dict.set_item(name, info.as_dict(py)?)?; } dict.set_item("nodes", nodes_dict)?; - let reclass_dict = PyDict::new(py); + let reclass_dict = PyDict::new_bound(py); let ts = Local::now(); reclass_dict.set_item("timestamp", ts.format("%c").to_string())?; dict.set_item("__reclass__", reclass_dict)?; diff --git a/src/lib.rs b/src/lib.rs index 7519297..2b1b5b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -295,7 +295,7 @@ impl Reclass { #[classmethod] #[pyo3(signature = (inventory_path, config_file, verbose=false))] fn from_config_file( - cls: &PyType, + cls: &Bound<'_, PyType>, inventory_path: &str, config_file: &str, verbose: bool, @@ -311,7 +311,7 @@ impl Reclass { /// /// Returns a `Reclass` instance or raises a `ValueError` #[classmethod] - fn from_config(_cls: &PyType, config: Config) -> PyResult { + fn from_config(_cls: &Bound<'_, PyType>, config: Config) -> PyResult { let r = Self::new_from_config(config).map_err(|e| PyValueError::new_err(format!("{e}")))?; Ok(r) } @@ -339,7 +339,7 @@ impl Reclass { /// Note that this method should only be called once and will print a diagnostic message if /// called again. #[classmethod] - pub fn set_thread_count(_cls: &PyType, count: usize) { + pub fn set_thread_count(_cls: &Bound<'_, PyType>, count: usize) { if let Err(e) = ThreadPoolBuilder::new().num_threads(count).build_global() { eprintln!("While initializing global thread pool: {e}"); } @@ -408,7 +408,7 @@ impl Default for Reclass { } #[pymodule] -fn reclass_rs(_py: Python, m: &PyModule) -> PyResult<()> { +fn reclass_rs(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { // Register the top-level `Reclass` Python class which is used to configure the library m.add_class::()?; // Register the `Config` class and `CompatFlag` enum diff --git a/src/list/mod.rs b/src/list/mod.rs index 264c5b5..f8a4875 100644 --- a/src/list/mod.rs +++ b/src/list/mod.rs @@ -4,12 +4,14 @@ mod unique; /// Defines the shared interface between the unique list (which is effectively an insert-ordered /// Set) and the unique list which supports removals. pub trait List { + #[allow(dead_code)] fn new() -> Self; fn with_capacity(capacity: usize) -> Self; fn len(&self) -> usize; fn shrink_to_fit(&mut self); fn append_if_new(&mut self, item: String); fn merge(&mut self, other: Self); + #[allow(dead_code)] fn merge_from(&mut self, other: &Self); } diff --git a/src/node/nodeinfo.rs b/src/node/nodeinfo.rs index 3420e5b..4712428 100644 --- a/src/node/nodeinfo.rs +++ b/src/node/nodeinfo.rs @@ -177,7 +177,7 @@ impl NodeInfo { /// This method generates a PyDict which should be structured identically to Python Reclass's /// `nodeinfo` return value. pub(crate) fn as_dict(&self, py: Python<'_>) -> PyResult> { - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); dict.set_item("__reclass__", self.reclass_as_dict(py)?)?; dict.set_item("applications", self.applications.clone().into_py(py))?; dict.set_item("classes", self.classes.clone().into_py(py))?; @@ -189,7 +189,7 @@ impl NodeInfo { /// Returns the NodeInfo `meta` field as a PyDict fn reclass_as_dict(&self, py: Python<'_>) -> PyResult> { - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); dict.set_item("node", self.reclass.node.clone().into_py(py))?; dict.set_item("name", self.reclass.name.clone().into_py(py))?; dict.set_item("uri", self.reclass.uri.clone().into_py(py))?; diff --git a/src/types/from.rs b/src/types/from.rs index e8fa5bf..a3f0323 100644 --- a/src/types/from.rs +++ b/src/types/from.rs @@ -120,18 +120,18 @@ impl<'a, T: Clone + Into> From<&'a [T]> for Value { } } -impl TryFrom<&PyAny> for Value { +impl TryFrom> for Value { type Error = PyErr; - fn try_from(value: &PyAny) -> PyResult { - match value.get_type().name()? { + fn try_from(value: Bound<'_, PyAny>) -> PyResult { + match value.get_type().name()?.to_str()? { "str" => { let v = value.extract::<&str>()?; Ok(Self::String(v.to_string())) } "list" => { let v = value.downcast::()?; - let mut items = vec![]; + let mut items: Vec = vec![]; for it in v.iter()? { items.push(TryInto::try_into(it?)?); } diff --git a/src/types/mapping.rs b/src/types/mapping.rs index f62d02d..5719b0e 100644 --- a/src/types/mapping.rs +++ b/src/types/mapping.rs @@ -356,7 +356,7 @@ impl Mapping { /// Converts the `Mapping` into a `PyDict`. pub fn as_py_dict(&self, py: Python<'_>) -> PyResult> { - let dict = PyDict::new(py); + let dict = PyDict::new_bound(py); for (k, v) in self { let pyk = k.as_py_obj(py)?; @@ -741,7 +741,7 @@ mod mapping_tests { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { let pym = m.as_py_dict(py).unwrap(); - let m = pym.as_ref(py); + let m = pym.bind(py); assert_eq!(m.len(), 6); assert_eq!(format!("{:?}", m.keys()), "['a', 'b', 'c', 'd', 'e', 'f']"); let a = m.get_item(&"a").unwrap().unwrap(); diff --git a/src/types/value/value_as_py_obj_tests.rs b/src/types/value/value_as_py_obj_tests.rs index c5022ba..e790ce3 100644 --- a/src/types/value/value_as_py_obj_tests.rs +++ b/src/types/value/value_as_py_obj_tests.rs @@ -4,7 +4,7 @@ fn test_as_py_obj_null() { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { let pyv = Value::Null.as_py_obj(py).unwrap(); - let v = pyv.as_ref(py); + let v = pyv.bind(py); assert!(v.is_none()); }); } @@ -14,7 +14,7 @@ fn test_as_py_obj_bool() { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { let pyb = Value::Bool(true).as_py_obj(py).unwrap(); - let b = pyb.as_ref(py); + let b = pyb.bind(py); assert!(b.is_instance_of::()); assert!(b.downcast_exact::().unwrap().is_true()); }); @@ -27,7 +27,7 @@ fn test_as_py_obj_int() { let nums: Vec = vec![5.into(), (-2i64).into()]; for n in nums { let pyn = n.as_py_obj(py).unwrap(); - let n = pyn.as_ref(py); + let n = pyn.bind(py); assert!(n.is_instance_of::()); assert!(n .downcast_exact::() @@ -44,7 +44,7 @@ fn test_as_py_obj_float() { Python::with_gil(|py| { let n: Value = 3.14.into(); let pyn = n.as_py_obj(py).unwrap(); - let n = pyn.as_ref(py); + let n = pyn.bind(py); assert!(n.is_instance_of::()); assert!(n .downcast_exact::() @@ -60,12 +60,12 @@ fn test_as_py_obj_sequence() { Python::with_gil(|py| { let s: Value = vec![1, 2, 3].into(); let pys = s.as_py_obj(py).unwrap(); - let s = pys.as_ref(py); + let s = pys.bind(py); assert!(s.is_instance_of::()); assert!(s .downcast_exact::() .unwrap() - .eq(pyo3::types::PyList::new(py, vec![1, 2, 3])) + .eq(pyo3::types::PyList::new_bound(py, vec![1, 2, 3])) .unwrap()); }); } @@ -77,7 +77,7 @@ fn test_as_py_obj_string() { let pys = std::convert::Into::::into("hello, world") .as_py_obj(py) .unwrap(); - let s = pys.as_ref(py); + let s = pys.bind(py); assert!(s.is_instance_of::()); assert_eq!( s.downcast_exact::() diff --git a/tests/test_py.rs b/tests/test_py.rs index ed998cc..7045f25 100644 --- a/tests/test_py.rs +++ b/tests/test_py.rs @@ -10,12 +10,12 @@ fn test_reclass() { let r = Reclass::new("./tests/inventory", "nodes", "classes", false) .unwrap() .into_py(py); - let locals = PyDict::new(py); + let locals = PyDict::new_bound(py); locals.set_item("r", r).unwrap(); - py.run( + py.run_bound( r#"assert r and "Reclass" in str(type(r))"#, None, - Some(locals), + Some(&locals), ) .unwrap(); });