Skip to content

GH-125413: Add private metadata methods to pathlib.Path.info #129897

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

Merged
merged 16 commits into from
Feb 17, 2025

Conversation

barneygale
Copy link
Contributor

@barneygale barneygale commented Feb 9, 2025

Add the following private methods to pathlib.Path.info:

  • _posix_permissions(): the POSIX file permissions (S_IMODE(st_mode))
  • _file_id(): the file ID ((st_dev, st_ino))
  • _access_time_ns(): the access time in nanoseconds (st_atime_ns)
  • _mod_time_ns(): the modify time in nanoseconds (st_mtime_ns)
  • _bsd_flags(): the BSD file flags (st_flags)
  • _xattrs(): the file extended attributes as a list of key, value pairs, or an empty list if listxattr() or getxattr() fail in an ignorable way.

These methods replace LocalCopyReader.read_metadata(), and so we can delete the CopyReader and LocalCopyReader classes. Rather than reading metadata via source._copy_reader.read_metadata(), we instead call source.info._posix_permissions(), _access_time_ns(), etc.

Preserving metadata is only supported for local-to-local copies at the moment. To support copying metadata between arbitrary ReadablePath and WritablePath objects, we'd need to make the new methods public and documented.

Add the following private methods to `pathlib.Path.info`:

- `_get_mode()`: returns the POSIX file mode (`st_mode`), or zero if
  `os.stat()` fails.
- `_get_times_ns()`: returns the access and modify times in nanoseconds
  (`st_atime_ns` and `st_mtime_ns`), or zeroes if `os.stat()` fails.
- `_get_flags()`: returns the BSD file flags (`st_flags`), or zero if
  `os.stat()` fails.
- `_get_xattrs()`: returns the file extended attributes as a list of
  key, value pairs, or an empty list if `listxattr()` or `getattr()` fail.

These methods replace `LocalCopyReader.read_metadata()`, and so we can
delete the `CopyReader` and `LocalCopyReader` classes. Rather than reading
metadata via `source._copy_reader.read_metadata()`, we instead call
`source.info._get_mode()`, `_get_times_ns()`, etc.

Copying metadata is only supported for local-to-local copies at the moment.
To support copying between arbitrary `ReadablePath` and `WritablePath`
objects, we'd need to make the new methods public and documented.
@encukou
Copy link
Member

encukou commented Feb 12, 2025

Should _file_id return a (st_dev, st_ino) tuple? AFAIK, separating them is only due to a low-level detail (you don't need to store st_dev on the disk).


To support copying metadata between arbitrary ReadablePath and WritablePath objects, we'd need to make the new methods public and documented.

Is that the plan?

It seems to me that people will want their subclasses to support such copying, and are might resort to underscored functions to get it.

@barneygale
Copy link
Contributor Author

barneygale commented Feb 12, 2025

Should _file_id return a (st_dev, st_ino) tuple? AFAIK, separating them is only due to a low-level detail (you don't need to store st_dev on the disk).

Sounds good to me. Would we (eventually) document it as returning (st_dev, st_ino), or should we just say "some comparable/hashable object"?

Is that the plan?

It seems to me that people will want their subclasses to support such copying, and are might resort to underscored functions to get it.

Yes, I think it will be part of the PEP for making Joinable/Readable/WritablePath public.

@encukou
Copy link
Member

encukou commented Feb 13, 2025

Sounds good to me. Would we (eventually) document it as returning (st_dev, st_ino), or should we just say "some comparable/hashable object"?

The tuple for the local FS†, a comparable/hashable object in general?
† (Not sure if there's something better for Windows?)

I can imagine a path class that would add extra functionality to Path (or limit the functionality), but expose local files.

@barneygale
Copy link
Contributor Author

Thanks :) I've deleted _device_id(), and made _file_id() return (st_dev, st_ino)

@barneygale barneygale enabled auto-merge (squash) February 17, 2025 18:54
@barneygale
Copy link
Contributor Author

Thanks for the review!

@barneygale barneygale merged commit 7fcace9 into python:main Feb 17, 2025
38 checks passed
barneygale added a commit to barneygale/cpython that referenced this pull request Feb 17, 2025
Replace `WritablePath._copy_writer` with a new `_write_info()` method. This
method allows the target of a `copy()` to preserve metadata.

Replace `pathlib._os.CopyWriter` and `LocalCopyWriter` classes with new
`copy_file()` and `copy_info()` functions. The `copy_file()` function uses
`source_path.info` wherever possible to save on `stat()`s.
barneygale added a commit to barneygale/cpython that referenced this pull request Feb 21, 2025
barneygale added a commit to barneygale/cpython that referenced this pull request Feb 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants