diff options
Diffstat (limited to 'sources/shiboken6/libshiboken/signature')
4 files changed, 53 insertions, 81 deletions
diff --git a/sources/shiboken6/libshiboken/signature/signature.cpp b/sources/shiboken6/libshiboken/signature/signature.cpp index f83618779..3255cb56d 100644 --- a/sources/shiboken6/libshiboken/signature/signature.cpp +++ b/sources/shiboken6/libshiboken/signature/signature.cpp @@ -197,7 +197,7 @@ PyObject *GetSignature_Wrapper(PyObject *ob, PyObject *modifier) PyObject *props = PyDict_GetItem(dict, func_name); if (props == nullptr) { // handle `__init__` like the class itself - if (strcmp(String::toCString(func_name), "__init__") == 0) + if (PyUnicode_CompareWithASCIIString(func_name, "__init__") == 0) return GetSignature_TypeMod(objclass, modifier); Py_RETURN_NONE; } @@ -227,6 +227,8 @@ PyObject *GetSignature_TypeMod(PyObject *ob, PyObject *modifier) // The `modifier` argument is a string that is passed in from `loader.py`. // Configuration what the modifiers mean is completely in Python. // +// PYSIDE-2101: The __signature__ attribute is gone due to rlcompleter. +// PyObject *get_signature_intern(PyObject *ob, PyObject *modifier) { @@ -246,6 +248,9 @@ PyObject *get_signature_intern(PyObject *ob, PyObject *modifier) return pyside_tp_get___signature__(ob, modifier); if (Py_TYPE(ob) == &PyWrapperDescr_Type) return pyside_wd_get___signature__(ob, modifier); + // For classmethods we use the simple wrapper description implementation. + if (Py_TYPE(ob) == &PyClassMethodDescr_Type) + return pyside_wd_get___signature__(ob, modifier); return nullptr; } @@ -302,7 +307,7 @@ static PyObject *feature_import(PyObject * /* self */, PyObject *args, PyObject PyMethodDef signature_methods[] = { {"__feature_import__", (PyCFunction)feature_import, METH_VARARGS | METH_KEYWORDS, nullptr}, {"get_signature", (PyCFunction)get_signature, METH_VARARGS, - "get the __signature__, but pass an optional string parameter"}, + "get the signature, passing an optional string parameter"}, {nullptr, nullptr, 0, nullptr} }; @@ -385,9 +390,7 @@ PyObject *PySide_BuildSignatureProps(PyObject *type_key) #ifdef PYPY_VERSION static bool get_lldebug_flag() { - PyObject *sysmodule = PyImport_AddModule("sys"); - auto *dic = PyModule_GetDict(sysmodule); - dic = PyDict_GetItemString(dic, "pypy_translation_info"); + auto *dic = PySys_GetObject("pypy_translation_info"); int lldebug = PyObject_IsTrue(PyDict_GetItemString(dic, "translation.lldebug")); int lldebug0 = PyObject_IsTrue(PyDict_GetItemString(dic, "translation.lldebug0")); return lldebug || lldebug0; @@ -428,8 +431,6 @@ static int PySide_FinishSignatures(PyObject *module, const char *signatures[]) if (PyCFunction_Check(func)) if (PyDict_SetItem(pyside_globals->map_dict, func, module) < 0) return -1; - if (_finish_nested_classes(obdict) < 0) - return -1; // The finish_import function will not work the first time since phase 2 // was not yet run. But that is ok, because the first import is always for // the shiboken module (or a test module). @@ -451,10 +452,12 @@ static int PySide_FinishSignatures(PyObject *module, const char *signatures[]) int InitSignatureStrings(PyTypeObject *type, const char *signatures[]) { + // PYSIDE-2404: This function now also builds the mapping for static methods. + // It was one missing spot to let Lazy import work. init_shibokensupport_module(); auto *ob_type = reinterpret_cast<PyObject *>(type); int ret = PySide_BuildSignatureArgs(ob_type, signatures); - if (ret < 0) { + if (ret < 0 || _build_func_to_type(ob_type) < 0) { PyErr_Print(); PyErr_SetNone(PyExc_ImportError); } @@ -471,6 +474,8 @@ void FinishSignatureInitialization(PyObject *module, const char *signatures[]) * Still, it is not possible to call init phase 2 from here, * because the import is still running. Do it from Python! */ + init_shibokensupport_module(); + #ifndef PYPY_VERSION static const bool patch_types = true; #else @@ -534,7 +539,7 @@ static PyObject *adjustFuncName(const char *func_name) // Find the feature flags auto type = reinterpret_cast<PyTypeObject *>(obtype.object()); - auto dict = type->tp_dict; + AutoDecRef dict(PepType_GetDict(type)); int id = currentSelectId(type); id = id < 0 ? 0 : id; // if undefined, set to zero auto lower = id & 0x01; @@ -583,7 +588,9 @@ void SetError_Argument(PyObject *args, const char *func_name, PyObject *info) PyObject *e, *v, *t; // Note: These references are all borrowed. PyErr_Fetch(&e, &v, &t); + Py_DECREF(e); info = v; + Py_XDECREF(t); } // PYSIDE-1019: Modify the function name expression according to feature. AutoDecRef new_func_name(adjustFuncName(func_name)); @@ -614,14 +621,10 @@ void SetError_Argument(PyObject *args, const char *func_name, PyObject *info) * But the __doc__ attribute existed already by inheritance, and calling * PyType_Modified() is not supported. So we added the getsets explicitly * to the metatype. + * + * PYSIDE-2101: The __signature__ attribute is gone due to rlcompleter. */ -PyObject *Sbk_TypeGet___signature__(PyObject *ob, PyObject *modifier) -{ - init_shibokensupport_module(); - return pyside_tp_get___signature__(ob, modifier); -} - PyObject *Sbk_TypeGet___doc__(PyObject *ob) { init_shibokensupport_module(); diff --git a/sources/shiboken6/libshiboken/signature/signature_extend.cpp b/sources/shiboken6/libshiboken/signature/signature_extend.cpp index d571f90f3..7292f8216 100644 --- a/sources/shiboken6/libshiboken/signature/signature_extend.cpp +++ b/sources/shiboken6/libshiboken/signature/signature_extend.cpp @@ -70,8 +70,6 @@ PyObject *pyside_cf_get___signature__(PyObject *func, PyObject *modifier) PyObject *pyside_sm_get___signature__(PyObject *sm, PyObject *modifier) { AutoDecRef func(PyObject_GetAttr(sm, PyMagicName::func())); - if (Py_TYPE(func) == PepFunction_TypePtr) - return PyObject_GetAttr(func, PyMagicName::signature()); return _get_written_signature(GetSignature_Function, func, modifier); } @@ -79,7 +77,7 @@ PyObject *pyside_md_get___signature__(PyObject *ob_md, PyObject *modifier) { AutoDecRef func(name_key_to_func(ob_md)); if (func.object() == Py_None) - return Py_None; + Py_RETURN_NONE; if (func.isNull()) Py_FatalError("missing mapping in MethodDescriptor"); return pyside_cf_get___signature__(func, modifier); @@ -123,13 +121,15 @@ static PyObject *handle_doc(PyObject *ob, PyObject *old_descr) { AutoDecRef ob_type_mod(GetClassOrModOf(ob)); const char *name; - if (PyModule_Check(ob_type_mod.object())) + bool isModule = PyModule_Check(ob_type_mod.object()); + if (isModule) name = PyModule_GetName(ob_type_mod.object()); else name = reinterpret_cast<PyTypeObject *>(ob_type_mod.object())->tp_name; PyObject *res{}; - if (handle_doc_in_progress || name == nullptr || strncmp(name, "PySide6.", 8) != 0) { + if (handle_doc_in_progress || name == nullptr + || (isModule && strncmp(name, "PySide6.", 8) != 0)) { res = PyObject_CallMethodObjArgs(old_descr, PyMagicName::get(), ob, nullptr); } else { handle_doc_in_progress++; @@ -169,59 +169,29 @@ static PyObject *pyside_wd_get___doc__(PyObject *wd) return handle_doc(wd, old_wd_doc_descr); } -// the default setter for all objects -static int pyside_set___signature__(PyObject *op, PyObject *value) -{ - // By this additional check, this function refuses write access. - // We consider both nullptr and Py_None as not been written. - AutoDecRef has_val(get_signature_intern(op, nullptr)); - if (!(has_val.isNull() || has_val == Py_None)) { - PyErr_Format(PyExc_AttributeError, - "Attribute '__signature__' of '%.50s' object is not writable", - Py_TYPE(op)->tp_name); - return -1; - } - int ret = value == nullptr ? PyDict_DelItem(pyside_globals->value_dict, op) - : PyDict_SetItem(pyside_globals->value_dict, op, value); - Py_XINCREF(value); - return ret; -} - // PYSIDE-535: We cannot patch types easily in PyPy. // Let's use the `get_signature` function, instead. static PyGetSetDef new_PyCFunction_getsets[] = { {const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_cf_get___doc__), nullptr, nullptr, nullptr}, - {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_cf_get___signature__), - reinterpret_cast<setter>(pyside_set___signature__), - nullptr, nullptr}, {nullptr, nullptr, nullptr, nullptr, nullptr} }; static PyGetSetDef new_PyStaticMethod_getsets[] = { {const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_sm_get___doc__), nullptr, nullptr, nullptr}, - {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_sm_get___signature__), - reinterpret_cast<setter>(pyside_set___signature__), - nullptr, nullptr}, {nullptr, nullptr, nullptr, nullptr, nullptr} }; static PyGetSetDef new_PyMethodDescr_getsets[] = { {const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_md_get___doc__), nullptr, nullptr, nullptr}, - {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_md_get___signature__), - reinterpret_cast<setter>(pyside_set___signature__), - nullptr, nullptr}, {nullptr, nullptr, nullptr, nullptr, nullptr} }; static PyGetSetDef new_PyWrapperDescr_getsets[] = { {const_cast<char *>("__doc__"), reinterpret_cast<getter>(pyside_wd_get___doc__), nullptr, nullptr, nullptr}, - {const_cast<char *>("__signature__"), reinterpret_cast<getter>(pyside_wd_get___signature__), - reinterpret_cast<setter>(pyside_set___signature__), - nullptr, nullptr}, {nullptr, nullptr, nullptr, nullptr, nullptr} }; diff --git a/sources/shiboken6/libshiboken/signature/signature_globals.cpp b/sources/shiboken6/libshiboken/signature/signature_globals.cpp index d0ea86fc6..3a79a12d5 100644 --- a/sources/shiboken6/libshiboken/signature/signature_globals.cpp +++ b/sources/shiboken6/libshiboken/signature/signature_globals.cpp @@ -88,11 +88,9 @@ static safe_globals_struc *init_phase_1() * Due to MSVC's limitation to 64k strings, we needed to assemble pieces. */ auto **block_ptr = reinterpret_cast<const char **>(PySide_CompressedSignaturePackage); - int npieces = 0; PyObject *piece{}; AutoDecRef zipped_string_sequence(PyList_New(0)); for (; **block_ptr != 0; ++block_ptr) { - npieces++; // we avoid the string/unicode dilemma by not using PyString_XXX: piece = Py_BuildValue("s", *block_ptr); if (piece == nullptr || PyList_Append(zipped_string_sequence, piece) < 0) @@ -189,6 +187,16 @@ static int init_phase_2(safe_globals_struc *p, PyMethodDef *methods) p->feature_imported_func = PyObject_GetAttrString(loader, "feature_imported"); if (p->feature_imported_func == nullptr) break; + + // We call stuff like the feature initialization late, + // after all the function pointers are in place. + PyObject *post_init_func = PyObject_GetAttrString(loader, "post_init"); + if (post_init_func == nullptr) + break; + PyObject *ret = PyObject_CallFunctionObjArgs(post_init_func, nullptr); + if (ret == nullptr) + break; + return 0; } while (0); @@ -201,12 +209,12 @@ static int init_phase_2(safe_globals_struc *p, PyMethodDef *methods) #ifndef _WIN32 //////////////////////////////////////////////////////////////////////////// // a stack trace for linux-like platforms -#include <stdio.h> +#include <cstdio> #if defined(__GLIBC__) # include <execinfo.h> #endif #include <signal.h> -#include <stdlib.h> +#include <cstdlib> #include <unistd.h> static void handler(int sig) { @@ -219,7 +227,7 @@ static void handler(int sig) { // print out all the frames to stderr #endif - fprintf(stderr, "Error: signal %d:\n", sig); + std::fprintf(stderr, "Error: signal %d:\n", sig); #if defined(__GLIBC__) backtrace_symbols_fd(array, size, STDERR_FILENO); #endif @@ -229,7 +237,7 @@ static void handler(int sig) { //////////////////////////////////////////////////////////////////////////// #endif // _WIN32 -safe_globals pyside_globals = nullptr; +safe_globals_struc *pyside_globals = nullptr; void init_shibokensupport_module(void) { diff --git a/sources/shiboken6/libshiboken/signature/signature_helper.cpp b/sources/shiboken6/libshiboken/signature/signature_helper.cpp index ef0c021d5..cf84cfa13 100644 --- a/sources/shiboken6/libshiboken/signature/signature_helper.cpp +++ b/sources/shiboken6/libshiboken/signature/signature_helper.cpp @@ -51,10 +51,13 @@ int add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr) /* * This function is used to assign a new `__signature__` attribute, * and also to override a `__doc__` or `__name__` attribute. + * + * PYSIDE-2101: The __signature__ attribute is gone due to rlcompleter. */ assert(PyType_Check(type)); PyType_Ready(type); - PyObject *dict = type->tp_dict; + AutoDecRef tpDict(PepType_GetDict(type)); + auto *dict = tpDict.object(); for (; gsp->name != nullptr; gsp++) { PyObject *have_descr = PyDict_GetItemString(dict, gsp->name); if (have_descr != nullptr) { @@ -291,7 +294,7 @@ PyObject *_address_to_stringlist(PyObject *numkey) return res_list; } -static int _build_func_to_type(PyObject *obtype) +int _build_func_to_type(PyObject *obtype) { /* * There is no general way to directly get the type of a static method. @@ -307,7 +310,17 @@ static int _build_func_to_type(PyObject *obtype) * We also check for hidden methods, see below. */ auto *type = reinterpret_cast<PyTypeObject *>(obtype); - PyObject *dict = type->tp_dict; + AutoDecRef tpDict(PepType_GetDict(type)); + auto *dict = tpDict.object(); + + // PYSIDE-2404: Get the original dict for late initialization. + // The dict might have been switched before signature init. + static const auto *pyTypeType_tp_dict = PepType_GetDict(&PyType_Type); + if (Py_TYPE(dict) != Py_TYPE(pyTypeType_tp_dict)) { + tpDict.reset(PyObject_GetAttr(dict, PyName::orig_dict())); + dict = tpDict.object(); + } + PyMethodDef *meth = type->tp_methods; if (meth == nullptr) @@ -373,26 +386,4 @@ static int _build_func_to_type(PyObject *obtype) return 0; } -int _finish_nested_classes(PyObject *obdict) -{ - PyObject *key, *value, *obtype; - PyTypeObject *subtype; - Py_ssize_t pos = 0; - - if (obdict == nullptr) - return -1; - while (PyDict_Next(obdict, &pos, &key, &value)) { - if (PyType_Check(value)) { - obtype = value; - if (_build_func_to_type(obtype) < 0) - return -1; - // now continue with nested cases - subtype = reinterpret_cast<PyTypeObject *>(obtype); - if (_finish_nested_classes(subtype->tp_dict) < 0) - return -1; - } - } - return 0; -} - } // extern "C" |