Metaclass conflict TypeError exception: problem demonstration script

Barak, Ron Ron.Barak at lsi.com
Mon Feb 23 10:32:52 CET 2009


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
________________________________
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20090223/e8b581e9/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: metaclass_test01.py
Type: application/octet-stream
Size: 1148 bytes
Desc: metaclass_test01.py
URL: <http://mail.python.org/pipermail/python-list/attachments/20090223/e8b581e9/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CopyAndPaste.py
Type: application/octet-stream
Size: 3288 bytes
Desc: CopyAndPaste.py
URL: <http://mail.python.org/pipermail/python-list/attachments/20090223/e8b581e9/attachment-0001.obj>


More information about the Python-list mailing list