Reputation: 2883
So I'm interacting with a 3rd party library, which raises exceptions someti0mes, but it raises the same exception for basically everything (specifically suds.WebFault
. It's possible however to determine the exact type of exception it is from the data on the exception raised. I'm looking to abstract this exception into exceptions that subclass this type, ie:
from suds import WebFault
class MoreSpecificError(WebFault):
pass
I like the subclassing, because it won't break existing implementations that expect a WebFault
. The problem I'm having is passing the data already on the WebFault
into the MoreSpecificError
. What I would like to do is take the existing exception object and just 'turn it into' the subclass, without any changes or re-running __init__
. What I've done so far to accomplish this is something like:
from suds import WebFault
class MoreSpecificError(WebFault):
# You pass the old WebFault when instantiating this exception.
# Then it gets poofed into a MoreSpecificError type
def __new__(cls, internal_fault):
return internal_fault
# This is necessary to prevent the parent class' __init__ from being run
def __init__(self, internal_fault):
pass
Which 'works', but the need to put that __init__
that's just a pass
feels really gross to me. Not to mention some stuff doesn't like custom __new__
methods (read: deepcopy
, it's not a choice, the testing framework we use (lettuce) uses it and we're pretty far invested already).
I'm wondering if there's a better way to do this? I know the ideal way is just to raise the subclass initially, but I'd really rather not start working with a forked copy of this library. I'm really hoping there's some magic somewhere in Python I just don't know yet.
Upvotes: 4
Views: 567
Reputation: 251365
I think this is what you're asking for:
class MoreSpecificError(WebFault):
def __new__(self, old):
old.__class__ = MoreSpecificError
return old
However, it is risky for reasons described here. If all you are doing is catching the exception it should probably work, but no guarantees.
I still think it'd be better to just actually create a new exception object in the normal way. If you're worried about losing the information from the original exception, look in the documentation for that exception to see what information is documented to be part of its public API, and copy that information. Code that was relying on exception info that was not part of the original API is not something you need to support with your new API.
Upvotes: 1