From b1df516bf1269c8230ae0e23a7ef95f9395e97a3 Mon Sep 17 00:00:00 2001 From: BLUELOVETH Date: Fri, 15 Sep 2023 17:37:07 +0800 Subject: [PATCH] add `callable` --- src/pocketpy.cpp | 19 +++++++++++++++++++ tests/99_builtin_func.py | 25 ++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 36315021..d43b4319 100644 --- a/src/pocketpy.cpp +++ b/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); diff --git a/tests/99_builtin_func.py b/tests/99_builtin_func.py index 1bd0b080..d1a3ad71 100644 --- a/tests/99_builtin_func.py +++ b/tests/99_builtin_func.py @@ -1147,4 +1147,27 @@ assert min([ (1, 2), (1, 3), (1, 4), -]) == (1, 2) \ No newline at end of file +]) == (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