Example #1
0
    def __init__(self, project, load_plugins=True):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=["jinja2.ext.autoescape", "jinja2.ext.with_"],
            loader=jinja2.FileSystemLoader(os.path.join(self.root_path, "templates")),
        )

        from lektor.db import F

        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types

        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers

        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []

        if load_plugins:
            self.load_plugins()
Example #2
0
    def __init__(self, project, load_plugins=True):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'],
            loader=jinja2.FileSystemLoader(
                os.path.join(self.root_path, 'templates')))

        from lektor.db import F
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(
                lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types
        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers
        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []

        if load_plugins:
            self.load_plugins()
Example #3
0
    def on_setup_env(self, **extra):
        maybeasset = jinja2.contextfilter(
            lambda ctx, *a, **kw: maybeasset_filter(*a, **kw))
        self.env.jinja_env.filters["maybeasset"] = maybeasset

        maybeurl = jinja2.contextfilter(
            lambda ctx, *a, **kw: maybeurl_filter(*a, **kw))
        self.env.jinja_env.filters["maybeurl"] = maybeurl
Example #4
0
    def __init__(self, *args, **kwargs):
        JinjaGenerator.__init__(self, *args, **kwargs)

        self.environment.filters.update(
            feature=lambda x: 'feature = "{}"'.format(x),
            enum_type=jinja2.contextfilter(lambda ctx, enum: enum_type(enum, ctx['feature_set'])),
            enum_value=jinja2.contextfilter(lambda ctx, enum: enum_value(enum, ctx['feature_set'])),
            type=to_rust_type,
            params=to_rust_params,
            identifier=identifier,
            no_prefix=jinja2.contextfilter(lambda ctx, value: strip_specification_prefix(value, ctx['spec']))
        )
Example #5
0
    def __init__(self, *args, **kwargs):
        JinjaGenerator.__init__(self, *args, **kwargs)

        self._headers = dict()

        self.environment.globals.update(
            get_debug_impl=get_debug_impl,
            loadable=loadable,
            enum_member=enum_member,
            chain=itertools.chain
        )

        self.environment.filters.update(
            defined=lambda x: 'defined({})'.format(x),
            type_to_c=type_to_c,
            params_to_c=params_to_c,
            param_names=param_names,
            pfn=pfn,
            ctx=ctx,
            no_prefix=jinja2.contextfilter(lambda ctx, value: strip_specification_prefix(value, ctx['spec'])),
            c_commands=c_commands
        )

        self.environment.tests.update(
            supports=lambda x, arg: x.supports(arg),
            void=is_void,
        )
Example #6
0
    def __init__(self, root_path):
        self.root_path = os.path.abspath(root_path)

        self.config_filename = os.path.join(self.root_path, 'site.ini')

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'],
            loader=jinja2.FileSystemLoader(
                os.path.join(self.root_path, 'templates'))
        )

        from lektor.db import F
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
        )
Example #7
0
 def wrapper(fn):
     fn = _inject(fn, inject)
     if safe:
         fn = _make_safe(fn)
     if pass_context:
         fn = jinja2.contextfilter(fn)
     self._defer(lambda app: app.add_template_filter(fn, name=name))
     return fn
Example #8
0
    def __init__(self, project):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'],
            loader=jinja2.FileSystemLoader(
                os.path.join(self.root_path, 'templates'))
        )

        from lektor.db import F
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(
                lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: url_to(get_asset_url(*a, **kw))),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_random_id=lambda: uuid.uuid4().hex,
        )

        from lektor.types import builtin_types
        self.types = builtin_types.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
    def __init__(self, environment):
        super(CoreExtension, self).__init__(environment)
        self.environment.globals.update({
            'svg_icon': svg_icon,
        })

        self.environment.filters.update({
            'richtext_isempty':
            richtext_isempty,
            'slugify_unique':
            contextfilter(slugify_unique),
        })
Example #10
0
    def __init__(self, environment):
        super(CoreExtension, self).__init__(environment)
        self.environment.globals.update({
            'signed_redirect': signed_redirect,
            'unsigned_redirect': unsigned_redirect,
            'svg_icon': svg_icon,
        })

        self.environment.filters.update({
            'slugify_unique':
            contextfilter(slugify_unique),
        })
Example #11
0
    def _register_options(self):
        # Add Context Functions
        for name, method in self.context_functions.items():
            self._env.globals[name] = jinja2.contextfunction(method)

        # Add Context Filters
        for name, method in self.context_filters.items():
            self._env.filters[name] = jinja2.contextfilter(method)

        # Add Filters
        for name, method in self.filters.items():
            self._env.filters[name] = method

        # Add Tests
        for name, method in self.tests.items():
            self._env.tests[name] = method
Example #12
0
    def __init__(self, project, load_plugins=True):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.theme_paths = [os.path.join(self.root_path, 'themes', theme)
                            for theme in self.project.themes]

        if not self.theme_paths:
            # load the directories in the themes directory as the themes
            try:
                for fname in os.listdir(os.path.join(self.root_path, 'themes')):
                    f = os.path.join(self.root_path, 'themes', fname)
                    if os.path.isdir(f):
                        self.theme_paths.append(f)
            except OSError:
                pass

        template_paths = [os.path.join(path, 'templates')
                          for path in [self.root_path] + self.theme_paths]

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'],
            loader=jinja2.FileSystemLoader(
                template_paths)
        )

        from lektor.db import F, get_alts
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(
                lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(
                lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_alts=get_alts,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types
        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers
        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []
        self.virtual_sources = {}

        if load_plugins:
            self.load_plugins()

        from lektor.db import siblings_resolver
        self.virtualpathresolver('siblings')(siblings_resolver)
Example #13
0
 def _register(self):
     django_jinja.library.filter(
         name=self.name,
         fn=jinja2.contextfilter(self))
Example #14
0
    def __init__(self, hass, limited=False):
        """Initialise template environment."""
        super().__init__(undefined=jinja2.make_logging_undefined(
            logger=_LOGGER))
        self.hass = hass
        self.template_cache = weakref.WeakValueDictionary()
        self.filters["round"] = forgiving_round
        self.filters["multiply"] = multiply
        self.filters["log"] = logarithm
        self.filters["sin"] = sine
        self.filters["cos"] = cosine
        self.filters["tan"] = tangent
        self.filters["asin"] = arc_sine
        self.filters["acos"] = arc_cosine
        self.filters["atan"] = arc_tangent
        self.filters["atan2"] = arc_tangent2
        self.filters["sqrt"] = square_root
        self.filters["as_timestamp"] = forgiving_as_timestamp
        self.filters["as_local"] = dt_util.as_local
        self.filters["timestamp_custom"] = timestamp_custom
        self.filters["timestamp_local"] = timestamp_local
        self.filters["timestamp_utc"] = timestamp_utc
        self.filters["to_json"] = to_json
        self.filters["from_json"] = from_json
        self.filters["is_defined"] = fail_when_undefined
        self.filters["max"] = max
        self.filters["min"] = min
        self.filters["random"] = random_every_time
        self.filters["base64_encode"] = base64_encode
        self.filters["base64_decode"] = base64_decode
        self.filters["ordinal"] = ordinal
        self.filters["regex_match"] = regex_match
        self.filters["regex_replace"] = regex_replace
        self.filters["regex_search"] = regex_search
        self.filters["regex_findall_index"] = regex_findall_index
        self.filters["bitwise_and"] = bitwise_and
        self.filters["bitwise_or"] = bitwise_or
        self.filters["ord"] = ord
        self.globals["log"] = logarithm
        self.globals["sin"] = sine
        self.globals["cos"] = cosine
        self.globals["tan"] = tangent
        self.globals["sqrt"] = square_root
        self.globals["pi"] = math.pi
        self.globals["tau"] = math.pi * 2
        self.globals["e"] = math.e
        self.globals["asin"] = arc_sine
        self.globals["acos"] = arc_cosine
        self.globals["atan"] = arc_tangent
        self.globals["atan2"] = arc_tangent2
        self.globals["float"] = forgiving_float
        self.globals["as_local"] = dt_util.as_local
        self.globals["as_timestamp"] = forgiving_as_timestamp
        self.globals["relative_time"] = relative_time
        self.globals["timedelta"] = timedelta
        self.globals["strptime"] = strptime
        self.globals["urlencode"] = urlencode
        if hass is None:
            return

        # We mark these as a context functions to ensure they get
        # evaluated fresh with every execution, rather than executed
        # at compile time and the value stored. The context itself
        # can be discarded, we only need to get at the hass object.
        def hassfunction(func):
            """Wrap function that depend on hass."""
            @wraps(func)
            def wrapper(*args, **kwargs):
                return func(hass, *args[1:], **kwargs)

            return contextfunction(wrapper)

        self.globals["device_entities"] = hassfunction(device_entities)
        self.filters["device_entities"] = contextfilter(
            self.globals["device_entities"])

        if limited:
            # Only device_entities is available to limited templates, mark other
            # functions and filters as unsupported.
            def unsupported(name):
                def warn_unsupported(*args, **kwargs):
                    raise TemplateError(
                        f"Use of '{name}' is not supported in limited templates"
                    )

                return warn_unsupported

            hass_globals = [
                "closest",
                "distance",
                "expand",
                "is_state",
                "is_state_attr",
                "state_attr",
                "states",
                "utcnow",
                "now",
            ]
            hass_filters = ["closest", "expand"]
            for glob in hass_globals:
                self.globals[glob] = unsupported(glob)
            for filt in hass_filters:
                self.filters[filt] = unsupported(filt)
            return

        self.globals["expand"] = hassfunction(expand)
        self.filters["expand"] = contextfilter(self.globals["expand"])
        self.globals["closest"] = hassfunction(closest)
        self.filters["closest"] = contextfilter(hassfunction(closest_filter))
        self.globals["distance"] = hassfunction(distance)
        self.globals["is_state"] = hassfunction(is_state)
        self.globals["is_state_attr"] = hassfunction(is_state_attr)
        self.globals["state_attr"] = hassfunction(state_attr)
        self.globals["states"] = AllStates(hass)
        self.globals["utcnow"] = hassfunction(utcnow)
        self.globals["now"] = hassfunction(now)
Example #15
0
    def __init__(self, project, load_plugins=True, extra_flags=None):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.theme_paths = [
            os.path.join(self.root_path, 'themes', theme)
            for theme in self.project.themes
        ]

        if not self.theme_paths:
            # load the directories in the themes directory as the themes
            try:
                for fname in os.listdir(os.path.join(self.root_path,
                                                     'themes')):
                    f = os.path.join(self.root_path, 'themes', fname)
                    if os.path.isdir(f):
                        self.theme_paths.append(f)
            except OSError:
                pass

        template_paths = [
            os.path.join(path, 'templates')
            for path in [self.root_path] + self.theme_paths
        ]

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=[
                'jinja2.ext.autoescape', 'jinja2.ext.with_', 'jinja2.ext.do'
            ],
            loader=jinja2.FileSystemLoader(template_paths))

        from lektor.db import F, get_alts
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(
                lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_alts=get_alts,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types
        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers
        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self, extra_flags)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []
        self.virtual_sources = {}

        if load_plugins:
            self.load_plugins()

        from lektor.db import siblings_resolver
        self.virtualpathresolver('siblings')(siblings_resolver)
Example #16
0
 def _register(self):
     django_jinja.library.filter(name=self.name,
                                 fn=jinja2.contextfilter(self))
Example #17
0
        def get_localtime_wrapper(conversion_wrapper):
            def localtime_wrapper(context, value, *args, **kwargs):
                value = template_localtime(value, use_tz=context.use_tz)
                return conversion_wrapper(value, *args, **kwargs)

            return contextfilter(localtime_wrapper)
Example #18
0
def register_filter(func, name=None, ctx=False):
    name = name or func.__name__
    if ctx:
        func = contextfilter(func)
    JINJA_FILTERS[name] = func
Example #19
0
    def __init__(self, hass):
        """Initialise template environment."""
        super().__init__()
        self.hass = hass
        self.filters['round'] = forgiving_round
        self.filters['multiply'] = multiply
        self.filters['log'] = logarithm
        self.filters['sin'] = sine
        self.filters['cos'] = cosine
        self.filters['tan'] = tangent
        self.filters['sqrt'] = square_root
        self.filters['as_timestamp'] = forgiving_as_timestamp
        self.filters['timestamp_custom'] = timestamp_custom
        self.filters['timestamp_local'] = timestamp_local
        self.filters['timestamp_utc'] = timestamp_utc
        self.filters['is_defined'] = fail_when_undefined
        self.filters['max'] = max
        self.filters['min'] = min
        self.filters['random'] = random_every_time
        self.filters['base64_encode'] = base64_encode
        self.filters['base64_decode'] = base64_decode
        self.filters['ordinal'] = ordinal
        self.filters['regex_match'] = regex_match
        self.filters['regex_replace'] = regex_replace
        self.filters['regex_search'] = regex_search
        self.filters['regex_findall_index'] = regex_findall_index
        self.filters['bitwise_and'] = bitwise_and
        self.filters['bitwise_or'] = bitwise_or
        self.globals['log'] = logarithm
        self.globals['sin'] = sine
        self.globals['cos'] = cosine
        self.globals['tan'] = tangent
        self.globals['sqrt'] = square_root
        self.globals['pi'] = math.pi
        self.globals['tau'] = math.pi * 2
        self.globals['e'] = math.e
        self.globals['float'] = forgiving_float
        self.globals['now'] = dt_util.now
        self.globals['utcnow'] = dt_util.utcnow
        self.globals['as_timestamp'] = forgiving_as_timestamp
        self.globals['relative_time'] = dt_util.get_age
        self.globals['strptime'] = strptime
        if hass is None:
            return

        # We mark these as a context functions to ensure they get
        # evaluated fresh with every execution, rather than executed
        # at compile time and the value stored. The context itself
        # can be discarded, we only need to get at the hass object.
        def hassfunction(func):
            """Wrap function that depend on hass."""
            @wraps(func)
            def wrapper(*args, **kwargs):
                return func(hass, *args[1:], **kwargs)

            return contextfunction(wrapper)

        self.globals['expand'] = hassfunction(expand)
        self.filters['expand'] = contextfilter(self.globals['expand'])
        self.globals['closest'] = hassfunction(closest)
        self.filters['closest'] = contextfilter(hassfunction(closest_filter))
        self.globals['distance'] = hassfunction(distance)
        self.globals['is_state'] = hassfunction(is_state)
        self.globals['is_state_attr'] = hassfunction(is_state_attr)
        self.globals['state_attr'] = hassfunction(state_attr)
        self.globals['states'] = AllStates(hass)
Example #20
0
    def __init__(self, hass):
        """Initialise template environment."""
        super().__init__()
        self.hass = hass
        self.filters["round"] = forgiving_round
        self.filters["multiply"] = multiply
        self.filters["log"] = logarithm
        self.filters["sin"] = sine
        self.filters["cos"] = cosine
        self.filters["tan"] = tangent
        self.filters["asin"] = arc_sine
        self.filters["acos"] = arc_cosine
        self.filters["atan"] = arc_tangent
        self.filters["atan2"] = arc_tangent2
        self.filters["sqrt"] = square_root
        self.filters["as_timestamp"] = forgiving_as_timestamp
        self.filters["timestamp_custom"] = timestamp_custom
        self.filters["timestamp_local"] = timestamp_local
        self.filters["timestamp_utc"] = timestamp_utc
        self.filters["is_defined"] = fail_when_undefined
        self.filters["max"] = max
        self.filters["min"] = min
        self.filters["random"] = random_every_time
        self.filters["base64_encode"] = base64_encode
        self.filters["base64_decode"] = base64_decode
        self.filters["ordinal"] = ordinal
        self.filters["regex_match"] = regex_match
        self.filters["regex_replace"] = regex_replace
        self.filters["regex_search"] = regex_search
        self.filters["regex_findall_index"] = regex_findall_index
        self.filters["bitwise_and"] = bitwise_and
        self.filters["bitwise_or"] = bitwise_or
        self.filters["ord"] = ord
        self.globals["log"] = logarithm
        self.globals["sin"] = sine
        self.globals["cos"] = cosine
        self.globals["tan"] = tangent
        self.globals["sqrt"] = square_root
        self.globals["pi"] = math.pi
        self.globals["tau"] = math.pi * 2
        self.globals["e"] = math.e
        self.globals["asin"] = arc_sine
        self.globals["acos"] = arc_cosine
        self.globals["atan"] = arc_tangent
        self.globals["atan2"] = arc_tangent2
        self.globals["float"] = forgiving_float
        self.globals["now"] = dt_util.now
        self.globals["utcnow"] = dt_util.utcnow
        self.globals["as_timestamp"] = forgiving_as_timestamp
        self.globals["relative_time"] = dt_util.get_age
        self.globals["strptime"] = strptime
        if hass is None:
            return

        # We mark these as a context functions to ensure they get
        # evaluated fresh with every execution, rather than executed
        # at compile time and the value stored. The context itself
        # can be discarded, we only need to get at the hass object.
        def hassfunction(func):
            """Wrap function that depend on hass."""

            @wraps(func)
            def wrapper(*args, **kwargs):
                return func(hass, *args[1:], **kwargs)

            return contextfunction(wrapper)

        self.globals["expand"] = hassfunction(expand)
        self.filters["expand"] = contextfilter(self.globals["expand"])
        self.globals["closest"] = hassfunction(closest)
        self.filters["closest"] = contextfilter(hassfunction(closest_filter))
        self.globals["distance"] = hassfunction(distance)
        self.globals["is_state"] = hassfunction(is_state)
        self.globals["is_state_attr"] = hassfunction(is_state_attr)
        self.globals["state_attr"] = hassfunction(state_attr)
        self.globals["states"] = AllStates(hass)
Example #21
0
def create_environment(site: Site,
                       default_locale: Optional[str] = None) -> Environment:
    if default_locale is None:
        default_locale = site.configuration.default_locale
    url_generator = SiteUrlGenerator(site.configuration)
    template_directory_paths = list(
        [join(path, 'templates') for path in site.resources.paths])
    environment = Environment(
        loader=FileSystemLoader(template_directory_paths),
        undefined=StrictUndefined,
        autoescape=select_autoescape(['html']),
        trim_blocks=True,
        lstrip_blocks=True,
        extensions=[
            'jinja2.ext.do',
            'jinja2.ext.i18n',
        ],
    )
    environment.install_gettext_translations(site.translations[default_locale])
    environment.globals['site'] = site
    environment.globals['locale'] = default_locale
    environment.globals['plugins'] = _Plugins(site.plugins)
    environment.globals['EventType'] = Event.Type
    environment.globals['PresenceRole'] = Presence.Role
    environment.globals['urlparse'] = urlparse
    environment.filters['map'] = _filter_map
    environment.filters['flatten'] = _filter_flatten
    environment.filters['walk'] = _filter_walk
    environment.filters['takewhile'] = _filter_takewhile
    environment.filters['locale_get_data'] = lambda locale: Locale.parse(
        locale, '-')
    environment.filters[
        'negotiate_localizeds'] = lambda localizeds: negotiate_localizeds(
            default_locale, localizeds)
    environment.filters['sort_localizeds'] = contextfilter(
        lambda context, *args, **kwargs: _filter_sort_localizeds(
            context, default_locale, *args, **kwargs))

    # A filter to convert any value to JSON.
    @contextfilter
    def _filter_json(context, data, indent=None):
        return stdjson.dumps(data,
                             indent=indent,
                             cls=JSONEncoder.get_factory(
                                 site.configuration,
                                 resolve_or_missing(context, 'locale')))

    environment.filters['json'] = _filter_json

    # Override Jinja2's built-in JSON filter, which escapes the JSON for use in HTML, to use Betty's own encoder.
    @contextfilter
    def _filter_tojson(context, data, indent=None):
        return htmlsafe_json_dumps(data,
                                   indent=indent,
                                   dumper=lambda *args, **kwargs: _filter_json(
                                       context, *args, **kwargs))

    environment.filters['tojson'] = _filter_tojson
    environment.tests['resource'] = lambda x: isinstance(x, Resource)
    environment.tests['identifiable'] = lambda x: isinstance(x, Identifiable)
    environment.filters['paragraphs'] = _filter_paragraphs

    def _filter_format_date(date: Datey):
        with Translations(site.translations[default_locale]):
            return format_datey(date, default_locale)

    environment.filters['format_date'] = _filter_format_date
    environment.filters['format_degrees'] = _filter_format_degrees
    environment.globals['citer'] = _Citer()

    def _filter_url(resource, content_type=None, locale=None, **kwargs):
        content_type = content_type if content_type else 'text/html'
        locale = locale if locale else default_locale
        return url_generator.generate(resource,
                                      content_type,
                                      locale=locale,
                                      **kwargs)

    environment.filters['url'] = _filter_url
    environment.filters['static_url'] = StaticPathUrlGenerator(
        site.configuration).generate
    environment.filters['file'] = lambda *args: _filter_file(site, *args)
    environment.filters['image'] = lambda *args, **kwargs: _filter_image(
        site, *args, **kwargs)
    environment.globals['search_index'] = lambda: index(site, environment)
    for plugin in site.plugins.values():
        if isinstance(plugin, Jinja2Provider):
            environment.globals.update(plugin.globals)
            environment.filters.update(plugin.filters)
    return environment