Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: third_party/jinja2/utils.py

Issue 2316103002: binding: Updates Jinja2 from 2.7.1 to 2.8. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/jinja2/tests.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 """ 2 """
3 jinja2.utils 3 jinja2.utils
4 ~~~~~~~~~~~~ 4 ~~~~~~~~~~~~
5 5
6 Utility functions. 6 Utility functions.
7 7
8 :copyright: (c) 2010 by the Jinja Team. 8 :copyright: (c) 2010 by the Jinja Team.
9 :license: BSD, see LICENSE for more details. 9 :license: BSD, see LICENSE for more details.
10 """ 10 """
11 import re 11 import re
12 import errno 12 import errno
13 from collections import deque 13 from collections import deque
14 from threading import Lock
14 from jinja2._compat import text_type, string_types, implements_iterator, \ 15 from jinja2._compat import text_type, string_types, implements_iterator, \
15 allocate_lock, url_quote 16 url_quote
16 17
17 18
18 _word_split_re = re.compile(r'(\s+)') 19 _word_split_re = re.compile(r'(\s+)')
19 _punctuation_re = re.compile( 20 _punctuation_re = re.compile(
20 '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % ( 21 '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
21 '|'.join(map(re.escape, ('(', '<', '&lt;'))), 22 '|'.join(map(re.escape, ('(', '<', '&lt;'))),
22 '|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '&gt;'))) 23 '|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
23 ) 24 )
24 ) 25 )
25 _simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$') 26 _simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 raise 143 raise
143 144
144 145
145 def open_if_exists(filename, mode='rb'): 146 def open_if_exists(filename, mode='rb'):
146 """Returns a file descriptor for the filename if that file exists, 147 """Returns a file descriptor for the filename if that file exists,
147 otherwise `None`. 148 otherwise `None`.
148 """ 149 """
149 try: 150 try:
150 return open(filename, mode) 151 return open(filename, mode)
151 except IOError as e: 152 except IOError as e:
152 if e.errno not in (errno.ENOENT, errno.EISDIR): 153 if e.errno not in (errno.ENOENT, errno.EISDIR, errno.EINVAL):
153 raise 154 raise
154 155
155 156
156 def object_type_repr(obj): 157 def object_type_repr(obj):
157 """Returns the name of the object's type. For some recognized 158 """Returns the name of the object's type. For some recognized
158 singletons the name of the object is returned instead. (For 159 singletons the name of the object is returned instead. (For
159 example for `None` and `Ellipsis`). 160 example for `None` and `Ellipsis`).
160 """ 161 """
161 if obj is None: 162 if obj is None:
162 return 'None' 163 return 'None'
(...skipping 12 matching lines...) Expand all
175 builtin `pprint`. 176 builtin `pprint`.
176 """ 177 """
177 try: 178 try:
178 from pretty import pretty 179 from pretty import pretty
179 return pretty(obj, verbose=verbose) 180 return pretty(obj, verbose=verbose)
180 except ImportError: 181 except ImportError:
181 from pprint import pformat 182 from pprint import pformat
182 return pformat(obj) 183 return pformat(obj)
183 184
184 185
185 def urlize(text, trim_url_limit=None, nofollow=False): 186 def urlize(text, trim_url_limit=None, nofollow=False, target=None):
186 """Converts any URLs in text into clickable links. Works on http://, 187 """Converts any URLs in text into clickable links. Works on http://,
187 https:// and www. links. Links can have trailing punctuation (periods, 188 https:// and www. links. Links can have trailing punctuation (periods,
188 commas, close-parens) and leading punctuation (opening parens) and 189 commas, close-parens) and leading punctuation (opening parens) and
189 it'll still do the right thing. 190 it'll still do the right thing.
190 191
191 If trim_url_limit is not None, the URLs in link text will be limited 192 If trim_url_limit is not None, the URLs in link text will be limited
192 to trim_url_limit characters. 193 to trim_url_limit characters.
193 194
194 If nofollow is True, the URLs in link text will get a rel="nofollow" 195 If nofollow is True, the URLs in link text will get a rel="nofollow"
195 attribute. 196 attribute.
197
198 If target is not None, a target attribute will be added to the link.
196 """ 199 """
197 trim_url = lambda x, limit=trim_url_limit: limit is not None \ 200 trim_url = lambda x, limit=trim_url_limit: limit is not None \
198 and (x[:limit] + (len(x) >=limit and '...' 201 and (x[:limit] + (len(x) >=limit and '...'
199 or '')) or x 202 or '')) or x
200 words = _word_split_re.split(text_type(escape(text))) 203 words = _word_split_re.split(text_type(escape(text)))
201 nofollow_attr = nofollow and ' rel="nofollow"' or '' 204 nofollow_attr = nofollow and ' rel="nofollow"' or ''
205 if target is not None and isinstance(target, string_types):
206 target_attr = ' target="%s"' % target
207 else:
208 target_attr = ''
202 for i, word in enumerate(words): 209 for i, word in enumerate(words):
203 match = _punctuation_re.match(word) 210 match = _punctuation_re.match(word)
204 if match: 211 if match:
205 lead, middle, trail = match.groups() 212 lead, middle, trail = match.groups()
206 if middle.startswith('www.') or ( 213 if middle.startswith('www.') or (
207 '@' not in middle and 214 '@' not in middle and
208 not middle.startswith('http://') and 215 not middle.startswith('http://') and
209 not middle.startswith('https://') and 216 not middle.startswith('https://') and
210 len(middle) > 0 and 217 len(middle) > 0 and
211 middle[0] in _letters + _digits and ( 218 middle[0] in _letters + _digits and (
212 middle.endswith('.org') or 219 middle.endswith('.org') or
213 middle.endswith('.net') or 220 middle.endswith('.net') or
214 middle.endswith('.com') 221 middle.endswith('.com')
215 )): 222 )):
216 middle = '<a href="http://%s"%s>%s</a>' % (middle, 223 middle = '<a href="http://%s"%s%s>%s</a>' % (middle,
217 nofollow_attr, trim_url(middle)) 224 nofollow_attr, target_attr, trim_url(middle))
218 if middle.startswith('http://') or \ 225 if middle.startswith('http://') or \
219 middle.startswith('https://'): 226 middle.startswith('https://'):
220 middle = '<a href="%s"%s>%s</a>' % (middle, 227 middle = '<a href="%s"%s%s>%s</a>' % (middle,
221 nofollow_attr, trim_url(middle)) 228 nofollow_attr, target_attr, trim_url(middle))
222 if '@' in middle and not middle.startswith('www.') and \ 229 if '@' in middle and not middle.startswith('www.') and \
223 not ':' in middle and _simple_email_re.match(middle): 230 not ':' in middle and _simple_email_re.match(middle):
224 middle = '<a href="mailto:%s">%s</a>' % (middle, middle) 231 middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
225 if lead + middle + trail != word: 232 if lead + middle + trail != word:
226 words[i] = lead + middle + trail 233 words[i] = lead + middle + trail
227 return u''.join(words) 234 return u''.join(words)
228 235
229 236
230 def generate_lorem_ipsum(n=5, html=True, min=20, max=100): 237 def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
231 """Generate some lorem impsum for the template.""" 238 """Generate some lorem ipsum for the template."""
232 from jinja2.constants import LOREM_IPSUM_WORDS 239 from jinja2.constants import LOREM_IPSUM_WORDS
233 from random import choice, randrange 240 from random import choice, randrange
234 words = LOREM_IPSUM_WORDS.split() 241 words = LOREM_IPSUM_WORDS.split()
235 result = [] 242 result = []
236 243
237 for _ in range(n): 244 for _ in range(n):
238 next_capitalized = True 245 next_capitalized = True
239 last_comma = last_fullstop = 0 246 last_comma = last_fullstop = 0
240 word = None 247 word = None
241 last = None 248 last = None
(...skipping 27 matching lines...) Expand all
269 p = p[:-1] + '.' 276 p = p[:-1] + '.'
270 elif not p.endswith('.'): 277 elif not p.endswith('.'):
271 p += '.' 278 p += '.'
272 result.append(p) 279 result.append(p)
273 280
274 if not html: 281 if not html:
275 return u'\n\n'.join(result) 282 return u'\n\n'.join(result)
276 return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result)) 283 return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
277 284
278 285
279 def unicode_urlencode(obj, charset='utf-8'): 286 def unicode_urlencode(obj, charset='utf-8', for_qs=False):
280 """URL escapes a single bytestring or unicode string with the 287 """URL escapes a single bytestring or unicode string with the
281 given charset if applicable to URL safe quoting under all rules 288 given charset if applicable to URL safe quoting under all rules
282 that need to be considered under all supported Python versions. 289 that need to be considered under all supported Python versions.
283 290
284 If non strings are provided they are converted to their unicode 291 If non strings are provided they are converted to their unicode
285 representation first. 292 representation first.
286 """ 293 """
287 if not isinstance(obj, string_types): 294 if not isinstance(obj, string_types):
288 obj = text_type(obj) 295 obj = text_type(obj)
289 if isinstance(obj, text_type): 296 if isinstance(obj, text_type):
290 obj = obj.encode(charset) 297 obj = obj.encode(charset)
291 return text_type(url_quote(obj)) 298 safe = for_qs and b'' or b'/'
299 rv = text_type(url_quote(obj, safe))
300 if for_qs:
301 rv = rv.replace('%20', '+')
302 return rv
292 303
293 304
294 class LRUCache(object): 305 class LRUCache(object):
295 """A simple LRU Cache implementation.""" 306 """A simple LRU Cache implementation."""
296 307
297 # this is fast for small capacities (something below 1000) but doesn't 308 # this is fast for small capacities (something below 1000) but doesn't
298 # scale. But as long as it's only used as storage for templates this 309 # scale. But as long as it's only used as storage for templates this
299 # won't do any harm. 310 # won't do any harm.
300 311
301 def __init__(self, capacity): 312 def __init__(self, capacity):
302 self.capacity = capacity 313 self.capacity = capacity
303 self._mapping = {} 314 self._mapping = {}
304 self._queue = deque() 315 self._queue = deque()
305 self._postinit() 316 self._postinit()
306 317
307 def _postinit(self): 318 def _postinit(self):
308 # alias all queue methods for faster lookup 319 # alias all queue methods for faster lookup
309 self._popleft = self._queue.popleft 320 self._popleft = self._queue.popleft
310 self._pop = self._queue.pop 321 self._pop = self._queue.pop
311 self._remove = self._queue.remove 322 self._remove = self._queue.remove
312 self._wlock = allocate_lock() 323 self._wlock = Lock()
313 self._append = self._queue.append 324 self._append = self._queue.append
314 325
315 def __getstate__(self): 326 def __getstate__(self):
316 return { 327 return {
317 'capacity': self.capacity, 328 'capacity': self.capacity,
318 '_mapping': self._mapping, 329 '_mapping': self._mapping,
319 '_queue': self._queue 330 '_queue': self._queue
320 } 331 }
321 332
322 def __setstate__(self, d): 333 def __setstate__(self, d):
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 522
512 def __call__(self): 523 def __call__(self):
513 if not self.used: 524 if not self.used:
514 self.used = True 525 self.used = True
515 return u'' 526 return u''
516 return self.sep 527 return self.sep
517 528
518 529
519 # Imported here because that's where it was in the past 530 # Imported here because that's where it was in the past
520 from markupsafe import Markup, escape, soft_unicode 531 from markupsafe import Markup, escape, soft_unicode
OLDNEW
« no previous file with comments | « third_party/jinja2/tests.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698