GH-128520: pathlib ABCs: add JoinablePath.__vfspath__() (#133437)

In the abstract interface of `JoinablePath`, replace `__str__()` with
`__vfspath__()`. This frees user implementations of `JoinablePath` to
implement `__str__()` however they like (or not at all.)

Also add `pathlib._os.vfspath()`, which calls `__fspath__()` or
`__vfspath__()`.
This commit is contained in:
Barney Gale 2025-05-12 19:00:36 +01:00 committed by GitHub
parent 9f69a58623
commit 5dbd27db7d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 118 additions and 81 deletions

View file

@ -210,6 +210,26 @@ def magic_open(path, mode='r', buffering=-1, encoding=None, errors=None,
raise TypeError(f"{cls.__name__} can't be opened with mode {mode!r}")
def vfspath(path):
"""
Return the string representation of a virtual path object.
"""
try:
return os.fsdecode(path)
except TypeError:
pass
path_type = type(path)
try:
return path_type.__vfspath__(path)
except AttributeError:
if hasattr(path_type, '__vfspath__'):
raise
raise TypeError("expected str, bytes, os.PathLike or JoinablePath "
"object, not " + path_type.__name__)
def ensure_distinct_paths(source, target):
"""
Raise OSError(EINVAL) if the other path is within this path.
@ -225,8 +245,8 @@ def ensure_distinct_paths(source, target):
err = OSError(EINVAL, "Source path is a parent of target path")
else:
return
err.filename = str(source)
err.filename2 = str(target)
err.filename = vfspath(source)
err.filename2 = vfspath(target)
raise err
@ -247,8 +267,8 @@ def ensure_different_files(source, target):
except (OSError, ValueError):
return
err = OSError(EINVAL, "Source and target are the same file")
err.filename = str(source)
err.filename2 = str(target)
err.filename = vfspath(source)
err.filename2 = vfspath(target)
raise err