diff --git a/src/pip/_internal/operations/install/wheel.py b/src/pip/_internal/operations/install/wheel.py index 0bd7b28be..681fc0aa8 100644 --- a/src/pip/_internal/operations/install/wheel.py +++ b/src/pip/_internal/operations/install/wheel.py @@ -592,7 +592,19 @@ def _install_wheel( ).format(wheel_path, record_path) raise InstallationError(message) - scheme_path = scheme_paths[scheme_key] + try: + scheme_path = scheme_paths[scheme_key] + except KeyError: + valid_scheme_keys = ", ".join(sorted(scheme_paths)) + message = ( + "Unknown scheme key used in {}: {} (for file {!r}). .data" + " directory contents should be in subdirectories named" + " with a valid scheme key ({})" + ).format( + wheel_path, scheme_key, record_path, valid_scheme_keys + ) + raise InstallationError(message) + dest_path = os.path.join(scheme_path, dest_subpath) assert_no_path_traversal(scheme_path, dest_path) return ZipBackedFile(record_path, dest_path, zip_file) diff --git a/tests/functional/test_install_wheel.py b/tests/functional/test_install_wheel.py index 89d24a62f..ad4e74967 100644 --- a/tests/functional/test_install_wheel.py +++ b/tests/functional/test_install_wheel.py @@ -699,3 +699,18 @@ def test_wheel_with_file_in_data_dir_has_reasonable_error( "install", "--no-index", str(wheel_path), expect_error=True ) assert "simple-0.1.0.data/{}".format(name) in result.stderr + + +def test_wheel_with_unknown_subdir_in_data_dir_has_reasonable_error( + script, tmpdir +): + wheel_path = make_wheel( + "simple", + "0.1.0", + extra_data_files={"unknown/hello.txt": "hello world"} + ).save_to_dir(tmpdir) + + result = script.pip( + "install", "--no-index", str(wheel_path), expect_error=True + ) + assert "simple-0.1.0.data/unknown/hello.txt" in result.stderr