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
Example #3
0
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'
                                               '=======================')
Example #4
0
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
Example #5
0
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)
Example #6
0
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
Example #7
0
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)
Example #8
0
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)
Example #9
0
#!/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()
Example #10
0
File: jinja.py Project: jd/hyde
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))
Example #11
0
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
Example #12
0
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))
Example #13
0
    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))
Example #14
0
File: jinja.py Project: hyde/hyde
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)