Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ZipFile.Path print failed when built zip file is based on a bytes stream #109200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
the-cat-that-codes opened this issue Sep 9, 2023 · 1 comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@the-cat-that-codes
Copy link

the-cat-that-codes commented Sep 9, 2023

Bug report

Bug description:

Hi,

The print() function of a zipfile.Path failed if the ZipFile is based on a bytes stream.
More generally, every try to display or build a path based on bytes stream ZipFile path seems to fail.

A zip file is needed for playing this use case.
The mine is composed like this :

folder_root
├── folder_depth1
│ ├── folder_depth2
│ │ ├── folder_depth3
│ │ │ └── Python-Logo.png
│ │ └── Python-Logo.png
│ └── Python-Logo.png
└── Python-Logo.png
and is named "my_package.zip"

To trigger the problem I type these commands :

from zipfile import ZipFile, Path as ZPath
from io import BytesIO

with open("my_package.zip", "rb") as f:
    my_bytes=BytesIO(f.read())

my_zf_from_file=ZipFile("my_package.zip")

for i in ZPath(my_zf_from_file).iterdir():
     print(i)
 
my_zf_from_bytes=ZipFile(my_bytes)
for i in ZPath(my_zf_from_bytes).iterdir():
     print(i)

Here is my output:

>>> from zipfile import ZipFile, Path as ZPath
>>> from io import BytesIO
>>> with open("my_package.zip", "rb") as f:
...     my_bytes=BytesIO(f.read())
... 
>>> my_zf_from_file=ZipFile("my_package.zip")
>>> for i in ZPath(my_zf_from_file).iterdir():
...      print(i)
... 
my_package.zip/folder_root/
>>> my_zf_from_bytes=ZipFile(my_bytes)
>>> for i in ZPath(my_zf_from_bytes).iterdir():
...      print(i)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python3.9/zipfile.py", line 2347, in __str__
    return posixpath.join(self.root.filename, self.at)
  File "/usr/lib/python3.9/posixpath.py", line 76, in join
    a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not NoneType

To have more information I wrote this function

def mywalk(top):
    dirs=[]
    files=[]
    for item in top.iterdir():
            if item.is_file():
                    files.append(item)
            elif item.is_dir():
                    dirs.append(item)
    yield top.name, dirs, files
    for d in dirs:
            for w in mywalk(d):
                    yield w

and then, launch it, like this

for w in mywalk(ZPath(my_zf_from_bytes)):
     print(w)
 
for w in mywalk(ZPath(my_zf_from_file)):
     print(w)

Here is my output:

>>> for w in mywalk(ZPath(my_zf_from_bytes)):
...      print(w)
...  
... 
('', [Path(None, 'folder_root/')], [])
('folder_root', [Path(None, 'folder_root/folder_depth1/')], [Path(None, 'folder_root/Python-Logo.png')])
('folder_depth1', [Path(None, 'folder_root/folder_depth1/folder_depth2/')], [Path(None, 'folder_root/folder_depth1/Python-Logo.png')])
('folder_depth2', [Path(None, 'folder_root/folder_depth1/folder_depth2/folder_depth3/')], [Path(None, 'folder_root/folder_depth1/folder_depth2/Python-Logo.png')])
('folder_depth3', [], [Path(None, 'folder_root/folder_depth1/folder_depth2/folder_depth3/Python-Logo.png')])
>>> 
>>> for w in mywalk(ZPath(my_zf_from_file)):
...      print(w)
... 
('', [Path('my_package.zip', 'folder_root/')], [])
('folder_root', [Path('my_package.zip', 'folder_root/folder_depth1/')], [Path('my_package.zip', 'folder_root/Python-Logo.png')])
('folder_depth1', [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/')], [Path('my_package.zip', 'folder_root/folder_depth1/Python-Logo.png')])
('folder_depth2', [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/folder_depth3/')], [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/Python-Logo.png')])
('folder_depth3', [], [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/folder_depth3/Python-Logo.png')])

In the first case (zipfile path based on a bytes stream), the Path-like objects have 'None' as root when the root is the name of the package in the second case (zipfile path made based on the file).

My though is that a path is not intended to bring a NoneType element and so a path.join failed when a transformation into a string is needed.
What about change this "None" by an empty string ?

CPython versions tested on:

3.8, 3.9

Operating systems tested on:

Linux

@the-cat-that-codes the-cat-that-codes added the type-bug An unexpected behavior, bug, or error label Sep 9, 2023
@iritkatriel iritkatriel added the stdlib Python modules in the Lib dir label Nov 24, 2023
@barneygale
Copy link
Contributor

I think this is a duplicate of #100609, so I'll close this issue. Thanks for reporting all the same!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
Status: Done
Development

No branches or pull requests

3 participants