Patchwork [4,of,4] atomictempfile: add context manager support

login
register
mail settings
Submitter Martijn Pieters
Date June 23, 2016, 5:24 p.m.
Message ID <7fe7962bb1ebd161e3c5.1466702693@mjpieters-mbp.dhcp.thefacebook.com>
Download mbox | patch
Permalink /patch/15590/
State Accepted
Headers show

Comments

Martijn Pieters - June 23, 2016, 5:24 p.m.
# HG changeset patch
# User Martijn Pieters <mjpieters@fb.com>
# Date 1466702485 -3600
#      Thu Jun 23 18:21:25 2016 +0100
# Node ID 7fe7962bb1ebd161e3c55600d39163869a5ab1ef
# Parent  79b315f113e47f7a9958dc538ba3a0f86a0e976b
atomictempfile: add context manager support

Close the file (moving it in place) on clean context exit, discard when there
has been an exception.
Pierre-Yves David - June 23, 2016, 6:38 p.m.
These are pushed, thanks.

On 06/23/2016 07:24 PM, Martijn Pieters wrote:
> # HG changeset patch
> # User Martijn Pieters <mjpieters@fb.com>
> # Date 1466702485 -3600
> #      Thu Jun 23 18:21:25 2016 +0100
> # Node ID 7fe7962bb1ebd161e3c55600d39163869a5ab1ef
> # Parent  79b315f113e47f7a9958dc538ba3a0f86a0e976b
> atomictempfile: add context manager support
> 
> Close the file (moving it in place) on clean context exit, discard when there
> has been an exception.
> 
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -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 --git a/tests/test-atomictempfile.py b/tests/test-atomictempfile.py
> --- a/tests/test-atomictempfile.py
> +++ b/tests/test-atomictempfile.py
> @@ -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__)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>

Patch

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -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 --git a/tests/test-atomictempfile.py b/tests/test-atomictempfile.py
--- a/tests/test-atomictempfile.py
+++ b/tests/test-atomictempfile.py
@@ -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__)