diff --git a/force_bdss/bdss_application.py b/force_bdss/bdss_application.py index e7c556fcff59ae8ee46fbb4e37ffb2b49fdb6c51..29c7f2517fd63c69a1d82f24b3bb0677bb487895 100644 --- a/force_bdss/bdss_application.py +++ b/force_bdss/bdss_application.py @@ -1,4 +1,7 @@ -from stevedore import extension +import functools +import logging + +from stevedore.extension import ExtensionManager from stevedore.exception import NoMatches from envisage.api import Application @@ -34,18 +37,35 @@ class BDSSApplication(Application): else: plugins.append(CoreMCODriver()) - mgr = extension.ExtensionManager( + mgr = ExtensionManager( namespace='force.bdss.extensions', - invoke_on_load=True + invoke_on_load=True, + on_load_failure_callback=functools.partial(_load_failure_callback, + plugins) ) - def import_extensions(ext): - print("Found extension {}".format(ext.name)) - plugins.append(ext.obj) - try: - mgr.map(import_extensions) + mgr.map(functools.partial(_import_extensions, plugins)) except NoMatches: - print("No extensions found") + logging.info("No extensions found") super(BDSSApplication, self).__init__(plugins=plugins) + + +def _import_extensions(plugins, ext): + """Service routine extracted for testing. + Imports the extension in the plugins argument. + """ + logging.info("Found extension {}".format(ext.obj)) + plugins.append(ext.obj) + + +def _load_failure_callback(plugins, manager, entry_point, exception): + """Service routine extracted for testing. + Reports failure to load a module through stevedore, using the + on_load_failure_callback option. + """ + logging.error( + "Unable to load plugin {}. Exception: {}. Message: {}".format( + entry_point, exception.__class__.__name__, exception) + ) diff --git a/force_bdss/tests/test_bdss_application.py b/force_bdss/tests/test_bdss_application.py new file mode 100644 index 0000000000000000000000000000000000000000..abf417075b150dba73118863c254dcf3585a0714 --- /dev/null +++ b/force_bdss/tests/test_bdss_application.py @@ -0,0 +1,43 @@ +import unittest +import testfixtures + +from force_bdss.bdss_application import ( + BDSSApplication, + _load_failure_callback, + _import_extensions +) + +try: + import mock +except ImportError: + from unittest import mock + + +class TestBDSSApplication(unittest.TestCase): + def test_initialization(self): + app = BDSSApplication(False, "foo/bar") + self.assertFalse(app.evaluate) + self.assertEqual(app.workflow_filepath, "foo/bar") + + def test_extension_load_failure(self): + plugins = [] + with testfixtures.LogCapture() as log: + _load_failure_callback(plugins, + mock.Mock(), + "foo", + Exception("hello")) + + log.check( + ('root', 'ERROR', "Unable to load plugin foo. Exception: " + "Exception. Message: hello") + ) + self.assertEqual(plugins, []) + + def test_import_extension(self): + plugins = [] + plugin = mock.Mock() + ext = mock.Mock() + ext.obj = plugin + _import_extensions(plugins, ext) + + self.assertEqual(plugins[0], plugin) diff --git a/requirements/dev_requirements.txt b/requirements/dev_requirements.txt index d4cbb0a0e1f21d700d0cfc04a62db394b88ae253..453d4d8a2717d98b6e8a03f97d798c5faccbc807 100644 --- a/requirements/dev_requirements.txt +++ b/requirements/dev_requirements.txt @@ -1,3 +1,4 @@ flake8 coverage mock +testfixtures