mirror of https://github.com/python/cpython
Closes issue 15505. unittest.installHandler and non-callable signal handlers.
This commit is contained in:
parent
45c4375ea7
commit
6debd76939
|
@ -9,6 +9,20 @@ __unittest = True
|
||||||
class _InterruptHandler(object):
|
class _InterruptHandler(object):
|
||||||
def __init__(self, default_handler):
|
def __init__(self, default_handler):
|
||||||
self.called = False
|
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
|
self.default_handler = default_handler
|
||||||
|
|
||||||
def __call__(self, signum, frame):
|
def __call__(self, signum, frame):
|
||||||
|
@ -54,4 +68,4 @@ def removeHandler(method=None):
|
||||||
|
|
||||||
global _interrupt_handler
|
global _interrupt_handler
|
||||||
if _interrupt_handler is not None:
|
if _interrupt_handler is not None:
|
||||||
signal.signal(signal.SIGINT, _interrupt_handler.default_handler)
|
signal.signal(signal.SIGINT, _interrupt_handler.original_handler)
|
||||||
|
|
|
@ -13,9 +13,12 @@ import unittest
|
||||||
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||||
"if threads have been used")
|
"if threads have been used")
|
||||||
class TestBreak(unittest.TestCase):
|
class TestBreak(unittest.TestCase):
|
||||||
|
int_handler = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self._default_handler = signal.getsignal(signal.SIGINT)
|
self._default_handler = signal.getsignal(signal.SIGINT)
|
||||||
|
if self.int_handler is not None:
|
||||||
|
signal.signal(signal.SIGINT, self.int_handler)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
signal.signal(signal.SIGINT, self._default_handler)
|
signal.signal(signal.SIGINT, self._default_handler)
|
||||||
|
@ -72,6 +75,10 @@ class TestBreak(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
def testSecondInterrupt(self):
|
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()
|
result = unittest.TestResult()
|
||||||
unittest.installHandler()
|
unittest.installHandler()
|
||||||
unittest.registerResult(result)
|
unittest.registerResult(result)
|
||||||
|
@ -121,6 +128,10 @@ class TestBreak(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
def testHandlerReplacedButCalled(self):
|
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
|
# 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
|
# called by the *new* handler, then it isn't safe to delay the
|
||||||
# SIGINT and we should immediately delegate to the default handler
|
# SIGINT and we should immediately delegate to the default handler
|
||||||
|
@ -250,3 +261,24 @@ class TestBreak(unittest.TestCase):
|
||||||
|
|
||||||
test()
|
test()
|
||||||
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
|
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
|
||||||
|
@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
|
||||||
|
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||||
|
"if threads have been used")
|
||||||
|
class TestBreakDefaultIntHandler(TestBreak):
|
||||||
|
int_handler = signal.default_int_handler
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
|
||||||
|
@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
|
||||||
|
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||||
|
"if threads have been used")
|
||||||
|
class TestBreakSignalIgnored(TestBreak):
|
||||||
|
int_handler = signal.SIG_IGN
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'kill'), "Test requires os.kill")
|
||||||
|
@unittest.skipIf(sys.platform =="win32", "Test cannot run on Windows")
|
||||||
|
@unittest.skipIf(sys.platform == 'freebsd6', "Test kills regrtest on freebsd6 "
|
||||||
|
"if threads have been used")
|
||||||
|
class TestBreakSignalDefault(TestBreak):
|
||||||
|
int_handler = signal.SIG_DFL
|
||||||
|
|
|
@ -216,6 +216,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #15505: `unittest.installHandler` no longer assumes SIGINT handler is
|
||||||
|
set to a callable object.
|
||||||
|
|
||||||
- Issue #12004: Fix an internal error in PyZipFile when writing an invalid
|
- Issue #12004: Fix an internal error in PyZipFile when writing an invalid
|
||||||
Python file. Patch by Ben Morgan.
|
Python file. Patch by Ben Morgan.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue