Bladeren bron

add `callable`

BLUELOVETH 2 jaren geleden
bovenliggende
commit
b1df516bf1
2 gewijzigde bestanden met toevoegingen van 43 en 1 verwijderingen
  1. 19 0
      src/pocketpy.cpp
  2. 24 1
      tests/99_builtin_func.py

+ 19 - 0
src/pocketpy.cpp

@@ -162,6 +162,17 @@ void init_builtins(VM* _vm) {
     _vm->bind_builtin_func<1>("staticmethod", [](VM* vm, ArgsView args) {
         return args[0];
     });
+    
+    _vm->bind_builtin_func<1>("callable", [](VM* vm, ArgsView args) {
+        PyObject* cls = vm->_t(args[0]);
+        Type t = PK_OBJ_GET(Type, cls);
+        if(t == vm->tp_function) return vm->True;
+        if(t == vm->tp_native_func) return vm->True;
+        if(t == vm->tp_bound_method) return vm->True;
+        if(t == vm->tp_type) return vm->True;
+        bool ok = vm->find_name_in_mro(cls, __call__) != nullptr;
+        return VAR(ok);
+    });
 
     _vm->bind_builtin_func<1>("__import__", [](VM* vm, ArgsView args) {
         const Str& name = CAST(Str&, args[0]);
@@ -1271,12 +1282,20 @@ void init_builtins(VM* _vm) {
         return VAR(func.decl->signature);
     });
 
+    // _vm->bind_property(_vm->_t(_vm->tp_function), "__call__", [](VM* vm, ArgsView args) {
+    //     return args[0];
+    // });
+
     _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("");
     });
 
+    // _vm->bind_property(_vm->_t(_vm->tp_native_func), "__call__", [](VM* vm, ArgsView args) {
+    //     return args[0];
+    // });
+
     RangeIter::register_class(_vm, _vm->builtins);
     ArrayIter::register_class(_vm, _vm->builtins);
     StringIter::register_class(_vm, _vm->builtins);

+ 24 - 1
tests/99_builtin_func.py

@@ -1147,4 +1147,27 @@ assert min([
     (1, 2),
     (1, 3),
     (1, 4),
-]) == (1, 2)
+]) == (1, 2)
+
+
+# test callable
+assert callable(lambda: 1) is True          # function
+assert callable(1) is False                 # int
+assert callable(object) is True             # type
+assert callable(object()) is False
+assert callable([].append) is True      # bound method
+assert callable([].__getitem__) is True # bound method
+
+class A:
+    def __init__(self):
+        pass
+
+    def __call__(self):
+        pass
+
+assert callable(A) is True      # type
+assert callable(A()) is True    # instance with __call__
+assert callable(A.__call__) is True  # bound method
+assert callable(A.__init__) is True  # bound method
+assert callable(print) is True  # builtin function
+assert callable(isinstance) is True  # builtin function