Patchwork [5,of,9] py3: build repr() of smartset as bytes then convert to str

login
register
mail settings
Submitter Yuya Nishihara
Date Feb. 3, 2018, 8:36 a.m.
Message ID <6fe094beb24e69c9a343.1517646976@mimosa>
Download mbox | patch
Permalink /patch/27265/
State Accepted
Headers show

Comments

Yuya Nishihara - Feb. 3, 2018, 8:36 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1517040755 -32400
#      Sat Jan 27 17:12:35 2018 +0900
# Node ID 6fe094beb24e69c9a34331a2e10fc4b79c6d7669
# Parent  85ed4b6e56fdceaae2a7deb5b129ea8ee24ee8c5
py3: build repr() of smartset as bytes then convert to str

This isn't pretty, but we have no way to teach Python 3 that our __repr__()
would like to return a byte string.

Patch

diff --git a/mercurial/smartset.py b/mercurial/smartset.py
--- a/mercurial/smartset.py
+++ b/mercurial/smartset.py
@@ -8,7 +8,9 @@ 
 from __future__ import absolute_import
 
 from . import (
+    encoding,
     error,
+    pycompat,
     util,
 )
 
@@ -19,7 +21,7 @@  def _formatsetrepr(r):
     type(r)   example
     ========  =================================
     tuple     ('<not %r>', other)
-    str       '<branch closed>'
+    bytes     '<branch closed>'
     callable  lambda: '<branch %r>' % sorted(b)
     object    other
     ========  =================================
@@ -28,12 +30,15 @@  def _formatsetrepr(r):
         return ''
     elif isinstance(r, tuple):
         return r[0] % r[1:]
-    elif isinstance(r, str):
+    elif isinstance(r, bytes):
         return r
     elif callable(r):
         return r()
     else:
-        return repr(r)
+        return pycompat.sysbytes(repr(r))
+
+def _typename(o):
+    return pycompat.sysbytes(type(o).__name__).lstrip('_')
 
 class abstractsmartset(object):
 
@@ -384,6 +389,7 @@  class baseset(abstractsmartset):
         s._ascending = self._ascending
         return s
 
+    @encoding.strmethod
     def __repr__(self):
         d = {None: '', False: '-', True: '+'}[self._ascending]
         s = _formatsetrepr(self._datarepr)
@@ -394,8 +400,8 @@  class baseset(abstractsmartset):
             # We fallback to the sorted version for a stable output.
             if self._ascending is not None:
                 l = self._asclist
-            s = repr(l)
-        return '<%s%s %s>' % (type(self).__name__, d, s)
+            s = pycompat.sysbytes(repr(l))
+        return '<%s%s %s>' % (_typename(self), d, s)
 
 class filteredset(abstractsmartset):
     """Duck type for baseset class which iterates lazily over the revisions in
@@ -505,12 +511,13 @@  class filteredset(abstractsmartset):
                 pass
             return x
 
+    @encoding.strmethod
     def __repr__(self):
-        xs = [repr(self._subset)]
+        xs = [pycompat.sysbytes(repr(self._subset))]
         s = _formatsetrepr(self._condrepr)
         if s:
             xs.append(s)
-        return '<%s %s>' % (type(self).__name__, ', '.join(xs))
+        return '<%s %s>' % (_typename(self), ', '.join(xs))
 
 def _iterordered(ascending, iter1, iter2):
     """produce an ordered iteration from two iterators with the same order
@@ -755,9 +762,10 @@  class addset(abstractsmartset):
         self.reverse()
         return val
 
+    @encoding.strmethod
     def __repr__(self):
         d = {None: '', False: '-', True: '+'}[self._ascending]
-        return '<%s%s %r, %r>' % (type(self).__name__, d, self._r1, self._r2)
+        return '<%s%s %r, %r>' % (_typename(self), d, self._r1, self._r2)
 
 class generatorset(abstractsmartset):
     """Wrap a generator for lazy iteration
@@ -918,9 +926,10 @@  class generatorset(abstractsmartset):
             return self.last()
         return next(it(), None)
 
+    @encoding.strmethod
     def __repr__(self):
         d = {False: '-', True: '+'}[self._ascending]
-        return '<%s%s>' % (type(self).__name__.lstrip('_'), d)
+        return '<%s%s>' % (_typename(self), d)
 
 class _generatorsetasc(generatorset):
     """Special case of generatorset optimized for ascending generators."""
@@ -1087,10 +1096,10 @@  class _spanset(abstractsmartset):
             y = max(self._end - start, self._start)
         return _spanset(x, y, self._ascending, self._hiddenrevs)
 
+    @encoding.strmethod
     def __repr__(self):
         d = {False: '-', True: '+'}[self._ascending]
-        return '<%s%s %d:%d>' % (type(self).__name__.lstrip('_'), d,
-                                 self._start, self._end)
+        return '<%s%s %d:%d>' % (_typename(self), d, self._start, self._end)
 
 class fullreposet(_spanset):
     """a set containing all revisions in the repo
@@ -1123,7 +1132,7 @@  class fullreposet(_spanset):
 
 def prettyformat(revs):
     lines = []
-    rs = repr(revs)
+    rs = pycompat.sysbytes(repr(revs))
     p = 0
     while p < len(rs):
         q = rs.find('<', p + 1)