[Checkins] SVN: zc.signalhandler/trunk/ import zc.signalhandler 1.0 (building history)

Fred Drake fdrake at gmail.com
Thu Nov 11 23:45:20 EST 2010


Log message for revision 118349:
  import zc.signalhandler 1.0 (building history)

Changed:
  _U  zc.signalhandler/trunk/
  A   zc.signalhandler/trunk/buildout.cfg
  A   zc.signalhandler/trunk/setup.py
  A   zc.signalhandler/trunk/src/
  A   zc.signalhandler/trunk/src/zc/
  A   zc.signalhandler/trunk/src/zc/__init__.py
  A   zc.signalhandler/trunk/src/zc/signalhandler/
  A   zc.signalhandler/trunk/src/zc/signalhandler/README.txt
  A   zc.signalhandler/trunk/src/zc/signalhandler/__init__.py
  A   zc.signalhandler/trunk/src/zc/signalhandler/component.xml
  A   zc.signalhandler/trunk/src/zc/signalhandler/datatypes.py
  A   zc.signalhandler/trunk/src/zc/signalhandler/tests.py

-=-

Property changes on: zc.signalhandler/trunk
___________________________________________________________________
Added: svn:ignore
   + .installed.cfg
bin
build
develop-eggs
dist
eggs
parts


Added: zc.signalhandler/trunk/buildout.cfg
===================================================================
--- zc.signalhandler/trunk/buildout.cfg	                        (rev 0)
+++ zc.signalhandler/trunk/buildout.cfg	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1,9 @@
+[buildout]
+develop = .
+find-links = http://download.zope.org/distribution/
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zc.signalhandler
+defaults = '--exit-with-status -1'.split()


Property changes on: zc.signalhandler/trunk/buildout.cfg
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: zc.signalhandler/trunk/setup.py
===================================================================
--- zc.signalhandler/trunk/setup.py	                        (rev 0)
+++ zc.signalhandler/trunk/setup.py	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1,11 @@
+from setuptools import find_packages, setup
+
+setup(
+    name="zc.signalhandler",
+    version="1.0",
+    packages=find_packages("src"),
+    package_dir={"": "src"},
+    install_requires=["ZConfig >= 2.4a3"],
+    include_package_data=True,
+    zip_safe=False,
+    )


Property changes on: zc.signalhandler/trunk/setup.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: zc.signalhandler/trunk/src/zc/__init__.py
===================================================================
--- zc.signalhandler/trunk/src/zc/__init__.py	                        (rev 0)
+++ zc.signalhandler/trunk/src/zc/__init__.py	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1,8 @@
+# This directory is a Python namespace package.
+try:
+    import pkg_resources
+except ImportError:
+    import pkgutil
+    __path__ = pkgutil.extend_path(__path__, __name__)
+else:
+    pkg_resources.declare_namespace(__name__)


Property changes on: zc.signalhandler/trunk/src/zc/__init__.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: zc.signalhandler/trunk/src/zc/signalhandler/README.txt
===================================================================
--- zc.signalhandler/trunk/src/zc/signalhandler/README.txt	                        (rev 0)
+++ zc.signalhandler/trunk/src/zc/signalhandler/README.txt	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1,95 @@
+===========================
+Registering signal handlers
+===========================
+
+This package provides a way to register signal handlers from a ZConfig
+configuration.  There is a ZConfig component which is converted to a
+mapping of signal names to a list of handler functions.  The handlers
+take no arguments.
+
+The configuration section that provides signal handling information is
+considered a "product configuration" section for Zope 3, so let's
+create a simple schema that accepts product configurations::
+
+  >>> schema_text = '''\
+  ... <schema>
+  ...   <abstracttype name="zope.product.base"/>
+  ...   <section type="zope.product.base"
+  ...            attribute="siginfo"
+  ...            name="*"
+  ...            />
+  ... </schema>
+  ... '''
+
+  >>> import os
+  >>> import signal
+  >>> import StringIO
+  >>> import ZConfig
+
+  >>> schema = ZConfig.loadSchemaFile(StringIO.StringIO(schema_text))
+
+A sample configuration can simple import the ``zc.signalhandler``
+component and use it::
+
+  >>> config_text = '''
+  ...
+  ... %import zc.signalhandler
+  ...
+  ... <signalhandlers>
+  ...   hup   zc.signalhandler.tests.sample_handler_1
+  ...   hup   zc.signalhandler.tests.sample_handler_2
+  ...   usr1  zc.signalhandler.tests.sample_handler_1
+  ... </signalhandlers>
+  ...
+  ... '''
+
+We can install some default behavior for a signal::
+
+  >>> def some_behavior(sign, frame):
+  ...     print "some old behavior"
+
+  >>> old = signal.signal(signal.SIGUSR1, some_behavior)
+
+Let's try loading our sample configuration::
+
+  >>> config, config_handlers = ZConfig.loadConfigFile(
+  ...     schema, StringIO.StringIO(config_text))
+
+  >>> handlers = config.siginfo.handlers
+  >>> sorted(handlers)
+  ['SIGHUP', 'SIGUSR1']
+
+  >>> import zc.signalhandler.tests
+
+  >>> h1, h2 = handlers["SIGHUP"]
+  >>> h1 is zc.signalhandler.tests.sample_handler_1
+  True
+  >>> h2 is zc.signalhandler.tests.sample_handler_2
+  True
+
+  >>> h1, = handlers["SIGUSR1"]
+  >>> h1 is zc.signalhandler.tests.sample_handler_1
+  True
+
+At this point, the handlers are installed.  We can signal ourselves,
+and see that the handler is triggered::
+
+  >>> os.kill(os.getpid(), signal.SIGUSR1)
+  handler 1
+
+We can even trigger multiple handlers for a single signal::
+
+  >>> os.kill(os.getpid(), signal.SIGHUP)
+  handler 1
+  handler 2
+
+We can also uninstall the handlers::
+
+  >>> config.siginfo.uninstall()
+
+  >>> os.kill(os.getpid(), signal.SIGUSR1)
+  some old behavior
+
+Now let's restore the previous behavior of the signal::
+
+  >>> x = signal.signal(signal.SIGUSR1, old)


Property changes on: zc.signalhandler/trunk/src/zc/signalhandler/README.txt
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: zc.signalhandler/trunk/src/zc/signalhandler/__init__.py
===================================================================
--- zc.signalhandler/trunk/src/zc/signalhandler/__init__.py	                        (rev 0)
+++ zc.signalhandler/trunk/src/zc/signalhandler/__init__.py	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1 @@
+# This directory is a Python package.


Property changes on: zc.signalhandler/trunk/src/zc/signalhandler/__init__.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: zc.signalhandler/trunk/src/zc/signalhandler/component.xml
===================================================================
--- zc.signalhandler/trunk/src/zc/signalhandler/component.xml	                        (rev 0)
+++ zc.signalhandler/trunk/src/zc/signalhandler/component.xml	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1,15 @@
+<component>
+  <sectiontype
+      name="signalhandlers"
+      implements="zope.product.base"
+      keytype="zc.signalhandler.datatypes.name2signal"
+      datatype="zc.signalhandler.datatypes.SignalHandlers"
+      handler="zc.signalhandler.datatypes.SignalHandlers.install"
+      >
+    <multikey name="+"
+              attribute="mapping"
+              required="no"
+              datatype="ZConfig.components.logger.handlers.resolve"
+              />
+  </sectiontype>
+</component>

Added: zc.signalhandler/trunk/src/zc/signalhandler/datatypes.py
===================================================================
--- zc.signalhandler/trunk/src/zc/signalhandler/datatypes.py	                        (rev 0)
+++ zc.signalhandler/trunk/src/zc/signalhandler/datatypes.py	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1,132 @@
+"""\
+Data conversion functions for signal handling.
+
+"""
+__docformat__ = "reStructuredText"
+
+import signal
+
+
+def name2signal(string):
+    """Converts a signal name to canonical form.
+
+    Signal names are recognized without regard for case:
+
+      >>> name2signal('sighup')
+      'SIGHUP'
+      >>> name2signal('SigHup')
+      'SIGHUP'
+      >>> name2signal('SIGHUP')
+      'SIGHUP'
+
+    The leading 'SIG' is not required::
+
+      >>> name2signal('hup')
+      'SIGHUP'
+      >>> name2signal('HUP')
+      'SIGHUP'
+
+    Names that are not known cause an exception to be raised::
+
+      >>> name2signal('woohoo')
+      Traceback (most recent call last):
+      ValueError: could not convert 'woohoo' to signal name
+
+      >>> name2signal('sigwoohoo')
+      Traceback (most recent call last):
+      ValueError: could not convert 'sigwoohoo' to signal name
+
+    Numeric values are converted to names as well::
+
+      >>> name2signal(str(signal.SIGHUP))
+      'SIGHUP'
+
+    Numeric values that can't be matched to any signal known to Python
+    are treated as errors::
+
+      >>> name2signal('-234')
+      Traceback (most recent call last):
+      ValueError: unsupported signal on this platform: -234
+
+      >>> name2signal(str(signal.NSIG))  #doctest: +ELLIPSIS
+      Traceback (most recent call last):
+      ValueError: unsupported signal on this platform: ...
+
+    Non-signal attributes of the signal module are not mistakenly
+    converted::
+
+      >>> name2signal('_ign')
+      Traceback (most recent call last):
+      ValueError: could not convert '_ign' to signal name
+
+      >>> name2signal('_DFL')
+      Traceback (most recent call last):
+      ValueError: could not convert '_DFL' to signal name
+
+      >>> name2signal('sig_ign')
+      Traceback (most recent call last):
+      ValueError: could not convert 'sig_ign' to signal name
+
+      >>> name2signal('SIG_DFL')
+      Traceback (most recent call last):
+      ValueError: could not convert 'SIG_DFL' to signal name
+
+      >>> name2signal('getsignal')
+      Traceback (most recent call last):
+      ValueError: could not convert 'getsignal' to signal name
+
+    """
+    try:
+        v = int(string)
+    except ValueError:
+        if "_" in string:
+            raise ValueError("could not convert %r to signal name" % string)
+        s = string.upper()
+        if not s.startswith("SIG"):
+            s = "SIG" + s
+        v = getattr(signal, s, None)
+        if isinstance(v, int):
+            return s
+        raise ValueError("could not convert %r to signal name" % string)
+    if v >= signal.NSIG:
+        raise ValueError("unsupported signal on this platform: %s" % string)
+    for name in dir(signal):
+        if "_" in name:
+            continue
+        if getattr(signal, name) == v:
+            return name
+    raise ValueError("unsupported signal on this platform: %s" % string)
+
+
+class SignalHandlers(object):
+
+    def __init__(self, section):
+        self.handlers = section.mapping
+
+        # Convert to an isolated signalnum->[handlers] mapping:
+        self._handlers = {}
+        self._oldhandlers = {}
+        for name in self.handlers:
+            signalnum = getattr(signal, name)
+            self._handlers[signalnum] = self.handlers[name][:]
+
+        self.install()
+
+    def install(self):
+        if not self.installed:
+            for signum in self._handlers:
+                old = signal.signal(signum, self._dispatch)
+                self._oldhandlers[signum] = old
+
+    def uninstall(self):
+        while self._oldhandlers:
+            signum, handler = self._oldhandlers.popitem()
+            signal.signal(signum, handler)
+
+    @property
+    def installed(self):
+        return self._oldhandlers
+
+    def _dispatch(self, signum, frame):
+        for f in self._handlers[signum]:
+            f()


Property changes on: zc.signalhandler/trunk/src/zc/signalhandler/datatypes.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: zc.signalhandler/trunk/src/zc/signalhandler/tests.py
===================================================================
--- zc.signalhandler/trunk/src/zc/signalhandler/tests.py	                        (rev 0)
+++ zc.signalhandler/trunk/src/zc/signalhandler/tests.py	2010-11-12 04:45:19 UTC (rev 118349)
@@ -0,0 +1,23 @@
+"""\
+Test harness for zc.signalhandler.
+
+"""
+__docformat__ = "reStructuredText"
+
+import unittest
+
+from zope.testing import doctest
+
+
+def sample_handler_1():
+    print "handler 1"
+
+def sample_handler_2():
+    print "handler 2"
+
+
+def test_suite():
+    return unittest.TestSuite([
+        doctest.DocTestSuite("zc.signalhandler.datatypes"),
+        doctest.DocFileSuite("README.txt"),
+        ])


Property changes on: zc.signalhandler/trunk/src/zc/signalhandler/tests.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native



More information about the checkins mailing list