Merge pull request #3678 from davidhewitt/mapping2
implement `PyMappingMethods`
This commit is contained in:
commit
7f626b26d4
|
@ -32,5 +32,6 @@ pub use crate::wrap_pyfunction;
|
||||||
// pub(crate) use crate::types::bytes::PyBytesMethods;
|
// pub(crate) use crate::types::bytes::PyBytesMethods;
|
||||||
// pub(crate) use crate::types::dict::PyDictMethods;
|
// pub(crate) use crate::types::dict::PyDictMethods;
|
||||||
// pub(crate) use crate::types::float::PyFloatMethods;
|
// pub(crate) use crate::types::float::PyFloatMethods;
|
||||||
|
// pub(crate) use crate::types::mapping::PyMappingMethods;
|
||||||
// pub(crate) use crate::types::sequence::PySequenceMethods;
|
// pub(crate) use crate::types::sequence::PySequenceMethods;
|
||||||
// pub(crate) use crate::types::string::PyStringMethods;
|
// pub(crate) use crate::types::string::PyStringMethods;
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use crate::err::{PyDowncastError, PyResult};
|
use crate::err::{PyDowncastError, PyResult};
|
||||||
|
use crate::ffi_ptr_ext::FfiPtrExt;
|
||||||
|
use crate::instance::Py2;
|
||||||
|
use crate::py_result_ext::PyResultExt;
|
||||||
use crate::sync::GILOnceCell;
|
use crate::sync::GILOnceCell;
|
||||||
use crate::type_object::PyTypeInfo;
|
use crate::type_object::PyTypeInfo;
|
||||||
|
use crate::types::any::PyAnyMethods;
|
||||||
use crate::types::{PyAny, PyDict, PySequence, PyType};
|
use crate::types::{PyAny, PyDict, PySequence, PyType};
|
||||||
use crate::{ffi, Py, PyNativeType, PyTypeCheck, Python, ToPyObject};
|
use crate::{ffi, Py, PyNativeType, PyTypeCheck, Python, ToPyObject};
|
||||||
|
|
||||||
|
@ -16,15 +20,13 @@ impl PyMapping {
|
||||||
/// This is equivalent to the Python expression `len(self)`.
|
/// This is equivalent to the Python expression `len(self)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> PyResult<usize> {
|
pub fn len(&self) -> PyResult<usize> {
|
||||||
let v = unsafe { ffi::PyMapping_Size(self.as_ptr()) };
|
Py2::borrowed_from_gil_ref(&self).len()
|
||||||
crate::err::error_on_minusone(self.py(), v)?;
|
|
||||||
Ok(v as usize)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the mapping is empty.
|
/// Returns whether the mapping is empty.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_empty(&self) -> PyResult<bool> {
|
pub fn is_empty(&self) -> PyResult<bool> {
|
||||||
self.len().map(|l| l == 0)
|
Py2::borrowed_from_gil_ref(&self).is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if the mapping contains the specified key.
|
/// Determines if the mapping contains the specified key.
|
||||||
|
@ -34,7 +36,7 @@ impl PyMapping {
|
||||||
where
|
where
|
||||||
K: ToPyObject,
|
K: ToPyObject,
|
||||||
{
|
{
|
||||||
PyAny::contains(self, key)
|
Py2::borrowed_from_gil_ref(&self).contains(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the item in self with key `key`.
|
/// Gets the item in self with key `key`.
|
||||||
|
@ -47,7 +49,9 @@ impl PyMapping {
|
||||||
where
|
where
|
||||||
K: ToPyObject,
|
K: ToPyObject,
|
||||||
{
|
{
|
||||||
PyAny::get_item(self, key)
|
Py2::borrowed_from_gil_ref(&self)
|
||||||
|
.get_item(key)
|
||||||
|
.map(Py2::into_gil_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the item in self with key `key`.
|
/// Sets the item in self with key `key`.
|
||||||
|
@ -59,7 +63,7 @@ impl PyMapping {
|
||||||
K: ToPyObject,
|
K: ToPyObject,
|
||||||
V: ToPyObject,
|
V: ToPyObject,
|
||||||
{
|
{
|
||||||
PyAny::set_item(self, key, value)
|
Py2::borrowed_from_gil_ref(&self).set_item(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes the item with key `key`.
|
/// Deletes the item with key `key`.
|
||||||
|
@ -70,34 +74,31 @@ impl PyMapping {
|
||||||
where
|
where
|
||||||
K: ToPyObject,
|
K: ToPyObject,
|
||||||
{
|
{
|
||||||
PyAny::del_item(self, key)
|
Py2::borrowed_from_gil_ref(&self).del_item(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a sequence containing all keys in the mapping.
|
/// Returns a sequence containing all keys in the mapping.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn keys(&self) -> PyResult<&PySequence> {
|
pub fn keys(&self) -> PyResult<&PySequence> {
|
||||||
unsafe {
|
Py2::borrowed_from_gil_ref(&self)
|
||||||
self.py()
|
.keys()
|
||||||
.from_owned_ptr_or_err(ffi::PyMapping_Keys(self.as_ptr()))
|
.map(Py2::into_gil_ref)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a sequence containing all values in the mapping.
|
/// Returns a sequence containing all values in the mapping.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn values(&self) -> PyResult<&PySequence> {
|
pub fn values(&self) -> PyResult<&PySequence> {
|
||||||
unsafe {
|
Py2::borrowed_from_gil_ref(&self)
|
||||||
self.py()
|
.values()
|
||||||
.from_owned_ptr_or_err(ffi::PyMapping_Values(self.as_ptr()))
|
.map(Py2::into_gil_ref)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a sequence of tuples of all (key, value) pairs in the mapping.
|
/// Returns a sequence of tuples of all (key, value) pairs in the mapping.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn items(&self) -> PyResult<&PySequence> {
|
pub fn items(&self) -> PyResult<&PySequence> {
|
||||||
unsafe {
|
Py2::borrowed_from_gil_ref(&self)
|
||||||
self.py()
|
.items()
|
||||||
.from_owned_ptr_or_err(ffi::PyMapping_Items(self.as_ptr()))
|
.map(Py2::into_gil_ref)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a pyclass as a subclass of `collections.abc.Mapping` (from the Python standard
|
/// Register a pyclass as a subclass of `collections.abc.Mapping` (from the Python standard
|
||||||
|
@ -110,6 +111,135 @@ impl PyMapping {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implementation of functionality for [`PyMapping`].
|
||||||
|
///
|
||||||
|
/// These methods are defined for the `Py2<'py, PyMapping>` smart pointer, so to use method call
|
||||||
|
/// syntax these methods are separated into a trait, because stable Rust does not yet support
|
||||||
|
/// `arbitrary_self_types`.
|
||||||
|
#[doc(alias = "PyMapping")]
|
||||||
|
pub(crate) trait PyMappingMethods<'py> {
|
||||||
|
/// Returns the number of objects in the mapping.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python expression `len(self)`.
|
||||||
|
fn len(&self) -> PyResult<usize>;
|
||||||
|
|
||||||
|
/// Returns whether the mapping is empty.
|
||||||
|
fn is_empty(&self) -> PyResult<bool>;
|
||||||
|
|
||||||
|
/// Determines if the mapping contains the specified key.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python expression `key in self`.
|
||||||
|
fn contains<K>(&self, key: K) -> PyResult<bool>
|
||||||
|
where
|
||||||
|
K: ToPyObject;
|
||||||
|
|
||||||
|
/// Gets the item in self with key `key`.
|
||||||
|
///
|
||||||
|
/// Returns an `Err` if the item with specified key is not found, usually `KeyError`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python expression `self[key]`.
|
||||||
|
fn get_item<K>(&self, key: K) -> PyResult<Py2<'py, PyAny>>
|
||||||
|
where
|
||||||
|
K: ToPyObject;
|
||||||
|
|
||||||
|
/// Sets the item in self with key `key`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python expression `self[key] = value`.
|
||||||
|
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||||
|
where
|
||||||
|
K: ToPyObject,
|
||||||
|
V: ToPyObject;
|
||||||
|
|
||||||
|
/// Deletes the item with key `key`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python statement `del self[key]`.
|
||||||
|
fn del_item<K>(&self, key: K) -> PyResult<()>
|
||||||
|
where
|
||||||
|
K: ToPyObject;
|
||||||
|
|
||||||
|
/// Returns a sequence containing all keys in the mapping.
|
||||||
|
fn keys(&self) -> PyResult<Py2<'py, PySequence>>;
|
||||||
|
|
||||||
|
/// Returns a sequence containing all values in the mapping.
|
||||||
|
fn values(&self) -> PyResult<Py2<'py, PySequence>>;
|
||||||
|
|
||||||
|
/// Returns a sequence of tuples of all (key, value) pairs in the mapping.
|
||||||
|
fn items(&self) -> PyResult<Py2<'py, PySequence>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'py> PyMappingMethods<'py> for Py2<'py, PyMapping> {
|
||||||
|
#[inline]
|
||||||
|
fn len(&self) -> PyResult<usize> {
|
||||||
|
let v = unsafe { ffi::PyMapping_Size(self.as_ptr()) };
|
||||||
|
crate::err::error_on_minusone(self.py(), v)?;
|
||||||
|
Ok(v as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_empty(&self) -> PyResult<bool> {
|
||||||
|
self.len().map(|l| l == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains<K>(&self, key: K) -> PyResult<bool>
|
||||||
|
where
|
||||||
|
K: ToPyObject,
|
||||||
|
{
|
||||||
|
PyAnyMethods::contains(&**self, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_item<K>(&self, key: K) -> PyResult<Py2<'py, PyAny>>
|
||||||
|
where
|
||||||
|
K: ToPyObject,
|
||||||
|
{
|
||||||
|
PyAnyMethods::get_item(&**self, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||||
|
where
|
||||||
|
K: ToPyObject,
|
||||||
|
V: ToPyObject,
|
||||||
|
{
|
||||||
|
PyAnyMethods::set_item(&**self, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn del_item<K>(&self, key: K) -> PyResult<()>
|
||||||
|
where
|
||||||
|
K: ToPyObject,
|
||||||
|
{
|
||||||
|
PyAnyMethods::del_item(&**self, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn keys(&self) -> PyResult<Py2<'py, PySequence>> {
|
||||||
|
unsafe {
|
||||||
|
ffi::PyMapping_Keys(self.as_ptr())
|
||||||
|
.assume_owned_or_err(self.py())
|
||||||
|
.downcast_into_unchecked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn values(&self) -> PyResult<Py2<'py, PySequence>> {
|
||||||
|
unsafe {
|
||||||
|
ffi::PyMapping_Values(self.as_ptr())
|
||||||
|
.assume_owned_or_err(self.py())
|
||||||
|
.downcast_into_unchecked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn items(&self) -> PyResult<Py2<'py, PySequence>> {
|
||||||
|
unsafe {
|
||||||
|
ffi::PyMapping_Items(self.as_ptr())
|
||||||
|
.assume_owned_or_err(self.py())
|
||||||
|
.downcast_into_unchecked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static MAPPING_ABC: GILOnceCell<Py<PyType>> = GILOnceCell::new();
|
static MAPPING_ABC: GILOnceCell<Py<PyType>> = GILOnceCell::new();
|
||||||
|
|
||||||
fn get_mapping_abc(py: Python<'_>) -> PyResult<&PyType> {
|
fn get_mapping_abc(py: Python<'_>) -> PyResult<&PyType> {
|
||||||
|
|
|
@ -290,7 +290,7 @@ mod frozenset;
|
||||||
mod function;
|
mod function;
|
||||||
mod iterator;
|
mod iterator;
|
||||||
pub(crate) mod list;
|
pub(crate) mod list;
|
||||||
mod mapping;
|
pub(crate) mod mapping;
|
||||||
mod memoryview;
|
mod memoryview;
|
||||||
mod module;
|
mod module;
|
||||||
mod none;
|
mod none;
|
||||||
|
|
Loading…
Reference in a new issue