OOF2: The Manual

Name

ErrError — Classes and functions for handling exceptions

Synopses

C++ Synopsis

#include "common/ooferror.h" 
class ErrError {
  virtual std::string pythonequiv();
  virtual std::string message();
}
class template <class E> ErrErrorBase: , public ErrError {
}

The following subclasses are all derived from the ErrErrorBase template, but the base class has been omitted here for clarity.

class ErrProgrammingError {
  ErrProgrammingError(const std::string& filename,
                      int line);

  ErrProgrammingError(const std::string& message,
                      const std::string& filename,
                      int line);

}
class ErrIndexError {
  ErrIndexError(const std::string& message);
}
class ErrUserError {
  ErrUserError(const std::string& message);
}
class ErrSetupError {
  ErrSetupError(const std::string& message);
}

Python Synopsis

from oof2.SWIG.common.ooferror import ErrProgrammingError
from oof2.SWIG.common.ooferror import ErrIndexError
from oof2.SWIG.common.ooferror import ErrUserError
from oof2.SWIG.common.ooferror import ErrSetupError 
class ErrProgrammingError:
  def __init__(self, message, filename, line)
class ErrPyProgrammingError:
  def __init__(self, message)
class ErrIndexError:
  def __init__(self, message)
class ErrUserError:
  def __init__(self, message)
class ErrSetupError:
  def __init__(self, message)
registerErrorClass(exc_class)

Source Files

  • SRC/common/ooferror.h
  • SRC/common/ooferror.C
  • SRC/common/ooferror.swg
  • SRC/common/ooferror.spy

Discussion

OOF2 predefines a number of useful exception classes for handling errors, and includes a mechanism for adding new classes. The mechanism is non-trivial because exceptions have to be able to pass back and forth between C++ and Python.

Predefined Exception Classes

The following classes are all declared in common/ooferror.h. The Python versions can be imported from oof2.SWIG.common.ooferror.

class ErrProgrammingError

This exception indicates that an internal consistency check failed. Its constructor arguments are a message, the name of the source file and the line number of the code that raised the exception. In C++, it's easily called like this:

throw ErrProgrammingError("Your message here", __FILE__, __LINE__);

In Python, it's easier to use ErrPyProgrammingError instead.

Programming errors are usually fatal to the program.

class ErrPyProgrammingError

ErrPyProgrammingError is a Python class derived from ErrProgrammingError. It automatically sets the filename and line number parameters by examining the Python traceback stack. It should be raised whenever an internal inconsistency is detected in Python code.

Python programming errors are usually fatal to the program.

class ErrIndexError

ErrIndexError indicates that an array index is out of range.

class ErrUserError

ErrUserError indicates that the user did something wrong. The GUI should (and does) prevent most user errors, but they can still occur if the user loads a malformed script. User errors should not be fatal (either to the user or to the program).

class ErrSetupError

An ErrSetupError is a particular variety of user error indicating that the finite element system being solved hasn't been defined properly.

Adding New Exception Classes

In order for exceptions to propagate properly from C++ to Python and back, all OOF2 exception classes must be derived from ErrErrorBase in the following way:

class MyError : public ErrErrorBase<MyError> {
public:
  MyError();
  virtual std::string pythonequiv() const;
  virtual std::string message() const;
}; 

Note that the template parameter is the name of the subclass!

The function pythonequiv() must return a string that, when evaluated by the Python interpreter, will create the equivalent exception in Python. The MyError example above would define it like this:

std::string MyError::pythonequiv() const {
  return "NewError()";
} 

The function message should return a string indicating what caused the exception.

All new exception subclasses must be swigged, and the Python function registerErrorClass must be called with the swigged class as its argument. (Exception classes declared in SRC/common/ooferror.h and swigged in SRC/common/ooferror.swg are exempt from this requirement.) For example, the MyError class above would have a swig file myerror.swg like this:

%module myerror
%include "common/typemaps.swg"
%extern "common/ooferror.swg"
%{
#include "myerror.h"
%}

class MyError : public ErrError {
public:
  MyError();
  %addmethods {
    string __repr__() {
      return self->message();
    }
  }
};

%pragma(python) include="myerror.spy" 

and myerror.spy would contain:

from oof2.SWIG.common import ooferror
ooferror.registerErrorClass(MyError) 

See Section 7.6 for more on writing swig input files.

For more examples of OOF2 exception classes, see SRC/engine/ooferror*. (The exceptions defined there have very specific internal uses and shouldn't be used in OOF2 extensions, so they aren't discussed here.) Note that it's not possible to derive new exceptions directly from ErrUserError or ErrProgrammingError because the template parameter would be wrong. New exceptions must be derived from the intermediate classes ErrUserErrorBase or ErrProgrammingErrorBase, or directly from ErrErrorBase.