-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes 4893 - error handling for malformed configurations #5026
Conversation
Hmm, I'm actually stumped about the build failure. It looks like one is a timeout and one is a mypy error. The mypy error appears to relate to my first question as to which exceptions we want to be handling here: So maybe catching MissingSectionHeader is not appropriate? However, I'm still not sure why it would get flagged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this review has been sitting idle for a bit. Sorry for the wait. :(
tests/unit/test_configuration.py
Outdated
@@ -46,6 +46,17 @@ def test_environment_config_loading(self): | |||
assert self.configuration.get_value("test.hello") == "4", \ | |||
self.configuration._config | |||
|
|||
def test_environment_config_errors_if_malformed(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel a better idea would be to create a new class called TestConfigurationLoadingErrors(ConfigurationMixin)
in the same file and move this test there.
I imagine I'll add more tests to such a class in the future.
news/4893.bugfix
Outdated
@@ -0,0 +1 @@ | |||
Add handling for configparser errors when conf is malformed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Malformed configuration files now show helpful error messages, instead of tracebacks.
src/pip/_internal/configuration.py
Outdated
@@ -292,6 +292,13 @@ def _construct_parser(self, fname): | |||
"Configuration file contains invalid %s characters.\n" | |||
"Please fix your configuration, located at %s\n" | |||
) % (locale.getpreferredencoding(False), fname)) | |||
except configparser.MissingSectionHeaderError: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error here seems to be caused by an incorrect declaration in typeshed.
For now, you can add a # type: ignore
to the end of this line and a comment above that links to python/typeshed#1883.
src/pip/_internal/configuration.py
Outdated
"ERROR: " | ||
"Configuration file headers cannot be parsed. \n" | ||
"Please fix the section formatting of the " | ||
"configuration located at %s.\n" % fname |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the "." at the end -- that way it is easier to just copy the entire path by selecting everything after "at".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This message should mention the lineno
from the error raised. That would be helpful while trying to locate the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thought, we should also add a handler after this for ParsingError
since they may be raised for other reasons.
tests/unit/test_configuration.py
Outdated
|
||
with pytest.raises(ConfigurationError): | ||
self.configuration.load() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should check for the word "malformed" (or something similar), the line number and the file path are mentioned in the error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean that it should check for all three of those things in the error message string? Presumably inside of the with block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with pytest.raises(ConfigurationError) as err:
self.configuration.load()
assert "malformed" in str(err)
assert lineno in str(err)
assert filepath in str(err)
About the mypy error, it was a bug in typeshed, fixed it in python/typeshed@b6bd582. I noted the workaround above. :) |
@fishd Are you likely to have time to resolve this in the coming week? Pip 10 beta will be released at the weekend, and if this PR can't be merged by then, I'd prefer to defer it until post pip 10 final. |
Yes, sorry that I sat on it for so long! I can get it resolved in the next few days. |
This comment has been minimized.
This comment has been minimized.
Sorry, but this is going to have to wait until post-10.0 now. |
Fine by me. |
Ping @fishd |
Hi, I am not dead. Thank you for your patience. I have some clarifying questions. I'll attempt to add those as inline comments... |
src/pip/_internal/configuration.py
Outdated
raise ConfigurationError( | ||
"ERROR: " | ||
"Configuration file cannot be parsed. \n" | ||
"%s\n" % e.message |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is killing the CI build (no "message" attribute), but I can't seem to reproduce it. I suspect something about what I'm doing is bad practice...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just do str(e)
here. It'll result in the same output: https://github.com/python/cpython/blob/3.6/Lib/configparser.py#L174
@fishd You seem to have rebased incorrectly. |
Whoops. I feel like that looks different than it did on my local branch...I'll investigate. |
Remove period for easier path copying Move config parsing error to new class 4893 - Add line number, add handling for generic ParsingErrors. Remove whitespace. Convert parsing error to string PEP8 - reformat line break
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Older inline comments still apply.
@fishd Do you have the time to make the requested changes? If not, I'll be happy to take this from here -- I'd like this to be a part of the next release. |
Pushing this down the road to the next release since I don't think this'd happen in time for 18.0. |
Adds more checks and skips creating a new class.
I'll take this up and redo this PR, reusing messages from the stdlib configparser. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
This fixes #4893 . In the event that a pip conf has malformed headers, it will handle the error and raise a specific message. Previously, pip would exit with a traceback.
Two things I'm uncertain about: