[pypy-svn] r36399 - in pypy/dist/pypy: module/signal module/signal/test translator/goal

exarkun at codespeak.net exarkun at codespeak.net
Wed Jan 10 03:01:28 CET 2007


Author: exarkun
Date: Wed Jan 10 03:01:26 2007
New Revision: 36399

Added:
   pypy/dist/pypy/module/signal/app_signal.py
Modified:
   pypy/dist/pypy/module/signal/__init__.py
   pypy/dist/pypy/module/signal/interp_signal.py
   pypy/dist/pypy/module/signal/test/test_signal.py
   pypy/dist/pypy/translator/goal/app_main.py
Log:
Fix signal.signal return value, add signal.getsignal and signal.default_int_handler

Modified: pypy/dist/pypy/module/signal/__init__.py
==============================================================================
--- pypy/dist/pypy/module/signal/__init__.py	(original)
+++ pypy/dist/pypy/module/signal/__init__.py	Wed Jan 10 03:01:26 2007
@@ -3,13 +3,15 @@
 
 class Module(MixedModule):
     interpleveldefs = {
-        'signal':  'interp_signal.signal',
-        'NSIG':    'space.wrap(interp_signal.NSIG)',
-        'SIG_DFL': 'space.wrap(interp_signal.SIG_DFL)',
-        'SIG_IGN': 'space.wrap(interp_signal.SIG_IGN)',
+        'signal':              'interp_signal.signal',
+        'getsignal':           'interp_signal.getsignal',
+        'NSIG':                'space.wrap(interp_signal.NSIG)',
+        'SIG_DFL':             'space.wrap(interp_signal.SIG_DFL)',
+        'SIG_IGN':             'space.wrap(interp_signal.SIG_IGN)',
     }
 
     appleveldefs = {
+        'default_int_handler': 'app_signal.default_int_handler',
     }
 
     def buildloaders(cls):

Added: pypy/dist/pypy/module/signal/app_signal.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/signal/app_signal.py	Wed Jan 10 03:01:26 2007
@@ -0,0 +1,10 @@
+
+
+def default_int_handler(signum, frame):
+    """
+    default_int_handler(...)
+
+    The default handler for SIGINT installed by Python.
+    It raises KeyboardInterrupt.
+    """
+    raise KeyboardInterrupt()

Modified: pypy/dist/pypy/module/signal/interp_signal.py
==============================================================================
--- pypy/dist/pypy/module/signal/interp_signal.py	(original)
+++ pypy/dist/pypy/module/signal/interp_signal.py	Wed Jan 10 03:01:26 2007
@@ -66,30 +66,60 @@
             w_frame = space.w_None
         space.call_function(w_handler, space.wrap(self.signum), w_frame)
 
+
+def getsignal(space, signum):
+    """
+    getsignal(sig) -> action
+
+    Return the current action for the given signal.  The return value can be:
+    SIG_IGN -- if the signal is being ignored
+    SIG_DFL -- if the default action for the signal is in effect
+    None -- if an unknown handler is in effect (XXX UNIMPLEMENTED)
+    anything else -- the callable Python object used as a handler
+    """
+    action = CheckSignalAction.get(space)
+    if signum in action.handlers_w:
+        return action.handlers_w[signum]
+    return space.wrap(SIG_DFL)
+getsignal.unwrap_spec = [ObjSpace, int]
+
+
 def signal(space, signum, w_handler):
+    """
+    signal(sig, action) -> action
+
+    Set the action for the given signal.  The action can be SIG_DFL,
+    SIG_IGN, or a callable Python object.  The previous action is
+    returned.  See getsignal() for possible return values.
+
+    *** IMPORTANT NOTICE ***
+    A signal handler function is called with two arguments:
+    the first is the signal number, the second is the interrupted stack frame.
+    """
     ec      = space.getexecutioncontext()
     main_ec = space.threadlocals.getmainthreadvalue()
+
+    old_handler = getsignal(space, signum)
+
     if ec is not main_ec:
         raise OperationError(space.w_ValueError,
                              space.wrap("signal() must be called from the "
                                         "main thread"))
     action = CheckSignalAction.get(space)
     if space.eq_w(w_handler, space.wrap(SIG_DFL)):
-        if signum in action.handlers_w:
-            del action.handlers_w[signum]
         pypysig_default(signum)
+        action.handlers_w[signum] = w_handler
     elif space.eq_w(w_handler, space.wrap(SIG_IGN)):
-        if signum in action.handlers_w:
-            del action.handlers_w[signum]
         pypysig_ignore(signum)
+        action.handlers_w[signum] = w_handler
     else:
         if not space.is_true(space.callable(w_handler)):
             raise OperationError(space.w_TypeError,
                                  space.wrap("'handler' must be a callable "
                                             "or SIG_DFL or SIG_IGN"))
-        action.handlers_w[signum] = w_handler
         pypysig_setflag(signum)
-    # XXX return value missing
+        action.handlers_w[signum] = w_handler
+    return old_handler
 signal.unwrap_spec = [ObjSpace, int, W_Root]
 
 # ____________________________________________________________

Modified: pypy/dist/pypy/module/signal/test/test_signal.py
==============================================================================
--- pypy/dist/pypy/module/signal/test/test_signal.py	(original)
+++ pypy/dist/pypy/module/signal/test/test_signal.py	Wed Jan 10 03:01:26 2007
@@ -49,3 +49,69 @@
         assert received == []
 
         signal.signal(signal.SIGUSR1, signal.SIG_DFL)
+
+
+    def test_default_return(self):
+        """
+        Test that signal.signal returns SIG_DFL if that is the current handler.
+        """
+        from signal import signal, SIGUSR1, SIG_DFL, SIG_IGN
+
+        try:
+            for handler in SIG_DFL, SIG_IGN, lambda *a: None:
+                signal(SIGUSR1, SIG_DFL)
+                assert signal(SIGUSR1, handler) == SIG_DFL
+        finally:
+            signal(SIGUSR1, SIG_DFL)
+
+
+    def test_ignore_return(self):
+        """
+        Test that signal.signal returns SIG_IGN if that is the current handler.
+        """
+        from signal import signal, SIGUSR1, SIG_DFL, SIG_IGN
+
+        try:
+            for handler in SIG_DFL, SIG_IGN, lambda *a: None:
+                signal(SIGUSR1, SIG_IGN)
+                assert signal(SIGUSR1, handler) == SIG_IGN
+        finally:
+            signal(SIGUSR1, SIG_DFL)
+
+
+    def test_obj_return(self):
+        """
+        Test that signal.signal returns a Python object if one is the current
+        handler.
+        """
+        from signal import signal, SIGUSR1, SIG_DFL, SIG_IGN
+        def installed(*a):
+            pass
+
+        try:
+            for handler in SIG_DFL, SIG_IGN, lambda *a: None:
+                signal(SIGUSR1, installed)
+                assert signal(SIGUSR1, handler) is installed
+        finally:
+            signal(SIGUSR1, SIG_DFL)
+
+
+    def test_getsignal(self):
+        """
+        Test that signal.getsignal returns the currently installed handler.
+        """
+        from signal import getsignal, signal, SIGUSR1, SIG_DFL, SIG_IGN
+
+        def handler(*a):
+            pass
+
+        try:
+            assert getsignal(SIGUSR1) == SIG_DFL
+            signal(SIGUSR1, SIG_DFL)
+            assert getsignal(SIGUSR1) == SIG_DFL
+            signal(SIGUSR1, SIG_IGN)
+            assert getsignal(SIGUSR1) == SIG_IGN
+            signal(SIGUSR1, handler)
+            assert getsignal(SIGUSR1) is handler
+        finally:
+            signal(SIGUSR1, SIG_DFL)

Modified: pypy/dist/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/dist/pypy/translator/goal/app_main.py	(original)
+++ pypy/dist/pypy/translator/goal/app_main.py	Wed Jan 10 03:01:26 2007
@@ -221,9 +221,7 @@
     except ImportError:
         pass
     else:
-        def keyboard_interrupt_handler(*args):
-            raise KeyboardInterrupt
-        signal.signal(signal.SIGINT, keyboard_interrupt_handler)
+        signal.signal(signal.SIGINT, signal.default_int_handler)
         signal.signal(signal.SIGPIPE, signal.SIG_IGN)
 
     try:



More information about the Pypy-commit mailing list