driver: raise by default on import failure

When using the DriverManager class, if the driver fails to load, it's
actually better by default to re-raise the exception. It's not something
possible when loading multiple extension, but it's safe to do so with
drivers. This just changes the default behaviour, and it can still be
overridden.

The upside of that change is that when you try to load a driver that
cannot be loaded because of missing dependency, you actually get the
ImportError backtrace on your screen rather than the useless:
  RuntimeError: No 'foo' driver found, looking for 'bar'

which doesn't help at all. And the default mechanism that logs via
LOG.error() doesn't print anything at the screen if the application
didn't configure the logging subsystem.

Change-Id: I67d9e13a07c822c54dd16ac9ae7716747a24dd73
This commit is contained in:
Julien Danjou 2014-04-24 15:57:19 +02:00
parent cde4b1d032
commit 3668de2513
5 changed files with 20 additions and 4 deletions

View File

@ -35,6 +35,7 @@ stevedore.test.extension =
t1 = stevedore.tests.test_extension:FauxExtension
t2 = stevedore.tests.test_extension:FauxExtension
e1 = stevedore.tests.test_extension:BrokenExtension
e2 = stevedore.tests.notfound:UnimportableExtension
[build_sphinx]

View File

@ -33,6 +33,8 @@ class DriverManager(NamedExtensionManager):
invoke_on_load=False, invoke_args=(), invoke_kwds={},
on_load_failure_callback=None,
verify_requirements=False):
on_load_failure_callback = on_load_failure_callback \
or self._default_on_load_failure
super(DriverManager, self).__init__(
namespace=namespace,
names=[name],
@ -43,6 +45,10 @@ class DriverManager(NamedExtensionManager):
verify_requirements=verify_requirements,
)
@staticmethod
def _default_on_load_failure(drivermanager, ep, err):
raise err
@classmethod
def make_test_instance(cls, extension, namespace='TESTING',
propagate_map_exceptions=False,

View File

@ -15,7 +15,7 @@ def test_extension_failure_custom_callback():
on_load_failure_callback=failure_callback)
extensions = list(em.extensions)
assert len(extensions) > 0
assert len(errors) == 1
(manager, entrypoint, error) = errors[0]
assert manager is em
assert isinstance(error, IOError)
assert len(errors) == 2
for manager, entrypoint, error in errors:
assert manager is em
assert isinstance(error, (IOError, ImportError))

View File

@ -43,6 +43,15 @@ def test_no_drivers():
assert "No 'stevedore.test.extension.none' driver found" in str(err)
def test_bad_driver():
try:
driver.DriverManager('stevedore.test.extension', 'e2')
except ImportError:
pass
else:
assert False, "No error raised"
def test_multiple_drivers():
# The idea for this test was contributed by clayg:
# https://gist.github.com/clayg/6311348