Patchwork [2,of,5] pycompat: extract function that converts attribute or encoding name to str

login
register
mail settings
Submitter Yuya Nishihara
Date Sept. 29, 2016, 2:50 p.m.
Message ID <bff052c460632022a9f8.1475160627@mimosa>
Download mbox | patch
Permalink /patch/16801/
State Accepted
Headers show

Comments

Yuya Nishihara - Sept. 29, 2016, 2:50 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1475069529 -32400
#      Wed Sep 28 22:32:09 2016 +0900
# Node ID bff052c460632022a9f896a945539c77085c77b7
# Parent  b1e134252685a51f3b2c5c3c22540f3ec30effb0
pycompat: extract function that converts attribute or encoding name to str

This will be used to convert encoding.encoding to a str acceptable by
Python 3 functions.

The source encoding is changed to "latin-1" because encoding.encoding can
have arbitrary bytes. Since valid names should consist of ASCII characters,
we don't care about the mapping of non-ASCII characters so long as invalid
names are distinct from valid names.

Patch

diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -35,12 +35,22 @@  if ispy3:
     import builtins
     import functools
 
+    def sysstr(s):
+        """Return a keyword str to be passed to Python functions such as
+        getattr() and str.encode()
+
+        This never raises UnicodeDecodeError. Non-ascii characters are
+        considered invalid and mapped to arbitrary but unique code points
+        such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
+        """
+        if isinstance(s, builtins.str):
+            return s
+        return s.decode(u'latin-1')
+
     def _wrapattrfunc(f):
         @functools.wraps(f)
         def w(object, name, *args):
-            if isinstance(name, bytes):
-                name = name.decode(u'utf-8')
-            return f(object, name, *args)
+            return f(object, sysstr(name), *args)
         return w
 
     # these wrappers are automagically imported by hgloader
@@ -50,6 +60,10 @@  if ispy3:
     setattr = _wrapattrfunc(builtins.setattr)
     xrange = builtins.range
 
+else:
+    def sysstr(s):
+        return s
+
 stringio = io.StringIO
 empty = _queue.Empty
 queue = _queue.Queue