# HG changeset patch # User Yuya Nishihara # Date 1521355348 -32400 # Node ID 08e042f0a67c15e07e04d0112753794c4345c1e7 # Parent 54355c243042fca46e1041a5ed3a65e4aa788e91 templatefilters: declare input type as bytes where appropriate Some test outputs changed since input is now coerced to a byte string. I think that's okay. Maybe {date} should have some readable representation? diff -r 54355c243042 -r 08e042f0a67c mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py Sun Mar 18 15:14:58 2018 +0900 +++ b/mercurial/hgweb/hgweb_mod.py Sun Mar 18 15:42:28 2018 +0900 @@ -173,7 +173,7 @@ filters = {} templatefilter = registrar.templatefilter(filters) - @templatefilter('websub') + @templatefilter('websub', intype=bytes) def websubfilter(text): return templatefilters.websub(text, self.websubtable) diff -r 54355c243042 -r 08e042f0a67c mercurial/templatefilters.py --- a/mercurial/templatefilters.py Sun Mar 18 15:14:58 2018 +0900 +++ b/mercurial/templatefilters.py Sun Mar 18 15:42:28 2018 +0900 @@ -40,7 +40,7 @@ templatefilter = registrar.templatefilter(filters) -@templatefilter('addbreaks') +@templatefilter('addbreaks', intype=bytes) def addbreaks(text): """Any text. Add an XHTML "
" tag before the end of every line except the last. @@ -90,7 +90,7 @@ return '%s from now' % fmt(t, n, a) return '%s ago' % fmt(t, n, a) -@templatefilter('basename') +@templatefilter('basename', intype=bytes) def basename(path): """Any text. Treats the text as a path, and returns the last component of the path after splitting by the path separator. @@ -103,14 +103,14 @@ """List or text. Returns the length as an integer.""" return len(i) -@templatefilter('dirname') +@templatefilter('dirname', intype=bytes) 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) -@templatefilter('domain') +@templatefilter('domain', intype=bytes) def domain(author): """Any text. Finds the first string that looks like an email address, and extracts just the domain component. Example: ``User @@ -125,7 +125,7 @@ author = author[:f] return author -@templatefilter('email') +@templatefilter('email', intype=bytes) def email(text): """Any text. Extracts the first string that looks like an email address. Example: ``User `` becomes @@ -133,7 +133,7 @@ """ return stringutil.email(text) -@templatefilter('escape') +@templatefilter('escape', intype=bytes) def escape(text): """Any text. Replaces the special XML/XHTML characters "&", "<" and ">" with XML entities, and filters out NUL characters. @@ -170,17 +170,17 @@ width, initindent, hangindent) + rest for para, rest in findparas()]) -@templatefilter('fill68') +@templatefilter('fill68', intype=bytes) def fill68(text): """Any text. Wraps the text to fit in 68 columns.""" return fill(text, 68) -@templatefilter('fill76') +@templatefilter('fill76', intype=bytes) def fill76(text): """Any text. Wraps the text to fit in 76 columns.""" return fill(text, 76) -@templatefilter('firstline') +@templatefilter('firstline', intype=bytes) def firstline(text): """Any text. Returns the first line of text.""" try: @@ -188,7 +188,7 @@ except IndexError: return '' -@templatefilter('hex') +@templatefilter('hex', intype=bytes) def hexfilter(text): """Any text. Convert a binary Mercurial node identifier into its long hexadecimal representation. @@ -262,17 +262,17 @@ else: raise TypeError('cannot encode type %s' % obj.__class__.__name__) -@templatefilter('lower') +@templatefilter('lower', intype=bytes) def lower(text): """Any text. Converts the text to lowercase.""" return encoding.lower(text) -@templatefilter('nonempty') +@templatefilter('nonempty', intype=bytes) def nonempty(text): """Any text. Returns '(none)' if the string is empty.""" return text or "(none)" -@templatefilter('obfuscate') +@templatefilter('obfuscate', intype=bytes) def obfuscate(text): """Any text. Returns the input text rendered as a sequence of XML entities. @@ -280,7 +280,7 @@ text = unicode(text, pycompat.sysstr(encoding.encoding), r'replace') return ''.join(['&#%d;' % ord(c) for c in text]) -@templatefilter('permissions') +@templatefilter('permissions', intype=bytes) def permissions(flags): if "l" in flags: return "lrwxrwxrwx" @@ -288,14 +288,14 @@ return "-rwxr-xr-x" return "-rw-r--r--" -@templatefilter('person') +@templatefilter('person', intype=bytes) def person(author): """Any text. Returns the name before an email address, interpreting it as per RFC 5322. """ return stringutil.person(author) -@templatefilter('revescape') +@templatefilter('revescape', intype=bytes) def revescape(text): """Any text. Escapes all "special" characters, except @. Forward slashes are escaped twice to prevent web servers from prematurely @@ -317,14 +317,14 @@ """ return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2") -@templatefilter('short') +@templatefilter('short', intype=bytes) def short(text): """Changeset hash. Returns the short form of a changeset hash, i.e. a 12 hexadecimal digit string. """ return text[:12] -@templatefilter('shortbisect') +@templatefilter('shortbisect', intype=bytes) def shortbisect(label): """Any text. Treats `label` as a bisection status, and returns a single-character representing the status (G: good, B: bad, @@ -340,17 +340,17 @@ """Date. Returns a date like "2006-09-18".""" return dateutil.shortdate(text) -@templatefilter('slashpath') +@templatefilter('slashpath', intype=bytes) def slashpath(path): """Any text. Replaces the native path separator with slash.""" return util.pconvert(path) -@templatefilter('splitlines') +@templatefilter('splitlines', intype=bytes) def splitlines(text): """Any text. Split text into a list of lines.""" return templateutil.hybridlist(text.splitlines(), name='line') -@templatefilter('stringescape') +@templatefilter('stringescape', intype=bytes) def stringescape(text): return stringutil.escapestr(text) @@ -361,7 +361,7 @@ """ return thing # coerced by the intype -@templatefilter('stripdir') +@templatefilter('stripdir', intype=bytes) def stripdir(text): """Treat the text as path and strip a directory level, if possible. For example, "foo" and "foo/bar" becomes "foo". @@ -372,42 +372,42 @@ else: return dir -@templatefilter('tabindent') +@templatefilter('tabindent', intype=bytes) def tabindent(text): """Any text. Returns the text, with every non-empty line except the first starting with a tab character. """ return indent(text, '\t') -@templatefilter('upper') +@templatefilter('upper', intype=bytes) def upper(text): """Any text. Converts the text to uppercase.""" return encoding.upper(text) -@templatefilter('urlescape') +@templatefilter('urlescape', intype=bytes) def urlescape(text): """Any text. Escapes all "special" characters. For example, "foo bar" becomes "foo%20bar". """ return urlreq.quote(text) -@templatefilter('user') +@templatefilter('user', intype=bytes) def userfilter(text): """Any text. Returns a short representation of a user name or email address.""" return stringutil.shortuser(text) -@templatefilter('emailuser') +@templatefilter('emailuser', intype=bytes) def emailuser(text): """Any text. Returns the user portion of an email address.""" return stringutil.emailuser(text) -@templatefilter('utf8') +@templatefilter('utf8', intype=bytes) def utf8(text): """Any text. Converts from the local character encoding to UTF-8.""" return encoding.fromlocal(text) -@templatefilter('xmlescape') +@templatefilter('xmlescape', intype=bytes) def xmlescape(text): text = (text .replace('&', '&') diff -r 54355c243042 -r 08e042f0a67c tests/test-command-template.t --- a/tests/test-command-template.t Sun Mar 18 15:14:58 2018 +0900 +++ b/tests/test-command-template.t Sun Mar 18 15:42:28 2018 +0900 @@ -2284,8 +2284,7 @@ $ hg log -r0 --template '{author|lower}\n' user name $ hg log -r0 --template '{date|upper}\n' - abort: template filter 'upper' is not compatible with keyword 'date' - [255] + 1000000.00 Add a commit that does all possible modifications at once @@ -2797,11 +2796,12 @@ hg: parse error: missing argument [255] -Behind the scenes, this will throw TypeError +Behind the scenes, this would throw TypeError without intype=bytes $ hg log -l 3 --template '{date|obfuscate}\n' - abort: template filter 'obfuscate' is not compatible with keyword 'date' - [255] + 0.00 + 0.00 + 1577872860.00 Behind the scenes, this will throw a ValueError @@ -2809,11 +2809,12 @@ abort: template filter 'shortdate' is not compatible with keyword 'desc' [255] -Behind the scenes, this will throw AttributeError +Behind the scenes, this would throw AttributeError without intype=bytes $ hg log -l 3 --template 'line: {date|escape}\n' - abort: template filter 'escape' is not compatible with keyword 'date' - [255] + line: 0.00 + line: 0.00 + line: 1577872860.00 $ hg log -l 3 --template 'line: {extras|localdate}\n' hg: parse error: localdate expects a date information @@ -4656,9 +4657,8 @@ $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1 abort: decoding near * (glob) [255] - $ hg log -T "invalid type: {rev|utf8}\n" -r0 - abort: template filter 'utf8' is not compatible with keyword 'rev' - [255] + $ hg log -T "coerced to string: {rev|utf8}\n" -r0 + coerced to string: 0 pad width: