]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-128520: pathlib ABCs: tighten up argument types (#131621)
authorBarney Gale <barney.gale@gmail.com>
Mon, 24 Mar 2025 15:39:08 +0000 (15:39 +0000)
committerGitHub <noreply@github.com>
Mon, 24 Mar 2025 15:39:08 +0000 (15:39 +0000)
In `JoinablePath.full_match()` and `ReadablePath.glob()`, accept a `str`
pattern argument rather than `JoinablePath | str`.

In `ReadablePath.copy()` and `copy_into()`, accept a `WritablePath` target
argument rather than `WritablePath | str`.

Lib/pathlib/__init__.py
Lib/pathlib/types.py

index a8111cc4f305faa9e528bfa13ac5a7707bdb4bfd..cd28f62ce3baf53a28171727184f657af8b92a4c 100644 (file)
@@ -1105,11 +1105,7 @@ class Path(PurePath):
         if not hasattr(target, 'with_segments'):
             target = self.with_segments(target)
         ensure_distinct_paths(self, target)
-        try:
-            copy_to_target = target._copy_from
-        except AttributeError:
-            raise TypeError(f"Target path is not writable: {target!r}") from None
-        copy_to_target(self, **kwargs)
+        target._copy_from(self, **kwargs)
         return target.joinpath()  # Empty join to ensure fresh metadata.
 
     def copy_into(self, target_dir, **kwargs):
index cd8b2a983379d004be073240219a30cf92351ae7..d1bb8701b887c8521db1548552b65a0d2194dff7 100644 (file)
@@ -17,14 +17,12 @@ from pathlib import PurePath, Path
 from typing import Optional, Protocol, runtime_checkable
 
 
-def _explode_path(path):
+def _explode_path(path, split):
     """
     Split the path into a 2-tuple (anchor, parts), where *anchor* is the
     uppermost parent of the path (equivalent to path.parents[-1]), and
     *parts* is a reversed list of parts following the anchor.
     """
-    split = path.parser.split
-    path = str(path)
     parent, name = split(path)
     names = []
     while path != parent:
@@ -95,7 +93,7 @@ class _JoinablePath(ABC):
     @property
     def anchor(self):
         """The concatenation of the drive and root, or ''."""
-        return _explode_path(self)[0]
+        return _explode_path(str(self), self.parser.split)[0]
 
     @property
     def name(self):
@@ -169,7 +167,7 @@ class _JoinablePath(ABC):
     def parts(self):
         """An object providing sequence-like access to the
         components in the filesystem path."""
-        anchor, parts = _explode_path(self)
+        anchor, parts = _explode_path(str(self), self.parser.split)
         if anchor:
             parts.append(anchor)
         return tuple(reversed(parts))
@@ -221,11 +219,9 @@ class _JoinablePath(ABC):
         Return True if this path matches the given glob-style pattern. The
         pattern is matched against the entire path.
         """
-        if not hasattr(pattern, 'with_segments'):
-            pattern = self.with_segments(pattern)
         case_sensitive = self.parser.normcase('Aa') == 'Aa'
-        globber = _PathGlobber(pattern.parser.sep, case_sensitive, recursive=True)
-        match = globber.compile(str(pattern), altsep=pattern.parser.altsep)
+        globber = _PathGlobber(self.parser.sep, case_sensitive, recursive=True)
+        match = globber.compile(pattern, altsep=self.parser.altsep)
         return match(str(self)) is not None
 
 
@@ -282,9 +278,7 @@ class _ReadablePath(_JoinablePath):
         """Iterate over this subtree and yield all existing files (of any
         kind, including directories) matching the given relative pattern.
         """
-        if not hasattr(pattern, 'with_segments'):
-            pattern = self.with_segments(pattern)
-        anchor, parts = _explode_path(pattern)
+        anchor, parts = _explode_path(pattern, self.parser.split)
         if anchor:
             raise NotImplementedError("Non-relative patterns are unsupported")
         elif not parts:
@@ -338,14 +332,8 @@ class _ReadablePath(_JoinablePath):
         """
         Recursively copy this file or directory tree to the given destination.
         """
-        if not hasattr(target, 'with_segments'):
-            target = self.with_segments(target)
         ensure_distinct_paths(self, target)
-        try:
-            copy_to_target = target._copy_from
-        except AttributeError:
-            raise TypeError(f"Target path is not writable: {target!r}") from None
-        copy_to_target(self, **kwargs)
+        target._copy_from(self, **kwargs)
         return target.joinpath()  # Empty join to ensure fresh metadata.
 
     def copy_into(self, target_dir, **kwargs):
@@ -355,11 +343,7 @@ class _ReadablePath(_JoinablePath):
         name = self.name
         if not name:
             raise ValueError(f"{self!r} has an empty name")
-        elif hasattr(target_dir, 'with_segments'):
-            target = target_dir / name
-        else:
-            target = self.with_segments(target_dir, name)
-        return self.copy(target, **kwargs)
+        return self.copy(target_dir / name, **kwargs)
 
 
 class _WritablePath(_JoinablePath):