##// END OF EJS Templates
copy-tracing: add a --compute flag to debugchangedfiles...
copy-tracing: add a --compute flag to debugchangedfiles This will help analysis of possible misbehaving cases. Differential Revision: https://phab.mercurial-scm.org/D9946

File last commit:

r46729:59fa3890 default
r47208:c2435280 default
Show More
templatefilters.py
557 lines | 15.1 KiB | text/x-python | PythonLexer
Yuya Nishihara
templatefilers: correct filename in header comment
r32740 # templatefilters.py - common template expansion filters
Matt Mackall
templates: move filters to their own module...
r5976 #
# Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
templates: move filters to their own module...
r5976
Gregory Szorc
templatefilters: use absolute_import
r25983 from __future__ import absolute_import
import os
import re
import time
Yuya Nishihara
templatefilters: handle TypeError by count()...
r37246 from .i18n import _
Joerg Sonnenberger
node: import symbols explicitly...
r46729 from .node import hex
Gregory Szorc
templatefilters: use absolute_import
r25983 from . import (
encoding,
Augie Fackler
templatefilters: defend against evil unicode strs in json filter...
r34838 error,
Pulkit Goyal
py3: alias long to int on Python 3
r32126 pycompat,
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 registrar,
Yuya Nishihara
templater: fix cbor() filter to accept smartset...
r45081 smartset,
Yuya Nishihara
templater: move stringify() to templateutil module...
r36938 templateutil,
Augie Fackler
python3: use our bytes-only version of cgi.escape everywhere...
r34696 url,
Gregory Szorc
templatefilters: use absolute_import
r25983 util,
)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
Yuya Nishihara
templatefilters: add {x|cbor} filter for custom CBOR output
r42164 cborutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 dateutil,
stringutil,
)
Matt Mackall
templates: move filters to their own module...
r5976
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 # filters are callables like:
# fn(obj)
# with:
# obj - object to be filtered (text, date, list and so on)
filters = {}
templatefilter = registrar.templatefilter(filters)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'addbreaks', intype=bytes)
Patrick Mezard
templatefilters: sort function definitions
r13588 def addbreaks(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Add an XHTML "<br />" tag before the end of
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 every line except the last.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return text.replace(b'\n', b'<br/>\n')
Dirkjan Ochtman
templater: provide the standard template filters by default
r8360
Augie Fackler
formatting: blacken the codebase...
r43346
agescales = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b"year", 3600 * 24 * 365, b'Y'),
(b"month", 3600 * 24 * 30, b'M'),
(b"week", 3600 * 24 * 7, b'W'),
(b"day", 3600 * 24, b'd'),
(b"hour", 3600, b'h'),
(b"minute", 60, b'm'),
(b"second", 1, b's'),
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Matt Mackall
templates: move filters to their own module...
r5976
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'age', intype=templateutil.date)
David Soria Parra
templatefilters: add short format for age formatting...
r19736 def age(date, abbrev=False):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a human-readable date/time difference between the
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 given date/time and the current date/time.
"""
Matt Mackall
templates: move filters to their own module...
r5976
def plural(t, c):
if c == 1:
return t
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return t + b"s"
Augie Fackler
formatting: blacken the codebase...
r43346
David Soria Parra
templatefilters: add short format for age formatting...
r19736 def fmt(t, c, a):
if abbrev:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"%d%s" % (c, a)
return b"%d %s" % (c, plural(t, c))
Matt Mackall
templates: move filters to their own module...
r5976
now = time.time()
then = date[0]
timeless
templates: provide granularity for future values for age filter
r13666 future = False
Dirkjan Ochtman
templater: fix age filter to state the obvious on future timestamps
r7682 if then > now:
timeless
templates: provide granularity for future values for age filter
r13666 future = True
delta = max(1, int(then - now))
if delta > agescales[0][1] * 30:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'in the distant future'
timeless
templates: provide granularity for future values for age filter
r13666 else:
delta = max(1, int(now - then))
if delta > agescales[0][1] * 2:
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 return dateutil.shortdate(date)
Dirkjan Ochtman
templater: readable dates older than 24 months revert to ISO8601 (issue1006)
r9722
David Soria Parra
templatefilters: add short format for age formatting...
r19736 for t, s, a in agescales:
Alejandro Santos
compat: use // for integer division
r9029 n = delta // s
Matt Mackall
templates: move filters to their own module...
r5976 if n >= 2 or s == 1:
timeless
templates: provide granularity for future values for age filter
r13666 if future:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'%s from now' % fmt(t, n, a)
return b'%s ago' % fmt(t, n, a)
Matt Mackall
templates: move filters to their own module...
r5976
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'basename', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def basename(path):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Treats the text as a path, and returns the last
Yuya Nishihara
templatefilters: fix doc of basename()...
r35577 component of the path after splitting by the path separator.
For example, "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "".
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return os.path.basename(path)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
templater: fix cbor() filter to recursively convert smartset to list...
r45087 def _tocborencodable(obj):
if isinstance(obj, smartset.abstractsmartset):
return list(obj)
return obj
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'cbor')
Yuya Nishihara
templatefilters: add {x|cbor} filter for custom CBOR output
r42164 def cbor(obj):
"""Any object. Serializes the object to CBOR bytes."""
Yuya Nishihara
templater: fix cbor() filter to recursively convert smartset to list...
r45087 # cborutil is stricter about type than json() filter
obj = pycompat.rapply(_tocborencodable, obj)
Yuya Nishihara
templatefilters: add {x|cbor} filter for custom CBOR output
r42164 return b''.join(cborutil.streamencode(obj))
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'commondir')
Martin von Zweigbergk
templatefilters: rename commonprefix to commondir...
r38323 def commondir(filelist):
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 """List of text. Treats each list item as file name with /
as path separator and returns the longest common directory
prefix shared by all list items.
Returns the empty string if no common prefix exists.
The list items are not normalized, i.e. "foo/../bar" is handled as
file "bar" in the directory "foo/..". Leading slashes are ignored.
For example, ["foo/bar/baz", "foo/baz/bar"] becomes "foo" and
["foo/bar", "baz"] becomes "".
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 def common(a, b):
if len(a) > len(b):
Augie Fackler
formatting: blacken the codebase...
r43346 a = b[: len(a)]
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 elif len(b) > len(a):
Augie Fackler
formatting: blacken the codebase...
r43346 b = b[: len(a)]
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 if a == b:
return a
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.xrange(len(a)):
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 if a[i] != b[i]:
return a[:i]
return a
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 try:
if not filelist:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b""
dirlist = [f.lstrip(b'/').split(b'/')[:-1] for f in filelist]
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 if len(dirlist) == 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'/'.join(dirlist[0])
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 a = min(dirlist)
b = max(dirlist)
# The common prefix of a and b is shared with all
# elements of the list since Python sorts lexicographical
# and [1, x] after [1].
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'/'.join(common(a, b))
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198 except TypeError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ParseError(_(b'argument is not a list of text'))
Joerg Sonnenberger
templatefilters: add commonprefix...
r38198
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'count')
Anton Shestakov
templater: add count template filter, plus tests...
r22668 def count(i):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """List or text. Returns the length as an integer."""
Yuya Nishihara
templatefilters: handle TypeError by count()...
r37246 try:
return len(i)
except TypeError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ParseError(_(b'not countable'))
Anton Shestakov
templater: add count template filter, plus tests...
r22668
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'dirname', intype=bytes)
Yuya Nishihara
templatefilters: add dirname() filter...
r36260 def dirname(path):
"""Any text. Treats the text as a path, and strips the last
component of the path after splitting by the path separator.
"""
return os.path.dirname(path)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'domain', intype=bytes)
Patrick Mezard
templatefilters: sort function definitions
r13588 def domain(author):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Finds the first string that looks like an email
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 address, and extracts just the domain component. Example: ``User
<user@example.com>`` becomes ``example.com``.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = author.find(b'@')
Patrick Mezard
templatefilters: sort function definitions
r13588 if f == -1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
Augie Fackler
formatting: blacken the codebase...
r43346 author = author[f + 1 :]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = author.find(b'>')
Patrick Mezard
templatefilters: sort function definitions
r13588 if f >= 0:
author = author[:f]
return author
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'email', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def email(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Extracts the first string that looks like an email
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 address. Example: ``User <user@example.com>`` becomes
``user@example.com``.
"""
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 return stringutil.email(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'escape', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def escape(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Replaces the special XML/XHTML characters "&", "<"
Siddharth Agarwal
hgweb: make the escape filter remove null characters (issue2567)
r17772 and ">" with XML entities, and filters out NUL characters.
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return url.escape(text.replace(b'\0', b''), True)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
templates: move filters to their own module...
r5976 para_re = None
space_re = None
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def fill(text, width, initindent=b'', hangindent=b''):
Sean Farley
templater: add indentation arguments to the fill function
r19228 '''fill many paragraphs with optional indentation.'''
Matt Mackall
templates: move filters to their own module...
r5976 global para_re, space_re
if para_re is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 para_re = re.compile(b'(\n\n|\n\\s*[-*]\\s*)', re.M)
Yuya Nishihara
py3: make regexp literal bytes in templatefilters.py...
r36516 space_re = re.compile(br' +')
Matt Mackall
templates: move filters to their own module...
r5976
def findparas():
start = 0
while True:
m = para_re.search(text, start)
if not m:
Yuya Nishihara
templatefilters: use encoding.unifromlocal/unitolocal() for py3 compatibility
r36515 uctext = encoding.unifromlocal(text[start:])
FUJIWARA Katsunori
replace Python standard textwrap by MBCS sensitive one for i18n text...
r11297 w = len(uctext)
Martin von Zweigbergk
cleanup: some Yoda conditions, this patch removes...
r40065 while w > 0 and uctext[w - 1].isspace():
Matt Mackall
many, many trivial check-code fixups
r10282 w -= 1
Augie Fackler
formatting: blacken the codebase...
r43346 yield (
encoding.unitolocal(uctext[:w]),
encoding.unitolocal(uctext[w:]),
)
Matt Mackall
templates: move filters to their own module...
r5976 break
Augie Fackler
formatting: blacken the codebase...
r43346 yield text[start : m.start(0)], m.group(1)
Matt Mackall
templates: move filters to their own module...
r5976 start = m.end(1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"".join(
Augie Fackler
formatting: blacken the codebase...
r43346 [
stringutil.wrap(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 space_re.sub(b' ', stringutil.wrap(para, width)),
Augie Fackler
formatting: blacken the codebase...
r43346 width,
initindent,
hangindent,
)
+ rest
for para, rest in findparas()
]
)
Matt Mackall
templates: move filters to their own module...
r5976
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'fill68', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def fill68(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Wraps the text to fit in 68 columns."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return fill(text, 68)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'fill76', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def fill76(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Wraps the text to fit in 76 columns."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return fill(text, 76)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'firstline', intype=bytes)
Matt Mackall
templates: move filters to their own module...
r5976 def firstline(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the first line of text."""
Matt Mackall
templates: move filters to their own module...
r5976 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return text.splitlines(True)[0].rstrip(b'\r\n')
Matt Mackall
templates: move filters to their own module...
r5976 except IndexError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
Matt Mackall
templates: move filters to their own module...
r5976
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'hex', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def hexfilter(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Convert a binary Mercurial node identifier into
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 its long hexadecimal representation.
"""
Joerg Sonnenberger
node: import symbols explicitly...
r46729 return hex(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'hgdate', intype=templateutil.date)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def hgdate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns the date as a pair of numbers: "1157407993
Yuya Nishihara
templatefilters: undeprecate hgdate...
r38319 25200" (Unix timestamp, timezone offset).
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"%d %d" % text
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'isodate', intype=templateutil.date)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def isodate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 +0200".
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return dateutil.datestr(text, b'%Y-%m-%d %H:%M %1%2')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'isodatesec', intype=templateutil.date)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def isodatesec(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns the date in ISO 8601 format, including
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
filter.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return dateutil.datestr(text, b'%Y-%m-%d %H:%M:%S %1%2')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
templates: make {indent("", " ")} be empty...
r44093 def indent(text, prefix, firstline=b''):
Matt Mackall
templates: move filters to their own module...
r5976 '''indent each non-empty line of text after first with prefix.'''
lines = text.splitlines()
num_lines = len(lines)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 endswithnewline = text[-1:] == b'\n'
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
templates: move filters to their own module...
r5976 def indenter():
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.xrange(num_lines):
Matt Mackall
templates: move filters to their own module...
r5976 l = lines[i]
Martin von Zweigbergk
templates: make {indent("", " ")} be empty...
r44093 if l.strip():
yield prefix if i else firstline
Matt Mackall
templates: move filters to their own module...
r5976 yield l
Nicolas Dumazet
templatefilters: indent: do not compute text.endswith('\n') in each iteration
r9387 if i < num_lines - 1 or endswithnewline:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'\n'
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"".join(indenter())
Matt Mackall
templates: move filters to their own module...
r5976
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'json')
Yuya Nishihara
formatter: use templatefilters.json()...
r31782 def json(obj, paranoid=True):
Yuya Nishihara
templatefilters: document the json filter...
r37967 """Any object. Serializes the object to a JSON formatted text."""
Yuya Nishihara
templatefilters: unroll handling of None/False/True...
r31780 if obj is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'null'
Yuya Nishihara
templatefilters: unroll handling of None/False/True...
r31780 elif obj is False:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'false'
Yuya Nishihara
templatefilters: unroll handling of None/False/True...
r31780 elif obj is True:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'true'
Yuya Nishihara
py3: leverage pycompat.long
r43641 elif isinstance(obj, (int, pycompat.long, float)):
Pulkit Goyal
py3: use pycompat.bytestr() instead of str()...
r32127 return pycompat.bytestr(obj)
Pulkit Goyal
py3: replace str with bytes in isinstance()
r32128 elif isinstance(obj, bytes):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'"%s"' % encoding.jsonescape(obj, paranoid=paranoid)
Martin von Zweigbergk
json: reject unicode on py2 as well...
r38044 elif isinstance(obj, type(u'')):
Augie Fackler
templatefilters: defend against evil unicode strs in json filter...
r34838 raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'Mercurial only does output with bytes: %r' % obj
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif util.safehasattr(obj, b'keys'):
Augie Fackler
formatting: blacken the codebase...
r43346 out = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'"%s": %s'
Augie Fackler
formatting: blacken the codebase...
r43346 % (encoding.jsonescape(k, paranoid=paranoid), json(v, paranoid))
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for k, v in sorted(pycompat.iteritems(obj))
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'{' + b', '.join(out) + b'}'
elif util.safehasattr(obj, b'__iter__'):
Yuya Nishihara
json: pass formatting options recursively...
r32743 out = [json(i, paranoid) for i in obj]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'[' + b', '.join(out) + b']'
raise error.ProgrammingError(b'cannot encode %r' % obj)
Dirkjan Ochtman
add graph page to hgweb
r6691
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'lower', intype=bytes)
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 def lower(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Converts the text to lowercase."""
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 return encoding.lower(text)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'nonempty', intype=bytes)
Pulkit Goyal
templatefilters: stop using str as a variable name...
r36570 def nonempty(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns '(none)' if the string is empty."""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return text or b"(none)"
Patrick Mezard
templatefilters: sort function definitions
r13588
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'obfuscate', intype=bytes)
Patrick Mezard
templatefilters: sort function definitions
r13588 def obfuscate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the input text rendered as a sequence of
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 XML entities.
"""
formatting: run black on all file again...
r43364 text = pycompat.unicode(
text, pycompat.sysstr(encoding.encoding), r'replace'
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''.join([b'&#%d;' % ord(c) for c in text])
Patrick Mezard
templatefilters: sort function definitions
r13588
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'permissions', intype=bytes)
Patrick Mezard
templatefilters: sort function definitions
r13588 def permissions(flags):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b"l" in flags:
return b"lrwxrwxrwx"
if b"x" in flags:
return b"-rwxr-xr-x"
return b"-rw-r--r--"
Patrick Mezard
templatefilters: sort function definitions
r13588
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'person', intype=bytes)
Patrick Mezard
templatefilters: sort function definitions
r13588 def person(author):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the name before an email address,
"Yann E. MORIN"
templates/filters: strip quotes from {author|person}...
r16235 interpreting it as per RFC 5322.
"""
Connor Sheehan
stringutil: move person function from templatefilters...
r37173 return stringutil.person(author)
Patrick Mezard
templatefilters: sort function definitions
r13588
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'revescape', intype=bytes)
av6
templates: introduce revescape filter for escaping symbolic revisions...
r25778 def revescape(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Escapes all "special" characters, except @.
av6
templates: introduce revescape filter for escaping symbolic revisions...
r25778 Forward slashes are escaped twice to prevent web servers from prematurely
unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return urlreq.quote(text, safe=b'/@').replace(b'/', b'%252F')
av6
templates: introduce revescape filter for escaping symbolic revisions...
r25778
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'rfc3339date', intype=templateutil.date)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def rfc3339date(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a date using the Internet date format
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return dateutil.datestr(text, b"%Y-%m-%dT%H:%M:%S%1:%2")
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'rfc822date', intype=templateutil.date)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def rfc822date(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a date using the same format used in email
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return dateutil.datestr(text, b"%a, %d %b %Y %H:%M:%S %1%2")
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'short', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def short(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Changeset hash. Returns the short form of a changeset hash,
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 i.e. a 12 hexadecimal digit string.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return text[:12]
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'shortbisect', intype=bytes)
Yuya Nishihara
templatefilters: inline hbisect.shortlabel()...
r36848 def shortbisect(label):
"""Any text. Treats `label` as a bisection status, and
"Yann E. MORIN"
templates: add 'bisect' keyword to return a cset's bisect status...
r15155 returns a single-character representing the status (G: good, B: bad,
S: skipped, U: untested, I: ignored). Returns single space if `text`
is not a valid bisection status.
"""
Yuya Nishihara
templatefilters: inline hbisect.shortlabel()...
r36848 if label:
Yuya Nishihara
py3: fix slicing of bisect label in templatefilters.shortbisect()
r36849 return label[0:1].upper()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b' '
"Yann E. MORIN"
templates: add 'bisect' keyword to return a cset's bisect status...
r15155
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'shortdate', intype=templateutil.date)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def shortdate(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Date. Returns a date like "2006-09-18"."""
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 return dateutil.shortdate(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'slashpath', intype=bytes)
Yuya Nishihara
templatefilters: add slashpath() to convert path separator to slash...
r35460 def slashpath(path):
"""Any text. Replaces the native path separator with slash."""
return util.pconvert(path)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'splitlines', intype=bytes)
Ryan McElroy
templatefilter: add splitlines function...
r21820 def splitlines(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Split text into a list of lines."""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return templateutil.hybridlist(text.splitlines(), name=b'line')
Ryan McElroy
templatefilter: add splitlines function...
r21820
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'stringescape', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def stringescape(text):
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 return stringutil.escapestr(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'stringify', intype=bytes)
Patrick Mezard
templatefilters: sort function definitions
r13588 def stringify(thing):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any type. Turns the value into text by converting values into
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 text and concatenating them.
"""
Yuya Nishihara
templatefilters: allow declaration of input data type...
r37239 return thing # coerced by the intype
Patrick Mezard
templatefilters: sort function definitions
r13588
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'stripdir', intype=bytes)
Aleix Conchillo Flaque
templatefilters: add new stripdir filter...
r8158 def stripdir(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Treat the text as path and strip a directory level, if
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 possible. For example, "foo" and "foo/bar" becomes "foo".
"""
Aleix Conchillo Flaque
templatefilters: add new stripdir filter...
r8158 dir = os.path.dirname(text)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if dir == b"":
Aleix Conchillo Flaque
templatefilters: add new stripdir filter...
r8158 return os.path.basename(text)
else:
return dir
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'tabindent', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def tabindent(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the text, with every non-empty line
Matt Mackall
template: fix tabindent docstring (issue2880)
r19467 except the first starting with a tab character.
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return indent(text, b'\t')
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'upper', intype=bytes)
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 def upper(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Converts the text to uppercase."""
Yuya Nishihara
templatefilters: add "upper" and "lower" for case conversion...
r24566 return encoding.upper(text)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'urlescape', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def urlescape(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Escapes all "special" characters. For example,
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 "foo bar" becomes "foo%20bar".
"""
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 return urlreq.quote(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'user', intype=bytes)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def userfilter(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns a short representation of a user name or email
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 address."""
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 return stringutil.shortuser(text)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'emailuser', intype=bytes)
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 def emailuser(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Returns the user portion of an email address."""
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 return stringutil.emailuser(text)
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'utf8', intype=bytes)
Yuya Nishihara
templatefilters: add "utf8" to get utf-8 bytes from local-encoding text...
r28209 def utf8(text):
FUJIWARA Katsunori
templatefilters: use templatefilter to mark a function as template filter...
r28693 """Any text. Converts from the local character encoding to UTF-8."""
Yuya Nishihara
templatefilters: add "utf8" to get utf-8 bytes from local-encoding text...
r28209 return encoding.fromlocal(text)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @templatefilter(b'xmlescape', intype=bytes)
Patrick Mezard
templatefilters: sort function definitions
r13588 def xmlescape(text):
Augie Fackler
formatting: blacken the codebase...
r43346 text = (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 text.replace(b'&', b'&amp;')
.replace(b'<', b'&lt;')
.replace(b'>', b'&gt;')
.replace(b'"', b'&quot;')
.replace(b"'", b'&#39;')
Augie Fackler
formatting: blacken the codebase...
r43346 ) # &apos; invalid in HTML
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return re.sub(b'[\x00-\x08\x0B\x0C\x0E-\x1F]', b' ', text)
Rocco Rutte
templatefilters: add "nonempty" template filter...
r8234
Augie Fackler
formatting: blacken the codebase...
r43346
Angel Ezquerra
hgweb: add websub template filter...
r18627 def websub(text, websubtable):
""":websub: Any text. Only applies to hgweb. Applies the regular
expression replacements defined in the websub section.
"""
if websubtable:
for regexp, format in websubtable:
text = regexp.sub(format, text)
return text
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
registrar: add templatefilter to mark a function as template filter (API)...
r28692 def loadfilter(ui, extname, registrarobj):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Load template filter from specified registrarobj"""
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for name, func in pycompat.iteritems(registrarobj._table):
FUJIWARA Katsunori
registrar: add templatefilter to mark a function as template filter (API)...
r28692 filters[name] = func
Augie Fackler
formatting: blacken the codebase...
r43346
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 # tell hggettext to extract docstrings from these functions:
i18nfunctions = filters.values()