[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