From 3668de2513053f05cec068d12cc7b9cfb642b298 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Thu, 24 Apr 2014 15:57:19 +0200 Subject: 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 --- setup.cfg | 1 + stevedore/driver.py | 6 ++++++ stevedore/tests/extension_unimportable.py | 0 stevedore/tests/test_callback.py | 8 ++++---- stevedore/tests/test_driver.py | 9 +++++++++ 5 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 stevedore/tests/extension_unimportable.py diff --git a/setup.cfg b/setup.cfg index 8cae156..571fa9b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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] diff --git a/stevedore/driver.py b/stevedore/driver.py index 47273d0..85a2ae2 100644 --- a/stevedore/driver.py +++ b/stevedore/driver.py @@ -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, diff --git a/stevedore/tests/extension_unimportable.py b/stevedore/tests/extension_unimportable.py new file mode 100644 index 0000000..e69de29 diff --git a/stevedore/tests/test_callback.py b/stevedore/tests/test_callback.py index d80c7f2..47ea262 100644 --- a/stevedore/tests/test_callback.py +++ b/stevedore/tests/test_callback.py @@ -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)) diff --git a/stevedore/tests/test_driver.py b/stevedore/tests/test_driver.py index e56d2c5..f81cd8b 100644 --- a/stevedore/tests/test_driver.py +++ b/stevedore/tests/test_driver.py @@ -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 -- cgit v1.2.1