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