#SQLObject ErrorMessage class.
class ErrorMessage(str):
def __new__(cls, e, append_msg=''):
obj = str.__new__(cls, e[1] + append_msg)
obj.code = int(e[0])
obj.module = e.__module__
obj.exception = e.__class__.__name__
return obj
The question that now arises is how do we handle this? In this case, we have exceptions being raised by other exceptions. The ErrorMessage class could simply be fixed by adding exception handling for IndexError exceptions. However, now that the error is fixed, how do we ship this fix along with our application? ECP will currently install SQLObject from pypi. One solution would be to build our own SQLObject package and point the ECP setup to a custom repository that contains this patched-version. One problem I find with this solution is that it could potentially introduce a myriad of other deployment problems.
Another solution is to perform the patch inside of ECP. In this scenario, we don't actually patch the SQLObject package. The SQLObject package would remain as is on the system so that other Python applications using SQLObject wouldn't experience any side-effects as a result of ECP providing a different SQLObject. And this is the approach we are taking. Once ECP has started up, we import the mysqlconnection module and replace ErrorMessage entirely. Here is how it is done.
#ECP approach to patching SQLObject.
from sqlobject.mysql import mysqlconnection
class NewErrorMessage(str):
def __new__(cls, e):
if not isinstance(e, Exception):
e = e.args[0]
else:
try:
dummy = e[1]
except IndexError:
e = e.args[0]
obj = str.__new__(cls, e[1])
obj.code = int(e[0])
obj.module = e.__module__
obj.exception = e.__class__.__name__
return obj
mysqlconnection.ErrorMessage = NewErrorMessage
As an afterthought, I'm wondering what led SQLObject to this issue to begin with. That is, how can a class so tightly associated with exception handling be the culprit for bigger problems such as this one? Is it that this class is taking on too many responsibilities and thus adding to the risk of raising unforeseen exceptions itself? I wouldn't think so. The ErrorMessage.__new__() method isn't exactly overwhelmed with code. Besides, the exceptions defined in ECP do a fair amount of work when instantiated (including interacting with SQLObject). When the ECP exceptions are raised, they never raise inadvertent exceptions.
Perhaps special care needs to be taken when defining exceptions that do any work. If nothing else, SQLObject provides us with a lesson learned. As developers, we need to be absolutely certain that any given exception we have defined ourselves can be raised under any circumstances. They cannot fail. It would obviously be nice of no code failed at all throughout an entire application. That is obviously not a reality though. The code will fail at some point and having stable exception to deal with will make your code one step closer to being fail safe.
No comments :
Post a Comment