signal.signal(signal.SIGALRM,
action if action is not None else signal.SIG_DFL)
- def start(self):
- if not logging.getLogger().handlers:
- # The IOLoop catches and logs exceptions, so it's
- # important that log output be visible. However, python's
- # default behavior for non-root loggers (prior to python
- # 3.2) is to print an unhelpful "no handlers could be
- # found" message rather than the actual log entry, so we
- # must explicitly configure logging if we've made it this
- # far without anything.
+ def _setup_logging(self):
+ """The IOLoop catches and logs exceptions, so it's
+ important that log output be visible. However, python's
+ default behavior for non-root loggers (prior to python
+ 3.2) is to print an unhelpful "no handlers could be
+ found" message rather than the actual log entry, so we
+ must explicitly configure logging if we've made it this
+ far without anything.
+
+ """
+ if not any([logging.getLogger().handlers,
+ logging.getLogger('tornado').handlers,
+ logging.getLogger('tornado.application').handlers]):
logging.basicConfig()
+
+ def start(self):
+ self._setup_logging()
if self._stopped:
self._stopped = False
return
import contextlib
import datetime
import functools
+import logging
import socket
import sys
import threading
except ImportError:
futures = None
+try:
+ from unittest import mock # python 3.3+
+except ImportError:
+ try:
+ import mock # third-party mock package
+ except ImportError:
+ mock = None
+
class TestIOLoop(AsyncTestCase):
@skipOnTravis
yield gen.Task(self.io_loop.add_timeout, self.io_loop.time() + 1)
self.assertRaises(TimeoutError, self.io_loop.run_sync, f, timeout=0.01)
+
+class TestIOLoopLogging(AsyncTestCase):
+
+ @unittest.skipIf(mock is None, 'mock package not present')
+ def test_basic_config_invoked(self):
+ """If no loggers have been defined, logging.basicConfig should be called
+ test for the presence of a root logger, start IOloop and then test
+ to see if one has been added
+
+ """
+ with mock.patch('logging.basicConfig') as basicConfig:
+ self.io_loop.add_timeout(datetime.timedelta(microseconds=1),
+ self.stop)
+ self.wait()
+ basicConfig.assert_called_once()
+
+ @unittest.skipIf(mock is None, 'mock package not present')
+ def test_basic_config_not_invoked(self):
+ """The setup_logging method will check for getLogger().handlers,
+ getLogger('tornado').handlers and
+ getLogger('tornado.application').handlers. If all are empty, it will
+ invoke basicConfig. Test to make sure all three are called, all three
+ are checked and basicConfig is not invoked because there is a handler
+ returned (for each).
+
+ """
+ with mock.patch('logging.getLogger') as getLogger:
+ with mock.patch('logging.basicConfig') as basicConfig:
+ getLogger.handlers = [True]
+ self.io_loop.add_timeout(datetime.timedelta(microseconds=1),
+ self.stop)
+ self.wait()
+ basicConfig.assert_not_called()
+ getLogger.assert_has_calls([mock.call(),
+ mock.call('tornado'),
+ mock.call('tornado.application')])
+ self.assertEqual(getLogger.call_count, 3)
+
+
if __name__ == "__main__":
unittest.main()