def test_help_output_redirect(self): # issue 940286, if output is set in Helper, then all output from # Helper.help should be redirected old_pattern = expected_text_pattern getpager_old = pydoc.getpager getpager_new = lambda: (lambda x: x) self.maxDiff = None buf = StringIO() helper = pydoc.Helper(output=buf) unused, doc_loc = get_pydoc_text(pydoc_mod) module = "test.pydoc_mod" help_header = """ Help on module test.pydoc_mod in test: """.lstrip() help_header = textwrap.dedent(help_header) expected_help_pattern = help_header + expected_text_pattern pydoc.getpager = getpager_new try: with captured_output('stdout') as output, \ captured_output('stderr') as err: helper.help(module) result = buf.getvalue().strip() expected_text = expected_help_pattern % ( (doc_loc,) + expected_text_data_docstrings + (inspect.getabsfile(pydoc_mod),)) self.assertEqual('', output.getvalue()) self.assertEqual('', err.getvalue()) self.assertEqual(expected_text, result) finally: pydoc.getpager = getpager_old
def test_badisinstance(self): # Bug #2542: if issubclass(e, MyException) raises an exception, # it should be ignored class Meta(type): def __subclasscheck__(cls, subclass): raise ValueError() class MyException(Exception, metaclass=Meta): pass with captured_output("stderr") as stderr: try: raise KeyError() except MyException as e: self.fail("exception should not be a MyException") except KeyError: pass except: self.fail("Should have raised KeyError") else: self.fail("Should have raised KeyError") def g(): try: return g() except RuntimeError: return sys.exc_info() e, v, tb = g() self.assertTrue(isinstance(v, RuntimeError), type(v)) self.assertIn("maximum recursion depth exceeded", str(v))
def get_report(self, e): e = self.get_exception(e) s = ''.join(traceback.format_exception(type(e), e, e.__traceback__)) with captured_output("stderr") as sio: traceback.print_exception(type(e), e, e.__traceback__) self.assertEqual(sio.getvalue(), s) return s
def test_unhashable(self): from _testcapi import exception_print class UnhashableException(Exception): def __eq__(self, other): return True ex1 = UnhashableException('ex1') ex2 = UnhashableException('ex2') try: raise ex2 from ex1 except UnhashableException: try: raise ex1 except UnhashableException: exc_type, exc_val, exc_tb = sys.exc_info() with captured_output("stderr") as stderr_f: exception_print(exc_val) tb = stderr_f.getvalue().strip().splitlines() self.assertEqual(11, len(tb)) self.assertEqual(context_message.strip(), tb[5]) self.assertIn('UnhashableException: ex2', tb[3]) self.assertIn('UnhashableException: ex1', tb[10])
def get_report(self, e): from _testcapi import exception_print e = self.get_exception(e) with captured_output("stderr") as s: exception_print(e) return s.getvalue()
def test_before_stop_fails(self): if captured_output: with captured_output('stdout'): yield self._test_hooks(behavior=ERROR, status='stopped', hook_name='before_stop', call=self._stop)
def test_badisinstance(self): # Bug #2542: if issubclass(e, MyException) raises an exception, # it should be ignored class Meta(type): def __subclasscheck__(cls, subclass): raise ValueError() class MyException(Exception, metaclass=Meta): pass with captured_output("stderr") as stderr: try: raise KeyError() except MyException as e: self.fail("exception should not be a MyException") except KeyError: pass except: self.fail("Should have raised KeyError") else: self.fail("Should have raised KeyError") def g(): try: return g() except RuntimeError: return sys.exc_info() e, v, tb = g() self.assertTrue(isinstance(v, RuntimeError), type(v)) self.assertTrue("maximum recursion depth exceeded" in str(v), str(v))
def test_after_spawn_failure(self): if captured_output: with captured_output('stdout'): yield self._test_hooks(behavior=ERROR, status='stopped', hook_name='after_spawn', call=self._stop)
def get_report(self, e): e = self.get_exception(e) s = "".join(traceback.format_exception(type(e), e, e.__traceback__)) with captured_output("stderr") as sio: traceback.print_exception(type(e), e, e.__traceback__) self.assertEqual(sio.getvalue(), s) return s
def test_stack_format(self): with captured_output('stderr') as ststderr: traceback.print_stack(sys._getframe(1)) stfile = StringIO() traceback.print_stack(sys._getframe(1), file=stfile) self.assertEqual(ststderr.getvalue(), stfile.getvalue()) stfmt = traceback.format_stack(sys._getframe(1)) self.assertEqual(ststderr.getvalue(), ''.join(stfmt))
def test_showwarning_not_callable(self): with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings("always", category=UserWarning) self.module.showwarning = print with support.captured_output('stdout'): self.module.warn('Warning!') self.module.showwarning = 23 self.assertRaises(TypeError, self.module.warn, "Warning!")
def test_showwarnmsg_missing(self): text = 'del _showwarnmsg test' with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings('always', category=UserWarning) del self.module._showwarnmsg with support.captured_output('stderr') as stream: self.module.warn(text) result = stream.getvalue() self.assertIn(text, result)
def test_slow(self): # Verify the behavior of the timer's thread under load. MT = self.timer(self.increment, 0.125) with support.captured_output('stderr') as stderr: MT.start() time.sleep(0.5) MT.stop() time.sleep(0.25) self.assert_(self.slow(), 'ValueError: Count') self.assert_(self.test(stderr.getvalue()), 'IOError: Thread')
def test_showwarning_missing(self): # Test that showwarning() missing is okay. text = 'del showwarning test' with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings("always", category=UserWarning) del self.module.showwarning with support.captured_output('stderr') as stream: self.module.warn(text) result = stream.getvalue() self.assertIn(text, result)
def test_showwarnmsg_missing(self): # Test that _showwarnmsg() missing is okay. text = 'del _showwarnmsg test' with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings("always", category=UserWarning) del self.module._showwarnmsg with support.captured_output('stderr') as stream: self.module.warn(text) result = stream.getvalue() self.assertIn(text, result)
def check_traceback_format(self, cleanup_func=None): from _testcapi import traceback_print try: self.some_exception() except KeyError: type_, value, tb = sys.exc_info() if cleanup_func is not None: # Clear the inner frames, not this one cleanup_func(tb.tb_next) traceback_fmt = "Traceback (most recent call last):\n" + "".join(traceback.format_tb(tb)) file_ = StringIO() traceback_print(tb, file_) python_fmt = file_.getvalue() # Call all _tb and _exc functions with captured_output("stderr") as tbstderr: traceback.print_tb(tb) tbfile = StringIO() traceback.print_tb(tb, file=tbfile) with captured_output("stderr") as excstderr: traceback.print_exc() excfmt = traceback.format_exc() excfile = StringIO() traceback.print_exc(file=excfile) else: raise Error("unable to create test traceback string") # Make sure that Python and the traceback module format the same thing self.assertEqual(traceback_fmt, python_fmt) # Now verify the _tb func output self.assertEqual(tbstderr.getvalue(), tbfile.getvalue()) # Now verify the _exc func output self.assertEqual(excstderr.getvalue(), excfile.getvalue()) self.assertEqual(excfmt, excfile.getvalue()) # Make sure that the traceback is properly indented. tb_lines = python_fmt.splitlines() self.assertEqual(len(tb_lines), 5) banner = tb_lines[0] location, source_line = tb_lines[-2:] self.assertTrue(banner.startswith("Traceback")) self.assertTrue(location.startswith(" File")) self.assertTrue(source_line.startswith(" raise"))
def check_traceback_format(self, cleanup_func=None): from _testcapi import traceback_print try: self.some_exception() except KeyError: type_, value, tb = sys.exc_info() if cleanup_func is not None: # Clear the inner frames, not this one cleanup_func(tb.tb_next) traceback_fmt = 'Traceback (most recent call last):\n' + \ ''.join(traceback.format_tb(tb)) file_ = StringIO() traceback_print(tb, file_) python_fmt = file_.getvalue() # Call all _tb and _exc functions with captured_output("stderr") as tbstderr: traceback.print_tb(tb) tbfile = StringIO() traceback.print_tb(tb, file=tbfile) with captured_output("stderr") as excstderr: traceback.print_exc() excfmt = traceback.format_exc() excfile = StringIO() traceback.print_exc(file=excfile) else: raise Error("unable to create test traceback string") # Make sure that Python and the traceback module format the same thing self.assertEqual(traceback_fmt, python_fmt) # Now verify the _tb func output self.assertEqual(tbstderr.getvalue(), tbfile.getvalue()) # Now verify the _exc func output self.assertEqual(excstderr.getvalue(), excfile.getvalue()) self.assertEqual(excfmt, excfile.getvalue()) # Make sure that the traceback is properly indented. tb_lines = python_fmt.splitlines() self.assertEqual(len(tb_lines), 5) banner = tb_lines[0] location, source_line = tb_lines[-2:] self.assertTrue(banner.startswith('Traceback')) self.assertTrue(location.startswith(' File')) self.assertTrue(source_line.startswith(' raise'))
def test_addpackage_import_bad_pth_file(self): # Issue 5258 pth_dir, pth_fn = self.make_pth("abc\x00def\n") with captured_output("stderr") as err_out: site.addpackage(pth_dir, pth_fn, set()) self.assertRegex(err_out.getvalue(), "line 1") self.assertRegex(err_out.getvalue(), re.escape(os.path.join(pth_dir, pth_fn))) # XXX: ditto previous XXX comment. self.assertRegex(err_out.getvalue(), 'Traceback') self.assertRegex(err_out.getvalue(), 'TypeError')
def test_addpackage_import_bad_exec(self): # Issue 10642 pth_dir, pth_fn = self.make_pth("randompath\nimport nosuchmodule\n") with captured_output("stderr") as err_out: site.addpackage(pth_dir, pth_fn, set()) self.assertRegex(err_out.getvalue(), "line 2") self.assertRegex(err_out.getvalue(), re.escape(os.path.join(pth_dir, pth_fn))) # XXX: ditto previous XXX comment. self.assertRegex(err_out.getvalue(), 'Traceback') self.assertRegex(err_out.getvalue(), 'ImportError')
def test_excepthook(self): with support.captured_output("stderr") as stderr: thread = ThreadRunFail(name="excepthook thread") thread.start() thread.join() stderr = stderr.getvalue().strip() self.assertIn(f'Exception in thread {thread.name}:\n', stderr) self.assertIn('Traceback (most recent call last):\n', stderr) self.assertIn(' raise ValueError("run failed")', stderr) self.assertIn('ValueError: run failed', stderr)
def test_print_stack(self): def prn(): traceback.print_stack() with captured_output("stderr") as stderr: prn() lineno = prn.__code__.co_firstlineno self.assertEqual(stderr.getvalue().splitlines()[-4:], [ ' File "%s", line %d, in test_print_stack' % (__file__, lineno+3), ' prn()', ' File "%s", line %d, in prn' % (__file__, lineno+1), ' traceback.print_stack()', ])
def test_stack_format(self): # Verify _stack functions. Note we have to use _getframe(1) to # compare them without this frame appearing in the output with captured_output("stderr") as ststderr: traceback.print_stack(sys._getframe(1)) stfile = StringIO() traceback.print_stack(sys._getframe(1), file=stfile) self.assertEqual(ststderr.getvalue(), stfile.getvalue()) stfmt = traceback.format_stack(sys._getframe(1)) self.assertEqual(ststderr.getvalue(), "".join(stfmt))
def test_system_exit(self): class ThreadExit(threading.Thread): def run(self): sys.exit(1) # threading.excepthook() silently ignores SystemExit with support.captured_output("stderr") as stderr: thread = ThreadExit() thread.start() thread.join() self.assertEqual(stderr.getvalue(), '')
def test_addpackage_import_bad_syntax(self): # Issue 10642 pth_dir, pth_fn = self.make_pth("import bad)syntax\n") with captured_output("stderr") as err_out: site.addpackage(pth_dir, pth_fn, set()) self.assertRegex(err_out.getvalue(), "line 1") self.assertRegex(err_out.getvalue(), re.escape(os.path.join(pth_dir, pth_fn))) # XXX: the previous two should be independent checks so that the # order doesn't matter. The next three could be a single check # but my regex foo isn't good enough to write it. self.assertRegex(err_out.getvalue(), 'Traceback') self.assertRegex(err_out.getvalue(), r'import bad\)syntax') self.assertRegex(err_out.getvalue(), 'SyntaxError')
def test_excepthook_thread_None(self): # threading.excepthook called with thread=None: log the thread # identifier in this case. with support.captured_output("stderr") as stderr: try: raise ValueError("bug") except Exception as exc: args = threading.ExceptHookArgs([*sys.exc_info(), None]) threading.excepthook(args) stderr = stderr.getvalue().strip() self.assertIn(f'Exception in thread {threading.get_ident()}:\n', stderr) self.assertIn('Traceback (most recent call last):\n', stderr) self.assertIn(' raise ValueError("bug")', stderr) self.assertIn('ValueError: bug', stderr)
def test_custom_excepthook_fail(self): def threading_hook(args): raise ValueError("threading_hook failed") err_str = None def sys_hook(exc_type, exc_value, exc_traceback): nonlocal err_str err_str = str(exc_value) with support.swap_attr(threading, 'excepthook', threading_hook), \ support.swap_attr(sys, 'excepthook', sys_hook), \ support.captured_output('stderr') as stderr: thread = ThreadRunFail() thread.start() thread.join() self.assertEqual(stderr.getvalue(), 'Exception in threading.excepthook:\n') self.assertEqual(err_str, 'threading_hook failed')
def test_save_exception_state_on_error(self): # See issue #14474 def task(): started.release() raise SyntaxError def mywrite(self, *args): try: raise ValueError except ValueError: pass real_write(self, *args) started = thread.allocate_lock() with support.captured_output("stderr") as stderr: real_write = stderr.write stderr.write = mywrite started.acquire() with support.wait_threads_exit(): thread.start_new_thread(task, ()) started.acquire() self.assertIn("Traceback", stderr.getvalue())
def test_save_exception_state_on_error(self): # See issue #14474 def task(): started.release() raise SyntaxError def mywrite(self, *args): try: raise ValueError except ValueError: pass real_write(self, *args) c = thread._count() started = thread.allocate_lock() with support.captured_output("stderr") as stderr: real_write = stderr.write stderr.write = mywrite started.acquire() with support.wait_threads_exit(): thread.start_new_thread(task, ()) started.acquire() self.assertIn("Traceback", stderr.getvalue())
def test_show_warning_output(self): # With showarning() missing, make sure that output is okay. text = "test show_warning" with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings("always", category=UserWarning) del self.module.showwarning with support.captured_output("stderr") as stream: warning_tests.inner(text) result = stream.getvalue() self.assertEqual(result.count("\n"), 2, "Too many newlines in %r" % result) first_line, second_line = result.split("\n", 1) expected_file = os.path.splitext(warning_tests.__file__)[0] + ".py" first_line_parts = first_line.rsplit(":", 3) path, line, warning_class, message = first_line_parts line = int(line) self.assertEqual(expected_file, path) self.assertEqual(warning_class, " " + UserWarning.__name__) self.assertEqual(message, " " + text) expected_line = " " + linecache.getline(path, line).strip() + "\n" assert expected_line self.assertEqual(second_line, expected_line)
def test_show_warning_output(self): text = 'test show_warning' with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings('always', category=UserWarning) del self.module.showwarning with support.captured_output('stderr') as stream: warning_tests.inner(text) result = stream.getvalue() self.assertEqual(result.count('\n'), 2, 'Too many newlines in %r' % result) first_line, second_line = result.split('\n', 1) expected_file = os.path.splitext(warning_tests.__file__)[0] + '.py' first_line_parts = first_line.rsplit(':', 3) path, line, warning_class, message = first_line_parts line = int(line) self.assertEqual(expected_file, path) self.assertEqual(warning_class, ' ' + UserWarning.__name__) self.assertEqual(message, ' ' + text) expected_line = ' ' + linecache.getline(path, line).strip() + '\n' assert expected_line self.assertEqual(second_line, expected_line)
def test_3611(self): class C: def __del__(self): try: 1 / 0 except: raise def f(): x = C() try: try: x.x except AttributeError: del x raise TypeError except Exception as e: self.assertNotEqual(e.__context__, None) self.assertIsInstance(e.__context__, AttributeError) with support.captured_output('stderr'): f()
def test_show_warning_output(self): # With showarning() missing, make sure that output is okay. text = 'test show_warning' with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings("always", category=UserWarning) del self.module.showwarning with support.captured_output('stderr') as stream: warning_tests.inner(text) result = stream.getvalue() self.assertEqual(result.count('\n'), 2, "Too many newlines in %r" % result) first_line, second_line = result.split('\n', 1) expected_file = warning_tests_py first_line_parts = first_line.rsplit(':', 3) path, line, warning_class, message = first_line_parts line = int(line) self.assertEqual(expected_file, path) self.assertEqual(warning_class, ' ' + UserWarning.__name__) self.assertEqual(message, ' ' + text) expected_line = ' ' + linecache.getline(path, line).strip() + '\n' assert expected_line self.assertEqual(second_line, expected_line)
def test_fatal_error(self): eq = self.assertEqual with captured_output('__stderr__') as err,\ mock.patch('idlelib.run.thread.interrupt_main', new_callable=Func) as func: try: raise EOFError except EOFError: run.MyRPCServer.handle_error(None, 'abc', '123') eq(run.exit_now, True) run.exit_now = False eq(err.getvalue(), '') try: raise IndexError except IndexError: run.MyRPCServer.handle_error(None, 'abc', '123') eq(run.quitting, True) run.quitting = False msg = err.getvalue() self.assertIn('abc', msg) self.assertIn('123', msg) self.assertIn('IndexError', msg) eq(func.called, 2)
def test_3611(self): # A re-raised exception in a __del__ caused the __context__ # to be cleared class C: def __del__(self): try: 1 / 0 except: raise def f(): x = C() try: try: x.x except AttributeError: del x raise TypeError except Exception as e: self.assertNotEqual(e.__context__, None) self.assertIsInstance(e.__context__, AttributeError) with support.captured_output("stderr"): f()
def test_3611(self): # A re-raised exception in a __del__ caused the __context__ # to be cleared class C: def __del__(self): try: 1/0 except: raise def f(): x = C() try: try: x.x except AttributeError: del x raise TypeError except Exception as e: self.assertNotEqual(e.__context__, None) self.assertIsInstance(e.__context__, AttributeError) with support.captured_output("stderr"): f()
def test_after_start_fails(self): if captured_output: with captured_output('stderr'): yield self._test_hooks(behavior=ERROR, status='stopped', hook_name='after_start')
def _check_recursive_traceback_display(self, render_exc): self.maxDiff = None def f(): f() with captured_output('stderr') as stderr_f: try: f() except RecursionError as exc: render_exc() else: self.fail('no recursion occurred') lineno_f = f.__code__.co_firstlineno result_f = f"""Traceback (most recent call last): File "{__file__}", line {(lineno_f + 5)}, in _check_recursive_traceback_display f() File "{__file__}", line {(lineno_f + 1)}, in f f() File "{__file__}", line {(lineno_f + 1)}, in f f() File "{__file__}", line {(lineno_f + 1)}, in f f() \\[Previous line repeated (\\d+) more times\\] RecursionError: maximum recursion depth exceeded """ expected = result_f.splitlines() actual = stderr_f.getvalue().splitlines() self.assertEqual(actual[:-2], expected[:-2]) self.assertRegex(actual[-2], expected[-2]) self.assertEqual(actual[-1], expected[-1]) rec_limit = sys.getrecursionlimit() self.assertIn(int(re.search('\\d+', actual[-2]).group()), range(rec_limit - 60, rec_limit)) def g(count=10): if count: return g(count - 1) raise ValueError with captured_output('stderr') as stderr_g: try: g() except ValueError as exc: render_exc() else: self.fail('no value error was raised') lineno_g = g.__code__.co_firstlineno result_g = f""" File "{__file__}", line {(lineno_g + 2)}, in g return g(count-1) File "{__file__}", line {(lineno_g + 2)}, in g return g(count-1) File "{__file__}", line {(lineno_g + 2)}, in g return g(count-1) [Previous line repeated 6 more times] File "{__file__}", line {(lineno_g + 3)}, in g raise ValueError ValueError """ tb_line = f"""Traceback (most recent call last): File "{__file__}", line {(lineno_g + 7)}, in _check_recursive_traceback_display g() """ expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected) def h(count=10): if count: return h(count - 1) g() with captured_output('stderr') as stderr_h: try: h() except ValueError as exc: render_exc() else: self.fail('no value error was raised') lineno_h = h.__code__.co_firstlineno result_h = f"""Traceback (most recent call last): File "{__file__}", line {(lineno_h + 7)}, in _check_recursive_traceback_display h() File "{__file__}", line {(lineno_h + 2)}, in h return h(count-1) File "{__file__}", line {(lineno_h + 2)}, in h return h(count-1) File "{__file__}", line {(lineno_h + 2)}, in h return h(count-1) [Previous line repeated 6 more times] File "{__file__}", line {(lineno_h + 3)}, in h g() """ expected = (result_h + result_g).splitlines() actual = stderr_h.getvalue().splitlines() self.assertEqual(actual, expected)
def _check_recursive_traceback_display(self, render_exc): # Always show full diffs when this test fails # Note that rearranging things may require adjusting # the relative line numbers in the expected tracebacks self.maxDiff = None # Check hitting the recursion limit def f(): f() with captured_output("stderr") as stderr_f: try: f() except RecursionError: render_exc() else: self.fail("no recursion occurred") lineno_f = f.__code__.co_firstlineno result_f = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n' ' f()\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' # XXX: The following line changes depending on whether the tests # are run through the interactive interpreter or with -m # It also varies depending on the platform (stack size) # Fortunately, we don't care about exactness here, so we use regex r' \[Previous line repeated (\d+) more times\]' '\n' 'RecursionError: maximum recursion depth exceeded\n' ) expected = result_f.splitlines() actual = stderr_f.getvalue().splitlines() # Check the output text matches expectations # 2nd last line contains the repetition count self.assertEqual(actual[:-2], expected[:-2]) self.assertRegex(actual[-2], expected[-2]) # last line can have additional text appended self.assertIn(expected[-1], actual[-1]) # Check the recursion count is roughly as expected rec_limit = sys.getrecursionlimit() self.assertIn(int(re.search(r"\d+", actual[-2]).group()), range(rec_limit-60, rec_limit)) # Check a known (limited) number of recursive invocations def g(count=10): if count: return g(count-1) raise ValueError with captured_output("stderr") as stderr_g: try: g() except ValueError: render_exc() else: self.fail("no value error was raised") lineno_g = g.__code__.co_firstlineno result_g = ( f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' ' [Previous line repeated 7 more times]\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_g+7}, in _check_recursive_traceback_display\n' ' g()\n' ) expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected) # Check 2 different repetitive sections def h(count=10): if count: return h(count-1) g() with captured_output("stderr") as stderr_h: try: h() except ValueError: render_exc() else: self.fail("no value error was raised") lineno_h = h.__code__.co_firstlineno result_h = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_h+7}, in _check_recursive_traceback_display\n' ' h()\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' ' [Previous line repeated 7 more times]\n' f' File "{__file__}", line {lineno_h+3}, in h\n' ' g()\n' ) expected = (result_h + result_g).splitlines() actual = stderr_h.getvalue().splitlines() self.assertEqual(actual, expected) # Check the boundary conditions. First, test just below the cutoff. with captured_output("stderr") as stderr_g: try: g(traceback._RECURSIVE_CUTOFF) except ValueError: render_exc() else: self.fail("no error raised") result_g = ( f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_g+71}, in _check_recursive_traceback_display\n' ' g(traceback._RECURSIVE_CUTOFF)\n' ) expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected) # Second, test just above the cutoff. with captured_output("stderr") as stderr_g: try: g(traceback._RECURSIVE_CUTOFF + 1) except ValueError: render_exc() else: self.fail("no error raised") result_g = ( f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' ' [Previous line repeated 1 more time]\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_g+99}, in _check_recursive_traceback_display\n' ' g(traceback._RECURSIVE_CUTOFF + 1)\n' ) expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected)
def test_print_function(self): with support.captured_output("stderr") as s: print("foo", file=sys.stderr) self.assertEqual(s.getvalue(), "foo\n")
def _check_recursive_traceback_display(self, render_exc): # Always show full diffs when this test fails # Note that rearranging things may require adjusting # the relative line numbers in the expected tracebacks self.maxDiff = None # Check hitting the recursion limit def f(): f() with captured_output("stderr") as stderr_f: try: f() except RecursionError as exc: render_exc() else: self.fail("no recursion occurred") lineno_f = f.__code__.co_firstlineno result_f = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_f+5}, in _check_recursive_traceback_display\n' ' f()\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' f' File "{__file__}", line {lineno_f+1}, in f\n' ' f()\n' # XXX: The following line changes depending on whether the tests # are run through the interactive interpreter or with -m # It also varies depending on the platform (stack size) # Fortunately, we don't care about exactness here, so we use regex r' \[Previous line repeated (\d+) more times\]' '\n' 'RecursionError: maximum recursion depth exceeded\n' ) expected = result_f.splitlines() actual = stderr_f.getvalue().splitlines() # Check the output text matches expectations # 2nd last line contains the repetition count self.assertEqual(actual[:-2], expected[:-2]) self.assertRegex(actual[-2], expected[-2]) self.assertEqual(actual[-1], expected[-1]) # Check the recursion count is roughly as expected rec_limit = sys.getrecursionlimit() self.assertIn(int(re.search(r"\d+", actual[-2]).group()), range(rec_limit-50, rec_limit)) # Check a known (limited) number of recursive invocations def g(count=10): if count: return g(count-1) raise ValueError with captured_output("stderr") as stderr_g: try: g() except ValueError as exc: render_exc() else: self.fail("no value error was raised") lineno_g = g.__code__.co_firstlineno result_g = ( f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' f' File "{__file__}", line {lineno_g+2}, in g\n' ' return g(count-1)\n' ' [Previous line repeated 6 more times]\n' f' File "{__file__}", line {lineno_g+3}, in g\n' ' raise ValueError\n' 'ValueError\n' ) tb_line = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_g+7}, in _check_recursive_traceback_display\n' ' g()\n' ) expected = (tb_line + result_g).splitlines() actual = stderr_g.getvalue().splitlines() self.assertEqual(actual, expected) # Check 2 different repetitive sections def h(count=10): if count: return h(count-1) g() with captured_output("stderr") as stderr_h: try: h() except ValueError as exc: render_exc() else: self.fail("no value error was raised") lineno_h = h.__code__.co_firstlineno result_h = ( 'Traceback (most recent call last):\n' f' File "{__file__}", line {lineno_h+7}, in _check_recursive_traceback_display\n' ' h()\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' f' File "{__file__}", line {lineno_h+2}, in h\n' ' return h(count-1)\n' ' [Previous line repeated 6 more times]\n' f' File "{__file__}", line {lineno_h+3}, in h\n' ' g()\n' ) expected = (result_h + result_g).splitlines() actual = stderr_h.getvalue().splitlines() self.assertEqual(actual, expected)