Merge branch 'master' into pyclass-new-layout
This commit is contained in:
commit
8f8785d7c2
45
.github/workflows/test.yml
vendored
45
.github/workflows/test.yml
vendored
|
@ -1,34 +1,33 @@
|
|||
name: Test
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
max-parallel: 3
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
python-version: [3.5, 3.6, 3.7]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Set Python PATH
|
||||
run: ci/actions/setup
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
default: true
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Install test dependencies
|
||||
run: |
|
||||
python -m pip install -U pip setuptools
|
||||
pip install setuptools-rust pytest pytest-benchmark tox tox-venv
|
||||
- name: Test
|
||||
run: ci/actions/test
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Set Python PATH
|
||||
run: ci/actions/setup
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
default: true
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Install test dependencies
|
||||
run: |
|
||||
python -m pip install -U pip setuptools
|
||||
pip install setuptools-rust pytest pytest-benchmark tox tox-venv
|
||||
- name: Test
|
||||
run: ci/actions/test
|
||||
|
|
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
## Unreleased
|
||||
|
||||
* Support for `#[name = "foo"]` attribute for `#[pyfunction]` and in `#[pymethods]`. [#692](https://github.com/PyO3/pyo3/pull/692)
|
||||
* Implemented `FromPyObject` for `HashMap` and `BTreeMap`
|
||||
|
||||
## [0.8.4]
|
||||
|
||||
|
|
2
src/lib.rs
Normal file → Executable file
2
src/lib.rs
Normal file → Executable file
|
@ -157,6 +157,8 @@ pub mod derive_utils;
|
|||
mod err;
|
||||
pub mod exceptions;
|
||||
/// Raw ffi declarations for the c interface of python
|
||||
#[allow(clippy::unknown_clippy_lints)]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub mod ffi;
|
||||
pub mod freelist;
|
||||
mod gil;
|
||||
|
|
|
@ -10,7 +10,9 @@ use crate::AsPyPointer;
|
|||
use crate::IntoPyPointer;
|
||||
use crate::Python;
|
||||
use crate::{ffi, IntoPy};
|
||||
use crate::{FromPyObject, PyTryFrom};
|
||||
use crate::{ToBorrowedObject, ToPyObject};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::{cmp, collections, hash};
|
||||
|
||||
/// Represents a Python `dict`.
|
||||
|
@ -308,6 +310,37 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'source, K, V, S> FromPyObject<'source> for HashMap<K, V, S>
|
||||
where
|
||||
K: FromPyObject<'source> + cmp::Eq + hash::Hash,
|
||||
V: FromPyObject<'source>,
|
||||
S: hash::BuildHasher + Default,
|
||||
{
|
||||
fn extract(ob: &'source PyAny) -> Result<Self, PyErr> {
|
||||
let dict = <PyDict as PyTryFrom>::try_from(ob)?;
|
||||
let mut ret = HashMap::default();
|
||||
for (k, v) in dict.iter() {
|
||||
ret.insert(K::extract(k)?, V::extract(v)?);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source, K, V> FromPyObject<'source> for BTreeMap<K, V>
|
||||
where
|
||||
K: FromPyObject<'source> + cmp::Ord,
|
||||
V: FromPyObject<'source>,
|
||||
{
|
||||
fn extract(ob: &'source PyAny) -> Result<Self, PyErr> {
|
||||
let dict = <PyDict as PyTryFrom>::try_from(ob)?;
|
||||
let mut ret = BTreeMap::new();
|
||||
for (k, v) in dict.iter() {
|
||||
ret.insert(K::extract(k)?, V::extract(v)?);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::conversion::IntoPy;
|
||||
|
@ -326,6 +359,10 @@ mod test {
|
|||
let dict = [(7, 32)].into_py_dict(py);
|
||||
assert_eq!(32, dict.get_item(7i32).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(None, dict.get_item(8i32));
|
||||
let map: HashMap<i32, i32> = [(7, 32)].iter().cloned().collect();
|
||||
assert_eq!(map, dict.extract().unwrap());
|
||||
let map: BTreeMap<i32, i32> = [(7, 32)].iter().cloned().collect();
|
||||
assert_eq!(map, dict.extract().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -336,6 +373,10 @@ mod test {
|
|||
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());
|
||||
let map: HashMap<&str, i32> = [("a", 1), ("b", 2)].iter().cloned().collect();
|
||||
assert_eq!(map, dict.extract().unwrap());
|
||||
let map: BTreeMap<&str, i32> = [("a", 1), ("b", 2)].iter().cloned().collect();
|
||||
assert_eq!(map, dict.extract().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -582,6 +623,7 @@ mod test {
|
|||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!(py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
assert_eq!(map, py_map.extract().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -597,6 +639,7 @@ mod test {
|
|||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!(py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
assert_eq!(map, py_map.extract().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue