On Tue, Aug 16, 2016 at 05:50:46PM +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <y...@tcha.org>
> # Date 1471318515 -32400
> #      Tue Aug 16 12:35:15 2016 +0900
> # Node ID 30c0fc2f9d07b0251e24ff1a61a23416038022c4
> # Parent  82f7a2639ea514b22a2cbb2000740dce513663e2
> py3: import builtin wrappers automagically by code transformer

Queued these, thanks

>
> This should be less invasive than mucking builtins.
>
> Since tokenize.untokenize() looks start/end positions of tokens, we calculates
> them from the NEWLINE token of the future import.
>
> diff --git a/mercurial/__init__.py b/mercurial/__init__.py
> --- a/mercurial/__init__.py
> +++ b/mercurial/__init__.py
> @@ -170,7 +170,7 @@ if sys.version_info[0] >= 3:
>              spec.loader = hgloader(spec.name, spec.origin)
>              return spec
>
> -    def replacetokens(tokens):
> +    def replacetokens(tokens, fullname):
>          """Transform a stream of tokens from raw to Python 3.
>
>          It is called by the custom module loading machinery to rewrite
> @@ -184,6 +184,7 @@ if sys.version_info[0] >= 3:
>          REMEMBER TO CHANGE ``BYTECODEHEADER`` WHEN CHANGING THIS FUNCTION
>          OR CACHED FILES WON'T GET INVALIDATED PROPERLY.
>          """
> +        futureimpline = False
>          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.
> @@ -217,6 +218,29 @@ if sys.version_info[0] >= 3:
>                                            t.line)
>                  continue
>
> +            # Insert compatibility imports at "from __future__ import" line.
> +            # No '\n' should be added to preserve line numbers.
> +            if (t.type == token.NAME and t.string == 'import' and
> +                all(u.type == token.NAME for u in tokens[i - 2:i]) and
> +                [u.string for u in tokens[i - 2:i]] == ['from', 
> '__future__']):
> +                futureimpline = True
> +            if t.type == token.NEWLINE and futureimpline:
> +                futureimpline = False
> +                if fullname == 'mercurial.pycompat':
> +                    yield t
> +                    continue
> +                r, c = t.start
> +                l = (b'; from mercurial.pycompat import '
> +                     b'delattr, getattr, hasattr, setattr, xrange\n')
> +                for u in tokenize.tokenize(io.BytesIO(l).readline):
> +                    if u.type in (tokenize.ENCODING, token.ENDMARKER):
> +                        continue
> +                    yield tokenize.TokenInfo(u.type, u.string,
> +                                             (r, c + u.start[1]),
> +                                             (r, c + u.end[1]),
> +                                             '')
> +                continue
> +
>              try:
>                  nexttoken = tokens[i + 1]
>              except IndexError:
> @@ -279,7 +303,7 @@ if sys.version_info[0] >= 3:
>      # ``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.
> @@ -338,7 +362,7 @@ if sys.version_info[0] >= 3:
>              """Perform token transformation before compilation."""
>              buf = io.BytesIO(data)
>              tokens = tokenize.tokenize(buf.readline)
> -            data = tokenize.untokenize(replacetokens(list(tokens)))
> +            data = tokenize.untokenize(replacetokens(list(tokens), 
> self.name))
>              # 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
> diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
> --- a/mercurial/pycompat.py
> +++ b/mercurial/pycompat.py
> @@ -32,7 +32,6 @@ else:
>  if sys.version_info[0] >= 3:
>      import builtins
>      import functools
> -    builtins.xrange = range
>
>      def _wrapattrfunc(f):
>          @functools.wraps(f)
> @@ -42,10 +41,12 @@ if sys.version_info[0] >= 3:
>              return f(object, name, *args)
>          return w
>
> +    # these wrappers are automagically imported by hgloader
>      delattr = _wrapattrfunc(builtins.delattr)
>      getattr = _wrapattrfunc(builtins.getattr)
>      hasattr = _wrapattrfunc(builtins.hasattr)
>      setattr = _wrapattrfunc(builtins.setattr)
> +    xrange = builtins.range
>
>  stringio = io.StringIO
>  empty = _queue.Empty
> 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
> @@ -122,48 +122,49 @@
>    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: <TypeError> str expected, not 
> bytes (error at i18n.py:*) (glob)
> -  mercurial/keepalive.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/localrepo.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/lock.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/mail.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/manifest.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/match.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/mdiff.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/merge.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/minirst.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/namespaces.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/obsolete.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/patch.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/pathutil.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/peer.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/pushkey.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/pvec.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/registrar.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/repair.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/repoview.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/revlog.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/revset.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/scmutil.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/scmwindows.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/similar.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/simplemerge.py: error importing: <TypeError> getattr(): 
> attribute name must be string (error at util.py:*) (glob)
> -  mercurial/sshpeer.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/sshserver.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/sslutil.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/statichttprepo.py: error importing: <TypeError> getattr(): 
> attribute name must be string (error at util.py:*) (glob)
> -  mercurial/store.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/streamclone.py: error importing: <TypeError> getattr(): 
> attribute name must be string (error at util.py:*) (glob)
> -  mercurial/subrepo.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/tagmerge.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/tags.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/templatefilters.py: error importing: <TypeError> getattr(): 
> attribute name must be string (error at util.py:*) (glob)
> -  mercurial/templatekw.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/templater.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/transaction.py: error importing: <TypeError> getattr(): 
> attribute name must be string (error at util.py:*) (glob)
> -  mercurial/ui.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/unionrepo.py: error importing: <TypeError> getattr(): attribute 
> name must be string (error at util.py:*) (glob)
> -  mercurial/url.py: error importing: <TypeError> getattr(): attribute name 
> must be string (error at util.py:*) (glob)
> -  mercurial/verify.py: error importing: <TypeError> attribute name must be 
> string, not 'bytes' (error at mdiff.py:*) (glob)
> +  mercurial/keepalive.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/localrepo.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/lock.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/mail.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/manifest.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/match.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/mdiff.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/merge.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/minirst.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/namespaces.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/obsolete.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/patch.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/pathutil.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/peer.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/profiling.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/pushkey.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/pvec.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/registrar.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/repair.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/repoview.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/revlog.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/revset.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/scmutil.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/scmwindows.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/similar.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/simplemerge.py: error importing: <TypeError> __slots__ items 
> must be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/sshpeer.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/sshserver.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/sslutil.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/statichttprepo.py: error importing: <TypeError> __slots__ items 
> must be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/store.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/streamclone.py: error importing: <TypeError> __slots__ items 
> must be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/subrepo.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/tagmerge.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/tags.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/templatefilters.py: error importing: <TypeError> __slots__ items 
> must be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/templatekw.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/templater.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/transaction.py: error importing: <TypeError> __slots__ items 
> must be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/ui.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/unionrepo.py: error importing: <TypeError> __slots__ items must 
> be strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/url.py: error importing: <TypeError> __slots__ items must be 
> strings, not 'bytes' (error at util.py:*) (glob)
> +  mercurial/verify.py: error importing module: <TypeError> unorderable 
> types: str() >= tuple() (line *) (glob)
>    mercurial/win32.py: error importing module: <ImportError> No module named 
> 'msvcrt' (line *) (glob)
>    mercurial/windows.py: error importing module: <ImportError> No module 
> named 'msvcrt' (line *) (glob)
>    mercurial/wireproto.py: error importing module: <TypeError> unorderable 
> types: str() >= tuple() (line *) (glob)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to