Mercurial > hg
changeset 39820:68ea1f8dcb84
py3: proxy posixfile objects to re-add a useful 'name' attribute on Windows
This file object is used in the vfs layer, so there are many errors like this:
...
File "mercurial\localrepo.py", line 2569, in savecommitmessage
return self.pathto(fp.name[len(self.root) + 1:])
TypeError: 'int' object is not subscriptable
It looks like the 'name' value is actually the fileno() value, and the
documentation says the name parameter to PyFile_FromFd() is ignored. [1] I
tried just assigning the attribute after osutil.posixfile() returns, but that
crashes saying that it's read-only.
[1] https://docs.python.org/3.6/c-api/file.html
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Fri, 21 Sep 2018 20:03:07 -0400 |
parents | fb628c048d64 |
children | 6787dc1b93a9 |
files | mercurial/windows.py |
diffstat | 1 files changed, 25 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/windows.py Sun Sep 23 22:36:44 2018 -0400 +++ b/mercurial/windows.py Fri Sep 21 20:03:07 2018 -0400 @@ -123,11 +123,36 @@ object.__setattr__(self, r'_lastop', self.OPREAD) return self._fp.readlines(*args, **kwargs) +class fdproxy(object): + """Wraps osutil.posixfile() to override the name attribute to reflect the + underlying file name. + """ + def __init__(self, name, fp): + self.name = name + self._fp = fp + + def __enter__(self): + return self._fp.__enter__() + + def __exit__(self, exc_type, exc_value, traceback): + self._fp.__exit__(exc_type, exc_value, traceback) + + def __iter__(self): + return iter(self._fp) + + def __getattr__(self, name): + return getattr(self._fp, name) + def posixfile(name, mode='r', buffering=-1): '''Open a file with even more POSIX-like semantics''' try: fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError + # PyFile_FromFd() ignores the name, and seems to report fp.name as the + # underlying file descriptor. + if pycompat.ispy3: + fp = fdproxy(name, fp) + # The position when opening in append mode is implementation defined, so # make it consistent with other platforms, which position at EOF. if 'a' in mode: