changeset 27706:22e362da27cf

scmutil: use context managers for file handles Now that we dropped support for Python 2.4, we are able to use context managers. Let's replace the try..finally pattern in scmutil.py with context managers, which close files automatically when the context manager is exited. There should be no change in behavior with this patch. Why convert to context managers if nothing is broken? I'm working on closing file handles in background threads to improve performance on Windows. As part of this, I realized there could be some future issues if the background file closing code isn't designed with context managers in mind. So, I'd like to switch some code to context managers so I can design an API that works with context managers.
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 02 Jan 2016 15:19:47 -0800
parents 2380889f8f52
children 14f5ea7cc4c2
files mercurial/scmutil.py
diffstat 1 files changed, 12 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/scmutil.py	Sat Jan 02 15:33:01 2016 -0800
+++ b/mercurial/scmutil.py	Sat Jan 02 15:19:47 2016 -0800
@@ -265,39 +265,24 @@
         return self.__call__(path, mode, text, atomictemp, notindexed)
 
     def read(self, path):
-        fp = self(path, 'rb')
-        try:
+        with self(path, 'rb') as fp:
             return fp.read()
-        finally:
-            fp.close()
 
     def readlines(self, path, mode='rb'):
-        fp = self(path, mode=mode)
-        try:
+        with self(path, mode=mode) as fp:
             return fp.readlines()
-        finally:
-            fp.close()
 
     def write(self, path, data):
-        fp = self(path, 'wb')
-        try:
+        with self(path, 'wb') as fp:
             return fp.write(data)
-        finally:
-            fp.close()
 
     def writelines(self, path, data, mode='wb', notindexed=False):
-        fp = self(path, mode=mode, notindexed=notindexed)
-        try:
+        with self(path, mode=mode, notindexed=notindexed) as fp:
             return fp.writelines(data)
-        finally:
-            fp.close()
 
     def append(self, path, data):
-        fp = self(path, 'ab')
-        try:
+        with self(path, 'ab') as fp:
             return fp.write(data)
-        finally:
-            fp.close()
 
     def basename(self, path):
         """return base element of a path (as os.path.basename would do)
@@ -526,11 +511,10 @@
                     else:
                         # nlinks() may behave differently for files on Windows
                         # shares if the file is open.
-                        fd = util.posixfile(f)
-                        nlink = util.nlinks(f)
-                        if nlink < 1:
-                            nlink = 2 # force mktempcopy (issue1922)
-                        fd.close()
+                        with util.posixfile(f):
+                            nlink = util.nlinks(f)
+                            if nlink < 1:
+                                nlink = 2 # force mktempcopy (issue1922)
                 except (OSError, IOError) as e:
                     if e.errno != errno.ENOENT:
                         raise
@@ -1047,10 +1031,9 @@
     return requirements
 
 def writerequires(opener, requirements):
-    reqfile = opener("requires", "w")
-    for r in sorted(requirements):
-        reqfile.write("%s\n" % r)
-    reqfile.close()
+    with opener('requires', 'w') as fp:
+        for r in sorted(requirements):
+            fp.write("%s\n" % r)
 
 class filecachesubentry(object):
     def __init__(self, path, stat):