Merge pull request #8614 from McSinyx/monkeypatch.setenv

Use monkeypatch.setenv to mock env vars
This commit is contained in:
Xavier Fernandez 2020-09-04 11:05:15 +02:00 committed by GitHub
commit 822d42b11a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 151 additions and 229 deletions

View File

@ -6,10 +6,12 @@ import re
import shutil import shutil
import subprocess import subprocess
import sys import sys
import time
from contextlib import contextmanager from contextlib import contextmanager
import pytest import pytest
import six import six
from mock import patch
from pip._vendor.contextlib2 import ExitStack, nullcontext from pip._vendor.contextlib2 import ExitStack, nullcontext
from setuptools.wheel import Wheel from setuptools.wheel import Wheel
@ -104,10 +106,12 @@ def use_new_resolver(request):
"""Set environment variable to make pip default to the new resolver. """Set environment variable to make pip default to the new resolver.
""" """
new_resolver = request.config.getoption("--new-resolver") new_resolver = request.config.getoption("--new-resolver")
features = set(os.environ.get("PIP_USE_FEATURE", "").split())
if new_resolver: if new_resolver:
os.environ["PIP_USE_FEATURE"] = "2020-resolver" features.add("2020-resolver")
else: else:
os.environ.pop("PIP_USE_FEATURE", None) features.discard("2020-resolver")
with patch.dict(os.environ, {"PIP_USE_FEATURE": " ".join(features)}):
yield new_resolver yield new_resolver
@ -151,7 +155,7 @@ def tmpdir(request, tmpdir):
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def isolate(tmpdir): def isolate(tmpdir, monkeypatch):
""" """
Isolate our tests so that things like global configuration files and the Isolate our tests so that things like global configuration files and the
like do not affect our test results. like do not affect our test results.
@ -174,45 +178,51 @@ def isolate(tmpdir):
if sys.platform == 'win32': if sys.platform == 'win32':
# Note: this will only take effect in subprocesses... # Note: this will only take effect in subprocesses...
home_drive, home_path = os.path.splitdrive(home_dir) home_drive, home_path = os.path.splitdrive(home_dir)
os.environ.update({ monkeypatch.setenv('USERPROFILE', home_dir)
'USERPROFILE': home_dir, monkeypatch.setenv('HOMEDRIVE', home_drive)
'HOMEDRIVE': home_drive, monkeypatch.setenv('HOMEPATH', home_path)
'HOMEPATH': home_path,
})
for env_var, sub_path in ( for env_var, sub_path in (
('APPDATA', 'AppData/Roaming'), ('APPDATA', 'AppData/Roaming'),
('LOCALAPPDATA', 'AppData/Local'), ('LOCALAPPDATA', 'AppData/Local'),
): ):
path = os.path.join(home_dir, *sub_path.split('/')) path = os.path.join(home_dir, *sub_path.split('/'))
os.environ[env_var] = path monkeypatch.setenv(env_var, path)
os.makedirs(path) os.makedirs(path)
else: else:
# Set our home directory to our temporary directory, this should force # Set our home directory to our temporary directory, this should force
# all of our relative configuration files to be read from here instead # all of our relative configuration files to be read from here instead
# of the user's actual $HOME directory. # of the user's actual $HOME directory.
os.environ["HOME"] = home_dir monkeypatch.setenv("HOME", home_dir)
# Isolate ourselves from XDG directories # Isolate ourselves from XDG directories
os.environ["XDG_DATA_HOME"] = os.path.join(home_dir, ".local", "share") monkeypatch.setenv("XDG_DATA_HOME", os.path.join(
os.environ["XDG_CONFIG_HOME"] = os.path.join(home_dir, ".config") home_dir, ".local", "share",
os.environ["XDG_CACHE_HOME"] = os.path.join(home_dir, ".cache") ))
os.environ["XDG_RUNTIME_DIR"] = os.path.join(home_dir, ".runtime") monkeypatch.setenv("XDG_CONFIG_HOME", os.path.join(
os.environ["XDG_DATA_DIRS"] = ":".join([ home_dir, ".config",
))
monkeypatch.setenv("XDG_CACHE_HOME", os.path.join(home_dir, ".cache"))
monkeypatch.setenv("XDG_RUNTIME_DIR", os.path.join(
home_dir, ".runtime",
))
monkeypatch.setenv("XDG_DATA_DIRS", os.pathsep.join([
os.path.join(fake_root, "usr", "local", "share"), os.path.join(fake_root, "usr", "local", "share"),
os.path.join(fake_root, "usr", "share"), os.path.join(fake_root, "usr", "share"),
]) ]))
os.environ["XDG_CONFIG_DIRS"] = os.path.join(fake_root, "etc", "xdg") monkeypatch.setenv("XDG_CONFIG_DIRS", os.path.join(
fake_root, "etc", "xdg",
))
# Configure git, because without an author name/email git will complain # Configure git, because without an author name/email git will complain
# and cause test failures. # and cause test failures.
os.environ["GIT_CONFIG_NOSYSTEM"] = "1" monkeypatch.setenv("GIT_CONFIG_NOSYSTEM", "1")
os.environ["GIT_AUTHOR_NAME"] = "pip" monkeypatch.setenv("GIT_AUTHOR_NAME", "pip")
os.environ["GIT_AUTHOR_EMAIL"] = "distutils-sig@python.org" monkeypatch.setenv("GIT_AUTHOR_EMAIL", "distutils-sig@python.org")
# We want to disable the version check from running in the tests # We want to disable the version check from running in the tests
os.environ["PIP_DISABLE_PIP_VERSION_CHECK"] = "true" monkeypatch.setenv("PIP_DISABLE_PIP_VERSION_CHECK", "true")
# Make sure tests don't share a requirements tracker. # Make sure tests don't share a requirements tracker.
os.environ.pop('PIP_REQ_TRACKER', None) monkeypatch.delenv("PIP_REQ_TRACKER", False)
# FIXME: Windows... # FIXME: Windows...
os.makedirs(os.path.join(home_dir, ".config", "git")) os.makedirs(os.path.join(home_dir, ".config", "git"))
@ -547,3 +557,13 @@ def mock_server():
test_server = MockServer(server) test_server = MockServer(server)
with test_server.context: with test_server.context:
yield test_server yield test_server
@pytest.fixture
def utc():
# time.tzset() is not implemented on some platforms, e.g. Windows.
tzset = getattr(time, 'tzset', lambda: None)
with patch.dict(os.environ, {'TZ': 'UTC'}):
tzset()
yield
tzset()

View File

@ -492,10 +492,7 @@ class PipTestEnvironment(TestFileEnvironment):
kwargs.setdefault("cwd", self.scratch_path) kwargs.setdefault("cwd", self.scratch_path)
# Setup our environment # Setup our environment
environ = kwargs.get("environ") environ = kwargs.setdefault("environ", os.environ.copy())
if environ is None:
environ = os.environ.copy()
environ["PATH"] = Path.pathsep.join( environ["PATH"] = Path.pathsep.join(
[self.bin_path] + [environ.get("PATH", [])], [self.bin_path] + [environ.get("PATH", [])],
) )
@ -504,7 +501,6 @@ class PipTestEnvironment(TestFileEnvironment):
environ["PYTHONDONTWRITEBYTECODE"] = "1" environ["PYTHONDONTWRITEBYTECODE"] = "1"
# Make sure we get UTF-8 on output, even on Windows... # Make sure we get UTF-8 on output, even on Windows...
environ["PYTHONIOENCODING"] = "UTF-8" environ["PYTHONIOENCODING"] = "UTF-8"
kwargs["environ"] = environ
# Whether all pip invocations should expect stderr # Whether all pip invocations should expect stderr
# (useful for Python version deprecation) # (useful for Python version deprecation)

View File

@ -14,18 +14,6 @@ from pip._internal.utils.misc import ensure_dir
kinds = pip._internal.configuration.kinds 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): class ConfigurationMixin(object):
def setup(self): def setup(self):
@ -34,14 +22,10 @@ class ConfigurationMixin(object):
) )
self._files_to_clear = [] self._files_to_clear = []
self._old_environ = os.environ.copy()
def teardown(self): def teardown(self):
for fname in self._files_to_clear: for fname in self._files_to_clear:
fname.stop() fname.stop()
reset_os_environ(self._old_environ)
def patch_configuration(self, variant, di): def patch_configuration(self, variant, di):
old = self.configuration._load_config_files old = self.configuration._load_config_files

View File

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

View File

@ -1,6 +1,5 @@
import logging import logging
import os import os
import time
import pytest import pytest
from mock import Mock, patch from mock import Mock, patch
@ -12,6 +11,12 @@ from pip._internal.utils.logging import BrokenStdoutLoggingError
from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.temp_dir import TempDirectory
@pytest.fixture
def fixed_time(utc):
with patch('time.time', lambda: 1547704837.040001):
yield
class FakeCommand(Command): class FakeCommand(Command):
_name = 'fake' _name = 'fake'
@ -91,63 +96,36 @@ def test_handle_pip_version_check_called(mock_handle_version_check):
mock_handle_version_check.assert_called_once() mock_handle_version_check.assert_called_once()
class Test_base_command_logging(object): def test_log_command_success(fixed_time, tmpdir):
""" """Test the --log option logs when command succeeds."""
Test `pip.base_command.Command` setting up logging consumers based on
options
"""
def setup(self):
self.old_time = time.time
time.time = lambda: 1547704837.040001
self.old_tz = os.environ.get('TZ')
os.environ['TZ'] = 'UTC'
# time.tzset() is not implemented on some platforms (notably, Windows).
if hasattr(time, 'tzset'):
time.tzset()
def teardown(self):
if self.old_tz:
os.environ['TZ'] = self.old_tz
else:
del os.environ['TZ']
if 'tzset' in dir(time):
time.tzset()
time.time = self.old_time
def test_log_command_success(self, tmpdir):
"""
Test the --log option logs when command succeeds
"""
cmd = FakeCommand() cmd = FakeCommand()
log_path = tmpdir.joinpath('log') log_path = tmpdir.joinpath('log')
cmd.main(['fake', '--log', log_path]) cmd.main(['fake', '--log', log_path])
with open(log_path) as f: with open(log_path) as f:
assert f.read().rstrip() == '2019-01-17T06:00:37,040 fake' assert f.read().rstrip() == '2019-01-17T06:00:37,040 fake'
def test_log_command_error(self, tmpdir):
""" def test_log_command_error(fixed_time, tmpdir):
Test the --log option logs when command fails """Test the --log option logs when command fails."""
"""
cmd = FakeCommand(error=True) cmd = FakeCommand(error=True)
log_path = tmpdir.joinpath('log') log_path = tmpdir.joinpath('log')
cmd.main(['fake', '--log', log_path]) cmd.main(['fake', '--log', log_path])
with open(log_path) as f: with open(log_path) as f:
assert f.read().startswith('2019-01-17T06:00:37,040 fake') assert f.read().startswith('2019-01-17T06:00:37,040 fake')
def test_log_file_command_error(self, tmpdir):
""" def test_log_file_command_error(fixed_time, tmpdir):
Test the --log-file option logs (when there's an error). """Test the --log-file option logs (when there's an error)."""
"""
cmd = FakeCommand(error=True) cmd = FakeCommand(error=True)
log_file_path = tmpdir.joinpath('log_file') log_file_path = tmpdir.joinpath('log_file')
cmd.main(['fake', '--log-file', log_file_path]) cmd.main(['fake', '--log-file', log_file_path])
with open(log_file_path) as f: with open(log_file_path) as f:
assert f.read().startswith('2019-01-17T06:00:37,040 fake') assert f.read().startswith('2019-01-17T06:00:37,040 fake')
def test_unicode_messages(self, tmpdir):
""" def test_log_unicode_messages(fixed_time, tmpdir):
Tests that logging bytestrings and unicode objects don't break logging """Tests that logging bytestrings and unicode objects
don't break logging.
""" """
cmd = FakeCommandWithUnicode() cmd = FakeCommandWithUnicode()
log_path = tmpdir.joinpath('log') log_path = tmpdir.joinpath('log')

View File

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

View File

@ -1,7 +1,5 @@
import errno import errno
import logging import logging
import os
import time
from threading import Thread from threading import Thread
import pytest import pytest
@ -33,24 +31,7 @@ def _make_broken_pipe_error():
class TestIndentingFormatter(object): class TestIndentingFormatter(object):
""" """Test ``pip._internal.utils.logging.IndentingFormatter``."""
Test `pip._internal.utils.logging.IndentingFormatter`.
"""
def setup(self):
self.old_tz = os.environ.get('TZ')
os.environ['TZ'] = 'UTC'
# time.tzset() is not implemented on some platforms (notably, Windows).
if hasattr(time, 'tzset'):
time.tzset()
def teardown(self):
if self.old_tz:
os.environ['TZ'] = self.old_tz
else:
del os.environ['TZ']
if 'tzset' in dir(time):
time.tzset()
def make_record(self, msg, level_name): def make_record(self, msg, level_name):
level_number = getattr(logging, level_name) level_number = getattr(logging, level_name)
@ -72,7 +53,7 @@ class TestIndentingFormatter(object):
('ERROR', 'ERROR: hello\nworld'), ('ERROR', 'ERROR: hello\nworld'),
('CRITICAL', 'ERROR: hello\nworld'), ('CRITICAL', 'ERROR: hello\nworld'),
]) ])
def test_format(self, level_name, expected): def test_format(self, level_name, expected, utc):
""" """
Args: Args:
level_name: a logging level name (e.g. "WARNING"). level_name: a logging level name (e.g. "WARNING").
@ -89,7 +70,7 @@ class TestIndentingFormatter(object):
'2019-01-17T06:00:37,040 WARNING: hello\n' '2019-01-17T06:00:37,040 WARNING: hello\n'
'2019-01-17T06:00:37,040 world'), '2019-01-17T06:00:37,040 world'),
]) ])
def test_format_with_timestamp(self, level_name, expected): def test_format_with_timestamp(self, level_name, expected, utc):
record = self.make_record('hello\nworld', level_name=level_name) record = self.make_record('hello\nworld', level_name=level_name)
f = IndentingFormatter(fmt="%(message)s", add_timestamp=True) f = IndentingFormatter(fmt="%(message)s", add_timestamp=True)
assert f.format(record) == expected assert f.format(record) == expected
@ -99,7 +80,7 @@ class TestIndentingFormatter(object):
('ERROR', 'DEPRECATION: hello\nworld'), ('ERROR', 'DEPRECATION: hello\nworld'),
('CRITICAL', 'DEPRECATION: hello\nworld'), ('CRITICAL', 'DEPRECATION: hello\nworld'),
]) ])
def test_format_deprecated(self, level_name, expected): def test_format_deprecated(self, level_name, expected, utc):
""" """
Test that logged deprecation warnings coming from deprecated() Test that logged deprecation warnings coming from deprecated()
don't get another prefix. don't get another prefix.
@ -110,7 +91,7 @@ class TestIndentingFormatter(object):
f = IndentingFormatter(fmt="%(message)s") f = IndentingFormatter(fmt="%(message)s")
assert f.format(record) == expected assert f.format(record) == expected
def test_thread_safety_base(self): def test_thread_safety_base(self, utc):
record = self.make_record( record = self.make_record(
'DEPRECATION: hello\nworld', level_name='WARNING', 'DEPRECATION: hello\nworld', level_name='WARNING',
) )
@ -126,7 +107,7 @@ class TestIndentingFormatter(object):
thread.join() thread.join()
assert results[0] == results[1] assert results[0] == results[1]
def test_thread_safety_indent_log(self): def test_thread_safety_indent_log(self, utc):
record = self.make_record( record = self.make_record(
'DEPRECATION: hello\nworld', level_name='WARNING', 'DEPRECATION: hello\nworld', level_name='WARNING',
) )

View File

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

View File

@ -600,15 +600,13 @@ class TestMessageAboutScriptsNotOnPATH(object):
) )
assert retval is None assert retval is None
def test_missing_PATH_env_treated_as_empty_PATH_env(self): def test_missing_PATH_env_treated_as_empty_PATH_env(self, monkeypatch):
scripts = ['a/b/foo'] scripts = ['a/b/foo']
env = os.environ.copy() monkeypatch.delenv('PATH')
del env['PATH']
with patch.dict('os.environ', env, clear=True):
retval_missing = wheel.message_about_scripts_not_on_PATH(scripts) retval_missing = wheel.message_about_scripts_not_on_PATH(scripts)
with patch.dict('os.environ', {'PATH': ''}): monkeypatch.setenv('PATH', '')
retval_empty = wheel.message_about_scripts_not_on_PATH(scripts) retval_empty = wheel.message_about_scripts_not_on_PATH(scripts)
assert retval_missing == retval_empty assert retval_missing == retval_empty