loaders.py (9235B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\jinja2\loaders.py 2 import os 3 import sys 4 import weakref 5 from types import ModuleType 6 from os import path 7 try: 8 from hashlib import sha1 9 except ImportError: 10 from sha import new as sha1 11 12 from jinja2.exceptions import TemplateNotFound 13 from jinja2.utils import LRUCache, open_if_exists, internalcode 14 15 def split_template_path(template): 16 pieces = [] 17 for piece in template.split('/'): 18 if path.sep in piece or path.altsep and path.altsep in piece or piece == path.pardir: 19 raise TemplateNotFound(template) 20 elif piece and piece != '.': 21 pieces.append(piece) 22 23 return pieces 24 25 26 class BaseLoader(object): 27 has_source_access = True 28 29 def get_source(self, environment, template): 30 if not self.has_source_access: 31 raise RuntimeError('%s cannot provide access to the source' % self.__class__.__name__) 32 raise TemplateNotFound(template) 33 34 def list_templates(self): 35 raise TypeError('this loader cannot iterate over all templates') 36 37 @internalcode 38 def load(self, environment, name, globals = None): 39 code = None 40 if globals is None: 41 globals = {} 42 source, filename, uptodate = self.get_source(environment, name) 43 bcc = environment.bytecode_cache 44 if bcc is not None: 45 bucket = bcc.get_bucket(environment, name, filename, source) 46 code = bucket.code 47 if code is None: 48 code = environment.compile(source, name, filename) 49 if bcc is not None and bucket.code is None: 50 bucket.code = code 51 bcc.set_bucket(bucket) 52 return environment.template_class.from_code(environment, code, globals, uptodate) 53 54 55 class FileSystemLoader(BaseLoader): 56 57 def __init__(self, searchpath, encoding = 'utf-8'): 58 if isinstance(searchpath, basestring): 59 searchpath = [searchpath] 60 self.searchpath = list(searchpath) 61 self.encoding = encoding 62 63 def get_source(self, environment, template): 64 pieces = split_template_path(template) 65 for searchpath in self.searchpath: 66 filename = path.join(searchpath, *pieces) 67 f = open_if_exists(filename) 68 if f is None: 69 continue 70 try: 71 contents = f.read().decode(self.encoding) 72 finally: 73 f.close() 74 75 mtime = path.getmtime(filename) 76 77 def uptodate(): 78 try: 79 return path.getmtime(filename) == mtime 80 except OSError: 81 return False 82 83 return (contents, filename, uptodate) 84 85 raise TemplateNotFound(template) 86 87 def list_templates(self): 88 found = set() 89 for searchpath in self.searchpath: 90 for dirpath, dirnames, filenames in os.walk(searchpath): 91 for filename in filenames: 92 template = os.path.join(dirpath, filename)[len(searchpath):].strip(os.path.sep).replace(os.path.sep, '/') 93 if template[:2] == './': 94 template = template[2:] 95 if template not in found: 96 found.add(template) 97 98 return sorted(found) 99 100 101 class PackageLoader(BaseLoader): 102 103 def __init__(self, package_name, package_path = 'templates', encoding = 'utf-8'): 104 from pkg_resources import DefaultProvider, ResourceManager, get_provider 105 provider = get_provider(package_name) 106 self.encoding = encoding 107 self.manager = ResourceManager() 108 self.filesystem_bound = isinstance(provider, DefaultProvider) 109 self.provider = provider 110 self.package_path = package_path 111 112 def get_source(self, environment, template): 113 pieces = split_template_path(template) 114 p = '/'.join((self.package_path,) + tuple(pieces)) 115 if not self.provider.has_resource(p): 116 raise TemplateNotFound(template) 117 filename = uptodate = None 118 if self.filesystem_bound: 119 filename = self.provider.get_resource_filename(self.manager, p) 120 mtime = path.getmtime(filename) 121 122 def uptodate(): 123 try: 124 return path.getmtime(filename) == mtime 125 except OSError: 126 return False 127 128 source = self.provider.get_resource_string(self.manager, p) 129 return (source.decode(self.encoding), filename, uptodate) 130 131 def list_templates(self): 132 path = self.package_path 133 if path[:2] == './': 134 path = path[2:] 135 elif path == '.': 136 path = '' 137 offset = len(path) 138 results = [] 139 140 def _walk(path): 141 for filename in self.provider.resource_listdir(path): 142 fullname = path + '/' + filename 143 if self.provider.resource_isdir(fullname): 144 _walk(fullname) 145 else: 146 results.append(fullname[offset:].lstrip('/')) 147 148 _walk(path) 149 results.sort() 150 return results 151 152 153 class DictLoader(BaseLoader): 154 155 def __init__(self, mapping): 156 self.mapping = mapping 157 158 def get_source(self, environment, template): 159 if template in self.mapping: 160 source = self.mapping[template] 161 return (source, None, lambda : source != self.mapping.get(template)) 162 raise TemplateNotFound(template) 163 164 def list_templates(self): 165 return sorted(self.mapping) 166 167 168 class FunctionLoader(BaseLoader): 169 170 def __init__(self, load_func): 171 self.load_func = load_func 172 173 def get_source(self, environment, template): 174 rv = self.load_func(template) 175 if rv is None: 176 raise TemplateNotFound(template) 177 elif isinstance(rv, basestring): 178 return (rv, None, None) 179 return rv 180 181 182 class PrefixLoader(BaseLoader): 183 184 def __init__(self, mapping, delimiter = '/'): 185 self.mapping = mapping 186 self.delimiter = delimiter 187 188 def get_loader(self, template): 189 try: 190 prefix, name = template.split(self.delimiter, 1) 191 loader = self.mapping[prefix] 192 except (ValueError, KeyError): 193 raise TemplateNotFound(template) 194 195 return (loader, name) 196 197 def get_source(self, environment, template): 198 loader, name = self.get_loader(template) 199 try: 200 return loader.get_source(environment, name) 201 except TemplateNotFound: 202 raise TemplateNotFound(template) 203 204 @internalcode 205 def load(self, environment, name, globals = None): 206 loader, local_name = self.get_loader(name) 207 try: 208 return loader.load(environment, local_name) 209 except TemplateNotFound: 210 raise TemplateNotFound(name) 211 212 def list_templates(self): 213 result = [] 214 for prefix, loader in self.mapping.iteritems(): 215 for template in loader.list_templates(): 216 result.append(prefix + self.delimiter + template) 217 218 return result 219 220 221 class ChoiceLoader(BaseLoader): 222 223 def __init__(self, loaders): 224 self.loaders = loaders 225 226 def get_source(self, environment, template): 227 for loader in self.loaders: 228 try: 229 return loader.get_source(environment, template) 230 except TemplateNotFound: 231 pass 232 233 raise TemplateNotFound(template) 234 235 @internalcode 236 def load(self, environment, name, globals = None): 237 for loader in self.loaders: 238 try: 239 return loader.load(environment, name, globals) 240 except TemplateNotFound: 241 pass 242 243 raise TemplateNotFound(name) 244 245 def list_templates(self): 246 found = set() 247 for loader in self.loaders: 248 found.update(loader.list_templates()) 249 250 return sorted(found) 251 252 253 class _TemplateModule(ModuleType): 254 pass 255 256 257 class ModuleLoader(BaseLoader): 258 has_source_access = False 259 260 def __init__(self, path): 261 package_name = '_jinja2_module_templates_%x' % id(self) 262 mod = _TemplateModule(package_name) 263 if isinstance(path, basestring): 264 path = [path] 265 else: 266 path = list(path) 267 mod.__path__ = path 268 sys.modules[package_name] = weakref.proxy(mod, lambda x: sys.modules.pop(package_name, None)) 269 self.module = mod 270 self.package_name = package_name 271 272 @staticmethod 273 def get_template_key(name): 274 return 'tmpl_' + sha1(name.encode('utf-8')).hexdigest() 275 276 @staticmethod 277 def get_module_filename(name): 278 return ModuleLoader.get_template_key(name) + '.py' 279 280 @internalcode 281 def load(self, environment, name, globals = None): 282 key = self.get_template_key(name) 283 module = '%s.%s' % (self.package_name, key) 284 mod = getattr(self.module, module, None) 285 if mod is None: 286 try: 287 mod = __import__(module, None, None, ['root']) 288 except ImportError: 289 raise TemplateNotFound(name) 290 291 sys.modules.pop(module, None) 292 return environment.template_class.from_module_dict(environment, mod.__dict__, globals)