Mercurial > public > mercurial-scm > hg
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 |