mercurial/templater.py
author Vadim Gelfer <vadim.gelfer@gmail.com>
Wed, 15 Mar 2006 11:28:00 -0800
changeset 1964 778281d46bb2
parent 1955 2f500a4b6e99
child 1975 6e1a8ea5d717
permissions -rw-r--r--
fix template bug that made hgweb break. problem found by Shun-ichi Goto <shunichi.goto@gmail.com>. this fix tested with command template and hgweb templates.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     1
# templater.py - template expansion for output
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     2
#
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     3
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     4
#
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     5
# This software may be used and distributed according to the terms
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     7
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
     8
import re
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     9
from demandload import demandload
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    10
from i18n import gettext as _
1955
2f500a4b6e99 Fix the py2exe template path problem (issue:152) again.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 1914
diff changeset
    11
demandload(globals(), "cStringIO cgi sys os time urllib util")
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    12
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    13
esctable = {
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    14
    '\\': '\\',
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    15
    'r': '\r',
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    16
    't': '\t',
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    17
    'n': '\n',
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    18
    'v': '\v',
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    19
    }
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    20
1902
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    21
def parsestring(s, quoted=True):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    22
    '''parse a string using simple c-like syntax.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    23
    string must be in quotes if quoted is True.'''
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    24
    fp = cStringIO.StringIO()
1902
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    25
    if quoted:
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    26
        first = s[0]
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    27
        if len(s) < 2: raise SyntaxError(_('string too short'))
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    28
        if first not in "'\"": raise SyntaxError(_('invalid quote'))
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    29
        if s[-1] != first: raise SyntaxError(_('unmatched quotes'))
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    30
        s = s[1:-1]
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    31
    escape = False
1902
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    32
    for c in s:
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    33
        if escape:
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    34
            fp.write(esctable.get(c, c))
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    35
            escape = False
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    36
        elif c == '\\': escape = True
1902
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    37
        elif quoted and c == first: raise SyntaxError(_('string ends early'))
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    38
        else: fp.write(c)
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    39
    if escape: raise SyntaxError(_('unterminated escape'))
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    40
    return fp.getvalue()
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    41
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    42
class templater(object):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    43
    '''template expansion engine.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    44
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    45
    template expansion works like this. a map file contains key=value
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    46
    pairs. if value is quoted, it is treated as string. otherwise, it
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    47
    is treated as name of template file.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    48
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    49
    templater is asked to expand a key in map. it looks up key, and
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    50
    looks for atrings like this: {foo}. it expands {foo} by looking up
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    51
    foo in map, and substituting it. expansion is recursive: it stops
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    52
    when there is no more {foo} to replace.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    53
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    54
    expansion also allows formatting and filtering.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    55
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    56
    format uses key to expand each item in list. syntax is
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    57
    {key%format}.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    58
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    59
    filter uses function to transform value. syntax is
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    60
    {key|filter1|filter2|...}.'''
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    61
1964
778281d46bb2 fix template bug that made hgweb break.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1955
diff changeset
    62
    def __init__(self, mapfile, filters={}, defaults={}, cache={}):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    63
        '''set up template engine.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    64
        mapfile is name of file to read map definitions from.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    65
        filters is dict of functions. each transforms a value into another.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    66
        defaults is dict of default map definitions.'''
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    67
        self.mapfile = mapfile or 'template'
1964
778281d46bb2 fix template bug that made hgweb break.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1955
diff changeset
    68
        self.cache = cache
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    69
        self.map = {}
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    70
        self.base = (mapfile and os.path.dirname(mapfile)) or ''
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    71
        self.filters = filters
1964
778281d46bb2 fix template bug that made hgweb break.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1955
diff changeset
    72
        self.defaults = defaults
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    73
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    74
        if not mapfile:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    75
            return
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    76
        i = 0
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    77
        for l in file(mapfile):
1914
a5bf0030df5f make --style=compact look for map-cmdline.compact.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1913
diff changeset
    78
            l = l.strip()
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    79
            i += 1
1914
a5bf0030df5f make --style=compact look for map-cmdline.compact.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1913
diff changeset
    80
            if not l or l[0] in '#;': continue
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    81
            m = re.match(r'([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$', l)
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    82
            if m:
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    83
                key, val = m.groups()
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    84
                if val[0] in "'\"":
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    85
                    try:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    86
                        self.cache[key] = parsestring(val)
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    87
                    except SyntaxError, inst:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    88
                        raise SyntaxError('%s:%s: %s' %
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    89
                                          (mapfile, i, inst.args[0]))
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    90
                else:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    91
                    self.map[key] = os.path.join(self.base, val)
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    92
            else:
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
    93
                raise SyntaxError(_("%s:%s: parse error") % (mapfile, i))
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    94
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
    95
    def __contains__(self, key):
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
    96
        return key in self.cache
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
    97
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    98
    def __call__(self, t, **map):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    99
        '''perform expansion.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   100
        t is name of map element to expand.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   101
        map is added elements to use during expansion.'''
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   102
        m = self.defaults.copy()
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   103
        m.update(map)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   104
        try:
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   105
            tmpl = self.cache[t]
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   106
        except KeyError:
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   107
            try:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   108
                tmpl = self.cache[t] = file(self.map[t]).read()
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   109
            except IOError, inst:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   110
                raise IOError(inst.args[0], _('template file %s: %s') %
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   111
                              (self.map[t], inst.args[1]))
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   112
        return self.template(tmpl, self.filters, **m)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   113
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   114
    template_re = re.compile(r"[#{]([a-zA-Z_][a-zA-Z0-9_]*)"
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   115
                             r"((%[a-zA-Z_][a-zA-Z0-9_]*)*)"
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   116
                             r"((\|[a-zA-Z_][a-zA-Z0-9_]*)*)[#}]")
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   117
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   118
    def template(self, tmpl, filters={}, **map):
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   119
        lm = map.copy()
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   120
        while tmpl:
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   121
            m = self.template_re.search(tmpl)
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   122
            if m:
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   123
                start, end = m.span(0)
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   124
                s, e = tmpl[start], tmpl[end - 1]
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   125
                key = m.group(1)
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   126
                if ((s == '#' and e != '#') or (s == '{' and e != '}')):
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   127
                    raise SyntaxError(_("'%s'/'%s' mismatch expanding '%s'") %
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   128
                                      (s, e, key))
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   129
                if start:
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   130
                    yield tmpl[:start]
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   131
                v = map.get(key, "")
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   132
                v = callable(v) and v(**map) or v
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   133
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   134
                format = m.group(2)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   135
                fl = m.group(4)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   136
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   137
                if format:
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   138
                    q = v.__iter__
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   139
                    for i in q():
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   140
                        lm.update(i)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   141
                        yield self(format[1:], **lm)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   142
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   143
                    v = ""
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   144
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   145
                elif fl:
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   146
                    for f in fl.split("|")[1:]:
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   147
                        v = filters[f](v)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   148
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   149
                yield v
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   150
                tmpl = tmpl[end:]
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   151
            else:
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   152
                yield tmpl
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   153
                break
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   154
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   155
agescales = [("second", 1),
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   156
             ("minute", 60),
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   157
             ("hour", 3600),
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   158
             ("day", 3600 * 24),
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   159
             ("week", 3600 * 24 * 7),
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   160
             ("month", 3600 * 24 * 30),
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   161
             ("year", 3600 * 24 * 365)]
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   162
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   163
agescales.reverse()
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   164
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   165
def age(date):
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   166
    '''turn a (timestamp, tzoff) tuple into an age string.'''
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   167
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   168
    def plural(t, c):
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   169
        if c == 1:
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   170
            return t
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   171
        return t + "s"
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   172
    def fmt(t, c):
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   173
        return "%d %s" % (c, plural(t, c))
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   174
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   175
    now = time.time()
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   176
    then = date[0]
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   177
    delta = max(1, int(now - then))
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   178
1900
f2815605186e move repeated work out of inner loops.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1899
diff changeset
   179
    for t, s in agescales:
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   180
        n = delta / s
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   181
        if n >= 2 or s == 1:
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   182
            return fmt(t, n)
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   183
1906
9dec2479622d add iso date template filter.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1905
diff changeset
   184
def isodate(date):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   185
    '''turn a (timestamp, tzoff) tuple into an iso 8631 date.'''
1906
9dec2479622d add iso date template filter.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1905
diff changeset
   186
    return util.datestr(date, format='%Y-%m-%d %H:%M')
9dec2479622d add iso date template filter.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1905
diff changeset
   187
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   188
def nl2br(text):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   189
    '''replace raw newlines with xhtml line breaks.'''
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   190
    return text.replace('\n', '<br/>\n')
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   191
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   192
def obfuscate(text):
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   193
    return ''.join(['&#%d;' % ord(c) for c in text])
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   194
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   195
def domain(author):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   196
    '''get domain of author, or empty string if none.'''
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   197
    f = author.find('@')
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   198
    if f == -1: return ''
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   199
    author = author[f+1:]
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   200
    f = author.find('>')
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   201
    if f >= 0: author = author[:f]
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   202
    return author
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   203
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   204
def person(author):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   205
    '''get name of author, or else username.'''
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   206
    f = author.find('<')
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   207
    if f == -1: return util.shortuser(author)
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   208
    return author[:f].rstrip()
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   209
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   210
common_filters = {
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   211
    "addbreaks": nl2br,
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   212
    "age": age,
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   213
    "date": lambda x: util.datestr(x),
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   214
    "domain": domain,
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   215
    "escape": lambda x: cgi.escape(x, True),
1912
b288b4bb8448 hide some functions behind lambdas, so demandload is useful.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1909
diff changeset
   216
    "firstline": lambda x: x.splitlines(1)[0].rstrip('\r\n'),
1906
9dec2479622d add iso date template filter.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1905
diff changeset
   217
    "isodate": isodate,
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   218
    "obfuscate": obfuscate,
1912
b288b4bb8448 hide some functions behind lambdas, so demandload is useful.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1909
diff changeset
   219
    "permissions": lambda x: x and "-rwxr-xr-x" or "-rw-r--r--",
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   220
    "person": person,
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   221
    "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"),
1912
b288b4bb8448 hide some functions behind lambdas, so demandload is useful.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1909
diff changeset
   222
    "short": lambda x: x[:12],
1904
a7e416bf3c1d improve templating.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1902
diff changeset
   223
    "strip": lambda x: x.strip(),
1912
b288b4bb8448 hide some functions behind lambdas, so demandload is useful.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1909
diff changeset
   224
    "urlescape": lambda x: urllib.quote(x),
b288b4bb8448 hide some functions behind lambdas, so demandload is useful.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1909
diff changeset
   225
    "user": lambda x: util.shortuser(x),
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   226
    }
1897
58b6784cf9f1 move hgweb.templatepath into templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1896
diff changeset
   227
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   228
def templatepath(name=None):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   229
    '''return location of template file or directory (if no name).
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   230
    returns None if not found.'''
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   231
    for f in 'templates', '../templates':
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   232
        fl = f.split('/')
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   233
        if name: fl.append(name)
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   234
        p = os.path.join(os.path.dirname(__file__), *fl)
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   235
        if (name and os.path.exists(p)) or os.path.isdir(p):
1897
58b6784cf9f1 move hgweb.templatepath into templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1896
diff changeset
   236
            return os.path.normpath(p)
1955
2f500a4b6e99 Fix the py2exe template path problem (issue:152) again.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 1914
diff changeset
   237
    else:
2f500a4b6e99 Fix the py2exe template path problem (issue:152) again.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 1914
diff changeset
   238
        # executable version (py2exe) doesn't support __file__
2f500a4b6e99 Fix the py2exe template path problem (issue:152) again.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 1914
diff changeset
   239
        if hasattr(sys, 'frozen'):
2f500a4b6e99 Fix the py2exe template path problem (issue:152) again.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 1914
diff changeset
   240
            return os.path.join(sys.prefix, "templates")