Don't lose AttributeError in API Wrappers

Instead of (implicitly) catching the AttributeError, and later
creating and raising a new one, we just re-raise the original
exception. This way all the information from the original is
retained, including the name of the actual object on which it
happened.

Change-Id: Idc0c5a8ed5dfca6a8724e393c220baf9960564ed
Closes-bug: #1274097
This commit is contained in:
Radomir Dopieralski 2014-01-29 14:06:46 +01:00
parent f96c049cda
commit 20b414db2f
2 changed files with 26 additions and 26 deletions

View File

@ -73,21 +73,19 @@ class APIResourceWrapper(object):
api object as the only argument to the constructor
"""
_attrs = []
_apiresource = None # Make sure _apiresource is there even in __init__.
def __init__(self, apiresource):
self._apiresource = apiresource
def __getattr__(self, attr):
if attr in self._attrs:
def __getattribute__(self, attr):
try:
return object.__getattribute__(self, attr)
except AttributeError:
if attr not in self._attrs:
raise
# __getattr__ won't find properties
return self._apiresource.__getattribute__(attr)
else:
msg = ('Attempted to access unknown attribute "%s" on '
'APIResource object of type "%s" wrapping resource of '
'type "%s".') % (attr, self.__class__,
self._apiresource.__class__)
LOG.debug(exceptions.error_color(msg))
raise AttributeError(attr)
return getattr(self._apiresource, attr)
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__,
@ -106,28 +104,30 @@ class APIDictWrapper(object):
Attribute access is the preferred method of access, to be
consistent with api resource objects from novaclient.
"""
_apidict = {} # Make sure _apidict is there even in __init__.
def __init__(self, apidict):
self._apidict = apidict
def __getattr__(self, attr):
def __getattribute__(self, attr):
try:
return object.__getattribute__(self, attr)
except AttributeError:
if attr not in self._apidict:
raise
return self._apidict[attr]
except KeyError:
msg = 'Unknown attribute "%(attr)s" on APIResource object ' \
'of type "%(cls)s"' % {'attr': attr, 'cls': self.__class__}
LOG.debug(exceptions.error_color(msg))
raise AttributeError(msg)
def __getitem__(self, item):
try:
return self.__getattr__(item)
return getattr(self, item)
except AttributeError as e:
# caller is expecting a KeyError
raise KeyError(e)
def get(self, item, default=None):
try:
return self.__getattr__(item)
return getattr(self, item)
except AttributeError:
return default

View File

@ -122,7 +122,7 @@ class NetworkApiNovaFloatingIpTests(NetworkApiNovaTestBase):
ret = api.network.tenant_floating_ip_list(self.request)
for r, e in zip(ret, fips):
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'instance_id']:
self.assertEqual(r.__getattr__(attr), e.__getattr__(attr))
self.assertEqual(getattr(r, attr), getattr(e, attr))
self.assertEqual(r.port_id, e.instance_id)
def test_floating_ip_get(self):
@ -134,7 +134,7 @@ class NetworkApiNovaFloatingIpTests(NetworkApiNovaTestBase):
ret = api.network.tenant_floating_ip_get(self.request, fip.id)
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'instance_id']:
self.assertEqual(ret.__getattr__(attr), fip.__getattr__(attr))
self.assertEqual(getattr(ret, attr), getattr(fip, attr))
self.assertEqual(ret.port_id, fip.instance_id)
def test_floating_ip_allocate(self):
@ -147,7 +147,7 @@ class NetworkApiNovaFloatingIpTests(NetworkApiNovaTestBase):
ret = api.network.tenant_floating_ip_allocate(self.request, pool_name)
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'instance_id']:
self.assertEqual(ret.__getattr__(attr), fip.__getattr__(attr))
self.assertEqual(getattr(ret, attr), getattr(fip, attr))
self.assertEqual(ret.port_id, fip.instance_id)
def test_floating_ip_release(self):
@ -410,7 +410,7 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
rets = api.network.floating_ip_pools_list(self.request)
for attr in ['id', 'name']:
self.assertEqual([p.__getattr__(attr) for p in rets],
self.assertEqual([getattr(p, attr) for p in rets],
[p[attr] for p in ext_nets])
def test_floating_ip_list(self):
@ -427,7 +427,7 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
self.assertEqual(len(fips), len(rets))
for ret, exp in zip(rets, fips):
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
self.assertEqual(ret.__getattr__(attr), exp[attr])
self.assertEqual(getattr(ret, attr), exp[attr])
if exp['port_id']:
dev_id = assoc_port['device_id'] if exp['port_id'] else None
self.assertEqual(ret.instance_id, dev_id)
@ -442,7 +442,7 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
ret = api.network.tenant_floating_ip_get(self.request, fip['id'])
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
self.assertEqual(ret.__getattr__(attr), fip[attr])
self.assertEqual(getattr(ret, attr), fip[attr])
self.assertEqual(ret.instance_id, assoc_port['device_id'])
def test_floating_ip_get_unassociated(self):
@ -452,7 +452,7 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
ret = api.network.tenant_floating_ip_get(self.request, fip['id'])
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
self.assertEqual(ret.__getattr__(attr), fip[attr])
self.assertEqual(getattr(ret, attr), fip[attr])
self.assertIsNone(ret.instance_id)
def test_floating_ip_allocate(self):
@ -468,7 +468,7 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
ret = api.network.tenant_floating_ip_allocate(self.request,
ext_net['id'])
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
self.assertEqual(ret.__getattr__(attr), fip[attr])
self.assertEqual(getattr(ret, attr), fip[attr])
self.assertIsNone(ret.instance_id)
def test_floating_ip_release(self):