propagation of error messages in matplotlib

Hello,

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.

7) Conclusions:

  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
    exceptions etc.

What do you think?

Jochen

···

--
http://seehuhn.de/

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.

I agree with these ideas.

7) Conclusions:

  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)

I'd prefer to merge error_msg into the Verbose class, or just delete it.

  - Change all callers of error_msg to terminate the program after the
    call when appropriate

Agree

  - Remove the verbose.report_error function and replace it with Python
    exceptions etc.

Agree

What do you think?

At the moment we have error_msg(), the Verbose class and exceptions all
working in the same area and a bit of confusion as to which one does
what. I don't think we need all three.

I suggest
- using exceptions to handle errors that may terminate the program, and
allowing the matlab interface, GUI backends and user scripts to catch
these exceptions.
- using verbose for all reporting
- merging error_msg() into the Verbose class (with the GUI backends
possibly subclassing Verbose to provide a popup error dialog)

Steve

···

On Thu, 2004-11-18 at 18:05 +0000, Jochen Voss wrote: