[PATCH 2 of 2 V3] encoding: use unicode literals to appease Python 3
Augie Fackler
raf at durin42.com
Tue Jul 12 16:38:02 UTC 2016
On Mon, Jul 04, 2016 at 11:44:10AM -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc at gmail.com>
> # Date 1467657692 25200
> # Mon Jul 04 11:41:32 2016 -0700
> # Node ID d0a5fd1255a1c7d9f09bcdc3d054e095a2e9bba9
> # Parent 99a1ac83fe44142a9793a93e55b41aa052954842
> encoding: use unicode literals to appease Python 3
I think this series is regrettable, but required. I'm happy with it,
but would like someone else to review.
>
> Various places in encoding.py related to encoding names and
> environment variables were expecting unicode/str types, not
> bytes. This was causing various imports in Python 3 to fail
> with our new module loader.
>
> Add some u'' prefixes to prevent these literals from getting
> b'' prefixed by the loader so Python 3 imports don't fail
> as fast.
>
> The introduction of u'' on Python 2 could cause some implicit
> conversions between str and unicode types using the ascii encoding.
> However, values of HGENCODING, HGENCODINGMODE, and HGENCODINGAMBIGUOUS
> *should* be ASCII. So I think this is safe. The alternative is
> likely a helper function to access os.environ on Python 2 and
> os.environb on Python 3 and returns bytes everywhere. This could
> be done as a follow-up.
>
> diff --git a/mercurial/encoding.py b/mercurial/encoding.py
> --- a/mercurial/encoding.py
> +++ b/mercurial/encoding.py
> @@ -65,30 +65,30 @@ def _getpreferredencoding():
> oldloc = locale.setlocale(locale.LC_CTYPE)
> locale.setlocale(locale.LC_CTYPE, "")
> result = locale.nl_langinfo(locale.CODESET)
> locale.setlocale(locale.LC_CTYPE, oldloc)
>
> return result
>
> _encodingfixers = {
> - '646': lambda: 'ascii',
> - 'ANSI_X3.4-1968': lambda: 'ascii',
> - 'mac-roman': _getpreferredencoding
> + u'646': lambda: u'ascii',
> + u'ANSI_X3.4-1968': lambda: u'ascii',
> + u'mac-roman': _getpreferredencoding
> }
>
> try:
> - encoding = os.environ.get("HGENCODING")
> + encoding = os.environ.get(u'HGENCODING')
> if not encoding:
> - encoding = locale.getpreferredencoding() or 'ascii'
> + encoding = locale.getpreferredencoding() or u'ascii'
> encoding = _encodingfixers.get(encoding, lambda: encoding)()
> except locale.Error:
> - encoding = 'ascii'
> -encodingmode = os.environ.get("HGENCODINGMODE", "strict")
> -fallbackencoding = 'ISO-8859-1'
> + encoding = u'ascii'
> +encodingmode = os.environ.get(u'HGENCODINGMODE', u'strict')
> +fallbackencoding = u'ISO-8859-1'
>
> class localstr(str):
> '''This class allows strings that are unmodified to be
> round-tripped to the local encoding and back'''
> def __new__(cls, u, l):
> s = str.__new__(cls, l)
> s._utf8 = u
> return s
> @@ -175,18 +175,18 @@ def fromlocal(s):
> return s.decode(encoding, encodingmode).encode("utf-8")
> except UnicodeDecodeError as inst:
> sub = s[max(0, inst.start - 10):inst.start + 10]
> raise error.Abort("decoding near '%s': %s!" % (sub, inst))
> except LookupError as k:
> raise error.Abort(k, hint="please check your locale settings")
>
> # How to treat ambiguous-width characters. Set to 'wide' to treat as wide.
> -wide = (os.environ.get("HGENCODINGAMBIGUOUS", "narrow") == "wide"
> - and "WFA" or "WF")
> +wide = (os.environ.get(u'HGENCODINGAMBIGUOUS', u'narrow') == u'wide'
> + and u'WFA' or u'WF')
>
> def colwidth(s):
> "Find the column width of a string for display in the local encoding"
> return ucolwidth(s.decode(encoding, 'replace'))
>
> def ucolwidth(d):
> "Find the column width of a Unicode string for display"
> eaw = getattr(unicodedata, 'east_asian_width', None)
> 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,100 +19,100 @@
> 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> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/automv.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/blackbox.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/bugzilla.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/censor.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/chgserver.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/children.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/churn.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/clonebundles.py: error importing: <TypeError> str expected, not bytes (error at encoding.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: <TypeError> str expected, not bytes (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: <TypeError> str expected, not bytes (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> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/common.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/convcmd.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/cvs.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/cvsps.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/darcs.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/filemap.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/git.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/gnuarch.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/hg.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/monotone.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/p4.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/convert/subversion.py: error importing: <TypeError> str expected, not bytes (error at encoding.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> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/extdiff.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/factotum.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/fetch.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/fsmonitor/state.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/fsmonitor/watchmanclient.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/gpg.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/graphlog.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/hgk.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/highlight/highlight.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/histedit.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/journal.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/keyword.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/basestore.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/lfcommands.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/lfutil.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/localstore.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/overrides.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/proto.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/remotestore.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/reposetup.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/storefactory.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/largefiles/uisetup.py: error importing: <TypeError> str expected, not bytes (error at encoding.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/journal.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> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/notify.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/pager.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/patchbomb.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/purge.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/rebase.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/record.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/relink.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/schemes.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/share.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/shelve.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/strip.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/transplant.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/win32mbcs.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - hgext/win32text.py: error importing: <TypeError> str expected, not bytes (error at encoding.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> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/branchmap.py: error importing: <TypeError> str expected, not bytes (error at encoding.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> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/byterange.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/changegroup.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/changelog.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/cmdutil.py: error importing: <TypeError> str expected, not bytes (error at encoding.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: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/config.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/context.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/copies.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/crecord.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/dagparser.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/dagutil.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/destutil.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/dirstate.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/discovery.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> - mercurial/dispatch.py: error importing: <TypeError> str expected, not bytes (error at encoding.py:*) (glob)
> + mercurial/commandserver.py: error importing: <TypeError> str expected, not bytes (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-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list