diff --git a/openstack/tests/unit/test_utils.py b/openstack/tests/unit/test_utils.py index 676a5de5..ae773439 100644 --- a/openstack/tests/unit/test_utils.py +++ b/openstack/tests/unit/test_utils.py @@ -11,6 +11,7 @@ # under the License. import mock +import sys import testtools from openstack import utils @@ -18,11 +19,11 @@ from openstack import utils class Test_enable_logging(testtools.TestCase): - def _console_tests(self, fake_logging, level, debug): + def _console_tests(self, fake_logging, level, debug, stream): the_logger = mock.MagicMock() fake_logging.getLogger.return_value = the_logger - utils.enable_logging(debug=debug) + utils.enable_logging(debug=debug, stream=stream) self.assertEqual(the_logger.addHandler.call_count, 1) the_logger.setLevel.assert_called_with(level) @@ -35,16 +36,33 @@ class Test_enable_logging(testtools.TestCase): utils.enable_logging(debug=debug, path=fake_path) fake_logging.FileHandler.assert_called_with(fake_path) - self.assertEqual(the_logger.addHandler.call_count, 2) + self.assertEqual(the_logger.addHandler.call_count, 1) the_logger.setLevel.assert_called_with(level) - @mock.patch("openstack.utils.logging") - def test_debug_console(self, fake_logging): - self._console_tests(fake_logging, fake_logging.DEBUG, True) + def test_none(self): + self.assertRaises( + ValueError, utils.enable_logging, + debug=True, path=None, stream=None) @mock.patch("openstack.utils.logging") - def test_warning_console(self, fake_logging): - self._console_tests(fake_logging, fake_logging.WARNING, False) + def test_debug_console_stderr(self, fake_logging): + self._console_tests(fake_logging, + fake_logging.DEBUG, True, sys.stderr) + + @mock.patch("openstack.utils.logging") + def test_warning_console_stderr(self, fake_logging): + self._console_tests(fake_logging, + fake_logging.WARNING, False, sys.stderr) + + @mock.patch("openstack.utils.logging") + def test_debug_console_stdout(self, fake_logging): + self._console_tests(fake_logging, + fake_logging.DEBUG, True, sys.stdout) + + @mock.patch("openstack.utils.logging") + def test_warning_console_stdout(self, fake_logging): + self._console_tests(fake_logging, + fake_logging.WARNING, False, sys.stdout) @mock.patch("openstack.utils.logging") def test_debug_file(self, fake_logging): diff --git a/openstack/utils.py b/openstack/utils.py index 367a5398..f91eb411 100644 --- a/openstack/utils.py +++ b/openstack/utils.py @@ -11,11 +11,10 @@ # under the License. import logging -import sys -def enable_logging(debug=False, path=None): - """Enable logging of messages to sys.stderr +def enable_logging(debug=False, path=None, stream=None): + """Enable logging to a file at path and/or a console stream. This function is available for debugging purposes. If you wish to log this package's message in your application, the standard library @@ -26,27 +25,35 @@ def enable_logging(debug=False, path=None): which includes HTTP requests and responses, or ``False`` for warning messages. :param str path: If a *path* is specified, logging output will - written to that file in addition to sys.stderr. + written to that file in addition to sys.stderr. The path is passed to logging.FileHandler, which will append messages the file (and create - it if needed). *Default: None* + it if needed). + :param stream: One of ``None `` or ``sys.stdout`` or ``sys.stderr``. + If it is ``None``, nothing is logged to a stream. + If it isn't ``None``, console output is logged + to this stream. :rtype: None """ - root_logger = logging.getLogger('') + if path is None and stream is None: + raise ValueError("path and/or stream must be set") + + logger = logging.getLogger('openstack') formatter = logging.Formatter( '%(asctime)s %(levelname)s: %(name)s %(message)s') - console = logging.StreamHandler(sys.stderr) - console.setFormatter(formatter) - root_logger.addHandler(console) + if stream is not None: + console = logging.StreamHandler(stream) + console.setFormatter(formatter) + logger.addHandler(console) if path is not None: file_handler = logging.FileHandler(path) file_handler.setFormatter(formatter) - root_logger.addHandler(file_handler) + logger.addHandler(file_handler) - root_logger.setLevel(logging.DEBUG if debug else logging.WARNING) + logger.setLevel(logging.DEBUG if debug else logging.WARNING) def urljoin(*args):