Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/template/engine.py: 45%

115 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1import functools 

2 

3from django.core.exceptions import ImproperlyConfigured 

4from django.utils.functional import cached_property 

5from django.utils.module_loading import import_string 

6 

7from .base import Template 

8from .context import Context, _builtin_context_processors 

9from .exceptions import TemplateDoesNotExist 

10from .library import import_library 

11 

12 

13class Engine: 

14 default_builtins = [ 

15 "django.template.defaulttags", 

16 "django.template.defaultfilters", 

17 "django.template.loader_tags", 

18 ] 

19 

20 def __init__( 

21 self, 

22 dirs=None, 

23 app_dirs=False, 

24 context_processors=None, 

25 debug=False, 

26 loaders=None, 

27 string_if_invalid="", 

28 file_charset="utf-8", 

29 libraries=None, 

30 builtins=None, 

31 autoescape=True, 

32 ): 

33 if dirs is None: 

34 dirs = [] 

35 if context_processors is None: 

36 context_processors = [] 

37 if loaders is None: 37 ↛ 44line 37 didn't jump to line 44, because the condition on line 37 was never false

38 loaders = ["django.template.loaders.filesystem.Loader"] 

39 if app_dirs: 

40 loaders += ["django.template.loaders.app_directories.Loader"] 

41 if not debug: 

42 loaders = [("django.template.loaders.cached.Loader", loaders)] 

43 else: 

44 if app_dirs: 

45 raise ImproperlyConfigured( 

46 "app_dirs must not be set when loaders is defined." 

47 ) 

48 if libraries is None: 48 ↛ 49line 48 didn't jump to line 49, because the condition on line 48 was never true

49 libraries = {} 

50 if builtins is None: 50 ↛ 53line 50 didn't jump to line 53, because the condition on line 50 was never false

51 builtins = [] 

52 

53 self.dirs = dirs 

54 self.app_dirs = app_dirs 

55 self.autoescape = autoescape 

56 self.context_processors = context_processors 

57 self.debug = debug 

58 self.loaders = loaders 

59 self.string_if_invalid = string_if_invalid 

60 self.file_charset = file_charset 

61 self.libraries = libraries 

62 self.template_libraries = self.get_template_libraries(libraries) 

63 self.builtins = self.default_builtins + builtins 

64 self.template_builtins = self.get_template_builtins(self.builtins) 

65 

66 def __repr__(self): 

67 return ( 

68 "<%s:%s app_dirs=%s%s debug=%s loaders=%s string_if_invalid=%s " 

69 "file_charset=%s%s%s autoescape=%s>" 

70 ) % ( 

71 self.__class__.__qualname__, 

72 "" if not self.dirs else " dirs=%s" % repr(self.dirs), 

73 self.app_dirs, 

74 "" 

75 if not self.context_processors 

76 else " context_processors=%s" % repr(self.context_processors), 

77 self.debug, 

78 repr(self.loaders), 

79 repr(self.string_if_invalid), 

80 repr(self.file_charset), 

81 "" if not self.libraries else " libraries=%s" % repr(self.libraries), 

82 "" if not self.builtins else " builtins=%s" % repr(self.builtins), 

83 repr(self.autoescape), 

84 ) 

85 

86 @staticmethod 

87 @functools.lru_cache() 

88 def get_default(): 

89 """ 

90 Return the first DjangoTemplates backend that's configured, or raise 

91 ImproperlyConfigured if none are configured. 

92 

93 This is required for preserving historical APIs that rely on a 

94 globally available, implicitly configured engine such as: 

95 

96 >>> from django.template import Context, Template 

97 >>> template = Template("Hello {{ name }}!") 

98 >>> context = Context({'name': "world"}) 

99 >>> template.render(context) 

100 'Hello world!' 

101 """ 

102 # Since Engine is imported in django.template and since 

103 # DjangoTemplates is a wrapper around this Engine class, 

104 # local imports are required to avoid import loops. 

105 from django.template import engines 

106 from django.template.backends.django import DjangoTemplates 

107 

108 for engine in engines.all(): 

109 if isinstance(engine, DjangoTemplates): 

110 return engine.engine 

111 raise ImproperlyConfigured("No DjangoTemplates backend is configured.") 

112 

113 @cached_property 

114 def template_context_processors(self): 

115 context_processors = _builtin_context_processors 

116 context_processors += tuple(self.context_processors) 

117 return tuple(import_string(path) for path in context_processors) 

118 

119 def get_template_builtins(self, builtins): 

120 return [import_library(x) for x in builtins] 

121 

122 def get_template_libraries(self, libraries): 

123 loaded = {} 

124 for name, path in libraries.items(): 

125 loaded[name] = import_library(path) 

126 return loaded 

127 

128 @cached_property 

129 def template_loaders(self): 

130 return self.get_template_loaders(self.loaders) 

131 

132 def get_template_loaders(self, template_loaders): 

133 loaders = [] 

134 for template_loader in template_loaders: 

135 loader = self.find_template_loader(template_loader) 

136 if loader is not None: 

137 loaders.append(loader) 

138 return loaders 

139 

140 def find_template_loader(self, loader): 

141 if isinstance(loader, (tuple, list)): 

142 loader, *args = loader 

143 else: 

144 args = [] 

145 

146 if isinstance(loader, str): 

147 loader_class = import_string(loader) 

148 return loader_class(self, *args) 

149 else: 

150 raise ImproperlyConfigured( 

151 "Invalid value in template loaders configuration: %r" % loader 

152 ) 

153 

154 def find_template(self, name, dirs=None, skip=None): 

155 tried = [] 

156 for loader in self.template_loaders: 

157 try: 

158 template = loader.get_template(name, skip=skip) 

159 return template, template.origin 

160 except TemplateDoesNotExist as e: 

161 tried.extend(e.tried) 

162 raise TemplateDoesNotExist(name, tried=tried) 

163 

164 def from_string(self, template_code): 

165 """ 

166 Return a compiled Template object for the given template code, 

167 handling template inheritance recursively. 

168 """ 

169 return Template(template_code, engine=self) 

170 

171 def get_template(self, template_name): 

172 """ 

173 Return a compiled Template object for the given template name, 

174 handling template inheritance recursively. 

175 """ 

176 template, origin = self.find_template(template_name) 

177 if not hasattr(template, "render"): 

178 # template needs to be compiled 

179 template = Template(template, origin, template_name, engine=self) 

180 return template 

181 

182 def render_to_string(self, template_name, context=None): 

183 """ 

184 Render the template specified by template_name with the given context. 

185 For use in Django's test suite. 

186 """ 

187 if isinstance(template_name, (list, tuple)): 

188 t = self.select_template(template_name) 

189 else: 

190 t = self.get_template(template_name) 

191 # Django < 1.8 accepted a Context in `context` even though that's 

192 # unintended. Preserve this ability but don't rewrap `context`. 

193 if isinstance(context, Context): 

194 return t.render(context) 

195 else: 

196 return t.render(Context(context, autoescape=self.autoescape)) 

197 

198 def select_template(self, template_name_list): 

199 """ 

200 Given a list of template names, return the first that can be loaded. 

201 """ 

202 if not template_name_list: 

203 raise TemplateDoesNotExist("No template names provided") 

204 not_found = [] 

205 for template_name in template_name_list: 

206 try: 

207 return self.get_template(template_name) 

208 except TemplateDoesNotExist as exc: 

209 if exc.args[0] not in not_found: 

210 not_found.append(exc.args[0]) 

211 continue 

212 # If we get here, none of the templates could be loaded 

213 raise TemplateDoesNotExist(", ".join(not_found))