mercurial/templater.py
author Martin Geisler <mg@aragost.com>
Tue, 22 Jun 2010 12:38:39 +0200
branchstable
changeset 11429 d420ff348c49
parent 11305 d4cafcb63f77
child 12402 b014f998959d
permissions -rw-r--r--
discovery: use stable sort order in --new-branch warning A Python set seems to do this already when you iterate over it, but this should be considered an implementation detail and not something we can rely on. This also gets rid of an unnecessary string conversion -- the set already contains strings.
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
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8223
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9842
diff changeset
     6
# GNU General Public License version 2 or any later version.
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     7
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
     8
from i18n import _
10843
b91c1804008e templater: directly parse templates, no regexes
Matt Mackall <mpm@selenic.com>
parents: 10339
diff changeset
     9
import sys, os
8360
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8312
diff changeset
    10
import util, config, templatefilters
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
    11
7107
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
    12
path = ['templates', '../templates']
8360
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8312
diff changeset
    13
stringify = templatefilters.stringify
7107
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
    14
10850
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    15
def _flatten(thing):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    16
    '''yield a single stream from a possibly nested set of iterators'''
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    17
    if isinstance(thing, str):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    18
        yield thing
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    19
    elif not hasattr(thing, '__iter__'):
11305
d4cafcb63f77 cleanups: undefined variables
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10855
diff changeset
    20
        if thing is not None:
10852
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    21
            yield str(thing)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    22
    else:
10850
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    23
        for i in thing:
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    24
            if isinstance(i, str):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    25
                yield i
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    26
            elif not hasattr(i, '__iter__'):
10852
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    27
                if i is not None:
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    28
                    yield str(i)
10850
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    29
            elif i is not None:
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    30
                for j in _flatten(i):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    31
                    yield j
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
    32
1902
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    33
def parsestring(s, quoted=True):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    34
    '''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
    35
    string must be in quotes if quoted is True.'''
1902
1cc5f25653a3 make parsestring work with strings that do not have quotes.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1901
diff changeset
    36
    if quoted:
3639
5c9a36210662 templater: simplify parsestring
Matt Mackall <mpm@selenic.com>
parents: 3638
diff changeset
    37
        if len(s) < 2 or s[0] != s[-1]:
5c9a36210662 templater: simplify parsestring
Matt Mackall <mpm@selenic.com>
parents: 3638
diff changeset
    38
            raise SyntaxError(_('unmatched quotes'))
5c9a36210662 templater: simplify parsestring
Matt Mackall <mpm@selenic.com>
parents: 3638
diff changeset
    39
        return s[1:-1].decode('string_escape')
3632
231393b7316f templater: use str.decode in parse_string
Matt Mackall <mpm@selenic.com>
parents: 3462
diff changeset
    40
231393b7316f templater: use str.decode in parse_string
Matt Mackall <mpm@selenic.com>
parents: 3462
diff changeset
    41
    return s.decode('string_escape')
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    42
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
    43
class engine(object):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    44
    '''template expansion engine.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    45
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    46
    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
    47
    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
    48
    is treated as name of template file.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    49
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    50
    templater is asked to expand a key in map. it looks up key, and
4334
66a3fe30f9fc minor typo fix in templater's docstring
TK Soh <teekaysoh@yahoo.com>
parents: 3904
diff changeset
    51
    looks for strings like this: {foo}. it expands {foo} by looking up
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    52
    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
    53
    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
    54
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    55
    expansion also allows formatting and filtering.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    56
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    57
    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
    58
    {key%format}.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    59
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    60
    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
    61
    {key|filter1|filter2|...}.'''
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
    62
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
    63
    def __init__(self, loader, filters={}, defaults={}):
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
    64
        self._loader = loader
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
    65
        self._filters = filters
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
    66
        self._defaults = defaults
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
    67
        self._cache = {}
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
    68
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
    69
    def process(self, t, mapping):
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
    70
        '''Perform expansion. t is name of map element to expand.
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
    71
        mapping contains added elements for use during expansion. Is a
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
    72
        generator.'''
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
    73
        return _flatten(self._process(self._load(t), mapping))
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
    74
10852
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    75
    def _load(self, t):
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    76
        '''load, parse, and cache a template'''
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
    77
        if t not in self._cache:
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
    78
            self._cache[t] = self._parse(self._loader(t))
10852
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    79
        return self._cache[t]
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    80
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    81
    def _get(self, mapping, key):
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    82
        v = mapping.get(key)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    83
        if v is None:
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    84
            v = self._defaults.get(key, '')
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    85
        if hasattr(v, '__call__'):
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    86
            v = v(**mapping)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    87
        return v
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    88
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    89
    def _filter(self, mapping, parts):
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    90
        filters, val = parts
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    91
        x = self._get(mapping, val)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    92
        for f in filters:
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    93
            x = f(x)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    94
        return x
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    95
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    96
    def _format(self, mapping, args):
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    97
        key, parsed = args
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    98
        v = self._get(mapping, key)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
    99
        if not hasattr(v, '__iter__'):
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   100
            raise SyntaxError(_("error expanding '%s%%%s'")
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   101
                              % (key, format))
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   102
        lm = mapping.copy()
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   103
        for i in v:
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   104
            if isinstance(i, dict):
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   105
                lm.update(i)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   106
                yield self._process(parsed, lm)
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   107
            else:
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   108
                # v is not an iterable of dicts, this happen when 'key'
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   109
                # has been fully expanded already and format is useless.
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   110
                # If so, return the expanded value.
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   111
                yield i
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   112
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   113
    def _parse(self, tmpl):
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   114
        '''preparse a template'''
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   115
        parsed = []
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   116
        pos, stop = 0, len(tmpl)
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   117
        while pos < stop:
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   118
            n = tmpl.find('{', pos)
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   119
            if n < 0:
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   120
                parsed.append((None, tmpl[pos:stop]))
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   121
                break
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   122
            if n > 0 and tmpl[n - 1] == '\\':
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   123
                # escaped
10855
62216faed067 templater: drop \ when handling escaped {
Matt Mackall <mpm@selenic.com>
parents: 10854
diff changeset
   124
                parsed.append((None, tmpl[pos:n - 1] + "{"))
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   125
                pos = n + 1
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   126
                continue
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   127
            if n > pos:
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   128
                parsed.append((None, tmpl[pos:n]))
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   129
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   130
            pos = n
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   131
            n = tmpl.find('}', pos)
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   132
            if n < 0:
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   133
                # no closing
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   134
                parsed.append((None, tmpl[pos:stop]))
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   135
                break
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   136
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   137
            expr = tmpl[pos + 1:n]
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   138
            pos = n + 1
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   139
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   140
            if '%' in expr:
10852
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   141
                key, t = expr.split('%')
10854
4036634560d6 templater: strip whitespace inside template methods
Matt Mackall <mpm@selenic.com>
parents: 10853
diff changeset
   142
                parsed.append((self._format, (key.strip(),
4036634560d6 templater: strip whitespace inside template methods
Matt Mackall <mpm@selenic.com>
parents: 10853
diff changeset
   143
                                              self._load(t.strip()))))
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   144
            elif '|' in expr:
10846
594140b1e12d templater: extend preparsing
Matt Mackall <mpm@selenic.com>
parents: 10845
diff changeset
   145
                parts = expr.split('|')
10854
4036634560d6 templater: strip whitespace inside template methods
Matt Mackall <mpm@selenic.com>
parents: 10853
diff changeset
   146
                val = parts[0].strip()
10846
594140b1e12d templater: extend preparsing
Matt Mackall <mpm@selenic.com>
parents: 10845
diff changeset
   147
                try:
10854
4036634560d6 templater: strip whitespace inside template methods
Matt Mackall <mpm@selenic.com>
parents: 10853
diff changeset
   148
                    filters = [self._filters[f.strip()] for f in parts[1:]]
10846
594140b1e12d templater: extend preparsing
Matt Mackall <mpm@selenic.com>
parents: 10845
diff changeset
   149
                except KeyError, i:
594140b1e12d templater: extend preparsing
Matt Mackall <mpm@selenic.com>
parents: 10845
diff changeset
   150
                    raise SyntaxError(_("unknown filter '%s'") % i[0])
10852
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   151
                parsed.append((self._filter, (filters, val)))
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   152
            else:
10854
4036634560d6 templater: strip whitespace inside template methods
Matt Mackall <mpm@selenic.com>
parents: 10853
diff changeset
   153
                parsed.append((self._get, expr.strip()))
10845
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   154
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   155
        return parsed
9d8194c2fcbd templater: preparse templates and cache
Matt Mackall <mpm@selenic.com>
parents: 10843
diff changeset
   156
10846
594140b1e12d templater: extend preparsing
Matt Mackall <mpm@selenic.com>
parents: 10845
diff changeset
   157
    def _process(self, parsed, mapping):
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   158
        '''Render a template. Returns a generator.'''
10846
594140b1e12d templater: extend preparsing
Matt Mackall <mpm@selenic.com>
parents: 10845
diff changeset
   159
        for f, e in parsed:
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   160
            if f:
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   161
                yield f(mapping, e)
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   162
            else:
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   163
                yield e
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   164
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   165
engines = {'default': engine}
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   166
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   167
class templater(object):
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   168
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   169
    def __init__(self, mapfile, filters={}, defaults={}, cache={},
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   170
                 minchunk=1024, maxchunk=65536):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   171
        '''set up template engine.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   172
        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
   173
        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
   174
        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
   175
        self.mapfile = mapfile or 'template'
1975
6e1a8ea5d717 Duplicate cache when creating templater.
Shun-ichi Goto <shunichi.goto@gmail.com>
parents: 1964
diff changeset
   176
        self.cache = cache.copy()
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   177
        self.map = {}
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   178
        self.base = (mapfile and os.path.dirname(mapfile)) or ''
8360
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8312
diff changeset
   179
        self.filters = templatefilters.filters.copy()
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8312
diff changeset
   180
        self.filters.update(filters)
1964
778281d46bb2 fix template bug that made hgweb break.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1955
diff changeset
   181
        self.defaults = defaults
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   182
        self.minchunk, self.maxchunk = minchunk, maxchunk
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   183
        self.engines = {}
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   184
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   185
        if not mapfile:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   186
            return
6337
d2713d902524 give better error message on non-existent mapfile (issue813)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5976
diff changeset
   187
        if not os.path.exists(mapfile):
d2713d902524 give better error message on non-existent mapfile (issue813)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5976
diff changeset
   188
            raise util.Abort(_('style not found: %s') % mapfile)
d2713d902524 give better error message on non-existent mapfile (issue813)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5976
diff changeset
   189
8194
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   190
        conf = config.config()
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   191
        conf.read(mapfile)
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   192
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   193
        for key, val in conf[''].items():
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   194
            if val[0] in "'\"":
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   195
                try:
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   196
                    self.cache[key] = parsestring(val)
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   197
                except SyntaxError, inst:
63c47e4ac617 templater: use new config parser
Matt Mackall <mpm@selenic.com>
parents: 8015
diff changeset
   198
                    raise SyntaxError('%s: %s' %
8198
cf9accffd0b3 config: getsource -> source
Matt Mackall <mpm@selenic.com>
parents: 8194
diff changeset
   199
                                      (conf.source('', key), inst.args[0]))
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   200
            else:
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   201
                val = 'default', val
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   202
                if ':' in val[1]:
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   203
                    val = val[1].split(':', 1)
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   204
                self.map[key] = val[0], os.path.join(self.base, val[1])
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   205
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   206
    def __contains__(self, key):
3637
e7639888bb2f templater: simplify cache and remove filter argument in __call__
Matt Mackall <mpm@selenic.com>
parents: 3636
diff changeset
   207
        return key in self.cache or key in self.map
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   208
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   209
    def load(self, t):
6783
6d824dc86907 templater: make a template a string-only iterator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6434
diff changeset
   210
        '''Get the template for the given template name. Use a local cache.'''
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5269
diff changeset
   211
        if not t in self.cache:
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   212
            try:
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   213
                self.cache[t] = open(self.map[t][1]).read()
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   214
            except IOError, inst:
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
   215
                raise IOError(inst.args[0], _('template file %s: %s') %
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   216
                              (self.map[t][1], inst.args[1]))
6783
6d824dc86907 templater: make a template a string-only iterator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6434
diff changeset
   217
        return self.cache[t]
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   218
10847
90f4367535a5 templater: map -> mapping
Matt Mackall <mpm@selenic.com>
parents: 10846
diff changeset
   219
    def __call__(self, t, **mapping):
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   220
        ttype = t in self.map and self.map[t][0] or 'default'
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   221
        proc = self.engines.get(ttype)
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   222
        if proc is None:
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   223
            proc = engines[ttype](self.load, self.filters, self.defaults)
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   224
            self.engines[ttype] = proc
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
   225
10847
90f4367535a5 templater: map -> mapping
Matt Mackall <mpm@selenic.com>
parents: 10846
diff changeset
   226
        stream = proc.process(t, mapping)
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   227
        if self.minchunk:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   228
            stream = util.increasingchunks(stream, min=self.minchunk,
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   229
                                           max=self.maxchunk)
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   230
        return stream
7434
cf7741aa1e96 kill some trailing spaces
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7396
diff changeset
   231
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   232
def templatepath(name=None):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   233
    '''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
   234
    returns None if not found.'''
7107
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   235
    normpaths = []
2189
e3eba577a0ae move changeset_templater into templater module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2001
diff changeset
   236
2001
a439b7b51530 Windows py2exe version didn't handle names given to templatepath() correctly
Lee Cantey <lcantey@gmail.com>
parents: 1987
diff changeset
   237
    # executable version (py2exe) doesn't support __file__
a439b7b51530 Windows py2exe version didn't handle names given to templatepath() correctly
Lee Cantey <lcantey@gmail.com>
parents: 1987
diff changeset
   238
    if hasattr(sys, 'frozen'):
a439b7b51530 Windows py2exe version didn't handle names given to templatepath() correctly
Lee Cantey <lcantey@gmail.com>
parents: 1987
diff changeset
   239
        module = sys.executable
a439b7b51530 Windows py2exe version didn't handle names given to templatepath() correctly
Lee Cantey <lcantey@gmail.com>
parents: 1987
diff changeset
   240
    else:
a439b7b51530 Windows py2exe version didn't handle names given to templatepath() correctly
Lee Cantey <lcantey@gmail.com>
parents: 1987
diff changeset
   241
        module = __file__
7107
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   242
    for f in path:
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   243
        if f.startswith('/'):
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   244
            p = f
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   245
        else:
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   246
            fl = f.split('/')
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   247
            p = os.path.join(os.path.dirname(module), *fl)
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   248
        if name:
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   249
            p = os.path.join(p, name)
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   250
        if name and os.path.exists(p):
1897
58b6784cf9f1 move hgweb.templatepath into templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1896
diff changeset
   251
            return os.path.normpath(p)
7107
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   252
        elif os.path.isdir(p):
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   253
            normpaths.append(os.path.normpath(p))
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   254
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   255
    return normpaths
2189
e3eba577a0ae move changeset_templater into templater module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2001
diff changeset
   256
9842
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   257
def stylemap(styles, paths=None):
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   258
    """Return path to mapfile for a given style.
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   259
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   260
    Searches mapfile in the following locations:
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   261
    1. templatepath/style/map
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   262
    2. templatepath/map-style
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   263
    3. templatepath/map
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   264
    """
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   265
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   266
    if paths is None:
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   267
        paths = templatepath()
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   268
    elif isinstance(paths, str):
8223
02145b700fe4 templater: fix little problem from stylemap() changes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8218
diff changeset
   269
        paths = [paths]
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   270
9842
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   271
    if isinstance(styles, str):
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   272
        styles = [styles]
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   273
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   274
    for style in styles:
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   275
        if not style:
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   276
            continue
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   277
        locations = [os.path.join(style, 'map'), 'map-' + style]
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   278
        locations.append('map')
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   279
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   280
        for path in paths:
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   281
            for location in locations:
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   282
                mapfile = os.path.join(path, location)
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   283
                if os.path.isfile(mapfile):
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
   284
                    return style, mapfile
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   285
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
   286
    raise RuntimeError("No hgweb templates found in %r" % paths)