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 api object as the only argument to the constructor
""" """
_attrs = [] _attrs = []
_apiresource = None # Make sure _apiresource is there even in __init__.
def __init__(self, apiresource): def __init__(self, apiresource):
self._apiresource = apiresource self._apiresource = apiresource
def __getattr__(self, attr): def __getattribute__(self, attr):
if attr in self._attrs: try:
return object.__getattribute__(self, attr)
except AttributeError:
if attr not in self._attrs:
raise
# __getattr__ won't find properties # __getattr__ won't find properties
return self._apiresource.__getattribute__(attr) return getattr(self._apiresource, 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)
def __repr__(self): def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, return "<%s: %s>" % (self.__class__.__name__,
@ -106,28 +104,30 @@ class APIDictWrapper(object):
Attribute access is the preferred method of access, to be Attribute access is the preferred method of access, to be
consistent with api resource objects from novaclient. consistent with api resource objects from novaclient.
""" """
_apidict = {} # Make sure _apidict is there even in __init__.
def __init__(self, apidict): def __init__(self, apidict):
self._apidict = apidict self._apidict = apidict
def __getattr__(self, attr): def __getattribute__(self, attr):
try: try:
return object.__getattribute__(self, attr)
except AttributeError:
if attr not in self._apidict:
raise
return self._apidict[attr] 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): def __getitem__(self, item):
try: try:
return self.__getattr__(item) return getattr(self, item)
except AttributeError as e: except AttributeError as e:
# caller is expecting a KeyError # caller is expecting a KeyError
raise KeyError(e) raise KeyError(e)
def get(self, item, default=None): def get(self, item, default=None):
try: try:
return self.__getattr__(item) return getattr(self, item)
except AttributeError: except AttributeError:
return default return default

View File

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