# HG changeset patch # User Martijn Pieters # Date 1466702485 -3600 # Node ID 6d96658a22b0fc1eb210c99c5629dd69fedf3006 # Parent 50269a4dce6118a9e156170b7e1925417b320d8a atomictempfile: add context manager support Close the file (moving it in place) on clean context exit, discard when there has been an exception. diff -r 50269a4dce61 -r 6d96658a22b0 mercurial/util.py --- a/mercurial/util.py Thu Jun 23 18:20:58 2016 +0100 +++ b/mercurial/util.py Thu Jun 23 18:21:25 2016 +0100 @@ -1516,6 +1516,15 @@ if safehasattr(self, '_fp'): # constructor actually did something self.discard() + def __enter__(self): + return self + + def __exit__(self, exctype, excvalue, traceback): + if exctype is not None: + self.discard() + else: + self.close() + def makedirs(name, mode=None, notindexed=False): """recursive directory creation with parent mode inheritance diff -r 50269a4dce61 -r 6d96658a22b0 tests/test-atomictempfile.py --- a/tests/test-atomictempfile.py Thu Jun 23 18:20:58 2016 +0100 +++ b/tests/test-atomictempfile.py Thu Jun 23 18:21:25 2016 +0100 @@ -96,6 +96,24 @@ self.assertTrue(file.read(), b'foobar\n') file.discard() + def testcontextmanagersuccess(self): + """When the context closes, the file is closed""" + with atomictempfile('foo') as f: + self.assertFalse(os.path.isfile('foo')) + f.write(b'argh\n') + self.assertTrue(os.path.isfile('foo')) + + def testcontextmanagerfailure(self): + """On exception, the file is discarded""" + try: + with atomictempfile('foo') as f: + self.assertFalse(os.path.isfile('foo')) + f.write(b'argh\n') + raise ValueError + except ValueError: + pass + self.assertFalse(os.path.isfile('foo')) + if __name__ == '__main__': import silenttestrunner silenttestrunner.main(__name__)