Merge pull request #5798 from pradyunsg/improve-configuration-handling

Improve configuration handling
This commit is contained in:
Pradyun Gedam 2018-10-04 14:27:42 +05:30 committed by GitHub
commit c759504217
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 8 deletions

1
news/5798.feature Normal file
View File

@ -0,0 +1 @@
Malformed configuration files now show helpful error messages, instead of tracebacks.

View File

@ -9,6 +9,7 @@ from distutils.util import strtobool
from pip._vendor.six import string_types
from pip._internal.cli.status_codes import UNKNOWN_ERROR
from pip._internal.configuration import Configuration, ConfigurationError
from pip._internal.utils.compat import get_terminal_size
@ -232,7 +233,7 @@ class ConfigOptionParser(CustomOptionParser):
try:
self.config.load()
except ConfigurationError as err:
self.exit(2, err.args[0])
self.exit(UNKNOWN_ERROR, str(err))
defaults = self._update_defaults(self.defaults.copy()) # ours
for option in self._get_all_options():
@ -244,7 +245,7 @@ class ConfigOptionParser(CustomOptionParser):
def error(self, msg):
self.print_usage(sys.stderr)
self.exit(2, "%s\n" % msg)
self.exit(UNKNOWN_ERROR, "%s\n" % msg)
def invalid_config_error_message(action, key, val):

View File

@ -18,7 +18,9 @@ import os
from pip._vendor import six
from pip._vendor.six.moves import configparser
from pip._internal.exceptions import ConfigurationError
from pip._internal.exceptions import (
ConfigurationError, ConfigurationFileCouldNotBeLoaded,
)
from pip._internal.locations import (
legacy_config_file, new_config_file, running_under_virtualenv,
site_config_files, venv_config_file,
@ -289,11 +291,16 @@ class Configuration(object):
try:
parser.read(fname)
except UnicodeDecodeError:
raise ConfigurationError((
"ERROR: "
"Configuration file contains invalid %s characters.\n"
"Please fix your configuration, located at %s\n"
) % (locale.getpreferredencoding(False), fname))
# See https://github.com/pypa/pip/issues/4963
raise ConfigurationFileCouldNotBeLoaded(
reason="contains invalid {} characters".format(
locale.getpreferredencoding(False)
),
fname=fname,
)
except configparser.Error as error:
# See https://github.com/pypa/pip/issues/4893
raise ConfigurationFileCouldNotBeLoaded(error=error)
return parser
def _load_environment_vars(self):

View File

@ -247,3 +247,22 @@ class HashMismatch(HashError):
class UnsupportedPythonVersion(InstallationError):
"""Unsupported python version according to Requires-Python package
metadata."""
class ConfigurationFileCouldNotBeLoaded(ConfigurationError):
"""When there are errors while loading a configuration file
"""
def __init__(self, reason="could not be loaded", fname=None, error=None):
super(ConfigurationFileCouldNotBeLoaded, self).__init__(error)
self.reason = reason
self.fname = fname
self.error = error
def __str__(self):
if self.fname is not None:
message_part = " in {}.".format(self.fname)
else:
assert self.error is not None
message_part = ".\n{}\n".format(self.error.message)
return "Configuration file {}{}".format(self.reason, message_part)

View File

@ -68,6 +68,23 @@ class TestConfigurationLoading(ConfigurationMixin):
with pytest.raises(ConfigurationError):
self.configuration.get_value(":env:.version")
def test_environment_config_errors_if_malformed(self):
contents = """
test]
hello = 4
"""
with self.tmpfile(contents) as config_file:
os.environ["PIP_CONFIG_FILE"] = config_file
with pytest.raises(ConfigurationError) as err:
self.configuration.load()
assert "section header" in str(err.value) # error kind
assert "1" in str(err.value) # line number
assert ( # file name
config_file in str(err.value) or
repr(config_file) in str(err.value)
)
class TestConfigurationPrecedence(ConfigurationMixin):
# Tests for methods to that determine the order of precedence of