2 import os, sys, types, time
4 from pyinotify import WatchManager, Notifier, EventsCodes
5 from Cheetah.Template import Template as _Template
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()
15 return sys.modules['.'.join(self._path)]
17 def __getattr__(self, name):
18 return Template(name, self._ns, self._path)
20 def __call__(self, **kw):
21 namespaces = self._ns.copy()
23 return getattr(self._template(),
24 self._name)(namespaces=namespaces).respond()
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']
39 def __init__(self, global_namespace={}):
41 self._assert_module('templates')
42 self._globals = global_namespace
43 self._thread = threading.Thread(target=self.loop)
44 self._thread.setDaemon(True)
47 def _tree_walk(self, tree, path, func):
53 return self._tree_walk(tree[x], path, func)
55 return func(tree, path[0])
57 def _tree_add(self, tree, path, value):
61 print self._tree_walk(tree, path, _add)
63 def _assert_module(self, name, path=None):
64 if not name in self._modules:
65 self._modules[name] = types.ModuleType(name)
67 self._modules[name].__path__ = path
68 sys.modules[name] = self._modules[name]
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'):
77 def _compile(self, template_path):
78 template = _Template.compile(file=self._files[template_path],
80 moduleName='.'.join(['templates']+list(template_path)),
81 className=template_path[-1],
83 compilerSettings={'useStackFrames':False})
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')
97 if template_name in sys.modules:
98 reload(sys.modules[template_name])
100 def remove(self, template_file):
101 #print 'removing', template_file
104 def _walk_path(self, path_name):
105 def _walk_load(args, dname, fnames):
107 if fname.endswith('.tmpl'):
108 template_file = os.path.join(dname, fname)
109 self.add(path_name, template_file)
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)
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)
127 self.add(path_name, event.pathname)
128 return _event_handler
130 def _event_init(self):
131 self._watch_manager = WatchManager()
132 self._notifier = Notifier(self._watch_manager)
134 def _event_add_watch(self, path_name):
135 r = self._watch_manager.add_watch(path_name,
137 self._path_event_handler(path_name),
144 self._notifier.process_events()
145 if self._notifier.check_events():
146 self._notifier.read_events()
147 except KeyboardInterrupt:
148 self._notifier.stop()
153 templates = Template()
155 __all__ = ['load', 'templates']
157 if __name__ == '__main__':
158 t = Loader('/home/joe/templates')