[PATCH 03 of 11] templatefilters: declare input type as bytes where appropriate

Yuya Nishihara yuya at tcha.org
Fri Mar 30 21:49:31 EDT 2018


# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1521355348 -32400
#      Sun Mar 18 15:42:28 2018 +0900
# Node ID 5b226692c357623256819fc6ab2abead595734bc
# Parent  a31ddf984c1b851d78faa753b12aa694f6884ee5
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 --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -173,7 +173,7 @@ class requestcontext(object):
 
         filters = {}
         templatefilter = registrar.templatefilter(filters)
-        @templatefilter('websub')
+        @templatefilter('websub', intype=bytes)
         def websubfilter(text):
             return templatefilters.websub(text, self.websubtable)
 
diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -40,7 +40,7 @@ filters = {}
 
 templatefilter = registrar.templatefilter(filters)
 
- at templatefilter('addbreaks')
+ at templatefilter('addbreaks', intype=bytes)
 def addbreaks(text):
     """Any text. Add an XHTML "<br />" tag before the end of
     every line except the last.
@@ -90,7 +90,7 @@ def age(date, abbrev=False):
                 return '%s from now' % fmt(t, n, a)
             return '%s ago' % fmt(t, n, a)
 
- at templatefilter('basename')
+ at 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 @@ def count(i):
     """List or text. Returns the length as an integer."""
     return len(i)
 
- at templatefilter('dirname')
+ at 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)
 
- at templatefilter('domain')
+ at 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 @@ def domain(author):
         author = author[:f]
     return author
 
- at templatefilter('email')
+ at templatefilter('email', intype=bytes)
 def email(text):
     """Any text. Extracts the first string that looks like an email
     address. Example: ``User <user at example.com>`` becomes
@@ -133,7 +133,7 @@ def email(text):
     """
     return stringutil.email(text)
 
- at templatefilter('escape')
+ at 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 @@ def fill(text, width, initindent='', han
                                     width, initindent, hangindent) + rest
                     for para, rest in findparas()])
 
- at templatefilter('fill68')
+ at templatefilter('fill68', intype=bytes)
 def fill68(text):
     """Any text. Wraps the text to fit in 68 columns."""
     return fill(text, 68)
 
- at templatefilter('fill76')
+ at templatefilter('fill76', intype=bytes)
 def fill76(text):
     """Any text. Wraps the text to fit in 76 columns."""
     return fill(text, 76)
 
- at templatefilter('firstline')
+ at templatefilter('firstline', intype=bytes)
 def firstline(text):
     """Any text. Returns the first line of text."""
     try:
@@ -188,7 +188,7 @@ def firstline(text):
     except IndexError:
         return ''
 
- at templatefilter('hex')
+ at templatefilter('hex', intype=bytes)
 def hexfilter(text):
     """Any text. Convert a binary Mercurial node identifier into
     its long hexadecimal representation.
@@ -262,17 +262,17 @@ def json(obj, paranoid=True):
     else:
         raise TypeError('cannot encode type %s' % obj.__class__.__name__)
 
- at templatefilter('lower')
+ at templatefilter('lower', intype=bytes)
 def lower(text):
     """Any text. Converts the text to lowercase."""
     return encoding.lower(text)
 
- at templatefilter('nonempty')
+ at templatefilter('nonempty', intype=bytes)
 def nonempty(text):
     """Any text. Returns '(none)' if the string is empty."""
     return text or "(none)"
 
- at templatefilter('obfuscate')
+ at templatefilter('obfuscate', intype=bytes)
 def obfuscate(text):
     """Any text. Returns the input text rendered as a sequence of
     XML entities.
@@ -280,7 +280,7 @@ def obfuscate(text):
     text = unicode(text, pycompat.sysstr(encoding.encoding), r'replace')
     return ''.join(['&#%d;' % ord(c) for c in text])
 
- at templatefilter('permissions')
+ at templatefilter('permissions', intype=bytes)
 def permissions(flags):
     if "l" in flags:
         return "lrwxrwxrwx"
@@ -288,14 +288,14 @@ def permissions(flags):
         return "-rwxr-xr-x"
     return "-rw-r--r--"
 
- at templatefilter('person')
+ at 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)
 
- at templatefilter('revescape')
+ at 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 @@ def rfc822date(text):
     """
     return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
 
- at templatefilter('short')
+ at 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]
 
- at templatefilter('shortbisect')
+ at 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 @@ def shortdate(text):
     """Date. Returns a date like "2006-09-18"."""
     return dateutil.shortdate(text)
 
- at templatefilter('slashpath')
+ at templatefilter('slashpath', intype=bytes)
 def slashpath(path):
     """Any text. Replaces the native path separator with slash."""
     return util.pconvert(path)
 
- at templatefilter('splitlines')
+ at templatefilter('splitlines', intype=bytes)
 def splitlines(text):
     """Any text. Split text into a list of lines."""
     return templateutil.hybridlist(text.splitlines(), name='line')
 
- at templatefilter('stringescape')
+ at templatefilter('stringescape', intype=bytes)
 def stringescape(text):
     return stringutil.escapestr(text)
 
@@ -361,7 +361,7 @@ def stringify(thing):
     """
     return thing  # coerced by the intype
 
- at templatefilter('stripdir')
+ at 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 @@ def stripdir(text):
     else:
         return dir
 
- at templatefilter('tabindent')
+ at 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')
 
- at templatefilter('upper')
+ at templatefilter('upper', intype=bytes)
 def upper(text):
     """Any text. Converts the text to uppercase."""
     return encoding.upper(text)
 
- at templatefilter('urlescape')
+ at templatefilter('urlescape', intype=bytes)
 def urlescape(text):
     """Any text. Escapes all "special" characters. For example,
     "foo bar" becomes "foo%20bar".
     """
     return urlreq.quote(text)
 
- at templatefilter('user')
+ at templatefilter('user', intype=bytes)
 def userfilter(text):
     """Any text. Returns a short representation of a user name or email
     address."""
     return stringutil.shortuser(text)
 
- at templatefilter('emailuser')
+ at templatefilter('emailuser', intype=bytes)
 def emailuser(text):
     """Any text. Returns the user portion of an email address."""
     return stringutil.emailuser(text)
 
- at templatefilter('utf8')
+ at templatefilter('utf8', intype=bytes)
 def utf8(text):
     """Any text. Converts from the local character encoding to UTF-8."""
     return encoding.fromlocal(text)
 
- at templatefilter('xmlescape')
+ at templatefilter('xmlescape', intype=bytes)
 def xmlescape(text):
     text = (text
             .replace('&', '&')
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -2284,8 +2284,7 @@ Upper/lower filters:
   $ hg log -r0 --template '{author|lower}\n'
   user name <user at hostname>
   $ 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 @@ Error on syntax:
   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 @@ Behind the scenes, this will throw a Val
   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 @@ utf8 filter:
   $ 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:
 


More information about the Mercurial-devel mailing list