diff options
author | Christian Tismer <tismer@stackless.com> | 2022-02-14 18:28:13 +0100 |
---|---|---|
committer | Christian Tismer <tismer@stackless.com> | 2022-02-21 20:01:38 +0100 |
commit | 404e9dff2d859edfc72b1dc45b2d4352ac8f2dff (patch) | |
tree | e499827cb6a089a7d916812eb85a79f714512932 | |
parent | bdc6234bff03fe957ae9db5419d304cb7490f0e5 (diff) |
__feature__: Do the renaming also in the hidden methods
It has taken quite a while until it was understood
why mistyped (un-renamed) methods are still found
when using `snake_case`. It is a very old patch
that searches hidden objects via the QMetaObject
when normal attribute retrieval fails.
This implementation is used all the time, but it is
easily overlooked because most generated wrapper
objects use this implementation from QObjectWrapper
by inheritance, and is not found in the source code.
Renaming these hidden methods the same way as the
normal methods are renamed solves this problem.
As a side effect, the solution to PYSIDE-1765 becomes
more complete, too, since these hidden attributes
were really missing.
[ChangeLog][PySide6] The snake_case feature is now
more complete since it renames hidden methods, too.
Change-Id: I8614314e417a40549ef09f3105a03f22cb575bab
Fixes: PYSIDE-1753
Task-number: PYSIDE-1765
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
(cherry picked from commit 89ea1b0b6579bb71be0fb4fab1ab36d116fcec78)
-rw-r--r-- | sources/pyside6/libpyside/pyside.cpp | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/sources/pyside6/libpyside/pyside.cpp b/sources/pyside6/libpyside/pyside.cpp index b4a119bf5..6b845fa3d 100644 --- a/sources/pyside6/libpyside/pyside.cpp +++ b/sources/pyside6/libpyside/pyside.cpp @@ -320,6 +320,34 @@ void initQApp() setDestroyQApplication(destroyQCoreApplication); } +static QByteArray _sigWithMangledName(const QByteArray &signature, bool mangle) +{ + if (!mangle) + return signature; + auto bracePos = signature.indexOf('('); + auto limit = bracePos >= 0 ? bracePos : signature.size(); + if (limit < 3) + return signature; + QByteArray result; + result.reserve(signature.size() + 4); + for (auto i = 0; i < limit; ++i) { + const char c = signature.at(i); + if (std::isupper(c)) { + if (i > 0) { + if (std::isupper(signature.at(i - 1))) + return signature; // Give up at consecutive upper chars + result.append('_'); + } + result.append(std::tolower(c)); + } else { + result.append(c); + } + } + // Copy the rest after the opening brace (if any) + result.append(signature.mid(limit)); + return result; +} + PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *name) { PyObject *attr = PyObject_GenericGetAttr(self, name); @@ -334,27 +362,38 @@ PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *nam attr = value; } - //mutate native signals to signal instance type + // Mutate native signals to signal instance type if (attr && PyObject_TypeCheck(attr, PySideSignalTypeF())) { - PyObject *signal = reinterpret_cast<PyObject *>(Signal::initialize(reinterpret_cast<PySideSignal *>(attr), name, self)); - PyObject_SetAttr(self, name, reinterpret_cast<PyObject *>(signal)); - return signal; + auto *inst = Signal::initialize(reinterpret_cast<PySideSignal *>(attr), name, self); + PyObject *signalInst = reinterpret_cast<PyObject *>(inst); + PyObject_SetAttr(self, name, signalInst); + return signalInst; } - //search on metaobject (avoid internal attributes started with '__') + // Search on metaobject (avoid internal attributes started with '__') if (!attr) { + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); // This was omitted for a loong time. + const char *cname = Shiboken::String::toCString(name); + int flags = SbkObjectType_GetReserved(Py_TYPE(self)); + int snake_flag = flags & 0x01; uint cnameLen = qstrlen(cname); if (std::strncmp("__", cname, 2)) { const QMetaObject *metaObject = cppSelf->metaObject(); - //signal QList<QMetaMethod> signalList; - for(int i=0, i_max = metaObject->methodCount(); i < i_max; i++) { + for (int i=0, imax = metaObject->methodCount(); i < imax; i++) { QMetaMethod method = metaObject->method(i); - const QByteArray methSig_ = method.methodSignature(); + // PYSIDE-1753: Snake case names must be renamed here too, or they will be + // found unexpectedly when forgetting to rename them. + auto origSignature = method.methodSignature(); + // Currently, we rename only methods but no signals. This might change. + bool use_lower = snake_flag and method.methodType() != QMetaMethod::Signal; + const QByteArray methSig_ = _sigWithMangledName(origSignature, use_lower); const char *methSig = methSig_.constData(); - bool methMacth = !std::strncmp(cname, methSig, cnameLen) && methSig[cnameLen] == '('; - if (methMacth) { + bool methMatch = std::strncmp(cname, methSig, cnameLen) == 0 + && methSig[cnameLen] == '('; + if (methMatch) { if (method.methodType() == QMetaMethod::Signal) { signalList.append(method); } else { @@ -368,11 +407,13 @@ PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *nam } } if (!signalList.isEmpty()) { - PyObject *pySignal = reinterpret_cast<PyObject *>(Signal::newObjectFromMethod(self, signalList)); + PyObject *pySignal = reinterpret_cast<PyObject *>( + Signal::newObjectFromMethod(self, signalList)); PyObject_SetAttr(self, name, pySignal); return pySignal; } } + PyErr_Restore(type, value, traceback); } return attr; } |