wx.xrc.XmlResourceHandler.CanHandle is never called for custom XmlResourceHandler

Hi list and discuss forum.

I am making an XmlResourceHandler for wx.py.shell.Shell like this:

class ShellXmlHandler(wx.xrc.XmlResourceHandler):
    def __init__(self):
        wx.xrc.XmlResourceHandler.__init__(self)
        self.AddWindowStyles()
        return


    def CanHandle(self, node):
        return self.IsOfClass(node, "Shell")


    def DoCreateResource(self):
        assert self.GetInstance() is None

        shell = wx.py.shell.Shell(self.GetParentAsWindow(),
                              self.GetID(),
                              self.GetPosition(),
                              self.GetSize(),
                              self.GetStyle()
                              )

        self.SetupWindow(shell)
        self.CreateChildren(shell)
        return shell

and in my app’s OnInit I am registering the handler like that:

    wx.xrc.XmlResource.Get().InitAllHandlers()
    wx.xrc.XmlResource.Get().InsertHandler(gui.agtres.ShellXmlHandler())

Its CanHandle never appears to be called (among others I have added a sys.exit(-1) inside it) and when the application starts it displays a message like

02:21:05: XRC error: 317: no handler found for XML node "object" (class "Shell")
02:21:05: XRC error: 317: unexpected item in sizer

What could be possibly wrong?

I am using wxPython 4.0.6 on python 2.7.16 win32. Thank you very much.

I think I have found the cause:

It appears that for some reason

wx.xrc.XmlResource.Get()

was not “very global”. When I assigned the value returned from Get() to a wx.App attribute (thus increasing its refcount) and accessing it through it (wx.GetApp().XmlRes) everything worked as expected. An explanation could be that somehow the global’s XmlResource object refcount is somehow reduced to 0 and removed by the garbage collector?

I have copy-pasted my code from an older (2.8.10 I think) application where it worked just fine with Get().

That’s a logical conclusion from the symptoms presented, but it doesn’t appear to be true. The deletion of the C++ object when the Python proxy object is GC’d only happens if the proxy object owns the C++ object. But as can be seen in the code below, that is not the case. So even if the Python object goes away the C++ object will still exist, and a new proxy wrapper around that same C++ object is created the next time Get is called.

>>> import wx.xrc
>>> import wx.siplib
>>> 
>>> r = wx.xrc.XmlResource.Get()
>>> r
<wx._xrc.XmlResource object at 0x11a945e58>
>>> wx.siplib.ispyowned(r)
False
>>> del r
>>> r = wx.xrc.XmlResource.Get()
>>> r
<wx._xrc.XmlResource object at 0x11a945ee8>
>>> wx.siplib.ispyowned(r)
False
>>> 

What version are you using now?

BTW, there is no need to call InitAllHandlers(). It is called when wx.xrc is imported the first time.

I am using wxPython 4.0.6 on python 2.7.16 win32.