add PyDict keys,values,items methods
This commit is contained in:
parent
97c6b7591a
commit
a00ae1757c
|
@ -5,7 +5,6 @@
|
|||
//! Python argument parsing
|
||||
|
||||
use ffi;
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use objects::{PyObjectRef, PyTuple, PyDict, PyString, exc};
|
||||
use err::{self, PyResult};
|
||||
|
@ -88,13 +87,13 @@ pub fn parse_args<'p>(py: Python<'p>,
|
|||
}
|
||||
if !accept_kwargs && used_keywords != nkeywords {
|
||||
// check for extraneous keyword arguments
|
||||
for (key, _value) in kwargs.unwrap().items() {
|
||||
let key = PyString::downcast_from(key.as_ref(py))?.to_string()?;
|
||||
for item in kwargs.unwrap().items().iter() {
|
||||
let item = PyTuple::downcast_from(item)?;
|
||||
let key = PyString::downcast_from(item.get_item(0))?.to_string()?;
|
||||
if !params.iter().any(|p| p.name == key) {
|
||||
return Err(err::PyErr::new::<exc::TypeError, _>(
|
||||
py,
|
||||
format!("'{}' is an invalid keyword argument for this function",
|
||||
key)));
|
||||
format!("'{}' is an invalid keyword argument for this function", key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,36 +44,24 @@ pub unsafe fn PyDictViewSet_Check(op : *mut PyObject) -> c_int {
|
|||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyDict_New() -> *mut PyObject;
|
||||
pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject)
|
||||
-> *mut PyObject;
|
||||
pub fn PyDict_GetItemWithError(mp: *mut PyObject, key: *mut PyObject)
|
||||
-> *mut PyObject;
|
||||
pub fn PyDict_SetItem(mp: *mut PyObject, key: *mut PyObject,
|
||||
item: *mut PyObject) -> c_int;
|
||||
pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject)
|
||||
-> c_int;
|
||||
pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject;
|
||||
pub fn PyDict_GetItemWithError(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject;
|
||||
pub fn PyDict_SetItem(mp: *mut PyObject, key: *mut PyObject, item: *mut PyObject) -> c_int;
|
||||
pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) -> c_int;
|
||||
pub fn PyDict_Clear(mp: *mut PyObject) -> ();
|
||||
pub fn PyDict_Next(mp: *mut PyObject, pos: *mut Py_ssize_t,
|
||||
key: *mut *mut PyObject, value: *mut *mut PyObject)
|
||||
-> c_int;
|
||||
key: *mut *mut PyObject, value: *mut *mut PyObject) -> c_int;
|
||||
pub fn PyDict_Keys(mp: *mut PyObject) -> *mut PyObject;
|
||||
pub fn PyDict_Values(mp: *mut PyObject) -> *mut PyObject;
|
||||
pub fn PyDict_Items(mp: *mut PyObject) -> *mut PyObject;
|
||||
pub fn PyDict_Size(mp: *mut PyObject) -> Py_ssize_t;
|
||||
pub fn PyDict_Copy(mp: *mut PyObject) -> *mut PyObject;
|
||||
pub fn PyDict_Contains(mp: *mut PyObject, key: *mut PyObject)
|
||||
-> c_int;
|
||||
pub fn PyDict_Update(mp: *mut PyObject, other: *mut PyObject)
|
||||
-> c_int;
|
||||
pub fn PyDict_Merge(mp: *mut PyObject, other: *mut PyObject,
|
||||
_override: c_int) -> c_int;
|
||||
pub fn PyDict_MergeFromSeq2(d: *mut PyObject, seq2: *mut PyObject,
|
||||
_override: c_int) -> c_int;
|
||||
pub fn PyDict_GetItemString(dp: *mut PyObject, key: *const c_char)
|
||||
-> *mut PyObject;
|
||||
pub fn PyDict_Contains(mp: *mut PyObject, key: *mut PyObject) -> c_int;
|
||||
pub fn PyDict_Update(mp: *mut PyObject, other: *mut PyObject) -> c_int;
|
||||
pub fn PyDict_Merge(mp: *mut PyObject, other: *mut PyObject, _override: c_int) -> c_int;
|
||||
pub fn PyDict_MergeFromSeq2(d: *mut PyObject, seq2: *mut PyObject, _override: c_int) -> c_int;
|
||||
pub fn PyDict_GetItemString(dp: *mut PyObject, key: *const c_char) -> *mut PyObject;
|
||||
pub fn PyDict_SetItemString(dp: *mut PyObject, key: *const c_char,
|
||||
item: *mut PyObject) -> c_int;
|
||||
pub fn PyDict_DelItemString(dp: *mut PyObject, key: *const c_char)
|
||||
-> c_int;
|
||||
pub fn PyDict_DelItemString(dp: *mut PyObject, key: *const c_char) -> c_int;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,17 +94,32 @@ impl PyDict {
|
|||
})
|
||||
}
|
||||
|
||||
/// List of dict keys.
|
||||
/// This is equivalent to the python expression `list(dict.keys())`.
|
||||
pub fn keys(&self) -> &PyList {
|
||||
unsafe {
|
||||
self.py().cast_from_ptr::<PyList>(ffi::PyDict_Keys(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// List of dict values.
|
||||
/// This is equivalent to the python expression `list(dict.values())`.
|
||||
pub fn values(&self) -> &PyList {
|
||||
unsafe {
|
||||
self.py().cast_from_ptr::<PyList>(ffi::PyDict_Values(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// List of dict items.
|
||||
/// This is equivalent to the python expression `list(dict.items())`.
|
||||
pub fn items_list(&self) -> &PyList {
|
||||
pub fn items(&self) -> &PyList {
|
||||
unsafe {
|
||||
self.py().cast_from_ptr::<PyList>(
|
||||
ffi::PyDict_Items(self.as_ptr()))
|
||||
self.py().cast_from_ptr::<PyList>(ffi::PyDict_Items(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the list of (key, value) pairs in this dictionary.
|
||||
pub fn items(&self) -> Vec<(PyObject, PyObject)> {
|
||||
pub fn items_vec(&self) -> Vec<(PyObject, PyObject)> {
|
||||
// Note that we don't provide an iterator because
|
||||
// PyDict_Next() is unsafe to use when the dictionary might be changed
|
||||
// by other python code.
|
||||
|
@ -231,6 +246,24 @@ mod test {
|
|||
assert_eq!(123i32, dict.get_item(8i32).unwrap().extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_item_refcnt() {
|
||||
let cnt;
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let dict = PyDict::new(py);
|
||||
let none = py.None();
|
||||
cnt = none.get_refcnt();
|
||||
dict.set_item(10, none).unwrap();
|
||||
}
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert_eq!(cnt, py.None().get_refcnt());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_item_does_not_update_original_object() {
|
||||
let gil = Python::acquire_gil();
|
||||
|
@ -270,28 +303,6 @@ mod test {
|
|||
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_items_list() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
for el in dict.items_list().iter() {
|
||||
let tuple = el.cast_as::<PyTuple>().unwrap();
|
||||
key_sum += tuple.get_item(0).extract::<i32>().unwrap();
|
||||
value_sum += tuple.get_item(1).extract::<i32>().unwrap();
|
||||
}
|
||||
assert_eq!(7 + 8 + 9, key_sum);
|
||||
assert_eq!(32 + 42 + 123, value_sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_items() {
|
||||
let gil = Python::acquire_gil();
|
||||
|
@ -305,7 +316,65 @@ mod test {
|
|||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
for (key, value) in dict.items() {
|
||||
for el in dict.items().iter() {
|
||||
let tuple = el.cast_as::<PyTuple>().unwrap();
|
||||
key_sum += tuple.get_item(0).extract::<i32>().unwrap();
|
||||
value_sum += tuple.get_item(1).extract::<i32>().unwrap();
|
||||
}
|
||||
assert_eq!(7 + 8 + 9, key_sum);
|
||||
assert_eq!(32 + 42 + 123, value_sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
for el in dict.keys().iter() {
|
||||
key_sum += el.extract::<i32>().unwrap();
|
||||
}
|
||||
assert_eq!(7 + 8 + 9, key_sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_values() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut values_sum = 0;
|
||||
for el in dict.values().iter() {
|
||||
values_sum += el.extract::<i32>().unwrap();
|
||||
}
|
||||
assert_eq!(32 + 42 + 123, values_sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_items_vec() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
for (key, value) in dict.items_vec() {
|
||||
key_sum += key.extract::<i32>(py).unwrap();
|
||||
value_sum += value.extract::<i32>(py).unwrap();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue