Hi Guys, Thanks to Michele, Chris, Hrvoje et. al. who helped me trying to resolve the metaclass exception when a class has two parents problem. This post tries to unify all the metaclasses exception threads, in an attempt to reach a solution.
I've created a short demo script (metaclass_test01.py) that demonstrate the problem. Listings of metaclass_test01.py and CopyAndPaste are below and attached. Note: When line 8 in metaclass_test01.py is in effect (with line 7 commented out), the script runs normally. However, when line 7 is in effect (with line 8 commented out), viz.: $ cat -n metaclass_test01.py | head 1 #!/usr/bin/env python 2 3 import sys 4 import wx 5 import CopyAndPaste 6 7 class ListControl(wx.Frame, CopyAndPaste): 8 #class ListControl(wx.Frame): 9 def __init__(self, parent, id, title, list, max_list_width): 10 wx.Frame.__init__(self,parent,id,title,size=(-1,-1), style=wx.DEFAULT_FRAME_STYLE) I get the metaclass conflict exception: $ python metaclass_test01.py Traceback (most recent call last): File "metaclass_test01.py", line 7, 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 I hope that now the problem is demonstrated more clearly, and the gurus out there could point me in the right direction towards a solution. Bye, Ron. ________________________________ $ cat -n metaclass_test01.py 1 #!/usr/bin/env python 2 3 import sys 4 import wx 5 import CopyAndPaste 6 7 #class ListControl(wx.Frame, CopyAndPaste): 8 class ListControl(wx.Frame): 9 def __init__(self, parent, id, title, list, max_list_width): 10 wx.Frame.__init__(self,parent,id,title,size=(-1,-1), style=wx.DEFAULT_FRAME_STYLE) 11 self.list = list 12 self.list_ctrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT| wx.LC_NO_HEADER) 13 self.list_ctrl.InsertColumn(0, title) 14 for i,line_ in enumerate(list): 15 self.list_ctrl.InsertStringItem(i, line_) 16 self.list_ctrl.SetColumnWidth(0, max_list_width) 17 18 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list_ctrl) 19 20 self.Raise() 21 self.Show(True) 22 23 def OnItemSelected(self, evt): 24 item = evt.GetText() 25 max_list_width = 10 * len(item) 26 ListControl(self, -1, item, item, max_list_width) 27 28 if __name__ == "__main__": 29 list = [ "First Line", "Second Line", "Third Line"] 30 app = wx.App(redirect=False) 31 max_list_width = 6 * max([len(x) for x in list]) 32 ListControl(None, -1, "Parent Window", list, max_list_width) 33 app.MainLoop() ________________________________ $ cat -n CopyAndPaste.py 1 #!/usr/bin/env python 2 3 import wx 4 5 class CopyAndPaste(object): 6 7 def __init__(self): 8 pass 9 10 def set_copy_and_paste(self): 11 """ 12 Setting clipboard copy-and-pasting (only copying from the application to the 13 clipboard is supported). 14 The "menu" menu is hidden, and is only there to facilitate the acceleration table. 15 Both CTRL-C and CTRL-Ins are supported. 16 """ 17 menu = wx.Menu() 18 copy_ = menu.Append(-1, "&Copy\tCtrl-Ins") # Copy with accelerator 19 minimize_ = menu.Append(-1, "Minimize") # 20 close_ = menu.Append(-1, "Close window\tCtrl-W") # Close window 21 exit_ = menu.Append(-1, "E&xit application\tCtrl-X") # Close window 22 23 self.Bind(wx.EVT_MENU, self.on_copy, copy_) 24 self.Bind(wx.EVT_MENU, self.on_minimize, minimize_) 25 self.Bind(wx.EVT_MENU, self.on_close, close_) 26 self.Bind(wx.EVT_MENU, self.on_exit, exit_) 27 28 menuBar = wx.MenuBar() 29 self.SetMenuBar(menuBar) 30 31 acceltbl = wx.AcceleratorTable( [ 32 (wx.ACCEL_CTRL, ord('C'), copy_.GetId()), 33 (wx.ACCEL_CTRL, ord('W'), close_.GetId()), 34 (wx.ACCEL_CTRL, ord('X'), exit_.GetId()), 35 (wx.ACCEL_CTRL, ord('Q'), exit_.GetId()), 36 (wx.ACCEL_CTRL, wx.WXK_INSERT, copy_.GetId()), 37 (wx.ACCEL_CTRL, wx.WXK_NUMPAD_INSERT, copy_.GetId()), 38 ]) 39 self.SetAcceleratorTable(acceltbl) 40 41 # Setting popup menu 42 43 self.popupmenu = menu 44 self.Bind(wx.EVT_CONTEXT_MENU, self.on_show_popup) 45 46 def on_show_popup(self, evt): 47 pos = evt.GetPosition() 48 pos = self.list_ctrl.ScreenToClient(pos) 49 self.PopupMenu(self.popupmenu, pos) 50 51 def get_data_for_clipboard(self,format="text"): 52 """ 53 Return data ready to be copied to the clipboard. 54 55 This is an abstract method - concrete subclasses must override this. 56 57 Sample implementation of get_data_for_clipboard() is: 58 59 def get_data_for_clipboard(self,format="text"): 60 first_selected = self.list_ctrl.GetFirstSelected() 61 selected_item_count = self.list_ctrl.GetSelectedItemCount() 62 text_for_clipboard = "" 63 for i in range(first_selected,first_selected+selected_item_count): 64 text_for_clipboard = "%s%s\n" % (text_for_clipboard, self.list_ctrl.GetItemText(i)) 65 return(text_for_clipboard) 66 """ 67 raise NotImplementedError 68 69 def on_copy(self, evt): 70 """ 71 """ 72 text_for_clipboard = self.get_data_for_clipboard() 73 74 data = wx.TextDataObject() 75 data.SetText(text_for_clipboard) 76 if wx.TheClipboard.Open(): 77 wx.TheClipboard.SetData(data) 78 wx.TheClipboard.Close() 79 else: 80 wx.MessageBox("Unable to copy to the clipboard", "Error") 81 82 def on_minimize(self, evt): 83 self.Iconize() 84 85 def on_close(self, evt): 86 self.Close() 87 88 def on_exit(self, evt): 89 try: 90 self.Parent.Close() 91 except AttributeError: 92 self.Close() 93 94 95 if __name__ == "__main__": 96 97 app = wx.App(redirect=False) 98 copy_and_paste = CopyAndPaste() 99 app.MainLoop() 100 ________________________________
metaclass_test01.py
Description: metaclass_test01.py
CopyAndPaste.py
Description: CopyAndPaste.py
-- http://mail.python.org/mailman/listinfo/python-list