Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User subclasses of pathlib.PurePath are os.PathLike #106037

Closed
barneygale opened this issue Jun 23, 2023 · 3 comments
Closed

User subclasses of pathlib.PurePath are os.PathLike #106037

barneygale opened this issue Jun 23, 2023 · 3 comments
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes topic-pathlib type-bug An unexpected behavior, bug, or error

Comments

@barneygale
Copy link
Contributor

barneygale commented Jun 23, 2023

In Python 3.12 we've made pathlib.PurePath subclassable - see #31691.

A significant wrinkle is that subclasses inherit an __fspath__() method, which can lead to unexpected behaviour when these "pure" paths are passed to filesystem APIs:

import pathlib

class TarPath(pathlib.PurePath):
    ...

readme = TarPath('README.md', tarfile=...)
with open(readme) as f:
   ...

The with open(readme) as f: line should throw a TypeError, but instead it attempts to open a file called README.md in the current working directory (!). This sort of thing makes subclasses that implement purely virtual filesystems difficult to use safely.

Linked PRs

@barneygale barneygale added type-bug An unexpected behavior, bug, or error 3.12 bugs and security fixes topic-pathlib 3.13 bugs and security fixes labels Jun 23, 2023
barneygale added a commit to barneygale/cpython that referenced this issue Jun 23, 2023
…os.PathLike`

We made it possible to subclass `pathlib.PurePath` in a68e585, which landed
in 3.12. However, user subclasses automatically inherit an `__fspath__()`
method, which may not be appropriate. For example, a user subclass may
implement a "virtual" filesystem to provide access to a `.zip` file or FTP
server. But it would be highly surprising if `open(FTPPath(...))` attempted
to open a *local* file.

This patch makes the `os.PathLike` interface opt-in. In pathlib itself, we
opt into the `os.PathLike` interface for `PurePosixPath`, `PureWindowsPath`
and `Path`. As `PurePath` is not instantiable (you always get a
`PurePosixPath` or `PureWindowsPath` object back), this is backwards
compatible with 3.11, but not with earlier 3.12 betas.
@barneygale
Copy link
Contributor Author

barneygale commented Jun 23, 2023

@brettcannon as co-author of PEP 519, your input here would be greatly appreciated!

Though it's not specified as such, I argue that os.PathLike has grown to mean "like a local filesystem path". Functions that accept os.PathLike objects almost always call operating system APIs on their paths. There are notable exceptions (like os.path.join()) that perform only lexical work, but they're in a pretty small minority. The result is that open() etc "work", even on path objects that represent non-local paths such as S3 keys.

PurePosixPath and PureWindowsPath instances and subclasses have always been path-like, so we can't change those. PurePath instances are impossible to create. PurePath subclasses have just become possible in 3.12, which is where I propose making this change. What do you think?

@brettcannon
Copy link
Member

If the question is, "can I leave __fspath__ off of AbstractPath", then I can see that making sense since it is meant for file systems which is not automatic for something which wants to implement pathlib's API.

@barneygale
Copy link
Contributor Author

Closing this issue - PurePath is already path-like and trying to do funky things in subclasses is probably more surprising than PurePath having __fspath__(). The latter may not be surprising at all depending on how you view PurePath! Alex has pointed me towards a good solution for pathlib.AbstractPath.

@barneygale barneygale closed this as not planned Won't fix, can't repro, duplicate, stale Jun 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes topic-pathlib type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants