Merge pull request #1997 from davidhewitt/get-panic

macros: fix panic in __get__ implementation
This commit is contained in:
David Hewitt 2021-11-15 16:42:06 +00:00 committed by GitHub
commit e790d55304
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 6 deletions

View File

@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix use of `catch_unwind` in `allow_threads` which can cause fatal crashes. [#1989](https://github.com/PyO3/pyo3/pull/1989)
- Fix build failure on PyPy when abi3 features are activated. [#1991](https://github.com/PyO3/pyo3/pull/1991)
- Fix mingw platform detection. [#1993](https://github.com/PyO3/pyo3/pull/1993)
- Fix panic in `__get__` implementation when accessing descriptor on type object. [#1997](https://github.com/PyO3/pyo3/pull/1997)
## [0.15.0] - 2021-11-03

View File

@ -483,8 +483,8 @@ const __HASH__: SlotDef = SlotDef::new("Py_tp_hash", "hashfunc")
const __RICHCMP__: SlotDef = SlotDef::new("Py_tp_richcompare", "richcmpfunc")
.extract_error_mode(ExtractErrorMode::NotImplemented)
.arguments(&[Ty::Object, Ty::CompareOp]);
const __GET__: SlotDef =
SlotDef::new("Py_tp_descr_get", "descrgetfunc").arguments(&[Ty::Object, Ty::Object]);
const __GET__: SlotDef = SlotDef::new("Py_tp_descr_get", "descrgetfunc")
.arguments(&[Ty::MaybeNullObject, Ty::MaybeNullObject]);
const __ITER__: SlotDef = SlotDef::new("Py_tp_iter", "getiterfunc");
const __NEXT__: SlotDef = SlotDef::new("Py_tp_iternext", "iternextfunc").return_conversion(
TokenGenerator(|| quote! { ::pyo3::class::iter::IterNextOutput::<_, _> }),
@ -606,6 +606,7 @@ fn pyproto(method_name: &str) -> Option<&'static SlotDef> {
#[derive(Clone, Copy)]
enum Ty {
Object,
MaybeNullObject,
NonNullObject,
CompareOp,
Int,
@ -617,7 +618,7 @@ enum Ty {
impl Ty {
fn ffi_type(self) -> TokenStream {
match self {
Ty::Object => quote! { *mut ::pyo3::ffi::PyObject },
Ty::Object | Ty::MaybeNullObject => quote! { *mut ::pyo3::ffi::PyObject },
Ty::NonNullObject => quote! { ::std::ptr::NonNull<::pyo3::ffi::PyObject> },
Ty::Int | Ty::CompareOp => quote! { ::std::os::raw::c_int },
Ty::PyHashT => quote! { ::pyo3::ffi::Py_hash_t },
@ -645,6 +646,22 @@ impl Ty {
);
extract_object(cls, arg.ty, ident, extract)
}
Ty::MaybeNullObject => {
let extract = handle_error(
extract_error_mode,
py,
quote! {
#py.from_borrowed_ptr::<::pyo3::PyAny>(
if #ident.is_null() {
::pyo3::ffi::Py_None()
} else {
#ident
}
).extract()
},
);
extract_object(cls, arg.ty, ident, extract)
}
Ty::NonNullObject => {
let extract = handle_error(
extract_error_mode,

View File

@ -548,11 +548,23 @@ fn descr_getset() {
r#"
class Class:
counter = Counter()
# access via type
counter = Class.counter
assert counter.count == 1
# access with instance directly
assert Counter.__get__(counter, Class()).count == 2
# access via instance
c = Class()
c.counter # count += 1
assert c.counter.count == 2
c.counter = Counter()
assert c.counter.count == 3
# __set__
c.counter = Counter()
assert c.counter.count == 4
# __delete__
del c.counter
assert c.counter.count == 1
"#