callbacks (version 0.1)
index
/Users/dewitt/svn/python-callbacks/callbacks.py

A library for creating, registering, and running callbacks and closures.
 
Features include:
 
  Scopes: Callbacks can be registered in instance, class, module or
  global scope.
 
  Priority levels: Callbacks can be given a priority, where higher
  priority callbacks will be run before lower priority callbacks.
 
  Automatic requeuing: Callbacks can be marked as 'permanent' to be
  requeued automatically after being executed.
 
  Callback chaining: Callbacks can be chained such that the result of
  the previous callback is used as the input for the next callback.
 
  Genericity: Any callable object (a Callback instance, a function, a
  anonymous lambda function, or a class-based closure) can be used as
  a callback.
 
  Iterators: Callbacks can be invoked automatically via
  RunAllCallbacks and RunCallbackChain, or iterated over manually with
  CallbackIterator and CopyFirstCallbackIterator.
 
Overview:
 
  A callback is callable code that can be registered and executed at
  some point in the future in a different context.  The callback
  pattern allows a library to handle arbitrary clients without knowing
  in advance what they will be.
 
  The callback registration mechanism that allows client code to tell
  a class or module about a method that should be executed at a point
  in time in the future.
 
  The library is used by two distinct groups: classes or modules that
  wish to register and execute callbacks, and clients that wish to
  register their code to be called back.
 
  Classes or modules that register and run callbacks should first
  write a wrapper function around the RegisterCallback method.  This
  method will be invoked by other classes and code that want to be
  called back at some point in the future.  E.g.:
 
>>> from callbacks import RegisterCallback, RunAllCallbacks
>>> 
>>> class CallbackHost(object):
...   def RegisterSomeCallback(self, callback):
...     '''Registers the callback to be invoked by RunAllCallbacks.'''
...     RegisterCallback(self, 'some callback', callback)
...
...   def RunTheCallbacks(self):
...     '''Returns the results (in a list) of  each registed callback.'''
...     return RunAllCallbacks(self, 'some callback')
 
 
  To use the registration methods, clients will provide a callback
  method in the form of a function, an anonymous lambda function, a
  class-based callable closure, or a CallbackPermanentCallback, or
  TemporaryCallback (or subclass) instance.
 
  After the callbacks have been registered, the class can run all of the
  registed callbacks automatically by executing the RunAllCallbacks
  method.  E.g.:
 
>>> from callbacks import PermanentCallbackCallback
 
>>> def MyCallback():
...   return 'MyCallback'
 
>>> host = CallbackHost()
>>> callback = PermanentCallback(MyCallback)
>>> host.RegisterSomeCallback(callback)
>>> host.RunTheCallbacks()
['MyCallback']
 
  Class-based closures can also be registered:
 
>>> class MyClosure(object):
...   def __init__(self, string):
...      self.string = string
...   def __call__(self):
...      return self.string
 
>>> callback = PermanentCallback(MyClosure('MyClosure'))
>>> host.RegisterSomeCallback(callback)
>>> host.RunTheCallbacks()
['MyCallback', 'MyClosure']
 
  As can higher-priority callbacks:
 
>>> callback = PermanentCallback(MyClosure('High priority'), priority=10)
>>> host.RegisterSomeCallback(callback)
>>> host.RunTheCallbacks()
['High priority', 'MyCallback', 'MyClosure']
 
  By default, callbacks expire after being run once:
 
>>> callback = Callback(MyClosure('Run once'))
>>> host.RegisterSomeCallback(callback)
>>> host.RunTheCallbacks()
['High priority', 'MyCallback', 'MyClosure', 'Run once']
>>> host.RunTheCallbacks()
['High priority', 'MyCallback', 'MyClosure']
 
 
Another Example:
  
  Imagine a TextProcessor class that is used to modify text.  The
  TextProcessor want to allow callers to provide their own text
  processing routines, and does so via a RegisterProcessor method.
  When the Process method is invoked, so are the registered text
  processors.
 
>>> import callbacks
 
>>> class TextProcessor(object):
...   '''A class that modifies text according to registered callbacks.'''
...
...   def RegisterProcessor(self, callback):
...     '''Registers a callback to be invoked when the text.'''
...     callbacks.RegisterCallback(self, 'process', callback)
...
...   def Process(self, text):
...     '''Runs all of the registered callbacks to process the text.'''
...     return callbacks.RunCallbackChain(self, 'process', text)
  
 
And defined elsewhere:
 
>>> import re
 
>>> def Capitalize(text):
...   '''Returns the text with the first character capitalized.'''
...   return text.capitalize()
 
>>> def CompactWhitespace(text):
...   '''Returns the text with successive whitespace characters collapsed.'''
...   return re.sub('\s+', ' ', text)     
 
>>> processor = TextProcessor()
>>> processor.RegisterProcessor(Capitalize)
>>> processor.RegisterProcessor(CompactWhitespace)
>>> processor.Process('four  score and  seven  years    ago...')
'Four score and seven years ago...'
 
 
Limitations and TODOs:
 
  Function signatures are not validated.  Helper code could be written
  to match callback signatures against a function specification or
  against a reference function.
 
  Exceptions raised by callbacks are not handled automatically yet.
 
  Automatic registration and execution wrappers could be created to
  simplify the one-line boilerplate functions.

 
Modules
       
Queue
heapq
inspect

 
Classes
       
Queue.Queue
PriorityQueue
__builtin__.object
Callback
PermanentCallback
TemporaryCallback

 
class Callback(__builtin__.object)
    A class wrapper around functions to be executed in the future.
 
  Methods defined here:
__call__(self, *args, **kwargs)
Runs the callback function, lambda, or callable closure.
__init__(self, callback, permanent=False, priority=0)
Creates a new callback instance.
 
Args:
  callback: The function, labmda, or callable closure to be executed.
  permanent: This callback should be requeued after being executed.
  priority: This callback will be run before callbacks of lower priority.

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class PermanentCallback(Callback)
    Callback that will be requeued after execution.
 
 
Method resolution order:
PermanentCallback
Callback
__builtin__.object

Methods defined here:
__init__(self, callback, priority=0)
Creates a new permaent callback instance.
 
Args:
  callback: The function, labmda, or callable closure to be executed.
  priority: This callback will be run before callbacks of lower priority.

Methods inherited from Callback:
__call__(self, *args, **kwargs)
Runs the callback function, lambda, or callable closure.

Data descriptors inherited from Callback:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class PriorityQueue(Queue.Queue)
    Implements a stable, heap-based, synchronized priority queue.
 
  Methods defined here:
__iter__(self)
put(self, item, priority=0, *args, **kwargs)
Puts the item into the queue. 
 
Items are enqueued to be retrieved in FIFO order based on their
priority group.
 
Args:
  item: The data to be enqueued.
  priority:  
    Higher priority items are retrieved before lower priority
    items.  Optional, default 0.
  block:
    If optional args block is true and timeout is None (the default),
    block if necessary until a free slot is available. 
  timeout:
    If timeout is a positive number, it blocks at most timeout
    seconds and raises the Full exception if no free slot was
    available within that time. Otherwise (block is false), put an
    item on the queue if a free slot is immediately available,
    else raise the Full exception (timeout is ignored in that
    case).

Methods inherited from Queue.Queue:
__init__(self, maxsize=0)
empty(self)
Return True if the queue is empty, False otherwise (not reliable!).
full(self)
Return True if the queue is full, False otherwise (not reliable!).
get(self, block=True, timeout=None)
Remove and return an item from the queue.
 
If optional args 'block' is true and 'timeout' is None (the default),
block if necessary until an item is available. If 'timeout' is
a positive number, it blocks at most 'timeout' seconds and raises
the Empty exception if no item was available within that time.
Otherwise ('block' is false), return an item if one is immediately
available, else raise the Empty exception ('timeout' is ignored
in that case).
get_nowait(self)
Remove and return an item from the queue without blocking.
 
Only get an item if one is immediately available. Otherwise
raise the Empty exception.
join(self)
Blocks until all items in the Queue have been gotten and processed.
 
The count of unfinished tasks goes up whenever an item is added to the
queue. The count goes down whenever a consumer thread calls task_done()
to indicate the item was retrieved and all work on it is complete.
 
When the count of unfinished tasks drops to zero, join() unblocks.
put_nowait(self, item)
Put an item into the queue without blocking.
 
Only enqueue the item if a free slot is immediately available.
Otherwise raise the Full exception.
qsize(self)
Return the approximate size of the queue (not reliable!).
task_done(self)
Indicate that a formerly enqueued task is complete.
 
Used by Queue consumer threads.  For each get() used to fetch a task,
a subsequent call to task_done() tells the queue that the processing
on the task is complete.
 
If a join() is currently blocking, it will resume when all items
have been processed (meaning that a task_done() call was received
for every item that had been put() into the queue).
 
Raises a ValueError if called more times than there were items
placed in the queue.

 
class TemporaryCallback(Callback)
    Callback that will not be requeued after execution.
 
 
Method resolution order:
TemporaryCallback
Callback
__builtin__.object

Methods defined here:
__init__(self, callback, priority=0)
Creates a new temporary callback instance.
 
Args:
  callback: The function, labmda, or callable closure to be executed.
  priority: This callback will be run before callbacks of lower priority.

Methods inherited from Callback:
__call__(self, *args, **kwargs)
Runs the callback function, lambda, or callable closure.

Data descriptors inherited from Callback:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
Functions
       
CallbackIterator(scope, name)
Returns an iterator over each named callback in priority order.
 
This iterator keeps a copy of all permanent callbacks, and after the
last callback has been executed, resets the callback queue with the
saved permanent callbacks.
 
Care must be taken to ensure that the iterator is run through to the
end, as the permament callbacks are only reset after the final
callback has been run.
 
See also CopyFirstCallbackIterator for an iterator that resets
permanent callbacks immediately, at the expense of making a copy
of the list beforehand.
 
Args:
  scope: A module, a class, an instance, or None (for the global scope)
  name: The name associated with this callback
Returns:
  An iterator over a copy of the named callbacks.
ClearAllCallbacks(scope)
Clears all callbacks within a given scope.
 
Args:
  scope: A module, a class, an instance, or None (for the global scope)
ClearCallbacks(scope, name)
CopyFirstCallbackIterator(scope, name)
Returns an iterator over each named callback in priority order.
 
This iterator makes a copy of the list of callbacks prior to
beginning the iteration so that permanent callbacks can be requeued
immediately.
 
See also CallbackIterator for an iterator that avoids the overhead
of making a copy up front, but needs to be run to completion to
requeue the permanent callbacks.
 
Args:
  scope: A module, a class, an instance, or None (for the global scope)
  name: The name associated with this callback
Returns:
  An iterator over a copy of the named callbacks.
RegisterCallback(scope, name, callback, permanent=False, priority=0)
Registers a new callback to be executed in the future.
 
Args:
  scope: A module, a class, an instance, or None (for the global scope)
  name: The name associated with this callback
  callback: A Callback instance, a function, or other callable object
  permanent: This callback should be requeued after being executed.
  priority: Set or override the priority with the specified value
RunAllCallbacks(scope, name, *args, **kwargs)
Executes all of the callbacks within a given scope in priority order.
 
Args:
  scope: A module, a class, an instance, or None (for the global scope)
  name: The name associated with the callbacks to be executed
  args:  Additional positional arguments for the callback
  kwargs:  Additional keyword arguments for the callback
Returns:
  A list of the results from each executed callback
RunCallbackChain(scope, name, param, *args, **kwargs)
Executes all of the callbacks with the previous callback as a parameter.
 
Args:
  scope: A module, a class, an instance, or None (for the global scope)
  name: The name associated with the callbacks to be executed
  param: The in_args to the first callback in the chain.
  args:  Additional positional arguments for the callback
  kwargs:  Additional keyword arguments for the callback
Returns:
  The final callback's result.

 
Data
        __author__ = 'dewitt@unto.net'
__version__ = '0.1'

 
Author
        dewitt@unto.net