changeset 33038:ce96efec8112

py3: add utility to forward __str__() to __bytes__() It calls unifromlocal() instead of sysstr() because __bytes__() may contain locale-dependent values such as paths.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 24 Jun 2017 13:48:04 +0900
parents 24c0a9a7fa86
children a10f5f6771f6
files mercurial/context.py mercurial/encoding.py mercurial/util.py
diffstat 3 files changed, 18 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/context.py	Sat Jun 24 13:20:30 2017 +0900
+++ b/mercurial/context.py	Sat Jun 24 13:48:04 2017 +0900
@@ -65,15 +65,11 @@
 
         return o
 
-    def __str__(self):
-        r = short(self.node())
-        if pycompat.ispy3:
-            return r.decode('ascii')
-        return r
-
     def __bytes__(self):
         return short(self.node())
 
+    __str__ = encoding.strmethod(__bytes__)
+
     def __int__(self):
         return self.rev()
 
@@ -710,17 +706,13 @@
 
     __bool__ = __nonzero__
 
-    def __str__(self):
+    def __bytes__(self):
         try:
             return "%s@%s" % (self.path(), self._changectx)
         except error.LookupError:
             return "%s@???" % self.path()
 
-    def __bytes__(self):
-        try:
-            return "%s@%s" % (self.path(), self._changectx)
-        except error.LookupError:
-            return "%s@???" % self.path()
+    __str__ = encoding.strmethod(__bytes__)
 
     def __repr__(self):
         return "<%s %s>" % (type(self).__name__, str(self))
@@ -1306,12 +1298,11 @@
         if self._extra['branch'] == '':
             self._extra['branch'] = 'default'
 
-    def __str__(self):
-        return str(self._parents[0]) + r"+"
-
     def __bytes__(self):
         return bytes(self._parents[0]) + "+"
 
+    __str__ = encoding.strmethod(__bytes__)
+
     def __nonzero__(self):
         return True
 
--- a/mercurial/encoding.py	Sat Jun 24 13:20:30 2017 +0900
+++ b/mercurial/encoding.py	Sat Jun 24 13:48:04 2017 +0900
@@ -177,15 +177,24 @@
     """Convert a byte string of local encoding to a unicode string"""
     return fromlocal(s).decode('utf-8')
 
+def unimethod(bytesfunc):
+    """Create a proxy method that forwards __unicode__() and __str__() of
+    Python 3 to __bytes__()"""
+    def unifunc(obj):
+        return unifromlocal(bytesfunc(obj))
+    return unifunc
+
 # converter functions between native str and byte string. use these if the
 # character encoding is not aware (e.g. exception message) or is known to
 # be locale dependent (e.g. date formatting.)
 if pycompat.ispy3:
     strtolocal = unitolocal
     strfromlocal = unifromlocal
+    strmethod = unimethod
 else:
     strtolocal = pycompat.identity
     strfromlocal = pycompat.identity
+    strmethod = pycompat.identity
 
 if not _nativeenviron:
     # now encoding and helper functions are available, recreate the environ
--- a/mercurial/util.py	Sat Jun 24 13:20:30 2017 +0900
+++ b/mercurial/util.py	Sat Jun 24 13:48:04 2017 +0900
@@ -2740,7 +2740,7 @@
                 attrs.append('%s: %r' % (a, v))
         return '<url %s>' % ', '.join(attrs)
 
-    def __str__(self):
+    def __bytes__(self):
         r"""Join the URL's components back into a URL string.
 
         Examples:
@@ -2774,9 +2774,6 @@
         >>> print url(r'file:///D:\data\hg')
         file:///D:\data\hg
         """
-        return encoding.strfromlocal(self.__bytes__())
-
-    def __bytes__(self):
         if self._localpath:
             s = self.path
             if self.scheme == 'bundle':
@@ -2820,6 +2817,8 @@
             s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
         return s
 
+    __str__ = encoding.strmethod(__bytes__)
+
     def authinfo(self):
         user, passwd = self.user, self.passwd
         try: