https://github.com/python/cpython/commit/d372472896ca9d5666b40072a9ed7040300e11a0
commit: d372472896ca9d5666b40072a9ed7040300e11a0
branch: main
author: Barney Gale <[email protected]>
committer: barneygale <[email protected]>
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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]