python / python/cpython

Make it easier to extend zipfile code

未关闭
#136,741 22 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

stdlib type-feature
主要语言
Python
星标
77.2k
派生
35.9k
PR 合并指标
PR 指标待抓取

描述

Feature or enhancement

Proposal:

This is follow up from https://github.com/python/cpython/issues/53416

Even if stdlib will never support WinZIP AES encrpyption, it would be useful to allow for downstream project to implement it.

There is pyzipper based on a fork but the code is now very different to what we have in stdlib.


it would help if the stdlib zipfile code is written to allow dependency injection

A very simple proof of concept downstream code is here that can only read AES ZIP files is here

https://github.com/chevah/zipfile-aes


It is using a patch for stdblib that looks like this

--- lib/python3.12/zipfile/__init__.py        2025-07-17 11:19:59.376677338 +0100
+++ src/dev_tools/zipfile_init.py       2025-07-17 11:21:50.797894299 +0100
@@ -1286,6 +1286,9 @@
 
     """
 
+    _ZipInfo = ZipInfo
+    _ZipExtFile = ZipExtFile
+
     fp = None                   # Set here since __del__ checks it
     _windows_illegal_name_trans_table = None
 
@@ -1456,7 +1459,7 @@
                 # Historical ZIP filename encoding
                 filename = filename.decode(self.metadata_encoding or 'cp437')
             # Create ZipInfo instance to store file information
-            x = ZipInfo(filename)
+            x = self._ZipInfo(filename)
             x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
             x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
             x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
@@ -1592,11 +1595,11 @@
                 "Attempt to use ZIP archive that was already closed")
 
         # Make sure we have an info object
-        if isinstance(name, ZipInfo):
+        if isinstance(name, self._ZipInfo):
             # 'name' is already an info object
             zinfo = name
         elif mode == 'w':
-            zinfo = ZipInfo(name)
+            zinfo = self._ZipInfo(name)
             zinfo.compress_type = self.compression
             zinfo._compresslevel = self.compresslevel
         else:
@@ -1664,7 +1667,7 @@
             else:
                 pwd = None
 
-            return ZipExtFile(zef_file, mode, zinfo, pwd, True)
+            return self._ZipExtFile(zef_file, mode, zinfo, pwd, True)
         except:
             zef_file.close()
             raise
@@ -1762,7 +1765,7 @@
         """Extract the ZipInfo object 'member' to a physical
            file on the path targetpath.
         """
-        if not isinstance(member, ZipInfo):
+        if not isinstance(member, self._ZipInfo):
             member = self.getinfo(member)
 
         # build the destination pathname, replacing
@@ -1838,7 +1841,7 @@
                 "Can't write to ZIP archive while an open writing handle exists"
             )
 
-        zinfo = ZipInfo.from_file(filename, arcname,
+        zinfo = self._ZipInfo.from_file(filename, arcname,
                                   strict_timestamps=self._strict_timestamps)
 
         if zinfo.is_dir():
@@ -1868,8 +1871,8 @@
         the name of the file in the archive."""
         if isinstance(data, str):
             data = data.encode("utf-8")
-        if not isinstance(zinfo_or_arcname, ZipInfo):
-            zinfo = ZipInfo(filename=zinfo_or_arcname,
+        if not isinstance(zinfo_or_arcname, self._ZipInfo):
+            zinfo = self._ZipInfo(filename=zinfo_or_arcname,
                             date_time=time.localtime(time.time())[:6])
             zinfo.compress_type = self.compression
             zinfo._compresslevel = self.compresslevel
@@ -1910,7 +1913,7 @@
             directory_name = zinfo_or_directory_name
             if not directory_name.endswith("/"):
                 directory_name += "/"
-            zinfo = ZipInfo(directory_name)
+            zinfo = self._ZipInfo(directory_name)
             zinfo.compress_size = 0
             zinfo.CRC = 0
             zinfo.external_attr = ((0o40000 | mode) & 0xFFFF) << 16

Would you consider such a patch ?

Thanks

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

https://github.com/python/cpython/issues/53416

https://github.com/python/cpython/issues/81719

PR at https://github.com/python/cpython/pull/14957

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 lib/python3.12/zipfile/init.py 开始,重点查看 ZipFile、ZipInfo 和 ZipExtFile,然后审阅 issue 53416 和 81719 以及 PR 14957,了解之前的设计讨论。当下游项目无需维护 fork 即可扩展 zipfile 实现以支持 AES 等功能,并且已根据相关行为验证所接受的扩展机制时,即视为完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
tooling
Issue 类型
功能
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
需要澄清
新手友好度
30/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。