Browse Source

interrogate: Support explicit `cls` parameter for static methods

rdb 2 years ago
parent
commit
5d833c988a

+ 15 - 5
dtool/src/interrogate/functionRemap.cxx

@@ -479,6 +479,10 @@ get_call_str(const string &container, const vector_string &pexprs) const {
       call << separator << "self";
       separator = ", ";
     }
+    if (_flags & F_explicit_cls) {
+      call << separator << "cls";
+      separator = ", ";
+    }
 
     size_t pn = _first_true_parameter;
     size_t num_parameters = pexprs.size();
@@ -807,14 +811,20 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     first_param = 1;
   }
 
-  if (_parameters.size() > first_param && _parameters[first_param]._name == "self" &&
+  if (_parameters.size() > first_param &&
       TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) {
     // Here's a special case.  If the first parameter of a nonstatic method
     // is a PyObject * called "self", then we will automatically fill it in
-    // from the this pointer, and remove it from the generated parameter
-    // list.
-    _parameters.erase(_parameters.begin() + first_param);
-    _flags |= F_explicit_self;
+    // from the this pointer, and remove it from the generated parameter list.
+    // For static methods, we offer "cls" instead, containing the type object.
+    if (_parameters[first_param]._name == "self") {
+      _parameters.erase(_parameters.begin() + first_param);
+      _flags |= F_explicit_self;
+    }
+    else if (!_has_this && _parameters[first_param]._name == "cls") {
+      _parameters.erase(_parameters.begin() + first_param);
+      _flags |= F_explicit_cls;
+    }
   }
 
   if (_parameters.size() == first_param) {

+ 1 - 0
dtool/src/interrogate/functionRemap.h

@@ -101,6 +101,7 @@ public:
     F_divide_float       = 0x2000,
     F_hash               = 0x4000,
     F_explicit_args      = 0x8000,
+    F_explicit_cls       =0x10000,
   };
 
   typedef std::vector<Parameter> Parameters;

+ 8 - 1
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -1669,7 +1669,11 @@ write_module_class(ostream &out, Object *obj) {
     }
 
     if (!func->_has_this) {
-      flags += " | METH_STATIC";
+      if (func->_flags & FunctionRemap::F_explicit_cls) {
+        flags += " | METH_CLASS";
+      } else {
+        flags += " | METH_STATIC";
+      }
 
       // Skip adding this entry if we also have a property with the same name.
       // In that case, we will use a Dtool_StaticProperty to disambiguate
@@ -3527,6 +3531,9 @@ write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker
   if (func->_has_this) {
     prototype += "self";
   }
+  else if (func->_flags & FunctionRemap::F_explicit_cls) {
+    prototype += "cls";
+  }
 
   switch (func->_args_type) {
   case AT_keyword_args: