Browse Source

add `inspect` module

blueloveTH 1 year ago
parent
commit
4a8776ec6c

+ 2 - 0
include/pocketpy/interpreter/modules.h

@@ -11,6 +11,8 @@ void pk__add_module_time();
 void pk__add_module_easing();
 void pk__add_module_traceback();
 void pk__add_module_enum();
+void pk__add_module_inspect();
+
 void pk__add_module_linalg();
 void pk__add_module_array2d();
 

+ 1 - 1
include/pocketpy/pocketpy.h

@@ -672,7 +672,7 @@ enum py_PredefinedTypes {
     tp_module,
     tp_function,
     tp_nativefunc,
-    tp_boundmethod,
+    tp_boundmethod,    // 2 slots (self, func)
     tp_super,          // 1 slot + py_Type
     tp_BaseException,  // 2 slots (arg + inner_exc)
     tp_Exception,

+ 1 - 0
include/typings/inspect.pyi

@@ -0,0 +1 @@
+def isgeneratorfunction(obj) -> bool: ...

+ 1 - 0
src/interpreter/vm.c

@@ -215,6 +215,7 @@ void VM__ctor(VM* self) {
     pk__add_module_easing();
     pk__add_module_traceback();
     pk__add_module_enum();
+    pk__add_module_inspect();
 
     pk__add_module_conio();
     pk__add_module_pkpy();

+ 1 - 0
src/modules/gc.c

@@ -6,6 +6,7 @@
 #include "pocketpy/interpreter/vm.h"
 
 static bool gc_collect(int argc, py_Ref argv){
+    PY_CHECK_ARGC(0);
     ManagedHeap* heap = &pk_current_vm->heap;
     int res = ManagedHeap__collect(heap);
     py_newint(py_retval(), res);

+ 28 - 0
src/modules/inspect.c

@@ -0,0 +1,28 @@
+#include "pocketpy/pocketpy.h"
+
+#include "pocketpy/common/utils.h"
+#include "pocketpy/objects/object.h"
+#include "pocketpy/common/sstream.h"
+#include "pocketpy/interpreter/vm.h"
+
+static bool inspect_isgeneratorfunction(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(1);
+    py_Ref obj = argv;
+    if(py_istype(argv, tp_boundmethod)) {
+        py_TValue* slots = PyObject__slots(argv->_obj);
+        obj = &slots[1];  // callable
+    }
+    if(py_istype(obj, tp_function)) {
+        Function* fn = py_touserdata(obj);
+        py_newbool(py_retval(), fn->decl->type == FuncType_GENERATOR);
+    } else {
+        py_newbool(py_retval(), false);
+    }
+    return true;
+}
+
+void pk__add_module_inspect() {
+    py_Ref mod = py_newmodule("inspect");
+
+    py_bindfunc(mod, "isgeneratorfunction", inspect_isgeneratorfunction);
+}

+ 49 - 0
tests/97_inspect.py

@@ -0,0 +1,49 @@
+from inspect import isgeneratorfunction
+
+def f(a, b):
+    return a + b
+
+assert not isgeneratorfunction(f)
+
+def g(a, b):
+    yield a
+    yield b
+
+assert isgeneratorfunction(g)
+
+class A:
+    @staticmethod
+    def non_gen(a, b):
+        return a + b
+    @staticmethod
+    def gen(a, b):
+        yield a
+        yield b
+    @classmethod
+    def non_gen_class(cls, a, b):
+        return a + b
+    @classmethod
+    def gen_class(cls, a, b):
+        yield a
+        yield b
+    def not_gen_instance(self, a, b):
+        return a + b
+    def gen_instance(self, a, b):
+        yield a
+        yield b
+
+a = A()
+assert not isgeneratorfunction(a.non_gen)
+assert isgeneratorfunction(a.gen)
+assert not isgeneratorfunction(A.non_gen)
+assert isgeneratorfunction(A.gen)
+
+assert not isgeneratorfunction(a.non_gen_class)
+assert isgeneratorfunction(a.gen_class)
+assert not isgeneratorfunction(A.non_gen_class)
+assert isgeneratorfunction(A.gen_class)
+
+assert not isgeneratorfunction(a.not_gen_instance)
+assert isgeneratorfunction(a.gen_instance)
+assert not isgeneratorfunction(A.not_gen_instance)
+assert isgeneratorfunction(A.gen_instance)