summaryrefslogtreecommitdiffstats
path: root/src/lib/Server/Plugins/TemplateHelper.py
blob: 42eafed566c8c45cb924f3458f11f83cfbe59598 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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())])