Metaclass conflict TypeError exception: problem demonstration script


B

Barak, Ron

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
________________________________
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top