]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-112361: Speed up pathlib by removing some temporary objects. (#112362)
authorBarney Gale <barney.gale@gmail.com>
Sat, 25 Nov 2023 17:19:38 +0000 (17:19 +0000)
committerGitHub <noreply@github.com>
Sat, 25 Nov 2023 17:19:38 +0000 (17:19 +0000)
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()`

Lib/pathlib.py
Lib/test/test_pathlib.py
Misc/NEWS.d/next/Library/2023-11-24-09-27-01.gh-issue-112361.kYtnHW.rst [new file with mode: 0644]

index 9bce5320ef68e9608a7cf5c37409bbf79bf19bec..32ccf818b157c559cd2ee02b9062edf4df3f974b 100644 (file)
@@ -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('')
index e1121a9d76c0405ed9a6137e6f396cc238e490be..427e082f3e16cb0c950baead8499963cbca135f4 100644 (file)
@@ -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
diff --git a/Misc/NEWS.d/next/Library/2023-11-24-09-27-01.gh-issue-112361.kYtnHW.rst b/Misc/NEWS.d/next/Library/2023-11-24-09-27-01.gh-issue-112361.kYtnHW.rst
new file mode 100644 (file)
index 0000000..5a83f93
--- /dev/null
@@ -0,0 +1,2 @@
+Speed up a small handful of :mod:`pathlib` methods by removing some
+temporary objects.