"metaclass conflict" error: where is noconflict ?

Barak, Ron Ron.Barak at lsi.com
Sun Feb 22 12:31:01 CET 2009


Hi Chris, 

> -----Original Message-----
> From: Chris Rebert [mailto:clp2 at rebertia.com] 
> Sent: Sunday, February 22, 2009 11:48
> To: Barak, Ron
> Cc: python-list at python.org; wxpython-users at lists.wxwidgets.org
> Subject: Re: "metaclass conflict" error: where is noconflict ?
> 
> On Sun, Feb 22, 2009 at 1:37 AM, Barak, Ron <Ron.Barak at lsi.com> wrote:
> > Hi Chris,
> >
> >> -----Original Message-----
> >> From: chris at rebertia.com [
> > mailto:chris at rebertia.com] On
> >> Behalf Of Chris Rebert
> >> Sent: Thursday, February 19, 2009 22:58
> >> To: Barak, Ron
> >> Cc: python-list at python.org; wxpython-users at lists.wxwidgets.org
> >> Subject: Re: "metaclass conflict" error: where is noconflict ?
> >>
> >> On Thu, Feb 19, 2009 at 5:01 AM, Barak, Ron 
> <Ron.Barak at lsi.com> wrote:
> >> > Hi,
> >> >
> >> > I have a class derived from two parents (in blue below),
> >> which gives
> >> > me the following error:
> >> >
> >> > $ python -u ./failover_pickle_demo09.py Traceback (most 
> recent call
> >> > last):
> >> >   File "./failover_pickle_demo09.py", line 291, in <module>
> >> >     class ListControl(wx.Frame, CopyAndPaste):
> >> > TypeError: Error when calling the metaclass bases
> >> >     metaclass conflict: the metaclass of a derived class 
> must be a
> >> > (non-strict) subclass of the metaclasses of all its 
> bases Googling 
> >> > suggested I should add from noconflict import classmaker and
> >> >
> >> > __metaclass__=classmaker()
> >> > to this class.
> >> >
> >> > However, I don't seem able to find where to get the
> >> noconflict module from.
> >> >
> >> > Do any of you where noconflict  could be 
> downloaded/installed from ?
> >>
> >> From what I could google, you should in theory be able to fix the 
> >> problem (without using any 3rd party module) by doing:
> >>
> >> class ListControlMeta(type(wx.Frame), type(CopyAndPaste)):
> >>     pass
> >>
> >> class ListControl(wx.Frame, CopyAndPaste):
> >>     __metaclass__ = ListControlMeta
> >>     #rest of class...
> >>
> >> Cheers,
> >> Chris
> >
> > Applying your suggestion:
> >
> > class ListControlMeta(type(wx.Frame), type(CopyAndPaste)):
> >     pass
> >
> > class ListControl(wx.Frame, CopyAndPaste):
> >     def __init__(self, parent, id, title, list, max_list_width, 
> > log_stream,
> > style=wx.DEFAULT_FRAME_STYLE):
> >
> >         __metaclass__= ListControlMeta
> >
> >         
> > wx.Frame.__init__(self,parent,id,title,size=(max_list_width,-1),
> > style=style)
> >         self.list = list
> >         self.log_stream = log_stream
> >         self.list_ctrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT |
> > wx.LC_NO_HEADER)
> >         self.list_ctrl.InsertColumn(0, title)
> >         for i,line_ in enumerate(list):
> >             self.list_ctrl.InsertStringItem(i, line_)
> >                 ...
> >
> > I get:
> >
> > $ python -u ./failover_pickle_demo09.py Traceback (most recent call 
> > last):
> >   File "./failover_pickle_demo09.py", line 319, in <module>
> >     class ListControlMeta(type(wx.Frame), type(CopyAndPaste)):
> > TypeError: Error when calling the metaclass bases
> >     multiple bases have instance lay-out conflict
> 
> >From what I recall, that basically means that type(wx.Frame) and
> type(CopyAndPaste) are both C classes that are are mutually 
> incompatible. It's basically the same reason you can't 
> subclass from both `list` and `dict` or two other built-in 
> types (you get the exact same error).
> 
> Sounds like the only way to workaround this would be to do 
> some coding in C or to use composition rather than 
> inheritance for one of ListControl's superclasses.

The wx.Frame may be coded in C, but the CopyAndPaste class, which I wrote, is not (see it's listing below).
Could you have a look at the CopyAndPaste class, and see if something in its construction strikes you as susspicious ?

Thanks,
Ron.

$ cat ./CopyAndPaste.py
#!/usr/bin/env python

import wx

class CopyAndPaste():
    def __init__(self):
        pass

    def set_copy_and_paste(self):
        """
        Setting clipboard copy-and-pasting (only copying from the application to the
        clipboard is supported).
        The "menu" menu is hidded, and is only there to facilitate the acceleration table.
        Both CTRL-C and CTRL-Ins are supported.
        """
        #print line()+". set_copy_and_paste started"
        #print line()+". self.__dict__:",self.__dict__
        menu = wx.Menu()        
        copy_ = menu.Append(-1, "&Copy\tCtrl-Ins") # Copy with accelerator
        minimize_ = menu.Append(-1, "Minimize") # 
        close_ = menu.Append(-1, "Close window\tCtrl-W") # Close window
        exit_ = menu.Append(-1, "E&xit application\tCtrl-X") # Close window
        """
        #copy2_  = menu.Append(-1, "&Copy\tCtrl-C") # Copy with accelerator
        paste_  = menu.Append(-1, "&Paste\tShift-Ins") # Paste with accelerator
        paste2_  = menu.Append(-1, "&Paste\tCtrl-V") # Paste with accelerator
        """
        
        self.Bind(wx.EVT_MENU, self.on_copy, copy_)
        self.Bind(wx.EVT_MENU, self.on_minimize, minimize_)
        self.Bind(wx.EVT_MENU, self.on_close, close_)
        self.Bind(wx.EVT_MENU, self.on_exit, exit_)
        #self.Bind(wx.EVT_MENU, self.on_paste, paste_)
                  
        menuBar = wx.MenuBar()
        self.SetMenuBar(menuBar)

        acceltbl = wx.AcceleratorTable( [
                (wx.ACCEL_CTRL, ord('C'), copy_.GetId()),
                (wx.ACCEL_CTRL, ord('W'), close_.GetId()),
                (wx.ACCEL_CTRL, ord('X'), exit_.GetId()),
                (wx.ACCEL_CTRL, ord('Q'), exit_.GetId()),
                (wx.ACCEL_CTRL, wx.WXK_INSERT, copy_.GetId()),
                (wx.ACCEL_CTRL, wx.WXK_NUMPAD_INSERT, copy_.GetId()),
                #(wx.ACCEL_CTRL, ord('V'), paste_.GetId()),
                #(wx.ACCEL_SHIFT, wx.WXK_INSERT, paste_.GetId()),
            ])
        self.SetAcceleratorTable(acceltbl)

        # Setting popup menu

        self.popupmenu = menu
        self.Bind(wx.EVT_CONTEXT_MENU, self.on_show_popup)

    """    
    def on_paste(self, evt):
        wx.MessageBox("You selected 'paste'")
        """

    
    def on_show_popup(self, evt):
        pos = evt.GetPosition()
        pos = self.list_ctrl.ScreenToClient(pos)
        self.PopupMenu(self.popupmenu, pos)

    def get_data_for_clipboard(self,format="text"):
        """
        Return data ready to be copied to the clipboard.

        This is an abstract method - concrete subclasses must override this.

        Sample implementation of get_data_for_clipboard() is:

        def get_data_for_clipboard(self,format="text"):
            first_selected = self.list_ctrl.GetFirstSelected()
            selected_item_count = self.list_ctrl.GetSelectedItemCount()
            text_for_clipboard = ""
            for i in range(first_selected,first_selected+selected_item_count):
                text_for_clipboard = "%s%s\n" % (text_for_clipboard, self.list_ctrl.GetItemText(i))
            return(text_for_clipboard)   
        """
        raise NotImplementedError

    def on_copy(self, evt):
        """
        """
        text_for_clipboard = self.get_data_for_clipboard()

        data = wx.TextDataObject()
        data.SetText(text_for_clipboard)
        if wx.TheClipboard.Open():
            wx.TheClipboard.SetData(data)
            wx.TheClipboard.Close()
        else:
            wx.MessageBox("Unable to copy to the clipboard", "Error")

    def on_minimize(self, evt):
        self.Iconize()
        #self.parent.Iconize()

    def on_close(self, evt):
        self.Close()
        #self.parent.Close()

    def on_exit(self, evt):
        try:
            self.Parent.Close()
        except AttributeError:
            self.Close()

        
if __name__ == "__main__":

    app = wx.App(redirect=False)
    copy_and_paste = CopyAndPaste()
    app.MainLoop()

> 
> Cheers,
> Chris
> 
> --
> Follow the path of the Iguana...
> http://rebertia.com
> 
> 


More information about the Python-list mailing list