From a834bb295a262bd9ff172748afa9c2a75a1d5a52 Mon Sep 17 00:00:00 2001 From: Andrew Hoos Date: Tue, 29 Nov 2016 07:01:48 -0800 Subject: Explicitely call sys.excepthook https://bitbucket.org/ned/coveragepy/issues/535/sysexcepthook-is-not-called --- coverage/execfile.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/coverage/execfile.py b/coverage/execfile.py index 3e20a52..39d17e9 100644 --- a/coverage/execfile.py +++ b/coverage/execfile.py @@ -192,8 +192,7 @@ def run_python_file(filename, args, package=None, modulename=None, path0=None): # and a nested exception is shown to the user. This getattr fixes # it somehow? https://bitbucket.org/pypy/pypy/issue/1903 getattr(err, '__context__', None) - - raise ExceptionDuringRun(typ, err, tb.tb_next) + sys.excepthook(typ, err, tb.tb_next) finally: # Restore the old __main__, argv, and path. sys.modules['__main__'] = old_main_mod -- cgit v1.2.1 From 27a52632dfb7cddc24506862383c406d31362beb Mon Sep 17 00:00:00 2001 From: Andrew Hoos Date: Tue, 29 Nov 2016 08:07:05 -0800 Subject: Update handling of sys.excepthook to only call custom excepthooks and re-raise exceptions --- coverage/execfile.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/coverage/execfile.py b/coverage/execfile.py index 39d17e9..8ff3877 100644 --- a/coverage/execfile.py +++ b/coverage/execfile.py @@ -192,7 +192,12 @@ def run_python_file(filename, args, package=None, modulename=None, path0=None): # and a nested exception is shown to the user. This getattr fixes # it somehow? https://bitbucket.org/pypy/pypy/issue/1903 getattr(err, '__context__', None) - sys.excepthook(typ, err, tb.tb_next) + + # call a custom user excepthook if it is provided + if sys.excepthook is not sys.__excepthook__: + sys.excepthook(typ, err, tb.tb_next) + raise ExceptionDuringRun(typ, err, tb.tb_next) + finally: # Restore the old __main__, argv, and path. sys.modules['__main__'] = old_main_mod -- cgit v1.2.1 From b02f118d6f1e43113f6ea4a7d0ad750ff5cf7edb Mon Sep 17 00:00:00 2001 From: Andrew Hoos Date: Tue, 29 Nov 2016 17:52:50 -0800 Subject: Update code to better handle calling sys.excepthook when it throws --- coverage/cmdline.py | 5 +---- coverage/execfile.py | 9 ++++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 8942024..bbddf0a 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -754,10 +754,7 @@ def main(argv=None): try: status = CoverageScript().command_line(argv) except ExceptionDuringRun as err: - # An exception was caught while running the product code. The - # sys.exc_info() return tuple is packed into an ExceptionDuringRun - # exception. - traceback.print_exception(*err.args) + # An exception was caught while running the product code. status = ERR except CoverageException as err: # A controlled error inside coverage.py: print the message to the user. diff --git a/coverage/execfile.py b/coverage/execfile.py index 8ff3877..d1aa252 100644 --- a/coverage/execfile.py +++ b/coverage/execfile.py @@ -6,6 +6,7 @@ import marshal import os import sys +import traceback import types from coverage.backward import BUILTINS @@ -195,7 +196,13 @@ def run_python_file(filename, args, package=None, modulename=None, path0=None): # call a custom user excepthook if it is provided if sys.excepthook is not sys.__excepthook__: - sys.excepthook(typ, err, tb.tb_next) + try: + sys.excepthook(typ, err, tb.tb_next) + except SystemExit: + raise + except: + typ, err, tb = sys.exc_info() + traceback.print_exception(typ, err, tb.tb_next) raise ExceptionDuringRun(typ, err, tb.tb_next) finally: -- cgit v1.2.1 From ae77a6b8880f036e8006ca75da4b9b4946f7d18d Mon Sep 17 00:00:00 2001 From: Andrew Hoos Date: Tue, 29 Nov 2016 17:56:47 -0800 Subject: Limit changes to only execfile.py --- coverage/cmdline.py | 5 ++++- coverage/execfile.py | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/coverage/cmdline.py b/coverage/cmdline.py index bbddf0a..8942024 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -754,7 +754,10 @@ def main(argv=None): try: status = CoverageScript().command_line(argv) except ExceptionDuringRun as err: - # An exception was caught while running the product code. + # An exception was caught while running the product code. The + # sys.exc_info() return tuple is packed into an ExceptionDuringRun + # exception. + traceback.print_exception(*err.args) status = ERR except CoverageException as err: # A controlled error inside coverage.py: print the message to the user. diff --git a/coverage/execfile.py b/coverage/execfile.py index d1aa252..fbb829f 100644 --- a/coverage/execfile.py +++ b/coverage/execfile.py @@ -202,7 +202,6 @@ def run_python_file(filename, args, package=None, modulename=None, path0=None): raise except: typ, err, tb = sys.exc_info() - traceback.print_exception(typ, err, tb.tb_next) raise ExceptionDuringRun(typ, err, tb.tb_next) finally: -- cgit v1.2.1 From d1da15f12e248954adc1d6bf222304ba1e16f9d9 Mon Sep 17 00:00:00 2001 From: Andrew Hoos Date: Tue, 29 Nov 2016 17:57:49 -0800 Subject: Remove the unused import --- coverage/execfile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/coverage/execfile.py b/coverage/execfile.py index fbb829f..4db737c 100644 --- a/coverage/execfile.py +++ b/coverage/execfile.py @@ -6,7 +6,6 @@ import marshal import os import sys -import traceback import types from coverage.backward import BUILTINS -- cgit v1.2.1 From 8ccdedf3ec46cb51130af886be36b85b9e3015b7 Mon Sep 17 00:00:00 2001 From: Andrew Hoos Date: Wed, 30 Nov 2016 15:07:51 -0800 Subject: Update change with tests and fixes for tests --- coverage/execfile.py | 17 ++++++++------- tests/test_process.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/coverage/execfile.py b/coverage/execfile.py index 4db737c..5633c59 100644 --- a/coverage/execfile.py +++ b/coverage/execfile.py @@ -194,14 +194,15 @@ def run_python_file(filename, args, package=None, modulename=None, path0=None): getattr(err, '__context__', None) # call a custom user excepthook if it is provided - if sys.excepthook is not sys.__excepthook__: - try: - sys.excepthook(typ, err, tb.tb_next) - except SystemExit: - raise - except: - typ, err, tb = sys.exc_info() - raise ExceptionDuringRun(typ, err, tb.tb_next) + try: + sys.excepthook(typ, err, tb.tb_next) + except SystemExit: + raise + except: + typ, err, tb = sys.exc_info() + raise ExceptionDuringRun(typ, err, tb.tb_next) + else: + sys.exit(1) finally: # Restore the old __main__, argv, and path. diff --git a/tests/test_process.py b/tests/test_process.py index 75d420a..dda43ba 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -785,6 +785,66 @@ class ProcessTest(CoverageTest): out = self.run_command("python -m coverage") self.assertIn("Use 'coverage help' for help", out) + def test_excepthook(self): + self.make_file("test_excepthook.py", """\ + import sys + + def excepthook(*args): + print('in excepthook') + + sys.excepthook = excepthook + + raise RuntimeError('Error Outside') + """) + cov_st, cov_out = self.run_command_status("coverage run test_excepthook.py") + py_st, py_out = self.run_command_status("python test_excepthook.py") + self.assertEqual(cov_st, py_st) + self.assertEqual(cov_st, 1) + + self.assertIn("in excepthook", py_out) + self.assertEqual(cov_out, py_out) + + def test_excepthook_exit(self): + self.make_file("test_excepthook_exit.py", """\ + import sys + + def excepthook(*args): + print('in excepthook') + sys.exit(0) + + sys.excepthook = excepthook + + raise RuntimeError('Error Outside') + """) + cov_st, cov_out = self.run_command_status("coverage run test_excepthook_exit.py") + py_st, py_out = self.run_command_status("python test_excepthook_exit.py") + self.assertEqual(cov_st, py_st) + self.assertEqual(cov_st, 0) + + self.assertIn("in excepthook", py_out) + self.assertEqual(cov_out, py_out) + + def test_excepthook_throw(self): + self.make_file("test_excepthook_exit.py", """\ + import sys + + def excepthook(*args): + print('in excepthook') + raise RuntimeError('Error Inside') + + sys.excepthook = excepthook + + raise RuntimeError('Error Outside') + """) + cov_st, cov_out = self.run_command_status("coverage run test_excepthook_exit.py") + py_st, py_out = self.run_command_status("python test_excepthook_exit.py") + self.assertEqual(cov_st, py_st) + self.assertEqual(cov_st, 0) + + self.assertIn("in excepthook", py_out) + self.assertEqual(cov_out, py_out) + + class AliasedCommandTest(CoverageTest): """Tests of the version-specific command aliases.""" -- cgit v1.2.1