Skip to content

Commit 23381b9

Browse files
committed
compatiibility for CPytthon descr_check
1 parent 226a2a6 commit 23381b9

File tree

12 files changed

+151
-69
lines changed

12 files changed

+151
-69
lines changed

derive/src/pyclass.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,13 @@ fn extract_impl_items(mut items: Vec<ItemSig>) -> Result<TokenStream2, Diagnosti
452452
slot_ident,
453453
item_ident,
454454
} => {
455+
let transform = if vec!["new", "call"].contains(&slot_ident.to_string().as_str()) {
456+
quote! { ::rustpython_vm::function::IntoPyNativeFunc::into_func }
457+
} else {
458+
quote! { Box::new }
459+
};
455460
let into_func = quote_spanned! {item_ident.span()=>
456-
::rustpython_vm::function::IntoPyNativeFunc::into_func(Self::#item_ident)
461+
#transform(Self::#item_ident)
457462
};
458463
Some(quote! {
459464
(*class.slots.borrow_mut()).#slot_ident = Some(#into_func);

tests/snippets/types_snippet.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,7 @@ class C(B, BB):
8686
pass
8787

8888
assert C.mro() == [C, B, A, BB, AA, object]
89+
90+
91+
assert type(Exception.args).__name__ == 'getset_descriptor'
92+
assert type(None).__bool__(None) is False

vm/src/obj/objbuiltinfunc.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use std::fmt;
33
use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc};
44
use crate::obj::objtype::PyClassRef;
55
use crate::pyobject::{
6-
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
6+
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol,
77
};
8-
use crate::slots::{PyBuiltinCallable, PyBuiltinDescriptor};
8+
use crate::slots::{SlotCall, SlotDescriptor};
99
use crate::vm::VirtualMachine;
1010

1111
#[pyclass]
@@ -35,13 +35,13 @@ impl PyBuiltinFunction {
3535
}
3636
}
3737

38-
impl PyBuiltinCallable for PyBuiltinFunction {
38+
impl SlotCall for PyBuiltinFunction {
3939
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
4040
(self.value)(vm, args)
4141
}
4242
}
4343

44-
#[pyimpl(with(PyBuiltinCallable))]
44+
#[pyimpl(with(SlotCall))]
4545
impl PyBuiltinFunction {}
4646

4747
#[pyclass]
@@ -73,13 +73,17 @@ impl PyBuiltinMethod {
7373
}
7474
}
7575

76-
impl PyBuiltinDescriptor for PyBuiltinMethod {
77-
fn get(
78-
zelf: PyRef<Self>,
79-
obj: PyObjectRef,
80-
cls: OptionalArg<PyObjectRef>,
76+
impl SlotDescriptor for PyBuiltinMethod {
77+
fn descr_get(
8178
vm: &VirtualMachine,
79+
zelf: PyObjectRef,
80+
obj: Option<PyObjectRef>,
81+
cls: OptionalArg<PyObjectRef>,
8282
) -> PyResult {
83+
let (zelf, obj) = match Self::_check(zelf, obj, vm) {
84+
Ok(obj) => obj,
85+
Err(result) => return result,
86+
};
8387
if obj.is(&vm.get_none()) && !Self::_cls_is(&cls, &obj.class()) {
8488
Ok(zelf.into_object())
8589
} else {
@@ -88,13 +92,13 @@ impl PyBuiltinDescriptor for PyBuiltinMethod {
8892
}
8993
}
9094

91-
impl PyBuiltinCallable for PyBuiltinMethod {
95+
impl SlotCall for PyBuiltinMethod {
9296
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
9397
(self.function.value)(vm, args)
9498
}
9599
}
96100

97-
#[pyimpl(with(PyBuiltinDescriptor, PyBuiltinCallable))]
101+
#[pyimpl(with(SlotDescriptor, SlotCall))]
98102
impl PyBuiltinMethod {}
99103

100104
pub fn init(context: &PyContext) {

vm/src/obj/objclassmethod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::function::OptionalArg;
33
use crate::pyobject::{
44
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
55
};
6-
use crate::slots::PyBuiltinDescriptor;
6+
use crate::slots::SlotDescriptor;
77
use crate::vm::VirtualMachine;
88

99
/// classmethod(function) -> method
@@ -47,19 +47,20 @@ impl PyValue for PyClassMethod {
4747
}
4848
}
4949

50-
impl PyBuiltinDescriptor for PyClassMethod {
51-
fn get(
52-
zelf: PyRef<Self>,
53-
obj: PyObjectRef,
54-
cls: OptionalArg<PyObjectRef>,
50+
impl SlotDescriptor for PyClassMethod {
51+
fn descr_get(
5552
vm: &VirtualMachine,
53+
zelf: PyObjectRef,
54+
obj: Option<PyObjectRef>,
55+
cls: OptionalArg<PyObjectRef>,
5656
) -> PyResult {
57+
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
5758
let cls = cls.unwrap_or_else(|| obj.class().into_object());
5859
Ok(vm.ctx.new_bound_method(zelf.callable.clone(), cls))
5960
}
6061
}
6162

62-
#[pyimpl(with(PyBuiltinDescriptor), flags(BASETYPE))]
63+
#[pyimpl(with(SlotDescriptor), flags(BASETYPE))]
6364
impl PyClassMethod {
6465
#[pyslot]
6566
fn tp_new(

vm/src/obj/objfunction.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::pyobject::{
1313
TypeProtocol,
1414
};
1515
use crate::scope::Scope;
16-
use crate::slots::{PyBuiltinCallable, PyBuiltinDescriptor};
16+
use crate::slots::{SlotCall, SlotDescriptor};
1717
use crate::vm::VirtualMachine;
1818

1919
pub type PyFunctionRef = PyRef<PyFunction>;
@@ -27,13 +27,14 @@ pub struct PyFunction {
2727
kw_only_defaults: Option<PyDictRef>,
2828
}
2929

30-
impl PyBuiltinDescriptor for PyFunction {
31-
fn get(
32-
zelf: PyRef<Self>,
33-
obj: PyObjectRef,
34-
cls: OptionalArg<PyObjectRef>,
30+
impl SlotDescriptor for PyFunction {
31+
fn descr_get(
3532
vm: &VirtualMachine,
33+
zelf: PyObjectRef,
34+
obj: Option<PyObjectRef>,
35+
cls: OptionalArg<PyObjectRef>,
3636
) -> PyResult {
37+
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
3738
if obj.is(&vm.get_none()) && !Self::_cls_is(&cls, &obj.class()) {
3839
Ok(zelf.into_object())
3940
} else {
@@ -240,7 +241,7 @@ impl PyValue for PyFunction {
240241
}
241242
}
242243

243-
#[pyimpl(with(PyBuiltinDescriptor))]
244+
#[pyimpl(with(SlotDescriptor))]
244245
impl PyFunction {
245246
#[pyslot]
246247
#[pymethod(magic)]
@@ -272,7 +273,7 @@ pub struct PyBoundMethod {
272273
pub function: PyObjectRef,
273274
}
274275

275-
impl PyBuiltinCallable for PyBoundMethod {
276+
impl SlotCall for PyBoundMethod {
276277
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
277278
let args = args.insert(self.object.clone());
278279
vm.invoke(&self.function, args)
@@ -285,7 +286,7 @@ impl PyBoundMethod {
285286
}
286287
}
287288

288-
#[pyimpl(with(PyBuiltinCallable))]
289+
#[pyimpl(with(SlotCall))]
289290
impl PyBoundMethod {
290291
#[pymethod(magic)]
291292
fn getattribute(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {

vm/src/obj/objgetset.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::function::{OptionalArg, OwnedParam, RefParam};
66
use crate::pyobject::{
77
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
88
};
9-
use crate::slots::PyBuiltinDescriptor;
9+
use crate::slots::SlotDescriptor;
1010
use crate::vm::VirtualMachine;
1111

1212
pub type PyGetterFunc = Box<dyn Fn(&VirtualMachine, PyObjectRef) -> PyResult>;
@@ -178,13 +178,17 @@ impl PyValue for PyGetSet {
178178

179179
pub type PyGetSetRef = PyRef<PyGetSet>;
180180

181-
impl PyBuiltinDescriptor for PyGetSet {
182-
fn get(
183-
zelf: PyRef<Self>,
184-
obj: PyObjectRef,
185-
_cls: OptionalArg<PyObjectRef>,
181+
impl SlotDescriptor for PyGetSet {
182+
fn descr_get(
186183
vm: &VirtualMachine,
184+
zelf: PyObjectRef,
185+
obj: Option<PyObjectRef>,
186+
_cls: OptionalArg<PyObjectRef>,
187187
) -> PyResult {
188+
let (zelf, obj) = match Self::_check(zelf, obj, vm) {
189+
Ok(obj) => obj,
190+
Err(result) => return result,
191+
};
188192
if let Some(ref f) = zelf.getter {
189193
f(vm, obj)
190194
} else {
@@ -222,7 +226,7 @@ impl PyGetSet {
222226
}
223227
}
224228

225-
#[pyimpl(with(PyBuiltinDescriptor))]
229+
#[pyimpl(with(SlotDescriptor))]
226230
impl PyGetSet {
227231
// Descriptor methods
228232

vm/src/obj/objproperty.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::pyobject::{
99
IdProtocol, PyClassImpl, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
1010
TypeProtocol,
1111
};
12-
use crate::slots::PyBuiltinDescriptor;
12+
use crate::slots::SlotDescriptor;
1313
use crate::vm::VirtualMachine;
1414

1515
// Read-only property, doesn't have __set__ or __delete__
@@ -27,13 +27,14 @@ impl PyValue for PyReadOnlyProperty {
2727

2828
pub type PyReadOnlyPropertyRef = PyRef<PyReadOnlyProperty>;
2929

30-
impl PyBuiltinDescriptor for PyReadOnlyProperty {
31-
fn get(
32-
zelf: PyRef<Self>,
33-
obj: PyObjectRef,
34-
cls: OptionalArg<PyObjectRef>,
30+
impl SlotDescriptor for PyReadOnlyProperty {
31+
fn descr_get(
3532
vm: &VirtualMachine,
33+
zelf: PyObjectRef,
34+
obj: Option<PyObjectRef>,
35+
cls: OptionalArg<PyObjectRef>,
3636
) -> PyResult {
37+
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
3738
if vm.is_none(&obj) {
3839
if Self::_cls_is(&cls, &vm.ctx.types.type_type) {
3940
vm.invoke(&zelf.getter, cls.unwrap())
@@ -46,7 +47,7 @@ impl PyBuiltinDescriptor for PyReadOnlyProperty {
4647
}
4748
}
4849

49-
#[pyimpl(with(PyBuiltinDescriptor))]
50+
#[pyimpl(with(SlotDescriptor))]
5051
impl PyReadOnlyProperty {}
5152

5253
/// Property attribute.
@@ -110,13 +111,14 @@ struct PropertyArgs {
110111
doc: Option<PyObjectRef>,
111112
}
112113

113-
impl PyBuiltinDescriptor for PyProperty {
114-
fn get(
115-
zelf: PyRef<Self>,
116-
obj: PyObjectRef,
117-
_cls: OptionalArg<PyObjectRef>,
114+
impl SlotDescriptor for PyProperty {
115+
fn descr_get(
118116
vm: &VirtualMachine,
117+
zelf: PyObjectRef,
118+
obj: Option<PyObjectRef>,
119+
_cls: OptionalArg<PyObjectRef>,
119120
) -> PyResult {
121+
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
120122
if let Some(getter) = zelf.getter.as_ref() {
121123
if obj.is(vm.ctx.none.as_object()) {
122124
Ok(zelf.into_object())
@@ -129,7 +131,7 @@ impl PyBuiltinDescriptor for PyProperty {
129131
}
130132
}
131133

132-
#[pyimpl(with(PyBuiltinDescriptor), flags(BASETYPE))]
134+
#[pyimpl(with(SlotDescriptor), flags(BASETYPE))]
133135
impl PyProperty {
134136
#[pyslot]
135137
fn tp_new(cls: PyClassRef, args: PropertyArgs, vm: &VirtualMachine) -> PyResult<PyPropertyRef> {

vm/src/obj/objstaticmethod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::objtype::PyClassRef;
22
use crate::function::OptionalArg;
33
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
4-
use crate::slots::PyBuiltinDescriptor;
4+
use crate::slots::SlotDescriptor;
55
use crate::vm::VirtualMachine;
66

77
#[pyclass(name = "staticmethod")]
@@ -17,18 +17,19 @@ impl PyValue for PyStaticMethod {
1717
}
1818
}
1919

20-
impl PyBuiltinDescriptor for PyStaticMethod {
21-
fn get(
22-
zelf: PyRef<Self>,
23-
_obj: PyObjectRef,
20+
impl SlotDescriptor for PyStaticMethod {
21+
fn descr_get(
22+
vm: &VirtualMachine,
23+
zelf: PyObjectRef,
24+
_obj: Option<PyObjectRef>,
2425
_cls: OptionalArg<PyObjectRef>,
25-
_vm: &VirtualMachine,
2626
) -> PyResult {
27+
let zelf = Self::_zelf(zelf, vm)?;
2728
Ok(zelf.callable.clone())
2829
}
2930
}
3031

31-
#[pyimpl(with(PyBuiltinDescriptor), flags(BASETYPE))]
32+
#[pyimpl(with(SlotDescriptor), flags(BASETYPE))]
3233
impl PyStaticMethod {
3334
#[pyslot]
3435
fn tp_new(

vm/src/obj/objtype.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::objproperty::PropertyBuilder;
99
use super::objstr::PyStringRef;
1010
use super::objtuple::PyTuple;
1111
use super::objweakref::PyWeak;
12-
use crate::function::PyFuncArgs;
12+
use crate::function::{OptionalArg, PyFuncArgs};
1313
use crate::pyobject::{
1414
IdProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, PyObject, PyObjectRef, PyRef,
1515
PyResult, PyValue, TypeProtocol,
@@ -170,7 +170,11 @@ impl PyClassRef {
170170

171171
if let Some(attr) = self.get_attr(&name) {
172172
let attr_class = attr.class();
173-
if let Some(ref descriptor) = attr_class.get_attr("__get__") {
173+
let slots = attr_class.slots.borrow();
174+
if let Some(ref descr_get) = slots.descr_get {
175+
return descr_get(vm, attr, None, OptionalArg::Present(self.into_object()));
176+
} else if let Some(ref descriptor) = attr_class.get_attr("__get__") {
177+
// TODO: is this nessessary?
174178
return vm.invoke(descriptor, vec![attr, vm.get_none(), self.into_object()]);
175179
}
176180
}

vm/src/obj/objweakref.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::function::{OptionalArg, PyFuncArgs};
33
use crate::pyobject::{
44
PyClassImpl, PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult, PyValue,
55
};
6-
use crate::slots::PyBuiltinCallable;
6+
use crate::slots::SlotCall;
77
use crate::vm::VirtualMachine;
88

99
use std::rc::{Rc, Weak};
@@ -34,14 +34,14 @@ impl PyValue for PyWeak {
3434

3535
pub type PyWeakRef = PyRef<PyWeak>;
3636

37-
impl PyBuiltinCallable for PyWeak {
37+
impl SlotCall for PyWeak {
3838
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
3939
args.bind::<()>(vm)?;
4040
Ok(self.referent.upgrade().unwrap_or_else(|| vm.get_none()))
4141
}
4242
}
4343

44-
#[pyimpl(with(PyBuiltinCallable), flags(BASETYPE))]
44+
#[pyimpl(with(SlotCall), flags(BASETYPE))]
4545
impl PyWeak {
4646
// TODO callbacks
4747
#[pyslot]

0 commit comments

Comments
 (0)