python
2010-01-28
Another cause for buildout failures: system distributed Python
Always compile your own! One day I'll even remember that...
I've had a buildout bootstrap process failure, this time a weird one, perhaps I should document the bug and report it.
The latest Ubuntu version which I have installed (Lucid Lynx) comes with a package called python-pkg-resources, which packages pkg_resources, which used to be available only through the setuptools distribution. Buildout's bootstrap.py tries to guess if Setuptools or Distribute are installed by checking the availability of pkg_resources; by guessing wrong it all comes to a crash at the end.
I'm not very interested in debugging these types of problems anymore. Distribution/packaging tools should just work. I want to focus on my work, not debug the toolchain. No more corner cases or whatver. So I'm gonna compile separate Pythons in the future, especially when dealing with older Zope/Plones.
2008-10-08
RichText control with wxpython: saving, loading and converting from internal XML to HTML
I tend to be an angry caveman these days (see my previous post) and this doesn't lead to too much clear thinking. I've been dealing with the wx.richtext.RichTextCtrl for the past couple of days and I think I'm now close to finishing the tasks that I set myself to do with it. I'm trying to run a bunch of richtext controls on the same page, that would increase their size and show a toolbar when focused. My first problems came from the fact that all 5 of them flashed a caret which I couldn't hide. Trying to do ctrl.GetCaret().Hide() would result in a crash. After struggling with various possible solutions - none of which worked, I've realized that I should try the latest wxpython distribution, I was even decided to compile it manually. Fortunately, the wxwidgets project offers a repository for Ubuntu and sure enough, after I've upgraded, things started to work (I still needed to hide the caret for all the richtext controls and show it when they were focused, but that's no problem).
Now, unto the next tasks: saving and loading the content of these fields. I wanted to display the content in an HtmlWindow control, so converting the content to html was one thing I had to discover how to do. First step that I've tried, saving the html and loading it through the RichTextCtrl and its closely related buffers and handlers didn't work, so I've settled for a solution that involves one RichTextHTMLHandler and one RichTextXmlHandler. To help me understand how this thing works, I've created a clean example class where I could play with this thing. I hope it helps someone, as I haven't found too much info on this on the web (the Load/SaveStream methods are not even documented anywhere).
The toolbar class is taken from my project, created with wxGlade, while the frame class is created by me, manually (actually, this is the first frame that I have created by hand). To demonstrate the loading and saving, a variable is used to keep the content (self.content). Change the text, add some formatting, hit Save and then Load. This will take the text that was saved from the richtext control (in xml format), load it in a buffer and convert it to html which is then displayed in the HtmlWindow. I've only tried this on Linux, hope it works on Windows too. Oh, and you need to supply your own icons if you want to try the code (hint: I've used /usr/share/icons/gnome/32x32/actions as source of my icons.
#!/usr/bin/env python
from StringIO import StringIO
import wx
import wx.html
import wx.richtext
class TextFormatToolBar(wx.ToolBar):
def __init__(self, *args, **kwds):
self.text_ctrl = kwds.pop('text_ctrl')
kwds["style"] = wx.TB_FLAT|wx.TB_3DBUTTONS
wx.ToolBar.__init__(self, *args, **kwds)
self.AddLabelTool(wx.ID_CUT, "Cut", wx.Bitmap("edit-cut.png", wx.BITMAP_TYPE_ANY),
wx.NullBitmap, wx.ITEM_NORMAL, "Cut selection", "")
self.AddLabelTool(wx.ID_COPY, "Copy", wx.Bitmap("edit-copy.png", wx.BITMAP_TYPE_ANY),
wx.NullBitmap, wx.ITEM_NORMAL, "", "")
self.AddLabelTool(wx.ID_PASTE, "Paste", wx.Bitmap("edit-paste.png", wx.BITMAP_TYPE_ANY),
wx.NullBitmap, wx.ITEM_NORMAL, "", "")
self.AddSeparator()
self.AddLabelTool(wx.ID_UNDO, "Undo", wx.Bitmap("edit-undo.png", wx.BITMAP_TYPE_ANY),
wx.NullBitmap, wx.ITEM_NORMAL, "", "")
self.AddLabelTool(wx.ID_REDO, "Redo", wx.Bitmap("edit-redo.png", wx.BITMAP_TYPE_ANY),
wx.NullBitmap, wx.ITEM_NORMAL, "", "")
self.AddSeparator()
self.AddLabelTool(wx.ID_BOLD, "Bold", wx.Bitmap("format-text-bold.png", wx.BITMAP_TYPE_ANY),
wx.NullBitmap, wx.ITEM_NORMAL, "", "")
self.AddLabelTool(wx.ID_ITALIC, "Italic", wx.Bitmap("format-text-italic.png", wx.BITMAP_TYPE_ANY),
wx.NullBitmap, wx.ITEM_NORMAL, "", "")
self.AddLabelTool(wx.ID_UNDERLINE, "Underline", wx.Bitmap("format-text-underline.png",
wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "", "")
self.Realize()
self.Bind(wx.EVT_TOOL, self.handle_bold, id=wx.ID_BOLD)
self.Bind(wx.EVT_TOOL, self.handle_italic, id=wx.ID_ITALIC)
self.Bind(wx.EVT_TOOL, self.handle_underline, id=wx.ID_UNDERLINE)
self.Bind(wx.EVT_TOOL, self.handle_paste, id=wx.ID_PASTE)
self.Bind(wx.EVT_TOOL, self.handle_copy, id=wx.ID_COPY)
self.Bind(wx.EVT_TOOL, self.handle_cut, id=wx.ID_CUT)
self.Bind(wx.EVT_TOOL, self.handle_undo, id=wx.ID_UNDO)
self.Bind(wx.EVT_TOOL, self.handle_redo, id=wx.ID_REDO)
def handle_bold(self, event):
self.text_ctrl.ApplyBoldToSelection()
def handle_italic(self, event):
self.text_ctrl.ApplyItalicToSelection()
def handle_underline(self, event):
self.text_ctrl.ApplyUnderlineToSelection()
def handle_paste(self, event):
self.text_ctrl.Paste()
def handle_copy(self, event):
self.text_ctrl.Copy()
def handle_cut(self, event):
self.text_ctrl.Cut()
def handle_undo(self, event):
self.text_ctrl.Undo()
def handle_redo(self, event):
self.text_ctrl.Redo()
class TopFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.Freeze()
sizer = wx.BoxSizer(wx.VERTICAL)
rt = wx.richtext.RichTextCtrl(self, -1)
toolbar = TextFormatToolBar(self, text_ctrl=rt)
rt.SetMinSize((300,200))
htmlwindow = wx.html.HtmlWindow(self)
htmlwindow.SetMinSize((300,200))
save_button = wx.Button(self, label="Save")
load_button = wx.Button(self, label="Load")
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
btn_sizer.Add(load_button, 0, wx.EXPAND|wx.ALL, 6)
btn_sizer.Add(save_button, 0, wx.EXPAND|wx.ALL, 6)
self.Bind(wx.EVT_BUTTON, self.handle_save, save_button)
self.Bind(wx.EVT_BUTTON, self.handle_load, load_button)
sizer.Add(toolbar, 0, wx.EXPAND|wx.ALL, 6)
sizer.Add(rt, 1, wx.EXPAND|wx.ALL, 6)
sizer.Add(htmlwindow, 1, wx.EXPAND|wx.ALL, 6)
sizer.Add(btn_sizer)
self.SetSizer(sizer)
sizer.Fit(self)
self.Thaw()
self.rt = rt
self.htmlwindow = htmlwindow
def handle_save(self, event):
out = StringIO()
handler = wx.richtext.RichTextXMLHandler()
buffer = self.rt.GetBuffer()
handler.SaveStream(buffer, out)
out.seek(0)
self.content = out.read()
def handle_load(self, event):
out = StringIO()
handler = wx.richtext.RichTextXMLHandler()
buffer = self.rt.GetBuffer()
buffer.AddHandler(handler)
out.write(self.content)
out.seek(0)
handler.LoadStream(buffer, out)
self.rt.Refresh()
cio = StringIO()
cio.write(self.content)
cio.seek(0)
cout = StringIO()
xmlhandler = wx.richtext.RichTextXMLHandler()
htmlhandler = wx.richtext.RichTextHTMLHandler()
newbuff = wx.richtext.RichTextBuffer()
newbuff.AddHandler(htmlhandler)
xmlhandler.LoadStream(newbuff, cio) #load xml into buffer
newbuff.SaveStream(cout, wx.richtext.RICHTEXT_TYPE_HTML)
cout.seek(0)
self.htmlwindow.SetPage(cout.read())
class MyApp(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
frame = TopFrame(None, - 1, "")
self.SetTopWindow(frame)
frame.Show()
return 1
def start():
app = MyApp(0)
app.MainLoop()
if __name__ == "__main__":
start()
2008-09-14
Workingenv, setuptools and svn 1.5 redux
I'm back to dealing with the incompatibility between setuptools and svn 1.5 which I have installed. Last time I've solved the problem by doing a svn checkout of http://svn.python.org/projects/sandbox/branches/setuptools-0.6/ and running sudo python setup.py install. Now I'm trying to do setup a virtualenv to play with repoze.catalog and I'm hitting the same problem. Of course, virtualenv comes with a hardcoded setuptools package and so it will setup a "broken" setuptools in the virtual environment. The solution is of course the same, adapted to use the virtualenv python script:
virtualenv myenv cd myenv svn co http://svn.python.org/projects/sandbox/branches/setuptools-0.6/ setuptools cd setuptools ../bin/python setup.py install
This will upgrade the easy_install script to use the new setuptools library