diff --git a/crates/accelerate/src/lib.rs b/crates/accelerate/src/lib.rs index 3adb646aaa28..1cf24044276d 100644 --- a/crates/accelerate/src/lib.rs +++ b/crates/accelerate/src/lib.rs @@ -49,7 +49,7 @@ pub fn getenv_use_multiple_threads() -> bool { } #[pymodule] -fn _accelerate(_py: Python<'_>, m: &PyModule) -> PyResult<()> { +fn _accelerate(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(nlayout::nlayout))?; m.add_wrapped(wrap_pymodule!(stochastic_swap::stochastic_swap))?; m.add_wrapped(wrap_pymodule!(sabre_swap::sabre_swap))?; diff --git a/crates/accelerate/src/quantum_circuit/circuit_data.rs b/crates/accelerate/src/quantum_circuit/circuit_data.rs index 915285f6ad6d..ebefeda87ac1 100644 --- a/crates/accelerate/src/quantum_circuit/circuit_data.rs +++ b/crates/accelerate/src/quantum_circuit/circuit_data.rs @@ -12,7 +12,6 @@ use crate::quantum_circuit::circuit_instruction::CircuitInstruction; use crate::quantum_circuit::intern_context::{BitType, IndexType, InternContext}; -use crate::quantum_circuit::py_ext; use crate::utils::SliceOrInt; use hashbrown::HashMap; use pyo3::exceptions::{PyIndexError, PyKeyError, PyRuntimeError, PyValueError}; @@ -70,10 +69,10 @@ impl PartialEq for BitAsKey { self.bit.is(&other.bit) || Python::with_gil(|py| { self.bit - .as_ref(py) + .bind(py) .repr() .unwrap() - .eq(other.bit.as_ref(py).repr().unwrap()) + .eq(other.bit.bind(py).repr().unwrap()) .unwrap() }) } @@ -172,8 +171,8 @@ impl CircuitData { clbits_native: Vec::new(), qubit_indices_native: HashMap::new(), clbit_indices_native: HashMap::new(), - qubits: PyList::empty(py).into_py(py), - clbits: PyList::empty(py).into_py(py), + qubits: PyList::empty_bound(py).unbind(), + clbits: PyList::empty_bound(py).unbind(), }; if let Some(qubits) = qubits { for bit in qubits.iter()? { @@ -860,22 +859,24 @@ impl CircuitData { py, CircuitInstruction { operation: inst.op.clone_ref(py), - qubits: py_ext::tuple_new( + qubits: PyTuple::new_bound( py, self.intern_context .lookup(inst.qubits_id) .iter() .map(|i| self.qubits_native[*i as usize].clone_ref(py)) - .collect(), - ), - clbits: py_ext::tuple_new( + .collect::>(), + ) + .unbind(), + clbits: PyTuple::new_bound( py, self.intern_context .lookup(inst.clbits_id) .iter() .map(|i| self.clbits_native[*i as usize].clone_ref(py)) - .collect(), - ), + .collect::>(), + ) + .unbind(), }, ) } diff --git a/crates/accelerate/src/quantum_circuit/circuit_instruction.rs b/crates/accelerate/src/quantum_circuit/circuit_instruction.rs index 0bf84a362c3f..23635bc90988 100644 --- a/crates/accelerate/src/quantum_circuit/circuit_instruction.rs +++ b/crates/accelerate/src/quantum_circuit/circuit_instruction.rs @@ -10,7 +10,6 @@ // copyright notice, and modified files need to carry a notice indicating // that they have been altered from the originals. -use crate::quantum_circuit::py_ext; use pyo3::basic::CompareOp; use pyo3::prelude::*; use pyo3::types::{PyList, PyTuple}; @@ -70,26 +69,27 @@ impl CircuitInstruction { pub fn new( py: Python<'_>, operation: PyObject, - qubits: Option<&PyAny>, - clbits: Option<&PyAny>, + qubits: Option<&Bound>, + clbits: Option<&Bound>, ) -> PyResult { - fn as_tuple(py: Python<'_>, seq: Option<&PyAny>) -> PyResult> { + fn as_tuple(py: Python<'_>, seq: Option<&Bound>) -> PyResult> { match seq { - None => Ok(py_ext::tuple_new_empty(py)), + None => Ok(PyTuple::empty_bound(py).unbind()), Some(seq) => { if seq.is_instance_of::() { Ok(seq.downcast_exact::()?.into_py(py)) } else if seq.is_instance_of::() { let seq = seq.downcast_exact::()?; - Ok(py_ext::tuple_from_list(seq)) + Ok(seq.to_tuple().unbind()) } else { // New tuple from iterable. - Ok(py_ext::tuple_new( + Ok(PyTuple::new_bound( py, seq.iter()? - .map(|o| Ok(o?.into_py(py))) + .map(|o| Ok(o?.unbind())) .collect::>>()?, - )) + ) + .unbind()) } } } @@ -118,27 +118,27 @@ impl CircuitInstruction { &self, py: Python<'_>, operation: Option, - qubits: Option<&PyAny>, - clbits: Option<&PyAny>, + qubits: Option<&Bound>, + clbits: Option<&Bound>, ) -> PyResult { CircuitInstruction::new( py, operation.unwrap_or_else(|| self.operation.clone_ref(py)), - Some(qubits.unwrap_or_else(|| self.qubits.as_ref(py))), - Some(clbits.unwrap_or_else(|| self.clbits.as_ref(py))), + Some(qubits.unwrap_or_else(|| self.qubits.bind(py))), + Some(clbits.unwrap_or_else(|| self.clbits.bind(py))), ) } fn __getstate__(&self, py: Python<'_>) -> PyObject { ( - self.operation.as_ref(py), - self.qubits.as_ref(py), - self.clbits.as_ref(py), + self.operation.bind(py), + self.qubits.bind(py), + self.clbits.bind(py), ) .into_py(py) } - fn __setstate__(&mut self, _py: Python<'_>, state: &PyTuple) -> PyResult<()> { + fn __setstate__(&mut self, _py: Python<'_>, state: &Bound) -> PyResult<()> { self.operation = state.get_item(0)?.extract()?; self.qubits = state.get_item(1)?.extract()?; self.clbits = state.get_item(2)?.extract()?; @@ -154,8 +154,8 @@ impl CircuitInstruction { .into_py(py)) } - pub fn __repr__(self_: &PyCell, py: Python<'_>) -> PyResult { - let type_name = self_.get_type().name()?; + pub fn __repr__(self_: &Bound, py: Python<'_>) -> PyResult { + let type_name = self_.get_type().qualname()?; let r = self_.try_borrow()?; Ok(format!( "{}(\ @@ -164,9 +164,9 @@ impl CircuitInstruction { , clbits={}\ )", type_name, - r.operation.as_ref(py).repr()?, - r.qubits.as_ref(py).repr()?, - r.clbits.as_ref(py).repr()? + r.operation.bind(py).repr()?, + r.qubits.bind(py).repr()?, + r.clbits.bind(py).repr()? )) } @@ -177,7 +177,7 @@ impl CircuitInstruction { // like that via unpacking or similar. That means that the `parameters` field is completely // absent, and the qubits and clbits must be converted to lists. pub fn _legacy_format(&self, py: Python<'_>) -> PyObject { - PyTuple::new( + PyTuple::new_bound( py, [ self.operation.as_ref(py), @@ -188,12 +188,8 @@ impl CircuitInstruction { .into_py(py) } - pub fn __getitem__(&self, py: Python<'_>, key: &PyAny) -> PyResult { - Ok(self - ._legacy_format(py) - .as_ref(py) - .get_item(key)? - .into_py(py)) + pub fn __getitem__(&self, py: Python<'_>, key: &Bound) -> PyResult { + Ok(self._legacy_format(py).bind(py).get_item(key)?.into_py(py)) } pub fn __iter__(&self, py: Python<'_>) -> PyResult { @@ -205,15 +201,15 @@ impl CircuitInstruction { } pub fn __richcmp__( - self_: &PyCell, - other: &PyAny, + self_: &Bound, + other: &Bound, op: CompareOp, py: Python<'_>, ) -> PyResult { fn eq( py: Python<'_>, - self_: &PyCell, - other: &PyAny, + self_: &Bound, + other: &Bound, ) -> PyResult> { if self_.is(other) { return Ok(Some(true)); @@ -221,19 +217,19 @@ impl CircuitInstruction { let self_ = self_.try_borrow()?; if other.is_instance_of::() { - let other: PyResult<&PyCell> = other.extract(); + let other: PyResult> = other.extract(); return other.map_or(Ok(Some(false)), |v| { let v = v.try_borrow()?; Ok(Some( - self_.clbits.as_ref(py).eq(v.clbits.as_ref(py))? - && self_.qubits.as_ref(py).eq(v.qubits.as_ref(py))? - && self_.operation.as_ref(py).eq(v.operation.as_ref(py))?, + self_.clbits.bind(py).eq(v.clbits.bind(py))? + && self_.qubits.bind(py).eq(v.qubits.bind(py))? + && self_.operation.bind(py).eq(v.operation.bind(py))?, )) }); } if other.is_instance_of::() { - return Ok(Some(self_._legacy_format(py).as_ref(py).eq(other)?)); + return Ok(Some(self_._legacy_format(py).bind(py).eq(other)?)); } Ok(None) diff --git a/crates/accelerate/src/quantum_circuit/mod.rs b/crates/accelerate/src/quantum_circuit/mod.rs index 4f4b56865034..2b94619c6f39 100644 --- a/crates/accelerate/src/quantum_circuit/mod.rs +++ b/crates/accelerate/src/quantum_circuit/mod.rs @@ -13,12 +13,11 @@ pub mod circuit_data; pub mod circuit_instruction; pub mod intern_context; -mod py_ext; use pyo3::prelude::*; #[pymodule] -pub fn quantum_circuit(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn quantum_circuit(m: &Bound) -> PyResult<()> { m.add_class::()?; m.add_class::()?; Ok(()) diff --git a/crates/accelerate/src/quantum_circuit/py_ext.rs b/crates/accelerate/src/quantum_circuit/py_ext.rs deleted file mode 100644 index da27764a7f4e..000000000000 --- a/crates/accelerate/src/quantum_circuit/py_ext.rs +++ /dev/null @@ -1,45 +0,0 @@ -// This code is part of Qiskit. -// -// (C) Copyright IBM 2023 -// -// This code is licensed under the Apache License, Version 2.0. You may -// obtain a copy of this license in the LICENSE.txt file in the root directory -// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -// -// Any modifications or derivative works of this code must retain this -// copyright notice, and modified files need to carry a notice indicating -// that they have been altered from the originals. -//! Contains helper functions for creating [Py] (GIL-independent) -//! objects without creating an intermediate owned reference. These functions -//! are faster than PyO3's list and tuple factory methods when the caller -//! doesn't need to dereference the newly constructed object (i.e. if the -//! resulting [Py] will simply be stored in a Rust struct). -//! -//! The reason this is faster is because PyO3 tracks owned references and -//! will perform deallocation when the active [GILPool] goes out of scope. -//! If we don't need to dereference the [Py], then we can skip the -//! tracking and deallocation. - -use pyo3::ffi::Py_ssize_t; -use pyo3::prelude::*; -use pyo3::types::{PyList, PyTuple}; -use pyo3::{ffi, AsPyPointer, PyNativeType}; - -pub fn tuple_new(py: Python<'_>, items: Vec) -> Py { - unsafe { - let ptr = ffi::PyTuple_New(items.len() as Py_ssize_t); - let tup: Py = Py::from_owned_ptr(py, ptr); - for (i, obj) in items.into_iter().enumerate() { - ffi::PyTuple_SetItem(ptr, i as Py_ssize_t, obj.into_ptr()); - } - tup - } -} - -pub fn tuple_new_empty(py: Python<'_>) -> Py { - unsafe { Py::from_owned_ptr(py, ffi::PyTuple_New(0)) } -} - -pub fn tuple_from_list(list: &PyList) -> Py { - unsafe { Py::from_owned_ptr(list.py(), ffi::PyList_AsTuple(list.as_ptr())) } -} diff --git a/crates/accelerate/src/results/mod.rs b/crates/accelerate/src/results/mod.rs index 2ac40bb307fe..36282a749e66 100644 --- a/crates/accelerate/src/results/mod.rs +++ b/crates/accelerate/src/results/mod.rs @@ -17,7 +17,7 @@ use pyo3::prelude::*; use pyo3::wrap_pyfunction; #[pymodule] -pub fn results(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn results(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(marginalization::marginal_counts))?; m.add_wrapped(wrap_pyfunction!(marginalization::marginal_distribution))?; m.add_wrapped(wrap_pyfunction!(marginalization::marginal_memory))?; diff --git a/crates/accelerate/src/sabre_layout.rs b/crates/accelerate/src/sabre_layout.rs index 8c237fe9a75a..343beb05ebae 100644 --- a/crates/accelerate/src/sabre_layout.rs +++ b/crates/accelerate/src/sabre_layout.rs @@ -216,7 +216,7 @@ fn layout_trial( } #[pymodule] -pub fn sabre_layout(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn sabre_layout(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(sabre_layout_and_routing))?; Ok(()) } diff --git a/crates/accelerate/src/sabre_swap/mod.rs b/crates/accelerate/src/sabre_swap/mod.rs index d07d31463e6c..c36a81233d27 100644 --- a/crates/accelerate/src/sabre_swap/mod.rs +++ b/crates/accelerate/src/sabre_swap/mod.rs @@ -760,7 +760,7 @@ fn choose_best_swap( } #[pymodule] -pub fn sabre_swap(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn sabre_swap(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(build_swap_map))?; m.add_class::()?; m.add_class::()?; diff --git a/crates/accelerate/src/sabre_swap/neighbor_table.rs b/crates/accelerate/src/sabre_swap/neighbor_table.rs index a795436caceb..be92153e7e8a 100644 --- a/crates/accelerate/src/sabre_swap/neighbor_table.rs +++ b/crates/accelerate/src/sabre_swap/neighbor_table.rs @@ -104,22 +104,22 @@ impl NeighborTable { } fn __getstate__(&self, py: Python<'_>) -> Py { - PyList::new( + PyList::new_bound( py, self.neighbors .iter() - .map(|v| PyList::new(py, v.iter()).to_object(py)), + .map(|v| PyList::new_bound(py, v.iter()).to_object(py)), ) .into() } - fn __setstate__(&mut self, state: &PyList) -> PyResult<()> { + fn __setstate__(&mut self, state: &Bound) -> PyResult<()> { self.neighbors = state .iter() .map(|v| { v.downcast::()? .iter() - .map(PyAny::extract) + .map(|b| b.extract()) .collect::>() }) .collect::>()?; diff --git a/crates/accelerate/src/sampled_exp_val.rs b/crates/accelerate/src/sampled_exp_val.rs index d71219ff16f6..b51ca3c98f0e 100644 --- a/crates/accelerate/src/sampled_exp_val.rs +++ b/crates/accelerate/src/sampled_exp_val.rs @@ -87,7 +87,7 @@ pub fn sampled_expval_complex( } #[pymodule] -pub fn sampled_exp_val(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn sampled_exp_val(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(sampled_expval_float))?; m.add_wrapped(wrap_pyfunction!(sampled_expval_complex))?; Ok(()) diff --git a/crates/accelerate/src/sparse_pauli_op.rs b/crates/accelerate/src/sparse_pauli_op.rs index ad4698639d5c..c8e0f0fb9316 100644 --- a/crates/accelerate/src/sparse_pauli_op.rs +++ b/crates/accelerate/src/sparse_pauli_op.rs @@ -258,7 +258,7 @@ fn decompose_dense_inner( } #[pymodule] -pub fn sparse_pauli_op(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn sparse_pauli_op(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(unordered_unique))?; m.add_wrapped(wrap_pyfunction!(decompose_dense))?; m.add_class::()?; diff --git a/crates/accelerate/src/stochastic_swap.rs b/crates/accelerate/src/stochastic_swap.rs index 748b7fb3b029..a3b52985dbf8 100644 --- a/crates/accelerate/src/stochastic_swap.rs +++ b/crates/accelerate/src/stochastic_swap.rs @@ -337,7 +337,7 @@ pub fn swap_trials( } #[pymodule] -pub fn stochastic_swap(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn stochastic_swap(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(swap_trials))?; m.add_class::()?; Ok(()) diff --git a/crates/accelerate/src/two_qubit_decompose.rs b/crates/accelerate/src/two_qubit_decompose.rs index 992b5e7bfd16..cef99a5c4788 100644 --- a/crates/accelerate/src/two_qubit_decompose.rs +++ b/crates/accelerate/src/two_qubit_decompose.rs @@ -469,7 +469,7 @@ impl Specialization { Self::fSimabbEquiv => 8, Self::fSimabmbEquiv => 9, }; - Ok((py.get_type::().getattr("_from_u8")?, (val,)).into_py(py)) + Ok((py.get_type_bound::().getattr("_from_u8")?, (val,)).into_py(py)) } #[staticmethod] @@ -599,7 +599,7 @@ impl TwoQubitWeylDecomposition { fn __reduce__(&self, py: Python) -> PyResult> { Ok(( - py.get_type::().getattr("_from_state")?, + py.get_type_bound::().getattr("_from_state")?, ( [self.a, self.b, self.c, self.global_phase], [ @@ -2051,7 +2051,7 @@ impl TwoQubitBasisDecomposer { } #[pymodule] -pub fn two_qubit_decompose(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn two_qubit_decompose(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(_num_basis_gates))?; m.add_class::()?; m.add_class::()?; diff --git a/crates/accelerate/src/utils.rs b/crates/accelerate/src/utils.rs index 41796cec2079..c0de89cb0fe7 100644 --- a/crates/accelerate/src/utils.rs +++ b/crates/accelerate/src/utils.rs @@ -54,7 +54,7 @@ pub fn eigenvalues(py: Python, unitary: PyReadonlyArray2>) -> PyObj } #[pymodule] -pub fn utils(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn utils(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(eigenvalues))?; Ok(()) } diff --git a/crates/accelerate/src/vf2_layout.rs b/crates/accelerate/src/vf2_layout.rs index 512da46731cb..e84b2bfbfb8c 100644 --- a/crates/accelerate/src/vf2_layout.rs +++ b/crates/accelerate/src/vf2_layout.rs @@ -107,7 +107,7 @@ pub fn score_layout( } #[pymodule] -pub fn vf2_layout(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn vf2_layout(m: &Bound) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(score_layout))?; m.add_class::()?; Ok(()) diff --git a/crates/qasm3/src/lib.rs b/crates/qasm3/src/lib.rs index 776724598d4b..12ff4c88a558 100644 --- a/crates/qasm3/src/lib.rs +++ b/crates/qasm3/src/lib.rs @@ -60,7 +60,7 @@ const STDGATES_INC_CUSTOM_GATES_ATTR: &str = "STDGATES_INC_GATES"; #[pyfunction] #[pyo3(pass_module, signature = (source, /, *, custom_gates=None, include_path=None))] pub fn loads( - module: Bound, + module: &Bound, py: Python, source: String, custom_gates: Option>, @@ -133,9 +133,9 @@ pub fn loads( signature = (pathlike_or_filelike, /, *, custom_gates=None, include_path=None), )] pub fn load( - module: Bound, + module: &Bound, py: Python, - pathlike_or_filelike: Bound, + pathlike_or_filelike: &Bound, custom_gates: Option>, include_path: Option>, ) -> PyResult {