diff --git a/Cargo.lock b/Cargo.lock index 244408d..93790b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arguments" @@ -17,9 +17,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "cfg-if" @@ -76,15 +76,21 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -111,9 +117,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "output" @@ -155,15 +161,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -177,9 +183,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.22.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831e8e819a138c36e212f3af3fd9eeffed6bf1510a805af35b0edee5ffa59433" +checksum = "e484fd2c8b4cb67ab05a318f1fd6fa8f199fcc30819f08f07d200809dba26c15" dependencies = [ "cfg-if", "indoc", @@ -195,9 +201,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.22.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e8730e591b14492a8945cdff32f089250b05f5accecf74aeddf9e8272ce1fa8" +checksum = "dc0e0469a84f208e20044b98965e1561028180219e35352a2afaf2b942beff3b" dependencies = [ "once_cell", "target-lexicon", @@ -205,9 +211,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.22.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e97e919d2df92eb88ca80a037969f44e5e70356559654962cbb3316d00300c6" +checksum = "eb1547a7f9966f6f1a0f0227564a9945fe36b90da5a93b3933fc3dc03fae372d" dependencies = [ "libc", "pyo3-build-config", @@ -215,9 +221,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.22.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb57983022ad41f9e683a599f2fd13c3664d7063a3ac5714cae4b7bee7d3f206" +checksum = "fdb6da8ec6fa5cedd1626c886fc8749bdcbb09424a86461eb8cdf096b7c33257" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -227,9 +233,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.22.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec480c0c51ddec81019531705acac51bcdbeae563557c982aa8263bb96880372" +checksum = "38a385202ff5a92791168b1136afae5059d3ac118457bb7bc304c197c2d33e7d" dependencies = [ "heck", "proc-macro2", @@ -240,9 +246,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -255,24 +261,24 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -281,11 +287,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -313,9 +320,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" dependencies = [ "proc-macro2", "quote", @@ -324,15 +331,15 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.15" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unindent" diff --git a/Cargo.toml b/Cargo.toml index ec90cb2..ff59c34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,10 @@ [workspace] members = ["exercises/*/*", "patcher"] resolver = "2" + +[workspace.dependencies] +anyhow = "1" +pyo3 = "0.23.3" +semver = "1.0.23" +serde = "1.0.204" +serde_json = "1.0.120" diff --git a/book/src/01_intro/01_setup.md b/book/src/01_intro/01_setup.md index 25a236c..651f05f 100644 --- a/book/src/01_intro/01_setup.md +++ b/book/src/01_intro/01_setup.md @@ -61,7 +61,7 @@ name = "setup" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.21.1" +pyo3 = "0.23.0" ``` Two things stand out in this file compared to a regular Rust project: diff --git a/book/src/01_intro/04_arguments.md b/book/src/01_intro/04_arguments.md index 095a4c1..12fae67 100644 --- a/book/src/01_intro/04_arguments.md +++ b/book/src/01_intro/04_arguments.md @@ -53,4 +53,4 @@ Don't try to use them to solve the exercise for this section: we'll cover them i ## References -- [The `FromPyObject` trait](https://docs.rs/pyo3/0.22.0/pyo3/conversion/trait.FromPyObject.html) +- [The `FromPyObject` trait](https://docs.rs/pyo3/0.23.3/pyo3/conversion/trait.FromPyObject.html) diff --git a/book/src/01_intro/05_gil.md b/book/src/01_intro/05_gil.md index 1dff49e..d9d2741 100644 --- a/book/src/01_intro/05_gil.md +++ b/book/src/01_intro/05_gil.md @@ -134,8 +134,8 @@ when we're interacting with the Python object during the conversion. ## References -- [`FromPyObject`](https://docs.rs/pyo3/0.22.1/pyo3/conversion/trait.FromPyObject.html) -- [`Python<'py>`](https://docs.rs/pyo3/0.22.1/pyo3/marker/struct.Python.html) +- [`FromPyObject`](https://docs.rs/pyo3/0.23.3/pyo3/conversion/trait.FromPyObject.html) +- [`Python<'py>`](https://docs.rs/pyo3/0.23.3/pyo3/marker/struct.Python.html) - [Global Interpreter Lock](https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock) - [Official guidance on Python-native vs Rust-native types](https://pyo3.rs/v0.22.0/conversions/tables#using-rust-library-types-vs-python-native-types) diff --git a/book/src/01_intro/06_output.md b/book/src/01_intro/06_output.md index 255ef9d..2b2bf6c 100644 --- a/book/src/01_intro/06_output.md +++ b/book/src/01_intro/06_output.md @@ -3,25 +3,32 @@ We've gone deep into the weeds of how `pyo3` handles arguments to your `#[pyfunction]`s. Let's now move our focus to output values: how do you return _something_ from your Rust functions to Python? -## `IntoPy` +## `IntoPyObject` Guess what? There's a trait for that too!\ -`IntoPy` is the counterpart of `FromPyObject`. It converts Rust values into Python objects: +`IntoPyObject` is the counterpart of `FromPyObject`. It converts Rust values into Python objects: ```rust -pub trait IntoPy: Sized { - fn into_py(self, py: Python<'_>) -> T; +pub trait IntoPyObject<'py>: Sized { + type Target; + type Output: BoundObject<'py, Self::Target>; + type Error: Into; + + fn into_pyobject(self, py: Python<'py>) -> Result; } ``` -The output type of your `#[pyfunction]` must implement `IntoPy`. +The output type of your `#[pyfunction]` must implement `IntoPyObject`. -### `IntoPy::into_py` +### `IntoPyObject::into_pyobject` -`IntoPy::into_py` expects two arguments: +`IntoPyObject::into_pyobject` expects two arguments: - `self`: the Rust value you want to convert into a Python object. -- `Python<'_>`: a GIL token that you can use to create new Python objects. +- `Python<'py>`: a GIL token that you can use to create new Python objects. + +The conversion can fail, so the method returns a `Result`.\ +The output type itself is more complex, so let's break it down using an example. ## Case study: a newtype @@ -29,20 +36,65 @@ Let's look at a simple example: a newtype that wraps a `u64`. We want it to be represented as a "plain" integer in Python. ```rust +use std::convert::Infallible; use pyo3::prelude::*; +use pyo3::types::PyInt; struct MyType { value: u64, } -impl IntoPy> for MyType { - fn into_py(self, py: Python<'_>) -> Py { - self.value.to_object(py) +impl<'py> IntoPyObject<'py> for MyType { + /// `Target` is the **concrete** Python type we want to use + /// to represent our Rust value. + /// The underlying Rust type is a `u64`, so we'll convert it to a `PyInt`, + /// a Python integer. + type Target = PyInt; + /// `Output`, instead, is a **wrapper** around the concrete type. + /// It captures the ownership relationship between the Python object + /// and the Python runtime. + /// In this case, we're using a `Bound` smart pointer to a `PyInt`. + /// The `'py` lifetime ensures that the Python object is owned + /// by the Python runtime. + type Output = Bound<'py, PyInt>; + /// Since the conversion can fail, we need to specify an error type. + /// We can't fail to convert a `u64` into a Python integer, + /// so we'll use `Infallible` as the error type. + type Error = Infallible; + + fn into_pyobject(self, py: Python<'py>) -> Result { + // `u64` already implements `IntoPyObject`, so we delegate + // to its implementation to do the actual conversion. + self.value.into_pyobject(py) } } ``` +### The `Output` associated type + +Let's focus on the `Output` associated type for a moment.\ +In almost all cases, you'll be setting `Output` to `Bound<'py, Self::Target>`[^syntax]. You're creating a new Python +object and its lifetime is tied to the Python runtime. + +In a few cases, you might be able to rely on [`Borrowed<'a, 'py, Self::Target>`](https://docs.rs/pyo3/0.23.3/pyo3/prelude/struct.Borrowed.html) +instead. +It's slightly faster[^conversation], but it's limited to scenarios where you are borrowing from an existing Python object—fairly +rare for an `IntoPyObject` implementation. + +There are no other options for `Output`, since `Output` must implement +[the `BoundObject` trait](https://docs.rs/pyo3/0.23.3/pyo3/trait.BoundObject.html), +the trait is [sealed](https://predr.ag/blog/definitive-guide-to-sealed-traits-in-rust/) and +those two types are the only implementors within `pyo3`.\ +If it helps, think of `Output` as an enum with two variants: `Bound` and `Borrowed`. + ## Provided implementations -`pyo3` provides out-of-the-box implementations of `IntoPy` for many Rust types, as well as for all `Py*` types. -Check out [its documentation](https://docs.rs/pyo3/0.22.0/pyo3/conversion/trait.IntoPy.html#) for an exhaustive list. +`pyo3` provides out-of-the-box implementations of `IntoPyObject` for many Rust types, as well as for all `Py*` types. +Check out [its documentation](https://docs.rs/pyo3/0.23.3/pyo3/conversion/trait.IntoPyObject.html#foreign-impls) +for an exhaustive list. + +[^syntax]: The actual syntax is a bit more complex: `type Output = Bound<'py, >::Target>>;`. +We've simplified it for clarity. + +[^conversation]: In addition to its documentation, you may find [this issue](https://github.com/PyO3/pyo3/issues/4467) +useful to understand the trade-offs between `&Bound` and `Borrowed`. diff --git a/book/src/02_classes/00_pyclass.md b/book/src/02_classes/00_pyclass.md index ed2b21f..c766452 100644 --- a/book/src/02_classes/00_pyclass.md +++ b/book/src/02_classes/00_pyclass.md @@ -31,9 +31,9 @@ fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { } ``` -## `IntoPy` +## `IntoPyObject` -Rust types that have been annotated with `#[pyclass]` automatically implement the `IntoPy` trait, thus +Rust types that have been annotated with `#[pyclass]` automatically implement the `IntoPyObject` trait, thus allowing you to return them from your `#[pyfunction]`s. For example, you can define a function that creates a new `Wallet` instance: diff --git a/book/src/02_classes/06_parent.md b/book/src/02_classes/06_parent.md index ca1ed01..3fe4112 100644 --- a/book/src/02_classes/06_parent.md +++ b/book/src/02_classes/06_parent.md @@ -79,7 +79,7 @@ impl Child { ``` `PyRef` represents an immutable reference to the Python object.\ -It allows us, in particular, to call the [`as_super`](https://docs.rs/pyo3/0.22.1/pyo3/pycell/struct.PyRef.html#method.as_super) method, +It allows us, in particular, to call the [`as_super`](https://docs.rs/pyo3/0.23.3/pyo3/pycell/struct.PyRef.html#method.as_super) method, which returns a reference to the parent class. ```rust diff --git a/exercises/01_intro/01_setup/Cargo.toml b/exercises/01_intro/01_setup/Cargo.toml index fcabaea..4f8af08 100644 --- a/exercises/01_intro/01_setup/Cargo.toml +++ b/exercises/01_intro/01_setup/Cargo.toml @@ -8,4 +8,4 @@ name = "setup" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/01_intro/02_modules/Cargo.toml b/exercises/01_intro/02_modules/Cargo.toml index af8e307..dbf3c14 100644 --- a/exercises/01_intro/02_modules/Cargo.toml +++ b/exercises/01_intro/02_modules/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/01_intro/03_functions/Cargo.toml b/exercises/01_intro/03_functions/Cargo.toml index c7e41b5..6618876 100644 --- a/exercises/01_intro/03_functions/Cargo.toml +++ b/exercises/01_intro/03_functions/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/01_intro/04_arguments/Cargo.toml b/exercises/01_intro/04_arguments/Cargo.toml index 0c24e4f..7f58665 100644 --- a/exercises/01_intro/04_arguments/Cargo.toml +++ b/exercises/01_intro/04_arguments/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/01_intro/05_gil/Cargo.toml b/exercises/01_intro/05_gil/Cargo.toml index 4fe8466..69467dc 100644 --- a/exercises/01_intro/05_gil/Cargo.toml +++ b/exercises/01_intro/05_gil/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/01_intro/06_output/Cargo.toml b/exercises/01_intro/06_output/Cargo.toml index 5143327..67ceea4 100644 --- a/exercises/01_intro/06_output/Cargo.toml +++ b/exercises/01_intro/06_output/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/01_intro/07_exceptions/Cargo.toml b/exercises/01_intro/07_exceptions/Cargo.toml index aa75b54..cb5545d 100644 --- a/exercises/01_intro/07_exceptions/Cargo.toml +++ b/exercises/01_intro/07_exceptions/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/01_intro/08_outro/Cargo.toml b/exercises/01_intro/08_outro/Cargo.toml index 8606ca1..bcd5e4f 100644 --- a/exercises/01_intro/08_outro/Cargo.toml +++ b/exercises/01_intro/08_outro/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/00_pyclass/Cargo.toml b/exercises/02_classes/00_pyclass/Cargo.toml index 4bded3d..76d3a02 100644 --- a/exercises/02_classes/00_pyclass/Cargo.toml +++ b/exercises/02_classes/00_pyclass/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/01_constructors/Cargo.toml b/exercises/02_classes/01_constructors/Cargo.toml index baef0d8..b0c8e45 100644 --- a/exercises/02_classes/01_constructors/Cargo.toml +++ b/exercises/02_classes/01_constructors/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/02_methods/Cargo.toml b/exercises/02_classes/02_methods/Cargo.toml index b3f3876..e0509b6 100644 --- a/exercises/02_classes/02_methods/Cargo.toml +++ b/exercises/02_classes/02_methods/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/03_setters/Cargo.toml b/exercises/02_classes/03_setters/Cargo.toml index ff4a67c..c653ad2 100644 --- a/exercises/02_classes/03_setters/Cargo.toml +++ b/exercises/02_classes/03_setters/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/04_static_methods/Cargo.toml b/exercises/02_classes/04_static_methods/Cargo.toml index 766fd9c..93cfacd 100644 --- a/exercises/02_classes/04_static_methods/Cargo.toml +++ b/exercises/02_classes/04_static_methods/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/05_inheritance/Cargo.toml b/exercises/02_classes/05_inheritance/Cargo.toml index 7e20527..5a77041 100644 --- a/exercises/02_classes/05_inheritance/Cargo.toml +++ b/exercises/02_classes/05_inheritance/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/06_parent/Cargo.toml b/exercises/02_classes/06_parent/Cargo.toml index e11e145..7c59cee 100644 --- a/exercises/02_classes/06_parent/Cargo.toml +++ b/exercises/02_classes/06_parent/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/exercises/02_classes/07_outro/Cargo.toml b/exercises/02_classes/07_outro/Cargo.toml index ac126eb..d47372b 100644 --- a/exercises/02_classes/07_outro/Cargo.toml +++ b/exercises/02_classes/07_outro/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.22" +pyo3 = { workspace = true } diff --git a/patcher/Cargo.toml b/patcher/Cargo.toml index 4712ea1..ff00bf7 100644 --- a/patcher/Cargo.toml +++ b/patcher/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1" -semver = "1.0.23" -serde = { version = "1.0.204", features = ["derive"] } -serde_json = "1.0.120" +anyhow = { workspace = true } +semver = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true }