diff --git a/src/objectprotocol.rs b/src/objectprotocol.rs index 84a1f92a..07fe1cfe 100644 --- a/src/objectprotocol.rs +++ b/src/objectprotocol.rs @@ -175,12 +175,12 @@ pub trait ObjectProtocol<'p> : PythonObject<'p> { /// Returns the length of the sequence or mapping. /// This is equivalent to the python expression: 'len(self)' #[inline] - fn len(&self) -> PyResult<'p, ffi::Py_ssize_t> { + fn len(&self) -> PyResult<'p, usize> { let v = unsafe { ffi::PyObject_Size(self.as_ptr()) }; if v == -1 { Err(PyErr::fetch(self.python())) } else { - Ok(v) + Ok(v as usize) } } diff --git a/src/objects/dict.rs b/src/objects/dict.rs index fbdb0807..85c54cfe 100644 --- a/src/objects/dict.rs +++ b/src/objects/dict.rs @@ -18,9 +18,10 @@ use std; use ffi; -use python::{Python, PythonObject}; +use python::{Python, ToPythonPointer, PythonObject}; +use conversion::ToPyObject; use objects::PyObject; -use err::{self, PyResult}; +use err::{self, PyResult, PyErr}; pyobject_newtype!(PyDict, PyDict_Check, PyDict_Type); @@ -34,5 +35,68 @@ impl <'p> PyDict<'p> { err::cast_from_owned_ptr_or_panic(py, ffi::PyDict_New()) } } + + /// Return a new dictionary that contains the same key-value pairs as self. + pub fn copy(&self) -> PyResult<'p, PyDict<'p>> { + let py = self.python(); + unsafe { + err::result_cast_from_owned_ptr(py, ffi::PyDict_Copy(self.as_ptr())) + } + } + + /// Empty an existing dictionary of all key-value pairs. + #[inline] + pub fn clear(&self) { + unsafe { ffi::PyDict_Clear(self.as_ptr()) } + } + + #[inline] + pub fn len(&self) -> usize { + unsafe { ffi::PyDict_Size(self.as_ptr()) as usize } + } + + /// Determine if the dictionary contains the specified key. + /// This is equivalent to the Python expression `key in self`. + pub fn contains(&self, key: &PyObject<'p>) -> PyResult<'p, bool> { + let py = self.python(); + unsafe { + match ffi::PyDict_Contains(self.as_ptr(), key.as_ptr()) { + 1 => Ok(true), + 0 => Ok(false), + _ => Err(PyErr::fetch(py)) + } + } + } + + /// Gets an item from the dictionary. + /// Returns None if the item is not present, or if an error occurs. + pub fn get_item(&self, key: K) -> Option> where K: ToPyObject<'p> { + let py = self.python(); + key.with_borrowed_ptr(py, |key| unsafe { + PyObject::from_borrowed_ptr_opt(py, + ffi::PyDict_GetItem(self.as_ptr(), key)) + }) + } + + /// Sets an item value. + /// This is equivalent to the Python expression `self[key] = value`. + pub fn set_item(&self, key: K, value: V) -> PyResult<'p, ()> where K: ToPyObject<'p>, V: ToPyObject<'p> { + let py = self.python(); + key.with_borrowed_ptr(py, move |key| + value.with_borrowed_ptr(py, |value| unsafe { + err::error_on_minusone(py, + ffi::PyDict_SetItem(self.as_ptr(), key, value)) + })) + } + + /// Deletes an item. + /// This is equivalent to the Python expression 'del self[key]'. + pub fn del_item(&self, key: K) -> PyResult<'p, ()> where K: ToPyObject<'p> { + let py = self.python(); + key.with_borrowed_ptr(py, |key| unsafe { + err::error_on_minusone(py, + ffi::PyDict_DelItem(self.as_ptr(), key)) + }) + } } diff --git a/src/objects/module.rs b/src/objects/module.rs index 7346ba0b..ebff66f0 100644 --- a/src/objects/module.rs +++ b/src/objects/module.rs @@ -96,7 +96,7 @@ impl <'p> PyModule<'p> { pub fn name<'a>(&'a self) -> PyResult<'p, &'a str> { unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.as_ptr())) } } - + /// Gets the module filename. /// /// May fail if the module does not have a __file__ attribute. @@ -114,11 +114,7 @@ impl <'p> PyModule<'p> { /// /// This is a convenience function which can be used from the module's initialization function. pub fn add(&self, name: &str, value: V) -> PyResult<'p, ()> where V: ToPyObject<'p> { - let py = self.python(); - let name = CString::new(name).unwrap(); - let value = value.into_py_object(py); - let r = unsafe { ffi::PyModule_AddObject(self.as_ptr(), name.as_ptr(), value.steal_ptr()) }; - err::error_on_minusone(py, r) + self.dict().set_item(name, value) } }