[PATCH 4 of 4 RFC] pycompat: patch (del|get|has|set)attr to accept bytes on Python 3
Gregory Szorc
gregory.szorc at gmail.com
Sun Aug 14 12:27:16 EDT 2016
On Sun, Aug 14, 2016 at 2:33 AM, Yuya Nishihara <yuya at tcha.org> wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya at tcha.org>
> # Date 1471146681 -32400
> # Sun Aug 14 12:51:21 2016 +0900
> # Node ID 2a300f882c077fa014046db96b545f6aff771d32
> # Parent d53bd633898ec6edafccea9f798d314699faf90a
> pycompat: patch (del|get|has|set)attr to accept bytes on Python 3
>
> getattr() and setattr() are widely used in our code. We wouldn't probably
> want to rewrite every single call of getattr/setattr. delattr() and
> hasattr()
> aren't that important, but they are functions of the same kind.
>
> Another option would be util.(get|set)attr.
>
I'm generally opposed to modifying the behavior of stdlib functionality
because, well, it's modifying the stdlib. Extensions may load
packages/modules that rely on the default behavior, perhaps in subtle ways.
I would prefer proxy functions (possibly in util.py) over modifying the
standard library.
>
> diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
> --- a/mercurial/pycompat.py
> +++ b/mercurial/pycompat.py
> @@ -31,8 +31,27 @@ else:
>
> if sys.version_info[0] >= 3:
> import builtins
> + import functools
> builtins.xrange = range
>
> + def _wrapattrfunc(f):
> + try:
> + # avoid useless wrapping on reload
> + f.__wrapped__
> + return f
> + except AttributeError:
> + pass
> + @functools.wraps(f)
> + def w(object, name, *args):
> + if isinstance(name, bytes):
> + name = name.decode('utf-8')
> + return f(object, name, *args)
> + return w
> + builtins.delattr = _wrapattrfunc(builtins.delattr)
> + builtins.getattr = _wrapattrfunc(builtins.getattr)
> + builtins.hasattr = _wrapattrfunc(builtins.hasattr)
> + builtins.setattr = _wrapattrfunc(builtins.setattr)
> +
> stringio = io.StringIO
> empty = _queue.Empty
> queue = _queue.Queue
> 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,48 @@
> 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/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 at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20160814/81c4a68c/attachment.html>
More information about the Mercurial-devel
mailing list