]> granicus.if.org Git - python/commitdiff
Issue #10990: Prevent tests from clobbering a set trace function.
authorBrett Cannon <bcannon@gmail.com>
Mon, 21 Feb 2011 19:29:56 +0000 (19:29 +0000)
committerBrett Cannon <bcannon@gmail.com>
Mon, 21 Feb 2011 19:29:56 +0000 (19:29 +0000)
Many tests simply didn't care if they unset a pre-existing trace function. This
made test coverage impossible. This patch fixes various tests to put back any
pre-existing trace function. It also introduces test.support.no_tracing as a
decorator which will temporarily unset the trace function for tests which
simply fail otherwise.

Thanks to Kristian Vlaardingerbroek for helping to find the cause of various
trace function unsets.

15 files changed:
Lib/doctest.py
Lib/test/pickletester.py
Lib/test/regrtest.py
Lib/test/support.py
Lib/test/test_doctest.py
Lib/test/test_exceptions.py
Lib/test/test_io.py
Lib/test/test_pdb.py
Lib/test/test_richcmp.py
Lib/test/test_runpy.py
Lib/test/test_scope.py
Lib/test/test_sys_settrace.py
Lib/test/test_trace.py
Lib/test/test_zipimport_support.py
Misc/NEWS

index b79db17881e21892b6d3bde456b183a612554fdc..e8f3bcbe3bf754b4cea93b2f2be53ea8cdc5be76 100644 (file)
@@ -1373,6 +1373,7 @@ class DocTestRunner:
         # Note that the interactive output will go to *our*
         # save_stdout, even if that's not the real sys.stdout; this
         # allows us to write test cases for the set_trace behavior.
+        save_trace = sys.gettrace()
         save_set_trace = pdb.set_trace
         self.debugger = _OutputRedirectingPdb(save_stdout)
         self.debugger.reset()
@@ -1392,6 +1393,7 @@ class DocTestRunner:
         finally:
             sys.stdout = save_stdout
             pdb.set_trace = save_set_trace
+            sys.settrace(save_trace)
             linecache.getlines = self.save_linecache_getlines
             sys.displayhook = save_displayhook
             if clear_globs:
index 3ae7defa648533a9e1cddbfc59462feb17fb223a..353448919cdb6d175c0c0439da7ef25b0bde85ac 100644 (file)
@@ -5,7 +5,7 @@ import pickletools
 import copyreg
 from http.cookies import SimpleCookie
 
-from test.support import TestFailed, TESTFN, run_with_locale
+from test.support import TestFailed, TESTFN, run_with_locale, no_tracing
 
 from pickle import bytes_types
 
@@ -1002,6 +1002,7 @@ class AbstractPickleTests(unittest.TestCase):
             y = self.loads(s)
             self.assertEqual(y._reduce_called, 1)
 
+    @no_tracing
     def test_bad_getattr(self):
         x = BadGetattr()
         for proto in 0, 1:
index b5288b5072138436cf1bbddaf9e5ff9aaa1650fd..440c01d7ad54fcca534818e5743eab5129234924 100755 (executable)
@@ -827,7 +827,7 @@ class saved_test_environment:
     resources = ('sys.argv', 'cwd', 'sys.stdin', 'sys.stdout', 'sys.stderr',
                  'os.environ', 'sys.path', 'sys.path_hooks', '__import__',
                  'warnings.filters', 'asyncore.socket_map',
-                 'logging._handlers', 'logging._handlerList')
+                 'logging._handlers', 'logging._handlerList', 'sys.gettrace')
 
     def get_sys_argv(self):
         return id(sys.argv), sys.argv, sys.argv[:]
@@ -874,6 +874,11 @@ class saved_test_environment:
         sys.path_hooks = saved_hooks[1]
         sys.path_hooks[:] = saved_hooks[2]
 
+    def get_sys_gettrace(self):
+        return sys.gettrace()
+    def restore_sys_gettrace(self, trace_fxn):
+        sys.settrace(trace_fxn)
+
     def get___import__(self):
         return builtins.__import__
     def restore___import__(self, import_):
index ea5b9cbda46ec2a7ed6a9c6d9c19eab7ef5a6bcc..f037a7aed8a1f7c5afafb3bee746bf47a6b8cf08 100644 (file)
@@ -1108,6 +1108,21 @@ def check_impl_detail(**guards):
     return guards.get(platform.python_implementation().lower(), default)
 
 
+def no_tracing(func):
+    """Decorator to temporarily turn off tracing for the duration of a test."""
+    if not hasattr(sys, 'gettrace'):
+        return func
+    else:
+        @functools.wraps(func)
+        def wrapper(*args, **kwargs):
+            original_trace = sys.gettrace()
+            try:
+                sys.settrace(None)
+                return func(*args, **kwargs)
+            finally:
+                sys.settrace(original_trace)
+        return wrapper
+
 
 def _run_suite(suite):
     """Run tests from a unittest.TestSuite-derived class."""
index 484a9b8468a6bc05714457458ebd39fef3fd8706..b839556249a1ae5937c0e50075194c4fb580c99b 100644 (file)
@@ -5,6 +5,7 @@ Test script for doctest.
 from test import support
 import doctest
 import os
+import sys
 
 
 # NOTE: There are some additional tests relating to interaction with
@@ -373,7 +374,7 @@ We'll simulate a __file__ attr that ends in pyc:
     >>> tests = finder.find(sample_func)
 
     >>> print(tests)  # doctest: +ELLIPSIS
-    [<DocTest sample_func from ...:17 (1 example)>]
+    [<DocTest sample_func from ...:18 (1 example)>]
 
 The exact name depends on how test_doctest was invoked, so allow for
 leading path components.
@@ -1686,226 +1687,227 @@ Run the debugger on the docstring, and then restore sys.stdin.
 
 """
 
-def test_pdb_set_trace():
-    """Using pdb.set_trace from a doctest.
-
-    You can use pdb.set_trace from a doctest.  To do so, you must
-    retrieve the set_trace function from the pdb module at the time
-    you use it.  The doctest module changes sys.stdout so that it can
-    capture program output.  It also temporarily replaces pdb.set_trace
-    with a version that restores stdout.  This is necessary for you to
-    see debugger output.
-
-      >>> doc = '''
-      ... >>> x = 42
-      ... >>> raise Exception('clé')
-      ... Traceback (most recent call last):
-      ... Exception: clé
-      ... >>> import pdb; pdb.set_trace()
-      ... '''
-      >>> parser = doctest.DocTestParser()
-      >>> test = parser.get_doctest(doc, {}, "foo-bar@baz", "foo-bar@baz.py", 0)
-      >>> runner = doctest.DocTestRunner(verbose=False)
-
-    To demonstrate this, we'll create a fake standard input that
-    captures our debugger input:
-
-      >>> import tempfile
-      >>> real_stdin = sys.stdin
-      >>> sys.stdin = _FakeInput([
-      ...    'print(x)',  # print data defined by the example
-      ...    'continue', # stop debugging
-      ...    ''])
-
-      >>> try: runner.run(test)
-      ... finally: sys.stdin = real_stdin
-      --Return--
-      > <doctest foo-bar@baz[2]>(1)<module>()->None
-      -> import pdb; pdb.set_trace()
-      (Pdb) print(x)
-      42
-      (Pdb) continue
-      TestResults(failed=0, attempted=3)
-
-      You can also put pdb.set_trace in a function called from a test:
-
-      >>> def calls_set_trace():
-      ...    y=2
-      ...    import pdb; pdb.set_trace()
-
-      >>> doc = '''
-      ... >>> x=1
-      ... >>> calls_set_trace()
-      ... '''
-      >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
-      >>> real_stdin = sys.stdin
-      >>> sys.stdin = _FakeInput([
-      ...    'print(y)',  # print data defined in the function
-      ...    'up',       # out of function
-      ...    'print(x)',  # print data defined by the example
-      ...    'continue', # stop debugging
-      ...    ''])
-
-      >>> try:
-      ...     runner.run(test)
-      ... finally:
-      ...     sys.stdin = real_stdin
-      --Return--
-      > <doctest test.test_doctest.test_pdb_set_trace[8]>(3)calls_set_trace()->None
-      -> import pdb; pdb.set_trace()
-      (Pdb) print(y)
-      2
-      (Pdb) up
-      > <doctest foo-bar@baz[1]>(1)<module>()
-      -> calls_set_trace()
-      (Pdb) print(x)
-      1
-      (Pdb) continue
-      TestResults(failed=0, attempted=2)
-
-    During interactive debugging, source code is shown, even for
-    doctest examples:
-
-      >>> doc = '''
-      ... >>> def f(x):
-      ... ...     g(x*2)
-      ... >>> def g(x):
-      ... ...     print(x+3)
-      ... ...     import pdb; pdb.set_trace()
-      ... >>> f(3)
-      ... '''
-      >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
-      >>> real_stdin = sys.stdin
-      >>> sys.stdin = _FakeInput([
-      ...    'list',     # list source from example 2
-      ...    'next',     # return from g()
-      ...    'list',     # list source from example 1
-      ...    'next',     # return from f()
-      ...    'list',     # list source from example 3
-      ...    'continue', # stop debugging
-      ...    ''])
-      >>> try: runner.run(test)
-      ... finally: sys.stdin = real_stdin
-      ... # doctest: +NORMALIZE_WHITESPACE
-      --Return--
-      > <doctest foo-bar@baz[1]>(3)g()->None
-      -> import pdb; pdb.set_trace()
-      (Pdb) list
-        1     def g(x):
-        2         print(x+3)
-        3  ->     import pdb; pdb.set_trace()
-      [EOF]
-      (Pdb) next
-      --Return--
-      > <doctest foo-bar@baz[0]>(2)f()->None
-      -> g(x*2)
-      (Pdb) list
-        1     def f(x):
-        2  ->     g(x*2)
-      [EOF]
-      (Pdb) next
-      --Return--
-      > <doctest foo-bar@baz[2]>(1)<module>()->None
-      -> f(3)
-      (Pdb) list
-        1  -> f(3)
-      [EOF]
-      (Pdb) continue
-      **********************************************************************
-      File "foo-bar@baz.py", line 7, in foo-bar@baz
-      Failed example:
-          f(3)
-      Expected nothing
-      Got:
-          9
-      TestResults(failed=1, attempted=3)
-      """
-
-def test_pdb_set_trace_nested():
-    """This illustrates more-demanding use of set_trace with nested functions.
-
-    >>> class C(object):
-    ...     def calls_set_trace(self):
-    ...         y = 1
-    ...         import pdb; pdb.set_trace()
-    ...         self.f1()
-    ...         y = 2
-    ...     def f1(self):
-    ...         x = 1
-    ...         self.f2()
-    ...         x = 2
-    ...     def f2(self):
-    ...         z = 1
-    ...         z = 2
-
-    >>> calls_set_trace = C().calls_set_trace
-
-    >>> doc = '''
-    ... >>> a = 1
-    ... >>> calls_set_trace()
-    ... '''
-    >>> parser = doctest.DocTestParser()
-    >>> runner = doctest.DocTestRunner(verbose=False)
-    >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
-    >>> real_stdin = sys.stdin
-    >>> sys.stdin = _FakeInput([
-    ...    'print(y)',  # print data defined in the function
-    ...    'step', 'step', 'step', 'step', 'step', 'step', 'print(z)',
-    ...    'up', 'print(x)',
-    ...    'up', 'print(y)',
-    ...    'up', 'print(foo)',
-    ...    'continue', # stop debugging
-    ...    ''])
-
-    >>> try:
-    ...     runner.run(test)
-    ... finally:
-    ...     sys.stdin = real_stdin
-    ... # doctest: +REPORT_NDIFF
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
-    -> self.f1()
-    (Pdb) print(y)
-    1
-    (Pdb) step
-    --Call--
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(7)f1()
-    -> def f1(self):
-    (Pdb) step
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(8)f1()
-    -> x = 1
-    (Pdb) step
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
-    -> self.f2()
-    (Pdb) step
-    --Call--
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(11)f2()
-    -> def f2(self):
-    (Pdb) step
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(12)f2()
-    -> z = 1
-    (Pdb) step
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(13)f2()
-    -> z = 2
-    (Pdb) print(z)
-    1
-    (Pdb) up
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
-    -> self.f2()
-    (Pdb) print(x)
-    1
-    (Pdb) up
-    > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
-    -> self.f1()
-    (Pdb) print(y)
-    1
-    (Pdb) up
-    > <doctest foo-bar@baz[1]>(1)<module>()
-    -> calls_set_trace()
-    (Pdb) print(foo)
-    *** NameError: name 'foo' is not defined
-    (Pdb) continue
-    TestResults(failed=0, attempted=2)
-"""
+if not hasattr(sys, 'gettrace') or not sys.gettrace():
+    def test_pdb_set_trace():
+        """Using pdb.set_trace from a doctest.
+
+        You can use pdb.set_trace from a doctest.  To do so, you must
+        retrieve the set_trace function from the pdb module at the time
+        you use it.  The doctest module changes sys.stdout so that it can
+        capture program output.  It also temporarily replaces pdb.set_trace
+        with a version that restores stdout.  This is necessary for you to
+        see debugger output.
+
+          >>> doc = '''
+          ... >>> x = 42
+          ... >>> raise Exception('clé')
+          ... Traceback (most recent call last):
+          ... Exception: clé
+          ... >>> import pdb; pdb.set_trace()
+          ... '''
+          >>> parser = doctest.DocTestParser()
+          >>> test = parser.get_doctest(doc, {}, "foo-bar@baz", "foo-bar@baz.py", 0)
+          >>> runner = doctest.DocTestRunner(verbose=False)
+
+        To demonstrate this, we'll create a fake standard input that
+        captures our debugger input:
+
+          >>> import tempfile
+          >>> real_stdin = sys.stdin
+          >>> sys.stdin = _FakeInput([
+          ...    'print(x)',  # print data defined by the example
+          ...    'continue', # stop debugging
+          ...    ''])
+
+          >>> try: runner.run(test)
+          ... finally: sys.stdin = real_stdin
+          --Return--
+          > <doctest foo-bar@baz[2]>(1)<module>()->None
+          -> import pdb; pdb.set_trace()
+          (Pdb) print(x)
+          42
+          (Pdb) continue
+          TestResults(failed=0, attempted=3)
+
+          You can also put pdb.set_trace in a function called from a test:
+
+          >>> def calls_set_trace():
+          ...    y=2
+          ...    import pdb; pdb.set_trace()
+
+          >>> doc = '''
+          ... >>> x=1
+          ... >>> calls_set_trace()
+          ... '''
+          >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
+          >>> real_stdin = sys.stdin
+          >>> sys.stdin = _FakeInput([
+          ...    'print(y)',  # print data defined in the function
+          ...    'up',       # out of function
+          ...    'print(x)',  # print data defined by the example
+          ...    'continue', # stop debugging
+          ...    ''])
+
+          >>> try:
+          ...     runner.run(test)
+          ... finally:
+          ...     sys.stdin = real_stdin
+          --Return--
+          > <doctest test.test_doctest.test_pdb_set_trace[8]>(3)calls_set_trace()->None
+          -> import pdb; pdb.set_trace()
+          (Pdb) print(y)
+          2
+          (Pdb) up
+          > <doctest foo-bar@baz[1]>(1)<module>()
+          -> calls_set_trace()
+          (Pdb) print(x)
+          1
+          (Pdb) continue
+          TestResults(failed=0, attempted=2)
+
+        During interactive debugging, source code is shown, even for
+        doctest examples:
+
+          >>> doc = '''
+          ... >>> def f(x):
+          ... ...     g(x*2)
+          ... >>> def g(x):
+          ... ...     print(x+3)
+          ... ...     import pdb; pdb.set_trace()
+          ... >>> f(3)
+          ... '''
+          >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
+          >>> real_stdin = sys.stdin
+          >>> sys.stdin = _FakeInput([
+          ...    'list',     # list source from example 2
+          ...    'next',     # return from g()
+          ...    'list',     # list source from example 1
+          ...    'next',     # return from f()
+          ...    'list',     # list source from example 3
+          ...    'continue', # stop debugging
+          ...    ''])
+          >>> try: runner.run(test)
+          ... finally: sys.stdin = real_stdin
+          ... # doctest: +NORMALIZE_WHITESPACE
+          --Return--
+          > <doctest foo-bar@baz[1]>(3)g()->None
+          -> import pdb; pdb.set_trace()
+          (Pdb) list
+            1     def g(x):
+            2         print(x+3)
+            3  ->     import pdb; pdb.set_trace()
+          [EOF]
+          (Pdb) next
+          --Return--
+          > <doctest foo-bar@baz[0]>(2)f()->None
+          -> g(x*2)
+          (Pdb) list
+            1     def f(x):
+            2  ->     g(x*2)
+          [EOF]
+          (Pdb) next
+          --Return--
+          > <doctest foo-bar@baz[2]>(1)<module>()->None
+          -> f(3)
+          (Pdb) list
+            1  -> f(3)
+          [EOF]
+          (Pdb) continue
+          **********************************************************************
+          File "foo-bar@baz.py", line 7, in foo-bar@baz
+          Failed example:
+              f(3)
+          Expected nothing
+          Got:
+              9
+          TestResults(failed=1, attempted=3)
+          """
+
+    def test_pdb_set_trace_nested():
+        """This illustrates more-demanding use of set_trace with nested functions.
+
+        >>> class C(object):
+        ...     def calls_set_trace(self):
+        ...         y = 1
+        ...         import pdb; pdb.set_trace()
+        ...         self.f1()
+        ...         y = 2
+        ...     def f1(self):
+        ...         x = 1
+        ...         self.f2()
+        ...         x = 2
+        ...     def f2(self):
+        ...         z = 1
+        ...         z = 2
+
+        >>> calls_set_trace = C().calls_set_trace
+
+        >>> doc = '''
+        ... >>> a = 1
+        ... >>> calls_set_trace()
+        ... '''
+        >>> parser = doctest.DocTestParser()
+        >>> runner = doctest.DocTestRunner(verbose=False)
+        >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
+        >>> real_stdin = sys.stdin
+        >>> sys.stdin = _FakeInput([
+        ...    'print(y)',  # print data defined in the function
+        ...    'step', 'step', 'step', 'step', 'step', 'step', 'print(z)',
+        ...    'up', 'print(x)',
+        ...    'up', 'print(y)',
+        ...    'up', 'print(foo)',
+        ...    'continue', # stop debugging
+        ...    ''])
+
+        >>> try:
+        ...     runner.run(test)
+        ... finally:
+        ...     sys.stdin = real_stdin
+        ... # doctest: +REPORT_NDIFF
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
+        -> self.f1()
+        (Pdb) print(y)
+        1
+        (Pdb) step
+        --Call--
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(7)f1()
+        -> def f1(self):
+        (Pdb) step
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(8)f1()
+        -> x = 1
+        (Pdb) step
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
+        -> self.f2()
+        (Pdb) step
+        --Call--
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(11)f2()
+        -> def f2(self):
+        (Pdb) step
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(12)f2()
+        -> z = 1
+        (Pdb) step
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(13)f2()
+        -> z = 2
+        (Pdb) print(z)
+        1
+        (Pdb) up
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
+        -> self.f2()
+        (Pdb) print(x)
+        1
+        (Pdb) up
+        > <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
+        -> self.f1()
+        (Pdb) print(y)
+        1
+        (Pdb) up
+        > <doctest foo-bar@baz[1]>(1)<module>()
+        -> calls_set_trace()
+        (Pdb) print(foo)
+        *** NameError: name 'foo' is not defined
+        (Pdb) continue
+        TestResults(failed=0, attempted=2)
+    """
 
 def test_DocTestSuite():
     """DocTestSuite creates a unittest test suite from a doctest.
index 76f4249490f9105ed6fb752c5c42912e313e9127..592c765e91e77fe99ec09a7fd4d3a276d38a2f60 100644 (file)
@@ -7,7 +7,7 @@ import pickle
 import weakref
 
 from test.support import (TESTFN, unlink, run_unittest, captured_output,
-                          gc_collect, cpython_only)
+                          gc_collect, cpython_only, no_tracing)
 
 # XXX This is not really enough, each *operation* should be tested!
 
@@ -388,6 +388,7 @@ class ExceptionTests(unittest.TestCase):
         x = DerivedException(fancy_arg=42)
         self.assertEqual(x.fancy_arg, 42)
 
+    @no_tracing
     def testInfiniteRecursion(self):
         def f():
             return f()
@@ -631,6 +632,7 @@ class ExceptionTests(unittest.TestCase):
         u.start = 1000
         self.assertEqual(str(u), "can't translate characters in position 1000-4: 965230951443685724997")
 
+    @no_tracing
     def test_badisinstance(self):
         # Bug #2542: if issubclass(e, MyException) raises an exception,
         # it should be ignored
@@ -741,6 +743,7 @@ class ExceptionTests(unittest.TestCase):
             self.fail("MemoryError not raised")
         self.assertEqual(wr(), None)
 
+    @no_tracing
     def test_recursion_error_cleanup(self):
         # Same test as above, but with "recursion exceeded" errors
         class C:
index a25d9afd526f282802d4c9545f7e542c4d0329c0..3a2589e36a43d7bb2a99a4c63d68982a8eb7c660 100644 (file)
@@ -2214,6 +2214,7 @@ class TextIOWrapperTest(unittest.TestCase):
         with self.open(support.TESTFN, "w", errors="replace") as f:
             self.assertEqual(f.errors, "replace")
 
+    @support.no_tracing
     @unittest.skipUnless(threading, 'Threading required for this test.')
     def test_threads_write(self):
         # Issue6750: concurrent writes could duplicate data
@@ -2669,6 +2670,7 @@ class SignalsTest(unittest.TestCase):
     def test_interrupted_write_text(self):
         self.check_interrupted_write("xy", b"xy", mode="w", encoding="ascii")
 
+    @support.no_tracing
     def check_reentrant_write(self, data, **fdopen_kwargs):
         def on_alarm(*args):
             # Will be called reentrantly from the same thread
index d861df52bb65eb855c30a64c460f91ca5dff5bb3..c197aff31838887e86fce83522cf93e6be6a307f 100644 (file)
@@ -20,9 +20,12 @@ class PdbTestInput(object):
     def __enter__(self):
         self.real_stdin = sys.stdin
         sys.stdin = _FakeInput(self.input)
+        self.orig_trace = sys.gettrace() if hasattr(sys, 'gettrace') else None
 
     def __exit__(self, *exc):
         sys.stdin = self.real_stdin
+        if self.orig_trace:
+            sys.settrace(self.orig_trace)
 
 
 def test_pdb_displayhook():
index f8f3717b641e1cae8edfd57259ff63d050e26153..0b629dc5bc884d0bfa8d688194e87f99af82c58c 100644 (file)
@@ -220,6 +220,7 @@ class MiscTest(unittest.TestCase):
         for func in (do, operator.not_):
             self.assertRaises(Exc, func, Bad())
 
+    @support.no_tracing
     def test_recursion(self):
         # Check that comparison for recursive objects fails gracefully
         from collections import UserList
index ad3ab397f49dc106451cd9191fd7344bd5a0958c..00f34b182489997fb82689c3f35b1ea1aefecfce 100644 (file)
@@ -6,7 +6,8 @@ import sys
 import re
 import tempfile
 import py_compile
-from test.support import forget, make_legacy_pyc, run_unittest, unload, verbose
+from test.support import (
+    forget, make_legacy_pyc, run_unittest, unload, verbose, no_tracing)
 from test.script_helper import (
     make_pkg, make_script, make_zip_pkg, make_zip_script, temp_dir)
 
@@ -395,6 +396,7 @@ argv0 = sys.argv[0]
             msg = "can't find '__main__' module in %r" % zip_name
             self._check_import_error(zip_name, msg)
 
+    @no_tracing
     def test_main_recursion_error(self):
         with temp_dir() as script_dir, temp_dir() as dummy_dir:
             mod_name = '__main__'
index fbc87aa80c7537be23676cba33f80430e51c51b8..129a18aade6b73ed56bc16d314be2164854bf16a 100644 (file)
@@ -1,5 +1,5 @@
 import unittest
-from test.support import check_syntax_error, run_unittest
+from test.support import check_syntax_error, cpython_only, run_unittest
 
 
 class ScopeTests(unittest.TestCase):
@@ -496,23 +496,22 @@ class ScopeTests(unittest.TestCase):
         self.assertNotIn("x", varnames)
         self.assertIn("y", varnames)
 
+    @cpython_only
     def testLocalsClass_WithTrace(self):
         # Issue23728: after the trace function returns, the locals()
         # dictionary is used to update all variables, this used to
         # include free variables. But in class statements, free
         # variables are not inserted...
         import sys
+        self.addCleanup(sys.settrace, sys.gettrace())
         sys.settrace(lambda a,b,c:None)
-        try:
-            x = 12
+        x = 12
 
-            class C:
-                def f(self):
-                    return x
+        class C:
+            def f(self):
+                return x
 
-            self.assertEqual(x, 12) # Used to raise UnboundLocalError
-        finally:
-            sys.settrace(None)
+        self.assertEqual(x, 12) # Used to raise UnboundLocalError
 
     def testBoundAndFree(self):
         # var is bound and free in class
@@ -527,6 +526,7 @@ class ScopeTests(unittest.TestCase):
         inst = f(3)()
         self.assertEqual(inst.a, inst.m())
 
+    @cpython_only
     def testInteractionWithTraceFunc(self):
 
         import sys
@@ -543,6 +543,7 @@ class ScopeTests(unittest.TestCase):
         class TestClass:
             pass
 
+        self.addCleanup(sys.settrace, sys.gettrace())
         sys.settrace(tracer)
         adaptgetter("foo", TestClass, (1, ""))
         sys.settrace(None)
index 43134e98bd49beee75eab8b428596ccb6107555f..acb8e29f196f5fafffe7e752f340613c30f015f3 100644 (file)
@@ -251,6 +251,7 @@ class TraceTestCase(unittest.TestCase):
     def setUp(self):
         self.using_gc = gc.isenabled()
         gc.disable()
+        self.addCleanup(sys.settrace, sys.gettrace())
 
     def tearDown(self):
         if self.using_gc:
@@ -389,6 +390,9 @@ class TraceTestCase(unittest.TestCase):
 
 
 class RaisingTraceFuncTestCase(unittest.TestCase):
+    def setUp(self):
+        self.addCleanup(sys.settrace, sys.gettrace())
+
     def trace(self, frame, event, arg):
         """A trace function that raises an exception in response to a
         specific trace event."""
@@ -688,6 +692,10 @@ def no_jump_without_trace_function():
 
 
 class JumpTestCase(unittest.TestCase):
+    def setUp(self):
+        self.addCleanup(sys.settrace, sys.gettrace())
+        sys.settrace(None)
+
     def compare_jump_output(self, expected, received):
         if received != expected:
             self.fail( "Outputs don't match:\n" +
@@ -739,6 +747,8 @@ class JumpTestCase(unittest.TestCase):
     def test_18_no_jump_to_non_integers(self):
         self.run_test(no_jump_to_non_integers)
     def test_19_no_jump_without_trace_function(self):
+        # Must set sys.settrace(None) in setUp(), else condition is not
+        # triggered.
         no_jump_without_trace_function()
 
     def test_20_large_function(self):
index 93df84f57cbf8d8d9c996811de9215812d67f8d7..9266280b9cd6941fff8bb46adc651656730e66df 100644 (file)
@@ -102,6 +102,7 @@ class TracedClass(object):
 class TestLineCounts(unittest.TestCase):
     """White-box testing of line-counting, via runfunc"""
     def setUp(self):
+        self.addCleanup(sys.settrace, sys.gettrace())
         self.tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
         self.my_py_filename = fix_ext_py(__file__)
 
@@ -192,6 +193,7 @@ class TestRunExecCounts(unittest.TestCase):
     """A simple sanity test of line-counting, via runctx (exec)"""
     def setUp(self):
         self.my_py_filename = fix_ext_py(__file__)
+        self.addCleanup(sys.settrace, sys.gettrace())
 
     def test_exec_counts(self):
         self.tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
@@ -218,6 +220,7 @@ class TestRunExecCounts(unittest.TestCase):
 class TestFuncs(unittest.TestCase):
     """White-box testing of funcs tracing"""
     def setUp(self):
+        self.addCleanup(sys.settrace, sys.gettrace())
         self.tracer = Trace(count=0, trace=0, countfuncs=1)
         self.filemod = my_file_and_modname()
 
@@ -257,6 +260,7 @@ class TestFuncs(unittest.TestCase):
 class TestCallers(unittest.TestCase):
     """White-box testing of callers tracing"""
     def setUp(self):
+        self.addCleanup(sys.settrace, sys.gettrace())
         self.tracer = Trace(count=0, trace=0, countcallers=1)
         self.filemod = my_file_and_modname()
 
@@ -280,6 +284,9 @@ class TestCallers(unittest.TestCase):
 
 # Created separately for issue #3821
 class TestCoverage(unittest.TestCase):
+    def setUp(self):
+        self.addCleanup(sys.settrace, sys.gettrace())
+
     def tearDown(self):
         rmtree(TESTFN)
         unlink(TESTFN)
index 610dfa0d0a99fee0aad24cbe6f6299d5554ed82d..e3dd3e99a2f64cb4d6d458128ab740d132498cae 100644 (file)
@@ -163,20 +163,24 @@ class ZipSupportTests(unittest.TestCase):
                     test_zipped_doctest.test_DocTestRunner.verbose_flag,
                     test_zipped_doctest.test_Example,
                     test_zipped_doctest.test_debug,
-                    test_zipped_doctest.test_pdb_set_trace,
-                    test_zipped_doctest.test_pdb_set_trace_nested,
                     test_zipped_doctest.test_testsource,
                     test_zipped_doctest.test_trailing_space_in_test,
                     test_zipped_doctest.test_DocTestSuite,
                     test_zipped_doctest.test_DocTestFinder,
                 ]
-                # These remaining tests are the ones which need access
+                # These tests are the ones which need access
                 # to the data files, so we don't run them
                 fail_due_to_missing_data_files = [
                     test_zipped_doctest.test_DocFileSuite,
                     test_zipped_doctest.test_testfile,
                     test_zipped_doctest.test_unittest_reportflags,
                 ]
+                # These tests are skipped when a trace funciton is set
+                can_fail_due_to_tracing = [
+                    test_zipped_doctest.test_pdb_set_trace,
+                    test_zipped_doctest.test_pdb_set_trace_nested,
+                ]
+
                 for obj in known_good_tests:
                     _run_object_doctest(obj, test_zipped_doctest)
             finally:
index e7325d8aafd5af171b60a7b0c5e93ade1b56c34f..9744ed80e3a4013e4be9619f008bce61a118e03c 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,10 @@ Library
 - Issue #10276: Fix the results of zlib.crc32() and zlib.adler32() on buffers
   larger than 4GB.  Patch by Nadeem Vawda.
 
+Tests
+
+- Issue #10990: Prevent tests from clobbering a set trace function.
+
 
 What's New in Python 3.2?
 =========================