summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2017-07-04 04:55:45 (GMT)
committerGitHub <noreply@github.com>2017-07-04 04:55:45 (GMT)
commit1a3bc5546aa27f01426ad76618a9b2c3b698ae68 (patch)
tree40ddc1d65316a424ff81b500e1376bb4b778871c
parent0b1210739d12c26e4a161ffd494bd572d49b2483 (diff)
downloadcpython-1a3bc5546aa27f01426ad76618a9b2c3b698ae68.zip
cpython-1a3bc5546aa27f01426ad76618a9b2c3b698ae68.tar.gz
cpython-1a3bc5546aa27f01426ad76618a9b2c3b698ae68.tar.bz2
[3.5] bpo-30441: Fix bug when modifying os.environ while iterating over it (GH-2409). (#2557)
(cherry picked from commit 8a8d28501fc8ce25926d168f1c657656c809fd4c)
-rw-r--r--Lib/os.py4
-rw-r--r--Lib/test/test_os.py24
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS.d/next/Library/2017-06-29-14-25-14.bpo-30441.3Wh9kc.rst1
4 files changed, 29 insertions, 1 deletions
diff --git a/Lib/os.py b/Lib/os.py
index 011285e..b1add54 100644
--- 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):
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index e9c8507..6dc05eb 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -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()."""
diff --git a/Misc/ACKS b/Misc/ACKS
index 7f9044a..5440326 100644
--- 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
index 0000000..55dd613
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-06-29-14-25-14.bpo-30441.3Wh9kc.rst
@@ -0,0 +1 @@
+Fix bug when modifying os.environ while iterating over it