Bug report
Bug description:
zipfile.Path.is_symlink() raises a KeyError when used on the archive root. The root is a valid Path object, and other predicate methods do not raise errors in this case.
Reproducer:
import io
import zipfile
data = io.BytesIO()
with zipfile.ZipFile(data, "w") as zf:
zf.writestr("a.txt", "hello")
data.seek(0)
with zipfile.ZipFile(data) as zf:
root = zipfile.Path(zf)
print(root.is_dir())
print(root.is_file())
print(root.is_symlink())
Output:
True
False
Traceback (most recent call last):
File "d:\Open Source\cpython\repro.py", line 16, in <module>
print(root.is_symlink())
~~~~~~~~~~~~~~~^^
File "C:\Users\vinee\AppData\Local\Programs\Python\Python315\Lib\zipfile\_path\__init__.py", line 417, in is_symlink
info = self.root.getinfo(self.at)
File "C:\Users\vinee\AppData\Local\Programs\Python\Python315\Lib\zipfile\_path\__init__.py", line 140, in getinfo
return super().getinfo(name)
~~~~~~~~~~~~~~~^^^^^^
File "C:\Users\vinee\AppData\Local\Programs\Python\Python315\Lib\zipfile\__init__.py", line 1646, in getinfo
raise KeyError(
'There is no item named %r in the archive' % name)
KeyError: "There is no item named '' in the archive"
Path.is_symlink() unconditionally calls self.root.getinfo(self.at). For the archive root, self.at == "", so ZipFile.getinfo("") raises KeyError. Unlike is_dir(), is_symlink() does not special-case the root.
Since the archive root is conceptually a directory rather than a symlink, I would expect:
root.is_symlink() == False
This change would make its behavior match the other predicate methods, like is_dir() and is_file(), which do not raise errors when called on the archive root.
A minimal fix appears to be:
def is_symlink(self):
if not self.at:
return False
info = self.root.getinfo(self.at)
mode = info.external_attr >> 16
return stat.S_ISLNK(mode)
I also noticed there is currently no regression test covering root.is_symlink().
CPython versions tested on:
3.15
Operating systems tested on:
Windows
Linked PRs
Bug report
Bug description:
zipfile.Path.is_symlink()raises aKeyErrorwhen used on the archive root. The root is a validPathobject, and other predicate methods do not raise errors in this case.Reproducer:
Output:
Path.is_symlink()unconditionally callsself.root.getinfo(self.at). For the archive root,self.at == "", soZipFile.getinfo("")raisesKeyError. Unlikeis_dir(),is_symlink()does not special-case the root.Since the archive root is conceptually a directory rather than a symlink, I would expect:
This change would make its behavior match the other predicate methods, like
is_dir()andis_file(), which do not raise errors when called on the archive root.A minimal fix appears to be:
I also noticed there is currently no regression test covering
root.is_symlink().CPython versions tested on:
3.15
Operating systems tested on:
Windows
Linked PRs