Skip to content

Commit

Permalink
Ensure Monkeypatch setenv and delenv keep bytes keys in Python 2
Browse files Browse the repository at this point in the history
Fixes the bug described in:

	tox-dev/tox#1025 (comment)

Which is more evident when using `unicode_literals`.
  • Loading branch information
nicoddemus committed Sep 30, 2018
1 parent b1fbb2a commit a664fb2
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
4 changes: 4 additions & 0 deletions changelog/4056.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Ensure ``MonkeyPatch.setenv`` and ``MonkeyPatch.delenv`` use native strings for environment variable names.

In Python 2, adding ``unicode`` keys to ``os.environ`` causes problems with ``subprocess`` (and possible other modules),
making this a subtle bug specially susceptible when used with ``from __future__ import unicode_literals``.
4 changes: 2 additions & 2 deletions src/_pytest/monkeypatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def setenv(self, name, value, prepend=None):
value = str(value)
if prepend and name in os.environ:
value = value + prepend + os.environ[name]
self.setitem(os.environ, name, value)
self.setitem(os.environ, str(name), value)

def delenv(self, name, raising=True):
""" Delete ``name`` from the environment. Raise KeyError if it does
Expand All @@ -225,7 +225,7 @@ def delenv(self, name, raising=True):
If ``raising`` is set to False, no exception will be raised if the
environment variable is missing.
"""
self.delitem(os.environ, name, raising=raising)
self.delitem(os.environ, str(name), raising=raising)

def syspath_prepend(self, path):
""" Prepend ``path`` to ``sys.path`` list of import locations. """
Expand Down
36 changes: 36 additions & 0 deletions testing/test_monkeypatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import sys
import textwrap

import six

import pytest
from _pytest.monkeypatch import MonkeyPatch

Expand Down Expand Up @@ -192,6 +194,40 @@ def test_delenv():
del os.environ[name]


@pytest.mark.skipif(six.PY3, reason="python 2 only bug")
class TestPython2BytesEnvironKeys(object):
"""
In Python 2, os.environ keys need to be bytes, otherwise this will cause problems with other modules (notably
subprocess).
"""

VAR_NAME = "PYTEST_INTERNAL_MY_VAR"

@pytest.fixture(autouse=True)
def cleanup(self):
self.check_all_environ_keys_are_bytes()
yield
if self.VAR_NAME in os.environ:
del os.environ[self.VAR_NAME]

def check_all_environ_keys_are_bytes(self):
for k in os.environ:
assert type(k) is bytes

def test_setenv_unicode_key(self):
monkeypatch = MonkeyPatch()
monkeypatch.setenv(unicode(self.VAR_NAME), "2") # noqa
self.check_all_environ_keys_are_bytes()

def test_delenv_unicode_key(self):
os.environ[self.VAR_NAME] = "1"
self.check_all_environ_keys_are_bytes()
monkeypatch = MonkeyPatch()
monkeypatch.delenv(unicode(self.VAR_NAME)) # noqa
monkeypatch.undo()
self.check_all_environ_keys_are_bytes()


def test_setenv_prepend():
import os

Expand Down

0 comments on commit a664fb2

Please sign in to comment.