Skip to content

Commit

Permalink
Merge pull request #936 from davidhewitt/optional-bool
Browse files Browse the repository at this point in the history
Fix passing explicit None to pyfunction with default
  • Loading branch information
kngwyu authored May 18, 2020
2 parents 8e63980 + 5c5527d commit c393d4a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Removed
- Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930)

### Fixed
- Fix passing explicit `None` to `Option<T>` argument `#[pyfunction]` with a default value. [#936](https://github.com/PyO3/pyo3/pull/936)

## [0.10.1] - 2020-05-14
### Fixed
- Fix deadlock in `Python::acquire_gil()` after dropping a `PyObject` or `Py<T>`. [#924](https://github.com/PyO3/pyo3/pull/924)
Expand Down
10 changes: 5 additions & 5 deletions pyo3-derive-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,25 +520,25 @@ fn impl_arg_param(
};
// Get Option<&T> from Option<PyRef<T>>
quote! {
let #mut_ _tmp = match #arg_value.as_ref().filter(|obj| !obj.is_none()) {
let #mut_ _tmp = match #arg_value {
Some(_obj) => {
Some(_obj.extract::<<#tref as pyo3::derive_utils::ExtractExt>::Target>()?)
_obj.extract::<Option<<#tref as pyo3::derive_utils::ExtractExt>::Target>>()?
},
None => #default,
};
let #arg_name = _tmp.#as_deref();
}
} else {
quote! {
let #arg_name = match #arg_value.as_ref().filter(|obj| !obj.is_none()) {
Some(_obj) => Some(_obj.extract()?),
let #arg_name = match #arg_value {
Some(_obj) => _obj.extract()?,
None => #default,
};
}
}
} else if let Some(default) = spec.default_value(name) {
quote! {
let #arg_name = match #arg_value.as_ref().filter(|obj| !obj.is_none()) {
let #arg_name = match #arg_value {
Some(_obj) => _obj.extract()?,
None => #default,
};
Expand Down
22 changes: 22 additions & 0 deletions tests/test_pyfunction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

mod common;

#[pyfunction(arg = "true")]
fn optional_bool(arg: Option<bool>) -> String {
format!("{:?}", arg)
}

#[test]
fn test_optional_bool() {
// Regression test for issue #932
let gil = Python::acquire_gil();
let py = gil.python();
let f = wrap_pyfunction!(optional_bool)(py);

py_assert!(py, f, "f() == 'Some(true)'");
py_assert!(py, f, "f(True) == 'Some(true)'");
py_assert!(py, f, "f(False) == 'Some(false)'");
py_assert!(py, f, "f(None) == 'None'");
}

0 comments on commit c393d4a

Please # to comment.