From e611b09a01c92a1f300eb66b8b5932cc5248128c Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Mon, 1 Aug 2022 13:07:48 +0200 Subject: [PATCH 1/6] git ignore IDEs and pyenv file --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index a49d28c544d..48e96b283bc 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ pip-wheel-metadata valgrind-python.supp *.pyd lcov.info +.idea/ +.vscode/ +.python-version \ No newline at end of file From 9547802e135dcd4f871330d4ab505c3c124e477b Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Mon, 1 Aug 2022 14:38:38 +0200 Subject: [PATCH 2/6] add `as_sequence()` method on dict views --- src/types/dict.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/types/dict.rs b/src/types/dict.rs index bd75d89722b..c18b7ea46fc 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -3,7 +3,7 @@ use super::PyMapping; use crate::err::{self, PyErr, PyResult}; use crate::ffi::Py_ssize_t; -use crate::types::{PyAny, PyList}; +use crate::types::{PyAny, PyList, PySequence}; #[cfg(not(PyPy))] use crate::IntoPyPointer; use crate::{ffi, AsPyPointer, FromPyObject, IntoPy, PyObject, PyTryFrom, Python, ToPyObject}; @@ -34,6 +34,13 @@ pyobject_native_type_core!( #checkfunction=ffi::PyDictKeys_Check ); +#[cfg(not(PyPy))] +impl PyDictKeys { + pub fn as_sequence(&self) -> &PySequence { + unsafe { PySequence::try_from_unchecked(self) } + } +} + /// Represents a Python `dict_values`. #[cfg(not(PyPy))] #[repr(transparent)] @@ -46,6 +53,13 @@ pyobject_native_type_core!( #checkfunction=ffi::PyDictValues_Check ); +#[cfg(not(PyPy))] +impl PyDictValues { + pub fn as_sequence(&self) -> &PySequence { + unsafe { PySequence::try_from_unchecked(self) } + } +} + /// Represents a Python `dict_items`. #[cfg(not(PyPy))] #[repr(transparent)] @@ -58,6 +72,13 @@ pyobject_native_type_core!( #checkfunction=ffi::PyDictItems_Check ); +#[cfg(not(PyPy))] +impl PyDictItems { + pub fn as_sequence(&self) -> &PySequence { + unsafe { PySequence::try_from_unchecked(self) } + } +} + impl PyDict { /// Creates a new empty dictionary. pub fn new(py: Python<'_>) -> &PyDict { @@ -972,6 +993,14 @@ mod tests { let dict = abc_dict(py); let keys = dict.call_method0("keys").unwrap(); assert!(keys.is_instance(PyDictKeys::type_object(py)).unwrap()); + assert_eq!( + keys.cast_as::() + .unwrap() + .as_sequence() + .len() + .unwrap(), + 3 + ); }) } @@ -982,6 +1011,15 @@ mod tests { let dict = abc_dict(py); let values = dict.call_method0("values").unwrap(); assert!(values.is_instance(PyDictValues::type_object(py)).unwrap()); + assert_eq!( + values + .cast_as::() + .unwrap() + .as_sequence() + .len() + .unwrap(), + 3 + ); }) } @@ -992,6 +1030,15 @@ mod tests { let dict = abc_dict(py); let items = dict.call_method0("items").unwrap(); assert!(items.is_instance(PyDictItems::type_object(py)).unwrap()); + assert_eq!( + items + .cast_as::() + .unwrap() + .as_sequence() + .len() + .unwrap(), + 3 + ); }) } } From ec1ab4d181ba9e23b6ca2450d1c7d97b61b755bf Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Mon, 1 Aug 2022 14:58:28 +0200 Subject: [PATCH 3/6] add entry in changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42fb3c37640..5612e5880f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add `as_sequence()` method on dict views. [#2527](https://github.com/PyO3/pyo3/pull/2527) - Add `timezone_utc()`. [#1588](https://github.com/PyO3/pyo3/pull/1588) - Implement `ToPyObject` for `[T; N]`. [#2313](https://github.com/PyO3/pyo3/pull/2313) - Added the internal `IntoPyResult` trait to give better error messages when function return types do not implement `IntoPy`. [#2326](https://github.com/PyO3/pyo3/pull/2326) From 7fef4dbe7c1c0e875a1fbe474b024adaeeffc47d Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Mon, 1 Aug 2022 15:45:09 +0200 Subject: [PATCH 4/6] avoid useless import on pypy --- src/types/dict.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/types/dict.rs b/src/types/dict.rs index c18b7ea46fc..b1a7f999c8f 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -3,7 +3,11 @@ use super::PyMapping; use crate::err::{self, PyErr, PyResult}; use crate::ffi::Py_ssize_t; +#[cfg(PyPy)] +use crate::types::{PyAny, PyList}; +#[cfg(not(PyPy))] use crate::types::{PyAny, PyList, PySequence}; + #[cfg(not(PyPy))] use crate::IntoPyPointer; use crate::{ffi, AsPyPointer, FromPyObject, IntoPy, PyObject, PyTryFrom, Python, ToPyObject}; From 458c2af4ceda2aa1bbe14e47078c268ab48509ea Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Tue, 2 Aug 2022 02:11:46 +0200 Subject: [PATCH 5/6] merge imports --- src/types/dict.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/types/dict.rs b/src/types/dict.rs index b1a7f999c8f..fe62eb483f6 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -3,14 +3,10 @@ use super::PyMapping; use crate::err::{self, PyErr, PyResult}; use crate::ffi::Py_ssize_t; -#[cfg(PyPy)] use crate::types::{PyAny, PyList}; -#[cfg(not(PyPy))] -use crate::types::{PyAny, PyList, PySequence}; - -#[cfg(not(PyPy))] -use crate::IntoPyPointer; use crate::{ffi, AsPyPointer, FromPyObject, IntoPy, PyObject, PyTryFrom, Python, ToPyObject}; +#[cfg(not(PyPy))] +use crate::{types::PySequence, IntoPyPointer}; use std::collections::{BTreeMap, HashMap}; use std::ptr::NonNull; use std::{cmp, collections, hash}; From d7a507b06fc5ecb684d6c382622830e3dea581a4 Mon Sep 17 00:00:00 2001 From: Eric Jolibois Date: Tue, 2 Aug 2022 02:15:05 +0200 Subject: [PATCH 6/6] add comments on methods --- src/types/dict.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/dict.rs b/src/types/dict.rs index fe62eb483f6..ed35df47e34 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -36,6 +36,7 @@ pyobject_native_type_core!( #[cfg(not(PyPy))] impl PyDictKeys { + /// Returns `self` cast as a `PySequence`. pub fn as_sequence(&self) -> &PySequence { unsafe { PySequence::try_from_unchecked(self) } } @@ -55,6 +56,7 @@ pyobject_native_type_core!( #[cfg(not(PyPy))] impl PyDictValues { + /// Returns `self` cast as a `PySequence`. pub fn as_sequence(&self) -> &PySequence { unsafe { PySequence::try_from_unchecked(self) } } @@ -74,6 +76,7 @@ pyobject_native_type_core!( #[cfg(not(PyPy))] impl PyDictItems { + /// Returns `self` cast as a `PySequence`. pub fn as_sequence(&self) -> &PySequence { unsafe { PySequence::try_from_unchecked(self) } }