From 677adabf0f4ae6bc73abdc7bdddaf23bf059e811 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Tue, 16 Apr 2024 11:53:30 +0100 Subject: [PATCH] feat: Update pyo3 dep to `0.21` --- Cargo.toml | 4 ++-- tket2-py/src/circuit.rs | 22 ++++++++++---------- tket2-py/src/circuit/convert.rs | 29 ++++++++++++++------------ tket2-py/src/circuit/cost.rs | 6 +++--- tket2-py/src/lib.rs | 8 +++---- tket2-py/src/optimiser.rs | 8 +++---- tket2-py/src/passes.rs | 31 +++++++++++++++------------- tket2-py/src/passes/chunks.rs | 8 +++---- tket2-py/src/pattern.rs | 10 ++++----- tket2-py/src/pattern/portmatching.rs | 6 +++--- tket2-py/src/rewrite.rs | 4 ++-- 11 files changed, 71 insertions(+), 65 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b4f0d14a..7dea3fde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,9 @@ missing_docs = "warn" tket2 = { path = "./tket2" } quantinuum-hugr = "0.2" portgraph = "0.11" -pyo3 = "0.20" +pyo3 = "0.21.2" itertools = "0.12.0" -tket-json-rs = "0.3.0" +tket-json-rs = "0.4.0" tracing = "0.1.37" portmatching = "0.3.1" bytemuck = "1.14.0" diff --git a/tket2-py/src/circuit.rs b/tket2-py/src/circuit.rs index aeffa682..55a5f03a 100644 --- a/tket2-py/src/circuit.rs +++ b/tket2-py/src/circuit.rs @@ -21,25 +21,25 @@ pub use self::cost::PyCircuitCost; pub use tket2::{Pauli, Tk2Op}; /// The module definition -pub fn module(py: Python) -> PyResult<&PyModule> { - let m = PyModule::new(py, "_circuit")?; +pub fn module(py: Python<'_>) -> PyResult> { + let m = PyModule::new_bound(py, "_circuit")?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; - m.add_function(wrap_pyfunction!(validate_hugr, m)?)?; - m.add_function(wrap_pyfunction!(to_hugr_dot, m)?)?; + m.add_function(wrap_pyfunction!(validate_hugr, &m)?)?; + m.add_function(wrap_pyfunction!(to_hugr_dot, &m)?)?; - m.add("HugrError", py.get_type::())?; - m.add("BuildError", py.get_type::())?; - m.add("ValidationError", py.get_type::())?; + m.add("HugrError", py.get_type_bound::())?; + m.add("BuildError", py.get_type_bound::())?; + m.add("ValidationError", py.get_type_bound::())?; m.add( "HUGRSerializationError", - py.get_type::(), + py.get_type_bound::(), )?; - m.add("OpConvertError", py.get_type::())?; + m.add("OpConvertError", py.get_type_bound::())?; Ok(m) } @@ -76,13 +76,13 @@ create_py_exception!( /// Run the validation checks on a circuit. #[pyfunction] -pub fn validate_hugr(c: &PyAny) -> PyResult<()> { +pub fn validate_hugr(c: &Bound) -> PyResult<()> { try_with_hugr(c, |hugr, _| hugr.validate(®ISTRY)) } /// Return a Graphviz DOT string representation of the circuit. #[pyfunction] -pub fn to_hugr_dot(c: &PyAny) -> PyResult { +pub fn to_hugr_dot(c: &Bound) -> PyResult { with_hugr(c, |hugr, _| hugr.dot_string()) } diff --git a/tket2-py/src/circuit/convert.rs b/tket2-py/src/circuit/convert.rs index ca31973d..46b6982b 100644 --- a/tket2-py/src/circuit/convert.rs +++ b/tket2-py/src/circuit/convert.rs @@ -2,7 +2,10 @@ use hugr::ops::OpType; use pyo3::exceptions::{PyAttributeError, PyValueError}; -use pyo3::{prelude::*, PyTypeInfo}; +use pyo3::types::PyAnyMethods; +use pyo3::{ + pyclass, pymethods, Bound, FromPyObject, PyAny, PyErr, PyResult, PyTypeInfo, Python, ToPyObject, +}; use derive_more::From; use hugr::{Hugr, HugrView}; @@ -50,14 +53,14 @@ pub struct Tk2Circuit { impl Tk2Circuit { /// Convert a tket1 circuit to a [`Tk2Circuit`]. #[new] - pub fn from_tket1(circ: &PyAny) -> PyResult { + pub fn from_tket1(circ: &Bound) -> PyResult { Ok(Self { hugr: with_hugr(circ, |hugr, _| hugr)?, }) } /// Convert the [`Tk2Circuit`] to a tket1 circuit. - pub fn to_tket1<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> { + pub fn to_tket1<'py>(&self, py: Python<'py>) -> PyResult> { SerialCircuit::encode(&self.hugr) .convert_pyerrs()? .to_tket1(py) @@ -108,7 +111,7 @@ impl Tk2Circuit { /// `__eq__`, `__int__`, and integer `__div__`. /// /// :returns: The sum of all operation costs. - pub fn circuit_cost<'py>(&self, cost_fn: &'py PyAny) -> PyResult<&'py PyAny> { + pub fn circuit_cost<'py>(&self, cost_fn: &Bound<'py, PyAny>) -> PyResult> { let py = cost_fn.py(); let cost_fn = |op: &OpType| -> PyResult { let tk2_op: Tk2Op = op.try_into().map_err(|e| { @@ -122,7 +125,7 @@ impl Tk2Circuit { }) }; let circ_cost = self.hugr.circuit_cost(cost_fn)?; - Ok(circ_cost.cost.into_ref(py)) + Ok(circ_cost.cost.into_bound(py)) } /// Returns a hash of the circuit. @@ -141,7 +144,7 @@ impl Tk2Circuit { } /// Copy the circuit. - pub fn __deepcopy__(&self, _memo: Py) -> PyResult { + pub fn __deepcopy__(&self, _memo: Bound) -> PyResult { Ok(self.clone()) } } @@ -165,10 +168,10 @@ pub enum CircuitType { impl CircuitType { /// Converts a `Hugr` into the format indicated by the flag. - pub fn convert(self, py: Python, hugr: Hugr) -> PyResult<&PyAny> { + pub fn convert(self, py: Python, hugr: Hugr) -> PyResult> { match self { CircuitType::Tket1 => SerialCircuit::encode(&hugr).convert_pyerrs()?.to_tket1(py), - CircuitType::Tket2 => Ok(Py::new(py, Tk2Circuit { hugr })?.into_ref(py)), + CircuitType::Tket2 => Ok(Bound::new(py, Tk2Circuit { hugr })?.into_any()), } } } @@ -176,12 +179,12 @@ impl CircuitType { /// Apply a fallible function expecting a hugr on a python circuit. /// /// This method supports both `pytket.Circuit` and `Tk2Circuit` python objects. -pub fn try_with_hugr(circ: &PyAny, f: F) -> PyResult +pub fn try_with_hugr(circ: &Bound, f: F) -> PyResult where E: ConvertPyErr, F: FnOnce(Hugr, CircuitType) -> Result, { - let (hugr, typ) = match Tk2Circuit::extract(circ) { + let (hugr, typ) = match Tk2Circuit::extract_bound(circ) { // hugr circuit Ok(t2circ) => (t2circ.hugr, CircuitType::Tket2), // tket1 circuit @@ -196,7 +199,7 @@ where /// Apply a function expecting a hugr on a python circuit. /// /// This method supports both `pytket.Circuit` and `Tk2Circuit` python objects. -pub fn with_hugr(circ: &PyAny, f: F) -> PyResult +pub fn with_hugr(circ: &Bound, f: F) -> PyResult where F: FnOnce(Hugr, CircuitType) -> T, { @@ -207,7 +210,7 @@ where /// /// This method supports both `pytket.Circuit` and `Tk2Circuit` python objects. /// The returned Hugr is converted to the matching python object. -pub fn try_update_hugr(circ: &PyAny, f: F) -> PyResult<&PyAny> +pub fn try_update_hugr<'py, E, F>(circ: &Bound<'py, PyAny>, f: F) -> PyResult> where E: ConvertPyErr, F: FnOnce(Hugr, CircuitType) -> Result, @@ -223,7 +226,7 @@ where /// /// This method supports both `pytket.Circuit` and `Tk2Circuit` python objects. /// The returned Hugr is converted to the matching python object. -pub fn update_hugr(circ: &PyAny, f: F) -> PyResult<&PyAny> +pub fn update_hugr<'py, F>(circ: &Bound<'py, PyAny>, f: F) -> PyResult> where F: FnOnce(Hugr, CircuitType) -> Hugr, { diff --git a/tket2-py/src/circuit/cost.rs b/tket2-py/src/circuit/cost.rs index cbd734cf..9ddb139c 100644 --- a/tket2-py/src/circuit/cost.rs +++ b/tket2-py/src/circuit/cost.rs @@ -96,7 +96,7 @@ impl PartialEq for PyCircuitCost { .cost .call_method1(py, "__eq__", (&other.cost,)) .expect("Could not compare circuit cost objects."); - res.is_true(py) + res.is_truthy(py) .expect("Could not compare circuit cost objects.") }) } @@ -114,11 +114,11 @@ impl Ord for PyCircuitCost { fn cmp(&self, other: &Self) -> Ordering { Python::with_gil(|py| -> PyResult { let res = self.cost.call_method1(py, "__lt__", (&other.cost,))?; - if res.is_true(py)? { + if res.is_truthy(py)? { return Ok(Ordering::Less); } let res = self.cost.call_method1(py, "__eq__", (&other.cost,))?; - if res.is_true(py)? { + if res.is_truthy(py)? { return Ok(Ordering::Equal); } Ok(Ordering::Greater) diff --git a/tket2-py/src/lib.rs b/tket2-py/src/lib.rs index bda5833a..59f4d2bf 100644 --- a/tket2-py/src/lib.rs +++ b/tket2-py/src/lib.rs @@ -11,7 +11,7 @@ use pyo3::prelude::*; /// The Python bindings to TKET2. #[pymodule] #[pyo3(name = "tket2")] -fn tket2_py(py: Python, m: &PyModule) -> PyResult<()> { +fn tket2_py(py: Python, m: &Bound) -> PyResult<()> { add_submodule(py, m, circuit::module(py)?)?; add_submodule(py, m, optimiser::module(py)?)?; add_submodule(py, m, passes::module(py)?)?; @@ -20,8 +20,8 @@ fn tket2_py(py: Python, m: &PyModule) -> PyResult<()> { Ok(()) } -fn add_submodule(py: Python, parent: &PyModule, submodule: &PyModule) -> PyResult<()> { - parent.add_submodule(submodule)?; +fn add_submodule(py: Python, parent: &Bound, submodule: Bound) -> PyResult<()> { + parent.add_submodule(&submodule)?; // Add submodule to sys.modules. // This is required to be able to do `from parent.submodule import ...`. @@ -29,7 +29,7 @@ fn add_submodule(py: Python, parent: &PyModule, submodule: &PyModule) -> PyResul // See [https://github.com/PyO3/pyo3/issues/759] let parent_name = parent.name()?; let submodule_name = submodule.name()?; - let modules = py.import("sys")?.getattr("modules")?; + let modules = py.import_bound("sys")?.getattr("modules")?; modules.set_item(format!("{parent_name}.{submodule_name}"), submodule)?; Ok(()) } diff --git a/tket2-py/src/optimiser.rs b/tket2-py/src/optimiser.rs index 2c92a89f..fdb428a6 100644 --- a/tket2-py/src/optimiser.rs +++ b/tket2-py/src/optimiser.rs @@ -11,8 +11,8 @@ use tket2::optimiser::{BadgerLogger, DefaultBadgerOptimiser}; use crate::circuit::update_hugr; /// The module definition -pub fn module(py: Python) -> PyResult<&PyModule> { - let m = PyModule::new(py, "_optimiser")?; +pub fn module(py: Python<'_>) -> PyResult> { + let m = PyModule::new_bound(py, "_optimiser")?; m.add_class::()?; Ok(m) } @@ -81,14 +81,14 @@ impl PyBadgerOptimiser { #[allow(clippy::too_many_arguments)] pub fn py_optimise<'py>( &self, - circ: &'py PyAny, + circ: &Bound<'py, PyAny>, timeout: Option, progress_timeout: Option, n_threads: Option, split_circ: Option, queue_size: Option, log_progress: Option, - ) -> PyResult<&'py PyAny> { + ) -> PyResult> { let options = BadgerOptions { timeout, progress_timeout, diff --git a/tket2-py/src/passes.rs b/tket2-py/src/passes.rs index 086a9256..9db63ac5 100644 --- a/tket2-py/src/passes.rs +++ b/tket2-py/src/passes.rs @@ -17,20 +17,23 @@ use crate::{ /// The module definition /// /// This module is re-exported from the python module with the same name. -pub fn module(py: Python) -> PyResult<&PyModule> { - let m = PyModule::new(py, "_passes")?; - m.add_function(wrap_pyfunction!(greedy_depth_reduce, m)?)?; - m.add_function(wrap_pyfunction!(badger_optimise, m)?)?; +pub fn module(py: Python<'_>) -> PyResult> { + let m = PyModule::new_bound(py, "_passes")?; + m.add_function(wrap_pyfunction!(greedy_depth_reduce, &m)?)?; + m.add_function(wrap_pyfunction!(badger_optimise, &m)?)?; m.add_class::()?; - m.add_function(wrap_pyfunction!(self::chunks::chunks, m)?)?; - m.add("PullForwardError", py.get_type::())?; + m.add_function(wrap_pyfunction!(self::chunks::chunks, &m)?)?; + m.add( + "PullForwardError", + py.get_type_bound::(), + )?; Ok(m) } create_py_exception!(tket2::passes::PullForwardError, PyPullForwardError, ""); #[pyfunction] -fn greedy_depth_reduce(circ: &PyAny) -> PyResult<(&PyAny, u32)> { +fn greedy_depth_reduce<'py>(circ: &Bound<'py, PyAny>) -> PyResult<(Bound<'py, PyAny>, u32)> { let py = circ.py(); try_with_hugr(circ, |mut h, typ| { let n_moves = apply_greedy_commutation(&mut h).convert_pyerrs()?; @@ -47,14 +50,14 @@ fn greedy_depth_reduce(circ: &PyAny) -> PyResult<(&PyAny, u32)> { /// from pytket import OpType /// auto_rebase_pass({OpType.CX, OpType.Rz, OpType.H}).apply(circ)" // ``` -fn rebase_nam(circ: &PyAny) -> PyResult<()> { +fn rebase_nam(circ: &Bound) -> PyResult<()> { let py = circ.py(); let auto_rebase = py - .import("pytket.passes.auto_rebase")? + .import_bound("pytket.passes.auto_rebase")? .getattr("auto_rebase_pass")?; - let optype = py.import("pytket")?.getattr("OpType")?; - let locals = [("OpType", &optype)].into_py_dict(py); - let op_set = py.eval("{OpType.CX, OpType.Rz, OpType.H}", None, Some(locals))?; + let optype = py.import_bound("pytket")?.getattr("OpType")?; + let locals = [("OpType", &optype)].into_py_dict_bound(py); + let op_set = py.eval_bound("{OpType.CX, OpType.Rz, OpType.H}", None, Some(&locals))?; let rebase_pass = auto_rebase.call1((op_set,))?.getattr("apply")?; rebase_pass.call1((circ,)).map(|_| ()) } @@ -75,14 +78,14 @@ fn rebase_nam(circ: &PyAny) -> PyResult<()> { /// Log files will be written to the directory `log_dir` if specified. #[pyfunction] fn badger_optimise<'py>( - circ: &'py PyAny, + circ: &Bound<'py, PyAny>, optimiser: &PyBadgerOptimiser, max_threads: Option, timeout: Option, progress_timeout: Option, log_dir: Option, rebase: Option, -) -> PyResult<&'py PyAny> { +) -> PyResult> { // Default parameter values let rebase = rebase.unwrap_or(true); let max_threads = max_threads.unwrap_or(num_cpus::get().try_into().unwrap()); diff --git a/tket2-py/src/passes/chunks.rs b/tket2-py/src/passes/chunks.rs index 7d97959b..c7f285a7 100644 --- a/tket2-py/src/passes/chunks.rs +++ b/tket2-py/src/passes/chunks.rs @@ -12,7 +12,7 @@ use crate::utils::ConvertPyErr; /// Split a circuit into chunks of a given size. #[pyfunction] -pub fn chunks(c: &PyAny, max_chunk_size: usize) -> PyResult { +pub fn chunks(c: &Bound, max_chunk_size: usize) -> PyResult { with_hugr(c, |hugr, typ| { // TODO: Detect if the circuit is in tket1 format or Tk2Circuit. let chunks = CircuitChunks::split(&hugr, max_chunk_size); @@ -38,13 +38,13 @@ pub struct PyCircuitChunks { #[pymethods] impl PyCircuitChunks { /// Reassemble the chunks into a circuit. - fn reassemble<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> { + fn reassemble<'py>(&self, py: Python<'py>) -> PyResult> { let hugr = self.clone().chunks.reassemble().convert_pyerrs()?; self.original_type.convert(py, hugr) } /// Returns clones of the split circuits. - fn circuits<'py>(&self, py: Python<'py>) -> PyResult> { + fn circuits<'py>(&self, py: Python<'py>) -> PyResult>> { self.chunks .iter() .map(|hugr| self.original_type.convert(py, hugr.clone())) @@ -52,7 +52,7 @@ impl PyCircuitChunks { } /// Replaces a chunk's circuit with an updated version. - fn update_circuit(&mut self, index: usize, new_circ: &PyAny) -> PyResult<()> { + fn update_circuit(&mut self, index: usize, new_circ: &Bound) -> PyResult<()> { try_with_hugr(new_circ, |hugr, _| { if hugr.circuit_signature() != self.chunks[index].circuit_signature() { return Err(PyAttributeError::new_err( diff --git a/tket2-py/src/pattern.rs b/tket2-py/src/pattern.rs index 953d1cd6..ba83fcbd 100644 --- a/tket2-py/src/pattern.rs +++ b/tket2-py/src/pattern.rs @@ -11,8 +11,8 @@ use pyo3::prelude::*; use tket2::portmatching::{CircuitPattern, PatternMatcher}; /// The module definition -pub fn module(py: Python) -> PyResult<&PyModule> { - let m = PyModule::new(py, "_pattern")?; +pub fn module(py: Python<'_>) -> PyResult> { + let m = PyModule::new_bound(py, "_pattern")?; m.add_class::()?; m.add_class::()?; m.add_class::()?; @@ -21,11 +21,11 @@ pub fn module(py: Python) -> PyResult<&PyModule> { m.add( "InvalidPatternError", - py.get_type::(), + py.get_type_bound::(), )?; m.add( "InvalidReplacementError", - py.get_type::(), + py.get_type_bound::(), )?; Ok(m) @@ -51,7 +51,7 @@ pub struct Rule(pub [Hugr; 2]); #[pymethods] impl Rule { #[new] - fn new_rule(l: &PyAny, r: &PyAny) -> PyResult { + fn new_rule(l: &Bound, r: &Bound) -> PyResult { let l = Tk2Circuit::from_tket1(l)?; let r = Tk2Circuit::from_tket1(r)?; diff --git a/tket2-py/src/pattern/portmatching.rs b/tket2-py/src/pattern/portmatching.rs index 8623bac3..b119cf1a 100644 --- a/tket2-py/src/pattern/portmatching.rs +++ b/tket2-py/src/pattern/portmatching.rs @@ -29,7 +29,7 @@ pub struct PyCircuitPattern { impl PyCircuitPattern { /// Construct a pattern from a TKET1 circuit #[new] - pub fn from_circuit(circ: &PyAny) -> PyResult { + pub fn from_circuit(circ: &Bound) -> PyResult { let pattern = try_with_hugr(circ, |circ, _| CircuitPattern::try_from_circuit(&circ))?; Ok(pattern.into()) } @@ -61,7 +61,7 @@ pub struct PyPatternMatcher { impl PyPatternMatcher { /// Construct a matcher from a list of patterns. #[new] - pub fn py_from_patterns(patterns: &PyIterator) -> PyResult { + pub fn py_from_patterns(patterns: &Bound) -> PyResult { Ok(PatternMatcher::from_patterns( patterns .iter()? @@ -79,7 +79,7 @@ impl PyPatternMatcher { } /// Find all convex matches in a circuit. - pub fn find_matches(&self, circ: &PyAny) -> PyResult> { + pub fn find_matches(&self, circ: &Bound) -> PyResult> { with_hugr(circ, |circ, _| { self.matcher .find_matches(&circ) diff --git a/tket2-py/src/rewrite.rs b/tket2-py/src/rewrite.rs index ff833cc1..4346aa08 100644 --- a/tket2-py/src/rewrite.rs +++ b/tket2-py/src/rewrite.rs @@ -9,8 +9,8 @@ use tket2::rewrite::{CircuitRewrite, ECCRewriter, Rewriter}; use crate::circuit::Tk2Circuit; /// The module definition -pub fn module(py: Python) -> PyResult<&PyModule> { - let m = PyModule::new(py, "_rewrite")?; +pub fn module(py: Python<'_>) -> PyResult> { + let m = PyModule::new_bound(py, "_rewrite")?; m.add_class::()?; m.add_class::()?; Ok(m)