]> granicus.if.org Git - python/commitdiff
[3.5] bpo-30441: Fix bug when modifying os.environ while iterating over it (GH-2409...
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 4 Jul 2017 04:55:45 +0000 (07:55 +0300)
committerGitHub <noreply@github.com>
Tue, 4 Jul 2017 04:55:45 +0000 (07:55 +0300)
(cherry picked from commit 8a8d28501fc8ce25926d168f1c657656c809fd4c)

Lib/os.py
Lib/test/test_os.py
Misc/ACKS
Misc/NEWS.d/next/Library/2017-06-29-14-25-14.bpo-30441.3Wh9kc.rst [new file with mode: 0644]

index 011285e74bd92b21d61c6c7bb9df2e69f3946fce..b1add54cf2f9c0f01cc2df56df3adff7c2ec57fd 100644 (file)
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -741,7 +741,9 @@ class _Environ(MutableMapping):
             raise KeyError(key) from None
 
     def __iter__(self):
-        for key in self._data:
+        # list() from dict object is an atomic operation
+        keys = list(self._data)
+        for key in keys:
             yield self.decodekey(key)
 
     def __len__(self):
index e9c850793a5d9bbbffebf60ec3a78289ee953374..6dc05eb7fde044f158efb8d4092b1aa7e14efc99 100644 (file)
@@ -809,6 +809,30 @@ class EnvironTests(mapping_tests.BasicTestMappingProtocol):
         self.assertIs(cm.exception.args[0], missing)
         self.assertTrue(cm.exception.__suppress_context__)
 
+    def _test_environ_iteration(self, collection):
+        iterator = iter(collection)
+        new_key = "__new_key__"
+
+        next(iterator)  # start iteration over os.environ.items
+
+        # add a new key in os.environ mapping
+        os.environ[new_key] = "test_environ_iteration"
+
+        try:
+            next(iterator)  # force iteration over modified mapping
+            self.assertEqual(os.environ[new_key], "test_environ_iteration")
+        finally:
+            del os.environ[new_key]
+
+    def test_iter_error_when_changing_os_environ(self):
+        self._test_environ_iteration(os.environ)
+
+    def test_iter_error_when_changing_os_environ_items(self):
+        self._test_environ_iteration(os.environ.items())
+
+    def test_iter_error_when_changing_os_environ_values(self):
+        self._test_environ_iteration(os.environ.values())
+
 
 class WalkTests(unittest.TestCase):
     """Tests for os.walk()."""
index 7f9044ac7cb6dab00b80555f4d1bbbdf56de6f54..5440326ac3346aa0a655ccb94f58c98f7371d0d0 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1056,6 +1056,7 @@ Vilmos Nebehaj
 Fredrik Nehr
 Tony Nelson
 Trent Nelson
+Osvaldo Santana Neto
 Chad Netzer
 Max Neunhöffer
 Anthon van der Neut
diff --git a/Misc/NEWS.d/next/Library/2017-06-29-14-25-14.bpo-30441.3Wh9kc.rst b/Misc/NEWS.d/next/Library/2017-06-29-14-25-14.bpo-30441.3Wh9kc.rst
new file mode 100644 (file)
index 0000000..55dd613
--- /dev/null
@@ -0,0 +1 @@
+Fix bug when modifying os.environ while iterating over it