pypa/wheel

Wheel build failure on AIX with 0.33.2

Closed this issue · 2 comments

The latest release introduces a bug on AIX which results in the following error when closing the wheel archive:

error: 'L' format requires 0 <= number <= 4294967295

The issue can be reliably reproduced by running the test suite on AIX. The full traceback from the test_wheelfile.py - test_directories test:

   def test_directories(tmpdir, wheel_path):
        """
        The WheelFile should contain entries for directories,
        empty and not.
        """
        build_dir = tmpdir
        sub_dir = build_dir / 'sub'
        sub_dir.mkdir()
        (sub_dir / '__init__.py').write_text('', encoding='utf-8')
        empty_dir = build_dir / 'empty'
        empty_dir.mkdir()

        with WheelFile(wheel_path, 'w') as wf:
>           wf.write_files(str(build_dir))

tests/test_wheelfile.py:191:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/opt/bb/lib/python2.7/zipfile.py:801: in __exit__
    self.close()
wheel/wheelfile.py:181: in close
    ZipFile.close(self)
...
                    try:
                        filename, flag_bits = zinfo._encodeFilenameFlags()
                        centdir = struct.pack(structCentralDir,
                        stringCentralDir, create_version,
                        zinfo.create_system, extract_version, zinfo.reserved,
                        flag_bits, zinfo.compress_type, dostime, dosdate,
                        zinfo.CRC, compress_size, file_size,
                        len(filename), len(extra_data), len(zinfo.comment),
                        0, zinfo.internal_attr, zinfo.external_attr,
>                       header_offset)
E                       error: 'L' format requires 0 <= number <= 4294967295

/opt/bb/lib/python2.7/zipfile.py:1315: error

I believe this is due to #289. The root cause seems to be something with the attributes set on the directory entries on the zip archive. The following patch fixes the issue:

diff --git a/wheel/wheelfile.py b/wheel/wheelfile.py
index 93b4bfa..579e179 100644
--- a/wheel/wheelfile.py
+++ b/wheel/wheelfile.py
@@ -145,7 +145,6 @@ class WheelFile(ZipFile):
     def mkdir(self, filename, arcname):
         st = os.stat(filename)
         zinfo = ZipInfo(arcname + '/', date_time=get_zipinfo_datetime(st.st_mtime))
-        zinfo.external_attr = st.st_mode << 16
         zinfo.compress_type = ZIP_DEFLATED
         self.writestr(zinfo, b'')

I will have to investigate further to determine what exactly is happening here.

In the two places that do:

zinfo.external_attr = st.st_mode << 16

I'm pretty sure that the fix is using stat.S_IMODE(st.st_mode) << 16 instead. Without that the mode is including the S_IFMT bits that define the file's type ("directory", in the failing case), and on AIX it's also including the S_IFJOURNAL bit (for, I assume, whether the filesystem is journaled?) and causing the problem @lkollar saw.

I've released v0.33.3 to fix this.