python / python/cpython

Make it easier to extend zipfile code

Aberta
#136,741 22 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

stdlib type-feature
Linguagem predominante
Python
Estrelas
77.2k
Forks
35.9k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

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

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece por lib/python3.12/zipfile/init.py, especialmente por ZipFile, ZipInfo e ZipExtFile; depois, revise as issues 53416 e 81719 e a PR 14957 para consultar discussões anteriores de design. Considera-se concluído quando projetos downstream puderem estender a implementação de zipfile para recursos como suporte a AES sem manter um fork, e o mecanismo de extensão aceito tiver sido validado em relação ao comportamento relevante.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
tooling
Tipo de issue
Funcionalidade
Dificuldade
5/5
Tempo estimado
Mais de uma semana
Status de atividade
Estagnada
Clareza
Precisa de esclarecimento
Facilidade para iniciantes
30/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.