]> granicus.if.org Git - python/commitdiff
bpo-30197: Enhance functions swap_attr() and swap_item() in test.support. (#1341)
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 28 Apr 2017 16:17:26 +0000 (19:17 +0300)
committerVictor Stinner <victor.stinner@gmail.com>
Fri, 28 Apr 2017 16:17:26 +0000 (18:17 +0200)
* bpo-30197: Enhance functions swap_attr() and swap_item() in test.support.

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.

* Update docstrings.

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

index ed611c96197c88cd73755a82d532a5d3012ec9f8..d8d599bad0f90c281657ba86e61f8daa087538ae 100644 (file)
@@ -2119,12 +2119,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:
@@ -2132,7 +2135,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):
@@ -2146,12 +2150,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:
@@ -2159,7 +2166,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 0dbe02eeb388b60f3d09779cf445b91cfc65f5fe..1e6b2b54e239542aebbd5fdfc2937df94f626585 100644 (file)
@@ -295,17 +295,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 71db0ee46b0dc483617d154a1541ad87b9e0f1e1..026beff1954e5e8152558c2fe51a382b90f147a5 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1107,6 +1107,12 @@ Tools/Demos
 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.
+
 - Issue #24932: Use proper command line parsing in _testembed
 
 - Issue #28950: Disallow -j0 to be combined with -T/-l in regrtest