Use monkeypatch.setenv in config and option tests

This commit is contained in:
Nguyễn Gia Phong 2020-07-22 23:01:30 +07:00
parent 89a51a6fef
commit c564a3d541
5 changed files with 57 additions and 108 deletions

View File

@ -14,18 +14,6 @@ from pip._internal.utils.misc import ensure_dir
kinds = pip._internal.configuration.kinds
def reset_os_environ(old_environ):
"""
Reset os.environ while preserving the same underlying mapping.
"""
# Preserving the same mapping is preferable to assigning a new mapping
# because the latter has interfered with test isolation by, for example,
# preventing time.tzset() from working in subsequent tests after
# changing os.environ['TZ'] in those tests.
os.environ.clear()
os.environ.update(old_environ)
class ConfigurationMixin(object):
def setup(self):
@ -34,14 +22,10 @@ class ConfigurationMixin(object):
)
self._files_to_clear = []
self._old_environ = os.environ.copy()
def teardown(self):
for fname in self._files_to_clear:
fname.stop()
reset_os_environ(self._old_environ)
def patch_configuration(self, variant, di):
old = self.configuration._load_config_files

View File

@ -1,12 +1,9 @@
"""Provides helper classes for testing option handling in pip
"""
import os
from pip._internal.cli import cmdoptions
from pip._internal.cli.base_command import Command
from pip._internal.commands import CommandInfo, commands_dict
from tests.lib.configuration_helpers import reset_os_environ
class FakeCommand(Command):
@ -23,11 +20,9 @@ class FakeCommand(Command):
class AddFakeCommandMixin(object):
def setup(self):
self.environ_before = os.environ.copy()
commands_dict['fake'] = CommandInfo(
'tests.lib.options_helpers', 'FakeCommand', 'fake summary',
)
def teardown(self):
reset_os_environ(self.environ_before)
commands_dict.pop('fake')

View File

@ -1,8 +1,6 @@
"""Tests for all things related to the configuration
"""
import os
import pytest
from mock import MagicMock
@ -31,48 +29,48 @@ class TestConfigurationLoading(ConfigurationMixin):
self.configuration.load()
assert self.configuration.get_value("test.hello") == "3"
def test_environment_config_loading(self):
def test_environment_config_loading(self, monkeypatch):
contents = """
[test]
hello = 4
"""
with self.tmpfile(contents) as config_file:
os.environ["PIP_CONFIG_FILE"] = config_file
monkeypatch.setenv("PIP_CONFIG_FILE", config_file)
self.configuration.load()
assert self.configuration.get_value("test.hello") == "4", \
self.configuration._config
def test_environment_var_loading(self):
os.environ["PIP_HELLO"] = "5"
def test_environment_var_loading(self, monkeypatch):
monkeypatch.setenv("PIP_HELLO", "5")
self.configuration.load()
assert self.configuration.get_value(":env:.hello") == "5"
@pytest.mark.skipif("sys.platform == 'win32'")
def test_environment_var_does_not_load_lowercase(self):
os.environ["pip_hello"] = "5"
def test_environment_var_does_not_load_lowercase(self, monkeypatch):
monkeypatch.setenv("pip_hello", "5")
self.configuration.load()
with pytest.raises(ConfigurationError):
self.configuration.get_value(":env:.hello")
def test_environment_var_does_not_load_version(self):
os.environ["PIP_VERSION"] = "True"
def test_environment_var_does_not_load_version(self, monkeypatch):
monkeypatch.setenv("PIP_VERSION", "True")
self.configuration.load()
with pytest.raises(ConfigurationError):
self.configuration.get_value(":env:.version")
def test_environment_config_errors_if_malformed(self):
def test_environment_config_errors_if_malformed(self, monkeypatch):
contents = """
test]
hello = 4
"""
with self.tmpfile(contents) as config_file:
os.environ["PIP_CONFIG_FILE"] = config_file
monkeypatch.setenv("PIP_CONFIG_FILE", config_file)
with pytest.raises(ConfigurationError) as err:
self.configuration.load()
@ -130,36 +128,36 @@ class TestConfigurationPrecedence(ConfigurationMixin):
assert self.configuration.get_value("test.hello") == "2"
def test_env_not_overriden_by_environment_var(self):
def test_env_not_overriden_by_environment_var(self, monkeypatch):
self.patch_configuration(kinds.ENV, {"test.hello": "1"})
os.environ["PIP_HELLO"] = "5"
monkeypatch.setenv("PIP_HELLO", "5")
self.configuration.load()
assert self.configuration.get_value("test.hello") == "1"
assert self.configuration.get_value(":env:.hello") == "5"
def test_site_not_overriden_by_environment_var(self):
def test_site_not_overriden_by_environment_var(self, monkeypatch):
self.patch_configuration(kinds.SITE, {"test.hello": "2"})
os.environ["PIP_HELLO"] = "5"
monkeypatch.setenv("PIP_HELLO", "5")
self.configuration.load()
assert self.configuration.get_value("test.hello") == "2"
assert self.configuration.get_value(":env:.hello") == "5"
def test_user_not_overriden_by_environment_var(self):
def test_user_not_overriden_by_environment_var(self, monkeypatch):
self.patch_configuration(kinds.USER, {"test.hello": "3"})
os.environ["PIP_HELLO"] = "5"
monkeypatch.setenv("PIP_HELLO", "5")
self.configuration.load()
assert self.configuration.get_value("test.hello") == "3"
assert self.configuration.get_value(":env:.hello") == "5"
def test_global_not_overriden_by_environment_var(self):
def test_global_not_overriden_by_environment_var(self, monkeypatch):
self.patch_configuration(kinds.GLOBAL, {"test.hello": "4"})
os.environ["PIP_HELLO"] = "5"
monkeypatch.setenv("PIP_HELLO", "5")
self.configuration.load()

View File

@ -10,23 +10,6 @@ from pip._internal.exceptions import PipError
from tests.lib.options_helpers import AddFakeCommandMixin
@contextmanager
def temp_environment_variable(name, value):
not_set = object()
original = os.environ[name] if name in os.environ else not_set
os.environ[name] = value
try:
yield
finally:
# Return the environment variable to its original state.
if original is not_set:
if name in os.environ:
del os.environ[name]
else:
os.environ[name] = original
@contextmanager
def assert_option_error(capsys, expected):
"""
@ -70,56 +53,48 @@ class TestOptionPrecedence(AddFakeCommandMixin):
}
return config[section]
def test_env_override_default_int(self):
def test_env_override_default_int(self, monkeypatch):
"""
Test that environment variable overrides an int option default.
"""
os.environ['PIP_TIMEOUT'] = '-1'
monkeypatch.setenv('PIP_TIMEOUT', '-1')
options, args = main(['fake'])
assert options.timeout == -1
def test_env_override_default_append(self):
@pytest.mark.parametrize('values', (['F1'], ['F1', 'F2']))
def test_env_override_default_append(self, values, monkeypatch):
"""
Test that environment variable overrides an append option default.
"""
os.environ['PIP_FIND_LINKS'] = 'F1'
monkeypatch.setenv('PIP_FIND_LINKS', ' '.join(values))
options, args = main(['fake'])
assert options.find_links == ['F1']
assert options.find_links == values
os.environ['PIP_FIND_LINKS'] = 'F1 F2'
options, args = main(['fake'])
assert options.find_links == ['F1', 'F2']
def test_env_override_default_choice(self):
@pytest.mark.parametrize('choises', (['w'], ['s', 'w']))
def test_env_override_default_choice(self, choises, monkeypatch):
"""
Test that environment variable overrides a choice option default.
"""
os.environ['PIP_EXISTS_ACTION'] = 'w'
monkeypatch.setenv('PIP_EXISTS_ACTION', ' '.join(choises))
options, args = main(['fake'])
assert options.exists_action == ['w']
assert options.exists_action == choises
os.environ['PIP_EXISTS_ACTION'] = 's w'
options, args = main(['fake'])
assert options.exists_action == ['s', 'w']
def test_env_alias_override_default(self):
@pytest.mark.parametrize('name', ('PIP_LOG_FILE', 'PIP_LOCAL_LOG'))
def test_env_alias_override_default(self, name, monkeypatch):
"""
When an option has multiple long forms, test that the technique of
using the env variable, "PIP_<long form>" works for all cases.
(e.g. PIP_LOG_FILE and PIP_LOCAL_LOG should all work)
"""
os.environ['PIP_LOG_FILE'] = 'override.log'
options, args = main(['fake'])
assert options.log == 'override.log'
os.environ['PIP_LOCAL_LOG'] = 'override.log'
monkeypatch.setenv(name, 'override.log')
options, args = main(['fake'])
assert options.log == 'override.log'
def test_cli_override_environment(self):
def test_cli_override_environment(self, monkeypatch):
"""
Test the cli overrides and environment variable
"""
os.environ['PIP_TIMEOUT'] = '-1'
monkeypatch.setenv('PIP_TIMEOUT', '-1')
options, args = main(['fake', '--timeout', '-2'])
assert options.timeout == -2
@ -136,49 +111,49 @@ class TestOptionPrecedence(AddFakeCommandMixin):
'off',
'no',
])
def test_cache_dir__PIP_NO_CACHE_DIR(self, pip_no_cache_dir):
def test_cache_dir__PIP_NO_CACHE_DIR(self, pip_no_cache_dir, monkeypatch):
"""
Test setting the PIP_NO_CACHE_DIR environment variable without
passing any command-line flags.
"""
os.environ['PIP_NO_CACHE_DIR'] = pip_no_cache_dir
monkeypatch.setenv('PIP_NO_CACHE_DIR', pip_no_cache_dir)
options, args = main(['fake'])
assert options.cache_dir is False
@pytest.mark.parametrize('pip_no_cache_dir', ['yes', 'no'])
def test_cache_dir__PIP_NO_CACHE_DIR__with_cache_dir(
self, pip_no_cache_dir
self, pip_no_cache_dir, monkeypatch,
):
"""
Test setting PIP_NO_CACHE_DIR while also passing an explicit
--cache-dir value.
"""
os.environ['PIP_NO_CACHE_DIR'] = pip_no_cache_dir
monkeypatch.setenv('PIP_NO_CACHE_DIR', pip_no_cache_dir)
options, args = main(['--cache-dir', '/cache/dir', 'fake'])
# The command-line flag takes precedence.
assert options.cache_dir == '/cache/dir'
@pytest.mark.parametrize('pip_no_cache_dir', ['yes', 'no'])
def test_cache_dir__PIP_NO_CACHE_DIR__with_no_cache_dir(
self, pip_no_cache_dir
self, pip_no_cache_dir, monkeypatch,
):
"""
Test setting PIP_NO_CACHE_DIR while also passing --no-cache-dir.
"""
os.environ['PIP_NO_CACHE_DIR'] = pip_no_cache_dir
monkeypatch.setenv('PIP_NO_CACHE_DIR', pip_no_cache_dir)
options, args = main(['--no-cache-dir', 'fake'])
# The command-line flag should take precedence (which has the same
# value in this case).
assert options.cache_dir is False
def test_cache_dir__PIP_NO_CACHE_DIR_invalid__with_no_cache_dir(
self, capsys,
self, monkeypatch, capsys,
):
"""
Test setting PIP_NO_CACHE_DIR to an invalid value while also passing
--no-cache-dir.
"""
os.environ['PIP_NO_CACHE_DIR'] = 'maybe'
monkeypatch.setenv('PIP_NO_CACHE_DIR', 'maybe')
expected_err = "--no-cache-dir error: invalid truth value 'maybe'"
with assert_option_error(capsys, expected=expected_err):
main(['--no-cache-dir', 'fake'])
@ -219,52 +194,49 @@ class TestUsePEP517Options(object):
options = self.parse_args(['--no-use-pep517'])
assert options.use_pep517 is False
def test_PIP_USE_PEP517_true(self):
def test_PIP_USE_PEP517_true(self, monkeypatch):
"""
Test setting PIP_USE_PEP517 to "true".
"""
with temp_environment_variable('PIP_USE_PEP517', 'true'):
options = self.parse_args([])
monkeypatch.setenv('PIP_USE_PEP517', 'true')
options = self.parse_args([])
# This is an int rather than a boolean because strtobool() in pip's
# configuration code returns an int.
assert options.use_pep517 == 1
def test_PIP_USE_PEP517_false(self):
def test_PIP_USE_PEP517_false(self, monkeypatch):
"""
Test setting PIP_USE_PEP517 to "false".
"""
with temp_environment_variable('PIP_USE_PEP517', 'false'):
options = self.parse_args([])
monkeypatch.setenv('PIP_USE_PEP517', 'false')
options = self.parse_args([])
# This is an int rather than a boolean because strtobool() in pip's
# configuration code returns an int.
assert options.use_pep517 == 0
def test_use_pep517_and_PIP_USE_PEP517_false(self):
def test_use_pep517_and_PIP_USE_PEP517_false(self, monkeypatch):
"""
Test passing --use-pep517 and setting PIP_USE_PEP517 to "false".
"""
with temp_environment_variable('PIP_USE_PEP517', 'false'):
options = self.parse_args(['--use-pep517'])
monkeypatch.setenv('PIP_USE_PEP517', 'false')
options = self.parse_args(['--use-pep517'])
assert options.use_pep517 is True
def test_no_use_pep517_and_PIP_USE_PEP517_true(self):
def test_no_use_pep517_and_PIP_USE_PEP517_true(self, monkeypatch):
"""
Test passing --no-use-pep517 and setting PIP_USE_PEP517 to "true".
"""
with temp_environment_variable('PIP_USE_PEP517', 'true'):
options = self.parse_args(['--no-use-pep517'])
monkeypatch.setenv('PIP_USE_PEP517', 'true')
options = self.parse_args(['--no-use-pep517'])
assert options.use_pep517 is False
def test_PIP_NO_USE_PEP517(self, capsys):
def test_PIP_NO_USE_PEP517(self, monkeypatch, capsys):
"""
Test setting PIP_NO_USE_PEP517, which isn't allowed.
"""
expected_err = (
'--no-use-pep517 error: A value was passed for --no-use-pep517,\n'
)
with temp_environment_variable('PIP_NO_USE_PEP517', 'true'):
with assert_option_error(capsys, expected=expected_err):
self.parse_args([])
monkeypatch.setenv('PIP_NO_USE_PEP517', 'true')
with assert_option_error(capsys, expected='--no-use-pep517 error'):
self.parse_args([])
class TestOptionsInterspersed(AddFakeCommandMixin):