mercurial/templateutil.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Wed, 06 Mar 2024 16:10:44 +0100
changeset 51534 767b62cb728e
parent 50929 18c8c18993f0
permissions -rw-r--r--
branchcache: gather newly closed head in a dedicated set This is part of a series to more clearly split the update in two step. This will allow us to introduce a fast path during update in a future changeset.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
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
#
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 44591
diff changeset
     3
# Copyright 2005, 2006 Olivia Mackall <olivia@selenic.com>
1909
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
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
     8
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
     9
import abc
17982
e06e9fd2d99f template engine: convert generator-based iterator to list-based iterator
Weiwen <weiwen@fb.com>
parents: 17890
diff changeset
    10
import types
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    11
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    12
from .i18n import _
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    13
from . import (
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    14
    error,
30615
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
    15
    pycompat,
44589
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
    16
    smartset,
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
)
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
    19
from .utils import (
37224
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
    20
    dateutil,
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
    21
    stringutil,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37074
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
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
    24
36444
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36443
diff changeset
    25
class ResourceUnavailable(error.Abort):
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36443
diff changeset
    26
    pass
717a279c0c21 templater: specialize ResourceUnavailable error so that it can be caught
Yuya Nishihara <yuya@tcha.org>
parents: 36443
diff changeset
    27
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
    28
36443
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36245
diff changeset
    29
class TemplateNotFound(error.Abort):
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36245
diff changeset
    30
    pass
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36245
diff changeset
    31
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
    32
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
    33
class wrapped:  # pytype: disable=ignored-metaclass
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    34
    """Object requiring extra conversion prior to displaying or processing
37279
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
    35
    as value
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
    36
38270
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38269
diff changeset
    37
    Use unwrapvalue() or unwrapastype() to obtain the inner object.
37279
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
    38
    """
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    39
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    40
    __metaclass__ = abc.ABCMeta
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    41
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    42
    @abc.abstractmethod
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
    43
    def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
    44
        """Test if the specified item is in self
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
    45
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
    46
        The item argument may be a wrapped object.
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
    47
        """
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
    48
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
    49
    @abc.abstractmethod
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    50
    def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    51
        """Return a member item for the specified key
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    52
38244
688fbb758ba9 templater: resolve type of dict key in getmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38243
diff changeset
    53
        The key argument may be a wrapped object.
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    54
        A returned object may be either a wrapped object or a pure value
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    55
        depending on the self type.
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    56
        """
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    57
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
    58
    @abc.abstractmethod
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    59
    def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    60
        """Return the smallest item, which may be either a wrapped or a pure
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    61
        value depending on the self type"""
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    62
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    63
    @abc.abstractmethod
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    64
    def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    65
        """Return the largest item, which may be either a wrapped or a pure
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    66
        value depending on the self type"""
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    67
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
    68
    @abc.abstractmethod
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    69
    def filter(self, context, mapping, select):
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    70
        """Return new container of the same type which includes only the
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    71
        selected elements
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    72
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    73
        select() takes each item as a wrapped object and returns True/False.
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    74
        """
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    75
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
    76
    @abc.abstractmethod
37324
c2f74b8f6b7f templater: pass context to itermaps() for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 37323
diff changeset
    77
    def itermaps(self, context):
37323
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
    78
        """Yield each template mapping"""
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
    79
8c31b434697f templater: define interface for objects which act as iterator of mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37279
diff changeset
    80
    @abc.abstractmethod
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    81
    def join(self, context, mapping, sep):
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    82
        """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
    83
        generator of bytes
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    84
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    85
        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
    86
        holds unprintable items.
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    87
        """
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    88
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
    89
    @abc.abstractmethod
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    90
    def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    91
        """Return a bytes or (possibly nested) generator of bytes representing
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    92
        the underlying object
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    93
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    94
        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: 37272
diff changeset
    95
        not printable.
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    96
        """
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
    97
37279
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
    98
    @abc.abstractmethod
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
    99
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   100
        """Return a boolean representation of the inner value"""
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   101
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   102
    @abc.abstractmethod
37279
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   103
    def tovalue(self, context, mapping):
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   104
        """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: 37278
diff changeset
   105
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   106
        A returned value must be serializable by templaterfilters.json().
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   107
        """
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   108
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   109
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   110
class mappable:  # pytype: disable=ignored-metaclass
38284
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   111
    """Object which can be converted to a single template mapping"""
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   112
43464
3e57809d3251 templateutil: fix a missing ABCMeta assignment
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   113
    __metaclass__ = abc.ABCMeta
3e57809d3251 templateutil: fix a missing ABCMeta assignment
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   114
38284
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   115
    def itermaps(self, context):
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   116
        yield self.tomap(context)
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   117
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   118
    @abc.abstractmethod
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   119
    def tomap(self, context):
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   120
        """Create a single template mapping representing this"""
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   121
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   122
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   123
class wrappedbytes(wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   124
    """Wrapper for byte string"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   125
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   126
    def __init__(self, value):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   127
        self._value = value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   128
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   129
    def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   130
        item = stringify(context, mapping, item)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   131
        return item in self._value
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   132
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   133
    def getmember(self, context, mapping, key):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   134
        raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   135
            _(b'%r is not a dictionary') % pycompat.bytestr(self._value)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   136
        )
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   137
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   138
    def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   139
        return self._getby(context, mapping, min)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   140
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   141
    def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   142
        return self._getby(context, mapping, max)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   143
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   144
    def _getby(self, context, mapping, func):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   145
        if not self._value:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   146
            raise error.ParseError(_(b'empty string'))
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   147
        return func(pycompat.iterbytestr(self._value))
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   148
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   149
    def filter(self, context, mapping, select):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   150
        raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   151
            _(b'%r is not filterable') % pycompat.bytestr(self._value)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   152
        )
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   153
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   154
    def itermaps(self, context):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   155
        raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   156
            _(b'%r is not iterable of mappings') % pycompat.bytestr(self._value)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   157
        )
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   158
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   159
    def join(self, context, mapping, sep):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   160
        return joinitems(pycompat.iterbytestr(self._value), sep)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   161
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   162
    def show(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   163
        return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   164
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   165
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   166
        return bool(self._value)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   167
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   168
    def tovalue(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   169
        return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   170
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   171
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   172
class wrappedvalue(wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   173
    """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: 38225
diff changeset
   174
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   175
    def __init__(self, value):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   176
        self._value = value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   177
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   178
    def contains(self, context, mapping, item):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   179
        raise error.ParseError(_(b"%r is not iterable") % self._value)
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   180
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   181
    def getmember(self, context, mapping, key):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   182
        raise error.ParseError(_(b'%r is not a dictionary') % self._value)
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   183
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   184
    def getmin(self, context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   185
        raise error.ParseError(_(b"%r is not iterable") % self._value)
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   186
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   187
    def getmax(self, context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   188
        raise error.ParseError(_(b"%r is not iterable") % self._value)
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   189
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   190
    def filter(self, context, mapping, select):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   191
        raise error.ParseError(_(b"%r is not iterable") % self._value)
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   192
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   193
    def itermaps(self, context):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   194
        raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   195
            _(b'%r is not iterable of mappings') % self._value
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   196
        )
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   197
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   198
    def join(self, context, mapping, sep):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   199
        raise error.ParseError(_(b'%r is not iterable') % self._value)
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   200
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   201
    def show(self, context, mapping):
38272
354fad8697fd templater: fix string representation of wrapped None
Yuya Nishihara <yuya@tcha.org>
parents: 38271
diff changeset
   202
        if self._value is None:
354fad8697fd templater: fix string representation of wrapped None
Yuya Nishihara <yuya@tcha.org>
parents: 38271
diff changeset
   203
            return b''
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   204
        return pycompat.bytestr(self._value)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   205
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   206
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   207
        if self._value is None:
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   208
            return False
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   209
        if isinstance(self._value, bool):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   210
            return self._value
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   211
        # otherwise evaluate as string, which means 0 is True
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   212
        return bool(pycompat.bytestr(self._value))
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   213
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   214
    def tovalue(self, context, mapping):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   215
        return self._value
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   216
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   217
38286
851fc9d42d6d templater: make date wrapper support dot/map operations
Yuya Nishihara <yuya@tcha.org>
parents: 38285
diff changeset
   218
class date(mappable, wrapped):
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   219
    """Wrapper for date tuple"""
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   220
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   221
    def __init__(self, value, showfmt=b'%d %d'):
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   222
        # value may be (float, int), but public interface shouldn't support
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   223
        # floating-point timestamp
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   224
        self._unixtime, self._tzoffset = map(int, value)
38299
88e7105b5cd9 templater: restore the original string format of {date}
Yuya Nishihara <yuya@tcha.org>
parents: 38289
diff changeset
   225
        self._showfmt = showfmt
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   226
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   227
    def contains(self, context, mapping, item):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   228
        raise error.ParseError(_(b'date is not iterable'))
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   229
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   230
    def getmember(self, context, mapping, key):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   231
        raise error.ParseError(_(b'date is not a dictionary'))
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   232
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   233
    def getmin(self, context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   234
        raise error.ParseError(_(b'date is not iterable'))
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   235
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   236
    def getmax(self, context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   237
        raise error.ParseError(_(b'date is not iterable'))
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   238
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   239
    def filter(self, context, mapping, select):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   240
        raise error.ParseError(_(b'date is not iterable'))
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   241
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   242
    def join(self, context, mapping, sep):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   243
        raise error.ParseError(_(b"date is not iterable"))
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   244
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   245
    def show(self, context, mapping):
38299
88e7105b5cd9 templater: restore the original string format of {date}
Yuya Nishihara <yuya@tcha.org>
parents: 38289
diff changeset
   246
        return self._showfmt % (self._unixtime, self._tzoffset)
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   247
38286
851fc9d42d6d templater: make date wrapper support dot/map operations
Yuya Nishihara <yuya@tcha.org>
parents: 38285
diff changeset
   248
    def tomap(self, context):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   249
        return {b'unixtime': self._unixtime, b'tzoffset': self._tzoffset}
38286
851fc9d42d6d templater: make date wrapper support dot/map operations
Yuya Nishihara <yuya@tcha.org>
parents: 38285
diff changeset
   250
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   251
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   252
        return True
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   253
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   254
    def tovalue(self, context, mapping):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   255
        return (self._unixtime, self._tzoffset)
37227
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
   256
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   257
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   258
class hybrid(wrapped):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   259
    """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: 36920
diff changeset
   260
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   261
    This class allows us to handle both:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   262
    - "{files}" (legacy command-line-specific list hack) and
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   263
    - "{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: 36920
diff changeset
   264
    and to access raw values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   265
    - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   266
    - "{get(extras, key)}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   267
    - "{files|json}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   268
    """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   269
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   270
    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
   271
        self._gen = gen  # generator or function returning generator
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   272
        self._values = values
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   273
        self._makemap = makemap
37329
676664592313 templater: mark .joinfmt as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37327
diff changeset
   274
        self._joinfmt = joinfmt
38268
49ef1539b84e templater: mark .keytype as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 38267
diff changeset
   275
        self._keytype = keytype  # hint for 'x in y' where type(x) is unresolved
37275
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37273
diff changeset
   276
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   277
    def contains(self, context, mapping, item):
38268
49ef1539b84e templater: mark .keytype as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 38267
diff changeset
   278
        item = unwrapastype(context, mapping, item, self._keytype)
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   279
        return item in self._values
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   280
38242
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   281
    def getmember(self, context, mapping, key):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   282
        # TODO: maybe split hybrid list/dict types?
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50620
diff changeset
   283
        if not hasattr(self._values, 'get'):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   284
            raise error.ParseError(_(b'not a dictionary'))
38268
49ef1539b84e templater: mark .keytype as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 38267
diff changeset
   285
        key = unwrapastype(context, mapping, key, self._keytype)
38242
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   286
        return self._wrapvalue(key, self._values.get(key))
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   287
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   288
    def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   289
        return self._getby(context, mapping, min)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   290
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   291
    def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   292
        return self._getby(context, mapping, max)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   293
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   294
    def _getby(self, context, mapping, func):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   295
        if not self._values:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   296
            raise error.ParseError(_(b'empty sequence'))
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   297
        val = func(self._values)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   298
        return self._wrapvalue(val, val)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   299
38242
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   300
    def _wrapvalue(self, key, val):
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   301
        if val is None:
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   302
            return
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50620
diff changeset
   303
        if hasattr(val, '_makemap'):
38266
80f423a14c90 templater: inline wraphybridvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38265
diff changeset
   304
            # a nested hybrid list/dict, which has its own way of map operation
80f423a14c90 templater: inline wraphybridvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38265
diff changeset
   305
            return val
38283
0e0d03d09ecd templater: rename mappable to hybriditem as it is the primary use case
Yuya Nishihara <yuya@tcha.org>
parents: 38272
diff changeset
   306
        return hybriditem(None, key, val, self._makemap)
38242
12b6ee9e88f3 templater: move getdictitem() to hybrid class
Yuya Nishihara <yuya@tcha.org>
parents: 38241
diff changeset
   307
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   308
    def filter(self, context, mapping, select):
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50620
diff changeset
   309
        if hasattr(self._values, 'get'):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   310
            values = {
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   311
                k: v
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   312
                for k, v in self._values.items()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   313
                if select(self._wrapvalue(k, v))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   314
            }
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   315
        else:
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   316
            values = [v for v in self._values if select(self._wrapvalue(v, v))]
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   317
        return hybrid(None, values, self._makemap, self._joinfmt, self._keytype)
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   318
37324
c2f74b8f6b7f templater: pass context to itermaps() for future extension
Yuya Nishihara <yuya@tcha.org>
parents: 37323
diff changeset
   319
    def itermaps(self, context):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   320
        makemap = self._makemap
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   321
        for x in self._values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   322
            yield makemap(x)
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   323
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   324
    def join(self, context, mapping, sep):
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   325
        # 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
   326
        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
   327
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   328
    def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   329
        # TODO: switch gen to (context, mapping) API?
37275
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37273
diff changeset
   330
        gen = self._gen
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
   331
        if gen is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   332
            return self.join(context, mapping, b' ')
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   333
        if callable(gen):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   334
            return gen()
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   335
        return gen
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   336
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   337
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   338
        return bool(self._values)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   339
37279
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   340
    def tovalue(self, context, mapping):
38269
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38268
diff changeset
   341
        # TODO: make it non-recursive for trivial lists/dicts
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38268
diff changeset
   342
        xs = self._values
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50620
diff changeset
   343
        if hasattr(xs, 'get'):
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   344
            return {k: unwrapvalue(context, mapping, v) for k, v in xs.items()}
38269
cf8d210dfac4 templater: drop hybrid-ness on unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38268
diff changeset
   345
        return [unwrapvalue(context, mapping, x) for x in xs]
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   346
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   347
38284
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   348
class hybriditem(mappable, wrapped):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   349
    """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: 36920
diff changeset
   350
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   351
    This class allows us to handle both:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   352
    - "{manifest}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   353
    - "{manifest % '{rev}:{node}'}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   354
    - "{manifest.rev}"
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   355
    """
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   356
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   357
    def __init__(self, gen, key, value, makemap):
37276
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
   358
        self._gen = gen  # generator or function returning generator
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   359
        self._key = key
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   360
        self._value = value  # may be generator of strings
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   361
        self._makemap = makemap
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   362
38284
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
   363
    def tomap(self, context):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   364
        return self._makemap(self._key)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   365
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   366
    def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   367
        w = makewrapped(context, mapping, self._value)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   368
        return w.contains(context, mapping, item)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   369
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   370
    def getmember(self, context, mapping, key):
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   371
        w = makewrapped(context, mapping, self._value)
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   372
        return w.getmember(context, mapping, key)
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   373
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   374
    def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   375
        w = makewrapped(context, mapping, self._value)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   376
        return w.getmin(context, mapping)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   377
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   378
    def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   379
        w = makewrapped(context, mapping, self._value)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   380
        return w.getmax(context, mapping)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   381
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   382
    def filter(self, context, mapping, select):
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   383
        w = makewrapped(context, mapping, self._value)
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   384
        return w.filter(context, mapping, select)
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   385
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   386
    def join(self, context, mapping, sep):
38228
8bded7eae26c templater: consistently join() string-like object per character (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38226
diff changeset
   387
        w = makewrapped(context, mapping, self._value)
8bded7eae26c templater: consistently join() string-like object per character (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38226
diff changeset
   388
        return w.join(context, mapping, sep)
37327
ebf139cbd4a1 templater: abstract away from joinfmt
Yuya Nishihara <yuya@tcha.org>
parents: 37326
diff changeset
   389
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   390
    def show(self, context, mapping):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   391
        # TODO: switch gen to (context, mapping) API?
37275
8c84dc8264dc templater: mark .gen as a private attribute
Yuya Nishihara <yuya@tcha.org>
parents: 37273
diff changeset
   392
        gen = self._gen
37276
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
   393
        if gen is None:
b4630e332a99 templater: drop unneeded generator from mappable object
Yuya Nishihara <yuya@tcha.org>
parents: 37275
diff changeset
   394
            return pycompat.bytestr(self._value)
37273
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   395
        if callable(gen):
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   396
            return gen()
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   397
        return gen
83e1bbd48991 templater: define interface for objects requiring unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   398
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   399
    def tobool(self, context, mapping):
38447
b6294c113794 templater: fix truth testing of integer 0 taken from a list/dict
Yuya Nishihara <yuya@tcha.org>
parents: 38299
diff changeset
   400
        w = makewrapped(context, mapping, self._value)
b6294c113794 templater: fix truth testing of integer 0 taken from a list/dict
Yuya Nishihara <yuya@tcha.org>
parents: 38299
diff changeset
   401
        return w.tobool(context, mapping)
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   402
37279
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   403
    def tovalue(self, context, mapping):
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   404
        return _unthunk(context, mapping, self._value)
26f6fc179e62 templater: define interface for objects requiring unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37278
diff changeset
   405
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   406
44589
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   407
class revslist(wrapped):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   408
    """Wrapper for a smartset (a list/set of revision numbers)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   409
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   410
    If name specified, the revs will be rendered with the old-style list
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   411
    template of the given name by default.
44591
1f81f680912f templater: remember cache key of evaluated revset
Yuya Nishihara <yuya@tcha.org>
parents: 44590
diff changeset
   412
1f81f680912f templater: remember cache key of evaluated revset
Yuya Nishihara <yuya@tcha.org>
parents: 44590
diff changeset
   413
    The cachekey provides a hint to cache further computation on this
1f81f680912f templater: remember cache key of evaluated revset
Yuya Nishihara <yuya@tcha.org>
parents: 44590
diff changeset
   414
    smartset. If the underlying smartset is dynamically created, the cachekey
1f81f680912f templater: remember cache key of evaluated revset
Yuya Nishihara <yuya@tcha.org>
parents: 44590
diff changeset
   415
    should be None.
44589
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   416
    """
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   417
44591
1f81f680912f templater: remember cache key of evaluated revset
Yuya Nishihara <yuya@tcha.org>
parents: 44590
diff changeset
   418
    def __init__(self, repo, revs, name=None, cachekey=None):
44589
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   419
        assert isinstance(revs, smartset.abstractsmartset)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   420
        self._repo = repo
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   421
        self._revs = revs
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   422
        self._name = name
44591
1f81f680912f templater: remember cache key of evaluated revset
Yuya Nishihara <yuya@tcha.org>
parents: 44590
diff changeset
   423
        self.cachekey = cachekey
44589
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   424
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   425
    def contains(self, context, mapping, item):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   426
        rev = unwrapinteger(context, mapping, item)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   427
        return rev in self._revs
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   428
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   429
    def getmember(self, context, mapping, key):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   430
        raise error.ParseError(_(b'not a dictionary'))
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   431
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   432
    def getmin(self, context, mapping):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   433
        makehybriditem = self._makehybriditemfunc()
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   434
        return makehybriditem(self._revs.min())
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   435
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   436
    def getmax(self, context, mapping):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   437
        makehybriditem = self._makehybriditemfunc()
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   438
        return makehybriditem(self._revs.max())
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   439
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   440
    def filter(self, context, mapping, select):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   441
        makehybriditem = self._makehybriditemfunc()
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   442
        frevs = self._revs.filter(lambda r: select(makehybriditem(r)))
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   443
        # once filtered, no need to support old-style list template
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   444
        return revslist(self._repo, frevs, name=None)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   445
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   446
    def itermaps(self, context):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   447
        makemap = self._makemapfunc()
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   448
        for r in self._revs:
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   449
            yield makemap(r)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   450
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   451
    def _makehybriditemfunc(self):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   452
        makemap = self._makemapfunc()
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   453
        return lambda r: hybriditem(None, r, r, makemap)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   454
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   455
    def _makemapfunc(self):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   456
        repo = self._repo
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   457
        name = self._name
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   458
        if name:
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   459
            return lambda r: {name: r, b'ctx': repo[r]}
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   460
        else:
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   461
            return lambda r: {b'ctx': repo[r]}
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   462
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   463
    def join(self, context, mapping, sep):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   464
        return joinitems(self._revs, sep)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   465
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   466
    def show(self, context, mapping):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   467
        if self._name:
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   468
            srevs = [b'%d' % r for r in self._revs]
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   469
            return _showcompatlist(context, mapping, self._name, srevs)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   470
        else:
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   471
            return self.join(context, mapping, b' ')
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   472
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   473
    def tobool(self, context, mapping):
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   474
        return bool(self._revs)
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   475
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   476
    def tovalue(self, context, mapping):
44590
e3e44e6e7245 templater: fix cbor() filter to accept smartset
Yuya Nishihara <yuya@tcha.org>
parents: 44589
diff changeset
   477
        return self._revs
44589
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   478
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43474
diff changeset
   479
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   480
class _mappingsequence(wrapped):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   481
    """Wrapper for sequence of template mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   482
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   483
    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
   484
    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
   485
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   486
    Template mappings may be nested.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   487
    """
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   488
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   489
    def __init__(self, name=None, tmpl=None, sep=b''):
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   490
        if name is not None and tmpl is not None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   491
            raise error.ProgrammingError(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   492
                b'name and tmpl are mutually exclusive'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   493
            )
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   494
        self._name = name
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   495
        self._tmpl = tmpl
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   496
        self._defaultsep = sep
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   497
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   498
    def contains(self, context, mapping, item):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   499
        raise error.ParseError(_(b'not comparable'))
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   500
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   501
    def getmember(self, context, mapping, key):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   502
        raise error.ParseError(_(b'not a dictionary'))
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   503
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   504
    def getmin(self, context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   505
        raise error.ParseError(_(b'not comparable'))
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   506
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   507
    def getmax(self, context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   508
        raise error.ParseError(_(b'not comparable'))
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   509
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   510
    def filter(self, context, mapping, select):
38449
bc8d925342f0 templater: extend filter() to accept template expression for emptiness test
Yuya Nishihara <yuya@tcha.org>
parents: 38448
diff changeset
   511
        # implement if necessary; we'll need a wrapped type for a mapping dict
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   512
        raise error.ParseError(_(b'not filterable without template'))
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   513
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   514
    def join(self, context, mapping, sep):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   515
        mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context))
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   516
        if self._name:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   517
            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
   518
        elif self._tmpl:
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   519
            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
   520
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   521
            raise error.ParseError(_(b'not displayable without template'))
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   522
        return joinitems(itemiter, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   523
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   524
    def show(self, context, mapping):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   525
        return self.join(context, mapping, self._defaultsep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   526
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   527
    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
   528
        knownres = context.knownresourcekeys()
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   529
        items = []
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   530
        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
   531
            # 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
   532
            lm = context.overlaymap(mapping, nm)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   533
            items.append(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   534
                {
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   535
                    k: unwrapvalue(context, lm, v)
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   536
                    for k, v in nm.items()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   537
                    if k not in knownres
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   538
                }
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   539
            )
37502
40c7347f6848 formatter: remove template resources from nested items before generating JSON
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   540
        return items
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   541
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   542
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   543
class mappinggenerator(_mappingsequence):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   544
    """Wrapper for generator of template mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   545
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   546
    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
   547
    mapping dicts.
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   548
    """
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   549
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   550
    def __init__(self, make, args=(), name=None, tmpl=None, sep=b''):
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   551
        super(mappinggenerator, self).__init__(name, tmpl, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   552
        self._make = make
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   553
        self._args = args
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   554
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   555
    def itermaps(self, context):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   556
        return self._make(context, *self._args)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   557
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   558
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   559
        return _nonempty(self.itermaps(context))
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   560
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   561
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   562
class mappinglist(_mappingsequence):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   563
    """Wrapper for list of template mappings"""
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   564
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   565
    def __init__(self, mappings, name=None, tmpl=None, sep=b''):
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   566
        super(mappinglist, self).__init__(name, tmpl, sep)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   567
        self._mappings = mappings
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   568
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   569
    def itermaps(self, context):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   570
        return iter(self._mappings)
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
   571
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   572
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   573
        return bool(self._mappings)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   574
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   575
40475
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   576
class mappingdict(mappable, _mappingsequence):
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   577
    """Wrapper for a single template mapping
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   578
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   579
    This isn't a sequence in a way that the underlying dict won't be iterated
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   580
    as a dict, but shares most of the _mappingsequence functions.
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   581
    """
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   582
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   583
    def __init__(self, mapping, name=None, tmpl=None):
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   584
        super(mappingdict, self).__init__(name, tmpl)
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   585
        self._mapping = mapping
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   586
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   587
    def tomap(self, context):
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   588
        return self._mapping
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   589
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   590
    def tobool(self, context, mapping):
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   591
        # no idea when a template mapping should be considered an empty, but
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   592
        # a mapping dict should have at least one item in practice, so always
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   593
        # mark this as non-empty.
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   594
        return True
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   595
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   596
    def tovalue(self, context, mapping):
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   597
        return super(mappingdict, self).tovalue(context, mapping)[0]
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
   598
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   599
40935
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   600
class mappingnone(wrappedvalue):
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   601
    """Wrapper for None, but supports map operation
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   602
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   603
    This represents None of Optional[mappable]. It's similar to
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   604
    mapplinglist([]), but the underlying value is not [], but None.
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   605
    """
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   606
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   607
    def __init__(self):
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   608
        super(mappingnone, self).__init__(None)
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   609
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   610
    def itermaps(self, context):
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   611
        return iter([])
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   612
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   613
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   614
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
   615
    """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
   616
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   617
    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
   618
    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
   619
    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
   620
    """
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   621
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   622
    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
   623
        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
   624
        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
   625
38267
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   626
    def contains(self, context, mapping, item):
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   627
        item = stringify(context, mapping, item)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   628
        return item in self.tovalue(context, mapping)
fb874fc1d9b4 templater: abstract ifcontains() over wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38266
diff changeset
   629
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   630
    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
   631
        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
   632
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   633
    def getmember(self, context, mapping, key):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   634
        raise error.ParseError(_(b'not a dictionary'))
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
   635
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   636
    def getmin(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   637
        return self._getby(context, mapping, min)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   638
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   639
    def getmax(self, context, mapping):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   640
        return self._getby(context, mapping, max)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   641
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   642
    def _getby(self, context, mapping, func):
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   643
        xs = self.tovalue(context, mapping)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   644
        if not xs:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   645
            raise error.ParseError(_(b'empty sequence'))
38265
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   646
        return func(xs)
41ae9b3cbfb9 templater: abstract min/max away
Yuya Nishihara <yuya@tcha.org>
parents: 38244
diff changeset
   647
38448
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   648
    @staticmethod
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   649
    def _filteredgen(context, mapping, make, args, select):
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   650
        for x in make(context, *args):
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   651
            s = stringify(context, mapping, x)
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   652
            if select(wrappedbytes(s)):
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   653
                yield s
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   654
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   655
    def filter(self, context, mapping, select):
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   656
        args = (mapping, self._make, self._args, select)
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   657
        return mappedgenerator(self._filteredgen, args)
dae829b4de78 templater: introduce filter() function to remove empty items from list
Yuya Nishihara <yuya@tcha.org>
parents: 38447
diff changeset
   658
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   659
    def itermaps(self, context):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   660
        raise error.ParseError(_(b'list of strings is not mappable'))
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   661
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   662
    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
   663
        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
   664
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   665
    def show(self, context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   666
        return self.join(context, mapping, b'')
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   667
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   668
    def tobool(self, context, mapping):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   669
        return _nonempty(self._gen(context))
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   670
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
   671
    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
   672
        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
   673
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   674
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   675
def hybriddict(data, key=b'key', value=b'value', fmt=None, gen=None):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   676
    """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: 36920
diff changeset
   677
    prefmt = pycompat.identity
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   678
    if fmt is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   679
        fmt = b'%s=%s'
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   680
        prefmt = pycompat.bytestr
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   681
    return hybrid(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   682
        gen,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   683
        data,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   684
        lambda k: {key: k, value: data[k]},
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   685
        lambda k: fmt % (prefmt(k), prefmt(data[k])),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   686
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   687
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   688
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   689
def hybridlist(data, name, fmt=None, gen=None):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   690
    """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: 36920
diff changeset
   691
    prefmt = pycompat.identity
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   692
    if fmt is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   693
        fmt = b'%s'
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   694
        prefmt = pycompat.bytestr
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   695
    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: 36920
diff changeset
   696
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   697
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   698
def compatdict(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   699
    context,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   700
    mapping,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   701
    name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   702
    data,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   703
    key=b'key',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   704
    value=b'value',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   705
    fmt=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   706
    plural=None,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   707
    separator=b' ',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   708
):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   709
    """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: 36920
diff changeset
   710
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   711
    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: 36920
diff changeset
   712
    hybriddict() for new template keywords.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   713
    """
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   714
    c = [{key: k, value: v} for k, v in data.items()]
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   715
    f = _showcompatlist(context, mapping, name, c, plural, separator)
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   716
    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: 36920
diff changeset
   717
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   718
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   719
def compatlist(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   720
    context,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   721
    mapping,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   722
    name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   723
    data,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   724
    element=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   725
    fmt=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   726
    plural=None,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   727
    separator=b' ',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   728
):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   729
    """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: 36920
diff changeset
   730
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   731
    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: 36920
diff changeset
   732
    hybridlist() for new template keywords.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   733
    """
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   734
    f = _showcompatlist(context, mapping, name, data, plural, separator)
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   735
    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: 36920
diff changeset
   736
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   737
39368
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   738
def compatfilecopiesdict(context, mapping, name, copies):
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   739
    """Wrap list of (dest, source) file names to support old-style list
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   740
    template and field names
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   741
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   742
    This exists for backward compatibility. Use hybriddict for new template
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   743
    keywords.
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   744
    """
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   745
    # no need to provide {path} to old-style list template
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   746
    c = [{b'name': k, b'source': v} for k, v in copies]
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   747
    f = _showcompatlist(context, mapping, name, c, plural=b'file_copies')
39368
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   748
    copies = util.sortdict(copies)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   749
    return hybrid(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   750
        f,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   751
        copies,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   752
        lambda k: {b'name': k, b'path': k, b'source': copies[k]},
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   753
        lambda k: b'%s (%s)' % (k, copies[k]),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   754
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   755
39368
5b1d406b39f1 templatekw: alias {name} of file copies dict to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 39367
diff changeset
   756
39367
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   757
def compatfileslist(context, mapping, name, files):
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   758
    """Wrap list of file names to support old-style list template and field
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   759
    names
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   760
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   761
    This exists for backward compatibility. Use hybridlist for new template
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   762
    keywords.
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   763
    """
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   764
    f = _showcompatlist(context, mapping, name, files)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   765
    return hybrid(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   766
        f, files, lambda x: {b'file': x, b'path': x}, pycompat.identity
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   767
    )
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   768
39367
83f8f7b9fa60 templatekw: alias {file} of files list to {path}
Yuya Nishihara <yuya@tcha.org>
parents: 38930
diff changeset
   769
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   770
def _showcompatlist(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   771
    context, mapping, name, values, plural=None, separator=b' '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   772
):
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   773
    """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: 37019
diff changeset
   774
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   775
    name is name of key in template map.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   776
    values is list of strings or dicts.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   777
    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: 36920
diff changeset
   778
    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: 36920
diff changeset
   779
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   780
    expansion works like this, given name 'foo'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   781
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   782
    if values is empty, expand 'no_foos'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   783
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   784
    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: 36920
diff changeset
   785
    joined by 'separator'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   786
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   787
    expand 'start_foos'.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   788
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   789
    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: 36920
diff changeset
   790
    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: 36920
diff changeset
   791
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   792
    expand 'end_foos'.
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   793
    """
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   794
    if not plural:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   795
        plural = name + b's'
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   796
    if not values:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   797
        noname = b'no_' + plural
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   798
        if context.preload(noname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   799
            yield context.process(noname, mapping)
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   800
        return
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   801
    if not context.preload(name):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   802
        if isinstance(values[0], bytes):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   803
            yield separator.join(values)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   804
        else:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   805
            for v in values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   806
                r = dict(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   807
                r.update(mapping)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   808
                yield r
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   809
        return
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   810
    startname = b'start_' + plural
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   811
    if context.preload(startname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   812
        yield context.process(startname, mapping)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   813
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   814
    def one(v, tag=name):
37074
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   815
        vmapping = {}
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   816
        try:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   817
            vmapping.update(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   818
        # 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: 36920
diff changeset
   819
        # 3 raises TypeError.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   820
        except (AttributeError, TypeError, ValueError):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   821
            try:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   822
                # 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: 36920
diff changeset
   823
                # bytes. Python 3 raises TypeError.
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   824
                for a, b in v:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   825
                    vmapping[a] = b
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   826
            except (TypeError, ValueError):
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   827
                vmapping[name] = v
37074
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   828
        vmapping = context.overlaymap(mapping, vmapping)
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   829
        return context.process(tag, vmapping)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   830
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   831
    lastname = b'last_' + name
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   832
    if context.preload(lastname):
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   833
        last = values.pop()
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   834
    else:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   835
        last = None
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   836
    for v in values:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   837
        yield one(v)
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   838
    if last is not None:
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   839
        yield one(last, tag=lastname)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   840
    endname = b'end_' + plural
37068
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   841
    if context.preload(endname):
aa97e06a1912 templater: use template context to render old-style list template
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   842
        yield context.process(endname, mapping)
36921
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36920
diff changeset
   843
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   844
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   845
def flatten(context, mapping, thing):
37157
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   846
    """Yield a single stream from a possibly nested set of iterators"""
38270
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38269
diff changeset
   847
    if isinstance(thing, wrapped):
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38269
diff changeset
   848
        thing = thing.show(context, mapping)
37157
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   849
    if isinstance(thing, bytes):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   850
        yield thing
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   851
    elif isinstance(thing, str):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   852
        # 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: 37104
diff changeset
   853
        # against infinite recursion.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   854
        raise error.ProgrammingError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   855
            b'Mercurial IO including templates is done'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   856
            b' with bytes, not strings, got %r' % thing
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   857
        )
37157
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   858
    elif thing is None:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   859
        pass
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50620
diff changeset
   860
    elif not hasattr(thing, '__iter__'):
37157
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   861
        yield pycompat.bytestr(thing)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   862
    else:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   863
        for i in thing:
38270
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38269
diff changeset
   864
            if isinstance(i, wrapped):
630c62804383 templater: inline unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 38269
diff changeset
   865
                i = i.show(context, mapping)
37157
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   866
            if isinstance(i, bytes):
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   867
                yield i
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   868
            elif i is None:
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   869
                pass
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50620
diff changeset
   870
            elif not hasattr(i, '__iter__'):
37157
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   871
                yield pycompat.bytestr(i)
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   872
            else:
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   873
                for j in flatten(context, mapping, i):
37157
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   874
                    yield j
888507ec655e templateutil: move flatten() from templater
Yuya Nishihara <yuya@tcha.org>
parents: 37104
diff changeset
   875
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   876
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   877
def stringify(context, mapping, thing):
36920
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36913
diff changeset
   878
    """Turn values into bytes by converting into text and concatenating them"""
37158
e09d2183e226 templateutil: reimplement stringify() using flatten()
Yuya Nishihara <yuya@tcha.org>
parents: 37157
diff changeset
   879
    if isinstance(thing, bytes):
e09d2183e226 templateutil: reimplement stringify() using flatten()
Yuya Nishihara <yuya@tcha.org>
parents: 37157
diff changeset
   880
        return thing  # retain localstr to be round-tripped
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   881
    return b''.join(flatten(context, mapping, thing))
36920
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36913
diff changeset
   882
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   883
31927
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   884
def findsymbolicname(arg):
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   885
    """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
   886
    if nothing found reliably"""
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   887
    while True:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   888
        func, data = arg
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   889
        if func is runsymbol:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   890
            return data
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   891
        elif func is runfilter:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   892
            arg = data[0]
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   893
        else:
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   894
            return None
2abc556dbe92 templater: find keyword name more thoroughly on filtering error
Yuya Nishihara <yuya@tcha.org>
parents: 31926
diff changeset
   895
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   896
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   897
def _nonempty(xiter):
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   898
    try:
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   899
        next(xiter)
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   900
        return True
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   901
    except StopIteration:
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   902
        return False
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   903
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   904
37278
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   905
def _unthunk(context, mapping, thing):
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   906
    """Evaluate a lazy byte string into value"""
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   907
    if not isinstance(thing, types.GeneratorType):
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   908
        return thing
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   909
    return stringify(context, mapping, thing)
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   910
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   911
34326
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
   912
def evalrawexp(context, mapping, arg):
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
   913
    """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: 34325
diff changeset
   914
    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
   915
    func, data = arg
34326
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
   916
    return func(context, mapping, data)
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
   917
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   918
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   919
def evalwrapped(context, mapping, arg):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   920
    """Evaluate given argument to wrapped object"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   921
    thing = evalrawexp(context, mapping, arg)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   922
    return makewrapped(context, mapping, thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   923
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   924
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   925
def makewrapped(context, mapping, thing):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   926
    """Lift object to a wrapped type"""
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   927
    if isinstance(thing, wrapped):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   928
        return thing
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   929
    thing = _unthunk(context, mapping, thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   930
    if isinstance(thing, bytes):
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   931
        return wrappedbytes(thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   932
    return wrappedvalue(thing)
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
   933
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   934
34326
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
   935
def evalfuncarg(context, mapping, arg):
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
   936
    """Evaluate given argument as value type"""
38225
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38224
diff changeset
   937
    return unwrapvalue(context, mapping, evalrawexp(context, mapping, arg))
37161
0023da2910c9 templater: extract type conversion from evalfuncarg()
Yuya Nishihara <yuya@tcha.org>
parents: 37160
diff changeset
   938
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   939
38225
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38224
diff changeset
   940
def unwrapvalue(context, mapping, thing):
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38224
diff changeset
   941
    """Move the inner value object out of the wrapper"""
38224
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
   942
    if isinstance(thing, wrapped):
61cecab0cc20 templater: inline unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 37502
diff changeset
   943
        return thing.tovalue(context, mapping)
34326
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
   944
    # 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: 34325
diff changeset
   945
    # such as date tuple, but filter does not want generator.
37278
671a01cd50b5 templater: extract private function to evaluate generator to byte string
Yuya Nishihara <yuya@tcha.org>
parents: 37277
diff changeset
   946
    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
   947
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   948
29816
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   949
def evalboolean(context, mapping, arg):
29817
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   950
    """Evaluate given argument as boolean, but also takes boolean literals"""
29816
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   951
    func, data = arg
29817
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   952
    if func is runsymbol:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   953
        thing = func(context, mapping, data, default=None)
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   954
        if thing is None:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   955
            # not a template keyword, takes as a boolean literal
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   956
            thing = stringutil.parsebool(data)
29817
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   957
    else:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   958
        thing = func(context, mapping, data)
38289
f9c426385853 templater: abstract truth testing to fix {if(list_of_empty_strings)}
Yuya Nishihara <yuya@tcha.org>
parents: 38286
diff changeset
   959
    return makewrapped(context, mapping, thing).tobool(context, mapping)
29816
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   960
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   961
37224
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
   962
def evaldate(context, mapping, arg, err=None):
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
   963
    """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: 37222
diff changeset
   964
    a (unixtime, offset) tuple"""
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   965
    thing = evalrawexp(context, mapping, arg)
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   966
    return unwrapdate(context, mapping, thing, err)
37224
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
   967
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   968
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   969
def unwrapdate(context, mapping, thing, err=None):
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   970
    if isinstance(thing, date):
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   971
        return thing.tovalue(context, mapping)
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38284
diff changeset
   972
    # TODO: update hgweb to not return bare tuple; then just stringify 'thing'
38225
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38224
diff changeset
   973
    thing = unwrapvalue(context, mapping, thing)
37224
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
   974
    try:
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
   975
        return dateutil.parsedate(thing)
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
   976
    except AttributeError:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   977
        raise error.ParseError(err or _(b'not a date tuple nor a string'))
37225
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   978
    except error.ParseError:
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   979
        if not err:
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   980
            raise
e70a90a72b80 templatefuncs: use evaldate() where seems appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   981
        raise error.ParseError(err)
37224
67efce231633 templater: factor out function that parses argument as date tuple
Yuya Nishihara <yuya@tcha.org>
parents: 37222
diff changeset
   982
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   983
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
   984
def evalinteger(context, mapping, arg, err=None):
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   985
    thing = evalrawexp(context, mapping, arg)
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   986
    return unwrapinteger(context, mapping, thing, err)
37162
9ab3491f84c2 templater: extract unwrapinteger() function from evalinteger()
Yuya Nishihara <yuya@tcha.org>
parents: 37161
diff changeset
   987
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   988
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   989
def unwrapinteger(context, mapping, thing, err=None):
38225
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38224
diff changeset
   990
    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
   991
    try:
37162
9ab3491f84c2 templater: extract unwrapinteger() function from evalinteger()
Yuya Nishihara <yuya@tcha.org>
parents: 37161
diff changeset
   992
        return int(thing)
28344
ac371d4c007f templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents: 28343
diff changeset
   993
    except (TypeError, ValueError):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   994
        raise error.ParseError(err or _(b'not an integer'))
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   995
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
   996
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   997
def evalstring(context, mapping, arg):
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   998
    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
   999
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1000
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
  1001
def evalstringliteral(context, mapping, arg):
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
  1002
    """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
  1003
    if it is unknown"""
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
  1004
    func, data = arg
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
  1005
    if func is runsymbol:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
  1006
        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
  1007
    else:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
  1008
        thing = func(context, mapping, data)
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
  1009
    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
  1010
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1011
37163
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37162
diff changeset
  1012
_unwrapfuncbytype = {
38225
d48b80d58848 templater: unify unwrapvalue() with _unwrapvalue()
Yuya Nishihara <yuya@tcha.org>
parents: 38224
diff changeset
  1013
    None: unwrapvalue,
37163
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37162
diff changeset
  1014
    bytes: stringify,
37227
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37226
diff changeset
  1015
    date: unwrapdate,
37163
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37162
diff changeset
  1016
    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
  1017
}
ee0d74083a22 templater: store revisions as ints so min/max won't compare them as strings
Yuya Nishihara <yuya@tcha.org>
parents: 34536
diff changeset
  1018
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1019
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
  1020
def unwrapastype(context, mapping, thing, typ):
37163
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37162
diff changeset
  1021
    """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
  1022
    try:
37163
0fb28899e81a templater: factor out unwrapastype() from evalastype()
Yuya Nishihara <yuya@tcha.org>
parents: 37162
diff changeset
  1023
        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
  1024
    except KeyError:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1025
        raise error.ProgrammingError(b'invalid type specified: %r' % typ)
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
  1026
    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
  1027
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1028
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
  1029
def runinteger(context, mapping, data):
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
  1030
    return int(data)
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
  1031
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1032
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1033
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
  1034
    return data
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1035
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1036
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
  1037
def _recursivesymbolblocker(key):
38930
382b055cc358 templatekw: deprecate old-style template keyword function (API)
Yuya Nishihara <yuya@tcha.org>
parents: 38449
diff changeset
  1038
    def showrecursion(context, mapping):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1039
        raise error.Abort(_(b"recursive reference '%s' in template") % key)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1040
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
  1041
    return showrecursion
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
  1042
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1043
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1044
def runsymbol(context, mapping, key, default=b''):
35467
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
  1045
    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
  1046
    if v is None:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
  1047
        # 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
  1048
        # 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
  1049
        safemapping = mapping.copy()
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
  1050
        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
  1051
        try:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
  1052
            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
  1053
        except TemplateNotFound:
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
  1054
            v = default
36445
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36444
diff changeset
  1055
    if callable(v):
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36444
diff changeset
  1056
        # new templatekw
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36444
diff changeset
  1057
        try:
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36444
diff changeset
  1058
            return v(context, mapping)
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36444
diff changeset
  1059
        except ResourceUnavailable:
e8d37838f5df templatekw: add 'requires' flag to switch to exception-safe interface
Yuya Nishihara <yuya@tcha.org>
parents: 36444
diff changeset
  1060
            # 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: 36444
diff changeset
  1061
            return None
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1062
    return v
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1063
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1064
25595
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
  1065
def runtemplate(context, mapping, template):
34326
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
  1066
    for arg in template:
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
  1067
        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
  1068
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1069
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1070
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
  1071
    arg, filt = data
37222
54355c243042 templatefilters: allow declaration of input data type
Yuya Nishihara <yuya@tcha.org>
parents: 37163
diff changeset
  1072
    thing = evalrawexp(context, mapping, arg)
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
  1073
    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
  1074
    try:
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
  1075
        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
  1076
        return filt(thing)
37226
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
  1077
    except error.ParseError as e:
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
  1078
        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: 37225
diff changeset
  1079
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1080
37226
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
  1081
def _formatfiltererror(arg, filt):
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
  1082
    fn = pycompat.sysbytes(filt.__name__)
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
  1083
    sym = findsymbolicname(arg)
920589f52be9 templater: attach hint to input-type error of runfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
  1084
    if not sym:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1085
        return _(b"incompatible use of template filter '%s'") % fn
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1086
    return _(b"template filter '%s' is not compatible with keyword '%s'") % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1087
        fn,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1088
        sym,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1089
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1090
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1091
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
  1092
def _iteroverlaymaps(context, origmapping, newmappings):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
  1093
    """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
  1094
    of partial mappings to override the original"""
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
  1095
    for i, nm in enumerate(newmappings):
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
  1096
        lm = context.overlaymap(origmapping, nm)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1097
        lm[b'index'] = i
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
  1098
        yield lm
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37329
diff changeset
  1099
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1100
38271
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1101
def _applymap(context, mapping, d, darg, targ):
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1102
    try:
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1103
        diter = d.itermaps(context)
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1104
    except error.ParseError as err:
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1105
        sym = findsymbolicname(darg)
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1106
        if not sym:
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1107
            raise
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1108
        hint = _(b"keyword '%s' does not support map operation") % sym
38271
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1109
        raise error.ParseError(bytes(err), hint=hint)
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1110
    for lm in _iteroverlaymaps(context, mapping, diter):
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37405
diff changeset
  1111
        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
  1112
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1113
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1114
def runmap(context, mapping, data):
34326
e60c601953d7 templater: extract helper to just evaluate template expression
Yuya Nishihara <yuya@tcha.org>
parents: 34325
diff changeset
  1115
    darg, targ = data
38229
7701c2d4a438 templater: always map over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38228
diff changeset
  1116
    d = evalwrapped(context, mapping, darg)
38271
4b0f39e7406e templater: show slightly better hint on map operation error
Yuya Nishihara <yuya@tcha.org>
parents: 38270
diff changeset
  1117
    return mappedgenerator(_applymap, args=(mapping, d, darg, targ))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1118
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1119
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
  1120
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
  1121
    darg, memb = data
38240
c2456a7726c1 templater: do dict lookup over a wrapped object
Yuya Nishihara <yuya@tcha.org>
parents: 38229
diff changeset
  1122
    d = evalwrapped(context, mapping, darg)
38284
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
  1123
    if isinstance(d, mappable):
e72697893c93 templater: promote tomap() to an interface type
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
  1124
        lm = context.overlaymap(mapping, d.tomap(context))
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
  1125
        return runsymbol(context, lm, memb)
38241
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38240
diff changeset
  1126
    try:
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
  1127
        return d.getmember(context, mapping, memb)
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
  1128
    except error.ParseError as err:
38241
ad06a4264daf templater: add try-except stub to runmember()
Yuya Nishihara <yuya@tcha.org>
parents: 38240
diff changeset
  1129
        sym = findsymbolicname(darg)
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
  1130
        if not sym:
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
  1131
            raise
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1132
        hint = _(b"keyword '%s' does not support member operation") % sym
38243
06d11cd90516 templater: promote getmember() to an interface of wrapped types
Yuya Nishihara <yuya@tcha.org>
parents: 38242
diff changeset
  1133
        raise error.ParseError(bytes(err), hint=hint)
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
  1134
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1135
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
  1136
def runnegate(context, mapping, data):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1137
    data = evalinteger(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1138
        context, mapping, data, _(b'negation needs an integer argument')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1139
    )
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
  1140
    return -data
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
  1141
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1142
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
  1143
def runarithmetic(context, mapping, data):
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
  1144
    func, left, right = data
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1145
    left = evalinteger(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1146
        context, mapping, left, _(b'arithmetic only defined on integers')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1147
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1148
    right = evalinteger(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1149
        context, mapping, right, _(b'arithmetic only defined on integers')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1150
    )
30116
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
  1151
    try:
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
  1152
        return func(left, right)
1c01fa29630f templater: handle division by zero in arithmetic
Simon Farnsworth <simonfar@fb.com>
parents: 30115
diff changeset
  1153
    except ZeroDivisionError:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1154
        raise error.Abort(_(b'division by zero is not defined'))
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
  1155
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42337
diff changeset
  1156
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
  1157
def joinitems(itemiter, sep):
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
  1158
    """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
  1159
    first = True
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
  1160
    for x in itemiter:
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
  1161
        if first:
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
  1162
            first = False
37326
9cd88dd3bf64 templater: micro-optimize join() with empty separator
Yuya Nishihara <yuya@tcha.org>
parents: 37325
diff changeset
  1163
        elif sep:
37325
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
  1164
            yield sep
41a5d815d2c1 templater: factor out generator of join()-ed items
Yuya Nishihara <yuya@tcha.org>
parents: 37324
diff changeset
  1165
        yield x