Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/template/utils.py: 83%
56 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1import functools
2from collections import Counter
3from pathlib import Path
5from django.apps import apps
6from django.conf import settings
7from django.core.exceptions import ImproperlyConfigured
8from django.utils.functional import cached_property
9from django.utils.module_loading import import_string
12class InvalidTemplateEngineError(ImproperlyConfigured):
13 pass
16class EngineHandler:
17 def __init__(self, templates=None):
18 """
19 templates is an optional list of template engine definitions
20 (structured like settings.TEMPLATES).
21 """
22 self._templates = templates
23 self._engines = {}
25 @cached_property
26 def templates(self):
27 if self._templates is None: 27 ↛ 30line 27 didn't jump to line 30, because the condition on line 27 was never false
28 self._templates = settings.TEMPLATES
30 templates = {}
31 backend_names = []
32 for tpl in self._templates:
33 try:
34 # This will raise an exception if 'BACKEND' doesn't exist or
35 # isn't a string containing at least one dot.
36 default_name = tpl["BACKEND"].rsplit(".", 2)[-2]
37 except Exception:
38 invalid_backend = tpl.get("BACKEND", "<not defined>")
39 raise ImproperlyConfigured(
40 "Invalid BACKEND for a template engine: {}. Check "
41 "your TEMPLATES setting.".format(invalid_backend)
42 )
44 tpl = {
45 "NAME": default_name,
46 "DIRS": [],
47 "APP_DIRS": False,
48 "OPTIONS": {},
49 **tpl,
50 }
52 templates[tpl["NAME"]] = tpl
53 backend_names.append(tpl["NAME"])
55 counts = Counter(backend_names)
56 duplicates = [alias for alias, count in counts.most_common() if count > 1]
57 if duplicates: 57 ↛ 58line 57 didn't jump to line 58, because the condition on line 57 was never true
58 raise ImproperlyConfigured(
59 "Template engine aliases aren't unique, duplicates: {}. "
60 "Set a unique NAME for each engine in settings.TEMPLATES.".format(
61 ", ".join(duplicates)
62 )
63 )
65 return templates
67 def __getitem__(self, alias):
68 try:
69 return self._engines[alias]
70 except KeyError:
71 try:
72 params = self.templates[alias]
73 except KeyError:
74 raise InvalidTemplateEngineError(
75 "Could not find config for '{}' "
76 "in settings.TEMPLATES".format(alias)
77 )
79 # If importing or initializing the backend raises an exception,
80 # self._engines[alias] isn't set and this code may get executed
81 # again, so we must preserve the original params. See #24265.
82 params = params.copy()
83 backend = params.pop("BACKEND")
84 engine_cls = import_string(backend)
85 engine = engine_cls(params)
87 self._engines[alias] = engine
88 return engine
90 def __iter__(self):
91 return iter(self.templates)
93 def all(self):
94 return [self[alias] for alias in self]
97@functools.lru_cache()
98def get_app_template_dirs(dirname):
99 """
100 Return an iterable of paths of directories to load app templates from.
102 dirname is the name of the subdirectory containing templates inside
103 installed applications.
104 """
105 template_dirs = [
106 Path(app_config.path) / dirname
107 for app_config in apps.get_app_configs()
108 if app_config.path and (Path(app_config.path) / dirname).is_dir()
109 ]
110 # Immutable return value because it will be cached and shared by callers.
111 return tuple(template_dirs)