NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

filters.py (11681B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\jinja2\filters.py
      2 import re
      3 import math
      4 from random import choice
      5 from operator import itemgetter
      6 from itertools import imap, groupby
      7 from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, unicode_urlencode
      8 from jinja2.runtime import Undefined
      9 from jinja2.exceptions import FilterArgumentError
     10 _word_re = re.compile('\\w+(?u)')
     11 
     12 def contextfilter(f):
     13     f.contextfilter = True
     14     return f
     15 
     16 
     17 def evalcontextfilter(f):
     18     f.evalcontextfilter = True
     19     return f
     20 
     21 
     22 def environmentfilter(f):
     23     f.environmentfilter = True
     24     return f
     25 
     26 
     27 def make_attrgetter(environment, attribute):
     28     if not isinstance(attribute, basestring) or '.' not in attribute:
     29         return lambda x: environment.getitem(x, attribute)
     30     attribute = attribute.split('.')
     31 
     32     def attrgetter(item):
     33         for part in attribute:
     34             item = environment.getitem(item, part)
     35 
     36         return item
     37 
     38     return attrgetter
     39 
     40 
     41 def do_forceescape(value):
     42     if hasattr(value, '__html__'):
     43         value = value.__html__()
     44     return escape(unicode(value))
     45 
     46 
     47 def do_urlencode(value):
     48     itemiter = None
     49     if isinstance(value, dict):
     50         itemiter = value.iteritems()
     51     elif not isinstance(value, basestring):
     52         try:
     53             itemiter = iter(value)
     54         except TypeError:
     55             pass
     56 
     57     if itemiter is None:
     58         return unicode_urlencode(value)
     59     return u'&'.join((unicode_urlencode(k) + '=' + unicode_urlencode(v) for k, v in itemiter))
     60 
     61 
     62 @evalcontextfilter
     63 def do_replace(eval_ctx, s, old, new, count = None):
     64     if count is None:
     65         count = -1
     66     if not eval_ctx.autoescape:
     67         return unicode(s).replace(unicode(old), unicode(new), count)
     68     if hasattr(old, '__html__') or hasattr(new, '__html__') and not hasattr(s, '__html__'):
     69         s = escape(s)
     70     else:
     71         s = soft_unicode(s)
     72     return s.replace(soft_unicode(old), soft_unicode(new), count)
     73 
     74 
     75 def do_upper(s):
     76     return soft_unicode(s).upper()
     77 
     78 
     79 def do_lower(s):
     80     return soft_unicode(s).lower()
     81 
     82 
     83 @evalcontextfilter
     84 def do_xmlattr(_eval_ctx, d, autospace = True):
     85     rv = u' '.join((u'%s="%s"' % (escape(key), escape(value)) for key, value in d.iteritems() if value is not None and not isinstance(value, Undefined)))
     86     if autospace and rv:
     87         rv = u' ' + rv
     88     if _eval_ctx.autoescape:
     89         rv = Markup(rv)
     90     return rv
     91 
     92 
     93 def do_capitalize(s):
     94     return soft_unicode(s).capitalize()
     95 
     96 
     97 def do_title(s):
     98     return soft_unicode(s).title()
     99 
    100 
    101 def do_dictsort(value, case_sensitive = False, by = 'key'):
    102     if by == 'key':
    103         pos = 0
    104     elif by == 'value':
    105         pos = 1
    106     else:
    107         raise FilterArgumentError('You can only sort by either "key" or "value"')
    108 
    109     def sort_func(item):
    110         value = item[pos]
    111         if isinstance(value, basestring) and not case_sensitive:
    112             value = value.lower()
    113         return value
    114 
    115     return sorted(value.items(), key=sort_func)
    116 
    117 
    118 @environmentfilter
    119 def do_sort(environment, value, reverse = False, case_sensitive = False, attribute = None):
    120     if not case_sensitive:
    121 
    122         def sort_func(item):
    123             if isinstance(item, basestring):
    124                 item = item.lower()
    125             return item
    126 
    127     else:
    128         sort_func = None
    129     if attribute is not None:
    130         getter = make_attrgetter(environment, attribute)
    131 
    132         def sort_func(item, processor = sort_func or (lambda x: x)):
    133             return processor(getter(item))
    134 
    135     return sorted(value, key=sort_func, reverse=reverse)
    136 
    137 
    138 def do_default(value, default_value = u'', boolean = False):
    139     if boolean and not value or isinstance(value, Undefined):
    140         return default_value
    141     return value
    142 
    143 
    144 @evalcontextfilter
    145 def do_join(eval_ctx, value, d = u'', attribute = None):
    146     if attribute is not None:
    147         value = imap(make_attrgetter(eval_ctx.environment, attribute), value)
    148     if not eval_ctx.autoescape:
    149         return unicode(d).join(imap(unicode, value))
    150     if not hasattr(d, '__html__'):
    151         value = list(value)
    152         do_escape = False
    153         for idx, item in enumerate(value):
    154             if hasattr(item, '__html__'):
    155                 do_escape = True
    156             else:
    157                 value[idx] = unicode(item)
    158 
    159         if do_escape:
    160             d = escape(d)
    161         else:
    162             d = unicode(d)
    163         return d.join(value)
    164     return soft_unicode(d).join(imap(soft_unicode, value))
    165 
    166 
    167 def do_center(value, width = 80):
    168     return unicode(value).center(width)
    169 
    170 
    171 @environmentfilter
    172 def do_first(environment, seq):
    173     try:
    174         return iter(seq).next()
    175     except StopIteration:
    176         return environment.undefined('No first item, sequence was empty.')
    177 
    178 
    179 @environmentfilter
    180 def do_last(environment, seq):
    181     try:
    182         return iter(reversed(seq)).next()
    183     except StopIteration:
    184         return environment.undefined('No last item, sequence was empty.')
    185 
    186 
    187 @environmentfilter
    188 def do_random(environment, seq):
    189     try:
    190         return choice(seq)
    191     except IndexError:
    192         return environment.undefined('No random item, sequence was empty.')
    193 
    194 
    195 def do_filesizeformat(value, binary = False):
    196     bytes = float(value)
    197     base = binary and 1024 or 1000
    198     prefixes = [binary and 'KiB' or 'kB',
    199      binary and 'MiB' or 'MB',
    200      binary and 'GiB' or 'GB',
    201      binary and 'TiB' or 'TB',
    202      binary and 'PiB' or 'PB',
    203      binary and 'EiB' or 'EB',
    204      binary and 'ZiB' or 'ZB',
    205      binary and 'YiB' or 'YB']
    206     if bytes == 1:
    207         return '1 Byte'
    208     elif bytes < base:
    209         return '%d Bytes' % bytes
    210     else:
    211         for i, prefix in enumerate(prefixes):
    212             unit = base ** (i + 2)
    213             if bytes < unit:
    214                 return '%.1f %s' % (base * bytes / unit, prefix)
    215 
    216         return '%.1f %s' % (base * bytes / unit, prefix)
    217 
    218 
    219 def do_pprint(value, verbose = False):
    220     return pformat(value, verbose=verbose)
    221 
    222 
    223 @evalcontextfilter
    224 def do_urlize(eval_ctx, value, trim_url_limit = None, nofollow = False):
    225     rv = urlize(value, trim_url_limit, nofollow)
    226     if eval_ctx.autoescape:
    227         rv = Markup(rv)
    228     return rv
    229 
    230 
    231 def do_indent(s, width = 4, indentfirst = False):
    232     indention = u' ' * width
    233     rv = (u'\n' + indention).join(s.splitlines())
    234     if indentfirst:
    235         rv = indention + rv
    236     return rv
    237 
    238 
    239 def do_truncate(s, length = 255, killwords = False, end = '...'):
    240     if len(s) <= length:
    241         return s
    242     if killwords:
    243         return s[:length] + end
    244     words = s.split(' ')
    245     result = []
    246     m = 0
    247     for word in words:
    248         m += len(word) + 1
    249         if m > length:
    250             break
    251         result.append(word)
    252 
    253     result.append(end)
    254     return u' '.join(result)
    255 
    256 
    257 @environmentfilter
    258 def do_wordwrap(environment, s, width = 79, break_long_words = True):
    259     import textwrap
    260     return environment.newline_sequence.join(textwrap.wrap(s, width=width, expand_tabs=False, replace_whitespace=False, break_long_words=break_long_words))
    261 
    262 
    263 def do_wordcount(s):
    264     return len(_word_re.findall(s))
    265 
    266 
    267 def do_int(value, default = 0):
    268     try:
    269         return int(value)
    270     except (TypeError, ValueError):
    271         try:
    272             return int(float(value))
    273         except (TypeError, ValueError):
    274             return default
    275 
    276 
    277 def do_float(value, default = 0.0):
    278     try:
    279         return float(value)
    280     except (TypeError, ValueError):
    281         return default
    282 
    283 
    284 def do_format(value, *args, **kwargs):
    285     if args and kwargs:
    286         raise FilterArgumentError("can't handle positional and keyword arguments at the same time")
    287     return soft_unicode(value) % (kwargs or args)
    288 
    289 
    290 def do_trim(value):
    291     return soft_unicode(value).strip()
    292 
    293 
    294 def do_striptags(value):
    295     if hasattr(value, '__html__'):
    296         value = value.__html__()
    297     return Markup(unicode(value)).striptags()
    298 
    299 
    300 def do_slice(value, slices, fill_with = None):
    301     seq = list(value)
    302     length = len(seq)
    303     items_per_slice = length // slices
    304     slices_with_extra = length % slices
    305     offset = 0
    306     for slice_number in xrange(slices):
    307         start = offset + slice_number * items_per_slice
    308         if slice_number < slices_with_extra:
    309             offset += 1
    310         end = offset + (slice_number + 1) * items_per_slice
    311         tmp = seq[start:end]
    312         if fill_with is not None and slice_number >= slices_with_extra:
    313             tmp.append(fill_with)
    314         yield tmp
    315 
    316 
    317 def do_batch(value, linecount, fill_with = None):
    318     result = []
    319     tmp = []
    320     for item in value:
    321         if len(tmp) == linecount:
    322             yield tmp
    323             tmp = []
    324         tmp.append(item)
    325 
    326     if tmp:
    327         if fill_with is not None and len(tmp) < linecount:
    328             tmp += [fill_with] * (linecount - len(tmp))
    329         yield tmp
    330 
    331 
    332 def do_round(value, precision = 0, method = 'common'):
    333     if method not in ('common', 'ceil', 'floor'):
    334         raise FilterArgumentError('method must be common, ceil or floor')
    335     if method == 'common':
    336         return round(value, precision)
    337     func = getattr(math, method)
    338     return func(value * 10 ** precision) / 10 ** precision
    339 
    340 
    341 @environmentfilter
    342 def do_groupby(environment, value, attribute):
    343     expr = make_attrgetter(environment, attribute)
    344     return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
    345 
    346 
    347 class _GroupTuple(tuple):
    348     __slots__ = ()
    349     grouper = property(itemgetter(0))
    350     list = property(itemgetter(1))
    351 
    352     def __new__(cls, (key, value)):
    353         return tuple.__new__(cls, (key, list(value)))
    354 
    355 
    356 @environmentfilter
    357 def do_sum(environment, iterable, attribute = None, start = 0):
    358     if attribute is not None:
    359         iterable = imap(make_attrgetter(environment, attribute), iterable)
    360     return sum(iterable, start)
    361 
    362 
    363 def do_list(value):
    364     return list(value)
    365 
    366 
    367 def do_mark_safe(value):
    368     return Markup(value)
    369 
    370 
    371 def do_mark_unsafe(value):
    372     return unicode(value)
    373 
    374 
    375 def do_reverse(value):
    376     if isinstance(value, basestring):
    377         return value[::-1]
    378     try:
    379         return reversed(value)
    380     except TypeError:
    381         try:
    382             rv = list(value)
    383             rv.reverse()
    384             return rv
    385         except TypeError:
    386             raise FilterArgumentError('argument must be iterable')
    387 
    388 
    389 @environmentfilter
    390 def do_attr(environment, obj, name):
    391     try:
    392         name = str(name)
    393     except UnicodeError:
    394         pass
    395     else:
    396         try:
    397             value = getattr(obj, name)
    398         except AttributeError:
    399             pass
    400         else:
    401             if environment.sandboxed and not environment.is_safe_attribute(obj, name, value):
    402                 return environment.unsafe_undefined(obj, name)
    403             return value
    404 
    405     return environment.undefined(obj=obj, name=name)
    406 
    407 
    408 FILTERS = {'attr': do_attr,
    409  'replace': do_replace,
    410  'upper': do_upper,
    411  'lower': do_lower,
    412  'escape': escape,
    413  'e': escape,
    414  'forceescape': do_forceescape,
    415  'capitalize': do_capitalize,
    416  'title': do_title,
    417  'default': do_default,
    418  'd': do_default,
    419  'join': do_join,
    420  'count': len,
    421  'dictsort': do_dictsort,
    422  'sort': do_sort,
    423  'length': len,
    424  'reverse': do_reverse,
    425  'center': do_center,
    426  'indent': do_indent,
    427  'title': do_title,
    428  'capitalize': do_capitalize,
    429  'first': do_first,
    430  'last': do_last,
    431  'random': do_random,
    432  'filesizeformat': do_filesizeformat,
    433  'pprint': do_pprint,
    434  'truncate': do_truncate,
    435  'wordwrap': do_wordwrap,
    436  'wordcount': do_wordcount,
    437  'int': do_int,
    438  'float': do_float,
    439  'string': soft_unicode,
    440  'list': do_list,
    441  'urlize': do_urlize,
    442  'format': do_format,
    443  'trim': do_trim,
    444  'striptags': do_striptags,
    445  'slice': do_slice,
    446  'batch': do_batch,
    447  'sum': do_sum,
    448  'abs': abs,
    449  'round': do_round,
    450  'groupby': do_groupby,
    451  'safe': do_mark_safe,
    452  'xmlattr': do_xmlattr,
    453  'urlencode': do_urlencode}