[PATCH 1 of 6] mercurial: implement a source transforming module loader on Python 3

Gregory Szorc gregory.szorc at gmail.com
Mon Jun 6 15:29:25 EDT 2016


On Tue, May 31, 2016 at 10:52 PM, Gregory Szorc <gregory.szorc at gmail.com>
wrote:

> # HG changeset patch
> # User Gregory Szorc <gregory.szorc at gmail.com>
> # Date 1464759986 25200
> #      Tue May 31 22:46:26 2016 -0700
> # Node ID 867ebaa1ca956c76022655eb1f7a6f39da42b5a4
> # Parent  48b38b16a8f83ea98ebdf0b370f59fd90dc17935
> mercurial: implement a source transforming module loader on Python 3
>
> The most painful part of ensuring Python code runs on both Python 2
> and 3 is string encoding. Making this difficult is that string
> literals in Python 2 are bytes and string literals in Python 3 are
> unicode. So, to ensure consistent types are used, you have to
> use "from __future__ import unicode_literals" and/or prefix literals
> with their type (e.g. b'foo' or u'foo').
>
> Nearly every string in Mercurial is bytes. So, to use the same source
> code on both Python 2 and 3 would require prefixing nearly every
> string literal with "b" to make it a byte literal. This is ugly and
> not something mpm is willing to do.
>
> This patch implements a custom module loader on Python 3 that performs
> source transformation to convert string literals (unicode in Python 3)
> to byte literals. In effect, it changes Python 3's string literals to
> behave like Python 2's.
>
> The module loader is only used on mercurial.* and hgext.* modules.
>
> The loader works by tokenizing the loaded source and replacing
> "string" tokens if necessary. The modified token stream is
> untokenized back to source and loaded like normal. This does add some
> overhead. However, this all occurs before caching: .pyc files will
> cache the transformed version. This means the transformation penalty
> is only paid on first load.
>
> As the extensive inline comments explain, the presence of a custom
> source transformer invalidates assumptions made by Python's built-in
> bytecode caching mechanism. So, we have to wrap bytecode loading and
> writing and add an additional header to bytecode files to facilitate
> additional cache validation when the source transformations
> change in the future.
>
> There are still a few things this code doesn't handle well, namely
> support for zip files as module sources and for extensions. Since
> Mercurial doesn't officially support Python 3 yet, I'm inclined to
> leave these as to-do items: getting a basic module loading mechanism
> in place to unblock further Python 3 porting effort is more important
> than comprehensive module importing support.
>
> check-py3-compat.py has been updated to ignore frames. This is
> necessary because CPython has built-in code to strip frames from the
> built-in importer. When our custom code is present, this doesn't work
> and the frames get all messed up. The new code is not perfect. It
> works for now. But once you start chasing import failures you find
> some edge cases where the files aren't being printed properly. This
> only burdens people doing future Python 3 porting work so I'm inclined
> to punt on the issue: the most important thing if for the source
> transforming module loader to land.
>
> There was a bit of churn in test-check-py3-compat.t because we now
> trip up on str/unicode/bytes failures as a result of source
> transformation. This is unfortunate. But what are you going to do?
>

I should probably add this to the commit message, but I chose this approach
over a custom codec because it feels more robust and cleaner to me. With a
custom codec:

* You need to declare the codec in the header of every .py file
* When the transformation semantics change, we'd likely need to bump the
codec name/version otherwise the cached .pyc will get used. This means
updating every .py file whenever we change transformation logic. Yuck.


>
> diff --git a/contrib/check-py3-compat.py b/contrib/check-py3-compat.py
> --- a/contrib/check-py3-compat.py
> +++ b/contrib/check-py3-compat.py
> @@ -56,17 +56,30 @@ def check_compat_py3(f):
>      if f.startswith(('hgext/', 'mercurial/')) and not
> f.endswith('__init__.py'):
>          assert f.endswith('.py')
>          name = f.replace('/', '.')[:-3]
>          with open(f, 'r') as fh:
>              try:
>                  imp.load_module(name, fh, '', ('py', 'r', imp.PY_SOURCE))
>              except Exception as e:
>                  exc_type, exc_value, tb = sys.exc_info()
> -                frame = traceback.extract_tb(tb)[-1]
> +                # We walk the stack and ignore frames from our custom
> importer,
> +                # import mechanisms, and stdlib modules. This kinda/sorta
> +                # emulates CPython behavior in import.c while also
> attempting
> +                # to pin blame on a Mercurial file.
> +                for frame in reversed(traceback.extract_tb(tb)):
> +                    if frame.name == '_call_with_frames_removed':
> +                        continue
> +                    if 'importlib' in frame.filename:
> +                        continue
> +                    if 'mercurial/__init__.py' in frame.filename:
> +                        continue
> +                    if frame.filename.startswith(sys.prefix):
> +                        continue
> +                    break
>
>                  if frame.filename:
>                      filename = os.path.basename(frame.filename)
>                      print('%s: error importing: <%s> %s (error at %s:%d)'
> % (
>                            f, type(e).__name__, e, filename, frame.lineno))
>                  else:
>                      print('%s: error importing module: <%s> %s (line %d)'
> % (
>                            f, type(e).__name__, e, frame.lineno))
> diff --git a/mercurial/__init__.py b/mercurial/__init__.py
> --- a/mercurial/__init__.py
> +++ b/mercurial/__init__.py
> @@ -116,14 +116,168 @@ class hgimporter(object):
>              if not modinfo:
>                  raise ImportError('could not find mercurial module %s' %
>                                    name)
>
>          mod = imp.load_module(name, *modinfo)
>          sys.modules[name] = mod
>          return mod
>
> +# Python 3 uses a custom module loader that transforms source code between
> +# source file reading and compilation. This is done by registering a
> custom
> +# finder that changes the spec for Mercurial modules to use a custom
> loader.
> +if sys.version_info[0] >= 3:
> +    from . import pure
> +    import importlib
> +    import io
> +    import token
> +    import tokenize
> +
> +    class hgpathentryfinder(importlib.abc.PathEntryFinder):
> +        """A sys.meta_path finder that uses a custom module loader."""
> +        def find_spec(self, fullname, path, target=None):
> +            # Only handle Mercurial-related modules.
> +            if not fullname.startswith(('mercurial.', 'hgext.')):
> +                return None
> +
> +            # This assumes Python 3 doesn't support loading C modules.
> +            if fullname in _dualmodules:
> +                stem = fullname.split('.')[-1]
> +                fullname = 'mercurial.pure.%s' % stem
> +                target = pure
> +                assert len(path) == 1
> +                path = [os.path.join(path[0], 'pure')]
> +
> +            # Try to find the module using other registered finders.
> +            spec = None
> +            for finder in sys.meta_path:
> +                if finder == self:
> +                    continue
> +
> +                spec = finder.find_spec(fullname, path, target=target)
> +                if spec:
> +                    break
> +
> +            # This is a Mercurial-related module but we couldn't find it
> +            # using the previously-registered finders. This likely means
> +            # the module doesn't exist.
> +            if not spec:
> +                return None
> +
> +            if fullname.startswith('mercurial.pure.'):
> +                spec.name = spec.name.replace('.pure.', '.')
> +
> +            # TODO need to support loaders from alternate specs, like zip
> +            # loaders.
> +            spec.loader = hgloader(spec.name, spec.origin)
> +            return spec
> +
> +    def replacetoken(t):
> +        """Transform a source token from raw to Python 3.
> +
> +        This function is called for every lexical token found from
> +        ``tokenize.tokenize()``. It allows the module loader to rewrite
> +        tokens between source decoding and compilation.
> +
> +        REMEMBER TO BUMP ``BYTECODEHEADER`` WHEN CHANGING THIS FUNCTION.
> +        """
> +        # 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
> +
> +            # If a docstring, keep it as a string literal.
> +            if s[0:3] in ("'''", '"""'):
> +                return t
> +
> +            if s[0] not in ("'", '"'):
> +                return t
> +
> +            # String literal. Prefix to make a b'' string.
> +            return tokenize.TokenInfo(t.type, 'b%s' % s, t.start, t.end,
> t.line)
> +
> +        return 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'
> +
> +    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.
> +
> +        We do this by transforming the token stream between parse and
> compile.
> +
> +        Implementing transformations invalidates caching assumptions made
> +        by the built-in importer. The built-in importer stores a header on
> +        saved bytecode files indicating the Python/bytecode version. If
> the
> +        version changes, the cached bytecode is ignored. The Mercurial
> +        transformations could change at any time. This means we need to
> check
> +        that cached bytecode was generated with the current transformation
> +        code or there could be a mismatch between cached bytecode and what
> +        would be generated from this class.
> +
> +        We supplement the bytecode caching layer by wrapping ``get_data``
> +        and ``set_data``. These functions are called when the
> +        ``SourceFileLoader`` retrieves and saves bytecode cache files,
> +        respectively. We simply add an additional header on the file. As
> +        long as the version in this file is changed when semantics change,
> +        cached bytecode should be invalidated when transformations change.
> +
> +        The added header has the form ``HG<VERSION>``. That is a literal
> +        ``HG`` with 2 binary bytes indicating the transformation version.
> +        """
> +        def get_data(self, path):
> +            data = super(hgloader, self).get_data(path)
> +
> +            if not
> path.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
> +                return data
> +
> +            # There should be a header indicating the Mercurial
> transformation
> +            # version. If it doesn't exist or doesn't match the current
> version,
> +            # we raise an OSError because that is what
> +            # ``SourceFileLoader.get_code()`` expects when loading
> bytecode
> +            # paths.
> +            if data[0:2] != b'HG':
> +                raise OSError('no hg header')
> +            if data[0:4] != BYTECODEHEADER:
> +                raise OSError('hg header version mismatch')
> +
> +            return data[4:]
> +
> +        def set_data(self, path, data, *args, **kwargs):
> +            if
> path.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
> +                data = BYTECODEHEADER + data
> +
> +            return super(hgloader, self).set_data(path, data, *args,
> **kwargs)
> +
> +        def source_to_code(self, data, path):
> +            """Perform token transformation before compilation."""
> +            buf = io.BytesIO(data)
> +            tokens = tokenize.tokenize(buf.readline)
> +            data = tokenize.untokenize(replacetoken(t) for t in tokens)
> +            # Python's built-in importer strips frames from exceptions
> raised
> +            # for this code. Unfortunately, that mechanism isn't
> extensible
> +            # and our frame will be blamed for the import failure. There
> +            # are extremely hacky ways to do frame stripping. We haven't
> +            # implemented them because they are very ugly.
> +            return super(hgloader, self).source_to_code(data, path)
> +
>  # We automagically register our custom importer as a side-effect of
> loading.
>  # This is necessary to ensure that any entry points are able to import
>  # mercurial.* modules without having to perform this registration
> themselves.
> -if not any(isinstance(x, hgimporter) for x in sys.meta_path):
> +if sys.version_info[0] >= 3:
> +    _importercls = hgpathentryfinder
> +else:
> +    _importercls = hgimporter
> +if not any(isinstance(x, _importercls) for x in sys.meta_path):
>      # meta_path is used before any implicit finders and before sys.path.
> -    sys.meta_path.insert(0, hgimporter())
> +    sys.meta_path.insert(0, _importercls())
> 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
> @@ -30,133 +30,164 @@
>    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/automv.py: error importing module: <SyntaxError> invalid syntax
> (commands.py, line *) (line *) (glob)
> -  hgext/blackbox.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/bugzilla.py: error importing module: <ImportError> No module
> named 'urlparse' (line *) (glob)
> -  hgext/censor.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/chgserver.py: error importing module: <ImportError> No module
> named 'SocketServer' (line *) (glob)
> -  hgext/children.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/churn.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/clonebundles.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> +  hgext/acl.py: error importing: <TypeError> encode() argument 1 must be
> str, not bytes (error at encoding.py:*) (glob)
> +  hgext/automv.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/blackbox.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/bugzilla.py: error importing module: <ImportError> No module
> named 'urlparse' (line 284)
> +  hgext/censor.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/chgserver.py: error importing module: <ImportError> No module
> named 'SocketServer' (line 43)
> +  hgext/children.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/churn.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/clonebundles.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
>    hgext/color.py: invalid syntax: invalid syntax (<unknown>, line *)
> (glob)
> -  hgext/convert/bzr.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/common.py: error importing module: <ImportError> No
> module named 'cPickle' (line *) (glob)
> -  hgext/convert/convcmd.py: error importing: <SyntaxError> invalid syntax
> (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
> -  hgext/convert/cvs.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/cvsps.py: error importing module: <ImportError> No module
> named 'cPickle' (line *) (glob)
> -  hgext/convert/darcs.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/filemap.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/git.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/gnuarch.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/hg.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/convert/monotone.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/p*.py: error importing module: <SystemError> Parent
> module 'hgext.convert' not loaded, cannot perform relative import (line *)
> (glob)
> -  hgext/convert/subversion.py: error importing module: <ImportError> No
> module named 'cPickle' (line *) (glob)
> -  hgext/convert/transport.py: error importing module: <ImportError> No
> module named 'svn.client' (line *) (glob)
> -  hgext/eol.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/extdiff.py: error importing module: <SyntaxError> invalid syntax
> (archival.py, line *) (line *) (glob)
> -  hgext/factotum.py: error importing: <ImportError> No module named
> 'rfc822' (error at __init__.py:*) (glob)
> -  hgext/fetch.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/fsmonitor/watchmanclient.py: error importing module:
> <SystemError> Parent module 'hgext.fsmonitor' not loaded, cannot perform
> relative import (line *) (glob)
> -  hgext/gpg.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/graphlog.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/hgk.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/histedit.py: error importing module: <SyntaxError> invalid syntax
> (bundle*.py, line *) (line *) (glob)
> -  hgext/keyword.py: error importing: <ImportError> No module named
> 'BaseHTTPServer' (error at common.py:*) (glob)
> -  hgext/largefiles/basestore.py: error importing: <SyntaxError> invalid
> syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
> -  hgext/largefiles/lfcommands.py: error importing: <SyntaxError> invalid
> syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
> -  hgext/largefiles/lfutil.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/largefiles/localstore.py: error importing module: <ImportError>
> No module named 'lfutil' (line *) (glob)
> -  hgext/largefiles/overrides.py: error importing: <SyntaxError> invalid
> syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
> +  hgext/convert/bzr.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/common.py: error importing module: <ImportError> No
> module named 'cPickle' (line 10)
> +  hgext/convert/convcmd.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/cvs.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/cvsps.py: error importing module: <ImportError> No module
> named 'cPickle' (line 9)
> +  hgext/convert/darcs.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/filemap.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/git.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/gnuarch.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/hg.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/monotone.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/p4.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/convert/subversion.py: error importing module: <ImportError> No
> module named 'cPickle' (line 6)
> +  hgext/convert/transport.py: error importing module: <ImportError> No
> module named 'svn.client' (line 21)
> +  hgext/eol.py: error importing: <TypeError> encode() argument 1 must be
> str, not bytes (error at encoding.py:*) (glob)
> +  hgext/extdiff.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/factotum.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/fetch.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/fsmonitor/state.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/fsmonitor/watchmanclient.py: error importing: <TypeError>
> encode() argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/gpg.py: error importing: <TypeError> encode() argument 1 must be
> str, not bytes (error at encoding.py:*) (glob)
> +  hgext/graphlog.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/hgk.py: error importing: <TypeError> encode() argument 1 must be
> str, not bytes (error at encoding.py:*) (glob)
> +  hgext/highlight/highlight.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/histedit.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/keyword.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/largefiles/basestore.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/largefiles/lfcommands.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/largefiles/lfutil.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/largefiles/localstore.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/largefiles/overrides.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
>    hgext/largefiles/proto.py: error importing: <ImportError> No module
> named 'httplib' (error at httppeer.py:*) (glob)
> -  hgext/largefiles/remotestore.py: error importing: <SyntaxError> invalid
> syntax (bundle*.py, line *) (error at wireproto.py:*) (glob)
> -  hgext/largefiles/reposetup.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> +  hgext/largefiles/remotestore.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/largefiles/reposetup.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
>    hgext/largefiles/uisetup.py: error importing module: <SyntaxError>
> invalid syntax (archival.py, line *) (line *) (glob)
> -  hgext/largefiles/wirestore.py: error importing module: <ImportError> No
> module named 'lfutil' (line *) (glob)
> -  hgext/mq.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/notify.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/pager.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/patchbomb.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/purge.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/rebase.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/record.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/relink.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/schemes.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/share.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/shelve.py: error importing module: <SyntaxError> invalid syntax
> (bundle*.py, line *) (line *) (glob)
> -  hgext/strip.py: error importing: <AttributeError> 'dict' object has no
> attribute 'iteritems' (error at revset.py:*) (glob)
> -  hgext/transplant.py: error importing: <SyntaxError> invalid syntax
> (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
> +  hgext/largefiles/wirestore.py: error importing module: <ImportError> No
> module named 'lfutil' (line 8)
> +  hgext/mq.py: error importing: <TypeError> encode() argument 1 must be
> str, not bytes (error at encoding.py:*) (glob)
> +  hgext/notify.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/pager.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/patchbomb.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/purge.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/rebase.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/record.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/relink.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/schemes.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/share.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/shelve.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/strip.py: error importing: <TypeError> encode() argument 1 must
> be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/transplant.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/win32mbcs.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  hgext/win32text.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
>    mercurial/archival.py: invalid syntax: invalid syntax (<unknown>, line
> *) (glob)
> -  mercurial/branchmap.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> +  mercurial/bookmarks.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/branchmap.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
>    mercurial/bundle*.py: invalid syntax: invalid syntax (<unknown>, line
> *) (glob)
> -  mercurial/bundlerepo.py: error importing module: <SyntaxError> invalid
> syntax (bundle*.py, line *) (line *) (glob)
> -  mercurial/changegroup.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/changelog.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/cmdutil.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> +  mercurial/bundlerepo.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/byterange.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/changegroup.py: error importing: <TypeError> encode()
> argument 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/changelog.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/cmdutil.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.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/context.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/copies.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/crecord.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/dirstate.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/discovery.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/dispatch.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/exchange.py: error importing module: <SyntaxError> invalid
> syntax (bundle*.py, line *) (line *) (glob)
> -  mercurial/extensions.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/filelog.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/filemerge.py: error importing: <ImportError> No module named
> 'cPickle' (error at formatter.py:*) (glob)
> -  mercurial/fileset.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/formatter.py: error importing module: <ImportError> No module
> named 'cPickle' (line *) (glob)
> -  mercurial/graphmod.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/help.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/hg.py: error importing: <SyntaxError> invalid syntax
> (bundle*.py, line *) (error at bundlerepo.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: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/httpconnection.py: error importing: <ImportError> No module
> named 'rfc822' (error at __init__.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: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/mail.py: error importing module: <AttributeError> module
> 'email' has no attribute 'Header' (line *) (glob)
> -  mercurial/manifest.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/merge.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/namespaces.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/patch.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/pure/mpatch.py: error importing module: <ImportError> cannot
> import name 'pycompat' (line *) (glob)
> -  mercurial/pure/parsers.py: error importing module: <ImportError> No
> module named 'mercurial.pure.node' (line *) (glob)
> +  mercurial/commandserver.py: error importing module: <ImportError> No
> module named 'SocketServer' (line 10)
> +  mercurial/config.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/context.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/copies.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/crecord.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/dagparser.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/dagutil.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/destutil.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/dirstate.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/discovery.py: error importing: <TypeError> encode() argument
> 1 must be str, not bytes (error at encoding.py:*) (glob)
> +  mercurial/dispatch.py: error importing: <TypeError> encode() argument 1
> must be str, not bytes (error at encoding.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 module: <ImportError> No module
> named 'cPickle' (line 10)
> +  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/hgweb/common.py: error importing module: <ImportError> No
> module named 'BaseHTTPServer' (line 11)
> +  mercurial/hgweb/hgweb_mod.py: error importing module: <SystemError>
> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import
> (line 14)
> +  mercurial/hgweb/hgwebdir_mod.py: error importing module: <SystemError>
> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import
> (line 15)
> +  mercurial/hgweb/protocol.py: error importing module: <SystemError>
> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import
> (line 13)
> +  mercurial/hgweb/request.py: error importing module: <SystemError>
> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import
> (line 15)
> +  mercurial/hgweb/server.py: error importing module: <ImportError> No
> module named 'BaseHTTPServer' (line 11)
> +  mercurial/hgweb/webcommands.py: error importing module: <SystemError>
> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import
> (line 16)
> +  mercurial/hgweb/webutil.py: error importing module: <SystemError>
> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import
> (line 16)
> +  mercurial/hgweb/wsgicgi.py: error importing module: <SystemError>
> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import
> (line 16)
> +  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/httppeer.py: error importing module: <ImportError> No module
> named 'httplib' (line 12)
> +  mercurial/keepalive.py: error importing module: <ImportError> No module
> named 'httplib' (line 113)
> +  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)
> +  mercurial/merge.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/minirst.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/namespaces.py: error importing: <TypeError> '_fields_' must
> be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/obsolete.py: error importing: <TypeError> getattr():
> attribute name must be string (error at pycompat.py:*) (glob)
> +  mercurial/patch.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/pathutil.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/peer.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/pure/mpatch.py: error importing module: <ImportError> cannot
> import name 'pycompat' (line 12)
> +  mercurial/pure/parsers.py: error importing module: <ImportError> No
> module named 'mercurial.pure.node' (line 13)
> +  mercurial/pushkey.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/pvec.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/registrar.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
>    mercurial/repair.py: error importing module: <SyntaxError> invalid
> syntax (bundle*.py, line *) (line *) (glob)
> -  mercurial/revlog.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/revset.py: error importing module: <AttributeError> 'dict'
> object has no attribute 'iteritems' (line *) (glob)
> -  mercurial/scmutil.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/scmwindows.py: error importing module: <ImportError> No
> module named '_winreg' (line *) (glob)
> -  mercurial/simplemerge.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/sshpeer.py: error importing: <SyntaxError> invalid syntax
> (bundle*.py, line *) (error at wireproto.py:*) (glob)
> -  mercurial/sshserver.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/statichttprepo.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/store.py: error importing: <AttributeError> 'dict' object has
> no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/streamclone.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/subrepo.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/templatefilters.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/templatekw.py: error importing: <AttributeError> 'dict'
> object has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/templater.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/ui.py: error importing: <ImportError> No module named
> 'cPickle' (error at formatter.py:*) (glob)
> -  mercurial/unionrepo.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/url.py: error importing module: <ImportError> No module named
> 'httplib' (line *) (glob)
> -  mercurial/verify.py: error importing: <AttributeError> 'dict' object
> has no attribute 'iteritems' (error at revset.py:*) (glob)
> -  mercurial/win*.py: error importing module: <ImportError> No module
> named 'msvcrt' (line *) (glob)
> -  mercurial/windows.py: error importing module: <ImportError> No module
> named '_winreg' (line *) (glob)
> +  mercurial/repoview.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/revlog.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/revset.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/scmposix.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/scmutil.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/scmwindows.py: error importing module: <ImportError> No
> module named '_winreg' (line 3)
> +  mercurial/similar.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/simplemerge.py: error importing: <TypeError> '_fields_' must
> be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/sshpeer.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/sshserver.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/sslutil.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/statichttprepo.py: error importing: <TypeError> '_fields_'
> must be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/store.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/streamclone.py: error importing: <TypeError> '_fields_' must
> be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/subrepo.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/tagmerge.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/tags.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/templatefilters.py: error importing: <TypeError> '_fields_'
> must be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/templatekw.py: error importing: <TypeError> '_fields_' must
> be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/templater.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/transaction.py: error importing: <TypeError> '_fields_' must
> be a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/ui.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/unionrepo.py: error importing: <TypeError> '_fields_' must be
> a sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/url.py: error importing module: <ImportError> No module named
> 'httplib' (line 13)
> +  mercurial/util.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/verify.py: error importing: <TypeError> '_fields_' must be a
> sequence of (name, C type) pairs (error at osutil.py:*) (glob)
> +  mercurial/win32.py: error importing module: <ImportError> No module
> named 'msvcrt' (line 12)
> +  mercurial/windows.py: error importing module: <ImportError> No module
> named '_winreg' (line 10)
>    mercurial/wireproto.py: error importing module: <SyntaxError> invalid
> syntax (bundle*.py, line *) (line *) (glob)
>
>  #endif
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20160606/96226eeb/attachment.html>


More information about the Mercurial-devel mailing list