py3: wrap tempfile.NamedTemporaryFile() to return bytes fp.name
authorYuya Nishihara <yuya@tcha.org>
Sat, 26 May 2018 12:38:07 +0900
changeset 38166 cc9aa88792fe
parent 38165 2ce60954b1b7
child 38167 ec37df9042f9
py3: wrap tempfile.NamedTemporaryFile() to return bytes fp.name Unlike its name, tempfile.NamedTemporaryFile is not a class, so I renamed the pycompat version to look like a plain function. Since temp.name uses in the infinitepush extension aren't bytes-safe, this patch leaves them unmodified. Another weird thing is tempfile.mktemp(), which does not accept bytes suffix nor prefix. Sigh.
hgext/infinitepush/store.py
mercurial/debugcommands.py
mercurial/posix.py
mercurial/pycompat.py
--- a/hgext/infinitepush/store.py	Sat May 26 12:20:36 2018 +0900
+++ b/hgext/infinitepush/store.py	Sat May 26 12:38:07 2018 +0900
@@ -120,6 +120,8 @@
     def write(self, data):
         # Won't work on windows because you can't open file second time without
         # closing it
+        # TODO: rewrite without str.format() and replace NamedTemporaryFile()
+        # with pycompat.namedtempfile()
         with NamedTemporaryFile() as temp:
             temp.write(data)
             temp.flush()
@@ -142,6 +144,8 @@
     def read(self, handle):
         # Won't work on windows because you can't open file second time without
         # closing it
+        # TODO: rewrite without str.format() and replace NamedTemporaryFile()
+        # with pycompat.namedtempfile()
         with NamedTemporaryFile() as temp:
             formatted_args = [arg.format(filename=temp.name, handle=handle)
                               for arg in self.get_args]
--- a/mercurial/debugcommands.py	Sat May 26 12:20:36 2018 +0900
+++ b/mercurial/debugcommands.py	Sat May 26 12:38:07 2018 +0900
@@ -21,7 +21,6 @@
 import string
 import subprocess
 import sys
-import tempfile
 import time
 
 from .i18n import _
@@ -970,7 +969,7 @@
     ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
     casesensitive = '(unknown)'
     try:
-        with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
+        with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
             casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
     except OSError:
         pass
--- a/mercurial/posix.py	Sat May 26 12:20:36 2018 +0900
+++ b/mercurial/posix.py	Sat May 26 12:38:07 2018 +0900
@@ -249,16 +249,15 @@
         else:
             checkdir = path
             cachedir = None
-        fscheckdir = pycompat.fsdecode(checkdir)
-        name = tempfile.mktemp(dir=fscheckdir,
+        name = tempfile.mktemp(dir=pycompat.fsdecode(checkdir),
                                prefix=r'checklink-')
         name = pycompat.fsencode(name)
         try:
             fd = None
             if cachedir is None:
-                fd = tempfile.NamedTemporaryFile(dir=fscheckdir,
-                                                 prefix=r'hg-checklink-')
-                target = pycompat.fsencode(os.path.basename(fd.name))
+                fd = pycompat.namedtempfile(dir=checkdir,
+                                            prefix='hg-checklink-')
+                target = os.path.basename(fd.name)
             else:
                 # create a fixed file to link to; doesn't matter if it
                 # already exists.
--- a/mercurial/pycompat.py	Sat May 26 12:20:36 2018 +0900
+++ b/mercurial/pycompat.py	Sat May 26 12:38:07 2018 +0900
@@ -392,3 +392,11 @@
 # text=True is not supported; use util.from/tonativeeol() instead
 def mkstemp(suffix=b'', prefix=b'tmp', dir=None):
     return tempfile.mkstemp(suffix, prefix, dir)
+
+# mode must include 'b'ytes as encoding= is not supported
+def namedtempfile(mode=b'w+b', bufsize=-1, suffix=b'', prefix=b'tmp', dir=None,
+                  delete=True):
+    mode = sysstr(mode)
+    assert r'b' in mode
+    return tempfile.NamedTemporaryFile(mode, bufsize, suffix=suffix,
+                                       prefix=prefix, dir=dir, delete=delete)