]> andersk Git - sql.git/blob - lib/python/mitsql/interface/cheetah.py
implemented base interface
[sql.git] / lib / python / mitsql / interface / cheetah.py
1 import qwobl
2 import os, sys, types, time
3 import threading 
4 from pyinotify import WatchManager, Notifier, EventsCodes
5 from Cheetah.Template import Template as _Template
6 import logging
7
8 class Template(object):
9     def __init__(self, name='templates', ns={}, path=[]):
10         self._name, self._ns, self._path = name, ns, len(path) and path+[name] or [name]
11         if len(self._path) > 1:
12             assert self._template()
13     
14     def _template(self):
15         return sys.modules['.'.join(self._path)]
16     
17     def __getattr__(self, name):
18         return Template(name, self._ns, self._path)
19     
20     def __call__(self, **kw):
21         namespaces = self._ns.copy()
22         namespaces.update(kw)
23         return getattr(self._template(),
24                        self._name)(namespaces=namespaces).respond()
25
26 class Loader(object):
27     _mask = EventsCodes.ALL_FLAGS['IN_CREATE'] \
28           | EventsCodes.ALL_FLAGS['IN_MODIFY'] \
29           | EventsCodes.ALL_FLAGS['IN_DELETE'] \
30           | EventsCodes.ALL_FLAGS['IN_ATTRIB']
31     _watch_manager = None
32     _notifier = None
33     _thread = None
34     
35     _loaded = False
36     _files = {}
37     _modules = {}
38     
39     def __init__(self, global_namespace={}):
40         self._event_init()
41         self._assert_module('templates')
42         self._globals = global_namespace
43         self._thread = threading.Thread(target=self.loop)
44         self._thread.setDaemon(True)
45         self._thread.start()
46
47     def _tree_walk(self, tree, path, func):
48         path = list(path)
49         if len(path) > 1:
50             x = path.pop(0)
51             if not x in tree:
52                 tree[x] = {}
53             return self._tree_walk(tree[x], path, func)
54         elif callable(func):
55             return func(tree, path[0])
56
57     def _tree_add(self, tree, path, value):
58         def _add(tree, key):
59             tree[key] = value
60             return value
61         print self._tree_walk(tree, path, _add)
62     
63     def _assert_module(self, name, path=None):
64         if not name in self._modules:
65             self._modules[name] = types.ModuleType(name)
66             if path:
67                 self._modules[name].__path__ = path
68             sys.modules[name] = self._modules[name]
69     
70     def _get_template_path(self, path_name, template_file):
71         r = template_file.startswith(path_name) \
72           and template_file[len(path_name)+1:].split(os.path.sep) or []
73         if r[-1].endswith('.tmpl'):
74             r[-1] = r[-1][:-5]
75         return tuple(r)
76     
77     def _compile(self, template_path):
78         template = _Template.compile(file=self._files[template_path],
79                                      returnAClass=False,
80                                      moduleName='.'.join(['templates']+list(template_path)),
81                                      className=template_path[-1],
82                                      useCache=False,
83                                      compilerSettings={'useStackFrames':False})
84         return template
85     
86     def add(self, path_name, template_file):
87         template_path = self._get_template_path(path_name, template_file)
88         template_name = '.'.join(['templates']+list(template_path))
89         template_pkg = '.'.join(['templates']+list(template_path[:-1]))
90         template_py = os.path.join(os.path.dirname(template_file), '%s.py' % template_path[-1])
91         self._assert_module(template_pkg, [os.path.dirname(template_file)])
92         self._files[template_path] = template_file
93         code = self._compile(template_path)
94         f_code = file(template_py, 'w')
95         f_code.write(code)
96         f_code.close()
97         if template_name in sys.modules:
98             reload(sys.modules[template_name])
99     
100     def remove(self, template_file):
101         #print 'removing', template_file
102         pass
103     
104     def _walk_path(self, path_name):
105         def _walk_load(args, dname, fnames):
106             for fname in fnames:
107                 if fname.endswith('.tmpl'):
108                     template_file = os.path.join(dname, fname)
109                     self.add(path_name, template_file)
110         return _walk_load
111     
112     def load(self, path_name):
113         os.path.walk(path_name, self._walk_path(path_name), None)
114         for path, filename in self._files.items():
115             logging.debug('TEMPLATE LOAD [%s] %s', path, filename)
116             __import__('.'.join(['templates']+list(path)))
117         self._event_add_watch(path_name)
118     
119     def _path_event_handler(self, path_name):
120         def _event_handler(event):
121             logging.debug('TEMPLATE EVENT: %s', repr(event.__dict__.items()))
122             if event.name.endswith('.tmpl') and not event.name.startswith('.'):
123                 if event.maskname == 'IN_DELETE':
124                     self.remove(event.pathname)
125                 else:
126                     time.sleep(0.5)
127                     self.add(path_name, event.pathname)
128         return _event_handler
129     
130     def _event_init(self):
131         self._watch_manager = WatchManager()
132         self._notifier = Notifier(self._watch_manager)
133     
134     def _event_add_watch(self, path_name):
135         r = self._watch_manager.add_watch(path_name,
136                                           self._mask,
137                                           self._path_event_handler(path_name),
138                                           rec=True,
139                                           auto_add=True)
140     
141     def loop(self):
142         while True:
143             try:
144                 self._notifier.process_events()
145                 if self._notifier.check_events():
146                     self._notifier.read_events()
147             except KeyboardInterrupt:
148                 self._notifier.stop()
149                 break
150
151 _loader = Loader()
152 load = _loader.load
153 templates = Template()
154
155 __all__ = ['load', 'templates']
156
157 if __name__ == '__main__':
158     t = Loader('/home/joe/templates')
This page took 0.574654 seconds and 5 git commands to generate.