text: import re
  import imp
  import sys
  import logging
  import Bcfg2.Server.Plugin
  
  logger = logging.getLogger(__name__)
  
  class HelperModule(Bcfg2.Server.Plugin.SpecificData):
      _module_name_re = re.compile(r'([^/]+?)\.py')
  
      def __init__(self, name, specific, encoding):
          Bcfg2.Server.Plugin.SpecificData.__init__(self, name, specific,
                                                    encoding)
          match = self._module_name_re.search(self.name)
          if match:
              self._module_name = match.group(1)
          else:
              self._module_name = name
          self._attrs = []
  
      def handle_event(self, event):
          Bcfg2.Server.Plugin.SpecificData.handle_event(self, event)
          try:
              module = imp.load_source(self._module_name, self.name)
          except:
              err = sys.exc_info()[1]
              logger.error("TemplateHelper: Failed to import %s: %s" %
                           (self.name, err))
              return
  
          if not hasattr(module, "__export__"):
              logger.error("TemplateHelper: %s has no __export__ list" %
                           self.name)
              return
  
          for sym in module.__export__:
              if sym not in self._attrs and hasattr(self, sym):
                  logger.warning("TemplateHelper: %s: %s is a reserved keyword, "
                                 "skipping export" % (self.name, sym))
              setattr(self, sym, getattr(module, sym))
          # remove old exports
          for sym in set(self._attrs) - set(module.__export__):
              delattr(self, sym)
  
          self._attrs = module.__export__
  
  
  class HelperSet(Bcfg2.Server.Plugin.EntrySet):
      ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\.py[co])$")
  
      def __init__(self, path, fam, encoding, plugin_name):
          fpattern = '[0-9A-Za-z_\-]+\.py'
          self.plugin_name = plugin_name
          Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path,
                                                HelperModule, encoding)
          fam.AddMonitor(path, self)
  
      def HandleEvent(self, event):
          if (event.filename != self.path and
              not self.ignore.match(event.filename)):
              return self.handle_event(event)
  
  
  class TemplateHelper(Bcfg2.Server.Plugin.Plugin,
                       Bcfg2.Server.Plugin.Connector):
      """ A plugin to provide helper classes and functions to templates """
      name = 'TemplateHelper'
      __author__ = 'chris.a.st.pierre@gmail.com'
  
      def __init__(self, core, datastore):
          Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
          Bcfg2.Server.Plugin.Connector.__init__(self)
  
          try:
              self.helpers = HelperSet(self.data, core.fam, core.encoding,
                                       self.name)
          except:
              raise Bcfg2.Server.Plugin.PluginInitError
  
      def get_additional_data(self, metadata):
          return dict([(h._module_name, h)
                       for h in list(self.helpers.entries.values())])
  