From 7d375282a9a74293d35d851e6ec985e544c272bf Mon Sep 17 00:00:00 2001 From: Ram Rachum Date: Thu, 25 Jun 2020 19:10:56 +0300 Subject: [PATCH] Fix exception causes all over the codebase --- notebook/bundler/handlers.py | 12 +++++---- notebook/gateway/managers.py | 27 ++++++++++++------- notebook/kernelspecs/handlers.py | 5 ++-- notebook/nbconvert/handlers.py | 12 ++++----- notebook/notebookapp.py | 16 +++++------ notebook/services/contents/fileio.py | 8 +++--- notebook/services/contents/filemanager.py | 9 ++++--- .../services/contents/largefilemanager.py | 4 +-- notebook/services/kernelspecs/handlers.py | 4 +-- notebook/services/nbconvert/handlers.py | 2 +- notebook/services/sessions/handlers.py | 12 ++++----- notebook/tests/launchnotebook.py | 2 +- notebook/tests/selenium/quick_selenium.py | 2 +- 13 files changed, 64 insertions(+), 51 deletions(-) diff --git a/notebook/bundler/handlers.py b/notebook/bundler/handlers.py index 9b74abefd7..868dd78324 100644 --- a/notebook/bundler/handlers.py +++ b/notebook/bundler/handlers.py @@ -59,9 +59,10 @@ def get(self, path): try: bundler = self.get_bundler(bundler_id) - except KeyError: - raise web.HTTPError(400, 'Bundler %s not enabled' % bundler_id) - + except KeyError as e: + raise web.HTTPError(400, 'Bundler %s not enabled' % + bundler_id) from e + module_name = bundler['module_name'] try: # no-op in python3, decode error in python2 @@ -72,8 +73,9 @@ def get(self, path): try: bundler_mod = import_item(module_name) - except ImportError: - raise web.HTTPError(500, 'Could not import bundler %s ' % bundler_id) + except ImportError as e: + raise web.HTTPError(500, 'Could not import bundler %s ' % + bundler_id) from e # Let the bundler respond in any way it sees fit and assume it will # finish the request diff --git a/notebook/gateway/managers.py b/notebook/gateway/managers.py index 8f89db6fb5..30382e8c0e 100644 --- a/notebook/gateway/managers.py +++ b/notebook/gateway/managers.py @@ -282,18 +282,23 @@ def gateway_request(endpoint, **kwargs): # or the server is not running. # NOTE: We do this here since this handler is called during the Notebook's startup and subsequent refreshes # of the tree view. - except ConnectionRefusedError: - raise web.HTTPError(503, "Connection refused from Gateway server url '{}'. " - "Check to be sure the Gateway instance is running.".format(GatewayClient.instance().url)) + except ConnectionRefusedError as e: + raise web.HTTPError( + 503, + "Connection refused from Gateway server url '{}'. Check to be sure the" + " Gateway instance is running.".format(GatewayClient.instance().url) + ) from e except HTTPError as e: # This can occur if the host is valid (e.g., foo.com) but there's nothing there. raise web.HTTPError(e.code, "Error attempting to connect to Gateway server url '{}'. " "Ensure gateway url is valid and the Gateway instance is running.". - format(GatewayClient.instance().url)) - except gaierror: - raise web.HTTPError(404, "The Gateway server specified in the gateway_url '{}' doesn't appear to be valid. " - "Ensure gateway url is valid and the Gateway instance is running.". - format(GatewayClient.instance().url)) + format(GatewayClient.instance().url)) from e + except gaierror as e: + raise web.HTTPError( + 404, + "The Gateway server specified in the gateway_url '{}' doesn't appear to be valid. Ensure gateway " + "url is valid and the Gateway instance is running.".format(GatewayClient.instance().url) + ) from e raise gen.Return(response) @@ -575,8 +580,10 @@ def get_kernel_spec(self, kernel_name, **kwargs): if error.status_code == 404: # Convert not found to KeyError since that's what the Notebook handler expects # message is not used, but might as well make it useful for troubleshooting - raise KeyError('kernelspec {kernel_name} not found on Gateway server at: {gateway_url}'. - format(kernel_name=kernel_name, gateway_url=GatewayClient.instance().url)) + raise KeyError( + 'kernelspec {kernel_name} not found on Gateway server at: {gateway_url}'. + format(kernel_name=kernel_name, gateway_url=GatewayClient.instance().url) + ) from error else: raise else: diff --git a/notebook/kernelspecs/handlers.py b/notebook/kernelspecs/handlers.py index 9ec642a82b..be768b5ab7 100644 --- a/notebook/kernelspecs/handlers.py +++ b/notebook/kernelspecs/handlers.py @@ -13,8 +13,9 @@ def get(self, kernel_name, path, include_body=True): ksm = self.kernel_spec_manager try: self.root = ksm.get_kernel_spec(kernel_name).resource_dir - except KeyError: - raise web.HTTPError(404, u'Kernel spec %s not found' % kernel_name) + except KeyError as e: + raise web.HTTPError(404, + u'Kernel spec %s not found' % kernel_name) from e self.log.debug("Serving kernel resource from: %s", self.root) return web.StaticFileHandler.get(self, path, include_body=include_body) diff --git a/notebook/nbconvert/handlers.py b/notebook/nbconvert/handlers.py index c3cc2462d7..faa1a6931e 100644 --- a/notebook/nbconvert/handlers.py +++ b/notebook/nbconvert/handlers.py @@ -61,19 +61,19 @@ def get_exporter(format, **kwargs): try: from nbconvert.exporters.base import get_exporter except ImportError as e: - raise web.HTTPError(500, "Could not import nbconvert: %s" % e) + raise web.HTTPError(500, "Could not import nbconvert: %s" % e) from e try: Exporter = get_exporter(format) - except KeyError: + except KeyError as e: # should this be 400? - raise web.HTTPError(404, u"No exporter for format: %s" % format) + raise web.HTTPError(404, u"No exporter for format: %s" % format) from e try: return Exporter(**kwargs) except Exception as e: app_log.exception("Could not construct Exporter: %s", Exporter) - raise web.HTTPError(500, "Could not construct Exporter: %s" % e) + raise web.HTTPError(500, "Could not construct Exporter: %s" % e) from e class NbconvertFileHandler(IPythonHandler): @@ -133,7 +133,7 @@ def get(self, format, path): ) except Exception as e: self.log.exception("nbconvert failed: %s", e) - raise web.HTTPError(500, "nbconvert failed: %s" % e) + raise web.HTTPError(500, "nbconvert failed: %s" % e) from e if respond_zip(self, name, output, resources): return @@ -175,7 +175,7 @@ def post(self, format): "config_dir": self.application.settings['config_dir'], }) except Exception as e: - raise web.HTTPError(500, "nbconvert failed: %s" % e) + raise web.HTTPError(500, "nbconvert failed: %s" % e) from e if respond_zip(self, name, output, resources): return diff --git a/notebook/notebookapp.py b/notebook/notebookapp.py index 2b82439595..57833caec0 100755 --- a/notebook/notebookapp.py +++ b/notebook/notebookapp.py @@ -54,12 +54,12 @@ # check for tornado 3.1.0 try: import tornado -except ImportError: - raise ImportError(_("The Jupyter Notebook requires tornado >= 5.0")) +except ImportError as e: + raise ImportError(_("The Jupyter Notebook requires tornado >= 5.0")) from e try: version_info = tornado.version_info -except AttributeError: - raise ImportError(_("The Jupyter Notebook requires tornado >= 5.0, but you have < 1.1.0")) +except AttributeError as e: + raise ImportError(_("The Jupyter Notebook requires tornado >= 5.0, but you have < 1.1.0")) from e if version_info < (5,0): raise ImportError(_("The Jupyter Notebook requires tornado >= 5.0, but you have %s") % tornado.version) @@ -858,14 +858,14 @@ def _validate_sock_mode(self, proposal): # And isn't out of bounds. converted_value <= 2 ** 12 )) - except ValueError: + except ValueError as e: raise TraitError( 'invalid --sock-mode value: %s, please specify as e.g. "0600"' % value - ) - except AssertionError: + ) from e + except AssertionError as e: raise TraitError( 'invalid --sock-mode value: %s, must have u+rw (0600) at a minimum' % value - ) + ) from e return value diff --git a/notebook/services/contents/fileio.py b/notebook/services/contents/fileio.py index 7cb1df3561..244571e8f7 100644 --- a/notebook/services/contents/fileio.py +++ b/notebook/services/contents/fileio.py @@ -226,7 +226,7 @@ def perm_to_403(self, os_path=''): if not os_path: os_path = str_to_unicode(e.filename or 'unknown file') path = to_api_path(os_path, root=self.root_dir) - raise HTTPError(403, u'Permission denied: %s' % path) + raise HTTPError(403, u'Permission denied: %s' % path) from e else: raise @@ -310,13 +310,13 @@ def _read_file(self, os_path, format): # was explicitly requested. try: return bcontent.decode('utf8'), 'text' - except UnicodeError: + except UnicodeError as e: if format == 'text': raise HTTPError( 400, "%s is not UTF-8 encoded" % os_path, reason='bad format', - ) + ) from e return encodebytes(bcontent).decode('ascii'), 'base64' def _save_file(self, os_path, content, format): @@ -335,7 +335,7 @@ def _save_file(self, os_path, content, format): except Exception as e: raise HTTPError( 400, u'Encoding error saving %s: %s' % (os_path, e) - ) + ) from e with self.atomic_writing(os_path, text=False) as f: f.write(bcontent) diff --git a/notebook/services/contents/filemanager.py b/notebook/services/contents/filemanager.py index 0cb3249cf4..3fa6dad212 100644 --- a/notebook/services/contents/filemanager.py +++ b/notebook/services/contents/filemanager.py @@ -131,7 +131,8 @@ def run_post_save_hook(self, model, os_path): self.post_save_hook(os_path=os_path, model=model, contents_manager=self) except Exception as e: self.log.error("Post-save hook failed o-n %s", os_path, exc_info=True) - raise web.HTTPError(500, u'Unexpected error while running post hook save: %s' % e) + raise web.HTTPError(500, u'Unexpected error while running post hook save: %s' + % e) from e @validate('root_dir') def _validate_root_dir(self, proposal): @@ -487,7 +488,8 @@ def save(self, model, path=''): raise except Exception as e: self.log.error(u'Error while saving file: %s %s', path, e, exc_info=True) - raise web.HTTPError(500, u'Unexpected error while saving file: %s %s' % (path, e)) + raise web.HTTPError(500, u'Unexpected error while saving file: %s %s' % + (path, e)) from e validation_message = None if model['type'] == 'notebook': @@ -584,7 +586,8 @@ def rename_file(self, old_path, new_path): except web.HTTPError: raise except Exception as e: - raise web.HTTPError(500, u'Unknown error renaming file: %s %s' % (old_path, e)) + raise web.HTTPError(500, u'Unknown error renaming file: %s %s' % + (old_path, e)) from e def info_string(self): return _("Serving notebooks from local directory: %s") % self.root_dir diff --git a/notebook/services/contents/largefilemanager.py b/notebook/services/contents/largefilemanager.py index 10808ba83f..a2b27ed99d 100644 --- a/notebook/services/contents/largefilemanager.py +++ b/notebook/services/contents/largefilemanager.py @@ -34,7 +34,7 @@ def save(self, model, path=''): raise except Exception as e: self.log.error(u'Error while saving file: %s %s', path, e, exc_info=True) - raise web.HTTPError(500, u'Unexpected error while saving file: %s %s' % (path, e)) + raise web.HTTPError(500, u'Unexpected error while saving file: %s %s' % (path, e)) from e model = self.get(path, content=False) @@ -61,7 +61,7 @@ def _save_large_file(self, os_path, content, format): except Exception as e: raise web.HTTPError( 400, u'Encoding error saving %s: %s' % (os_path, e) - ) + ) from e with self.perm_to_403(os_path): if os.path.islink(os_path): diff --git a/notebook/services/kernelspecs/handlers.py b/notebook/services/kernelspecs/handlers.py index 6302e96dfa..62a0df6191 100644 --- a/notebook/services/kernelspecs/handlers.py +++ b/notebook/services/kernelspecs/handlers.py @@ -87,8 +87,8 @@ def get(self, kernel_name): kernel_name = url_unescape(kernel_name) try: spec = yield maybe_future(ksm.get_kernel_spec(kernel_name)) - except KeyError: - raise web.HTTPError(404, u'Kernel spec %s not found' % kernel_name) + except KeyError as e: + raise web.HTTPError(404, u'Kernel spec %s not found' % kernel_name) from e if is_kernelspec_model(spec): model = spec else: diff --git a/notebook/services/nbconvert/handlers.py b/notebook/services/nbconvert/handlers.py index 2a9897fc47..7c65ee0fd9 100644 --- a/notebook/services/nbconvert/handlers.py +++ b/notebook/services/nbconvert/handlers.py @@ -13,7 +13,7 @@ def get(self): try: from nbconvert.exporters import base except ImportError as e: - raise web.HTTPError(500, "Could not import nbconvert: %s" % e) + raise web.HTTPError(500, "Could not import nbconvert: %s" % e) from e res = {} exporters = base.get_export_names() for exporter_name in exporters: diff --git a/notebook/services/sessions/handlers.py b/notebook/services/sessions/handlers.py index 49e030df87..42815f4d4a 100644 --- a/notebook/services/sessions/handlers.py +++ b/notebook/services/sessions/handlers.py @@ -44,13 +44,13 @@ def post(self): try: path = model['path'] - except KeyError: - raise web.HTTPError(400, "Missing field in JSON data: path") + except KeyError as e: + raise web.HTTPError(400, "Missing field in JSON data: path") from e try: mtype = model['type'] - except KeyError: - raise web.HTTPError(400, "Missing field in JSON data: type") + except KeyError as e: + raise web.HTTPError(400, "Missing field in JSON data: type") from e name = model.get('name', None) kernel = model.get('kernel', {}) @@ -155,9 +155,9 @@ def delete(self, session_id): sm = self.session_manager try: yield maybe_future(sm.delete_session(session_id)) - except KeyError: + except KeyError as e: # the kernel was deleted but the session wasn't! - raise web.HTTPError(410, "Kernel deleted before session") + raise web.HTTPError(410, "Kernel deleted before session") from e self.set_status(204) self.finish() diff --git a/notebook/tests/launchnotebook.py b/notebook/tests/launchnotebook.py index 41d0131717..6a393102d3 100644 --- a/notebook/tests/launchnotebook.py +++ b/notebook/tests/launchnotebook.py @@ -56,7 +56,7 @@ def wait_until_alive(cls): cls.fetch_url(url) except Exception as e: if not cls.notebook_thread.is_alive(): - raise RuntimeError("The notebook server failed to start") + raise RuntimeError("The notebook server failed to start") from e time.sleep(POLL_INTERVAL) else: return diff --git a/notebook/tests/selenium/quick_selenium.py b/notebook/tests/selenium/quick_selenium.py index 10e46e1f32..e5c1ab7270 100644 --- a/notebook/tests/selenium/quick_selenium.py +++ b/notebook/tests/selenium/quick_selenium.py @@ -27,7 +27,7 @@ def quick_driver(lab=False): server = list(list_running_servers())[0] except IndexError as e: raise NoServerError('You need a server running before you can run ' - 'this command') + 'this command') from e driver = Firefox() auth_url = '{url}?token={token}'.format(**server) driver.get(auth_url)