Ticket #1301: turbokid_reload_and_filter.patch
| File turbokid_reload_and_filter.patch, 7.9 kB (added by chrisz, 2 years ago) |
|---|
-
kidsupport.py
old new 32 32 class KidSupport(object): 33 33 #XXX: Is itertools.count threadsafe? 34 34 string_template_serial = itertools.count() 35 35 36 36 def __init__(self, extra_vars_func=None, options=None): 37 37 if options is None: 38 38 options = dict() … … 43 43 self.sitetemplate = None 44 44 self.stname = options.get("kid.sitetemplate", None) 45 45 self.compiled_templates = {} 46 46 47 47 def load_template_string(self, template_string): 48 48 assert isinstance(template_string, basestring) 49 49 tempclass = kid.load_template( 50 template_string, 50 template_string, 51 51 name = "KidTemplateFromString-%d" % self.string_template_serial.next() 52 52 ).Template 53 53 tempclass.serializer = self.serializer 54 54 return tempclass 55 55 56 56 def load_template(self, classname=None, template_string=None, loadingSite=False): 57 57 """Searches for a template along the Python path. 58 58 59 59 Template files must end in ".kid" and be in legitimate packages. 60 60 If the templates are precompiled to ".pyc" files, you can 61 set the "kid.precompiled" option to 61 set the "kid.precompiled" option to 62 62 just do a straight import of the template. 63 63 """ 64 64 65 65 if template_string is not None: 66 66 return self.load_template_string(template_string) 67 67 elif classname is None: … … 73 73 self.load_template(self.stname, loadingSite=True) 74 74 sys.modules["sitetemplate"] = sys.modules[self.stname] 75 75 self.sitetemplate = sys.modules["sitetemplate"] 76 76 77 77 divider = classname.rfind(".") 78 78 if divider > -1: 79 79 package = classname[0:divider] 80 80 basename = classname[divider+1:] 81 81 else: 82 82 raise ValueError, "All templates must be in a package" 83 84 if not self.options.get("kid.precompiled", False): 85 tfile = pkg_resources.resource_filename(package, 86 "%s.kid" % basename) 83 84 if self.options.get("kid.precompiled", False): 85 # Always use the precompiled template since this is what 86 # the config says. 87 mod = __import__(classname, dict(), dict(), [basename]) 88 else: 89 tfile = pkg_resources.resource_filename( 90 package, "%s.kid" % basename) 87 91 ct = self.compiled_templates 88 92 if sys.modules.has_key(classname) and ct.has_key(classname): 89 93 # This means that in sys.modules there is already the compiled … … 92 96 # In this case we may need to recompile because the template 93 97 # itself or one of its bases could have been modified. 94 98 tclass = sys.modules[classname].Template 95 involved_modules = [classname] + _get_extended_modules(tclass) 96 # Check the status of every involved module, if the module has 97 # been modified remove it from sys.modules, update its mtime 98 # and set to True the reload_template flag. 99 reload_template = False 100 for module in involved_modules: 99 ttime = ct[classname] 100 mtime = os.stat(sys.modules[classname].__file__).st_mtime 101 reload_template = mtime > ttime 102 if reload_template: 103 ttime = mtime 104 # Check the status of all base moduls. 105 for module in _get_extended_modules(tclass): 101 106 mtime = os.stat(sys.modules[module].__file__).st_mtime 102 if ct[module] != mtime: 107 if mtime > ct[module]: 108 # base template has changed 103 109 del sys.modules[module] 104 110 ct[module] = mtime 105 111 reload_template = True 106 112 if mtime > ttime: 113 # base module has changed 114 reload_template = True 115 ttime = mtime 107 116 if reload_template: 108 117 # We need to recompile the template. 109 118 log.debug("Recompiling template for %s" % classname) 110 # If the template module is still in sys.modules (this 111 # means that the template has not been modified but one or 112 # more of its base templates have been) remove it 113 # otherwise Kid will not recompile the removed bases 114 # templates giving us a NoneType error. 115 if sys.modules.has_key(classname): 116 del sys.modules[classname] 117 mod = _compile_template(package, basename, 118 tfile, classname) 119 del sys.modules[classname] 120 ct[classname] = ttime 121 mod = _compile_template( 122 package, basename, tfile, classname) 119 123 else: 120 # No need to recompile the template or its bases, 124 # No need to recompile the template or its bases, 121 125 # just reuse the existing modules. 122 126 mod = __import__(classname, dict(), dict(), [basename]) 123 127 else: … … 127 131 log.debug("Compiling template for %s" % classname) 128 132 mod = _compile_template(package, basename, tfile, classname) 129 133 tclass = mod.Template 130 involved_modules = [classname] + _get_extended_modules(tclass) 131 for module in involved_modules: 132 ct[module] = os.stat(sys.modules[module].__file__).st_mtime 133 else: 134 # Always use the precompiled template since this is what 135 # the config says. 136 mod = __import__(classname, dict(), dict(), [basename]) 134 ttime = os.stat(sys.modules[classname].__file__).st_mtime 135 for module in _get_extended_modules(tclass): 136 mtime = os.stat(sys.modules[module].__file__).st_mtime 137 ct[module] = mtime 138 if mtime > ttime: 139 ttime = mtime 140 # Store max of mtimes of template and all of its bases 141 ct[classname] = ttime 137 142 138 143 tempclass = mod.Template 139 144 tempclass.serializer = self.serializer … … 141 146 142 147 def render(self, info, format="html", fragment=False, template=None): 143 148 """Renders data in the desired format. 144 149 145 150 @param info: the data itself 146 151 @type info: dict 147 152 @param format: "html", "xml" or "json" … … 169 174 if options.get("kid.assume_encoding", "utf-8"): 170 175 t.assume_encoding = options.get("kid.assume_encoding", "utf-8") 171 176 if options.get("kid.i18n.run_template_filter", False): 172 t._filters+=[options.get("kid.i18n_filter")] 173 177 filter = options.get("kid.i18n_filter") 178 if callable(filter) and filter not in t._filters: 179 t._filters.append(filter) 180 174 181 return t.serialize(encoding=self.defaultencoding, output=format, fragment=fragment) 175 182 176 183 def transform(self, info, template): … … 182 189 if self.get_extra_vars: 183 190 data.update(self.get_extra_vars()) 184 191 data.update(info) 185 192 186 193 t = tclass(**data) 187 194 188 195 options = self.options 189 196 if options.get("kid.i18n.run_template_filter", False): 190 t._filters+=[options.get("kid.i18n_filter")] 197 filter = options.get("kid.i18n_filter") 198 if callable(filter) and filter not in t._filters: 199 t._filters.append(filter) 200 191 201 return ElementStream(t.transform()).expand() 192