diff --git a/mopidy/ext.py b/mopidy/ext.py index 3122611f..37e91a82 100644 --- a/mopidy/ext.py +++ b/mopidy/ext.py @@ -148,8 +148,21 @@ def load_extensions(): for entry_point in pkg_resources.iter_entry_points('mopidy.ext'): logger.debug('Loading entry point: %s', entry_point) extension_class = entry_point.load(require=False) - extension = extension_class() + + try: + if not issubclass(extension_class, Extension): + continue # TODO: log this + except TypeError: + continue # TODO: log that extension_class is not a class + + try: + extension = extension_class() + except Exception: + continue # TODO: log this + extension.entry_point = entry_point + + # TODO: store: (instance, entry_point, command, schema, defaults) installed_extensions.append(extension) logger.debug( 'Loaded extension: %s %s', extension.dist_name, extension.version) diff --git a/tests/test_ext.py b/tests/test_ext.py index 7b16df83..ab54bc07 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -1,10 +1,14 @@ from __future__ import absolute_import, unicode_literals +import mock + import pytest from mopidy import config, ext +# ext.Extension + @pytest.fixture def extension(): return ext.Extension() @@ -39,3 +43,76 @@ def test_validate_environment_does_nothing_by_default(extension): def test_setup_raises_not_implemented(extension): with pytest.raises(NotImplementedError): extension.setup(None) + + +# ext.load_extensions + +class TestExtension(ext.Extension): + dist_name = 'Mopidy-Foobar' + ext_name = 'foobar' + version = '1.2.3' + + +@mock.patch('pkg_resources.iter_entry_points') +def test_load_extensions_no_extenions(mock_entry_points): + mock_entry_points.return_value = [] + assert [] == ext.load_extensions() + + +@mock.patch('pkg_resources.iter_entry_points') +def test_load_extensions(mock_entry_points): + mock_entry_point = mock.Mock() + mock_entry_point.load.return_value = TestExtension + + mock_entry_points.return_value = [mock_entry_point] + + extensions = ext.load_extensions() + assert len(extensions) == 1 + assert isinstance(extensions[0], TestExtension) + + +@mock.patch('pkg_resources.iter_entry_points') +def test_load_extensions_gets_wrong_class(mock_entry_points): + + class WrongClass(object): + pass + + mock_entry_point = mock.Mock() + mock_entry_point.load.return_value = WrongClass + + mock_entry_points.return_value = [mock_entry_point] + + assert [] == ext.load_extensions() + + +@mock.patch('pkg_resources.iter_entry_points') +def test_load_extensions_gets_instance(mock_entry_points): + mock_entry_point = mock.Mock() + mock_entry_point.load.return_value = TestExtension() + + mock_entry_points.return_value = [mock_entry_point] + + assert [] == ext.load_extensions() + + +@mock.patch('pkg_resources.iter_entry_points') +def test_load_extensions_creating_instance_fails(mock_entry_points): + mock_extension = mock.Mock(spec=ext.Extension) + mock_extension.side_effect = Exception + + mock_entry_point = mock.Mock() + mock_entry_point.load.return_value = mock_extension + + mock_entry_points.return_value = [mock_entry_point] + assert [] == ext.load_extensions() + + +@mock.patch('pkg_resources.iter_entry_points') +def test_load_extensions_store_entry_point(mock_entry_points): + mock_entry_point = mock.Mock() + mock_entry_point.load.return_value = TestExtension + mock_entry_points.return_value = [mock_entry_point] + + extensions = ext.load_extensions() + assert len(extensions) == 1 + assert extensions[0].entry_point == mock_entry_point