summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-04-18 17:01:42 +0000
committerGerrit Code Review <review@openstack.org>2016-04-18 17:01:42 +0000
commite3a6fc27b0cfc9b82801e13d61c2fad3a09bf6b1 (patch)
tree35d9bc4bbfc7bffcfcd0f9a02fac58ce3f874c98 /openstackclient
parent89445855acffc5ae4cf87dc501c09f3434d08bad (diff)
parent926330d3726e9ce7001190730c69bf6ee45b422a (diff)
downloadpython-openstackclient-e3a6fc27b0cfc9b82801e13d61c2fad3a09bf6b1.tar.gz
Merge "Propagate AttributeErrors when lazily loading plugins"
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/common/clientmanager.py10
-rw-r--r--openstackclient/common/exceptions.py7
-rw-r--r--openstackclient/tests/common/test_clientmanager.py8
3 files changed, 24 insertions, 1 deletions
diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py
index 6d23b55e..8b0fb921 100644
--- a/openstackclient/common/clientmanager.py
+++ b/openstackclient/common/clientmanager.py
@@ -22,8 +22,10 @@ import sys
from oslo_utils import strutils
import requests
+import six
from openstackclient.api import auth
+from openstackclient.common import exceptions
from openstackclient.common import session as osc_session
from openstackclient.identity import client as identity_client
@@ -45,7 +47,13 @@ class ClientCache(object):
def __get__(self, instance, owner):
# Tell the ClientManager to login to keystone
if self._handle is None:
- self._handle = self.factory(instance)
+ try:
+ self._handle = self.factory(instance)
+ except AttributeError as err:
+ # Make sure the failure propagates. Otherwise, the plugin just
+ # quietly isn't there.
+ new_err = exceptions.PluginAttributeError(err)
+ six.reraise(new_err.__class__, new_err, sys.exc_info()[2])
return self._handle
diff --git a/openstackclient/common/exceptions.py b/openstackclient/common/exceptions.py
index 5f81e6a6..bdc33ddb 100644
--- a/openstackclient/common/exceptions.py
+++ b/openstackclient/common/exceptions.py
@@ -24,6 +24,13 @@ class AuthorizationFailure(Exception):
pass
+class PluginAttributeError(Exception):
+ """A plugin threw an AttributeError while being lazily loaded."""
+ # This *must not* inherit from AttributeError;
+ # that would defeat the whole purpose.
+ pass
+
+
class NoTokenLookupException(Exception):
"""This does not support looking up endpoints from an existing token."""
pass
diff --git a/openstackclient/tests/common/test_clientmanager.py b/openstackclient/tests/common/test_clientmanager.py
index 6fc5b41e..fa6c3fcc 100644
--- a/openstackclient/tests/common/test_clientmanager.py
+++ b/openstackclient/tests/common/test_clientmanager.py
@@ -41,6 +41,7 @@ auth.get_options_list()
class Container(object):
attr = clientmanager.ClientCache(lambda x: object())
+ buggy_attr = clientmanager.ClientCache(lambda x: x.foo)
def __init__(self):
pass
@@ -72,6 +73,13 @@ class TestClientCache(utils.TestCase):
c = Container()
self.assertEqual(c.attr, c.attr)
+ def test_attribute_error_propagates(self):
+ c = Container()
+ err = self.assertRaises(exc.PluginAttributeError,
+ getattr, c, 'buggy_attr')
+ self.assertNotIsInstance(err, AttributeError)
+ self.assertEqual("'Container' object has no attribute 'foo'", str(err))
+
class TestClientManager(utils.TestCase):