From 5d833c988aaace97b5460ed1bb2d4c53c3c9bf27 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 5 May 2023 10:55:06 +0200 Subject: [PATCH] interrogate: Support explicit `cls` parameter for static methods --- dtool/src/interrogate/functionRemap.cxx | 20 ++++++++++++++----- dtool/src/interrogate/functionRemap.h | 1 + .../interfaceMakerPythonNative.cxx | 9 ++++++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index 2e984c652b..f4fc81ddbe 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/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) { diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index 61ce48bcb6..87c6b0a523 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/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 Parameters; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index cc184c7efa..e1bf72eb93 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/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: