Skip to content
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

Trace a better error message on installation failure due to invalid .data files in wheels #8656

Merged
merged 3 commits into from
Aug 2, 2020

Conversation

chrahunt
Copy link
Member

@chrahunt chrahunt commented Jul 29, 2020

This explicitly handles erroneous files in the .data directory of wheels.

Before:

ERROR: Exception:
Traceback (most recent call last):
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/cli/base_command.py", line 216, in _main
    status = self.run(options, args)
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/cli/req_command.py", line 182, in wrapper
    return func(self, options, args)
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/commands/install.py", line 421, in run
    pycompile=options.compile,
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/req/__init__.py", line 90, in install_given_reqs
    pycompile=pycompile,
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/req/req_install.py", line 831, in install
    requested=self.user_supplied,
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/operations/install/wheel.py", line 830, in install_wheel
    requested=requested,
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/operations/install/wheel.py", line 658, in _install_wheel
    for file in files:
  File "/tmp/venv/lib/python3.6/site-packages/pip/_internal/operations/install/wheel.py", line 587, in make_data_scheme_file
    _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2)
ValueError: not enough values to unpack (expected 3, got 2)

After:

ERROR: For req: python-apt==0.0.0. Unexpected file in /home/chris/.cache/pip/wheels/ff/46/14/4b2fa60308f0a0cf20345e549cb154c557f117417af56cf5f7/python_apt-0.0.0-cp38-cp38-linux_x86_64.whl: 'python_apt-0.0.0.data/purelib'. .data directory contents should be named like: '<scheme key>/<path>'.

While updating this error message, I noticed the very next line was subject to throwing a similarly confusing error. That has also been updated.

Fixes #8654.

Previously our wheel installation process allowed wheels which contained
non-conforming contents in a contained .data directory.

After the refactoring to enable direct-from-wheel installation, pip
throws an exception when encountering these wheels, but does not include
any helpful information to pinpoint the cause.

Now if we encounter such a wheel, we trace an error that includes the
name of the requirement we're trying to install, the path to the wheel
file, the path we didn't understand, and a hint about what we expect.
@chrahunt chrahunt changed the title gracefully handle bad data paths Trace a better error message on installation failure due to invalid .data files in wheels Jul 29, 2020
@chrahunt chrahunt force-pushed the gracefully-handle-bad-data-paths branch from 3f0dd40 to 517af16 Compare July 29, 2020 22:22
@uranusjr
Copy link
Member

uranusjr commented Jul 29, 2020

Are files in the .data root disallowed? PEP 427 does not seem to explicitly say it.

@chrahunt chrahunt marked this pull request as ready for review July 29, 2020 23:17
@chrahunt
Copy link
Member Author

I could see it interpreted either way, which means it could probably use a clarifying update.

With regards to the pip behavior, our current and past implementations disallowed it in general. Example with pip 20.1:

$ ./.tox/py38/bin/python
Python 3.8.0 (default, Jan  4 2020, 14:08:19)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from tests.lib.wheel import make_wheel
>>> make_wheel("simple", "0.1.0", extra_data_files={"abc": "hello.txt"}).save_to_dir("/tmp/user/1000/tmp.E0kpIwbLtL")
'/tmp/user/1000/tmp.E0kpIwbLtL/simple-0.1.0-py2.py3-none-any.whl'
>>>

Then in that directory with a pip 20.1:

$ ./env/bin/python -m pip install '/tmp/user/1000/tmp.E0kpIwbLtL/simple-0.1.0-py2.py3-none-any.whl'
Processing ./simple-0.1.0-py2.py3-none-any.whl
Installing collected packages: simple
ERROR: Exception:
Traceback (most recent call last):
  File "/tmp/user/1000/tmp.E0kpIwbLtL/env/lib/python3.8/site-packages/pip/_internal/cli/base_command.py", line 188, in _main
    status = self.run(options, args)
  File "/tmp/user/1000/tmp.E0kpIwbLtL/env/lib/python3.8/site-packages/pip/_internal/cli/req_command.py", line 185, in wrapper
    return func(self, options, args)
  File "/tmp/user/1000/tmp.E0kpIwbLtL/env/lib/python3.8/site-packages/pip/_internal/commands/install.py", line 398, in run
    installed = install_given_reqs(
  File "/tmp/user/1000/tmp.E0kpIwbLtL/env/lib/python3.8/site-packages/pip/_internal/req/__init__.py", line 67, in install_given_reqs
    requirement.install(
  File "/tmp/user/1000/tmp.E0kpIwbLtL/env/lib/python3.8/site-packages/pip/_internal/req/req_install.py", line 804, in install
    install_wheel(
  File "/tmp/user/1000/tmp.E0kpIwbLtL/env/lib/python3.8/site-packages/pip/_internal/operations/install/wheel.py", line 622, in install_wheel
    install_unpacked_wheel(
  File "/tmp/user/1000/tmp.E0kpIwbLtL/env/lib/python3.8/site-packages/pip/_internal/operations/install/wheel.py", line 452, in install_unpacked_wheel
    dest = getattr(scheme, subdir)
AttributeError: 'Scheme' object has no attribute 'abc'
WARNING: You are using pip version 20.1; however, version 20.2 is available.
You should consider upgrading via the '/tmp/user/1000/tmp.E0kpIwbLtL/env/bin/python -m pip install --upgrade pip' command.

When the file happened to be named the same as a scheme key (which is the case in #8654), we silently ignored it.

@uranusjr
Copy link
Member

cc @dholth for wheel spec inputs.

Copy link
Member

@uranusjr uranusjr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation looks good to me, just a minor comment but I wouldn’t mind if this is merged without it.

src/pip/_internal/operations/install/wheel.py Outdated Show resolved Hide resolved
Originally we would throw an `AttributeError` if a bad scheme key was
used. After refactoring we would throw a `KeyError`, which isn't much
better. Now we call out the wheel being processed, scheme key we didn't
recognize, and provide a list of the valid scheme keys. This would
likely be useful for people developing/testing the wheel.
@chrahunt chrahunt force-pushed the gracefully-handle-bad-data-paths branch from 517af16 to 127c5b0 Compare July 30, 2020 02:25
Copy link

@cjp256 cjp256 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you for addressing this so quickly 👍

@pradyunsg pradyunsg added this to the 20.2 milestone Jul 30, 2020
@pradyunsg pradyunsg modified the milestones: 20.2, 20.2.1 Aug 2, 2020
Copy link
Contributor

@eamanu eamanu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :)

@pradyunsg
Copy link
Member

Looks like everyone agrees that this is good to go, so I'll click merge. git will blame Chris if things break anyway. :P

@pradyunsg pradyunsg merged commit 7e6ff08 into pypa:master Aug 2, 2020
@chrahunt chrahunt deleted the gracefully-handle-bad-data-paths branch August 2, 2020 18:45
pradyunsg added a commit to pradyunsg/pip that referenced this pull request Aug 4, 2020
…-paths

Trace a better error message on installation failure due to invalid .data files in wheels
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

pip 20.2 - ValueError exception on improperly formatted package
6 participants