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