Re: [PyKDE] Now tackle dtor strangeness
On Sunday 26 January 2003 01:16, Phil Thompson wrote: Funny side note: it was enough to fix one of both sub classes this way to prevent attribute errors here. This is pretty undeterministic, and that's exactly the reason, why I don't like this behaviour... Phil, one would expect, that as long as a class exists, its baseclass should exist, either. The same goes for globals in module scope. The class will exist (because the sub-class keeps a reference to it) but that doesn't mean that the reference to the class in (for example) the module's dictionary still exists. The problem is that the order in which a dictionary's elements are deleted isn't very deterministic. In your example qEventDict is being removed from the module dictionary before the qEvent function is removed. By moving qEventDict into the qEvent function you guarantee it will exist whenever qEvent is called. I would guess that the problem would also go away if you played with the names of qEvent and qEventDict so that they had hash values that caused them to appear in the module dictionary in the opposite order so that qEvent was deleted first. I wasn't able to modify this behaviour with name mangling. OTOH, creating a separate startup module solved this for me. For the record: If you suffer from attribute exceptions after calling qApp.quit(), and have defined overloaded event methods in an all in one module, try creating a seperate startup module in order to fix the race between pythons cleanup and Qt events still delivered. Pythons '-v' option may be helpful in this scenario, too. Pete ___ PyKDE mailing list[EMAIL PROTECTED] http://mats.gmd.de/mailman/listinfo/pykde
[PyKDE] Now tackle dtor strangeness
On Saturday 25 January 2003 17:02, Phil Thompson wrote: Thanks for putting the effort into this - it was very helpful. The bug is that qspinbox.sip should say... bool eventFilter(QObject *,QEvent *); ...instead of... void eventFilter(QObject *,QEvent *); It will be fixed in tonight's snapshot. Thanks. Well done. I feel better now. But please have another look into these two: qApp.quit(). Phil, it appears, that the QSpinBox base class disappears while subclassed SpinBox event() handler is active. This doesn't look right to me. While making both versions functional identical, I've rewritten the event decoder qEvent(), but couldn't believe my eyes: during qApp.quit() the value of the global defined qEventDict{} in the .py script is replaced with a None value somewhere under the covers! Please remove the Something is definitely going wrong here. I think this is just Python and Qt racing each other to tidy up. As the behaviour of either isn't formally documented I think it's more a feature rather than a bug. Well, I cannot see the feature aspect here. OTOH, this obfuscates the code, and it defies the principle of least surprise. I digged into this a bit further and found a way to get around these problems somehow: 1) The qEventDict does survive, if it is declared inside the qEvent function. 2) just keep a reference of QSpinBox, and call it, instead of the baseclass: class SpinBox(QSpinBox): def __init__(self, minValue, maxValue, step = 1, parent = None, name = None): self.lastval = None QSpinBox.__init__(self, minValue, maxValue, step, parent, name) self.QSpinBox = QSpinBox def event(self, e): t = e.type() print SpinBox event:, qEvent(t) return self.QSpinBox.event(self, e) Funny side note: it was enough to fix one of both sub classes this way to prevent attribute errors here. This is pretty undeterministic, and that's exactly the reason, why I don't like this behaviour... Phil, one would expect, that as long as a class exists, its baseclass should exist, either. The same goes for globals in module scope. Note, that this happens, before dtor of QApplication aka PyQtDisownTopLevelWidgets(), and even siplib:finalise() is called: closeEvent exec_loop: 0 PushButton event: WindowDeactivate SpinBox event: WindowDeactivate PushButton event: FocusOut PushButton focusOutEvent PushButton event: Hide SpinBox event: Hide PyQtDisownTopLevelWidgets PyQtDisownTopLevelWidgets finalise begin finalise done Is it possible to keep a reference on these internally and throw them away in finalise()? For reference, current sbtest.py attached. Phil Pete #!/usr/bin/env python # sbtest v0.1: investigate QSpinBox strangeness # # Copyright 2002 Hans-Peter Jansen [EMAIL PROTECTED] # # This program is placed under the GNU General Public License V.2 import sys from qt import * # Just swap the _ of both qEventDicts to suppress the attribute errors qEventDict = { 0: None, 1: Timer, 2: MouseButtonPress, 3: MouseButtonRelease, 4: MouseButtonDblClick, 5: MouseMove, 6: KeyPress, 7: KeyRelease, 8: FocusIn, 9: FocusOut, 10: Enter, 11: Leave, 12: Paint, 13: Move, 14: Resize, 15: Create, 16: Destroy, 17: Show, 18: Hide, 19: Close, 20: Quit, 21: Reparent, 22: ShowMinimized, 23: ShowNormal, 24: WindowActivate, 25: WindowDeactivate, 26: ShowToParent, 27: HideToParent, 28: ShowMaximized, 29: ShowFullScreen, 30: Accel, 31: Wheel, 32: AccelAvailable, 33: CaptionChange, 34: IconChange, 35: ParentFontChange, 36: ApplicationFontChange, 37: ParentPaletteChange, 38: ApplicationPaletteChange, 39: PaletteChange, 40: Clipboard, 42: Speech, 50: SockAct, 51: AccelOverride, 52: DeferredDelete, 60: DragEnter, 61: DragMove, 62: DragLeave, 63: Drop, 64: DragResponse, 70: ChildInserted, 71: ChildRemoved, 72: LayoutHint, 73: ShowWindowRequest, 80: ActivateControl, 81: DeactivateControl, 82: ContextMenu, 83: IMStart, 84: IMCompose, 85: IMEnd, 86: Accessibility, 87: Tablet } def qEvent(t): _qEventDict = { 0: None, 1: Timer, 2: MouseButtonPress, 3: MouseButtonRelease, 4: MouseButtonDblClick, 5: MouseMove, 6: KeyPress, 7: KeyRelease, 8: FocusIn, 9: FocusOut, 10: Enter, 11: Leave, 12: Paint, 13: Move, 14: Resize, 15: Create, 16: Destroy, 17: Show, 18: Hide, 19: Close, 20: Quit, 21: Reparent, 22: ShowMinimized, 23: ShowNormal, 24: WindowActivate, 25: WindowDeactivate, 26: ShowToParent, 27: HideToParent, 28: ShowMaximized, 29: ShowFullScreen, 30: Accel, 31: Wheel,
Re: [PyKDE] Now tackle dtor strangeness
On Saturday 25 January 2003 11:07 pm, Hans-Peter Jansen wrote: On Saturday 25 January 2003 17:02, Phil Thompson wrote: Thanks for putting the effort into this - it was very helpful. The bug is that qspinbox.sip should say... bool eventFilter(QObject *,QEvent *); ...instead of... void eventFilter(QObject *,QEvent *); It will be fixed in tonight's snapshot. Thanks. Well done. I feel better now. But please have another look into these two: qApp.quit(). Phil, it appears, that the QSpinBox base class disappears while subclassed SpinBox event() handler is active. This doesn't look right to me. While making both versions functional identical, I've rewritten the event decoder qEvent(), but couldn't believe my eyes: during qApp.quit() the value of the global defined qEventDict{} in the .py script is replaced with a None value somewhere under the covers! Please remove the Something is definitely going wrong here. I think this is just Python and Qt racing each other to tidy up. As the behaviour of either isn't formally documented I think it's more a feature rather than a bug. Well, I cannot see the feature aspect here. OTOH, this obfuscates the code, and it defies the principle of least surprise. I digged into this a bit further and found a way to get around these problems somehow: 1) The qEventDict does survive, if it is declared inside the qEvent function. 2) just keep a reference of QSpinBox, and call it, instead of the baseclass: class SpinBox(QSpinBox): def __init__(self, minValue, maxValue, step = 1, parent = None, name = None): self.lastval = None QSpinBox.__init__(self, minValue, maxValue, step, parent, name) self.QSpinBox = QSpinBox def event(self, e): t = e.type() print SpinBox event:, qEvent(t) return self.QSpinBox.event(self, e) Funny side note: it was enough to fix one of both sub classes this way to prevent attribute errors here. This is pretty undeterministic, and that's exactly the reason, why I don't like this behaviour... Phil, one would expect, that as long as a class exists, its baseclass should exist, either. The same goes for globals in module scope. The class will exist (because the sub-class keeps a reference to it) but that doesn't mean that the reference to the class in (for example) the module's dictionary still exists. The problem is that the order in which a dictionary's elements are deleted isn't very deterministic. In your example qEventDict is being removed from the module dictionary before the qEvent function is removed. By moving qEventDict into the qEvent function you guarantee it will exist whenever qEvent is called. I would guess that the problem would also go away if you played with the names of qEvent and qEventDict so that they had hash values that caused them to appear in the module dictionary in the opposite order so that qEvent was deleted first. Phil ___ PyKDE mailing list[EMAIL PROTECTED] http://mats.gmd.de/mailman/listinfo/pykde