On Sat, 2006-08-12 at 16:01 +1000, Edward d'Auvergne wrote:
I've implemented most of a new relax error/warning system that has been talked about in this and a few other threads. The changes are located within the 1.2 line (the new system can sit side-by-side with the old RelaxError system without affected program execution). The way these new RelaxErrors and RelaxWarnings are called is by typing something like: relax> RelaxBadError('Hello') This is because RelaxBadError (a test error) is a class instance and I've created a '__call__()' function for these simple, non-exception objects. Are there any features of the old system missing in the new that you would like added? Can you see useful new ways that this mailable framework can be extended? Or can you see disadvantages with this approach?
I agree that this approach gives us a great deal of flexibility when it comes to how errors and warnings will behave. I'm a bit concerned about some of the features of Python exceptions that we loose by going this way, however. I'm a big fan of the try/except style of error managment that Python encourages, and its not at all clear how we might impliment that easily in the new framework. This means that while its easy to generate classes of error with specific and complex behaviour, its not easy to override that behaviour in a specific context. Ultimately I guess I'm looking at the distinction between an error (or warning) and an exception. An error or warning means something has gone wrong that the user needs to know about. An exception is just another programing tool for controling how our programs respond to events. As an example, consider the way python iterator objects work: they iterate through a series of objects, returning them one a time. When they run out of objects, they raise a StopIteration exception. Clearly this exception does not indicate an error that the user needs to know about, or even an unexpected event (most iterators will stop eventually). Instead code using iterators needs to use an appropriate try/except construct to catch the StopIteration and respond appropriately. The nice thing about exception behaviour in this context is that this try/except can be at any level in the code - it doesn't need to sit in the same function that directly interacts with the iterator. The message that the iterator has run out of objects gets passed to the appropriate place without any extra code from us. Thus we get much simpler, clearer code. This issue that needs to be dealt with, then, is how to have the sort of error handling at the users end that we want (errors and warnings that can be up- and down-graded, rich debugging behaviour, etc) as well as having good exception handling at the code level, for both builtin Python exceptions and specific relax exceptions. In addition to the options we've already considered, there is the possibility of coding appropriately rich behaviour into a replacement function for sys.excepthook. This is the function that is called when an exception is not caught by an appropriate handler. It's default behaviour is to print the traceback and display the error. It is passed both the exception class and the specific instance that was raised, as well as the traceback object. This should be enough to get some quite rich behaviour without too much hacking, I think. Chris