[PyQt] [BUG] Class name collision

Vladimir Rutsky rutsky.vladimir at gmail.com
Mon Dec 14 15:15:03 GMT 2015


On Sat, Dec 12, 2015 at 1:26 PM, Phil Thompson
<phil at riverbankcomputing.com> wrote:
> On 9 Dec 2015, at 1:21 p.m., Vladimir Rutsky <rutsky.vladimir at gmail.com> wrote:
>>
>> If Python class name is the same as some Qt class name PyQt metacast
>> machinery may try to access missing attribute of the class and
>> generate AttributeError.
>> This AttributeError is not explicitly catched and if Python
>> interpreter is built with enabled assertions (e.g. in debug mode)
>> Python interpreter aborts with failed assert.
>>
>> Here is an example that reproduces this bug (only in debug Python):
>> https://gist.github.com/rutsky/0adfbb56a32b208ab28c
>>
>> from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout
>>
>> class QWindow(QWidget):
>>    def __init__(self, parent=None):
>>        super().__init__(parent)
>>        self.setLayout(QVBoxLayout())
>>        self.layout().parentWidget()  # <-- uncaught exception is
>> generated and asserted here
>>
>> qapp = QApplication([])
>> qwin = QWindow()
>> qwin.show()
>> qapp.exec()
>>
>>
>> Example generates following error:
>>
>> python: ../Objects/abstract.c:2050: PyObject_Call: Assertion `(result
>> != ((void *)0) && !PyErr_Occurred()) || (result == ((void *)0) &&
>> PyErr_Occurred())' failed.
>> Aborted (core dumped)
>>
>>
>> Exception is generated in this PyQt code of
>> qpycore_qobject_qt_metacast() function
>> (PyQt-gpl-5.5.1/qpy/QtCore/qpycore_qobject_helpers.cpp):
>>
>>    for (SIP_SSIZE_T i = 0; i < PyTuple_GET_SIZE(mro); ++i)
>>    {
>>        PyTypeObject *pytype = (PyTypeObject *)PyTuple_GET_ITEM(mro, i);
>>
>>        if (!PyObject_IsInstance((PyObject *)pytype, (PyObject
>> *)&qpycore_pyqtWrapperType_Type))
>>            continue;
>>
>>        const sipTypeDef *td = ((sipWrapperType *)pytype)->type;
>>
>>        if (qstrcmp(pytype->tp_name, _clname) == 0)
>>        {
>>            // The generated type definitions represent the C++ (rather than
>>            // Python) hierachy.  If the C++ hierachy doesn't match then the
>>            // super-type must be provided by a mixin.
>>            if (PyType_IsSubtype(base_pytype, pytype))
>>                *sipCpp = sipGetAddress(pySelf);
>>            else
>>                // ====================================
>>                // Attribute error is generated here, something like:
>>                // "AttributeError: 'QWindow' object has no attribute 'QWidget'"
>>                // ====================================
>>               *sipCpp = sipGetMixinAddress(pySelf, td);
>>
>>            is_py_class = true;
>>            break;
>>        }
>>
>> While whole attribute access thing looks unstable to me (what if not
>> only class name will collide, but also my class will have accessed
>> attribute?), adding explicit check for AttributeError here fixes this
>> issue. Attached patch workarounds (fixes?) this issue.
>
> The underlying bug is actually in SIP - fixed in tonight's snapshot.
>
> Thanks,
> Phil


Thanks, Phil, I can confirm that with nightly snapshot of sip
(sip-4.17.1-snapshot-602884540b54) the issue is not reproduced.

--
Vladimir Rutsky


More information about the PyQt mailing list