v0.165.0
 1from collections.abc import Callable
 2from typing import Any
 3
 4from plain.packages import packages_registry
 5from plain.runtime import settings
 6from plain.utils.functional import LazyObject
 7from plain.utils.module_loading import import_string
 8
 9from .environments import DefaultEnvironment, get_template_dirs
10
11
12class JinjaEnvironment(LazyObject):
13    def _setup(self) -> None:
14        environment_setting = settings.TEMPLATES_JINJA_ENVIRONMENT
15
16        if isinstance(environment_setting, str):
17            env = import_string(environment_setting)()
18        else:
19            env = environment_setting()
20
21        # We have to set _wrapped before we trigger the autoloading of "register" commands
22        self._wrapped = env
23
24        # Autoload template helpers using the registry method
25        packages_registry.autodiscover_modules("templates", include_app=True)
26
27
28environment = JinjaEnvironment()
29
30
31def register_template_extension(extension_class: type) -> type:
32    environment.add_extension(extension_class)
33    return extension_class
34
35
36def register_template_global(value: Any, name: str | None = None) -> Any:
37    """
38    Adds a global to the Jinja environment.
39
40    Can be used as a decorator on a function:
41
42            @register_template_global
43            def my_global():
44                return "Hello, world!"
45
46    Or as a function:
47
48            register_template_global("Hello, world!", name="my_global")
49    """
50    if callable(value):
51        environment.globals[name or value.__name__] = value
52    elif name:
53        environment.globals[name] = value
54    else:
55        raise ValueError("name must be provided if value is not callable")
56
57    return value
58
59
60def register_template_filter(
61    func: Callable[..., Any], name: str | None = None
62) -> Callable[..., Any]:
63    """Adds a filter to the Jinja environment."""
64    filter_name = name if name is not None else func.__name__  # ty: ignore[unresolved-attribute]
65    environment.filters[filter_name] = func
66    return func
67
68
69__all__ = [
70    "DefaultEnvironment",
71    "environment",
72    "get_template_dirs",
73    "register_template_extension",
74    "register_template_filter",
75    "register_template_global",
76]