Clear error indicator when the exception is handled on the Rust side

Leaving Python's global exception state is misleading, e.g. subsequent
calls of `py.eval` will fail.
This commit is contained in:
Alexander Niederbühl 2020-01-10 23:27:10 +01:00
parent 41e3b25070
commit 1f675dcaa7
4 changed files with 17 additions and 1 deletions

View File

@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Implemented `IntoIterator` for `PySet` and `PyFrozenSet`. [#716](https://github.com/PyO3/pyo3/pull/716) * Implemented `IntoIterator` for `PySet` and `PyFrozenSet`. [#716](https://github.com/PyO3/pyo3/pull/716)
### Fixed
* Clear error indicator when the exception is handled on the Rust side. [#719](https://github.com/PyO3/pyo3/pull/719)
## [0.8.5] ## [0.8.5]
* Support for `#[name = "foo"]` attribute for `#[pyfunction]` and in `#[pymethods]`. [#692](https://github.com/PyO3/pyo3/pull/692) * Support for `#[name = "foo"]` attribute for `#[pyfunction]` and in `#[pymethods]`. [#692](https://github.com/PyO3/pyo3/pull/692)

View File

@ -42,6 +42,7 @@ impl<'p> PyIterator<'p> {
let ptr = ffi::PyObject_GetIter(obj.as_ptr()); let ptr = ffi::PyObject_GetIter(obj.as_ptr());
// Returns NULL if an object cannot be iterated. // Returns NULL if an object cannot be iterated.
if ptr.is_null() { if ptr.is_null() {
PyErr::fetch(py);
return Err(PyDowncastError); return Err(PyDowncastError);
} }

View File

@ -93,7 +93,12 @@ impl PySet {
/// Remove and return an arbitrary element from the set /// Remove and return an arbitrary element from the set
pub fn pop(&self) -> Option<PyObject> { pub fn pop(&self) -> Option<PyObject> {
unsafe { PyObject::from_owned_ptr_or_opt(self.py(), ffi::PySet_Pop(self.as_ptr())) } let element =
unsafe { PyObject::from_owned_ptr_or_err(self.py(), ffi::PySet_Pop(self.as_ptr())) };
match element {
Ok(e) => Some(e),
Err(_) => None,
}
} }
/// Returns an iterator of values in this set. /// Returns an iterator of values in this set.
@ -324,6 +329,9 @@ mod test {
assert!(val.is_some()); assert!(val.is_some());
let val2 = set.pop(); let val2 = set.pop();
assert!(val2.is_none()); assert!(val2.is_none());
assert!(py
.eval("print('Exception state should not be set.')", None, None)
.is_ok());
} }
#[test] #[test]

View File

@ -179,4 +179,7 @@ fn incorrect_iter() {
let int_ref = int.as_ref(py); let int_ref = int.as_ref(py);
// Should not segfault. // Should not segfault.
assert!(int_ref.iter().is_err()); assert!(int_ref.iter().is_err());
assert!(py
.eval("print('Exception state should not be set.')", None, None)
.is_ok());
} }