"""
adesklets signal handler module.

Originally written by Michael P. Reilly - http://www.speakeasy.org/~arcege/

Slightly modified to handle multiple signal registration/unregistration
in the base class.
"""

import types

class Signal_handler:
  """
  Create a mechanism to set a signal handler and reset when the instance
  is destroyed.
  """

  # the module is encapsulated in the class
  import posix_signal
  func = posix_signal.signal
  ignore = posix_signal.SIG_IGN

  def __init__(self, signals, handler=None):
    """
    Can take integer signal number (checked in the signal module)
    or the string name of a valid signal (encapsulated in an array)
    """
    self.sigvals_and_handlers = {}          # Dictionary
    for signal in signals:
      sigval = self._sigval(signal)
      
      if handler is None:
        handler = self.ignore
      elif not callable(handler):
        raise TypeError, "must supply a callable object"

      old_handler = self.func(sigval, handler)
      self.sigvals_and_handlers.setdefault(sigval,old_handler)

    self.handler = handler
  
  def _sigval(self, my_signal):
    if type(my_signal) is types.IntType:
      for name, val in vars(self.posix_signal).iteritems():
        if val == my_signal:
          break
      if val!=my_signal:
        raise ValueError, "must be a valid signal value " + str(my_signal)
      sigval=my_signal
    elif type(my_signal) is types.StringType:
      if my_signal[:3] != 'SIG':
        my_signal = 'SIG' + my_signal
        try:
          sigval = getattr(self.posix_signal, my_signal)
        except AttributeError:
          raise ValueError, "must be a valid signal name " + my_signal
    else:
      raise TypeError, "must supply a string or integer"

    return sigval
    
  def __del__(self):
    try:
      self.clear()
    except:
      pass

  def clear(self, my_signals=None):
    # having signal.signal be a class attribute keeps the function around
    # even if the signal module is destroyed
    if my_signals==None:
      my_signals=self.sigvals_and_handlers.iteritems.keys()

    for signal in my_signals:
      sigval=self._sigval(signal)
      old_handler = self.sigvals_and_handlers.pop(sigval)
      self.func(sigval, old_handler)
    
