Skip to content

Commit 0c7638a

Browse files
authored
Merge pull request #135 from barneygale/fix-134
Fix `TypeError` from `str(Path(...))`
2 parents e7956b7 + 6d1e280 commit 0c7638a

4 files changed

Lines changed: 29 additions & 3 deletions

File tree

newsfragments/134.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``str(Path(...))`` now renders ":zipfile" for the filename when a zipfile has no filename instead of failing with a TypeError.

tests/test_path.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,19 @@ class Subclass(zipfile.Path):
346346
root = Subclass(alpharep)
347347
assert isinstance(root / 'b', Subclass)
348348

349+
def test_at(self):
350+
root = zipfile.Path(zipfile.ZipFile(io.BytesIO(), 'w'))
351+
assert root.at == ''
352+
assert (root / 'foo' / 'bar').at == 'foo/bar'
353+
354+
def test_str(self):
355+
"""
356+
An unnamed zip file is indicated by ":zipfile:"
357+
"""
358+
root = zipfile.Path(zipfile.ZipFile(io.BytesIO(), 'w'))
359+
assert str(root) == ':zipfile:'
360+
assert str(root / 'foo' / 'bar') == ':zipfile:/foo/bar'
361+
349362
@pass_alpharep
350363
def test_filename(self, alpharep):
351364
root = zipfile.Path(alpharep)

zipp/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import sys
1818
import zipfile
1919

20-
from ._functools import save_method_args
20+
from ._functools import none_as, save_method_args
2121
from .compat.py310 import text_encoding
2222
from .glob import Translator
2323

@@ -277,7 +277,7 @@ class Path:
277277
resolve to the zipfile.
278278
279279
>>> str(path)
280-
'mem/abcde.zip/'
280+
'mem/abcde.zip'
281281
>>> path.name
282282
'abcde.zip'
283283
>>> path.filename == pathlib.Path('mem/abcde.zip')
@@ -435,7 +435,8 @@ def relative_to(self, other, *extra):
435435
return posixpath.relpath(str(self), str(other.joinpath(*extra)))
436436

437437
def __str__(self):
438-
return posixpath.join(self.root.filename, self.at)
438+
root = none_as(self.root.filename, ':zipfile:')
439+
return posixpath.join(root, self.at) if self.at else root
439440

440441
def __repr__(self):
441442
return self.__repr.format(self=self)

zipp/_functools.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,14 @@ def wrapper(self, /, *args, **kwargs):
1818
return method(self, *args, **kwargs)
1919

2020
return wrapper
21+
22+
23+
# from jaraco.functools 4.3
24+
def none_as(value, replacement=None):
25+
"""
26+
>>> none_as(None, 'foo')
27+
'foo'
28+
>>> none_as('bar', 'foo')
29+
'bar'
30+
"""
31+
return replacement if value is None else value

0 commit comments

Comments
 (0)