[Python-checkins] cpython (2.7): Issue 15505. unittest.installHandler and non callable signal handlers

michael.foord python-checkins at python.org
Tue Jan 29 23:59:07 CET 2013


http://hg.python.org/cpython/rev/7e4c5914ba76
changeset:   81836:7e4c5914ba76
branch:      2.7
parent:      81834:c34a761d843a
user:        Michael Foord <michael at voidspace.org.uk>
date:        Tue Jan 29 22:59:02 2013 +0000
summary:
  Issue 15505. unittest.installHandler and non callable signal handlers

files:
  Lib/unittest/signals.py         |  16 +++++++++-
  Lib/unittest/test/test_break.py |  32 +++++++++++++++++++++
  Misc/NEWS                       |   3 +
  3 files changed, 50 insertions(+), 1 deletions(-)


diff --git a/Lib/unittest/signals.py b/Lib/unittest/signals.py
--- a/Lib/unittest/signals.py
+++ b/Lib/unittest/signals.py
@@ -9,6 +9,20 @@
 class _InterruptHandler(object):
     def __init__(self, default_handler):
         self.called = False
+        self.original_handler = default_handler
+        if isinstance(default_handler, int):
+            if default_handler == signal.SIG_DFL:
+                # Pretend it's signal.default_int_handler instead.
+                default_handler = signal.default_int_handler
+            elif default_handler == signal.SIG_IGN:
+                # Not quite the same thing as SIG_IGN, but the closest we
+                # can make it: do nothing.
+                def default_handler(unused_signum, unused_frame):
+                    pass
+            else:
+                raise TypeError("expected SIGINT signal handler to be "
+                                "signal.SIG_IGN, signal.SIG_DFL, or a "
+                                "callable object")
         self.default_handler = default_handler
 
     def __call__(self, signum, frame):
@@ -54,4 +68,4 @@
 
     global _interrupt_handler
     if _interrupt_handler is not None:
-        signal.signal(signal.SIGINT, _interrupt_handler.default_handler)
+        signal.signal(signal.SIGINT, _interrupt_handler.original_handler)
diff --git a/Lib/unittest/test/test_break.py b/Lib/unittest/test/test_break.py
--- a/Lib/unittest/test/test_break.py
+++ b/Lib/unittest/test/test_break.py
@@ -15,9 +15,12 @@
 @unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
     "if threads have been used")
 class TestBreak(unittest.TestCase):
+    int_handler = None
 
     def setUp(self):
         self._default_handler = signal.getsignal(signal.SIGINT)
+        if self.int_handler is not None:
+            signal.signal(signal.SIGINT, self.int_handler)
 
     def tearDown(self):
         signal.signal(signal.SIGINT, self._default_handler)
@@ -74,6 +77,10 @@
 
 
     def testSecondInterrupt(self):
+        # Can't use skipIf decorator because the signal handler may have
+        # been changed after defining this method.
+        if signal.getsignal(signal.SIGINT) == signal.SIG_IGN:
+            self.skipTest("test requires SIGINT to not be ignored")
         result = unittest.TestResult()
         unittest.installHandler()
         unittest.registerResult(result)
@@ -123,6 +130,10 @@
 
 
     def testHandlerReplacedButCalled(self):
+        # Can't use skipIf decorator because the signal handler may have
+        # been changed after defining this method.
+        if signal.getsignal(signal.SIGINT) == signal.SIG_IGN:
+            self.skipTest("test requires SIGINT to not be ignored")
         # If our handler has been replaced (is no longer installed) but is
         # called by the *new* handler, then it isn't safe to delay the
         # SIGINT and we should immediately delegate to the default handler
@@ -250,3 +261,24 @@
 
         test()
         self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
+
+ at unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
+ at unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
+ at unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
+    "if threads have been used")
+class TestBreakDefaultIntHandler(TestBreak):
+    int_handler = signal.default_int_handler
+
+ at unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
+ at unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
+ at unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
+    "if threads have been used")
+class TestBreakSignalIgnored(TestBreak):
+    int_handler = signal.SIG_IGN
+
+ at unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
+ at unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
+ at unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
+    "if threads have been used")
+class TestBreakSignalDefault(TestBreak):
+    int_handler = signal.SIG_DFL
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -202,6 +202,9 @@
 Library
 -------
 
+- Issue #15505: `unittest.installHandler` no longer assumes SIGINT handler is
+  set to a callable object.
+
 - Issue #17051: Fix a memory leak in os.path.isdir() on Windows. Patch by
   Robert Xiao.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list