[Python-3000] How far to go with cleaning up exceptions (original) (raw)
Brett Cannon brett at python.org
Thu Mar 1 18:09:26 CET 2007
- Previous message: [Python-3000] Draft PEP for New IO system
- Next message: [Python-3000] How far to go with cleaning up exceptions
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
I spent my sprint time cleaning up exceptions for Py3K and Guido suggested I run some things by the group to make sure they don't make transitioning from 2.6 too difficult. After adding the proper restrictions in terms of what can and cannot be raised or caught, I began cleaning up BaseException's API per PEP 352.
First thing I did was remove slicing. That wasn't too bad since I just got exceptions about the lack of getitem and went to the affected line and tossed in '.args' between the index and the exception. Not sure if 2to3 can handle this as it would need to realize when an exception is within scope and then insert '.args' when it is be indexed on.
The next thing I did was strip out the use of '.args' and make BaseException take a single argument that gets assigned to 'message'. The fruits of this labour are in the p3yk_no_args_on_exc branch. This one turned out to be a pain in the rear.
Probably the biggest headache were the built-in exceptions themselves and various exceptions specified by extension modules. Many of the built-in modules assumed 'args' would be there and so would pull from them as needed instead of assigning None to their various attributes. It also required implementing several reduce methods as BaseException's just return 'args' which kept things simple. Plus their constructors had to be made to use BaseException's more restrictive constructor signature.
For the extension modules, though, the biggest pain was the fact that most of them use PyErr_NewException() to create their exception objects. That provides no easy way of dealing with the more restrictive constructor on BaseException. For bsddb.DBError I just made it take one argument and forced all calls to pass in a tuple. For socket.error I defined the exception in Python and used a trick _bsddb.c uses so that the init for socket.error stuck any second argument on to the 'errno' attribute.
In other words the more restrictive construtor is going to be what causes the most pain. Exceptions that expect more than one argument are going to need to be rewritten so that if they get more than one argument they call BaseException.init with only one and store away the rest in some other attribute. This kind of sucks at the C level, especially when most defined there just use PyErr_NewException(). Then the various accesses that would have gone to 'args' would need to be changed to access the specific attribute.
For solving these issues, there a couple possibilities. For those exceptions that use PyErr_NewException() there could be a PyErr_NewExceptionEx() that takes an init function for thew new exception. As for transforming the 'args' accesses to something else, I guess 2to3 could automatically do 'args[0]' accesses to 'message', but anything else will need to be changed by hand.
Now, for the question: is all of this worth it? If this happens exceptions will have a much nicer interface. By default you will have just 'message'. it will also force exceptions to explicitly set attributes instead of using the position within 'args' to get to a specific piece of information. But obviously there are transition pains in doing this. If you have an opinion on this please speak up.
-Brett
- Previous message: [Python-3000] Draft PEP for New IO system
- Next message: [Python-3000] How far to go with cleaning up exceptions
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]