mercurial/templateutil.py
author Yuya Nishihara <yuya@tcha.org>
Wed, 21 Mar 2018 01:39:44 +0900
changeset 38254 12b6ee9e88f3
parent 38253 ad06a4264daf
child 38255 06d11cd90516
permissions -rw-r--r--
templater: move getdictitem() to hybrid class Since a raw dict will never be returned by evalwrapped(), we don't need to support d.get(key).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36919
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36918
diff changeset
     1
# templateutil.py - utility for template evaluation
1909
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
36919
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36918
diff changeset
     8
from __future__ import absolute_import
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
     9
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    10
import abc
17982
e06e9fd2d99f template engine: convert generator-based iterator to list-based iterator
Weiwen <weiwen@fb.com>
parents: 17890
diff changeset
    11
import types
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    12
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    13
from .i18n import _
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    14
from . import (
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    15
    error,
30620
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30342
diff changeset
    16
    pycompat,
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    17
    util,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    18
)
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
    19
from .utils import (
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
    20
    dateutil,
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
    21
    stringutil,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
    22
)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    23
36474
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36473
diff changeset
    24
class ResourceUnavailable(error.Abort):
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36473
diff changeset
    25
    pass
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36473
diff changeset
    26
36473
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36278
diff changeset
    27
class TemplateNotFound(error.Abort):
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36278
diff changeset
    28
    pass
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36278
diff changeset
    29
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    30
class wrapped(object):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    31
    """Object requiring extra conversion prior to displaying or processing
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    32
    as value
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    33
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    34
    Use unwrapvalue(), unwrapastype(), or unwraphybrid() to obtain the inner
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    35
    object.
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    36
    """
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    37
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    38
    __metaclass__ = abc.ABCMeta
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    39
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    40
    @abc.abstractmethod
37324
c2f74b8f6b7f templater: pass context to itermaps() for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 37323
diff changeset
    41
    def itermaps(self, context):
37323
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37281
diff changeset
    42
        """Yield each template mapping"""
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37281
diff changeset
    43
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37281
diff changeset
    44
    @abc.abstractmethod
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    45
    def join(self, context, mapping, sep):
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    46
        """Join items with the separator; Returns a bytes or (possibly nested)
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    47
        generator of bytes
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    48
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    49
        A pre-configured template may be rendered per item if this container
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    50
        holds unprintable items.
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    51
        """
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    52
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    53
    @abc.abstractmethod
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    54
    def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    55
        """Return a bytes or (possibly nested) generator of bytes representing
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    56
        the underlying object
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    57
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    58
        A pre-configured template may be rendered if the underlying object is
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    59
        not printable.
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    60
        """
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
    61
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    62
    @abc.abstractmethod
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    63
    def tovalue(self, context, mapping):
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    64
        """Move the inner value object out or create a value representation
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    65
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    66
        A returned value must be serializable by templaterfilters.json().
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    67
        """
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
    68
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    69
class wrappedbytes(wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    70
    """Wrapper for byte string"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    71
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    72
    def __init__(self, value):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    73
        self._value = value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    74
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    75
    def itermaps(self, context):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    76
        raise error.ParseError(_('%r is not iterable of mappings')
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    77
                               % pycompat.bytestr(self._value))
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    78
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    79
    def join(self, context, mapping, sep):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    80
        return joinitems(pycompat.iterbytestr(self._value), sep)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    81
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    82
    def show(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    83
        return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    84
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    85
    def tovalue(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    86
        return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    87
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    88
class wrappedvalue(wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    89
    """Generic wrapper for pure non-list/dict/bytes value"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    90
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    91
    def __init__(self, value):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    92
        self._value = value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    93
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    94
    def itermaps(self, context):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    95
        raise error.ParseError(_('%r is not iterable of mappings')
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    96
                               % self._value)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    97
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    98
    def join(self, context, mapping, sep):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
    99
        raise error.ParseError(_('%r is not iterable') % self._value)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   100
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   101
    def show(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   102
        return pycompat.bytestr(self._value)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   103
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   104
    def tovalue(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   105
        return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   106
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
   107
# stub for representing a date type; may be a real date type that can
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
   108
# provide a readable string value
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
   109
class date(object):
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
   110
    pass
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
   111
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   112
class hybrid(wrapped):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   113
    """Wrapper for list or dict to support legacy template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   114
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   115
    This class allows us to handle both:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   116
    - "{files}" (legacy command-line-specific list hack) and
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   117
    - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   118
    and to access raw values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   119
    - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   120
    - "{get(extras, key)}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   121
    - "{files|json}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   122
    """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   123
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   124
    def __init__(self, gen, values, makemap, joinfmt, keytype=None):
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   125
        self._gen = gen  # generator or function returning generator
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   126
        self._values = values
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   127
        self._makemap = makemap
37329
676664592313 templater: mark .joinfmt as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37327
diff changeset
   128
        self._joinfmt = joinfmt
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   129
        self.keytype = keytype  # hint for 'x in y' where type(x) is unresolved
37277
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
   130
38254
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   131
    def getmember(self, context, mapping, key):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   132
        # TODO: maybe split hybrid list/dict types?
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   133
        if not util.safehasattr(self._values, 'get'):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   134
            raise error.ParseError(_('not a dictionary'))
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   135
        return self._wrapvalue(key, self._values.get(key))
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   136
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   137
    def _wrapvalue(self, key, val):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   138
        if val is None:
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   139
            return
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   140
        return wraphybridvalue(self, key, val)
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   141
37324
c2f74b8f6b7f templater: pass context to itermaps() for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 37323
diff changeset
   142
    def itermaps(self, context):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   143
        makemap = self._makemap
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   144
        for x in self._values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   145
            yield makemap(x)
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   146
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   147
    def join(self, context, mapping, sep):
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   148
        # TODO: switch gen to (context, mapping) API?
37329
676664592313 templater: mark .joinfmt as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37327
diff changeset
   149
        return joinitems((self._joinfmt(x) for x in self._values), sep)
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   150
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   151
    def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   152
        # TODO: switch gen to (context, mapping) API?
37277
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
   153
        gen = self._gen
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   154
        if gen is None:
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   155
            return self.join(context, mapping, ' ')
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   156
        if callable(gen):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   157
            return gen()
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   158
        return gen
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   159
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   160
    def tovalue(self, context, mapping):
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   161
        # TODO: return self._values and get rid of proxy methods
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   162
        return self
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   163
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   164
    def __contains__(self, x):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   165
        return x in self._values
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   166
    def __getitem__(self, key):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   167
        return self._values[key]
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   168
    def __len__(self):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   169
        return len(self._values)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   170
    def __iter__(self):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   171
        return iter(self._values)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   172
    def __getattr__(self, name):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   173
        if name not in (r'get', r'items', r'iteritems', r'iterkeys',
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   174
                        r'itervalues', r'keys', r'values'):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   175
            raise AttributeError(name)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   176
        return getattr(self._values, name)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   177
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   178
class mappable(wrapped):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   179
    """Wrapper for non-list/dict object to support map operation
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   180
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   181
    This class allows us to handle both:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   182
    - "{manifest}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   183
    - "{manifest % '{rev}:{node}'}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   184
    - "{manifest.rev}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   185
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   186
    Unlike a hybrid, this does not simulate the behavior of the underling
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   187
    value.
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   188
    """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   189
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   190
    def __init__(self, gen, key, value, makemap):
37278
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   191
        self._gen = gen  # generator or function returning generator
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   192
        self._key = key
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   193
        self._value = value  # may be generator of strings
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   194
        self._makemap = makemap
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   195
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   196
    def tomap(self):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   197
        return self._makemap(self._key)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   198
37324
c2f74b8f6b7f templater: pass context to itermaps() for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 37323
diff changeset
   199
    def itermaps(self, context):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   200
        yield self.tomap()
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   201
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   202
    def join(self, context, mapping, sep):
38240
8bded7eae26c templater: consistently join() string-like object per character (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38238
diff changeset
   203
        w = makewrapped(context, mapping, self._value)
8bded7eae26c templater: consistently join() string-like object per character (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38238
diff changeset
   204
        return w.join(context, mapping, sep)
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   205
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   206
    def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   207
        # TODO: switch gen to (context, mapping) API?
37277
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
   208
        gen = self._gen
37278
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   209
        if gen is None:
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   210
            return pycompat.bytestr(self._value)
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   211
        if callable(gen):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   212
            return gen()
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   213
        return gen
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   214
37281
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   215
    def tovalue(self, context, mapping):
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   216
        return _unthunk(context, mapping, self._value)
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37280
diff changeset
   217
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   218
class _mappingsequence(wrapped):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   219
    """Wrapper for sequence of template mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   220
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   221
    This represents an inner template structure (i.e. a list of dicts),
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   222
    which can also be rendered by the specified named/literal template.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   223
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   224
    Template mappings may be nested.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   225
    """
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   226
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   227
    def __init__(self, name=None, tmpl=None, sep=''):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   228
        if name is not None and tmpl is not None:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   229
            raise error.ProgrammingError('name and tmpl are mutually exclusive')
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   230
        self._name = name
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   231
        self._tmpl = tmpl
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   232
        self._defaultsep = sep
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   233
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   234
    def join(self, context, mapping, sep):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   235
        mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context))
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   236
        if self._name:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   237
            itemiter = (context.process(self._name, m) for m in mapsiter)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   238
        elif self._tmpl:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   239
            itemiter = (context.expand(self._tmpl, m) for m in mapsiter)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   240
        else:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   241
            raise error.ParseError(_('not displayable without template'))
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   242
        return joinitems(itemiter, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   243
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   244
    def show(self, context, mapping):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   245
        return self.join(context, mapping, self._defaultsep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   246
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   247
    def tovalue(self, context, mapping):
37502
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   248
        knownres = context.knownresourcekeys()
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   249
        items = []
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   250
        for nm in self.itermaps(context):
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   251
            # drop internal resources (recursively) which shouldn't be displayed
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   252
            lm = context.overlaymap(mapping, nm)
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   253
            items.append({k: unwrapvalue(context, lm, v)
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   254
                          for k, v in nm.iteritems() if k not in knownres})
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   255
        return items
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   256
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   257
class mappinggenerator(_mappingsequence):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   258
    """Wrapper for generator of template mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   259
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   260
    The function ``make(context, *args)`` should return a generator of
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   261
    mapping dicts.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   262
    """
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   263
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   264
    def __init__(self, make, args=(), name=None, tmpl=None, sep=''):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   265
        super(mappinggenerator, self).__init__(name, tmpl, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   266
        self._make = make
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   267
        self._args = args
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   268
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   269
    def itermaps(self, context):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   270
        return self._make(context, *self._args)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   271
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   272
class mappinglist(_mappingsequence):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   273
    """Wrapper for list of template mappings"""
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   274
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   275
    def __init__(self, mappings, name=None, tmpl=None, sep=''):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   276
        super(mappinglist, self).__init__(name, tmpl, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   277
        self._mappings = mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   278
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   279
    def itermaps(self, context):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   280
        return iter(self._mappings)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   281
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   282
class mappedgenerator(wrapped):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   283
    """Wrapper for generator of strings which acts as a list
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   284
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   285
    The function ``make(context, *args)`` should return a generator of
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   286
    byte strings, or a generator of (possibly nested) generators of byte
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   287
    strings (i.e. a generator for a list of byte strings.)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   288
    """
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   289
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   290
    def __init__(self, make, args=()):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   291
        self._make = make
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   292
        self._args = args
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   293
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   294
    def _gen(self, context):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   295
        return self._make(context, *self._args)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   296
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   297
    def itermaps(self, context):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   298
        raise error.ParseError(_('list of strings is not mappable'))
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   299
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   300
    def join(self, context, mapping, sep):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   301
        return joinitems(self._gen(context), sep)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   302
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   303
    def show(self, context, mapping):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   304
        return self.join(context, mapping, '')
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   305
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   306
    def tovalue(self, context, mapping):
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   307
        return [stringify(context, mapping, x) for x in self._gen(context)]
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   308
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   309
def hybriddict(data, key='key', value='value', fmt=None, gen=None):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   310
    """Wrap data to support both dict-like and string-like operations"""
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   311
    prefmt = pycompat.identity
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   312
    if fmt is None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   313
        fmt = '%s=%s'
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   314
        prefmt = pycompat.bytestr
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   315
    return hybrid(gen, data, lambda k: {key: k, value: data[k]},
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   316
                  lambda k: fmt % (prefmt(k), prefmt(data[k])))
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   317
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   318
def hybridlist(data, name, fmt=None, gen=None):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   319
    """Wrap data to support both list-like and string-like operations"""
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   320
    prefmt = pycompat.identity
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   321
    if fmt is None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   322
        fmt = '%s'
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   323
        prefmt = pycompat.bytestr
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   324
    return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x))
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   325
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   326
def unwraphybrid(context, mapping, thing):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   327
    """Return an object which can be stringified possibly by using a legacy
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   328
    template"""
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   329
    if not isinstance(thing, wrapped):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   330
        return thing
37275
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37274
diff changeset
   331
    return thing.show(context, mapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   332
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   333
def wraphybridvalue(container, key, value):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   334
    """Wrap an element of hybrid container to be mappable
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   335
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   336
    The key is passed to the makemap function of the given container, which
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   337
    should be an item generated by iter(container).
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   338
    """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   339
    makemap = getattr(container, '_makemap', None)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   340
    if makemap is None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   341
        return value
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   342
    if util.safehasattr(value, '_makemap'):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   343
        # a nested hybrid list/dict, which has its own way of map operation
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   344
        return value
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   345
    return mappable(None, key, value, makemap)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   346
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   347
def compatdict(context, mapping, name, data, key='key', value='value',
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   348
               fmt=None, plural=None, separator=' '):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   349
    """Wrap data like hybriddict(), but also supports old-style list template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   350
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   351
    This exists for backward compatibility with the old-style template. Use
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   352
    hybriddict() for new template keywords.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   353
    """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   354
    c = [{key: k, value: v} for k, v in data.iteritems()]
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   355
    f = _showcompatlist(context, mapping, name, c, plural, separator)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   356
    return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   357
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   358
def compatlist(context, mapping, name, data, element=None, fmt=None,
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   359
               plural=None, separator=' '):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   360
    """Wrap data like hybridlist(), but also supports old-style list template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   361
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   362
    This exists for backward compatibility with the old-style template. Use
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   363
    hybridlist() for new template keywords.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   364
    """
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   365
    f = _showcompatlist(context, mapping, name, data, plural, separator)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   366
    return hybridlist(data, name=element or name, fmt=fmt, gen=f)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   367
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   368
def _showcompatlist(context, mapping, name, values, plural=None, separator=' '):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   369
    """Return a generator that renders old-style list template
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   370
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   371
    name is name of key in template map.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   372
    values is list of strings or dicts.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   373
    plural is plural of name, if not simply name + 's'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   374
    separator is used to join values as a string
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   375
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   376
    expansion works like this, given name 'foo'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   377
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   378
    if values is empty, expand 'no_foos'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   379
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   380
    if 'foo' not in template map, return values as a string,
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   381
    joined by 'separator'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   382
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   383
    expand 'start_foos'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   384
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   385
    for each value, expand 'foo'. if 'last_foo' in template
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   386
    map, expand it instead of 'foo' for last key.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   387
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   388
    expand 'end_foos'.
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   389
    """
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   390
    if not plural:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   391
        plural = name + 's'
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   392
    if not values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   393
        noname = 'no_' + plural
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   394
        if context.preload(noname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   395
            yield context.process(noname, mapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   396
        return
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   397
    if not context.preload(name):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   398
        if isinstance(values[0], bytes):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   399
            yield separator.join(values)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   400
        else:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   401
            for v in values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   402
                r = dict(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   403
                r.update(mapping)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   404
                yield r
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   405
        return
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   406
    startname = 'start_' + plural
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   407
    if context.preload(startname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   408
        yield context.process(startname, mapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   409
    def one(v, tag=name):
37077
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
   410
        vmapping = {}
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   411
        try:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   412
            vmapping.update(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   413
        # Python 2 raises ValueError if the type of v is wrong. Python
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   414
        # 3 raises TypeError.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   415
        except (AttributeError, TypeError, ValueError):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   416
            try:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   417
                # Python 2 raises ValueError trying to destructure an e.g.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   418
                # bytes. Python 3 raises TypeError.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   419
                for a, b in v:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   420
                    vmapping[a] = b
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   421
            except (TypeError, ValueError):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   422
                vmapping[name] = v
37077
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
   423
        vmapping = context.overlaymap(mapping, vmapping)
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   424
        return context.process(tag, vmapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   425
    lastname = 'last_' + name
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   426
    if context.preload(lastname):
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   427
        last = values.pop()
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   428
    else:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   429
        last = None
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   430
    for v in values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   431
        yield one(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   432
    if last is not None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   433
        yield one(last, tag=lastname)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   434
    endname = 'end_' + plural
37071
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   435
    if context.preload(endname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37022
diff changeset
   436
        yield context.process(endname, mapping)
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   437
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   438
def flatten(context, mapping, thing):
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   439
    """Yield a single stream from a possibly nested set of iterators"""
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   440
    thing = unwraphybrid(context, mapping, thing)
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   441
    if isinstance(thing, bytes):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   442
        yield thing
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   443
    elif isinstance(thing, str):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   444
        # We can only hit this on Python 3, and it's here to guard
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   445
        # against infinite recursion.
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   446
        raise error.ProgrammingError('Mercurial IO including templates is done'
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   447
                                     ' with bytes, not strings, got %r' % thing)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   448
    elif thing is None:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   449
        pass
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   450
    elif not util.safehasattr(thing, '__iter__'):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   451
        yield pycompat.bytestr(thing)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   452
    else:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   453
        for i in thing:
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   454
            i = unwraphybrid(context, mapping, i)
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   455
            if isinstance(i, bytes):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   456
                yield i
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   457
            elif i is None:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   458
                pass
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   459
            elif not util.safehasattr(i, '__iter__'):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   460
                yield pycompat.bytestr(i)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   461
            else:
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   462
                for j in flatten(context, mapping, i):
37159
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   463
                    yield j
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37107
diff changeset
   464
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   465
def stringify(context, mapping, thing):
36926
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36919
diff changeset
   466
    """Turn values into bytes by converting into text and concatenating them"""
37160
e09d2183e226 templateutil: reimplement stringify() using flatten()
Yuya Nishihara <yuya@tcha.org>
parents: 37159
diff changeset
   467
    if isinstance(thing, bytes):
e09d2183e226 templateutil: reimplement stringify() using flatten()
Yuya Nishihara <yuya@tcha.org>
parents: 37159
diff changeset
   468
        return thing  # retain localstr to be round-tripped
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   469
    return b''.join(flatten(context, mapping, thing))
36926
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36919
diff changeset
   470
31927
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   471
def findsymbolicname(arg):
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   472
    """Find symbolic name for the given compiled expression; returns None
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   473
    if nothing found reliably"""
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   474
    while True:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   475
        func, data = arg
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   476
        if func is runsymbol:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   477
            return data
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   478
        elif func is runfilter:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   479
            arg = data[0]
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   480
        else:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   481
            return None
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   482
37280
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
   483
def _unthunk(context, mapping, thing):
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
   484
    """Evaluate a lazy byte string into value"""
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
   485
    if not isinstance(thing, types.GeneratorType):
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
   486
        return thing
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
   487
    return stringify(context, mapping, thing)
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
   488
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   489
def evalrawexp(context, mapping, arg):
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   490
    """Evaluate given argument as a bare template object which may require
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   491
    further processing (such as folding generator of strings)"""
26124
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   492
    func, data = arg
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   493
    return func(context, mapping, data)
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   494
38238
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   495
def evalwrapped(context, mapping, arg):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   496
    """Evaluate given argument to wrapped object"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   497
    thing = evalrawexp(context, mapping, arg)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   498
    return makewrapped(context, mapping, thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   499
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   500
def makewrapped(context, mapping, thing):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   501
    """Lift object to a wrapped type"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   502
    if isinstance(thing, wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   503
        return thing
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   504
    thing = _unthunk(context, mapping, thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   505
    if isinstance(thing, bytes):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   506
        return wrappedbytes(thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   507
    return wrappedvalue(thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38237
diff changeset
   508
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   509
def evalfuncarg(context, mapping, arg):
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   510
    """Evaluate given argument as value type"""
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
   511
    return unwrapvalue(context, mapping, evalrawexp(context, mapping, arg))
37163
0023da2910c9 templater: extract type conversion from evalfuncarg()
Yuya Nishihara <yuya@tcha.org>
parents: 37162
diff changeset
   512
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
   513
def unwrapvalue(context, mapping, thing):
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
   514
    """Move the inner value object out of the wrapper"""
38236
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
   515
    if isinstance(thing, wrapped):
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
   516
        return thing.tovalue(context, mapping)
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   517
    # evalrawexp() may return string, generator of strings or arbitrary object
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   518
    # such as date tuple, but filter does not want generator.
37280
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
   519
    return _unthunk(context, mapping, thing)
26124
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   520
29827
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
   521
def evalboolean(context, mapping, arg):
29828
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
   522
    """Evaluate given argument as boolean, but also takes boolean literals"""
29827
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
   523
    func, data = arg
29828
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
   524
    if func is runsymbol:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
   525
        thing = func(context, mapping, data, default=None)
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
   526
        if thing is None:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
   527
            # not a template keyword, takes as a boolean literal
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37077
diff changeset
   528
            thing = stringutil.parsebool(data)
29828
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
   529
    else:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29827
diff changeset
   530
        thing = func(context, mapping, data)
38236
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
   531
    if isinstance(thing, wrapped):
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
   532
        thing = thing.tovalue(context, mapping)
29827
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
   533
    if isinstance(thing, bool):
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
   534
        return thing
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
   535
    # other objects are evaluated as strings, which means 0 is True, but
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
   536
    # empty dict/list should be False as they are expected to be ''
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   537
    return bool(stringify(context, mapping, thing))
29827
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29826
diff changeset
   538
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   539
def evaldate(context, mapping, arg, err=None):
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   540
    """Evaluate given argument as a date tuple or a date string; returns
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   541
    a (unixtime, offset) tuple"""
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   542
    thing = evalrawexp(context, mapping, arg)
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   543
    return unwrapdate(context, mapping, thing, err)
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   544
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   545
def unwrapdate(context, mapping, thing, err=None):
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
   546
    thing = unwrapvalue(context, mapping, thing)
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   547
    try:
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   548
        return dateutil.parsedate(thing)
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   549
    except AttributeError:
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   550
        raise error.ParseError(err or _('not a date tuple nor a string'))
37227
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
   551
    except error.ParseError:
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
   552
        if not err:
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
   553
            raise
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
   554
        raise error.ParseError(err)
37226
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   555
34581
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   556
def evalinteger(context, mapping, arg, err=None):
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   557
    thing = evalrawexp(context, mapping, arg)
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   558
    return unwrapinteger(context, mapping, thing, err)
37164
9ab3491f84c2 templater: extract unwrapinteger() function from evalinteger()
Yuya Nishihara <yuya@tcha.org>
parents: 37163
diff changeset
   559
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   560
def unwrapinteger(context, mapping, thing, err=None):
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
   561
    thing = unwrapvalue(context, mapping, thing)
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   562
    try:
37164
9ab3491f84c2 templater: extract unwrapinteger() function from evalinteger()
Yuya Nishihara <yuya@tcha.org>
parents: 37163
diff changeset
   563
        return int(thing)
28344
ac371d4c007f templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents: 28343
diff changeset
   564
    except (TypeError, ValueError):
34581
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   565
        raise error.ParseError(err or _('not an integer'))
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   566
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   567
def evalstring(context, mapping, arg):
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   568
    return stringify(context, mapping, evalrawexp(context, mapping, arg))
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   569
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   570
def evalstringliteral(context, mapping, arg):
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   571
    """Evaluate given argument as string template, but returns symbol name
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   572
    if it is unknown"""
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   573
    func, data = arg
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   574
    if func is runsymbol:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   575
        thing = func(context, mapping, data, default=data)
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   576
    else:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   577
        thing = func(context, mapping, data)
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   578
    return stringify(context, mapping, thing)
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   579
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
   580
_unwrapfuncbytype = {
38237
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38236
diff changeset
   581
    None: unwrapvalue,
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
   582
    bytes: stringify,
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37228
diff changeset
   583
    date: unwrapdate,
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
   584
    int: unwrapinteger,
34581
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   585
}
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   586
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   587
def unwrapastype(context, mapping, thing, typ):
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
   588
    """Move the inner value object out of the wrapper and coerce its type"""
34581
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   589
    try:
37165
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37164
diff changeset
   590
        f = _unwrapfuncbytype[typ]
34581
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   591
    except KeyError:
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   592
        raise error.ProgrammingError('invalid type specified: %r' % typ)
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   593
    return f(context, mapping, thing)
34581
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
   594
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   595
def runinteger(context, mapping, data):
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   596
    return int(data)
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   597
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   598
def runstring(context, mapping, data):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   599
    return data
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   600
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   601
def _recursivesymbolblocker(key):
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   602
    def showrecursion(**args):
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   603
        raise error.Abort(_("recursive reference '%s' in template") % key)
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   604
    return showrecursion
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   605
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   606
def runsymbol(context, mapping, key, default=''):
35471
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35421
diff changeset
   607
    v = context.symbol(mapping, key)
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
   608
    if v is None:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   609
        # put poison to cut recursion. we can't move this to parsing phase
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   610
        # because "x = {x}" is allowed if "x" is a keyword. (issue4758)
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   611
        safemapping = mapping.copy()
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   612
        safemapping[key] = _recursivesymbolblocker(key)
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
   613
        try:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   614
            v = context.process(key, safemapping)
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
   615
        except TemplateNotFound:
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   616
            v = default
36475
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   617
    if callable(v) and getattr(v, '_requires', None) is None:
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   618
        # old templatekw: expand all keywords and resources
37073
1101d6747d2d templater: drop 'templ' from resources dict
Yuya Nishihara <yuya@tcha.org>
parents: 37071
diff changeset
   619
        # (TODO: deprecate this after porting web template keywords to new API)
37076
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   620
        props = {k: context._resources.lookup(context, mapping, k)
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   621
                 for k in context._resources.knownkeys()}
37073
1101d6747d2d templater: drop 'templ' from resources dict
Yuya Nishihara <yuya@tcha.org>
parents: 37071
diff changeset
   622
        # pass context to _showcompatlist() through templatekw._showlist()
1101d6747d2d templater: drop 'templ' from resources dict
Yuya Nishihara <yuya@tcha.org>
parents: 37071
diff changeset
   623
        props['templ'] = context
35472
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35471
diff changeset
   624
        props.update(mapping)
35588
dadbf213a765 py3: convert dict keys' to str before passing as kwargs
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35485
diff changeset
   625
        return v(**pycompat.strkwargs(props))
36475
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   626
    if callable(v):
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   627
        # new templatekw
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   628
        try:
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   629
            return v(context, mapping)
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   630
        except ResourceUnavailable:
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   631
            # unsupported keyword is mapped to empty just like unknown keyword
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36474
diff changeset
   632
            return None
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   633
    return v
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   634
25595
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
   635
def runtemplate(context, mapping, template):
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   636
    for arg in template:
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   637
        yield evalrawexp(context, mapping, arg)
25595
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
   638
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   639
def runfilter(context, mapping, data):
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   640
    arg, filt = data
37224
54355c243042 templatefilters: allow declaration of input data type
Yuya Nishihara <yuya@tcha.org>
parents: 37165
diff changeset
   641
    thing = evalrawexp(context, mapping, arg)
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   642
    intype = getattr(filt, '_intype', None)
17383
099c778ceb33 templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents: 17334
diff changeset
   643
    try:
37274
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37233
diff changeset
   644
        thing = unwrapastype(context, mapping, thing, intype)
24280
6c55e37ba5f2 templater: allow piping generator-type function output to filters
Yuya Nishihara <yuya@tcha.org>
parents: 24240
diff changeset
   645
        return filt(thing)
37228
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   646
    except error.ParseError as e:
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   647
        raise error.ParseError(bytes(e), hint=_formatfiltererror(arg, filt))
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   648
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   649
def _formatfiltererror(arg, filt):
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   650
    fn = pycompat.sysbytes(filt.__name__)
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   651
    sym = findsymbolicname(arg)
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   652
    if not sym:
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   653
        return _("incompatible use of template filter '%s'") % fn
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   654
    return (_("template filter '%s' is not compatible with keyword '%s'")
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37227
diff changeset
   655
            % (fn, sym))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   656
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   657
def _iteroverlaymaps(context, origmapping, newmappings):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   658
    """Generate combined mappings from the original mapping and an iterable
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   659
    of partial mappings to override the original"""
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   660
    for i, nm in enumerate(newmappings):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   661
        lm = context.overlaymap(origmapping, nm)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   662
        lm['index'] = i
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   663
        yield lm
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   664
38241
7701c2d4a438 templater: always map over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38240
diff changeset
   665
def _applymap(context, mapping, d, targ):
7701c2d4a438 templater: always map over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38240
diff changeset
   666
    for lm in _iteroverlaymaps(context, mapping, d.itermaps(context)):
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   667
        yield evalrawexp(context, lm, targ)
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   668
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   669
def runmap(context, mapping, data):
34333
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34332
diff changeset
   670
    darg, targ = data
38241
7701c2d4a438 templater: always map over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38240
diff changeset
   671
    d = evalwrapped(context, mapping, darg)
7701c2d4a438 templater: always map over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38240
diff changeset
   672
    return mappedgenerator(_applymap, args=(mapping, d, targ))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   673
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   674
def runmember(context, mapping, data):
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   675
    darg, memb = data
38252
c2456a7726c1 templater: do dict lookup over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   676
    d = evalwrapped(context, mapping, darg)
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   677
    if util.safehasattr(d, 'tomap'):
37077
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37076
diff changeset
   678
        lm = context.overlaymap(mapping, d.tomap())
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   679
        return runsymbol(context, lm, memb)
38253
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   680
    try:
38254
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   681
        if util.safehasattr(d, 'getmember'):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38253
diff changeset
   682
            return d.getmember(context, mapping, memb)
38253
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   683
        raise error.ParseError
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   684
    except error.ParseError:
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   685
        sym = findsymbolicname(darg)
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   686
        if sym:
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   687
            raise error.ParseError(_("keyword '%s' has no member") % sym)
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   688
        else:
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38252
diff changeset
   689
            raise error.ParseError(_("%r has no member") % pycompat.bytestr(d))
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   690
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   691
def runnegate(context, mapping, data):
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   692
    data = evalinteger(context, mapping, data,
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   693
                       _('negation needs an integer argument'))
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   694
    return -data
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   695
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   696
def runarithmetic(context, mapping, data):
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   697
    func, left, right = data
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   698
    left = evalinteger(context, mapping, left,
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   699
                       _('arithmetic only defined on integers'))
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   700
    right = evalinteger(context, mapping, right,
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   701
                        _('arithmetic only defined on integers'))
30116
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
   702
    try:
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
   703
        return func(left, right)
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
   704
    except ZeroDivisionError:
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
   705
        raise error.Abort(_('division by zero is not defined'))
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   706
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   707
def joinitems(itemiter, sep):
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   708
    """Join items with the separator; Returns generator of bytes"""
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   709
    first = True
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   710
    for x in itemiter:
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   711
        if first:
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   712
            first = False
37326
9cd88dd3bf64 templater: micro-optimize join() with empty separator
Yuya Nishihara <yuya@tcha.org>
parents: 37325
diff changeset
   713
        elif sep:
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   714
            yield sep
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   715
        yield x