Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/rest_framework/templatetags/rest_framework.py: 29%

177 statements  

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

1import re 

2from collections import OrderedDict 

3 

4from django import template 

5from django.template import loader 

6from django.urls import NoReverseMatch, reverse 

7from django.utils.encoding import iri_to_uri 

8from django.utils.html import escape, format_html, smart_urlquote 

9from django.utils.safestring import mark_safe 

10 

11from rest_framework.compat import apply_markdown, pygments_highlight 

12from rest_framework.renderers import HTMLFormRenderer 

13from rest_framework.utils.urls import replace_query_param 

14 

15register = template.Library() 

16 

17# Regex for adding classes to html snippets 

18class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])') 

19 

20 

21@register.tag(name='code') 

22def highlight_code(parser, token): 

23 code = token.split_contents()[-1] 

24 nodelist = parser.parse(('endcode',)) 

25 parser.delete_first_token() 

26 return CodeNode(code, nodelist) 

27 

28 

29class CodeNode(template.Node): 

30 style = 'emacs' 

31 

32 def __init__(self, lang, code): 

33 self.lang = lang 

34 self.nodelist = code 

35 

36 def render(self, context): 

37 text = self.nodelist.render(context) 

38 return pygments_highlight(text, self.lang, self.style) 

39 

40 

41@register.filter() 

42def with_location(fields, location): 

43 return [ 

44 field for field in fields 

45 if field.location == location 

46 ] 

47 

48 

49@register.simple_tag 

50def form_for_link(link): 

51 import coreschema 

52 properties = OrderedDict([ 

53 (field.name, field.schema or coreschema.String()) 

54 for field in link.fields 

55 ]) 

56 required = [ 

57 field.name 

58 for field in link.fields 

59 if field.required 

60 ] 

61 schema = coreschema.Object(properties=properties, required=required) 

62 return mark_safe(coreschema.render_to_form(schema)) 

63 

64 

65@register.simple_tag 

66def render_markdown(markdown_text): 

67 if apply_markdown is None: 

68 return markdown_text 

69 return mark_safe(apply_markdown(markdown_text)) 

70 

71 

72@register.simple_tag 

73def get_pagination_html(pager): 

74 return pager.to_html() 

75 

76 

77@register.simple_tag 

78def render_form(serializer, template_pack=None): 

79 style = {'template_pack': template_pack} if template_pack else {} 

80 renderer = HTMLFormRenderer() 

81 return renderer.render(serializer.data, None, {'style': style}) 

82 

83 

84@register.simple_tag 

85def render_field(field, style): 

86 renderer = style.get('renderer', HTMLFormRenderer()) 

87 return renderer.render_field(field, style) 

88 

89 

90@register.simple_tag 

91def optional_login(request): 

92 """ 

93 Include a login snippet if REST framework's login view is in the URLconf. 

94 """ 

95 try: 

96 login_url = reverse('rest_framework:login') 

97 except NoReverseMatch: 

98 return '' 

99 

100 snippet = "<li><a href='{href}?next={next}'>Log in</a></li>" 

101 snippet = format_html(snippet, href=login_url, next=escape(request.path)) 

102 

103 return mark_safe(snippet) 

104 

105 

106@register.simple_tag 

107def optional_docs_login(request): 

108 """ 

109 Include a login snippet if REST framework's login view is in the URLconf. 

110 """ 

111 try: 

112 login_url = reverse('rest_framework:login') 

113 except NoReverseMatch: 

114 return 'log in' 

115 

116 snippet = "<a href='{href}?next={next}'>log in</a>" 

117 snippet = format_html(snippet, href=login_url, next=escape(request.path)) 

118 

119 return mark_safe(snippet) 

120 

121 

122@register.simple_tag 

123def optional_logout(request, user): 

124 """ 

125 Include a logout snippet if REST framework's logout view is in the URLconf. 

126 """ 

127 try: 

128 logout_url = reverse('rest_framework:logout') 

129 except NoReverseMatch: 

130 snippet = format_html('<li class="navbar-text">{user}</li>', user=escape(user)) 

131 return mark_safe(snippet) 

132 

133 snippet = """<li class="dropdown"> 

134 <a href="#" class="dropdown-toggle" data-toggle="dropdown"> 

135 {user} 

136 <b class="caret"></b> 

137 </a> 

138 <ul class="dropdown-menu"> 

139 <li><a href='{href}?next={next}'>Log out</a></li> 

140 </ul> 

141 </li>""" 

142 snippet = format_html(snippet, user=escape(user), href=logout_url, next=escape(request.path)) 

143 

144 return mark_safe(snippet) 

145 

146 

147@register.simple_tag 

148def add_query_param(request, key, val): 

149 """ 

150 Add a query parameter to the current request url, and return the new url. 

151 """ 

152 iri = request.get_full_path() 

153 uri = iri_to_uri(iri) 

154 return escape(replace_query_param(uri, key, val)) 

155 

156 

157@register.filter 

158def as_string(value): 

159 if value is None: 

160 return '' 

161 return '%s' % value 

162 

163 

164@register.filter 

165def as_list_of_strings(value): 

166 return [ 

167 '' if (item is None) else ('%s' % item) 

168 for item in value 

169 ] 

170 

171 

172@register.filter 

173def add_class(value, css_class): 

174 """ 

175 https://stackoverflow.com/questions/4124220/django-adding-css-classes-when-rendering-form-fields-in-a-template 

176 

177 Inserts classes into template variables that contain HTML tags, 

178 useful for modifying forms without needing to change the Form objects. 

179 

180 Usage: 

181 

182 {{ field.label_tag|add_class:"control-label" }} 

183 

184 In the case of REST Framework, the filter is used to add Bootstrap-specific 

185 classes to the forms. 

186 """ 

187 html = str(value) 

188 match = class_re.search(html) 

189 if match: 

190 m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class, 

191 css_class, css_class), 

192 match.group(1)) 

193 if not m: 

194 return mark_safe(class_re.sub(match.group(1) + " " + css_class, 

195 html)) 

196 else: 

197 return mark_safe(html.replace('>', ' class="%s">' % css_class, 1)) 

198 return value 

199 

200 

201@register.filter 

202def format_value(value): 

203 if getattr(value, 'is_hyperlink', False): 

204 name = str(value.obj) 

205 return mark_safe('<a href=%s>%s</a>' % (value, escape(name))) 

206 if value is None or isinstance(value, bool): 

207 return mark_safe('<code>%s</code>' % {True: 'true', False: 'false', None: 'null'}[value]) 

208 elif isinstance(value, list): 

209 if any(isinstance(item, (list, dict)) for item in value): 

210 template = loader.get_template('rest_framework/admin/list_value.html') 

211 else: 

212 template = loader.get_template('rest_framework/admin/simple_list_value.html') 

213 context = {'value': value} 

214 return template.render(context) 

215 elif isinstance(value, dict): 

216 template = loader.get_template('rest_framework/admin/dict_value.html') 

217 context = {'value': value} 

218 return template.render(context) 

219 elif isinstance(value, str): 

220 if ( 

221 (value.startswith('http:') or value.startswith('https:')) and not 

222 re.search(r'\s', value) 

223 ): 

224 return mark_safe('<a href="{value}">{value}</a>'.format(value=escape(value))) 

225 elif '@' in value and not re.search(r'\s', value): 

226 return mark_safe('<a href="mailto:{value}">{value}</a>'.format(value=escape(value))) 

227 elif '\n' in value: 

228 return mark_safe('<pre>%s</pre>' % escape(value)) 

229 return str(value) 

230 

231 

232@register.filter 

233def items(value): 

234 """ 

235 Simple filter to return the items of the dict. Useful when the dict may 

236 have a key 'items' which is resolved first in Django template dot-notation 

237 lookup. See issue #4931 

238 Also see: https://stackoverflow.com/questions/15416662/django-template-loop-over-dictionary-items-with-items-as-key 

239 """ 

240 if value is None: 

241 # `{% for k, v in value.items %}` doesn't raise when value is None or 

242 # not in the context, so neither should `{% for k, v in value|items %}` 

243 return [] 

244 return value.items() 

245 

246 

247@register.filter 

248def data(value): 

249 """ 

250 Simple filter to access `data` attribute of object, 

251 specifically coreapi.Document. 

252 

253 As per `items` filter above, allows accessing `document.data` when 

254 Document contains Link keyed-at "data". 

255 

256 See issue #5395 

257 """ 

258 return value.data 

259 

260 

261@register.filter 

262def schema_links(section, sec_key=None): 

263 """ 

264 Recursively find every link in a schema, even nested. 

265 """ 

266 NESTED_FORMAT = '%s > %s' # this format is used in docs/js/api.js:normalizeKeys 

267 links = section.links 

268 if section.data: 

269 data = section.data.items() 

270 for sub_section_key, sub_section in data: 

271 new_links = schema_links(sub_section, sec_key=sub_section_key) 

272 links.update(new_links) 

273 

274 if sec_key is not None: 

275 new_links = OrderedDict() 

276 for link_key, link in links.items(): 

277 new_key = NESTED_FORMAT % (sec_key, link_key) 

278 new_links.update({new_key: link}) 

279 return new_links 

280 

281 return links 

282 

283 

284@register.filter 

285def add_nested_class(value): 

286 if isinstance(value, dict): 

287 return 'class=nested' 

288 if isinstance(value, list) and any(isinstance(item, (list, dict)) for item in value): 

289 return 'class=nested' 

290 return '' 

291 

292 

293# Bunch of stuff cloned from urlize 

294TRAILING_PUNCTUATION = ['.', ',', ':', ';', '.)', '"', "']", "'}", "'"] 

295WRAPPING_PUNCTUATION = [('(', ')'), ('<', '>'), ('[', ']'), ('&lt;', '&gt;'), 

296 ('"', '"'), ("'", "'")] 

297word_split_re = re.compile(r'(\s+)') 

298simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE) 

299simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)$', re.IGNORECASE) 

300simple_email_re = re.compile(r'^\S+@\S+\.\S+$') 

301 

302 

303def smart_urlquote_wrapper(matched_url): 

304 """ 

305 Simple wrapper for smart_urlquote. ValueError("Invalid IPv6 URL") can 

306 be raised here, see issue #1386 

307 """ 

308 try: 

309 return smart_urlquote(matched_url) 

310 except ValueError: 

311 return None 

312 

313 

314@register.filter 

315def break_long_headers(header): 

316 """ 

317 Breaks headers longer than 160 characters (~page length) 

318 when possible (are comma separated) 

319 """ 

320 if len(header) > 160 and ',' in header: 

321 header = mark_safe('<br> ' + ', <br>'.join(header.split(','))) 

322 return header