https://github.com/python/cpython/commit/d372472896ca9d5666b40072a9ed7040300e11a0
commit: d372472896ca9d5666b40072a9ed7040300e11a0
branch: main
author: Barney Gale <barney.g...@gmail.com>
committer: barneygale <barney.g...@gmail.com>
date: 2025-03-24T15:39:08Z
summary:

GH-128520: pathlib ABCs: tighten up argument types (#131621)

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`.

files:
M Lib/pathlib/__init__.py
M Lib/pathlib/types.py

diff --git a/Lib/pathlib/__init__.py b/Lib/pathlib/__init__.py
index a8111cc4f305fa..cd28f62ce3baf5 100644
--- a/Lib/pathlib/__init__.py
+++ b/Lib/pathlib/__init__.py
@@ -1105,11 +1105,7 @@ def copy(self, target, **kwargs):
         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):
diff --git a/Lib/pathlib/types.py b/Lib/pathlib/types.py
index cd8b2a983379d0..d1bb8701b887c8 100644
--- a/Lib/pathlib/types.py
+++ b/Lib/pathlib/types.py
@@ -17,14 +17,12 @@
 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 @@ def __str__(self):
     @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 @@ def with_suffix(self, suffix):
     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 @@ def full_match(self, pattern):
         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 @@ def glob(self, pattern, *, recurse_symlinks=True):
         """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 @@ def copy(self, target, **kwargs):
         """
         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 @@ def copy_into(self, target_dir, **kwargs):
         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):

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to