From b0839c91da7b29a7412c373326e1ab05f23a5afc Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Mon, 26 Apr 2021 10:27:16 +0300 Subject: [PATCH] gh-70280: allow using custom sys.displayhook's with doctest This partially reverts patch from https://bugs.python.org/issue8048 Now it's possible to test interactive examples in applications, which use cusomized sys.displayhook, e.g. SymPy, without nasty workarrounds (i.e. overriding the sys.__displayhook__ value before each tests). --- Doc/library/doctest.rst | 4 ++ Lib/doctest.py | 3 +- Lib/test/test_doctest.py | 41 ++++++++++++------- .../2021-04-27-08-36-50.bpo-26092.1qLzp5.rst | 2 + 4 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-04-27-08-36-50.bpo-26092.1qLzp5.rst diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst index ad013944ce3ca3..349410b8111836 100644 --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -1562,6 +1562,10 @@ DocTestRunner objects output checker, and the results are formatted by the :meth:`DocTestRunner.report_\*` methods. + .. versionchanged:: 3.13 + Added support for testing examples with a customized + :func:`sys.displayhook` value. Previously, this wasn't allowed and + the method was always using the :func:`sys.__displayhook__`. .. method:: summarize(verbose=None) diff --git a/Lib/doctest.py b/Lib/doctest.py index 2f14aa08334895..fa33e9d44b2f70 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1533,9 +1533,8 @@ def out(s): self.save_linecache_getlines = linecache.getlines linecache.getlines = self.__patched_linecache_getlines - # Make sure sys.displayhook just prints the value to stdout + # Make sure sys.displayhook restored at the end save_displayhook = sys.displayhook - sys.displayhook = sys.__displayhook__ try: return self.__run(test, compileflags, out) diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index cb4e2157bb228b..4d07a39cac3915 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -1220,33 +1220,46 @@ def exceptions(): r""" TestResults(failed=1, attempted=1) """ def displayhook(): r""" -Test that changing sys.displayhook doesn't matter for doctest. +Test changing sys.displayhook. + +Run with a custom displayhook: >>> import sys - >>> orig_displayhook = sys.displayhook >>> def my_displayhook(x): ... print('hi!') + ... sys.__displayhook__(x) >>> sys.displayhook = my_displayhook + >>> 3 + hi! + 3 >>> def f(): ... ''' ... >>> 3 + ... hi! ... 3 ... ''' >>> test = doctest.DocTestFinder().find(f)[0] - >>> r = doctest.DocTestRunner(verbose=False).run(test) - >>> post_displayhook = sys.displayhook - - We need to restore sys.displayhook now, so that we'll be able to test - results. - - >>> sys.displayhook = orig_displayhook + >>> doctest.DocTestRunner(verbose=False).run(test) + hi! + TestResults(failed=0, attempted=1) + >>> sys.displayhook = sys.__displayhook__ + >>> 3 + 3 - Ok, now we can check that everything is ok. +Test changing displayhook in the doctest: - >>> r - TestResults(failed=0, attempted=1) - >>> post_displayhook is my_displayhook - True + >>> def g(): + ... ''' + ... >>> import sys + ... >>> sys.displayhook = lambda x: print('spam') + ... >>> 3 + ... spam + ... ''' + >>> test = doctest.DocTestFinder().find(g)[0] + >>> doctest.DocTestRunner(verbose=False).run(test) + TestResults(failed=0, attempted=3) + >>> 42 + 42 """ def optionflags(): r""" Tests of `DocTestRunner`'s option flag handling. diff --git a/Misc/NEWS.d/next/Library/2021-04-27-08-36-50.bpo-26092.1qLzp5.rst b/Misc/NEWS.d/next/Library/2021-04-27-08-36-50.bpo-26092.1qLzp5.rst new file mode 100644 index 00000000000000..e4c12bdfcf1093 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-04-27-08-36-50.bpo-26092.1qLzp5.rst @@ -0,0 +1,2 @@ +Allow using custom sys.displayhook's with doctest. Patch by Sergey B +Kirpichev.