It should be clear by this point that the ability to use a general context as the namespace when executing code permits some complex behaviors to be implemented simply. There are circumstances where it would be useful to replace the namespace of a function with a context. The context_function module provides some tools for doing this.
This example shows how to set up a simple listening data context that displays changes within a function’s local namespace as it executes:
from traits.api import HasTraits, on_trait_change from codetools.contexts.api import DataContext, context_function class ListeningDataContext(DataContext): """ A simple subclass of DataContext which listens for items_modified events and pretty-prints them.""" @on_trait_change('items_modified') def print_event(self, event): print "Event: items_modified" for added in event.added: print " Added:", added, "=", repr(self[added]) for modified in event.modified: print " Modified:", modified, "=", repr(self[modified]) for removed in event.removed: print " Removed:", removed def f(x, t=3): """ A function which fires add, modify and delete events. """ y = x+2 y += 1 z = '12' del z return y f = context_function(f, ListeningDataContext)
The functionality is also available as a function decorator:
@local_context(ListeningDataContext) def f(x, t=3): """ A function which will fire add, modify and delete events. """ y = x+2 y += 1 z = '12' del z return y
The context_function() and local_context() functions both take an argument which is a context factory: each invocation of the function results in a call to the context factory. In most cases it returns a freshly created context.