diff options
author | Osvaldo Santana Neto <osantana@users.noreply.github.com> | 2017-07-01 14:34:45 -0300 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-07-01 20:34:45 +0300 |
commit | 8a8d28501fc8ce25926d168f1c657656c809fd4c (patch) | |
tree | e987cc31628e5c5dd7c4d07fafc9e0464659f0b3 | |
parent | bpo-30695: Add set_nomemory(start, stop) to _testcapi (GH-2406) (diff) | |
download | cpython-8a8d28501fc8ce25926d168f1c657656c809fd4c.tar.gz cpython-8a8d28501fc8ce25926d168f1c657656c809fd4c.tar.bz2 cpython-8a8d28501fc8ce25926d168f1c657656c809fd4c.zip |
bpo-30441: Fix bug when modifying os.environ while iterating over it (#2409)
-rw-r--r-- | Lib/os.py | 4 | ||||
-rw-r--r-- | Lib/test/test_os.py | 24 | ||||
-rw-r--r-- | Misc/ACKS | 1 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2017-06-29-14-25-14.bpo-30441.3Wh9kc.rst | 1 |
4 files changed, 29 insertions, 1 deletions
diff --git a/Lib/os.py b/Lib/os.py index e293ecae7fd..807ddb56c06 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -697,7 +697,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 d06927073ed..49e5a37cd20 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -835,6 +835,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 910f8196a76..3455c1bc1a1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1088,6 +1088,7 @@ Fredrik Nehr Tony Nelson Trent Nelson Andrew Nester +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 00000000000..55dd6136c8d --- /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 |