propagation of error messages in matplotlib

I was thinking of something like:

    > class VerboseGTK(Verbose): def report_error(self, s):
    > dialog = gtk.MessageDialog( parent = None, type =
    > gtk.MESSAGE_ERROR, buttons = gtk.BUTTONS_OK, message_format
    > = msg) dialog.run() dialog.destroy()

    > So that the matlab interface can call
    > verbose.report_error() and for image backends it writes to
    > stdout and for GUI backends it pops up a message dialog.

    > You can hook a GTK dialog into unhandled Python exceptions
    > with: import sys

    > def exception_handler(type, value, tb): """Handle uncaught
    > exceptions""" error_msg_gtk(value)

    > sys.excepthook = exception_handler

    > (I've added this to backend_gtk.py in cvs if you want to
    > try it out)

As for report_error, subclassing Verbose, or using figure manager for
this as Jochen has suggested, are both workable solutions, but what
does it ultimately buy us? I am inclined to the logically cleaner
solution of doing all error handling with exceptions, using a hook
like you've provided for GUIs.

The only lingering advantage I see for a report_error call w/o an
exception being raised is it presents a cleaner error message, which
is nice for newbies. I have a python 3000-esque design philosophy for
matplotlib -- I want it to be accessible to newbies. And a simple
message "function blah expects 1 or 2 arguments" is much more likely
to be read and parsed by a newbie, who in my experience will disregard
a traceback simply because it often appears unreadable, until you are
trained to read from the bottom up, which is counter intuitive to
some.

Are there other advantages to report_error that I'm missing, and if
not, does the readability issue justify circumventing the default
exception handling mechanism? My inclination is that it doesn't.

    > But you still need to decide how to handle the exceptions -
    > with some you need to terminate the program, with others
    > its safe to continue. It may mean you end up writing a
    > complicated generic exception handler that tries to handle
    > every possible exception. In that case handling exceptions
    > individually, the usual way might be better, possibly using
    > the sys.excepthook to handle the remaining uncaught
    > exceptions, or using it when you want to terminate the
    > program and want to popup a message saying "Fatal error..."

I grepped for all the current uses of report error (included below) --
on quick inspection none of these appear fatal for a GUI. I think
simply informing the user of the error may suffice. Can you provide
an example of where we may need to exit (and would it suffice for the
raiser to simply raise a SystemExit for this case?)

JDH

'Error: %s'%msg
'Unable to allocate color %1.3f, %1.3f, %1.3f; using nearest neighbor' % rgb
'Error: %s'% msg
'Error: %s' % msg
'Could not load font file "%s"'%fname
'Error: %s'% msg
'Could not load filename for text "%s"'%fname
msg
'Could not find bitmap file "%s"; dying'%bmpFilename
'backend_gtk could not import mathtext (build with ft2font')
'Error: %s' % exc
'The GTK backend cannot draw text at a %i degree angle, try GtkAgg instead' % angle
'mathtext not supported: %s' % exc
"Could not renderer vertical text", s
"cairo.numpy module required for draw_image(")
'Mathtext not implemented yet'
'Unrecognized cap style. Found %s' % cs
'Unrecognized join style. Found %s' % js
"%s: %s" % (exc.filename, exc.strerror)
'Format "%s" is not supported.\nSupported formats: %s.' %
./__init__.py: def report_error(self, s:
'Could not find .matplotlibrc; using defaults'
message
'Illegal line #%d\n\t%s\n\tin file "%s"' % (cnt, line, fname)
'%s is deprecated in .matplotlibrc - use %s instead.' % (key, alt)
'Bad key "%s" on line %d in %s' % (key, cnt, fname)
'Bad val "%s" on line #%d\n\t"%s"\n\tin file "%s"\n\t%s' % (val, cnt, line, fname, msg)
'unrecognized backend %s.\n' % arg +\
./backend_bases.py: verbose.report_error('Error: %s'% msg
"ColormapJet deprecated, please use cm.jet instead"
"Grayscale deprecated, please use cm.gray instead"
'urlopen( failure\n' + url + '\n' + exc.strerror[1])
"Could not open font file %s"%fpath
"Could not open font file %s"%fpath
msg % name
'Could not match %s, %s, %s. Returning %s' % (name, style, variant, self.defaultFont)
'Unrecognized location %s. Falling back on upper right; valid locations are\n%s\t' %(loc, '\n\t'.join(self.codes.keys()))
'Unrecognized line style %s' %( linestyle, type(linestyle))
'Unrecognized marker style %s'%( marker, type(marker))
'unrecognized symbol "%s"' % sym
'unrecognized symbol "%s, %d"' % (sym, num)
'Coherence is calculated by averaging over NFFT length segments. Your signal is too short for your choice of NFFT'
'Dimension error'
'Second argument not permitted for matrices'
__doc__
'Unrecognized location %s. Falling back on bottom; valid locations are\n%s\t' %(loc, '\n\t'.join(self.codes.keys()))
'AutoLocator illegal dataInterval range %s; returning NullLocator'%d
'Unrecognized location %s. Falling back on upper right; valid locations are\n%s\t' %(loc, '\n\t'.join(self.codes.keys()))

···

Steve

    > -------------------------------------------------------
    > This SF.Net email is sponsored by: InterSystems CACHE FREE
    > OODBMS DOWNLOAD - A multidimensional database that combines
    > robust object and relational technologies, making it a
    > perfect match for Java, C++,COM, XML, ODBC and
    > JDBC. www.intersystems.com/match8
    > _______________________________________________
    > Matplotlib-devel mailing list
    > Matplotlib-devel@lists.sourceforge.net
    > https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

As for report_error, subclassing Verbose, or using figure manager for
this as Jochen has suggested, are both workable solutions, but what
does it ultimately buy us? I am inclined to the logically cleaner
solution of doing all error handling with exceptions, using a hook
like you've provided for GUIs.

By subclassing Verbose you group all the functions that display messages
to the user together into one class.
I may have misunderstood some of the discussion - I agree with doing all
error handling with exceptions, but when you catch the exception in a
GUI I'm assuming you still want to popup a message to inform the user.
Are you describing using exceptions and tracebacks without any error
messages for GUI backends? I don't think you can assume a GUI backend
user will see a traceback since the terminal window may be obscured,
iconified or even closed.

I grepped for all the current uses of report error (included below) --
on quick inspection none of these appear fatal for a GUI. I think
simply informing the user of the error may suffice. Can you provide
an example of where we may need to exit (and would it suffice for the
raiser to simply raise a SystemExit for this case?)

It does look like they are all non-fatal. I guess the fatal ones are the
ones that matplotlib does not anticipate or catch, thinks like faulty
installations, missing libraries etc. At the moment these would cause
matplotlib to terminate but if we add a default exception handler we
will start catching these also.
We could have a policy for matplotlib to catch all exceptions and always
attempt to continue, and if it becomes unusable its up to the user to
close the window. Also we could recognise some situations (if there are
any) where we need to terminate, so we raise SystemExit and set the
default exception handler to terminate on SystemExit and continue on all
other cases.

Steve

···

On Sat, 2004-11-20 at 17:26 -0600, John Hunter wrote: