From 101f72669072e30faaa41e8d1507766a56a7ae8d Mon Sep 17 00:00:00 2001 From: David Leen Date: Fri, 26 Jul 2019 14:53:00 -0700 Subject: [PATCH] Prevent tests from hanging When the NotebookApp raises an exception on initialization, a test can hang forever. This can happen when passing configuration when customizing NotebookTestBase: ``` class TestMissingExtension(NotebookTestBase): @classmethod def get_argv(cls): argv = super(TestMissingExtension, cls).get_argv() argv.extend( [ "--NotebookApp.session_manager_class=doesnt_exist", ] ) return argv def test_this_will_hang_forever(self): pass ``` Since the exception happens before the try/finally the `Event` will never be triggered. By including the construction and initialization of the notebook in the try/finally we can handle situations like this. --- notebook/tests/launchnotebook.py | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/notebook/tests/launchnotebook.py b/notebook/tests/launchnotebook.py index 9e84a5964..14132522f 100644 --- a/notebook/tests/launchnotebook.py +++ b/notebook/tests/launchnotebook.py @@ -146,31 +146,31 @@ class NotebookTestBase(TestCase): if 'asyncio' in sys.modules: import asyncio asyncio.set_event_loop(asyncio.new_event_loop()) - app = cls.notebook = NotebookApp( - port=cls.port, - port_retries=0, - open_browser=False, - config_dir=cls.config_dir, - data_dir=cls.data_dir, - runtime_dir=cls.runtime_dir, - notebook_dir=cls.notebook_dir, - base_url=cls.url_prefix, - config=config, - allow_root=True, - token=cls.token, - ) - # don't register signal handler during tests - app.init_signal = lambda : None - # clear log handlers and propagate to root for nose to capture it - # needs to be redone after initialize, which reconfigures logging - app.log.propagate = True - app.log.handlers = [] - app.initialize(argv=cls.get_argv()) - app.log.propagate = True - app.log.handlers = [] - loop = IOLoop.current() - loop.add_callback(started.set) try: + app = cls.notebook = NotebookApp( + port=cls.port, + port_retries=0, + open_browser=False, + config_dir=cls.config_dir, + data_dir=cls.data_dir, + runtime_dir=cls.runtime_dir, + notebook_dir=cls.notebook_dir, + base_url=cls.url_prefix, + config=config, + allow_root=True, + token=cls.token, + ) + # don't register signal handler during tests + app.init_signal = lambda : None + # clear log handlers and propagate to root for nose to capture it + # needs to be redone after initialize, which reconfigures logging + app.log.propagate = True + app.log.handlers = [] + app.initialize(argv=cls.get_argv()) + app.log.propagate = True + app.log.handlers = [] + loop = IOLoop.current() + loop.add_callback(started.set) app.start() finally: # set the event, so failure to start doesn't cause a hang