]> granicus.if.org Git - python/commitdiff
[3.6] bpo-30197: Enhance functions swap_attr() and swap_item() in test.support. ...
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 28 Apr 2017 17:05:05 +0000 (20:05 +0300)
committerGitHub <noreply@github.com>
Fri, 28 Apr 2017 17:05:05 +0000 (20:05 +0300)
They now work when delete replaced attribute or item inside the with
statement.  The old value of the attribute or item (or None if it doesn't
exist) now will be assigned to the target of the "as" clause, if there is
one.

(cherry picked from commit d1a1def7bf221b04dcf3fc3a67aa19aa2f622f83)

Lib/test/support/__init__.py
Lib/test/test_support.py
Lib/test/test_tempfile.py
Misc/NEWS

index 2d60adc3dc0fd175ca8dc5ee2e340b4d10c356ae..f8d177990bfb03be93c9994f157b793ef614bc49 100644 (file)
@@ -2105,12 +2105,15 @@ def swap_attr(obj, attr, new_val):
         restoring the old value at the end of the block. If `attr` doesn't
         exist on `obj`, it will be created and then deleted at the end of the
         block.
+
+        The old value (or None if it doesn't exist) will be assigned to the
+        target of the "as" clause, if there is one.
     """
     if hasattr(obj, attr):
         real_val = getattr(obj, attr)
         setattr(obj, attr, new_val)
         try:
-            yield
+            yield real_val
         finally:
             setattr(obj, attr, real_val)
     else:
@@ -2118,7 +2121,8 @@ def swap_attr(obj, attr, new_val):
         try:
             yield
         finally:
-            delattr(obj, attr)
+            if hasattr(obj, attr):
+                delattr(obj, attr)
 
 @contextlib.contextmanager
 def swap_item(obj, item, new_val):
@@ -2132,12 +2136,15 @@ def swap_item(obj, item, new_val):
         restoring the old value at the end of the block. If `item` doesn't
         exist on `obj`, it will be created and then deleted at the end of the
         block.
+
+        The old value (or None if it doesn't exist) will be assigned to the
+        target of the "as" clause, if there is one.
     """
     if item in obj:
         real_val = obj[item]
         obj[item] = new_val
         try:
-            yield
+            yield real_val
         finally:
             obj[item] = real_val
     else:
@@ -2145,7 +2152,8 @@ def swap_item(obj, item, new_val):
         try:
             yield
         finally:
-            del obj[item]
+            if item in obj:
+                del obj[item]
 
 def strip_python_stderr(stderr):
     """Strip the stderr of a Python process from potential debug output
index e83a4d6426a8b2d05517eb76c77bb4e5220afd73..ddd65092312a3b495b08f9f062a44647c714eff8 100644 (file)
@@ -282,17 +282,34 @@ class TestSupport(unittest.TestCase):
 
     def test_swap_attr(self):
         class Obj:
-            x = 1
+            pass
         obj = Obj()
-        with support.swap_attr(obj, "x", 5):
+        obj.x = 1
+        with support.swap_attr(obj, "x", 5) as x:
             self.assertEqual(obj.x, 5)
+            self.assertEqual(x, 1)
         self.assertEqual(obj.x, 1)
+        with support.swap_attr(obj, "y", 5) as y:
+            self.assertEqual(obj.y, 5)
+            self.assertIsNone(y)
+        self.assertFalse(hasattr(obj, 'y'))
+        with support.swap_attr(obj, "y", 5):
+            del obj.y
+        self.assertFalse(hasattr(obj, 'y'))
 
     def test_swap_item(self):
-        D = {"item":1}
-        with support.swap_item(D, "item", 5):
-            self.assertEqual(D["item"], 5)
-        self.assertEqual(D["item"], 1)
+        D = {"x":1}
+        with support.swap_item(D, "x", 5) as x:
+            self.assertEqual(D["x"], 5)
+            self.assertEqual(x, 1)
+        self.assertEqual(D["x"], 1)
+        with support.swap_item(D, "y", 5) as y:
+            self.assertEqual(D["y"], 5)
+            self.assertIsNone(y)
+        self.assertNotIn("y", D)
+        with support.swap_item(D, "y", 5):
+            del D["y"]
+        self.assertNotIn("y", D)
 
     class RefClass:
         attribute1 = None
index 51df1ecd7d18e63e0f927cde322087f007d3eee5..d0cf04b0cb67ca5bac7887cd9cdef0c019c60f20 100644 (file)
@@ -273,13 +273,12 @@ class TestGetDefaultTempdir(BaseTestCase):
                         tempfile._get_default_tempdir()
                     self.assertEqual(os.listdir(our_temp_directory), [])
 
-                open = io.open
                 def bad_writer(*args, **kwargs):
-                    fp = open(*args, **kwargs)
+                    fp = orig_open(*args, **kwargs)
                     fp.write = raise_OSError
                     return fp
 
-                with support.swap_attr(io, "open", bad_writer):
+                with support.swap_attr(io, "open", bad_writer) as orig_open:
                     # test again with failing write()
                     with self.assertRaises(FileNotFoundError):
                         tempfile._get_default_tempdir()
index b1f79d612402811e5316390e6ce8b3a0b8f3f9a7..936e2b02017f8ed1523b556911d7fef0aa1c1a95 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -114,6 +114,15 @@ Documentation
 
 - bpo-26985: Add missing info of code object in inspect documentation.
 
+Tests
+-----
+
+- bpo-30197: Enhanced functions swap_attr() and swap_item() in the
+  test.support module.  They now work when delete replaced attribute or item
+  inside the with statement.  The old value of the attribute or item (or None
+  if it doesn't exist) now will be assigned to the target of the "as" clause,
+  if there is one.
+
 
 What's New in Python 3.6.1?
 ===========================