diff --git a/plotly/optional_imports.py b/plotly/optional_imports.py index 7e9ba805b42..7f49d1fe26f 100644 --- a/plotly/optional_imports.py +++ b/plotly/optional_imports.py @@ -5,7 +5,9 @@ from __future__ import absolute_import from importlib import import_module +import logging +logger = logging.getLogger(__name__) _not_importable = set() @@ -23,3 +25,7 @@ def get_module(name): return import_module(name) except ImportError: _not_importable.add(name) + except Exception as e: + _not_importable.add(name) + msg = "Error importing optional module {}".format(name) + logger.exception(msg) diff --git a/plotly/tests/test_core/test_optional_imports/exploding_module.py b/plotly/tests/test_core/test_optional_imports/exploding_module.py new file mode 100644 index 00000000000..00e8ed7d43a --- /dev/null +++ b/plotly/tests/test_core/test_optional_imports/exploding_module.py @@ -0,0 +1,2 @@ +# A module that raises and exception on import +raise Exception("Boom!") diff --git a/plotly/tests/test_core/test_optional_imports/test_optional_imports.py b/plotly/tests/test_core/test_optional_imports/test_optional_imports.py index e7569f1609d..de70ee2d122 100644 --- a/plotly/tests/test_core/test_optional_imports/test_optional_imports.py +++ b/plotly/tests/test_core/test_optional_imports/test_optional_imports.py @@ -1,7 +1,6 @@ from __future__ import absolute_import - +import sys from unittest import TestCase - from plotly.optional_imports import get_module @@ -22,3 +21,33 @@ def test_get_module_exists_submodule(self): def test_get_module_does_not_exist(self): module = get_module('hoopla') self.assertIsNone(module) + + def test_get_module_import_exception(self): + # Get module that raises an exception on import + module_str = ('plotly.tests.test_core.' + 'test_optional_imports.exploding_module') + + if sys.version_info.major == 3 and sys.version_info.minor >= 4: + with self.assertLogs('plotly.optional_imports', level='ERROR') as cm: + module = get_module(module_str) + + # No exception should be raised and None should be returned + self.assertIsNone(module) + + # Check logging level and log message + expected_start = ('ERROR:plotly.optional_imports:' + 'Error importing optional module ' + module_str) + + self.assertEqual( + cm.output[0][:len(expected_start)], expected_start) + + # Check that exception message is included after log message + expected_end = 'Boom!' + self.assertEqual( + cm.output[0][-len(expected_end):], expected_end) + else: + # Don't check logging + module = get_module(module_str) + + # No exception should be raised and None should be returned + self.assertIsNone(module)