Skip to content

Using pip.override() to patch a wheel that includes a file with a name containing commas fails #2261

@kcon-stackav

Description

@kcon-stackav

🐞 bug report

Affected Rule

The issue is caused by the rule:

pip.override(): https://rules-python.readthedocs.io/en/latest/api/rules_python/python/extensions/pip.html#pip.override

Is this a regression?

No

Description

I'm using pip.override() to patch a wheel that (unfortunately) includes files whose name contain commas, and when I try to build a target that uses that patched wheel as a dependency, Bazel fails with the error below, I think because rules_python is not quoting those filenames in the updated RECORD file to avoid https://pypi.org/project/installer/ parsing them incorrectly when the wheel is later installed.

🔥 Exception or Error

Traceback (most recent call last):
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~~python~python_3_10_x86_64-unknown-linux-gnu/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~~python~python_3_10_x86_64-unknown-linux-gnu/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~/python/private/pypi/whl_installer/wheel_installer.py", line 205, in <module>
    main()
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~/python/private/pypi/whl_installer/wheel_installer.py", line 160, in main
    _extract_wheel(
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~/python/private/pypi/whl_installer/wheel_installer.py", line 121, in _extract_wheel
    whl.unzip(installation_dir)
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~/python/private/pypi/whl_installer/wheel.py", line 377, in unzip
    installer.install(
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~~internal_deps~pypi__installer/installer/_core.py", line 96, in install
    for record_elements, stream, is_executable in source.get_contents():
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~~internal_deps~pypi__installer/installer/sources.py", line 301, in get_contents
    record_mapping = {record[0]: record for record in records}
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~~internal_deps~pypi__installer/installer/sources.py", line 301, in <dictcomp>
    record_mapping = {record[0]: record for record in records}
  File "/home/kevin/.bazel/d13b924e1e99a7808dc764c718e83a2c/external/rules_python~~internal_deps~pypi__installer/installer/records.py", line 214, in parse_record_file
    raise InvalidRecordEntry(elements=elements, issues=[message])
installer.records.InvalidRecordEntry: Row Index 360: expected 3 elements, got 5

🌍 Your Environment

Operating System:

❯ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.4 LTS"

❯ uname -m                                                                 
x86_64

Output of bazel version:

❯ bazel --version                                                            
bazel 7.2.1

Rules_python version:

0.36.0

Anything else relevant?

To work around this issue I'm patching rules_python with this diff that appears to fix the issue:

diff --git tools/wheelmaker.py tools/wheelmaker.py
index 68578b8e..f9041e3a 100644
--- tools/wheelmaker.py
+++ tools/wheelmaker.py
@@ -212,7 +212,7 @@ class _WhlFile(zipfile.ZipFile):
         for filename, digest, size in entries:
             if isinstance(filename, str):
                 filename = filename.lstrip("/").encode("utf-8", "surrogateescape")
-            contents += b"%s,%s,%s\n" % (filename, digest, size)
+            contents += b'"%s",%s,%s\n' % (filename, digest, size)
 
         self.add_string(record_path, contents)
         return contents

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions