From b5f7777cb3ecae02d49e0b348968c1ff1ffe21f4 Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Wed, 11 Oct 2023 04:45:11 +0100 Subject: [PATCH] GH-110488: Fix two small issues in `pathlib.PurePath.with_name()` (#110651) Ensure that `PurePath('foo/a').with_name('.')` raises `ValueError` Ensure that `PureWindowsPath('foo/a').with_name('a:b')` does not raise `ValueError`. --- Lib/pathlib.py | 3 +-- Lib/test/test_pathlib.py | 14 ++++++++++---- .../2023-10-10-22-54-56.gh-issue-110488.2I7OiZ.rst | 4 ++++ 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-10-10-22-54-56.gh-issue-110488.2I7OiZ.rst diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 9e6d0754eccf3e..5c1c71ecec2805 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -603,8 +603,7 @@ def with_name(self, name): if not self.name: raise ValueError("%r has an empty name" % (self,)) m = self.pathmod - drv, root, tail = m.splitroot(name) - if drv or root or not tail or m.sep in tail or (m.altsep and m.altsep in tail): + if not name or m.sep in name or (m.altsep and m.altsep in name) or name == '.': raise ValueError("Invalid name %r" % (name)) return self._from_parsed_parts(self.drive, self.root, self._tail[:-1] + [name]) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index f077825fc7c09a..2781e019220353 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -614,6 +614,7 @@ def test_with_name_common(self): self.assertRaises(ValueError, P('.').with_name, 'd.xml') self.assertRaises(ValueError, P('/').with_name, 'd.xml') self.assertRaises(ValueError, P('a/b').with_name, '') + self.assertRaises(ValueError, P('a/b').with_name, '.') self.assertRaises(ValueError, P('a/b').with_name, '/c') self.assertRaises(ValueError, P('a/b').with_name, 'c/') self.assertRaises(ValueError, P('a/b').with_name, 'c/d') @@ -631,6 +632,7 @@ def test_with_stem_common(self): self.assertRaises(ValueError, P('.').with_stem, 'd') self.assertRaises(ValueError, P('/').with_stem, 'd') self.assertRaises(ValueError, P('a/b').with_stem, '') + self.assertRaises(ValueError, P('a/b').with_stem, '.') self.assertRaises(ValueError, P('a/b').with_stem, '/c') self.assertRaises(ValueError, P('a/b').with_stem, 'c/') self.assertRaises(ValueError, P('a/b').with_stem, 'c/d') @@ -1235,8 +1237,10 @@ def test_with_name(self): self.assertRaises(ValueError, P('c:').with_name, 'd.xml') self.assertRaises(ValueError, P('c:/').with_name, 'd.xml') self.assertRaises(ValueError, P('//My/Share').with_name, 'd.xml') - self.assertRaises(ValueError, P('c:a/b').with_name, 'd:') - self.assertRaises(ValueError, P('c:a/b').with_name, 'd:e') + self.assertEqual(str(P('a').with_name('d:')), '.\\d:') + self.assertEqual(str(P('a').with_name('d:e')), '.\\d:e') + self.assertEqual(P('c:a/b').with_name('d:'), P('c:a/d:')) + self.assertEqual(P('c:a/b').with_name('d:e'), P('c:a/d:e')) self.assertRaises(ValueError, P('c:a/b').with_name, 'd:/e') self.assertRaises(ValueError, P('c:a/b').with_name, '//My/Share') @@ -1249,8 +1253,10 @@ def test_with_stem(self): self.assertRaises(ValueError, P('c:').with_stem, 'd') self.assertRaises(ValueError, P('c:/').with_stem, 'd') self.assertRaises(ValueError, P('//My/Share').with_stem, 'd') - self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:') - self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:e') + self.assertEqual(str(P('a').with_stem('d:')), '.\\d:') + self.assertEqual(str(P('a').with_stem('d:e')), '.\\d:e') + self.assertEqual(P('c:a/b').with_stem('d:'), P('c:a/d:')) + self.assertEqual(P('c:a/b').with_stem('d:e'), P('c:a/d:e')) self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:/e') self.assertRaises(ValueError, P('c:a/b').with_stem, '//My/Share') diff --git a/Misc/NEWS.d/next/Library/2023-10-10-22-54-56.gh-issue-110488.2I7OiZ.rst b/Misc/NEWS.d/next/Library/2023-10-10-22-54-56.gh-issue-110488.2I7OiZ.rst new file mode 100644 index 00000000000000..aec9120d72e358 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-10-22-54-56.gh-issue-110488.2I7OiZ.rst @@ -0,0 +1,4 @@ +Fix a couple of issues in :meth:`pathlib.PurePath.with_name`: a single dot +was incorrectly considered a valid name, and in :class:`PureWindowsPath`, a +name with an NTFS alternate data stream, like ``a:b``, was incorrectly +considered invalid.