Просмотр исходного кода

add `__signature__` for `property`

BLUELOVETH 2 лет назад
Родитель
Сommit
ef157946aa
4 измененных файлов с 29 добавлено и 21 удалено
  1. 2 2
      include/pocketpy/obj.h
  2. 6 5
      src/pocketpy.cpp
  3. 3 6
      src/vm.cpp
  4. 18 8
      tests/99_builtin_func.py

+ 2 - 2
include/pocketpy/obj.h

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

+ 6 - 5
src/pocketpy.cpp

@@ -1231,17 +1231,18 @@ void init_builtins(VM* _vm) {
             return VAR(Property(args[1], vm->None, ""));
         }else if(args.size() == 1+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;
     });
 
-    _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]);
-        return VAR(self.type_hint);
+        return VAR(self.signature);
     });
     
-
     _vm->bind_property(_vm->_t(_vm->tp_function), "__doc__", [](VM* vm, ArgsView args) {
         Function& func = _CAST(Function&, args[0]);
         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) {
         NativeFunc& func = _CAST(NativeFunc&, args[0]);
         if(func.decl != nullptr) return VAR(func.decl->signature);
-        return VAR("unknown(*args, **kwargs)");
+        return VAR("");
     });
 
     RangeIter::register_class(_vm, _vm->builtins);

+ 3 - 6
src/vm.cpp

@@ -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* _1 = vm->None;
     if(fset != nullptr) _1 = heap.gcnew<NativeFunc>(tp_native_func, fset, 2, false);
-    Str type_hint;
+    Str signature = name;
     int pos = name.index(":");
-    if(pos > 0){
-        type_hint = name.substr(pos + 1).strip();
-        name = name.substr(0, pos).strip();
-    }
-    PyObject* prop = VAR(Property(_0, _1, type_hint));
+    if(pos > 0) name = name.substr(0, pos).strip();
+    PyObject* prop = VAR(Property(_0, _1, signature));
     obj->attr().set(name, prop);
     return prop;
 }

+ 18 - 8
tests/99_builtin_func.py

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