add migration guide entry for `PyDict::get_item`
This commit is contained in:
parent
8ddfef04bc
commit
c7f834ad87
|
@ -9,6 +9,56 @@ For a detailed list of all changes, see the [CHANGELOG](changelog.md).
|
||||||
|
|
||||||
PyO3 0.20 has increased minimum Rust version to 1.56. This enables use of newer language features and simplifies maintenance of the project.
|
PyO3 0.20 has increased minimum Rust version to 1.56. This enables use of newer language features and simplifies maintenance of the project.
|
||||||
|
|
||||||
|
### `PyDict::get_item` now returns a `Result`
|
||||||
|
|
||||||
|
`PyDict::get_item` in PyO3 0.19 and older was implemented using a Python API which would suppress all exceptions and return `None` in those cases. This included errors in `__hash__` and `__eq__` implementations of the key being looked up.
|
||||||
|
|
||||||
|
Newer recommendations by the Python core developers advise against using these APIs which suppress exceptions, instead allowing exceptions to bubble upwards. `PyDict::get_item_with_error` already implemented this recommended behavior, so that API has been renamed to `PyDict::get_item`.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```rust,ignore
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::exceptions::PyTypeError;
|
||||||
|
use pyo3::types::{PyDict, IntoPyDict};
|
||||||
|
|
||||||
|
# fn main() {
|
||||||
|
# let _ =
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let dict: &PyDict = [("a", 1)].into_py_dict(py);
|
||||||
|
// `a` is in the dictionary, with value 1
|
||||||
|
assert!(dict.get_item("a").map_or(Ok(false), |x| x.eq(1))?);
|
||||||
|
// `b` is not in the dictionary
|
||||||
|
assert!(dict.get_item("b").is_none());
|
||||||
|
// `dict` is not hashable, so this fails with a `TypeError`
|
||||||
|
assert!(dict.get_item_with_error(dict).unwrap_err().is_instance_of::<PyTypeError>(py));
|
||||||
|
});
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::exceptions::PyTypeError;
|
||||||
|
use pyo3::types::{PyDict, IntoPyDict};
|
||||||
|
|
||||||
|
# fn main() {
|
||||||
|
# let _ =
|
||||||
|
Python::with_gil(|py| -> PyResult<()> {
|
||||||
|
let dict: &PyDict = [("a", 1)].into_py_dict(py);
|
||||||
|
// `a` is in the dictionary, with value 1
|
||||||
|
assert!(dict.get_item("a")?.map_or(Ok(false), |x| x.eq(1))?);
|
||||||
|
// `b` is not in the dictionary
|
||||||
|
assert!(dict.get_item("b")?.is_none());
|
||||||
|
// `dict` is not hashable, so this fails with a `TypeError`
|
||||||
|
assert!(dict.get_item(dict).unwrap_err().is_instance_of::<PyTypeError>(py));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
### Required arguments are no longer accepted after optional arguments
|
### Required arguments are no longer accepted after optional arguments
|
||||||
|
|
||||||
[Trailing `Option<T>` arguments](./function/signature.md#trailing-optional-arguments) have an automatic default of `None`. To avoid unwanted changes when modifying function signatures, in PyO3 0.18 it was deprecated to have a required argument after an `Option<T>` argument without using `#[pyo3(signature = (...))]` to specify the intended defaults. In PyO3 0.20, this becomes a hard error.
|
[Trailing `Option<T>` arguments](./function/signature.md#trailing-optional-arguments) have an automatic default of `None`. To avoid unwanted changes when modifying function signatures, in PyO3 0.18 it was deprecated to have a required argument after an `Option<T>` argument without using `#[pyo3(signature = (...))]` to specify the intended defaults. In PyO3 0.20, this becomes a hard error.
|
||||||
|
|
Loading…
Reference in New Issue