diff --git a/news/9330.bugfix.rst b/news/9330.bugfix.rst new file mode 100644 index 00000000000..4cbd4192b89 --- /dev/null +++ b/news/9330.bugfix.rst @@ -0,0 +1 @@ +``pip config`` normalizes names, converting underscores into dashes \ No newline at end of file diff --git a/src/pip/_internal/configuration.py b/src/pip/_internal/configuration.py index a8092d1ae06..a2b0607c5dc 100644 --- a/src/pip/_internal/configuration.py +++ b/src/pip/_internal/configuration.py @@ -142,13 +142,16 @@ def items(self) -> Iterable[Tuple[str, Any]]: def get_value(self, key: str) -> Any: """Get a value from the configuration.""" + orig_key = key + key = _normalize_name(key) try: return self._dictionary[key] except KeyError: - raise ConfigurationError(f"No such key - {key}") + raise ConfigurationError(f"No such key - {orig_key}") def set_value(self, key: str, value: Any) -> None: """Modify a value in the configuration.""" + key = _normalize_name(key) self._ensure_have_load_only() assert self.load_only @@ -167,11 +170,13 @@ def set_value(self, key: str, value: Any) -> None: def unset_value(self, key: str) -> None: """Unset a value in the configuration.""" + orig_key = key + key = _normalize_name(key) self._ensure_have_load_only() assert self.load_only if key not in self._config[self.load_only]: - raise ConfigurationError(f"No such key - {key}") + raise ConfigurationError(f"No such key - {orig_key}") fname, parser = self._get_parser_to_modify() diff --git a/tests/unit/test_configuration.py b/tests/unit/test_configuration.py index 788d32b9b76..22ea983958c 100644 --- a/tests/unit/test_configuration.py +++ b/tests/unit/test_configuration.py @@ -185,12 +185,8 @@ class TestConfigurationModification(ConfigurationMixin): def test_no_specific_given_modification(self) -> None: self.configuration.load() - try: + with pytest.raises(ConfigurationError): self.configuration.set_value("test.hello", "10") - except ConfigurationError: - pass - else: - assert False, "Should have raised an error." def test_site_modification(self) -> None: self.configuration.load_only = kinds.SITE @@ -241,3 +237,16 @@ def test_global_modification(self) -> None: # get the path to user config file assert mymock.call_count == 1 assert mymock.call_args[0][0] == (get_configuration_files()[kinds.GLOBAL][-1]) + + def test_normalization(self) -> None: + # underscores and dashes can be used interchangeably. + # internally, underscores get converted into dashes before reading/writing file + self.configuration.load_only = kinds.GLOBAL + self.configuration.load() + self.configuration.set_value("global.index-url", "example.org") + assert self.configuration.get_value("global.index_url") == "example.org" + assert self.configuration.get_value("global.index-url") == "example.org" + self.configuration.unset_value("global.index-url") + pat = r"^No such key - global\.index-url$" + with pytest.raises(ConfigurationError, match=pat): + self.configuration.get_value("global.index-url")