summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBarney Gale <barney.gale@gmail.com>2023-11-25 17:19:38 (GMT)
committerGitHub <noreply@github.com>2023-11-25 17:19:38 (GMT)
commit19a1fc1b3df30f64450d157dc3a5d40c992e347f (patch)
tree347f7abd5eb38070f713b2d5f32e1e2a792590d5 /Lib
parent6b961b8ceaba372b78d03feaceb4837bf7236694 (diff)
downloadcpython-19a1fc1b3df30f64450d157dc3a5d40c992e347f.zip
cpython-19a1fc1b3df30f64450d157dc3a5d40c992e347f.tar.gz
cpython-19a1fc1b3df30f64450d157dc3a5d40c992e347f.tar.bz2
GH-112361: Speed up pathlib by removing some temporary objects. (#112362)
Construct only one new list object (using `list.copy()`) when creating a new path object with a modified tail. This slightly speeds up `with_name()` and `with_suffix()`
Diffstat (limited to 'Lib')
-rw-r--r--Lib/pathlib.py32
-rw-r--r--Lib/test/test_pathlib.py2
2 files changed, 12 insertions, 22 deletions
diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index 9bce532..32ccf81 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -400,13 +400,14 @@ class PurePath:
def with_name(self, name):
"""Return a new path with the file name changed."""
- if not self.name:
- raise ValueError("%r has an empty name" % (self,))
m = self.pathmod
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])
+ raise ValueError(f"Invalid name {name!r}")
+ tail = self._tail.copy()
+ if not tail:
+ raise ValueError(f"{self!r} has an empty name")
+ tail[-1] = name
+ return self._from_parsed_parts(self.drive, self.root, tail)
def with_stem(self, stem):
"""Return a new path with the stem changed."""
@@ -417,21 +418,12 @@ class PurePath:
has no suffix, add given suffix. If the given suffix is an empty
string, remove the suffix from the path.
"""
- m = self.pathmod
- if m.sep in suffix or m.altsep and m.altsep in suffix:
- raise ValueError("Invalid suffix %r" % (suffix,))
- if suffix and not suffix.startswith('.') or suffix == '.':
- raise ValueError("Invalid suffix %r" % (suffix))
- name = self.name
- if not name:
- raise ValueError("%r has an empty name" % (self,))
- old_suffix = self.suffix
- if not old_suffix:
- name = name + suffix
+ if not suffix:
+ return self.with_name(self.stem)
+ elif suffix.startswith('.') and len(suffix) > 1:
+ return self.with_name(self.stem + suffix)
else:
- name = name[:-len(old_suffix)] + suffix
- return self._from_parsed_parts(self.drive, self.root,
- self._tail[:-1] + [name])
+ raise ValueError(f"Invalid suffix {suffix!r}")
def relative_to(self, other, /, *_deprecated, walk_up=False):
"""Return the relative path to another path identified by the passed
@@ -1029,7 +1021,7 @@ class _PathBase(PurePath):
elif not path_pattern._tail:
raise ValueError("Unacceptable pattern: {!r}".format(pattern))
- pattern_parts = list(path_pattern._tail)
+ pattern_parts = path_pattern._tail.copy()
if pattern[-1] in (self.pathmod.sep, self.pathmod.altsep):
# GH-65238: pathlib doesn't preserve trailing slash. Add it back.
pattern_parts.append('')
diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index e1121a9..427e082 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -575,8 +575,6 @@ class PurePathTest(unittest.TestCase):
self.assertRaises(ValueError, P('a/b').with_suffix, '.c/.d')
self.assertRaises(ValueError, P('a/b').with_suffix, './.d')
self.assertRaises(ValueError, P('a/b').with_suffix, '.d/.')
- self.assertRaises(ValueError, P('a/b').with_suffix,
- (self.pathmod.sep, 'd'))
def test_relative_to_common(self):
P = self.cls