GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — ZipFile.extractall fails if zipfile.Path object is created based on the ZipFile object · Issue #101566 · python/cpython

ZipFile.extractall fails if zipfile.Path object is created based on the ZipFile object #101566

New issue
Copy link
New issue
Copy link
Closed
jaraco/zipp
#90
jaraco/zipp#90
Closed
ZipFile.extractall fails if zipfile.Path object is created based on the ZipFile object#101566
jaraco/zipp
#90
Copy link
Assignees
jaraco
Labels
3.10 (EOL)end of lifeend of life3.11only security fixesonly security fixes3.12only security fixesonly security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@mmohrhard
mmohrhard
opened on Feb 4, 2023
Issue body actions

Bug report

The following code works fine with Python 3.8 and 3.9 but starts failing with Python 3.10.

It seems that zipfile.Path creates an entry in the zipfile.ZipFile object that does not exist in the underlying file and therefore makes zipfile.ZipFile.extractall fail.

import zipfile
import tempfile

path = tempfile.mktemp()

f = zipfile.ZipFile(path, "w")
f.writestr("data/test.txt", "test1")
f.writestr("data/test2.txt", "test2")
f.close()

dest = tempfile.mkdtemp()

p = zipfile.ZipFile(path)
src_zipfile_path = zipfile.Path(p, "data")
p.extractall(dest)

Your environment

Working version:

(python39) [moggi@mars cloudfluid]$ python --version
Python 3.9.16
(python39) [moggi@mars cloudfluid]$ python test.py
(python39) [moggi@mars cloudfluid]$ 

Failing versions:

3.10.9:

(python_310_2) [moggi@mars cloudfluid]$ python --version
Python 3.10.9
(python_310_2) [moggi@mars cloudfluid]$ python test.py
Traceback (most recent call last):
  File "/home/moggi/devel/cloudfluid/test.py", line 15, in <module>
    p.extractall(dest)
  File "/home/moggi/devel/envs/python_310_2/lib/python3.10/zipfile.py", line 1645, in extractall
    self._extract_member(zipinfo, path, pwd)
  File "/home/moggi/devel/envs/python_310_2/lib/python3.10/zipfile.py", line 1667, in _extract_member
    member = self.getinfo(member)
  File "/home/moggi/devel/envs/python_310_2/lib/python3.10/zipfile.py", line 1441, in getinfo
    raise KeyError(
KeyError: "There is no item named 'data/' in the archive"

and 3.11.0

(python311) [moggi@mars cloudfluid]$ python --version
Python 3.11.0
(python311) [moggi@mars cloudfluid]$ python test.py
Traceback (most recent call last):
  File "/home/moggi/devel/cloudfluid/test.py", line 15, in <module>
    p.extractall(dest)
  File "/home/moggi/devel/envs/python311/lib/python3.11/zipfile.py", line 1677, in extractall
    self._extract_member(zipinfo, path, pwd)
  File "/home/moggi/devel/envs/python311/lib/python3.11/zipfile.py", line 1699, in _extract_member
    member = self.getinfo(member)
             ^^^^^^^^^^^^^^^^^^^^
  File "/home/moggi/devel/envs/python311/lib/python3.11/zipfile.py", line 1473, in getinfo
    raise KeyError(
KeyError: "There is no item named 'data/' in the archive"

If this is the expected new behavior I think the documentation for 3.10 should mention this breaking change and the zipfile.Path documentation might need an entry about this problem.

The zipfile.Path object is used in the original code to check if the "data/" directory exists in the zip file.

Linked PRs

  • gh-101566: Sync with zipp 3.14. #102018
  • [3.11] gh-101566: Sync with zipp 3.14. (GH-102018). #102090
  • [3.10] gh-101566: Sync with zipp 3.14. (GH-102018). #102091
Reacted by Jason R. Coombs

Activity

Next
  1. mmohrhard
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Feb 4, 2023
  2. arhadthedev
    added
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Feb 4, 2023
  3. arhadthedev commented on Feb 4, 2023

    @arhadthedev
    arhadthedev
    on Feb 4, 2023
    Member
    More actions

    @serhiy-storchaka, @Yhg1s, @gpshead as zipfile experts.

  4. gpshead
    added
    3.11only security fixesonly security fixes
    3.10 (EOL)end of lifeend of life
    3.12only security fixesonly security fixes
    on Feb 4, 2023
  5. gpshead commented on Feb 4, 2023

    @gpshead
    gpshead
    on Feb 4, 2023
    Member
    More actions

    @jaraco

  6. gpshead
    assigned
    jaraco
    on Feb 4, 2023
  7. jaraco commented on Feb 5, 2023

    @jaraco
    jaraco
    on Feb 5, 2023
    Member
    More actions

    This issue occurs because of the optimizations / tradeoffs made in attempting to extend an open file object. Here's what's going on:

    • zipfile.Path needs to be able to infer directories when there are none in the zipfile (i.e. the presence of data/test.txt implies the presence of data/ even though it's not explicitly a member of the zipfile).
    • To accomplish this goal, the CompleteDirs wraps the original zipfile.
    • Due to challenges with the lifecycle of a zipfile (which may have been created in memory or exist on disk as an open file), wrapping a Zipfile in a Path actually mutates its class, giving the original Zipfile object the CompleteDirs behavior.
    • In extractall, it's assumed that every item in the namelist is also a member, but with CompleteDirs, that's no longer true.

    This report is the first I've seen that this (admittedly impure) behavior has caused any trouble.

    I agree that at the very least, it's worthwhile documenting these limitations.

    I did try to track down the origins of the change that led to this regression in behavior. I took a brief look at the readme for zipp, the forward/backport, and it doesn't mention any changes for Python 3.10 (now updated to reflect new findings).

    Okay. I see the change occurred in ebbe803, bpo-40564/#84744. That bug pretty thoroughly describes the thought process and the tradeoffs considered.

    I can think of a few ways to address the issue.

    • document it as unsupported behavior
    • document it as unsupported behavior, but provide a mechanism to restore the original object
    • add support for zipfile.Zipfile to be lenient to dirs not present
    • add support to CompleteDirs to return a virtual member info for an implied dir
    • CompleteDirs to override extractall to bypass the issue

    I'm leaning toward (3) or (4). (4) has an advantage over all of the other options in that, if it can be implemented, it provides better compatibility for more use cases (not just ZipFile.extractall).

  8. jaraco
    added 3 commits that reference this issue on Feb 5, 2023

    Add xfail test capturing missed expectation. Ref python/cpython#101566.

    29b95e1

    Override ZipFile.getinfo to supply a ZipInfo for implied dirs. Fixes p…

    6f8ae4c

    Update changelog. Ref python/cpython#101566.

    7bf2869
  9. jaraco commented on Feb 5, 2023

    @jaraco
    jaraco
    on Feb 5, 2023
    Member
    More actions

    In jaraco/zipp#90, I've drafted a patch implementing option 4, to be released as zipp 3.12.1. I'd like to get some feedback on the concept before porting that to cpython.

    Reacted by Gregory P. Smith
  10. jaraco
    closed this as completedin jaraco/zipp#90on Feb 5, 2023
  11. jaraco
    reopened this on Feb 5, 2023
  12. 2 remaining items

  13. jaraco
    added 2 commits that reference this issue on Feb 18, 2023

    pythongh-101566: Sync with zipp 3.14.

    77e76a1

    pythongh-101566: Sync with zipp 3.14.

    c23d6fb
  14. miss-islington
    added a commit that references this issue on Feb 20, 2023

    gh-101566: Sync with zipp 3.14. (GH-102018)

    36854bb
  15. jaraco
    added 3 commits that reference this issue on Feb 20, 2023

    [3.11] pythongh-101566: Sync with zipp 3.14. (pythonGH-102018).

    0357993

    [3.11] pythongh-101566: Sync with zipp 3.14. (pythonGH-102018).

    423bab4

    [3.10] pythongh-101566: Sync with zipp 3.14. (pythonGH-102018).

    7ffb276
  16. miss-islington
    added 2 commits that reference this issue on Feb 20, 2023

    [3.10] gh-101566: Sync with zipp 3.14. (GH-102018). (GH-102091)

    7bb41d9

    [3.11] gh-101566: Sync with zipp 3.14. (GH-102018). (GH-102090)

    d15e958
  17. carljm
    added 3 commits that reference this issue on Feb 20, 2023

    Merge branch 'main' into inlinecomp2

    9f0fc5b

    Merge branch 'main' into inlinecomp

    544b30c

    Merge branch 'main' into lockfreecp

    b257a16
  18. jaraco commented on Jul 14, 2023

    @jaraco
    jaraco
    on Jul 14, 2023
    Member
    More actions

    This issue was closed back in Feb.

  19. jaraco
    closed this as completedon Jul 14, 2023
  20. python-sidebar
    added 2 commits that reference this issue on Sep 1, 2024

    pythongh-101566: Sync with zipp 3.14. (pythonGH-102018)

    e7bd72c

    pythongh-101566: Sync with zipp 3.14. (pythonGH-102018)

    f0de686
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @jaraco
    jaraco

Labels

3.10 (EOL)end of lifeend of life3.11only security fixesonly security fixes3.12only security fixesonly security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.