Skip to content

Instantly share code, notes, and snippets.

@altendky

altendky/bad.py Secret

Last active August 3, 2019 18:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save altendky/f15f8d180269a4080c25dec83cf556a0 to your computer and use it in GitHub Desktop.
Save altendky/f15f8d180269a4080c25dec83cf556a0 to your computer and use it in GitHub Desktop.
import io
import sys
import traceback
import PyQt5.QtCore
import PyQt5.QtWidgets
import PyQt5.uic
import sip
system_info = f'''\
sys.version: {sys.version}
sys.platform: {sys.platform}
QT_VERSION_STR: {PyQt5.QtCore.QT_VERSION_STR}
PYQT_VERSION_STR: {PyQt5.QtCore.PYQT_VERSION_STR}
SIP_VERSION_STR: {sip.SIP_VERSION_STR}'''
ui_text = '''\
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
'''
class WidgetA(PyQt5.QtWidgets.QWidget):
def __init__(self, broken, parent=None):
super().__init__(parent=parent)
if broken:
PyQt5.uic.loadUi(io.StringIO(ui_text), self)
self._a = 0
self._b = 1
if not broken:
PyQt5.uic.loadUi(io.StringIO(ui_text), self)
# removing either of the following also makes it not fail
@PyQt5.QtCore.pyqtProperty(int)
def property_a(self):
print('getting a')
result = self._a
print('got a')
return result
@PyQt5.QtCore.pyqtProperty(int)
def property_b(self):
print('getting b')
result = self._b
print('got b')
return result
class WidgetB(PyQt5.QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = PyQt5.uic.loadUi(io.StringIO(ui_text), self)
@PyQt5.QtCore.pyqtProperty(int)
def property_a(self):
print('getting a:')
print(" hasattr(self, 'ui') == {}".format(hasattr(self, 'ui')))
print(" hasattr(self, 'label') == {}".format(hasattr(self, 'label')))
result = self.ui.label.text()
print('got a')
return result
Ui, UiBase = PyQt5.uic.loadUiType(io.StringIO(ui_text))
class WidgetC(UiBase):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = Ui()
self.ui.setupUi(self)
@PyQt5.QtCore.pyqtProperty(int)
def property_a(self):
print('getting a:')
print(" hasattr(self, 'ui') == {}".format(hasattr(self, 'ui')))
print(" hasattr(self.ui, 'label') == {}".format(hasattr(self.ui, 'label')))
result = self.ui.label.text()
print('got a')
return result
def main():
print(system_info)
app = PyQt5.QtWidgets.QApplication([])
widgets = []
print()
print(' ------ creating WidgetC and...')
widgets.append(WidgetC())
print()
print(' ------ creating WidgetC and... now it still works')
widgets.append(WidgetC())
print()
print(' ------ creating WidgetB and...')
widgets.append(WidgetB())
print()
print(' ------ creating WidgetB and... now it breaks')
try:
widgets.append(WidgetB())
except Exception:
traceback.print_exc()
print()
print(' ------ creating WidgetA without breaking')
widgets.append(WidgetA(broken=False))
print()
print(' ------ creating WidgetA but breaking in the process')
try:
widgets.append(WidgetA(broken=True))
except Exception:
traceback.print_exc()
main()
~/tmp   master ●  venv3.7.3/bin/python bad.py
sys.version: 3.7.3 (default, Apr 16 2019, 16:54:41)
[GCC 6.3.0 20170516]
sys.platform: linux
QT_VERSION_STR: 5.13.0
PYQT_VERSION_STR: 5.13.0
SIP_VERSION_STR: 4.19.18
------ creating WidgetC and...
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetC and... now it still works
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetB and...
getting a:
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
------ creating WidgetB and... now it breaks
getting a:
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
------ creating WidgetA without breaking
getting a
got a
getting b
got b
------ creating WidgetA but breaking in the process
getting a
getting b
~/tmp   master ●  venv3.7.4/bin/python bad.py
sys.version: 3.7.4 (default, Aug 2 2019, 12:58:45)
[GCC 6.3.0 20170516]
sys.platform: linux
QT_VERSION_STR: 5.13.0
PYQT_VERSION_STR: 5.13.0
SIP_VERSION_STR: 4.19.18
------ creating WidgetC and...
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetC and... now it still works
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetB and...
getting a:
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
------ creating WidgetB and... now it breaks
getting a:
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
AttributeError: __getattribute__
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "bad.py", line 135, in main
widgets.append(WidgetB())
File "bad.py", line 82, in __init__
self.ui = PyQt5.uic.loadUi(io.StringIO(ui_text), self)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/__init__.py", line 227, in loadUi
return DynamicUILoader(package).loadUi(uifile, baseinstance, resource_suffix)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/Loader/loader.py", line 72, in loadUi
return self.parse(filename, resource_suffix, basedir)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/uiparser.py", line 1030, in parse
actor(elem)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/uiparser.py", line 942, in createConnections
QtCore.QMetaObject.connectSlotsByName(self.toplevelWidget)
SystemError: <built-in function connectSlotsByName> returned a result with an error set
------ creating WidgetA without breaking
getting a
got a
getting b
got b
------ creating WidgetA but breaking in the process
getting a
getting b
AttributeError: __getattribute__
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "bad.py", line 146, in main
widgets.append(WidgetA(broken=True))
File "bad.py", line 53, in __init__
PyQt5.uic.loadUi(io.StringIO(ui_text), self)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/__init__.py", line 227, in loadUi
return DynamicUILoader(package).loadUi(uifile, baseinstance, resource_suffix)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/Loader/loader.py", line 72, in loadUi
return self.parse(filename, resource_suffix, basedir)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/uiparser.py", line 1030, in parse
actor(elem)
File "/home/altendky/tmp/venv3.7.4/lib/python3.7/site-packages/PyQt5/uic/uiparser.py", line 942, in createConnections
QtCore.QMetaObject.connectSlotsByName(self.toplevelWidget)
SystemError: <built-in function connectSlotsByName> returned a result with an error set
PS C:\epc\bug> venv/scripts/python bad.py
sys.version: 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 21:26:53) [MSC v.1916 32 bit (Intel)]
sys.platform: win32
QT_VERSION_STR: 5.13.0
PYQT_VERSION_STR: 5.13.0
SIP_VERSION_STR: 4.19.18
------ creating WidgetC and...
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetC and... now it still works
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetB and...
getting a:
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
------ creating WidgetB and... now it breaks
getting a:
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
------ creating WidgetA without breaking
getting a
got a
getting b
got b
------ creating WidgetA but breaking in the process
getting a
getting b
PS C:\epc\bug> venv3.7-32/scripts/python bad.py
sys.version: 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 19:29:22) [MSC v.1916 32 bit (Intel)]
sys.platform: win32
QT_VERSION_STR: 5.13.0
PYQT_VERSION_STR: 5.13.0
SIP_VERSION_STR: 4.19.18
------ creating WidgetC and...
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetC and... now it still works
getting a:
hasattr(self, 'ui') == True
hasattr(self.ui, 'label') == True
got a
------ creating WidgetB and...
getting a:
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
------ creating WidgetB and... now it breaks
hasattr(self, 'ui') == False
hasattr(self, 'label') == True
AttributeError: __getattribute__
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "bad.py", line 135, in main
widgets.append(WidgetB())
File "bad.py", line 82, in __init__
self.ui = PyQt5.uic.loadUi(io.StringIO(ui_text), self)
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\__init__.py", line 227, in loadUi
return DynamicUILoader(package).loadUi(uifile, baseinstance, resource_suffix)
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\Loader\loader.py", line 72, in loadUi
return self.parse(filename, resource_suffix, basedir)
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\uiparser.py", line 1030, in parse
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\uiparser.py", line 942, in createConnections
QtCore.QMetaObject.connectSlotsByName(self.toplevelWidget)
SystemError: <built-in function connectSlotsByName> returned a result with an error set
------ creating WidgetA without breaking
got a
getting b
got b
------ creating WidgetA but breaking in the process
AttributeError: __getattribute__
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "bad.py", line 146, in main
widgets.append(WidgetA(broken=True))
File "bad.py", line 53, in __init__
PyQt5.uic.loadUi(io.StringIO(ui_text), self)
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\__init__.py", line 227, in loadUi
return DynamicUILoader(package).loadUi(uifile, baseinstance, resource_suffix)
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\Loader\loader.py", line 72, in loadUi
return self.parse(filename, resource_suffix, basedir)
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\uiparser.py", line 1030, in parse
actor(elem)
File "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\uiparser.py", line 942, in createConnections
QtCore.QMetaObject.connectSlotsByName(self.toplevelWidget)
SystemError: <built-in function connectSlotsByName> returned a result with an error set
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment