Hey all,
This isn't so much a question as a heads up...

After using python for a few years (mainly doing blender scripts and random console/command-line apps and tools) I've recently started looking into doing some GUI based stuff using wxPython.

I've had a look at a few of the examples in the "Starting wxPython" thread at the top of the page, but I've hit an error while trying to run one of the wx.lib.plot examples..(Vegaseat's example on page 10 of the thread)
(oh yeah, I'm using Python 2.6 with version 2.8 of wx BTW!)

Anyway, in the example code, the line of code which saves the graph to an image:

plot_canvas.SaveFile(fileName='trig1.jpg')

causes the following error to be thrown by the interpreter:

Traceback (most recent call last):
File "C:/Documents and Settings/Jason/Desktop/wxPythonStuff/usingPlot2.py", line 60, in <module>
MyFrame(None, mytitle, (width, height)).Show()
File "C:/Documents and Settings/Jason/Desktop/wxPythonStuff/usingPlot2.py", line 53, in __init__
plot_canvas.SaveFile(fileName='trig1.jpg')
File "C:\Python26\Lib\site-packages\wx-2.8-msw-unicode\wx\lib\plot.py", line 642, in SaveFile
dlg1.Destroy()
AttributeError: 'NoneType' object has no attribute 'Destroy'

Now, this isn't a bug in Vegaseat's code. It's actually a bug in plot.py in the wx library.
I've taken a look at the code in the SaveFile() function in plot.py (in the wx library) and the problem is this block of code:

extensions = {
            "bmp": wx.BITMAP_TYPE_BMP,       # Save a Windows bitmap file.
            "xbm": wx.BITMAP_TYPE_XBM,       # Save an X bitmap file.
            "xpm": wx.BITMAP_TYPE_XPM,       # Save an XPM bitmap file.
            "jpg": wx.BITMAP_TYPE_JPEG,      # Save a JPG file.
            "png": wx.BITMAP_TYPE_PNG,       # Save a PNG file.
            }

       fType = _string.lower(fileName[-3:])
        dlg1 = None
        while fType not in extensions:

            if dlg1:                   # FileDialog exists: Check for extension
                dlg2 = wx.MessageDialog(self, 'File name extension\n'
                'must be one of\nbmp, xbm, xpm, png, or jpg',
                'File Name Error', wx.OK | wx.ICON_ERROR)
                try:
                    dlg2.ShowModal()
                finally:
                    dlg2.Destroy()
            else:                      # FileDialog doesn't exist: just check one
                dlg1 = wx.FileDialog(
                    self, 
                    "Choose a file with extension bmp, gif, xbm, xpm, png, or jpg", ".", "",
                    "BMP files (*.bmp)|*.bmp|XBM files (*.xbm)|*.xbm|XPM file (*.xpm)|*.xpm|PNG files (*.png)|*.png|JPG files (*.jpg)|*.jpg",
                    wx.SAVE|wx.OVERWRITE_PROMPT
                    )

            if dlg1.ShowModal() == wx.ID_OK:
                fileName = dlg1.GetPath()
                fType = _string.lower(fileName[-3:])
            else:                      # exit without saving
                dlg1.Destroy()
                return False

        dlg1.Destroy()

Note: The very last line of code in the above excerpt is line 642 i.e. the line which the interpreter is complaining about...The call to dlg1.Destroy()

I've noticed if you don't pass a filename into the SaveFile() function, or you pass a filename with an invalid extension, the while loop is entered and the file selection dialog will pop up and blah blah blah..basically the code will execute properly and the call to dlg1.Destroy() (after the while loop, at line 642) will succeed.

But if you pass a valid filename, you get the crash because line 642 is essentially attempting to call something (Destroy()) which isn't there. So looking at the code, what's happening in this case is:
1. dlg1 is initially set to None
2. because you've passed a filename with a valid extension, the while loop is skipped, so the dialog never gets instantiated (because it doesn't need to be)
3. The first line of code after the while loop is the call to dlg1.Destroy(). But because dlg1 is still set to None and None doesn't have a Destroy() function, the interpreter is flagging an error!

To get around the problem I've altered line 642 so that dlg1 only gets destroyed if it's not "None". See code below:

if dlg1:
            dlg1.Destroy()

I've saved the changes and recompiled my version of plot.py to bytecode and the bug appears to be fixed. Now Vegaseat's little example runs like a dream (BTW - Great job to everybody who contributes to the starting wxPython thread..There are some excellent examples on there. All of which have been a great help so far!)

Anyway, I just thought it might be worth mentioning the bug here in case anybody else comes across this problem. Googling it didn't yield any results for me, so I'm guessing I must be one of the first!

I haven't reported it to the wxpython.org people yet as I've been unable to get onto their site...network timeouts and suchthelike, they must be having problems with their servers or something!

Anyways..that's both the bug and the fix all in one post.
I hope it's of some use!
Cheers for now,
Jas.

OK, I know it's been a while since I originally posted this and I've marked the thread as solved, but this is a valid bug in wxPython....So here's a quick update!

I finally managed to get onto the wxpython.org site to report the bug today. (All of the wxpython/wxwidgets websites were down when I originally discovered this bug back in June and I haven't tried any of their websites for a while, so I completely forgot about reporting it until today!)

Anyway, I've taken a quick look at the current python source code in their svn repository and the issue is still there, so nobody else has reported/fixed it yet!

My bug report ticket number is #11255 (http://trac.wxwidgets.org/ticket/11255)

Hopefully the bug will be accepted and fixed for a future release of wxPython, but in the meantime if anybody has problems with this bug then by all means use the fix I documented in my original post.

I'll keep an eye on this and keep you all posted!
Cheers for now,
Jas.

commented: thanks for the bug fix! +9
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.