comparison mercurial/scmutil.py @ 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 07fc2f2134ba
children 4133a306606c
comparison
equal deleted inserted replaced
27705:2380889f8f52 27706:22e362da27cf
263 ''' 263 '''
264 self.open = self.__call__ 264 self.open = self.__call__
265 return self.__call__(path, mode, text, atomictemp, notindexed) 265 return self.__call__(path, mode, text, atomictemp, notindexed)
266 266
267 def read(self, path): 267 def read(self, path):
268 fp = self(path, 'rb') 268 with self(path, 'rb') as fp:
269 try:
270 return fp.read() 269 return fp.read()
271 finally:
272 fp.close()
273 270
274 def readlines(self, path, mode='rb'): 271 def readlines(self, path, mode='rb'):
275 fp = self(path, mode=mode) 272 with self(path, mode=mode) as fp:
276 try:
277 return fp.readlines() 273 return fp.readlines()
278 finally:
279 fp.close()
280 274
281 def write(self, path, data): 275 def write(self, path, data):
282 fp = self(path, 'wb') 276 with self(path, 'wb') as fp:
283 try:
284 return fp.write(data) 277 return fp.write(data)
285 finally:
286 fp.close()
287 278
288 def writelines(self, path, data, mode='wb', notindexed=False): 279 def writelines(self, path, data, mode='wb', notindexed=False):
289 fp = self(path, mode=mode, notindexed=notindexed) 280 with self(path, mode=mode, notindexed=notindexed) as fp:
290 try:
291 return fp.writelines(data) 281 return fp.writelines(data)
292 finally:
293 fp.close()
294 282
295 def append(self, path, data): 283 def append(self, path, data):
296 fp = self(path, 'ab') 284 with self(path, 'ab') as fp:
297 try:
298 return fp.write(data) 285 return fp.write(data)
299 finally:
300 fp.close()
301 286
302 def basename(self, path): 287 def basename(self, path):
303 """return base element of a path (as os.path.basename would do) 288 """return base element of a path (as os.path.basename would do)
304 289
305 This exists to allow handling of strange encoding if needed.""" 290 This exists to allow handling of strange encoding if needed."""
524 util.unlink(f) 509 util.unlink(f)
525 nlink = 0 510 nlink = 0
526 else: 511 else:
527 # nlinks() may behave differently for files on Windows 512 # nlinks() may behave differently for files on Windows
528 # shares if the file is open. 513 # shares if the file is open.
529 fd = util.posixfile(f) 514 with util.posixfile(f):
530 nlink = util.nlinks(f) 515 nlink = util.nlinks(f)
531 if nlink < 1: 516 if nlink < 1:
532 nlink = 2 # force mktempcopy (issue1922) 517 nlink = 2 # force mktempcopy (issue1922)
533 fd.close()
534 except (OSError, IOError) as e: 518 except (OSError, IOError) as e:
535 if e.errno != errno.ENOENT: 519 if e.errno != errno.ENOENT:
536 raise 520 raise
537 nlink = 0 521 nlink = 0
538 util.ensuredirs(dirname, self.createmode, notindexed) 522 util.ensuredirs(dirname, self.createmode, notindexed)
1045 hint=_("see https://mercurial-scm.org/wiki/MissingRequirement" 1029 hint=_("see https://mercurial-scm.org/wiki/MissingRequirement"
1046 " for more information")) 1030 " for more information"))
1047 return requirements 1031 return requirements
1048 1032
1049 def writerequires(opener, requirements): 1033 def writerequires(opener, requirements):
1050 reqfile = opener("requires", "w") 1034 with opener('requires', 'w') as fp:
1051 for r in sorted(requirements): 1035 for r in sorted(requirements):
1052 reqfile.write("%s\n" % r) 1036 fp.write("%s\n" % r)
1053 reqfile.close()
1054 1037
1055 class filecachesubentry(object): 1038 class filecachesubentry(object):
1056 def __init__(self, path, stat): 1039 def __init__(self, path, stat):
1057 self.path = path 1040 self.path = path
1058 self.cachestat = None 1041 self.cachestat = None