PyDict::from_sequence()

This commit is contained in:
ijl 2018-09-25 14:19:23 +00:00
parent af68396c31
commit 28bc3cf1e6
2 changed files with 39 additions and 2 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* `#[pyclass]` objects can now be returned from rust functions
* `PyComplex` by kngwyu in [#226](https://github.com/PyO3/pyo3/pull/226)
* `PyDict::from_sequence()`, equivalent to `dict([(key, val), ...])`
### Removed
* Removed most entries from the prelude. The new prelude is small and clear.

View File

@ -5,7 +5,7 @@ use err::{self, PyErr, PyResult};
use ffi;
use instance::PyObjectWithToken;
use object::PyObject;
use python::{Python, ToPyPointer};
use python::{Python, ToPyPointer, IntoPyPointer};
use std;
use std::{cmp, collections, hash, mem};
use types::{PyList, PyObjectRef};
@ -22,6 +22,24 @@ impl PyDict {
unsafe { py.from_owned_ptr::<PyDict>(ffi::PyDict_New()) }
}
/// Creates a new dictionary from the sequence given.
///
/// The sequence must consist of `(PyObject, PyObject)`. This is
/// equivalent to `dict([("a", 1), ("b", 2)])`.
///
/// Returns an error on invalid input. In the case of key collisions,
/// this keeps the last entry seen.
pub fn from_sequence(py: Python, seq: PyObject) -> PyResult<&PyDict> {
unsafe {
let dict = py.from_owned_ptr::<PyDict>(ffi::PyDict_New());
match ffi::PyDict_MergeFromSeq2(dict.into_ptr(), seq.into_ptr(), 1i32) {
0 => Ok(dict),
-1 => Err(PyErr::fetch(py)),
_ => unreachable!(),
}
}
}
/// Return a new dictionary that contains the same key-value pairs as self.
/// Corresponds to `dict(self)` in Python.
pub fn copy(&self) -> PyResult<&PyDict> {
@ -259,7 +277,7 @@ mod test {
use python::Python;
use std::collections::{BTreeMap, HashMap};
use types::dict::IntoPyDict;
use types::{PyDict, PyTuple};
use types::{PyDict, PyTuple, PyList};
use ObjectProtocol;
#[test]
@ -272,6 +290,24 @@ mod test {
assert_eq!(None, dict.get_item(8i32));
}
#[test]
fn test_from_sequence() {
let gil = Python::acquire_gil();
let py = gil.python();
let items = PyList::new(py, &vec![("a", 1), ("b", 2)]);
let dict = PyDict::from_sequence(py, items.to_object(py)).unwrap();
assert_eq!(1, dict.get_item("a").unwrap().extract::<i32>().unwrap());
assert_eq!(2, dict.get_item("b").unwrap().extract::<i32>().unwrap());
}
#[test]
fn test_from_sequence_err() {
let gil = Python::acquire_gil();
let py = gil.python();
let items = PyList::new(py, &vec!["a", "b"]);
assert!(PyDict::from_sequence(py, items.to_object(py)).is_err());
}
#[test]
fn test_copy() {
let gil = Python::acquire_gil();