Skip to content

Commit

Permalink
Add a format_message method to the Exceptions
Browse files Browse the repository at this point in the history
This patch adds a format_message method to the NovaException class that
will almost always do what a user wants, when they want to print out the
message of the exception.

Exceptions that are received through RPC are turned into an actual
exception classes by the deserialize_remote_exception function of the
nova.openstack.common.rpc.common module. This function then overrides
__str__ and __unicode__ methods of a new class to print the whole trace.
We still want to preserve this functionality (for logging) but do not
want to leak the trace back to the user in the HTTP response.

Based on the above, This patch attempts to establish a convention that
states: if you need to get the message of a NovaException subclass -
always use the format_message method. Only use str(e) or unicode(e) when
you suspect that they were overriden.

Initially this was attempted through adding a custom metaclass to the
NovaException class so that format_message cannot be overridden in
subclasses, however due to a bug in testtools - many tests were failing.
A patch was proposed to testtols to remedy this
(testing-cabal/testtools#34) however until it is
merged, we cannot use metaclasses with our exception classes as they
cause tests to fail.

Change-Id: I0a399b9ab3227bad644b031c9b689fe0ce64586e
  • Loading branch information
djipko committed Mar 27, 2013
1 parent e9912c6 commit b936df8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
6 changes: 6 additions & 0 deletions nova/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ def __init__(self, message=None, **kwargs):

super(NovaException, self).__init__(message)

def format_message(self):
if self.__class__.__name__.endswith('_Remote'):
return self.args[0]
else:
return unicode(self)


class EC2APIError(NovaException):
message = _("Unknown")
Expand Down
29 changes: 29 additions & 0 deletions nova/tests/test_exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,32 @@ def test_cleanse_dict(self):

kwargs = {}
self.assertEquals(exception._cleanse_dict(kwargs), {})

def test_format_message_local(self):
class FakeNovaException(exception.NovaException):
message = "some message"

exc = FakeNovaException()
self.assertEquals(unicode(exc), exc.format_message())

def test_format_message_remote(self):
class FakeNovaException_Remote(exception.NovaException):
message = "some message"

def __unicode__(self):
return u"print the whole trace"

exc = FakeNovaException_Remote()
self.assertEquals(unicode(exc), u"print the whole trace")
self.assertEquals(exc.format_message(), "some message")

def test_format_message_remote_error(self):
class FakeNovaException_Remote(exception.NovaException):
message = "some message %(somearg)s"

def __unicode__(self):
return u"print the whole trace"

self.flags(fatal_exception_format_errors=False)
exc = FakeNovaException_Remote(lame_arg='lame')
self.assertEquals(exc.format_message(), "some message %(somearg)s")

0 comments on commit b936df8

Please sign in to comment.