Hi Chris,
From: Chris Rebert [mailto:clp2@rebertia.com]
Sent: Sunday, February 22, 2009 11:48
To: Barak, Ron
Cc: python-list@python.org; wxpython-users@lists.wxwidgets.org
Subject: Re: "metaclass conflict" error: where is noconflict ?
> Hi Chris,
>
>> From: chris@rebertia.com [
> mailto:chris@rebertia.com] On
>> Behalf Of Chris Rebert
>> Sent: Thursday, February 19, 2009 22:58
>> To: Barak, Ron
>> Cc: python-list@python.org; wxpython-users@lists.wxwidgets.org
>> Subject: Re: "metaclass conflict" error: where is noconflict ?
>>
>> > 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()
···
-----Original Message-----
On Sun, Feb 22, 2009 at 1:37 AM, Barak, Ron <Ron.Barak@lsi.com> wrote:
>> -----Original Message-----
>> On Thu, Feb 19, 2009 at 5:01 AM, Barak, Ron > <Ron.Barak@lsi.com> wrote:
Cheers,
Chris
--
Follow the path of the Iguana...
http://rebertia.com