diff --git a/Cargo.lock b/Cargo.lock index 0c58a34..1763b36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,7 +84,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 2.1.1", + "rustc-hash", "shlex", "syn 2.0.106", ] @@ -158,15 +158,6 @@ dependencies = [ "parking_lot_core", ] -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - [[package]] name = "diff" version = "0.1.13" @@ -255,12 +246,6 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -277,12 +262,6 @@ dependencies = [ "hashbrown 0.16.0", ] -[[package]] -name = "indoc" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" - [[package]] name = "internment" version = "0.8.6" @@ -442,7 +421,7 @@ dependencies = [ "libc", "libloading", "num-complex", - "paste", + "pastey", "pkg-config", "quil-rs", "serde_json", @@ -493,15 +472,6 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -581,12 +551,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - [[package]] name = "num-integer" version = "0.1.46" @@ -618,9 +582,9 @@ dependencies = [ [[package]] name = "numpy" -version = "0.20.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef41cbb417ea83b30525259e30ccef6af39b31c240bda578889494c5392d331" +checksum = "6a5b15d63a5ff39e378daed0e1340d3a5964703ea9712eb09a0dc66fade996f4" dependencies = [ "libc", "ndarray", @@ -628,7 +592,8 @@ dependencies = [ "num-integer", "num-traits", "pyo3", - "rustc-hash 1.1.0", + "pyo3-build-config", + "rustc-hash", ] [[package]] @@ -637,16 +602,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - [[package]] name = "parking_lot_core" version = "0.9.11" @@ -666,6 +621,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" + [[package]] name = "petgraph" version = "0.6.5" @@ -688,12 +649,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -724,39 +679,33 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.20.3" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bdbb96d49157e65d45cc287af5f32ffadd5f4761438b527b055fb0d4bb8233" +checksum = "4688ddedf473e32662b9b067670129a8afb8c18e351482c70d62ba4a88171e8b" dependencies = [ - "cfg-if", - "indoc", "inventory", "libc", - "memoffset", - "num-complex", - "parking_lot", + "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", - "unindent", ] [[package]] name = "pyo3-build-config" -version = "0.20.3" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deaa5745de3f5231ce10517a1f5dd97d53e5a2fd77aa6b5842292085831d48d7" +checksum = "f41027e41b4bd03f6e60f9f417fe24a6341a6bb744edd62b6f709f2a52ea30e9" dependencies = [ - "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" -version = "0.20.3" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b42531d03e08d4ef1f6e85a2ed422eb678b8cd62b762e53891c05faf0d4afa" +checksum = "e591a95526fead067432c3b3a33fc74770b87b1e04e73671090d9c2055a2b327" dependencies = [ "libc", "pyo3-build-config", @@ -764,9 +713,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.20.3" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7305c720fa01b8055ec95e484a6eca7a83c841267f0dd5280f0c8b8551d2c158" +checksum = "73225868fc1cd84eef2c3c230ddb91273bf1de46aeb8a4248da76d32a0924a1c" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -776,13 +725,12 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.20.3" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7e9b68bb9c3149c5b0cade5d07f953d6d125eb4337723c4ccdb665f1f96185" +checksum = "571575aa3749fa6216757dd47d2a3e7ef360f329a40f0666a9fbd14889024952" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", - "pyo3-build-config", "quote", "syn 2.0.106", ] @@ -913,24 +861,14 @@ checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "rigetti-pyo3" -version = "0.4.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd34d8ee532b7e640f53b99286534e6e2f2b80726865c81074dfe44c37e124b" +checksum = "54283d7a88051a30fd1d508c22a1c5bca9b74ef9572d1e43ee707c5f8417e3d0" dependencies = [ - "internment", - "num-complex", - "num-traits", - "paste", + "pastey", "pyo3", - "time", ] -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -1075,7 +1013,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", @@ -1106,9 +1044,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.16" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "thiserror" @@ -1150,25 +1088,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "time" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde", - "time-core", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - [[package]] name = "typenum" version = "1.18.0" @@ -1181,12 +1100,6 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" - [[package]] name = "version_check" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index c15f290..7650574 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,23 @@ [workspace] resolver = "2" members = ["lib", "python"] + +[workspace.dependencies] +assert2 = "0.3.11" +bindgen = "0.72" +cc = "1.0" +libc = "0.2" +libloading = "0.8.0" +libquil-sys = { path = "lib" } +num-complex = "0.4.4" +pastey = "0.2" +pkg-config = "0.3" +quil-rs = "0.32.0" +serde_json = "1.0.105" +thiserror = "2.0" + +# PyO3 dependencies (must be kept compatible with each other) +pyo3 = "0.29" +pyo3-build-config = "0.29" +numpy = "0.29" +rigetti-pyo3 = "0.8" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index d347ed9..5793d7b 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -15,20 +15,20 @@ readme = "../README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libc = "0.2" -libloading = "0.8.0" -num-complex = "0.4.4" -serde_json = "1.0.105" -thiserror = "2.0" -paste = "1.0.6" +libc = { workspace = true } +libloading = { workspace = true } +num-complex = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +pastey = { workspace = true } [build-dependencies] -cc = { version = "1.0", features = ["parallel"] } -pkg-config = "0.3" -bindgen = "0.72" -thiserror = "2.0" +cc = { workspace = true, features = ["parallel"] } +pkg-config = { workspace = true } +bindgen = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] -assert2 = "0.3.11" -quil-rs = "0.32.0" +assert2 = { workspace = true } +quil-rs = { workspace = true } diff --git a/lib/src/quilc.rs b/lib/src/quilc.rs index 2b7ac51..c879ffc 100644 --- a/lib/src/quilc.rs +++ b/lib/src/quilc.rs @@ -219,7 +219,7 @@ macro_rules! get_metadata_field { let mut var = $field_type::default(); let mut present = 0; - paste::paste!( + pastey::paste!( let err = []( $metadata_ptr, std::ptr::addr_of_mut!(var) as *mut _, diff --git a/python/Cargo.toml b/python/Cargo.toml index b4650d4..4f1c3f2 100644 --- a/python/Cargo.toml +++ b/python/Cargo.toml @@ -8,12 +8,12 @@ name = "libquil" crate-type = ["cdylib", "rlib"] [dependencies] -libloading = "0.8.0" -libquil-sys = { path = "../lib" } +libloading = { workspace = true } +libquil-sys = { workspace = true } # pyo3 dependencies should be updated together -numpy = { version = "0.20" } -pyo3 = { version = "0.20", features = ["extension-module"] } -rigetti-pyo3 = "0.4" +numpy = { workspace = true } +pyo3 = { workspace = true, features = ["extension-module"] } +rigetti-pyo3 = { workspace = true } [build-dependencies] -pyo3-build-config = { version = "0.20" } +pyo3-build-config = { workspace = true } diff --git a/python/src/chip.rs b/python/src/chip.rs index 59d5401..9c41878 100644 --- a/python/src/chip.rs +++ b/python/src/chip.rs @@ -1,20 +1,15 @@ use pyo3::prelude::*; -use pyo3::types::PyString; -use rigetti_pyo3::{py_wrap_struct, ToPythonError}; +#[pyclass(name = "Chip", unsendable)] +pub struct PyChip(pub(crate) libquil_sys::quilc::Chip); -#[derive(Clone)] -pub struct Chip(pub(crate) libquil_sys::quilc::Chip); - -py_wrap_struct! { - PyChip(Chip) as "Chip" { - py -> rs { - str: Py => Chip { - let s = str.as_ref(py).to_str()?; - let lc: libquil_sys::quilc::Chip = s.parse().map_err(|err| crate::RustLibquilQuilcError::from(err).to_py_err())?; - let c: Chip = Chip(lc); - Ok::<_, PyErr>(c) - } - }, +#[pymethods] +impl PyChip { + #[new] + pub fn new(s: &str) -> PyResult { + let chip: libquil_sys::quilc::Chip = s + .parse() + .map_err(|err| PyErr::from(crate::RustLibquilQuilcError::from(err)))?; + Ok(Self(chip)) } } diff --git a/python/src/compile.rs b/python/src/compile.rs index 0852c47..0a7dbc4 100644 --- a/python/src/compile.rs +++ b/python/src/compile.rs @@ -1,27 +1,31 @@ -use pyo3::{exceptions::PyValueError, prelude::*, types::PyBool}; -use rigetti_pyo3::{py_wrap_data_struct, PyWrapper, ToPythonError}; +use pyo3::{exceptions::PyValueError, prelude::*}; -#[derive(Clone)] -pub struct CompileOptions { +#[pyclass(name = "CompileOptions", skip_from_py_object)] +#[derive(Debug, Clone, Default)] +pub struct PyCompileOptions { pub protoquil: Option, } -py_wrap_data_struct! { - PyCompileOptions(CompileOptions) as "CompileOptions" { - protoquil: Option => Option> - } -} - #[pymethods] impl PyCompileOptions { #[new] - pub fn new(py: Python<'_>, protoquil: Option>) -> PyResult { - let protoquil = protoquil.map(|p| p.is_true(py)).transpose()?; - Ok(Self(CompileOptions { protoquil })) + #[pyo3(signature = (protoquil=None))] + pub fn new(protoquil: Option) -> Self { + Self { protoquil } + } + + #[getter] + pub fn get_protoquil(&self) -> Option { + self.protoquil + } + + #[setter] + pub fn set_protoquil(&mut self, protoquil: Option) { + self.protoquil = protoquil; } } -#[pyclass(name = "CompilationMetadata")] +#[pyclass(name = "CompilationMetadata", skip_from_py_object)] #[derive(Debug, Clone)] pub struct PyCompilationMetadata(libquil_sys::quilc::CompilationMetadata); @@ -94,14 +98,14 @@ pub fn compile( chip: &crate::chip::PyChip, options: Option<&PyCompileOptions>, ) -> PyResult { - let protoquil = options.and_then(|e| e.as_inner().protoquil); + let protoquil = options.and_then(|e| e.protoquil); let compilation_result = if let Some(true) = protoquil { - libquil_sys::quilc::compile_protoquil(&program.as_inner().0, &chip.as_inner().0) - .map_err(|e| crate::RustLibquilQuilcError::from(e).to_py_err())? + libquil_sys::quilc::compile_protoquil(&program.0, &chip.0) + .map_err(|e| PyErr::from(crate::RustLibquilQuilcError::from(e)))? } else { - libquil_sys::quilc::compile_program(&program.as_inner().0, &chip.as_inner().0) - .map_err(|e| crate::RustLibquilQuilcError::from(e).to_py_err())? + libquil_sys::quilc::compile_program(&program.0, &chip.0) + .map_err(|e| PyErr::from(crate::RustLibquilQuilcError::from(e)))? }; let metadata = compilation_result.metadata.map(PyCompilationMetadata); diff --git a/python/src/lib.rs b/python/src/lib.rs index 9cef4b0..0738ff1 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -4,26 +4,43 @@ mod program; use pyo3::prelude::*; -use rigetti_pyo3::{create_init_submodule, py_wrap_error, wrap_error}; +use rigetti_pyo3::{create_init_submodule, exception}; -wrap_error! { - RustLibquilQuilcError(libquil_sys::quilc::Error) +/// Newtype around [`libquil_sys::quilc::Error`] so it can be converted into a +/// Python exception (the orphan rule forbids implementing `From` for the +/// foreign error type directly). +#[derive(Debug)] +pub struct RustLibquilQuilcError(libquil_sys::quilc::Error); + +impl From for RustLibquilQuilcError { + fn from(err: libquil_sys::quilc::Error) -> Self { + Self(err) + } +} + +impl std::fmt::Display for RustLibquilQuilcError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } } -py_wrap_error!( - libquil, +impl std::error::Error for RustLibquilQuilcError {} + +exception!( RustLibquilQuilcError, + "libquil", PyLibquilError, pyo3::exceptions::PyException ); #[pymodule] -fn libquil(py: Python<'_>, m: &PyModule) -> PyResult<()> { +fn libquil(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { init_submodule("libquil", py, m)?; Ok(()) } create_init_submodule! { classes: [chip::PyChip, program::PyProgram, compile::PyCompileOptions], + errors: [PyLibquilError], funcs: [compile::compile], } diff --git a/python/src/program.rs b/python/src/program.rs index 35b66af..33798db 100644 --- a/python/src/program.rs +++ b/python/src/program.rs @@ -1,18 +1,15 @@ use pyo3::prelude::*; -use pyo3::types::PyString; -use rigetti_pyo3::{py_wrap_struct, ToPythonError}; -#[derive(Clone)] -pub struct Program(pub(crate) libquil_sys::quilc::Program); +#[pyclass(name = "Program", unsendable)] +pub struct PyProgram(pub(crate) libquil_sys::quilc::Program); -py_wrap_struct! { - PyProgram(Program) as "Program" { - py -> rs { - str: Py => Chip { - let s = str.as_ref(py).to_str()?; - let program = s.parse().map_err(|err| crate::RustLibquilQuilcError::from(err).to_py_err())?; - Ok::<_, PyErr>(Program(program)) - } - }, +#[pymethods] +impl PyProgram { + #[new] + pub fn new(s: &str) -> PyResult { + let program: libquil_sys::quilc::Program = s + .parse() + .map_err(|err| PyErr::from(crate::RustLibquilQuilcError::from(err)))?; + Ok(Self(program)) } }