def test_python_tpl_with_cssclass(self): env = Environment(extensions=['jinja2_highlight.HighlightExtension']) env.extend(jinja2_highlight_cssclass = 'codehilite') #env.globals['jinja2_highlight_cssclass'] = 'codehilite' tpl = env.from_string(''' {% highlight "python" %} print("Hello world") {% endhighlight %} ''') self.assertHtmlListEqual(tpl.render().split(), self.cssclass_rendered)
def test_python_tpl_with_cssclass(self): env = Environment(extensions=['jinja2_highlight.HighlightExtension']) env.extend(jinja2_highlight_cssclass='codehilite') #env.globals['jinja2_highlight_cssclass'] = 'codehilite' tpl = env.from_string(''' {% highlight "python" %} print("Hello world") {% endhighlight %} ''') assert tpl.render().split() == self.cssclass_rendered
def test_heading(): env = Environment() env.extend(language=None) assert heading(env, 'Hello') == ('Hello\n' '=====') assert heading(env, 'Hello', 1) == ('Hello\n' '=====') assert heading(env, 'Hello', 2) == ('Hello\n' '-----') assert heading(env, 'Hello', 3) == ('Hello\n' '~~~~~') assert heading(env, 'русский язык', 1) == ('русский язык\n' '============') # language=ja: ambiguous env.language = 'ja' assert heading(env, 'русский язык', 1) == ('русский язык\n' '=======================')
class Snaql(object): def __init__(self, sql_root, sql_ns): self.sql_root = sql_root self.jinja_env = Environment( trim_blocks=True, extensions=[JinjaSQLExtension], loader=RawFileSystemLoader(os.path.join(self.sql_root, sql_ns)), ) self.jinja_env.extend(sql_params={}) def gen_func(self, name, meta_struct, env): def fn(**kwargs): if kwargs: sql_tmpl = env.from_string(meta_struct['funcs'][name]['raw_sql']) sql_raw = sql_tmpl.render(**kwargs) return escape_string(sql_raw) return meta_struct['funcs'][name]['sql'] fn.__doc__ = meta_struct['funcs'][name]['note'] fn.func_name = name return fn def load_queries(self, sql_path): template = self.jinja_env.get_template(sql_path) template.render() factory_methods = {} meta_struct = copy.deepcopy(self.jinja_env.sql_params) for name, block in self.jinja_env.sql_params['funcs'].items(): fn = self.gen_func(name, meta_struct, self.jinja_env) factory_methods[name] = fn factory = namedtuple('SQLFactory', factory_methods.keys()) struct = factory(*factory_methods.values()) self.jinja_env.sql_params.clear() return struct
class Jinja2Template(Template): """ The Jinja2 Template implementation """ def __init__(self, sitepath): super(Jinja2Template, self).__init__(sitepath) def configure(self, site, engine=None): """ Uses the site object to initialize the jinja environment. """ self.site = site self.engine = engine self.preprocessor = (engine.preprocessor if hasattr(engine, 'preprocessor') else None) self.loader = HydeLoader(self.sitepath, site, self.preprocessor) default_extensions = [ IncludeText, Spaceless, Asciidoc, Markdown, restructuredText, Syntax, Reference, Refer, YamlVar, 'jinja2.ext.do', 'jinja2.ext.loopcontrols', 'jinja2.ext.with_' ] defaults = { 'line_statement_prefix': '$$$', 'trim_blocks': True, } settings = dict() settings.update(defaults) settings['extensions'] = list() settings['extensions'].extend(default_extensions) conf = {} try: conf = attrgetter('config.jinja2')(site).to_dict() except AttributeError: pass settings.update( dict([(key, conf[key]) for key in defaults if key in conf])) extensions = conf.get('extensions', []) if isinstance(extensions, list): settings['extensions'].extend(extensions) else: settings['extensions'].append(extensions) self.env = Environment( loader=self.loader, undefined=SilentUndefined, line_statement_prefix=settings['line_statement_prefix'], trim_blocks=True, bytecode_cache=FileSystemBytecodeCache(), extensions=settings['extensions']) self.env.globals['media_url'] = media_url self.env.globals['content_url'] = content_url self.env.globals['full_url'] = full_url self.env.globals['engine'] = engine self.env.globals['deps'] = {} self.env.filters['urlencode'] = urlencode self.env.filters['urldecode'] = urldecode self.env.filters['asciidoc'] = asciidoc self.env.filters['markdown'] = markdown self.env.filters['restructuredtext'] = restructuredtext self.env.filters['syntax'] = syntax self.env.filters['date_format'] = date_format self.env.filters['xmldatetime'] = xmldatetime self.env.filters['islice'] = islice self.env.filters['top'] = top config = {} if hasattr(site, 'config'): config = site.config self.env.extend(config=config) try: from typogrify.templatetags import jinja2_filters except ImportError: jinja2_filters = False if jinja2_filters: jinja2_filters.register(self.env) def clear_caches(self): """ Clear all caches to prepare for regeneration """ if self.env.bytecode_cache: self.env.bytecode_cache.clear() def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except: logger.error("Error parsing[%s]" % path) raise tpls = find_referenced_templates(ast) deps = list(self.env.globals['deps'].get('path', [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps)) @property def exception_class(self): """ The exception to throw. Used by plugins. """ return TemplateError @property def patterns(self): """ The pattern for matching selected template statements. """ return { "block_open": '\s*\{\%\s*block\s*([^\s]+)\s*\%\}', "block_close": '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}', "include": '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}', "extends": '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}' } def get_include_statement(self, path_to_include): """ Returns an include statement for the current template, given the path to include. """ return '{%% include \'%s\' %%}' % path_to_include def get_extends_statement(self, path_to_extend): """ Returns an extends statement for the current template, given the path to extend. """ return '{%% extends \'%s\' %%}' % path_to_extend def get_open_tag(self, tag, params): """ Returns an open tag statement. """ return '{%% %s %s %%}' % (tag, params) def get_close_tag(self, tag, params): """ Returns an open tag statement. """ return '{%% end%s %%}' % tag def get_content_url_statement(self, url): """ Returns the content url statement. """ return '{{ content_url(\'%s\') }}' % url def get_media_url_statement(self, url): """ Returns the media url statement. """ return '{{ media_url(\'%s\') }}' % url def get_full_url_statement(self, url): """ Returns the full url statement. """ return '{{ full_url(\'%s\') }}' % url def render_resource(self, resource, context): """ Renders the given resource using the context """ try: template = self.env.get_template(resource.relative_path) out = template.render(context) except: out = "" logger.debug(self.env.loader.get_source( self.env, resource.relative_path)) raise return out def render(self, text, context): """ Renders the given text using the context """ template = self.env.from_string(text) return template.render(context)
class Snaql(object): def __init__(self, sql_root, sql_ns): self.sql_root = sql_root self.jinja_env = Environment( trim_blocks=True, extensions=[JinjaSQLExtension], loader=RawFileSystemLoader(os.path.join(self.sql_root, sql_ns)), ) self.jinja_env.filters.update({ 'guards.string': guard_string, 'guards.integer': guard_integer, 'guards.datetime': guard_datetime, 'guards.date': guard_date, 'guards.float': guard_float, 'guards.timedelta': guard_timedelta, 'guards.time': guard_time, 'guards.case': guard_case, 'guards.regexp': guard_regexp, 'guards.bool': guard_bool, }) self.jinja_env.extend(sql_params={}) def gen_func(self, name, meta_struct, env): def subrender_cond(owner_name, cond_func, context): if isinstance(cond_func, collections.Callable) and cond_func.is_cond: if meta_struct['funcs'][cond_func.func_name]['cond_for'] != owner_name: raise SnaqlException( '"%s" is not proper condition for "%s"' % ( cond_func.func_name, owner_name ) ) cond_tmpl = env.from_string( meta_struct['funcs'][cond_func.func_name]['raw_sql'] ) return cond_tmpl.render(**context).strip() return cond_func def fn(**kwargs): if meta_struct['funcs'][name]['is_cond']: raise SnaqlException(( '"%s" is condition for "%s" and can not ' 'be rendered outside of it\'s scope' ) % (name, meta_struct['funcs'][name]['cond_for'])) if kwargs: for point, val in kwargs.items(): maybe_cond_sql = subrender_cond(name, val, kwargs) if maybe_cond_sql: kwargs[point] = maybe_cond_sql if ( isinstance(val, collections.Iterable) and not isinstance( val, (str if PY3K else types.StringTypes, dict) ) ): val = [subrender_cond(name, v, kwargs) for v in val] kwargs[point] = [v for v in val if v] if 'schema' in kwargs and isinstance(kwargs['schema'], Schema): validation_schema = kwargs.pop('schema') kwargs = validation_schema.validate(kwargs) sql_tmpl = env.from_string(meta_struct['funcs'][name]['raw_sql']) return sql_tmpl.render(**kwargs).strip() return meta_struct['funcs'][name]['sql'] fn.__doc__ = meta_struct['funcs'][name]['note'] fn.is_cond = meta_struct['funcs'][name]['is_cond'] fn.func_name = name return fn def gen_dep_graph(self, node, accum): for edge in node.edges: if edge not in accum: self.gen_dep_graph(edge, accum) accum.append(node) return accum def load_queries(self, sql_path): template = self.jinja_env.get_template(sql_path) template.render() factory_methods = {} meta_struct = copy.deepcopy(self.jinja_env.sql_params) blocks = set(meta_struct['funcs']) node = SnaqlDepNode('root') for name, block in meta_struct['funcs'].items(): # Dependency graph building block['node'] = block['node'] or SnaqlDepNode(name) for dep in block['depends_on']: if dep not in blocks: raise SnaqlException( '"%s" block not found in "%s"' % (dep, sql_path) ) if meta_struct['funcs'][dep]['node'] is None: meta_struct['funcs'][dep]['node'] = SnaqlDepNode(dep) block['node'].add_edge(meta_struct['funcs'][dep]['node']) node.add_edge(block['node']) fn = self.gen_func(name, meta_struct, self.jinja_env) factory_methods[name] = fn edges_accum = [] graph = self.gen_dep_graph(node, edges_accum) graph.pop() # root node factory_methods['ordered_blocks'] = [ factory_methods[n.name] for n in graph ] factory = namedtuple('SQLFactory', factory_methods.keys()) struct = factory(*factory_methods.values()) self.jinja_env.sql_params.clear() return struct
class Jinja2Template(Template): """ The Jinja2 Template implementation """ def __init__(self, sitepath): super(Jinja2Template, self).__init__(sitepath) def configure(self, site, engine=None): """ Uses the site object to initialize the jinja environment. """ self.site = site self.engine = engine self.preprocessor = (engine.preprocessor if hasattr( engine, 'preprocessor') else None) self.loader = HydeLoader(self.sitepath, site, self.preprocessor) default_extensions = [ IncludeText, Spaceless, Asciidoc, Markdown, restructuredText, Syntax, Reference, Refer, YamlVar, 'jinja2.ext.do', 'jinja2.ext.loopcontrols', 'jinja2.ext.with_' ] defaults = { 'line_statement_prefix': '$$$', 'trim_blocks': True, } settings = dict() settings.update(defaults) settings['extensions'] = list() settings['extensions'].extend(default_extensions) conf = {} try: conf = attrgetter('config.jinja2')(site).to_dict() except AttributeError: pass settings.update( dict([(key, conf[key]) for key in defaults if key in conf])) extensions = conf.get('extensions', []) if isinstance(extensions, list): settings['extensions'].extend(extensions) else: settings['extensions'].append(extensions) self.env = Environment( loader=self.loader, undefined=SilentUndefined, line_statement_prefix=settings['line_statement_prefix'], trim_blocks=True, bytecode_cache=FileSystemBytecodeCache(), extensions=settings['extensions']) self.env.globals['media_url'] = media_url self.env.globals['content_url'] = content_url self.env.globals['full_url'] = full_url self.env.globals['engine'] = engine self.env.globals['deps'] = {} self.env.filters['urlencode'] = urlencode self.env.filters['urldecode'] = urldecode self.env.filters['asciidoc'] = asciidoc self.env.filters['markdown'] = markdown self.env.filters['restructuredtext'] = restructuredtext self.env.filters['syntax'] = syntax self.env.filters['date_format'] = date_format self.env.filters['xmldatetime'] = xmldatetime self.env.filters['islice'] = islice self.env.filters['top'] = top config = {} if hasattr(site, 'config'): config = site.config self.env.extend(config=config) try: from typogrify.templatetags import jinja2_filters except ImportError: jinja2_filters = False if jinja2_filters: jinja2_filters.register(self.env) def clear_caches(self): """ Clear all caches to prepare for regeneration """ if self.env.bytecode_cache: self.env.bytecode_cache.clear() def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except: logger.error("Error parsing[%s]" % path) raise tpls = find_referenced_templates(ast) deps = list(self.env.globals['deps'].get('path', [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps)) @property def exception_class(self): """ The exception to throw. Used by plugins. """ return TemplateError @property def patterns(self): """ The pattern for matching selected template statements. """ return { "block_open": '\s*\{\%\s*block\s*([^\s]+)\s*\%\}', "block_close": '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}', "include": '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}', "extends": '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}' } def get_include_statement(self, path_to_include): """ Returns an include statement for the current template, given the path to include. """ return '{%% include \'%s\' %%}' % path_to_include def get_extends_statement(self, path_to_extend): """ Returns an extends statement for the current template, given the path to extend. """ return '{%% extends \'%s\' %%}' % path_to_extend def get_open_tag(self, tag, params): """ Returns an open tag statement. """ return '{%% %s %s %%}' % (tag, params) def get_close_tag(self, tag, params): """ Returns an open tag statement. """ return '{%% end%s %%}' % tag def get_content_url_statement(self, url): """ Returns the content url statement. """ return '{{ content_url(\'%s\') }}' % url def get_media_url_statement(self, url): """ Returns the media url statement. """ return '{{ media_url(\'%s\') }}' % url def get_full_url_statement(self, url): """ Returns the full url statement. """ return '{{ full_url(\'%s\') }}' % url def render_resource(self, resource, context): """ Renders the given resource using the context """ try: template = self.env.get_template(resource.relative_path) out = template.render(context) except: out = "" logger.debug( self.env.loader.get_source(self.env, resource.relative_path)) raise return out def render(self, text, context): """ Renders the given text using the context """ template = self.env.from_string(text) return template.render(context)
class Jinja2Template(Template): """ The Jinja2 Template implementation """ def __init__(self, sitepath): super(Jinja2Template, self).__init__(sitepath) def configure(self, site, engine=None): """ Uses the site object to initialize the jinja environment. """ self.site = site self.engine = engine self.preprocessor = (engine.preprocessor if hasattr(engine, 'preprocessor') else None) self.loader = HydeLoader(self.sitepath, site, self.preprocessor) self.env = Environment(loader=self.loader, undefined=SilentUndefined, trim_blocks=True, extensions=[IncludeText, Markdown, Syntax, Reference, Refer, YamlVar, 'jinja2.ext.do', 'jinja2.ext.loopcontrols', 'jinja2.ext.with_']) self.env.globals['media_url'] = media_url self.env.globals['content_url'] = content_url self.env.globals['engine'] = engine self.env.globals['deps'] = {} self.env.filters['markdown'] = markdown self.env.filters['syntax'] = syntax config = {} if hasattr(site, 'config'): config = site.config self.env.extend(config=config) try: from typogrify.templatetags import jinja2_filters except ImportError: jinja2_filters = False if jinja2_filters: jinja2_filters.register(self.env) def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates ast = self.env.parse(text) tpls = find_referenced_templates(ast) deps = list(self.env.globals['deps'].get('path', [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps)) @property def exception_class(self): """ The exception to throw. Used by plugins. """ return TemplateError @property def patterns(self): """ The pattern for matching selected template statements. """ return { "block_open": '\s*\{\%\s*block\s*([^\s]+)\s*\%\}', "block_close": '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}', "include": '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}', "extends": '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}' } def get_include_statement(self, path_to_include): """ Returns an include statement for the current template, given the path to include. """ return '{%% include \'%s\' %%}' % path_to_include def get_extends_statement(self, path_to_extend): """ Returns an extends statement for the current template, given the path to extend. """ return '{%% extends \'%s\' %%}' % path_to_extend def get_open_tag(self, tag, params): """ Returns an open tag statement. """ return '{%% %s %s %%}' % (tag, params) def get_close_tag(self, tag, params): """ Returns an open tag statement. """ return '{%% end%s %%}' % tag def get_content_url_statement(self, url): """ Returns the content url statement. """ return '{{ content_url(\'%s\') }}' % url def get_media_url_statement(self, url): """ Returns the media url statement. """ return '{{ media_url(\'%s\') }}' % url def render(self, text, context): """ Renders the given resource using the context """ template = self.env.from_string(text) return template.render(context)
#!/usr/bin/env python3.6 # # Run with python 3.6+ # import csv import markdown from jinja2 import Environment, FileSystemLoader, Markup, select_autoescape env = Environment(loader=FileSystemLoader('templates'), autoescape=select_autoescape(['html', 'xml']), extensions=['jinja2_highlight.HighlightExtension']) env.extend(jinja2_highlight_cssclass='highlight') common_pages = [ 'diversity/index', ] for p in common_pages: print("Processing " + p) md = open(p + ".md", "r") content = markdown.markdown(md.read(), extensions=['extra', 'smarty'], output_format='html5') template = env.get_template("index.html") file = open(p + ".html", "w") file.write(template.render(page=p, content=Markup(content))) file.close()
class Jinja2Template(Template): """ The Jinja2 Template implementation """ def __init__(self, sitepath): super(Jinja2Template, self).__init__(sitepath) def configure(self, site, engine=None): """ Uses the site object to initialize the jinja environment. """ self.site = site self.engine = engine self.preprocessor = (engine.preprocessor if hasattr(engine, 'preprocessor') else None) self.loader = HydeLoader(self.sitepath, site, self.preprocessor) default_extensions = [ IncludeText, Spaceless, Asciidoc, Markdown, restructuredText, Syntax, Reference, Refer, YamlVar, 'jinja2.ext.do', 'jinja2.ext.loopcontrols', 'jinja2.ext.with_' ] defaults = { 'line_statement_prefix': '$$$', 'trim_blocks': True, } settings = dict() settings.update(defaults) settings['extensions'] = list() settings['extensions'].extend(default_extensions) settings['filters'] = {} settings['tests'] = {} conf = {} try: conf = attrgetter('config.jinja2')(site).to_dict() except AttributeError: pass settings.update( dict([(key, conf[key]) for key in defaults if key in conf])) extensions = conf.get('extensions', []) if isinstance(extensions, list): settings['extensions'].extend(extensions) else: settings['extensions'].append(extensions) filters = conf.get('filters', {}) if isinstance(filters, dict): for name, value in filters.items(): parts = value.split('.') module_name = '.'.join(parts[:-1]) function_name = parts[-1] module = __import__(module_name, fromlist=[function_name]) settings['filters'][name] = getattr(module, function_name) tests = conf.get('tests', {}) if isinstance(tests, dict): for name, value in tests.items(): parts = value.split('.') module_name = '.'.join(parts[:-1]) function_name = parts[-1] module = __import__(module_name, fromlist=[function_name]) settings['tests'][name] = getattr(module, function_name) self.env = Environment( loader=self.loader, undefined=SilentUndefined, line_statement_prefix=settings['line_statement_prefix'], trim_blocks=True, bytecode_cache=FileSystemBytecodeCache(), extensions=settings['extensions']) self.env.globals['media_url'] = media_url self.env.globals['content_url'] = content_url self.env.globals['full_url'] = full_url self.env.globals['engine'] = engine self.env.globals['deps'] = {} self.env.filters['urlencode'] = urlencode self.env.filters['urldecode'] = urldecode self.env.filters['asciidoc'] = asciidoc self.env.filters['markdown'] = markdown self.env.filters['restructuredtext'] = restructuredtext self.env.filters['syntax'] = syntax self.env.filters['date_format'] = date_format self.env.filters['xmldatetime'] = xmldatetime self.env.filters['islice'] = islice self.env.filters['top'] = top self.env.filters.update(settings['filters']) self.env.tests.update(settings['tests']) config = {} if hasattr(site, 'config'): config = site.config self.env.extend(config=config) try: from typogrify.templatetags import jinja_filters except ImportError: jinja_filters = False if jinja_filters: jinja_filters.register(self.env) def clear_caches(self): """ Clear all caches to prepare for regeneration """ if self.env.bytecode_cache: self.env.bytecode_cache.clear() def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except Exception, e: HydeException.reraise( "Error processing %s: \n%s" % (path, unicode(e)), sys.exc_info()) tpls = find_referenced_templates(ast) deps = list(self.env.globals['deps'].get('path', [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps))
class JinJAQL(object): def __init__( self, folder_path: pathlib.Path, engine=None, cache=None, ): folder_path = pathlib.Path(folder_path) self.jinja_env = Environment( trim_blocks=True, extensions=[JinjaSQLExtension], loader=RawFileSystemLoader(folder_path) ) self.jinja_env.filters.update({ 'guards.string': guard_string, 'guards.integer': guard_integer, 'guards.datetime': guard_datetime, 'guards.date': guard_date, 'guards.float': guard_float, 'guards.timedelta': guard_timedelta, 'guards.time': guard_time, 'guards.case': guard_case, 'guards.regexp': guard_regexp, 'guards.bool': guard_bool, }) self.jinja_env.extend(sql_params={}) self._engine = engine or default_engine self._cache = cache or default_cache def gen_func(self, name, meta_struct, env): def subrender_cond(owner_name, cond_func, context): if ( isinstance(cond_func, collections.abc.Callable) and cond_func.is_cond ): cond_struct = meta_struct['funcs'][cond_func.func_name] if cond_struct['cond_for'] != owner_name: raise SnaqlException( '"%s" is not proper condition for "%s"' % ( cond_func.func_name, owner_name ) ) cond_tmpl = env.from_string( meta_struct['funcs'][cond_func.func_name]['raw_sql'] ) return cond_tmpl.render(**context).strip() return cond_func def fn(**kwargs): if meta_struct['funcs'][name]['is_cond']: raise SnaqlException(( '"%s" is condition for "%s" and can not ' 'be rendered outside of it\'s scope' ) % (name, meta_struct['funcs'][name]['cond_for'])) if kwargs: for point, val in kwargs.items(): maybe_cond_sql = subrender_cond(name, val, kwargs) if maybe_cond_sql: kwargs[point] = maybe_cond_sql if ( isinstance(val, collections.abc.Iterable) and not isinstance( val, (str if PY3K else types.StringTypes, dict) ) ): val = [subrender_cond(name, v, kwargs) for v in val] kwargs[point] = [v for v in val if v] if 'schema' in kwargs and isinstance(kwargs['schema'], Schema): validation_schema = kwargs.pop('schema') kwargs = validation_schema.validate(kwargs) sql_tmpl = ( env.from_string(meta_struct['funcs'][name]['raw_sql']) ) rendered_sql = sql_tmpl.render(**kwargs).strip() else: rendered_sql = meta_struct['funcs'][name]['sql'] return self._engine( query_string=rendered_sql, connection_string=meta_struct['funcs'][name]['connection_string'], ) fn = self._cache()(fn) fn.__doc__ = meta_struct['funcs'][name]['note'] fn.is_cond = meta_struct['funcs'][name]['is_cond'] fn.func_name = str(name) return fn def gen_dep_graph(self, node, accum): for edge in node.edges: if edge not in accum: self.gen_dep_graph(edge, accum) accum.append(node) return accum def load_queries(self, sql_path): template = self.jinja_env.get_template(sql_path) template.render() factory_methods = {} meta_struct = copy.deepcopy(self.jinja_env.sql_params) blocks = set(meta_struct['funcs']) node = SnaqlDepNode('root') for name, block in meta_struct['funcs'].items(): # Dependency graph building block['node'] = block['node'] or SnaqlDepNode(name) for dep in block['depends_on']: if dep not in blocks: raise SnaqlException( '"%s" block not found in "%s"' % (dep, sql_path) ) if meta_struct['funcs'][dep]['node'] is None: meta_struct['funcs'][dep]['node'] = SnaqlDepNode(dep) block['node'].add_edge(meta_struct['funcs'][dep]['node']) node.add_edge(block['node']) fn = self.gen_func(name, meta_struct, self.jinja_env) factory_methods[name] = fn edges_accum = [] graph = self.gen_dep_graph(node, edges_accum) graph.pop() # root node factory_methods['ordered_blocks'] = [ factory_methods[n.name] for n in graph ] factory = namedtuple('SQLFactory', factory_methods.keys()) struct = factory(*factory_methods.values()) self.jinja_env.sql_params.clear() return struct
class Jinja2Template(Template): """ The Jinja2 Template implementation """ def __init__(self, sitepath): super(Jinja2Template, self).__init__(sitepath) def configure(self, site, engine=None): """ Uses the site object to initialize the jinja environment. """ self.site = site self.engine = engine self.preprocessor = (engine.preprocessor if hasattr( engine, 'preprocessor') else None) self.loader = HydeLoader(self.sitepath, site, self.preprocessor) default_extensions = [ IncludeText, Spaceless, Asciidoc, Markdown, restructuredText, Syntax, Reference, Refer, YamlVar, 'jinja2.ext.do', 'jinja2.ext.loopcontrols', 'jinja2.ext.with_' ] defaults = { 'line_statement_prefix': '$$$', 'trim_blocks': True, } settings = dict() settings.update(defaults) settings['extensions'] = list() settings['extensions'].extend(default_extensions) settings['filters'] = {} conf = {} try: conf = attrgetter('config.jinja2')(site).to_dict() except AttributeError: pass settings.update( dict([(key, conf[key]) for key in defaults if key in conf])) extensions = conf.get('extensions', []) if isinstance(extensions, list): settings['extensions'].extend(extensions) else: settings['extensions'].append(extensions) filters = conf.get('filters', {}) if isinstance(filters, dict): for name, value in filters.items(): parts = value.split('.') module_name = '.'.join(parts[:-1]) function_name = parts[-1] module = __import__(module_name, fromlist=[function_name]) settings['filters'][name] = getattr(module, function_name) self.env = Environment( loader=self.loader, undefined=SilentUndefined, line_statement_prefix=settings['line_statement_prefix'], trim_blocks=True, bytecode_cache=FileSystemBytecodeCache(), extensions=settings['extensions']) self.env.globals['media_url'] = media_url self.env.globals['content_url'] = content_url self.env.globals['full_url'] = full_url self.env.globals['engine'] = engine self.env.globals['deps'] = {} self.env.filters['urlencode'] = urlencode self.env.filters['urldecode'] = urldecode self.env.filters['asciidoc'] = asciidoc self.env.filters['markdown'] = markdown self.env.filters['restructuredtext'] = restructuredtext self.env.filters['syntax'] = syntax self.env.filters['date_format'] = date_format self.env.filters['xmldatetime'] = xmldatetime self.env.filters['islice'] = islice self.env.filters['top'] = top self.env.filters.update(settings['filters']) config = {} if hasattr(site, 'config'): config = site.config self.env.extend(config=config) try: from typogrify.templatetags import jinja_filters except ImportError: jinja_filters = False if jinja_filters: jinja_filters.register(self.env) def clear_caches(self): """ Clear all caches to prepare for regeneration """ if self.env.bytecode_cache: self.env.bytecode_cache.clear() def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except Exception, e: HydeException.reraise( "Error processing %s: \n%s" % (path, unicode(e)), sys.exc_info()) tpls = find_referenced_templates(ast) deps = list(self.env.globals['deps'].get('path', [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps))
def __init__( self, template: PathType, from_file: bool = None, mode: str = None, env: Environment = None, filter_with_colon: bool = None, search_paths: PathTypeOrIter = None, globals: Mapping[str, Any] = None, filters: Mapping[str, Callable] = None, filters_as_globals: bool = None, **kwargs: Any, ) -> None: """Constructor""" # default values # fetch at runtime, so that they can be configured at importing from .defaults import ( FROM_FILE, MODE, FILTER_WITH_COLON, SEARCH_PATHS, ENV_ARGS, SHARED_GLOBALS, FILTERS_AS_GLOBALS, ) if from_file is None: from_file = FROM_FILE if mode is None: mode = MODE if filter_with_colon is None: filter_with_colon = FILTER_WITH_COLON if search_paths is None: search_paths = SEARCH_PATHS if filters_as_globals is None: filters_as_globals = FILTERS_AS_GLOBALS # split kwargs into arguments for Environment constructor and # configurations for extensions env_args = {} ext_conf = {} for key, val in kwargs.items(): if key in ENV_ARGS: env_args[key] = val else: ext_conf[key] = val loader = env_args.pop("loader", None) fsloader = FileSystemLoader(search_paths) # type: ignore if loader: loader = ChoiceLoader([loader, fsloader]) else: loader = fsloader self.env = env = Environment(**env_args, loader=loader) env.extend(**ext_conf) env.globals.update(SHARED_GLOBALS) standard_filter_manager.update_to_env(env) env.add_extension("jinja2.ext.loopcontrols") if filter_with_colon: from .exts.filter_colon import FilterColonExtension env.add_extension(FilterColonExtension) if mode == "wild": from .exts.wild import LiquidWildExtension from .filters.wild import wild_filter_manager env.add_extension("jinja2.ext.debug") env.add_extension(LiquidWildExtension) bfilters = { key: getattr(builtins, key) for key in dir(builtins) if not key.startswith("_") and callable(getattr(builtins, key)) and key not in ( "copyright", "credits", "input", "help", "globals", "license", "locals", "memoryview", "object", "property", "staticmethod", "super", ) and not any(key_c.isupper() for key_c in key) } env.filters.update(bfilters) wild_filter_manager.update_to_env(env) env.globals.update({ key: val for key, val in __builtins__.items() if not key.startswith("_") }) if filters_as_globals: env.globals.update(standard_filter_manager.filters) env.globals.update(wild_filter_manager.filters) elif mode == "jekyll": from .exts.front_matter import FrontMatterExtension from .exts.jekyll import LiquidJekyllExtension from .filters.jekyll import jekyll_filter_manager jekyll_filter_manager.update_to_env(env) env.add_extension(FrontMatterExtension) env.add_extension(LiquidJekyllExtension) elif mode == "shopify": from .exts.shopify import LiquidShopifyExtension from .filters.shopify import shopify_filter_manager shopify_filter_manager.update_to_env(env) env.add_extension(LiquidShopifyExtension) else: # standard from .exts.standard import LiquidStandardExtension env.add_extension(LiquidStandardExtension) if filters: env.filters.update(filters) builtin_globals = { "int": int, "float": float, "str": str, "bool": bool } if globals: builtin_globals.update(globals) env.globals.update(builtin_globals) if from_file: # in case template is a PathLike self.template = env.get_template(str(template)) else: self.template = env.from_string(str(template))
class Jinja2Template(Template): """ The Jinja2 Template implementation """ def __init__(self, sitepath): super(Jinja2Template, self).__init__(sitepath) def configure(self, site, engine=None): """ Uses the site object to initialize the jinja environment. """ self.site = site self.engine = engine self.preprocessor = engine.preprocessor if hasattr(engine, "preprocessor") else None self.loader = HydeLoader(self.sitepath, site, self.preprocessor) default_extensions = [ IncludeText, Spaceless, Asciidoc, Markdown, restructuredText, Syntax, Reference, Refer, YamlVar, "jinja2.ext.do", "jinja2.ext.loopcontrols", "jinja2.ext.with_", ] defaults = {"line_statement_prefix": "$$$", "trim_blocks": True} settings = dict() settings.update(defaults) settings["extensions"] = list() settings["extensions"].extend(default_extensions) settings["filters"] = {} settings["tests"] = {} conf = {} try: conf = attrgetter("config.jinja2")(site).to_dict() except AttributeError: pass settings.update(dict([(key, conf[key]) for key in defaults if key in conf])) extensions = conf.get("extensions", []) if isinstance(extensions, list): settings["extensions"].extend(extensions) else: settings["extensions"].append(extensions) filters = conf.get("filters", {}) if isinstance(filters, dict): for name, value in filters.items(): parts = value.split(".") module_name = ".".join(parts[:-1]) function_name = parts[-1] module = __import__(module_name, fromlist=[function_name]) settings["filters"][name] = getattr(module, function_name) tests = conf.get("tests", {}) if isinstance(tests, dict): for name, value in tests.items(): parts = value.split(".") module_name = ".".join(parts[:-1]) function_name = parts[-1] module = __import__(module_name, fromlist=[function_name]) settings["tests"][name] = getattr(module, function_name) self.env = Environment( loader=self.loader, undefined=SilentUndefined, line_statement_prefix=settings["line_statement_prefix"], trim_blocks=True, bytecode_cache=FileSystemBytecodeCache(), extensions=settings["extensions"], ) self.env.globals["media_url"] = media_url self.env.globals["content_url"] = content_url self.env.globals["full_url"] = full_url self.env.globals["engine"] = engine self.env.globals["deps"] = {} self.env.filters["urlencode"] = urlencode self.env.filters["urldecode"] = urldecode self.env.filters["asciidoc"] = asciidoc self.env.filters["markdown"] = markdown self.env.filters["restructuredtext"] = restructuredtext self.env.filters["syntax"] = syntax self.env.filters["date_format"] = date_format self.env.filters["xmldatetime"] = xmldatetime self.env.filters["islice"] = islice self.env.filters["top"] = top self.env.filters.update(settings["filters"]) self.env.tests.update(settings["tests"]) config = {} if hasattr(site, "config"): config = site.config self.env.extend(config=config) try: from typogrify.templatetags import jinja_filters except ImportError: jinja_filters = False if jinja_filters: jinja_filters.register(self.env) def clear_caches(self): """ Clear all caches to prepare for regeneration """ if self.env.bytecode_cache: self.env.bytecode_cache.clear() def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except Exception as e: HydeException.reraise("Error processing %s: \n%s" % (path, str(e)), sys.exc_info()) tpls = find_referenced_templates(ast) deps = list(self.env.globals["deps"].get("path", [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps)) @property def exception_class(self): """ The exception to throw. Used by plugins. """ return TemplateError @property def patterns(self): """ The pattern for matching selected template statements. """ return { "block_open": "\s*\{\%\s*block\s*([^\s]+)\s*\%\}", "block_close": "\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}", "include": "\s*\{\%\s*include\s*(?:'|\")(.+?\.[^.]*)(?:'|\")\s*\%\}", "extends": "\s*\{\%\s*extends\s*(?:'|\")(.+?\.[^.]*)(?:'|\")\s*\%\}", } def get_include_statement(self, path_to_include): """ Returns an include statement for the current template, given the path to include. """ return "{%% include '%s' %%}" % path_to_include def get_extends_statement(self, path_to_extend): """ Returns an extends statement for the current template, given the path to extend. """ return "{%% extends '%s' %%}" % path_to_extend def get_open_tag(self, tag, params): """ Returns an open tag statement. """ return "{%% %s %s %%}" % (tag, params) def get_close_tag(self, tag, params): """ Returns an open tag statement. """ return "{%% end%s %%}" % tag def get_content_url_statement(self, url): """ Returns the content url statement. """ return "{{ content_url('%s') }}" % url def get_media_url_statement(self, url): """ Returns the media url statement. """ return "{{ media_url('%s') }}" % url def get_full_url_statement(self, url): """ Returns the full url statement. """ return "{{ full_url('%s') }}" % url def render_resource(self, resource, context): """ Renders the given resource using the context """ try: template = self.env.get_template(resource.relative_path) out = template.render(context) except: raise return out def render(self, text, context): """ Renders the given text using the context """ template = self.env.from_string(text) return template.render(context)