Ticket #485: template-encoding-bugfix.diff
| File template-encoding-bugfix.diff, 6.1 KB (added by hodgestar, 12 years ago) |
|---|
-
genshi/template/loader.py
14 14 """Template loading and caching.""" 15 15 16 16 import os 17 import codecs 17 18 try: 18 19 import threading 19 20 except ImportError: … … 21 22 22 23 from genshi.template.base import TemplateError 23 24 from genshi.util import LRUCache 25 from genshi.compat import StringIO 24 26 25 27 __all__ = ['TemplateLoader', 'TemplateNotFound', 'directory', 'package', 26 28 'prefixed'] … … 120 122 """Whether templates should be reloaded when the underlying file is 121 123 changed""" 122 124 123 self.default_encoding = default_encoding 125 if default_encoding is None: 126 self.default_encoding = "utf-8" 127 else: 128 self.default_encoding = default_encoding 124 129 self.default_class = default_class or MarkupTemplate 125 130 self.variable_lookup = variable_lookup 126 131 self.allow_exec = allow_exec … … 183 188 184 189 filename = os.path.normpath(filename) 185 190 cachekey = filename 191 if encoding is None: 192 encoding = self.default_encoding 186 193 187 194 self._lock.acquire() 188 195 try: … … 220 227 if isinstance(loadfunc, basestring): 221 228 loadfunc = directory(loadfunc) 222 229 try: 223 filepath, filename, fileobj, uptodate = loadfunc(filename) 230 filepath, filename, fileobj, uptodate = loadfunc(filename, 231 encoding) 224 232 except IOError: 225 233 continue 226 234 else: … … 233 241 # search path 234 242 filename = filepath 235 243 tmpl = self._instantiate(cls, fileobj, filepath, 236 filename , encoding=encoding)244 filename) 237 245 if self.callback: 238 246 self.callback(tmpl) 239 247 self._cache[cachekey] = tmpl … … 248 256 finally: 249 257 self._lock.release() 250 258 251 def _instantiate(self, cls, fileobj, filepath, filename , encoding=None):259 def _instantiate(self, cls, fileobj, filepath, filename): 252 260 """Instantiate and return the `Template` object based on the given 253 261 class and parameters. 254 262 … … 262 270 :param filepath: the absolute path to the template file 263 271 :param filename: the path to the template file relative to the search 264 272 path 265 :param encoding: the encoding of the template to load; defaults to the266 ``default_encoding`` of the loader instance267 273 :return: the loaded `Template` instance 268 274 :rtype: `Template` 269 275 """ 270 if encoding is None: 271 encoding = self.default_encoding 276 # encoding here is always None because the encoding has already 277 # been handled by opening the file using codec.open(...) under 278 # Python 2.x or open(...) under Python 3.x. 272 279 return cls(fileobj, filepath=filepath, filename=filename, loader=self, 273 encoding= encoding, lookup=self.variable_lookup,280 encoding=None, lookup=self.variable_lookup, 274 281 allow_exec=self.allow_exec) 275 282 276 283 @staticmethod … … 281 288 :return: the loader function to load templates from the given directory 282 289 :rtype: ``function`` 283 290 """ 284 def _load_from_directory(filename ):291 def _load_from_directory(filename, encoding): 285 292 filepath = os.path.join(path, filename) 286 fileobj = open(filepath, 'rU')293 fileobj = codecs.open(filepath, 'rU', encoding=encoding) 287 294 mtime = os.path.getmtime(filepath) 288 295 def _uptodate(): 289 296 return mtime == os.path.getmtime(filepath) … … 300 307 :rtype: ``function`` 301 308 """ 302 309 from pkg_resources import resource_stream 303 def _load_from_package(filename ):310 def _load_from_package(filename, encoding): 304 311 filepath = os.path.join(path, filename) 305 return filepath, filename, resource_stream(name, filepath), None 312 # TODO: read file iteratively 313 bytes_stream = resource_stream(name, filepath) 314 file_stream = StringIO(bytes_stream.read().decode(encoding)) 315 return filepath, filename, file_stream, None 306 316 return _load_from_package 307 317 308 318 @staticmethod … … 314 324 request to the delegate. 315 325 316 326 >>> load = prefixed( 317 ... app1 = lambda filename : ('app1', filename, None, None),318 ... app2 = lambda filename : ('app2', filename, None, None)327 ... app1 = lambda filename, enc: ('app1', filename, None, None), 328 ... app2 = lambda filename, enc: ('app2', filename, None, None) 319 329 ... ) 320 >>> print(load('app1/foo.html' ))330 >>> print(load('app1/foo.html', 'utf-8')) 321 331 ('app1', 'app1/foo.html', None, None) 322 >>> print(load('app2/bar.html' ))332 >>> print(load('app2/bar.html', 'utf-8')) 323 333 ('app2', 'app2/bar.html', None, None) 324 334 325 335 :param delegates: mapping of path prefixes to loader functions 326 336 :return: the loader function 327 337 :rtype: ``function`` 328 338 """ 329 def _dispatch_by_prefix(filename ):339 def _dispatch_by_prefix(filename, encoding): 330 340 for prefix, delegate in delegates.items(): 331 341 if filename.startswith(prefix): 332 342 if isinstance(delegate, basestring): 333 343 delegate = directory(delegate) 334 344 filepath, _, fileobj, uptodate = delegate( 335 filename[len(prefix):].lstrip('/\\') 345 filename[len(prefix):].lstrip('/\\'), 346 encoding 336 347 ) 337 348 return filepath, filename, fileobj, uptodate 338 349 raise TemplateNotFound(filename, list(delegates.keys()))
