add __signature__ for property

This commit is contained in:
BLUELOVETH 2023-08-14 18:32:26 +08:00
parent 285f8b18a1
commit ef157946aa
4 changed files with 29 additions and 21 deletions

View File

@ -31,8 +31,8 @@ struct BoundMethod {
struct Property{ struct Property{
PyObject* getter; PyObject* getter;
PyObject* setter; PyObject* setter;
Str type_hint; Str signature;
Property(PyObject* getter, PyObject* setter, Str type_hint) : getter(getter), setter(setter), type_hint(type_hint) {} Property(PyObject* getter, PyObject* setter, Str signature) : getter(getter), setter(setter), signature(signature) {}
}; };
struct Range { struct Range {

View File

@ -1231,17 +1231,18 @@ void init_builtins(VM* _vm) {
return VAR(Property(args[1], vm->None, "")); return VAR(Property(args[1], vm->None, ""));
}else if(args.size() == 1+2){ }else if(args.size() == 1+2){
return VAR(Property(args[1], args[2], "")); return VAR(Property(args[1], args[2], ""));
}else if(args.size() == 1+3){
return VAR(Property(args[1], args[2], CAST(Str, args[3])));
} }
vm->TypeError("property() takes at most 2 arguments"); vm->TypeError("property() takes at most 3 arguments");
return vm->None; return vm->None;
}); });
_vm->bind_property(_vm->_t(_vm->tp_property), "type_hint: str", [](VM* vm, ArgsView args){ _vm->bind_property(_vm->_t(_vm->tp_property), "__signature__", [](VM* vm, ArgsView args){
Property& self = _CAST(Property&, args[0]); Property& self = _CAST(Property&, args[0]);
return VAR(self.type_hint); return VAR(self.signature);
}); });
_vm->bind_property(_vm->_t(_vm->tp_function), "__doc__", [](VM* vm, ArgsView args) { _vm->bind_property(_vm->_t(_vm->tp_function), "__doc__", [](VM* vm, ArgsView args) {
Function& func = _CAST(Function&, args[0]); Function& func = _CAST(Function&, args[0]);
return VAR(func.decl->docstring); return VAR(func.decl->docstring);
@ -1261,7 +1262,7 @@ void init_builtins(VM* _vm) {
_vm->bind_property(_vm->_t(_vm->tp_native_func), "__signature__", [](VM* vm, ArgsView args) { _vm->bind_property(_vm->_t(_vm->tp_native_func), "__signature__", [](VM* vm, ArgsView args) {
NativeFunc& func = _CAST(NativeFunc&, args[0]); NativeFunc& func = _CAST(NativeFunc&, args[0]);
if(func.decl != nullptr) return VAR(func.decl->signature); if(func.decl != nullptr) return VAR(func.decl->signature);
return VAR("unknown(*args, **kwargs)"); return VAR("");
}); });
RangeIter::register_class(_vm, _vm->builtins); RangeIter::register_class(_vm, _vm->builtins);

View File

@ -977,13 +977,10 @@ PyObject* VM::bind_property(PyObject* obj, Str name, NativeFuncC fget, NativeFun
PyObject* _0 = heap.gcnew<NativeFunc>(tp_native_func, fget, 1, false); PyObject* _0 = heap.gcnew<NativeFunc>(tp_native_func, fget, 1, false);
PyObject* _1 = vm->None; PyObject* _1 = vm->None;
if(fset != nullptr) _1 = heap.gcnew<NativeFunc>(tp_native_func, fset, 2, false); if(fset != nullptr) _1 = heap.gcnew<NativeFunc>(tp_native_func, fset, 2, false);
Str type_hint; Str signature = name;
int pos = name.index(":"); int pos = name.index(":");
if(pos > 0){ if(pos > 0) name = name.substr(0, pos).strip();
type_hint = name.substr(pos + 1).strip(); PyObject* prop = VAR(Property(_0, _1, signature));
name = name.substr(0, pos).strip();
}
PyObject* prop = VAR(Property(_0, _1, type_hint));
obj->attr().set(name, prop); obj->attr().set(name, prop);
return prop; return prop;
} }

View File

@ -747,10 +747,12 @@ assert type(slice(0.1, 0.2, 0.3)) is slice
# 116: 1535: bind_property(_t(tp_slice), "step", [](VM* vm, ArgsView args){ # 116: 1535: bind_property(_t(tp_slice), "step", [](VM* vm, ArgsView args){
# #####: 1536: return CAST(Slice&, args[0]).step; # #####: 1536: return CAST(Slice&, args[0]).step;
# -: 1537: }); # -: 1537: });
# test slice.start: s = slice(1, 2, 3)
assert type(slice(0.1, 0.2, 0.3)) is slice assert type(s) is slice
# test slice.stop: assert s.start == 1
# test slice.step: assert s.stop == 2
assert s.step == 3
assert slice.__dict__['start'].__signature__ == 'start'
# 未完全测试准确性----------------------------------------------- # 未完全测试准确性-----------------------------------------------
# 116: 957: _vm->bind__repr__(_vm->tp_slice, [](VM* vm, PyObject* obj) { # 116: 957: _vm->bind__repr__(_vm->tp_slice, [](VM* vm, PyObject* obj) {
@ -984,6 +986,10 @@ class A():
def __init__(self): def __init__(self):
self._name = '123' self._name = '123'
@property
def value(self):
return 2
def get_name(self): def get_name(self):
''' '''
doc string 1 doc string 1
@ -996,7 +1002,11 @@ class A():
''' '''
self._name = val self._name = val
A.name = property(A.get_name, A.set_name) assert A().value == 2
assert A.__dict__['value'].__signature__ == ''
A.name = property(A.get_name, A.set_name, "name: str")
assert A.__dict__['name'].__signature__ == 'name: str'
try: try:
property(A.get_name, A.set_name, 1) property(A.get_name, A.set_name, 1)
print('未能拦截错误, 在测试 property') print('未能拦截错误, 在测试 property')
@ -1008,8 +1018,8 @@ except:
import timeit import timeit
def aaa(): def aaa():
for i in range(1000): for i in range(100):
for j in range(1000): for j in range(100):
pass pass
assert type(timeit.timeit(aaa, 2)) is float assert type(timeit.timeit(aaa, 2)) is float
@ -1064,7 +1074,7 @@ assert type(time.time()) is float
# #####: 1275: return vm->None; # #####: 1275: return vm->None;
# #####: 1276: }); # #####: 1276: });
# test time.sleep # test time.sleep
time.sleep(0.5) time.sleep(0.1)
# 未完全测试准确性----------------------------------------------- # 未完全测试准确性-----------------------------------------------
# 116: 1278: vm->bind_func<0>(mod, "localtime", [](VM* vm, ArgsView args) { # 116: 1278: vm->bind_func<0>(mod, "localtime", [](VM* vm, ArgsView args) {