Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-30441: Fix bug when modifying os.environ while iterating over it #2409

Merged
merged 7 commits into from Jul 1, 2017
3 changes: 2 additions & 1 deletion Lib/os.py
Expand Up @@ -697,7 +697,8 @@ def __delitem__(self, key):
raise KeyError(key) from None

def __iter__(self):
for key in self._data:
data = list(self._data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either inline data or rename it to keys. Add an explaining comment about atomicity of list() from dict.

for key in data:
yield self.decodekey(key)

def __len__(self):
Expand Down
15 changes: 15 additions & 0 deletions Lib/test/test_os.py
Expand Up @@ -835,6 +835,21 @@ def test_key_type(self):
self.assertIs(cm.exception.args[0], missing)
self.assertTrue(cm.exception.__suppress_context__)

def test_iter_error_when_os_environ_changes(self):
def _iter_environ_change():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use iter(os.environ.items()).

It may be worth to test also other iterators: iter(os.environ) and iter(os.environ.values()).

for key, value in os.environ.items():
yield key, value

iter_environ = _iter_environ_change()
key, value = next(iter_environ) # start iteration over os.environ

# add a new key in os.environ mapping
new_key = "__{}".format(key)
os.environ[new_key] = value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to remove the added key.


next(iter_environ) # force iteration over modified mapping
self.assertEqual(os.environ[new_key], value)


class WalkTests(unittest.TestCase):
"""Tests for os.walk()."""
Expand Down