Skip to content

Commit 8aea4b3

Browse files
authored
bpo-40148: Add PurePath.with_stem() (GH-19295)
Add PurePath.with_stem()
1 parent c8f1715 commit 8aea4b3

File tree

4 files changed

+60
-0
lines changed

4 files changed

+60
-0
lines changed

Doc/library/pathlib.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,30 @@ Pure paths provide the following methods and properties:
571571
ValueError: PureWindowsPath('c:/') has an empty name
572572

573573

574+
.. method:: PurePath.with_stem(stem)
575+
576+
Return a new path with the :attr:`stem` changed. If the original path
577+
doesn't have a name, ValueError is raised::
578+
579+
>>> p = PureWindowsPath('c:/Downloads/draft.txt')
580+
>>> p.with_stem('final')
581+
PureWindowsPath('c:/Downloads/final.txt')
582+
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
583+
>>> p.with_stem('lib')
584+
PureWindowsPath('c:/Downloads/lib.gz')
585+
>>> p = PureWindowsPath('c:/')
586+
>>> p.with_stem('')
587+
Traceback (most recent call last):
588+
File "<stdin>", line 1, in <module>
589+
File "/home/antoine/cpython/default/Lib/pathlib.py", line 861, in with_stem
590+
return self.with_name(stem + self.suffix)
591+
File "/home/antoine/cpython/default/Lib/pathlib.py", line 851, in with_name
592+
raise ValueError("%r has an empty name" % (self,))
593+
ValueError: PureWindowsPath('c:/') has an empty name
594+
595+
.. versionadded:: 3.9
596+
597+
574598
.. method:: PurePath.with_suffix(suffix)
575599

576600
Return a new path with the :attr:`suffix` changed. If the original path

Lib/pathlib.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,10 @@ def with_name(self, name):
870870
return self._from_parsed_parts(self._drv, self._root,
871871
self._parts[:-1] + [name])
872872

873+
def with_stem(self, stem):
874+
"""Return a new path with the stem changed."""
875+
return self.with_name(stem + self.suffix)
876+
873877
def with_suffix(self, suffix):
874878
"""Return a new path with the file suffix changed. If the path
875879
has no suffix, add given suffix. If the given suffix is an empty

Lib/test/test_pathlib.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,23 @@ def test_with_name_common(self):
559559
self.assertRaises(ValueError, P('a/b').with_name, 'c/')
560560
self.assertRaises(ValueError, P('a/b').with_name, 'c/d')
561561

562+
def test_with_stem_common(self):
563+
P = self.cls
564+
self.assertEqual(P('a/b').with_stem('d'), P('a/d'))
565+
self.assertEqual(P('/a/b').with_stem('d'), P('/a/d'))
566+
self.assertEqual(P('a/b.py').with_stem('d'), P('a/d.py'))
567+
self.assertEqual(P('/a/b.py').with_stem('d'), P('/a/d.py'))
568+
self.assertEqual(P('/a/b.tar.gz').with_stem('d'), P('/a/d.gz'))
569+
self.assertEqual(P('a/Dot ending.').with_stem('d'), P('a/d'))
570+
self.assertEqual(P('/a/Dot ending.').with_stem('d'), P('/a/d'))
571+
self.assertRaises(ValueError, P('').with_stem, 'd')
572+
self.assertRaises(ValueError, P('.').with_stem, 'd')
573+
self.assertRaises(ValueError, P('/').with_stem, 'd')
574+
self.assertRaises(ValueError, P('a/b').with_stem, '')
575+
self.assertRaises(ValueError, P('a/b').with_stem, '/c')
576+
self.assertRaises(ValueError, P('a/b').with_stem, 'c/')
577+
self.assertRaises(ValueError, P('a/b').with_stem, 'c/d')
578+
562579
def test_with_suffix_common(self):
563580
P = self.cls
564581
self.assertEqual(P('a/b').with_suffix('.gz'), P('a/b.gz'))
@@ -1014,6 +1031,20 @@ def test_with_name(self):
10141031
self.assertRaises(ValueError, P('c:a/b').with_name, 'd:/e')
10151032
self.assertRaises(ValueError, P('c:a/b').with_name, '//My/Share')
10161033

1034+
def test_with_stem(self):
1035+
P = self.cls
1036+
self.assertEqual(P('c:a/b').with_stem('d'), P('c:a/d'))
1037+
self.assertEqual(P('c:/a/b').with_stem('d'), P('c:/a/d'))
1038+
self.assertEqual(P('c:a/Dot ending.').with_stem('d'), P('c:a/d'))
1039+
self.assertEqual(P('c:/a/Dot ending.').with_stem('d'), P('c:/a/d'))
1040+
self.assertRaises(ValueError, P('c:').with_stem, 'd')
1041+
self.assertRaises(ValueError, P('c:/').with_stem, 'd')
1042+
self.assertRaises(ValueError, P('//My/Share').with_stem, 'd')
1043+
self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:')
1044+
self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:e')
1045+
self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:/e')
1046+
self.assertRaises(ValueError, P('c:a/b').with_stem, '//My/Share')
1047+
10171048
def test_with_suffix(self):
10181049
P = self.cls
10191050
self.assertEqual(P('c:a/b').with_suffix('.gz'), P('c:a/b.gz'))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added :meth:`pathlib.Path.with_stem()` to create a new Path with the stem replaced.

0 commit comments

Comments
 (0)