-
-
Notifications
You must be signed in to change notification settings - Fork 611
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
Malformed .in results in uncaught exception #2139
Comments
Here is the code excerpt. Since the unexpected Exception is not caught, the exit code is not 2. The return variable name is When /piptools/scripts/compile.py", line 383
Notice the
|
Assign metadata.requirements to a variable within
then write a pytest test with the malformed .in file ">=24pip\n" |
Generator is a curse word! There are three cases in the piptools/scripts/compile.py lines: 366, 383, and 390 The solution is to not do that.
I get it. The code is easy to read, but that comes at the expense of not being DRY. |
Lets see how pip-compile performs given a purposefully malformed .in file. Normally would expect a pip-compile specific Exception and a non-zero exit code.
malformed-pip.in
>=24pip\n
Which is obviously malformed. Since a .in is user input, it can contain errors.
pip has vendored package, packaging. When packaging fails to parse a requirement, it produces this Exception chain
pip-compile does not gracefully catch the InstallationError. Instead just bombs with exit code 1 and the below traceback.
Environment Versions
OS: Linux distro Void Linux LXDE
Python version: Python 3.9.16
pip version: pip 24.3.1
pip-tools version: pip-compile, version 7.4.1
Steps to replicate
echo ">=24pip\n" > malformed-pip.in
pip-compile --allow-unsafe --no-header -o malformed-pip.txt malformed-pip.in
Expected result
pip-compile should catch the Exception in a try-except block. Exception is reraised with a pip-compile specific Exception. The entire traceback does not get shown.
Taken from the traceback, handling of the Exception doesn't happen here.
Actual result
Traceback (most recent call last):
File "[venv base path]/lib/python3.9/site-packages/pip/_vendor/packaging/requirements.py", line 36, in init
parsed = _parse_requirement(requirement_string)
File "[venv base path]/lib/python3.9/site-packages/pip/_vendor/packaging/_parser.py", line 62, in parse_requirement
return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES))
File "[venv base path]/lib/python3.9/site-packages/pip/_vendor/packaging/_parser.py", line 71, in _parse_requirement
name_token = tokenizer.expect(
File "[venv base path]/lib/python3.9/site-packages/pip/_vendor/packaging/_tokenizer.py", line 142, in expect
raise self.raise_syntax_error(f"Expected {expected}")
File "[venv base path]/lib/python3.9/site-packages/pip/_vendor/packaging/_tokenizer.py", line 167, in raise_syntax_error
raise ParserSyntaxError(
pip._vendor.packaging._tokenizer.ParserSyntaxError: Expected package name at the start of dependency specifier
>=24pip
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "[venv base path]/lib/python3.9/site-packages/pip/_internal/req/constructors.py", line 362, in _parse_req_string
return get_requirement(req_as_string)
File "[venv base path]/lib/python3.9/site-packages/pip/_internal/utils/packaging.py", line 45, in get_requirement
return Requirement(req_string)
File "[venv base path]/lib/python3.9/site-packages/pip/_vendor/packaging/requirements.py", line 38, in init
raise InvalidRequirement(str(e)) from e
pip._vendor.packaging.requirements.InvalidRequirement: Expected package name at the start of dependency specifier
>=24pip
^
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "[venv base path]/bin/pip-compile", line 8, in
sys.exit(cli())
File "[venv base path]/lib/python3.9/site-packages/click/core.py", line 1157, in call
return self.main(*args, **kwargs)
File "[venv base path]/lib/python3.9/site-packages/click/core.py", line 1078, in main
rv = self.invoke(ctx)
File "[venv base path]/lib/python3.9/site-packages/click/core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "[venv base path]/lib/python3.9/site-packages/click/core.py", line 783, in invoke
return __callback(*args, **kwargs)
File "[venv base path]/lib/python3.9/site-packages/click/decorators.py", line 33, in new_func
return f(get_current_context(), *args, **kwargs)
File "[venv base path]/lib/python3.9/site-packages/piptools/scripts/compile.py", line 383, in cli
constraints.extend(
File "[venv base path]/lib/python3.9/site-packages/piptools/_compat/pip_compat.py", line 77, in parse_requirements
yield install_req_from_parsed_requirement(parsed_req, isolated=isolated)
File "[venv base path]/lib/python3.9/site-packages/pip/_internal/req/constructors.py", line 480, in install_req_from_parsed_requirement
req = install_req_from_line(
File "[venv base path]/lib/python3.9/site-packages/pip/_internal/req/constructors.py", line 405, in install_req_from_line
parts = parse_req_from_line(name, line_source)
File "[venv base path]/lib/python3.9/site-packages/pip/_internal/req/constructors.py", line 379, in parse_req_from_line
req: Optional[Requirement] = _parse_req_string(req_as_string)
File "[venv base path]/lib/python3.9/site-packages/pip/_internal/req/constructors.py", line 376, in _parse_req_string
raise InstallationError(msg)
pip._internal.exceptions.InstallationError: Invalid requirement: '>=24pip': Expected package name at the start of dependency specifier
>=24pip
^ (from line 1 of /tmp/pytest-of-chaosmonkey/pytest-24/test_compile_malformed_in_mix_0/requirements/malformed-pip.in)
The text was updated successfully, but these errors were encountered: