GH-114610: Fix pathlib._abc.PurePathBase.with_suffix('.ext') handling of stems (#114613)

Raise `ValueError` if `with_suffix('.ext')` is called on a path without a
stem. Paths may only have a non-empty suffix if they also have a non-empty
stem.

ABC-only bugfix; no effect on public classes.
This commit is contained in:
Barney Gale 2024-01-30 14:25:16 +00:00 committed by GitHub
parent e21754d7f8
commit 809eed4805
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 7 additions and 12 deletions

View file

@ -299,10 +299,13 @@ class PurePathBase:
has no suffix, add given suffix. If the given suffix is an empty has no suffix, add given suffix. If the given suffix is an empty
string, remove the suffix from the path. string, remove the suffix from the path.
""" """
stem = self.stem
if not suffix: if not suffix:
return self.with_name(self.stem) return self.with_name(stem)
elif not stem:
raise ValueError(f"{self!r} has an empty name")
elif suffix.startswith('.') and len(suffix) > 1: elif suffix.startswith('.') and len(suffix) > 1:
return self.with_name(self.stem + suffix) return self.with_name(stem + suffix)
else: else:
raise ValueError(f"Invalid suffix {suffix!r}") raise ValueError(f"Invalid suffix {suffix!r}")

View file

@ -327,13 +327,6 @@ class PurePathTest(test_pathlib_abc.DummyPurePathTest):
self.assertRaises(ValueError, P('a/b').with_stem, '') self.assertRaises(ValueError, P('a/b').with_stem, '')
self.assertRaises(ValueError, P('a/b').with_stem, '.') self.assertRaises(ValueError, P('a/b').with_stem, '.')
def test_with_suffix_empty(self):
# Path doesn't have a "filename" component.
P = self.cls
self.assertRaises(ValueError, P('').with_suffix, '.gz')
self.assertRaises(ValueError, P('.').with_suffix, '.gz')
self.assertRaises(ValueError, P('/').with_suffix, '.gz')
def test_relative_to_several_args(self): def test_relative_to_several_args(self):
P = self.cls P = self.cls
p = P('a/b') p = P('a/b')

View file

@ -977,9 +977,8 @@ class DummyPurePathTest(unittest.TestCase):
def test_with_suffix_empty(self): def test_with_suffix_empty(self):
P = self.cls P = self.cls
# Path doesn't have a "filename" component. # Path doesn't have a "filename" component.
self.assertEqual(P('').with_suffix('.gz'), P('.gz')) self.assertRaises(ValueError, P('').with_suffix, '.gz')
self.assertEqual(P('.').with_suffix('.gz'), P('..gz')) self.assertRaises(ValueError, P('/').with_suffix, '.gz')
self.assertEqual(P('/').with_suffix('.gz'), P('/.gz'))
def test_with_suffix_seps(self): def test_with_suffix_seps(self):
P = self.cls P = self.cls