1"""Tests for all things related to the configuration 2""" 3 4import pytest 5from mock import MagicMock 6 7from pip._internal.configuration import get_configuration_files, kinds 8from pip._internal.exceptions import ConfigurationError 9from tests.lib.configuration_helpers import ConfigurationMixin 10 11 12class TestConfigurationLoading(ConfigurationMixin): 13 14 def test_global_loading(self): 15 self.patch_configuration(kinds.GLOBAL, {"test.hello": "1"}) 16 17 self.configuration.load() 18 assert self.configuration.get_value("test.hello") == "1" 19 20 def test_user_loading(self): 21 self.patch_configuration(kinds.USER, {"test.hello": "2"}) 22 23 self.configuration.load() 24 assert self.configuration.get_value("test.hello") == "2" 25 26 def test_site_loading(self): 27 self.patch_configuration(kinds.SITE, {"test.hello": "3"}) 28 29 self.configuration.load() 30 assert self.configuration.get_value("test.hello") == "3" 31 32 def test_environment_config_loading(self, monkeypatch): 33 contents = """ 34 [test] 35 hello = 4 36 """ 37 38 with self.tmpfile(contents) as config_file: 39 monkeypatch.setenv("PIP_CONFIG_FILE", config_file) 40 41 self.configuration.load() 42 assert self.configuration.get_value("test.hello") == "4", \ 43 self.configuration._config 44 45 def test_environment_var_loading(self, monkeypatch): 46 monkeypatch.setenv("PIP_HELLO", "5") 47 48 self.configuration.load() 49 assert self.configuration.get_value(":env:.hello") == "5" 50 51 @pytest.mark.skipif("sys.platform == 'win32'") 52 def test_environment_var_does_not_load_lowercase(self, monkeypatch): 53 monkeypatch.setenv("pip_hello", "5") 54 55 self.configuration.load() 56 with pytest.raises(ConfigurationError): 57 self.configuration.get_value(":env:.hello") 58 59 def test_environment_var_does_not_load_version(self, monkeypatch): 60 monkeypatch.setenv("PIP_VERSION", "True") 61 62 self.configuration.load() 63 64 with pytest.raises(ConfigurationError): 65 self.configuration.get_value(":env:.version") 66 67 def test_environment_config_errors_if_malformed(self, monkeypatch): 68 contents = """ 69 test] 70 hello = 4 71 """ 72 with self.tmpfile(contents) as config_file: 73 monkeypatch.setenv("PIP_CONFIG_FILE", config_file) 74 with pytest.raises(ConfigurationError) as err: 75 self.configuration.load() 76 77 assert "section header" in str(err.value) # error kind 78 assert "1" in str(err.value) # line number 79 assert ( # file name 80 config_file in str(err.value) or 81 repr(config_file) in str(err.value) 82 ) 83 84 85class TestConfigurationPrecedence(ConfigurationMixin): 86 # Tests for methods to that determine the order of precedence of 87 # configuration options 88 89 def test_env_overides_site(self): 90 self.patch_configuration(kinds.SITE, {"test.hello": "1"}) 91 self.patch_configuration(kinds.ENV, {"test.hello": "0"}) 92 self.configuration.load() 93 94 assert self.configuration.get_value("test.hello") == "0" 95 96 def test_env_overides_user(self): 97 self.patch_configuration(kinds.USER, {"test.hello": "2"}) 98 self.patch_configuration(kinds.ENV, {"test.hello": "0"}) 99 self.configuration.load() 100 101 assert self.configuration.get_value("test.hello") == "0" 102 103 def test_env_overides_global(self): 104 self.patch_configuration(kinds.GLOBAL, {"test.hello": "3"}) 105 self.patch_configuration(kinds.ENV, {"test.hello": "0"}) 106 self.configuration.load() 107 108 assert self.configuration.get_value("test.hello") == "0" 109 110 def test_site_overides_user(self): 111 self.patch_configuration(kinds.USER, {"test.hello": "2"}) 112 self.patch_configuration(kinds.SITE, {"test.hello": "1"}) 113 self.configuration.load() 114 115 assert self.configuration.get_value("test.hello") == "1" 116 117 def test_site_overides_global(self): 118 self.patch_configuration(kinds.GLOBAL, {"test.hello": "3"}) 119 self.patch_configuration(kinds.SITE, {"test.hello": "1"}) 120 self.configuration.load() 121 122 assert self.configuration.get_value("test.hello") == "1" 123 124 def test_user_overides_global(self): 125 self.patch_configuration(kinds.GLOBAL, {"test.hello": "3"}) 126 self.patch_configuration(kinds.USER, {"test.hello": "2"}) 127 self.configuration.load() 128 129 assert self.configuration.get_value("test.hello") == "2" 130 131 def test_env_not_overriden_by_environment_var(self, monkeypatch): 132 self.patch_configuration(kinds.ENV, {"test.hello": "1"}) 133 monkeypatch.setenv("PIP_HELLO", "5") 134 135 self.configuration.load() 136 137 assert self.configuration.get_value("test.hello") == "1" 138 assert self.configuration.get_value(":env:.hello") == "5" 139 140 def test_site_not_overriden_by_environment_var(self, monkeypatch): 141 self.patch_configuration(kinds.SITE, {"test.hello": "2"}) 142 monkeypatch.setenv("PIP_HELLO", "5") 143 144 self.configuration.load() 145 146 assert self.configuration.get_value("test.hello") == "2" 147 assert self.configuration.get_value(":env:.hello") == "5" 148 149 def test_user_not_overriden_by_environment_var(self, monkeypatch): 150 self.patch_configuration(kinds.USER, {"test.hello": "3"}) 151 monkeypatch.setenv("PIP_HELLO", "5") 152 153 self.configuration.load() 154 155 assert self.configuration.get_value("test.hello") == "3" 156 assert self.configuration.get_value(":env:.hello") == "5" 157 158 def test_global_not_overriden_by_environment_var(self, monkeypatch): 159 self.patch_configuration(kinds.GLOBAL, {"test.hello": "4"}) 160 monkeypatch.setenv("PIP_HELLO", "5") 161 162 self.configuration.load() 163 164 assert self.configuration.get_value("test.hello") == "4" 165 assert self.configuration.get_value(":env:.hello") == "5" 166 167 168class TestConfigurationModification(ConfigurationMixin): 169 # Tests for methods to that modify the state of a Configuration 170 171 def test_no_specific_given_modification(self): 172 self.configuration.load() 173 174 try: 175 self.configuration.set_value("test.hello", "10") 176 except ConfigurationError: 177 pass 178 else: 179 assert False, "Should have raised an error." 180 181 def test_site_modification(self): 182 self.configuration.load_only = kinds.SITE 183 self.configuration.load() 184 185 # Mock out the method 186 mymock = MagicMock(spec=self.configuration._mark_as_modified) 187 self.configuration._mark_as_modified = mymock 188 189 self.configuration.set_value("test.hello", "10") 190 191 # get the path to site config file 192 assert mymock.call_count == 1 193 assert mymock.call_args[0][0] == ( 194 get_configuration_files()[kinds.SITE][0] 195 ) 196 197 def test_user_modification(self): 198 # get the path to local config file 199 self.configuration.load_only = kinds.USER 200 self.configuration.load() 201 202 # Mock out the method 203 mymock = MagicMock(spec=self.configuration._mark_as_modified) 204 self.configuration._mark_as_modified = mymock 205 206 self.configuration.set_value("test.hello", "10") 207 208 # get the path to user config file 209 assert mymock.call_count == 1 210 assert mymock.call_args[0][0] == ( 211 # Use new config file 212 get_configuration_files()[kinds.USER][1] 213 ) 214 215 def test_global_modification(self): 216 # get the path to local config file 217 self.configuration.load_only = kinds.GLOBAL 218 self.configuration.load() 219 220 # Mock out the method 221 mymock = MagicMock(spec=self.configuration._mark_as_modified) 222 self.configuration._mark_as_modified = mymock 223 224 self.configuration.set_value("test.hello", "10") 225 226 # get the path to user config file 227 assert mymock.call_count == 1 228 assert mymock.call_args[0][0] == ( 229 get_configuration_files()[kinds.GLOBAL][-1] 230 ) 231