Re: [PyKDE] Now tackle dtor strangeness

2003-01-28 Thread Hans-Peter Jansen
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

2003-01-25 Thread Hans-Peter Jansen
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

2003-01-25 Thread Phil Thompson
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