changeset 38239:1c8098cf560a

templater: always join() over a wrapped object (BC) This is a behavior change in a sense that join() of a byte string is no longer "implementation dependent." Before, if a byte string was backed by a lazy generator, join() would concatenate each chunk with the specified separator, which seems wrong. The new behavior is always join() each byte. TypeError on join() over uniterable is also fixed.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 21 Apr 2018 17:00:21 +0900
parents 7824783a6d5e
children 8bded7eae26c
files mercurial/templatefuncs.py tests/test-command-template.t
diffstat 2 files changed, 14 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/templatefuncs.py	Tue Mar 20 23:56:26 2018 +0900
+++ b/mercurial/templatefuncs.py	Sat Apr 21 17:00:21 2018 +0900
@@ -36,6 +36,7 @@
 )
 
 evalrawexp = templateutil.evalrawexp
+evalwrapped = templateutil.evalwrapped
 evalfuncarg = templateutil.evalfuncarg
 evalboolean = templateutil.evalboolean
 evaldate = templateutil.evaldate
@@ -327,17 +328,11 @@
         # i18n: "join" is a keyword
         raise error.ParseError(_("join expects one or two arguments"))
 
-    joinset = evalrawexp(context, mapping, args[0])
+    joinset = evalwrapped(context, mapping, args[0])
     joiner = " "
     if len(args) > 1:
         joiner = evalstring(context, mapping, args[1])
-    if isinstance(joinset, templateutil.wrapped):
-        return joinset.join(context, mapping, joiner)
-    # TODO: rethink about join() of a byte string, which had no defined
-    # behavior since a string may be either a bytes or a generator.
-    # TODO: fix type error on join() of non-iterable
-    joinset = templateutil.unwrapvalue(context, mapping, joinset)
-    return templateutil.joinitems(pycompat.maybebytestr(joinset), joiner)
+    return joinset.join(context, mapping, joiner)
 
 @templatefunc('label(label, expr)')
 def label(context, mapping, args):
--- a/tests/test-command-template.t	Tue Mar 20 23:56:26 2018 +0900
+++ b/tests/test-command-template.t	Sat Apr 21 17:00:21 2018 +0900
@@ -3249,6 +3249,17 @@
   $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), "")}\n'
   default
 
+Test join() over string
+
+  $ hg log -R latesttag -r tip -T '{join(rev|stringify, ".")}\n'
+  1.1
+
+Test join() over uniterable
+
+  $ hg log -R latesttag -r tip -T '{join(rev, "")}\n'
+  hg: parse error: 11 is not iterable
+  [255]
+
 Test min/max of integers
 
   $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'