I tried to think a little bit more systematically about the way
error conditions and messages are passed around in matplotlib.
1) There see to be several kinds of object:
- informational messages like the output of --verbose-debug-annoying
- error messages which the matlab interface passes to the
backends to have them displayed to the user
- error conditions reported by the backends to the caller
2) Typical scenarios:
a) A user tries to debug some installation problem by using
the --verbose-debug-annoying option or similar. This generates
potentially a lot of messages which should shown to the user.
Dumping them all to stdout or stderr seems fine here.
b) A script calls the matlab interface functions with invalid arguments.
The user should get an error message. In a GUI backend this error
message might pop up in a message window or similar.
c) A backend encounters an error condition, e.g. if it cannot open
the file, cannot load a font etc. If a GUI backend is active
the error message should be displayed by the GUI backend,
otherwise it should be printed to stderr or similar.
Is this so far correct?
3) Required or almost required properties of the implementation:
- the user should be able to customise how much information he
sees, e.g. by using the --verbose-* options
- The GUI backends should not be terminated if there is an error
while saving a file etc.
4) some ideas:
- The backends could return errors via python standard exceptions
without printing messages and such. This leads to simple code,
feels quite Pythonic, makes the backends more independent of the
error reporting policy and at the moment seems to be the only sane
solution to me.
- The backends should have a function which the matlab interface can
call to report errors to the user. This should pop up a dialog
etc. on GUI backends and just print the message to stderr for
non-GUI backends. It should not terminate the program.
Rationale for not calling verbose.report_error in this function:
the GUI backend reports the error on its own (dialog, status line,
etc), so it does not need to use verbose.report_error
additionally. When the PostScript backend is called from the GUI
backend, then the GUI backends error report function will be used,
what PostScript does does not matter. In all other cases
displaying the error message to stderr seems the only useful thing
to do (e.g. disabling it is not useful).
5) the verbose.report mechanism:
At the moment I am not sure how this fits in here. Maybe it should
only be used for non-error messages?
What is configurable here? The user can choose the amount of
messages he wants to see. Anything else?
6) Analysis of the three scenarios above:
a) --verbose-* output:
Here the flow of control is straightforward. At random places
there are calls to verbose.report. These are either discarded
or printed to stdout. This is currently done by the Verbose class.
b) invalid arguments
Again, this is simple: the matlab interface calls error_msg,
the GUI backend does something useful with the message.
c) backend error conditions
This seems to be the most complex scenario. I think this should
work as follows: the backend raises the standard Python exception,
e.g IOError. If the GUI backend calls the PostScript backend,
it should catch any exception from the PostScript backend call,
and tell the user about it.
If the user in a script calls e.g. "savefig('/fig1.eps')" and has
no write permission for the root directory, then he will get the
Python exception and can do with it whatever he likes.
I suggest the following.
- Change backend_template.py and all the other non-GUI backends to
def error_msg_ps(msg, *args):
Signal an error condition.
sys.stderr.write('Error: %s' % msg)
Maybe even make this function a class method of the
FigureManagerBase class? (the "error_msg = error_msg_..."
assignments seem hackish.)
- Change all callers of error_msg to terminate the program after the
call when appropriate
- Remove the verbose.report_error function and replace it with Python
What do you think?