diff --git a/tests/unit/test_basecommand.py b/tests/unit/test_basecommand.py deleted file mode 100644 index 285454cb751..00000000000 --- a/tests/unit/test_basecommand.py +++ /dev/null @@ -1,99 +0,0 @@ -import os -import copy -from pip import main -from pip import cmdoptions -from pip.basecommand import Command -from pip.commands import InstallCommand -from pip.commands import commands - -class FakeCommand(Command): - name = 'fake' - summary = name - def main(self, args): - return self.parse_args(args) - -class TestCommandParsing(object): - - def setup(self): - self.environ_before = os.environ.copy() - commands[FakeCommand.name] = FakeCommand - - def teardown(self): - os.environ = self.environ_before - commands.pop(FakeCommand.name) - - def different_than_default(self, option): - """ - Generate something different than the option default - Returns a tuple containing: - - the value to test against getattr(options, option.dest) - - the args to achieve it , e.g ['--log', '/path'] - """ - NO_DEFAULT = (option.default == ('NO', 'DEFAULT')) - long_opt = option._long_opts[0] - - if option.type == 'choice': - dest = option.default[:] - dest.append(option.choices[0]) - if dest == option.default: - assert False, "The test is not altering the default" - args = [] - for d in dest: - args.extend([long_opt, d]) - elif option.type in ['str', 'string']: - if NO_DEFAULT: - dest = 'CHANGED' - else: - dest = option.default + 'CHANGED' - args = [long_opt, dest] - elif option.action == 'count': - dest = option.default + 1 - args = [long_opt] - elif option.type == 'float': - dest = option.default + 100 - args = [long_opt, str(dest)] - elif option.action == 'store_true': - dest = not option.default - args = [long_opt] - elif option.default == ('NO', 'DEFAULT'): - dest = 'CHANGED' - args = [long_opt, dest] - - return dest, args - - def test_general_options_dont_have_duplicated_defaults(self): - """ - Confirm that 'append' options don't end up with duplicated defaults. - """ - # It's possible for our general options to be used twice during command - # initialization, e.g. `--exists-action` option will be used twice in - # this case: "pip --exists-action s install somepkg". And if they carry - # state (like append options with [] defaults) then this can be - # trouble. We need to confirm this is not happening. - options, args = main(['--exists-action', 's', 'fake']) - assert options.exists_action == ['s'] # not ['s','s'] - - def test_cli_override_general_options(self): - """ - Test overriding default values for general options using the cli - (not referring to config or environment overrides) - """ - # the reason to specifically test general options is due to the - # extra parsing they receive, and the bugs we've had - for option_maker in cmdoptions.general_group['options']: - option = option_maker.make() - if option.dest in ['help', 'version']: - continue - expected_dest, opt_args = self.different_than_default(option) - - # we're going to check with the args before and after the subcommand - # our parser allows general options to live after the subcommand - for args in (opt_args + ['fake'], ['fake'] + opt_args): - options, args_ = main(args) - msg = "%s != %s with args %s" %( - getattr(options, option.dest), - expected_dest, - args - ) - assert getattr(options, option.dest) == expected_dest, msg - diff --git a/tests/unit/test_baseparser.py b/tests/unit/test_baseparser.py deleted file mode 100644 index 76f9173568e..00000000000 --- a/tests/unit/test_baseparser.py +++ /dev/null @@ -1,72 +0,0 @@ -import os -from pip.baseparser import ConfigOptionParser - -class TestConfigOptionParser(object): - """ - Unit tests for `pip.baseparser.ConfigOptionParser` (our option parser that - overrides defaults from config files and environment vars) - """ - - def setup(self): - self.environ_before = os.environ.copy() - self.parser = ConfigOptionParser(name='test') - self.parser.add_option( - '--normal', - default='v1') - self.parser.add_option( - '--append', - action='append', - default=['v1']) - self.parser.add_option( - '--choice', - action='append', - choices=['v1', 'v2', 'v3'], - type='choice', - default=['v1']) - - def teardown(self): - os.environ = self.environ_before - - def test_env_non_append_override_default(self): - """ - Test that a PIP_* environ variable overrides a non-append option default. - """ - os.environ['PIP_NORMAL'] = 'v2' - options, args = self.parser.parse_args([]) - assert options.normal == 'v2' - - def test_env_append_single_override_default(self): - """ - Test that a PIP_* environ variable overrides an append option default. - (where the value is one item) - """ - os.environ['PIP_APPEND'] = 'v2' - options, args = self.parser.parse_args([]) - assert options.append == ['v2'] - - def test_env_append_multi_override_default(self): - """ - Test that a PIP_* environ variable overrides an append option default. - (where the value is multiple) - """ - os.environ['PIP_APPEND'] = 'v1 v2' - options, args = self.parser.parse_args([]) - assert options.append == ['v1', 'v2'] - - def test_env_choice_single_override_default(self): - """ - Test that a PIP_* environ variable overrides a choice option default. - (where the value is one item) - """ - os.environ['PIP_CHOICE'] = 'v2' - options, args = self.parser.parse_args([]) - assert options.choice == ['v2'] - - def test_env_choice_multi_override_default(self): - """ - Test that a PIP_* environ variable overrides a choice option default. - (where the value is multiple) - """ - os.environ['PIP_CHOICE'] = 'v1 v2' - options, args = self.parser.parse_args([]) - assert options.choice == ['v1', 'v2'] diff --git a/tests/unit/test_options.py b/tests/unit/test_options.py new file mode 100644 index 00000000000..e0c29acc665 --- /dev/null +++ b/tests/unit/test_options.py @@ -0,0 +1,215 @@ +import os +import pytest +import pip.baseparser +from pip import main +from pip import cmdoptions +from pip.basecommand import Command +from pip.commands import commands + +class FakeCommand(Command): + name = 'fake' + summary = name + def main(self, args): + index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser) + self.parser.add_option_group(index_opts) + return self.parse_args(args) + + +class TestOptionPrecedence(object): + """ + Tests for confirming our option precedence: + cli -> environment -> subcommand config -> global config -> option defaults + """ + + def setup(self): + self.environ_before = os.environ.copy() + commands[FakeCommand.name] = FakeCommand + + def teardown(self): + os.environ = self.environ_before + commands.pop(FakeCommand.name) + + def get_config_section(self, section): + config = { + 'global': [('timeout','-3')], + 'fake': [('timeout','-2')] + } + return config[section] + + def get_config_section_global(self, section): + config = { + 'global': [('timeout','-3')], + 'fake': [] + } + return config[section] + + def test_env_override_default_int(self): + """ + Test that environment variable overrides an int option default. + """ + os.environ['PIP_TIMEOUT'] = '-1' + options, args = main(['fake']) + assert options.timeout == -1 + + def test_env_override_default_append(self): + """ + Test that environment variable overrides an append option default. + """ + os.environ['PIP_FIND_LINKS'] = 'F1' + options, args = main(['fake']) + assert options.find_links == ['F1'] + + os.environ['PIP_FIND_LINKS'] = 'F1 F2' + options, args = main(['fake']) + assert options.find_links == ['F1', 'F2'] + + def test_env_override_default_choice(self): + """ + Test that environment variable overrides a choice option default. + """ + os.environ['PIP_EXISTS_ACTION'] = 'w' + options, args = main(['fake']) + assert options.exists_action == ['w'] + + os.environ['PIP_EXISTS_ACTION'] = 's w' + options, args = main(['fake']) + assert options.exists_action == ['s', 'w'] + + def test_cli_override_environment(self): + """ + Test the cli overrides and environment variable + """ + os.environ['PIP_TIMEOUT'] = '-1' + options, args = main(['fake', '--timeout', '-2']) + assert options.timeout == -2 + + def test_environment_override_config(self, monkeypatch): + """ + Test an environment variable overrides the config file + """ + monkeypatch.setattr(pip.baseparser.ConfigOptionParser, "get_config_section", self.get_config_section) + os.environ['PIP_TIMEOUT'] = '-1' + options, args = main(['fake']) + assert options.timeout == -1 + + def test_commmand_config_override_global_config(self, monkeypatch): + """ + Test that command config overrides global config + """ + monkeypatch.setattr(pip.baseparser.ConfigOptionParser, "get_config_section", self.get_config_section) + options, args = main(['fake']) + assert options.timeout == -2 + + def test_global_config_is_used(self, monkeypatch): + """ + Test that global config is used + """ + monkeypatch.setattr(pip.baseparser.ConfigOptionParser, "get_config_section", self.get_config_section_global) + options, args = main(['fake']) + assert options.timeout == -3 + + +class TestOptionsInterspersed(object): + + def setup(self): + self.environ_before = os.environ.copy() + commands[FakeCommand.name] = FakeCommand + + def teardown(self): + os.environ = self.environ_before + commands.pop(FakeCommand.name) + + def test_general_option_after_subcommand(self): + options, args = main(['fake', '--timeout', '-1']) + assert options.timeout == -1 + + def test_option_after_subcommand_arg(self): + options, args = main(['fake', 'arg', '--timeout', '-1']) + assert options.timeout == -1 + + def test_additive_before_after_subcommand(self): + options, args = main(['-v', 'fake', '-v']) + assert options.verbose == 2 + + def test_subcommand_option_before_subcommand_fails(self): + with pytest.raises(SystemExit): + main(['--find-links', 'F1', 'fake']) + + +class TestGeneralOptions(object): + + # the reason to specifically test general options is due to the + # extra processing they receive, and the number of bugs we've had + + def setup(self): + self.environ_before = os.environ.copy() + commands[FakeCommand.name] = FakeCommand + + def teardown(self): + os.environ = self.environ_before + commands.pop(FakeCommand.name) + + def test_require_virtualenv(self): + options1, args1 = main(['--require-virtualenv', 'fake']) + options2, args2 = main(['fake', '--require-virtualenv']) + assert options1.require_venv == options2.require_venv == True + + def test_verbose(self): + options1, args1 = main(['--verbose', 'fake']) + options2, args2 = main(['fake', '--verbose']) + assert options1.verbose == options2.verbose == 1 + + def test_quiet(self): + options1, args1 = main(['--quiet', 'fake']) + options2, args2 = main(['fake', '--quiet']) + assert options1.quiet == options2.quiet == 1 + + def test_log(self): + options1, args1 = main(['--log', 'path', 'fake']) + options2, args2 = main(['fake', '--log', 'path']) + assert options1.log == options2.log == 'path' + + def test_log_explicit_levels(self): + options1, args1 = main(['--log-explicit-levels', 'fake']) + options2, args2 = main(['fake', '--log-explicit-levels']) + assert options1.log_explicit_levels == options2.log_explicit_levels == True + + def test_local_log(self): + options1, args1 = main(['--local-log', 'path', 'fake']) + options2, args2 = main(['fake', '--local-log', 'path']) + assert options1.log_file == options2.log_file == 'path' + + def test_no_input(self): + options1, args1 = main(['--no-input', 'fake']) + options2, args2 = main(['fake', '--no-input']) + assert options1.no_input == options2.no_input == True + + def test_proxy(self): + options1, args1 = main(['--proxy', 'path', 'fake']) + options2, args2 = main(['fake', '--proxy', 'path']) + assert options1.proxy == options2.proxy == 'path' + + def test_timeout(self): + options1, args1 = main(['--timeout', '-1', 'fake']) + options2, args2 = main(['fake', '--timeout', '-1']) + assert options1.timeout == options2.timeout == -1 + + def test_default_vcs(self): + options1, args1 = main(['--default-vcs', 'path', 'fake']) + options2, args2 = main(['fake', '--default-vcs', 'path']) + assert options1.default_vcs == options2.default_vcs == 'path' + + def test_skip_requirements_regex(self): + options1, args1 = main(['--skip-requirements-regex', 'path', 'fake']) + options2, args2 = main(['fake', '--skip-requirements-regex', 'path']) + assert options1.skip_requirements_regex == options2.skip_requirements_regex == 'path' + + def test_exists_action(self): + options1, args1 = main(['--exists-action', 'w', 'fake']) + options2, args2 = main(['fake', '--exists-action', 'w']) + assert options1.exists_action == options2.exists_action == ['w'] + + def test_cert(self): + options1, args1 = main(['--cert', 'path', 'fake']) + options2, args2 = main(['fake', '--cert', 'path']) + assert options1.cert == options2.cert == 'path'