wxPython Development Journal
Robin Dunn
Chandler GUI Frameworks Engineer, OSA Foundation
07 February 2006
Introduction
This document is a journal of significant development changes to the wxPython bindings for wxWidgets, in reverse chronological order. Enjoy!
07 February 2006
The changes affect how the C++ virtual method calls are reflected into Python when the methods are overridden in a Python-derived class. Well, actually the call is basically the same as before, but now in those cases when the overridden method needs to call the base class version of the method it is able to do it the "normal way" by just invoking the base method using the base class name, rather than needing to know that the base method was renamed with a "base_" prefix.
There is one tricky thing that was done to enable this and that is to temporarily set an attribute in the instance that has the same name as the overridden method. In this case, if the overridden method wants to call the base class version, then the lookup mechanism in wxPython will first find the temporary attribute, but since it is not a method object it will instead call the base class version. So for example, in a class derived from wx.html.HtmlWindow if you want to override OnLinkClicked and want to still have the base class version of the method called, you can now do it like this instead of needing to call self.base_OnLinkClicked, (although base_OnLinkClicked is still there):
def <nop>OnLinkClicked(self, linkinfo):
# ... whatever ...
wx.html.HtmlWindow.OnLinkClicked(self, linkinfo)
And so the trick I mentioned above is that for the duration of this function call self will have an OnLinkClicked attribute set to None, so when the call to wx.html.HtmlWindow.OnLinkClicked is made the code in wxPyCallbackHelper::findCallback will not find a method object by that name and so will reflect the call to the C++ version of the method. Potential runtime issues to watch out for are related to this tricky thing of setting this attribute. If the attrbiute doesn't get removed for some reason, or if the base class version is called in some way that I'm not expecting, then you can get an exception something like "NoneType has no method named OnWhatever."
This works even in the following example:
class A(wx.html.HtmlWindow):
def OnLinkClicked(self, linkinfo):
super(A, self).OnLinkClicked(linkinfo)
class B(A):
def OnLinkClicked(self, linkinfo):
super(B, self).OnLinkClicked(linkinfo)