def get_source(self, environment, template): # keep legacy asset: prefix checking that bypasses # source path checking altogether if template.startswith('asset:'): template = template[6:] # split the template into the chain of relative-imports rel_chain = template.split(PARENT_RELATIVE_DELIM) template, rel_chain = rel_chain[0], rel_chain[1:] # load the template directly if it's an absolute path or asset spec if os.path.isabs(template) or ':' in template: src = self._get_absolute_source(template) if src is not None: return src else: # fallback to the search path just incase return FileSystemLoader.get_source(self, environment, template) # try to import the template as an asset spec or absolute path # relative to its parents rel_searchpath = self._relative_searchpath(rel_chain) for parent in rel_searchpath: if os.path.isabs(parent): uri = os.path.join(parent, template) # avoid recursive includes if uri not in rel_chain: src = self._get_absolute_source(uri) if src is not None: return src # avoid doing "':' in" and then redundant "split" parts = parent.split(':', 1) if len(parts) > 1: # parent is an asset spec ppkg, ppath = parts ppath = posixpath.join(ppath, template) uri = '{0}:{1}'.format(ppkg, ppath) # avoid recursive includes if uri not in rel_chain: src = self._get_absolute_source(uri) if src is not None: return src # try to load the template from the default search path for parent in rel_searchpath: try: uri = os.path.join(parent, template) # avoid recursive includes if uri not in rel_chain: return FileSystemLoader.get_source(self, environment, uri) except TemplateNotFound: pass # we're here because of an exception during the last step so extend # the message and raise an appropriate error # there should always be an exception because the rel_searchpath is # guaranteed to contain at least one element ('') searchpath = [p for p in rel_searchpath if p] + self.searchpath message = '{0}; searchpath={1}'.format(template, searchpath) raise TemplateNotFound(name=template, message=message)
def get_source(self, environment, template): # Check if dottedname if not template.endswith(self.template_extension): # Get the actual filename from dotted finder finder = self.dotted_finder template = finder.get_dotted_filename(template_name=template, template_extension=self.template_extension) else: return FileSystemLoader.get_source(self, environment, template) # Check if the template exists if not exists(template): raise TemplateNotFound(template) # Get modification time mtime = getmtime(template) # Read the source fd = open(template, 'rb') try: source = fd.read().decode('utf-8') finally: fd.close() return source, template, lambda: mtime == getmtime(template)
def get_source(self, environment, template): if callable(self.path_filter): pieces = split_template_path(template) if not self._combined_filter(os.path.join(*pieces)): raise TemplateNotFound(template) return FileSystemLoader.get_source(self, environment, template)
def get_source(self, environment, template): if not template.startswith(self.prefix): raise TemplateNotFound(template) template = template[len(self.prefix):] if not template in self.files: raise TemplateNotFound(template) return FileSystemLoader.get_source(self, environment, template)
class CustomizationLoader(BaseLoader): def __init__(self, fallback_loader, customization_dir, customization_debug=False): from indico.core.logger import Logger self.logger = Logger.get('customization') self.debug = customization_debug self.fallback_loader = fallback_loader self.fs_loader = FileSystemLoader(customization_dir, followlinks=True) def _get_fallback(self, environment, template, path, customization_ignored=False): rv = self.fallback_loader.get_source(environment, template) if not customization_ignored and self.debug: try: orig_path = rv[1] except TemplateNotFound: orig_path = None self.logger.debug('Customizable: %s (original: %s, reference: ~%s)', path, orig_path, template) return rv def get_source(self, environment, template): path = posixpath.join(*split_template_path(template)) if template[0] == '~': return self._get_fallback(environment, template[1:], path[1:], customization_ignored=True) try: plugin, path = path.split(':', 1) except ValueError: plugin = None prefix = posixpath.join('plugins', plugin) if plugin else 'core' path = posixpath.join(prefix, path) try: rv = self.fs_loader.get_source(environment, path) if self.debug: self.logger.debug('Customized: %s', path) return rv except TemplateNotFound: return self._get_fallback(environment, template, path) @internalcode def load(self, environment, name, globals=None): tpl = super(CustomizationLoader, self).load(environment, name, globals) if ':' not in name: return tpl # This is almost exactly what PluginPrefixLoader.load() does, but we have # to replicate it here since we need to handle `~` and use our custom # `get_source` to get the overridden template plugin_name, tpl_name = name.split(':', 1) if plugin_name[0] == '~': plugin_name = plugin_name[1:] plugin = get_state(current_app).plugin_engine.get_plugin(plugin_name) if plugin is None: # that should never happen raise RuntimeError('Plugin template {} has no plugin'.format(name)) tpl.plugin = plugin return tpl
class CustomizationLoader(BaseLoader): def __init__(self, fallback_loader, customization_dir, customization_debug=False): from indico.core.logger import Logger self.logger = Logger.get('customization') self.debug = customization_debug self.fallback_loader = fallback_loader self.fs_loader = FileSystemLoader(customization_dir, followlinks=True) def _get_fallback(self, environment, template, path, customization_ignored=False): rv = self.fallback_loader.get_source(environment, template) if not customization_ignored and self.debug: try: orig_path = rv[1] except TemplateNotFound: orig_path = None self.logger.debug('Customizable: %s (original: %s, reference: ~%s)', path, orig_path, template) return rv def get_source(self, environment, template): path = posixpath.join(*split_template_path(template)) if template[0] == '~': return self._get_fallback(environment, template[1:], path[1:], customization_ignored=True) try: plugin, path = path.split(':', 1) except ValueError: plugin = None prefix = posixpath.join('plugins', plugin) if plugin else 'core' path = posixpath.join(prefix, path) try: rv = self.fs_loader.get_source(environment, path) if self.debug: self.logger.debug('Customized: %s', path) return rv except TemplateNotFound: return self._get_fallback(environment, template, path) @internalcode def load(self, environment, name, globals=None): tpl = super().load(environment, name, globals) if ':' not in name: return tpl # This is almost exactly what PluginPrefixLoader.load() does, but we have # to replicate it here since we need to handle `~` and use our custom # `get_source` to get the overridden template plugin_name, tpl_name = name.split(':', 1) if plugin_name[0] == '~': plugin_name = plugin_name[1:] plugin = get_state(current_app).plugin_engine.get_plugin(plugin_name) if plugin is None: # that should never happen raise RuntimeError(f'Plugin template {name} has no plugin') tpl.plugin = plugin return tpl
def get_source(self, environment, template): # keep legacy asset: prefix checking that bypasses # source path checking altogether if template.startswith('asset:'): newtemplate = template.split(':', 1)[1] fi = self._get_asset_source_fileinfo(environment, newtemplate) return fi.contents, fi.filename, fi.uptodate fi = self._get_asset_source_fileinfo(environment, template) if os.path.isfile(fi.filename): return fi.contents, fi.filename, fi.uptodate try: return FileSystemLoader.get_source(self, environment, template) except TemplateNotFound, ex: message = ex.message message += ('; asset=%s; searchpath=%r' % (fi.filename, self.searchpath)) raise TemplateNotFound(name=ex.name, message=message)
def get_source(self, environment, template): # keep legacy asset: prefix checking that bypasses # source path checking altogether if template.startswith('asset:'): template = template[6:] # load template directly from the filesystem filename = abspath_from_asset_spec(template) fi = FileInfo(filename, self.encoding) if os.path.isfile(fi.filename): return fi.contents, fi.filename, fi.uptodate # fallback to search-path lookup try: return FileSystemLoader.get_source(self, environment, template) except TemplateNotFound as ex: message = ex.message message += ('; asset=%s; searchpath=%r' % (template, self.searchpath)) raise TemplateNotFound(name=ex.name, message=message)
class TachyonicLoader(BaseLoader): """Jinja class for loading templates. """ __slots__ = ('override_path', '_fsl', '_pkgloaders') def __init__(self, app_path): """Load Templates Jinja2 Templates Initialize loading for Jinja2 Templates. """ override_path = app_path + '/templates' self._fsl = FileSystemLoader(override_path) self._pkgloaders = {} def get_source(self, environment, template): """Get raw template for environment. First attempts to load overriding template then uses template within specified package. For example "package/template.html" """ try: if self._fsl is not None: source = self._fsl.get_source(environment, template) log.info("Loaded Override Template %s" % template) return source except TemplateNotFound: pass try: package_path = split_template_path(template) package = package_path[0] template = "/".join(package_path[1:]) if package not in self._pkgloaders: self._pkgloaders[package] = PackageLoader( package, package_path='/templates', encoding='UTF-8') source = self._pkgloaders[package].get_source( environment, template) log.info("Loaded Package Template %s/%s" % (package, template)) return source except ImportError: raise TemplateNotFound("'importerror' " + package + '/' + template) from None except TemplateNotFound: raise TemplateNotFound(package + '/' + template) from None def list_overrides(self): """Returns a list of overiding templates for this environment. Overiding templates are located within wsgi application installation path in templates. Templates to override are located in package/templates path structure. For example /var/www/ui/templates/template.html """ fsl = self.fsl.list_templates() return fsl def list_templates(self): """Returns a list of templates for this environment. Templates are located within the python package source. """ raise NotImplementedError('list_templates')
class TachyonicLoader(BaseLoader): """Jinja class for loading templates. """ __slots__ = ('override_path', '_fsl', '_pkgloaders') def __init__(self): """Load Templates Jinja2 Templates Initialize loading for Jinja2 Templates. """ override_path = g.app.app_root + '/templates' self._fsl = FileSystemLoader(override_path) self._pkgloaders = {} def get_source(self, environment, template): """Get raw template for environment. First attempts to load overriding template then uses template within specified package. For example "package/template.html" """ with Timer() as elapsed: try: source = self._fsl.get_source(environment, template) log.info("Loaded Override Template %s" % template, timer=elapsed()) return source except TemplateNotFound: pass try: package_path = split_template_path(template) package = package_path[0] template = ".".join(package_path[1:]) if package not in self._pkgloaders: self._pkgloaders[package] = PackageLoader( package, package_path='/templates', encoding='UTF-8') source = self._pkgloaders[package].get_source( environment, template) log.info("Loaded Package Template %s/%s" % (package, template), timer=elapsed()) except ModuleNotFoundError: raise TemplateNotFound(package + '/' + template) from None return source def list_overrides(self): """Returns a list of overiding templates for this environment. Overiding templates are located within wsgi application installation path in templates. Templates to override are located in package/templates path structure. For example /var/www/ui/templates/template.html """ fsl = self.fsl.list_templates() return fsl def list_templates(self): """Returns a list of templates for this environment. Templates are located within the python package source. """ path = self.package_path if path[:2] == './': path = path[2:] elif path == '.': path = '' offset = len(path) results = [] def _walk(path, pkg): for filename in pkg['provider'].resource_listdir(path): fullname = path + '/' + filename if pkg['provider'].resource_isdir(fullname): _walk(fullname, pkg) else: p = fullname[offset:].lstrip('/') p = "%s/%s" % (package_name, p) results.append(p) for package_name in self.packages: pkg = self.packages[package_name] if pkg['provider'].resource_isdir(path): _walk(path, pkg) results = (results + self.list_overrides()).sort() return results