Patchwork [5,of,9,V2] mercurial: don't rewrite string argument to *attr()

login
register
mail settings
Submitter Gregory Szorc
Date June 25, 2016, 9:11 p.m.
Message ID <3803d2501ef928a177fa.1466889079@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/15619/
State Superseded
Headers show

Comments

Gregory Szorc - June 25, 2016, 9:11 p.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1466886629 25200
#      Sat Jun 25 13:30:29 2016 -0700
# Node ID 3803d2501ef928a177fa09df612da6a09e9f42e6
# Parent  146c88395195b15027c80ad2931a26cb1c46768a
mercurial: don't rewrite string argument to *attr()

The getattr(), setattr(), and hasattr() builtin functions and
util.safehasattr() don't accept bytes as their 2nd argument. Our
naive string token replacer was converting unprefixed string
literals to byte prefixed strings for these function calls,
leading to various import time failures when calling these
functions as part of loading modules.

Since *attr functions are commonly used and updating all callers
would be annoying, detect these function calls and ensure a string
literal 2nd argument doesn't get converted to a bytes literal.

Patch

diff --git a/mercurial/__init__.py b/mercurial/__init__.py
--- a/mercurial/__init__.py
+++ b/mercurial/__init__.py
@@ -179,17 +179,17 @@  if sys.version_info[0] >= 3:
         Returns a generator of possibly rewritten tokens.
 
         The input token list may be mutated as part of processing. However,
         its changes do not necessarily match the output token stream.
 
         REMEMBER TO CHANGE ``BYTECODEHEADER`` WHEN CHANGING THIS FUNCTION
         OR CACHED FILES WON'T GET INVALIDATED PROPERLY.
         """
-        for t in tokens:
+        for i, t in enumerate(tokens):
             # Convert most string literals to byte literals. String literals
             # in Python 2 are bytes. String literals in Python 3 are unicode.
             # Most strings in Mercurial are bytes and unicode strings are rare.
             # Rather than rewrite all string literals to use ``b''`` to indicate
             # byte strings, we apply this token transformer to insert the ``b``
             # prefix nearly everywhere.
             if t.type == token.STRING:
                 s = t.string
@@ -212,24 +212,53 @@  if sys.version_info[0] >= 3:
                     yield t
                     continue
 
                 # String literal. Prefix to make a b'' string.
                 yield tokenize.TokenInfo(t.type, 'b%s' % s, t.start, t.end,
                                           t.line)
                 continue
 
+            try:
+                nexttoken = tokens[i + 1]
+            except IndexError:
+                nexttoken = None
+
+            # This looks like a function call.
+            if (t.type == token.NAME and nexttoken and
+                nexttoken.type == token.OP and nexttoken.string == '('):
+                fn = t.string
+
+                # *attr() builtins don't accept byte strings to 2nd argument.
+                # Rewrite the token to include the unicode literal prefix so
+                # the string transformer above doesn't add the byte prefix.
+                if fn in ('getattr', 'setattr', 'hasattr', 'safehasattr'):
+                    try:
+                        # (NAME, 'getattr')
+                        # (OP, '(')
+                        # (NAME, 'foo')
+                        # (OP, ',')
+                        # (NAME|STRING, foo)
+                        st = tokens[i + 4]
+                        if (st.type == token.STRING and
+                            st.string[0] in ("'", '"')):
+                            rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
+                                                    st.start, st.end, st.line)
+                            tokens[i + 4] = rt
+                    except IndexError:
+                        pass
+
             # Emit unmodified token.
             yield t
 
     # Header to add to bytecode files. This MUST be changed when
     # ``replacetoken`` or any mechanism that changes semantics of module
     # loading is changed. Otherwise cached bytecode may get loaded without
     # the new transformation mechanisms applied.
-    BYTECODEHEADER = b'HG\x00\x01'
+    BYTECODEHEADER = b'HG\x00\x02'
 
     class hgloader(importlib.machinery.SourceFileLoader):
         """Custom module loader that transforms source code.
 
         When the source code is converted to a code object, we transform
         certain patterns to be Python 3 compatible. This allows us to write code
         that is natively Python 2 and compatible with Python 3 without
         making the code excessively ugly.
diff --git a/tests/test-check-py3-compat.t b/tests/test-check-py3-compat.t
--- a/tests/test-check-py3-compat.t
+++ b/tests/test-check-py3-compat.t
@@ -19,121 +19,121 @@ 
   tests/md5sum.py not using absolute_import
   tests/readlink.py not using absolute_import
   tests/run-tests.py not using absolute_import
   tests/test-demandimport.py not using absolute_import
 
 #if py3exe
   $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs $PYTHON3 contrib/check-py3-compat.py
   doc/hgmanpage.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
-  hgext/acl.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/automv.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/blackbox.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  hgext/acl.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/automv.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/blackbox.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   hgext/bugzilla.py: error importing module: <ImportError> No module named 'urlparse' (line *) (glob)
-  hgext/censor.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  hgext/censor.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   hgext/chgserver.py: error importing module: <ImportError> No module named 'SocketServer' (line *) (glob)
-  hgext/children.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/churn.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/clonebundles.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  hgext/children.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/churn.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/clonebundles.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   hgext/color.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
-  hgext/convert/bzr.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/common.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/convcmd.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/cvs.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/cvsps.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/darcs.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/filemap.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/git.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/gnuarch.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/hg.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/monotone.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/p4.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/convert/subversion.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  hgext/convert/bzr.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/common.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/convcmd.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/cvs.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/cvsps.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/darcs.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/filemap.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/git.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/gnuarch.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/hg.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/monotone.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/p4.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/convert/subversion.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   hgext/convert/transport.py: error importing module: <ImportError> No module named 'svn.client' (line *) (glob)
-  hgext/eol.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/extdiff.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/factotum.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/fetch.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/fsmonitor/state.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/fsmonitor/watchmanclient.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/gpg.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/graphlog.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/hgk.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/highlight/highlight.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/histedit.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/keyword.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/basestore.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/lfcommands.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/lfutil.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/localstore.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/overrides.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/proto.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/remotestore.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/reposetup.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/storefactory.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/largefiles/uisetup.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  hgext/eol.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/extdiff.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/factotum.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/fetch.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/fsmonitor/state.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/fsmonitor/watchmanclient.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/gpg.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/graphlog.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/hgk.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/highlight/highlight.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/histedit.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/keyword.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/basestore.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/lfcommands.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/lfutil.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/localstore.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/overrides.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/proto.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/remotestore.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/reposetup.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/storefactory.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/largefiles/uisetup.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   hgext/largefiles/wirestore.py: error importing module: <SystemError> Parent module 'hgext.largefiles' not loaded, cannot perform relative import (line *) (glob)
-  hgext/mq.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/notify.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/pager.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/patchbomb.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/purge.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/rebase.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/record.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/relink.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/schemes.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/share.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/shelve.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/strip.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/transplant.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/win32mbcs.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  hgext/win32text.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  hgext/mq.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/notify.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/pager.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/patchbomb.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/purge.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/rebase.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/record.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/relink.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/schemes.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/share.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/shelve.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/strip.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/transplant.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/win32mbcs.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  hgext/win32text.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   mercurial/archival.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
-  mercurial/bookmarks.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/branchmap.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  mercurial/bookmarks.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/branchmap.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   mercurial/bundle2.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
-  mercurial/bundlerepo.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/byterange.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/changegroup.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/changelog.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/cmdutil.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  mercurial/bundlerepo.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/byterange.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/changegroup.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/changelog.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/cmdutil.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   mercurial/commands.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
   mercurial/commandserver.py: error importing module: <ImportError> No module named 'SocketServer' (line *) (glob)
-  mercurial/config.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/context.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/copies.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/crecord.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/dagparser.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/dagutil.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/destutil.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/dirstate.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/discovery.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/dispatch.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/exchange.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/extensions.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/fancyopts.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/filelog.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/filemerge.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/fileset.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/formatter.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/graphmod.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/hbisect.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/help.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/hg.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  mercurial/config.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/context.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/copies.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/crecord.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/dagparser.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/dagutil.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/destutil.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/dirstate.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/discovery.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/dispatch.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/exchange.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/extensions.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/fancyopts.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/filelog.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/filemerge.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/fileset.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/formatter.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/graphmod.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/hbisect.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/help.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/hg.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   mercurial/hgweb/common.py: error importing module: <ImportError> No module named 'BaseHTTPServer' (line *) (glob)
   mercurial/hgweb/hgweb_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
   mercurial/hgweb/hgwebdir_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
   mercurial/hgweb/protocol.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
   mercurial/hgweb/request.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
   mercurial/hgweb/server.py: error importing module: <ImportError> No module named 'BaseHTTPServer' (line *) (glob)
   mercurial/hgweb/webcommands.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
   mercurial/hgweb/webutil.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
   mercurial/hgweb/wsgicgi.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
-  mercurial/hook.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
-  mercurial/httpconnection.py: error importing: <TypeError> getattr(): attribute name must be string (error at i18n.py:*) (glob)
+  mercurial/hook.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
+  mercurial/httpconnection.py: error importing: <TypeError> str expected, not bytes (error at i18n.py:*) (glob)
   mercurial/httppeer.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
   mercurial/keepalive.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
   mercurial/localrepo.py: error importing: <TypeError> '_fields_' must be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
   mercurial/lock.py: error importing: <TypeError> '_fields_' must be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
   mercurial/mail.py: error importing: <TypeError> '_fields_' must be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
   mercurial/manifest.py: error importing: <TypeError> getattr(): attribute name must be string (error at pycompat.py:*) (glob)
   mercurial/match.py: error importing: <TypeError> '_fields_' must be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
   mercurial/mdiff.py: error importing: <TypeError> getattr(): attribute name must be string (error at pycompat.py:*) (glob)