Expose file size, mode, etc from `pathlib.Path.info`

Just for clarity, I suggest a couple dataclasses for the mode with some useful factories for the most common cases (saves users from having to look things up):

@dataclass
class BasicPermission:
    read: bool
    write: bool
    execute: bool


@dataclass
class FilePermissions:
    owner: BasicPermission
    group: BasicPermission
    others: BasicPermission

    def as_int(self) -> int:
        return ...

    @classmethod
    def from_int(cls, mode: int, /) -> FilePermissions:
        return FilePermissions(...)

    @classmethod
    def public_file(cls) -> FilePermissions:
        """
        644 → rw-r--r--
        Owner can read/write, group and others can read. Common for text 
        files, configs, documents.
        """
        return FilePermissions.from_int(0o644)

    @classmethod
    def private_file(cls) -> FilePermissions:
        """
        600 → rw-------
        Only owner can read/write. Used for private files (SSH keys,
        credentials).
        """
        return FilePermissions.from_int(0o600)

    @classmethod
    def shared_file(cls) -> FilePermissions:
        """
        664 → rw-rw-r--
        Owner and group can read/write, others can only read. Used in
        collaborative environments.
        """
        return FilePermissions.from_int(0o664)

    @classmethod
    def executable_script(cls) -> FilePermissions:
        """
        755 → rwxr-xr-x
        Owner can read/write/execute, others can read/execute. For executable
        scripts.
        """
        return FilePermissions.from_int(0o755)

    @classmethod
    def system_directory(cls) -> FilePermissions:
        """
        755 → rwxr-xr-x
        Owner can read/write/enter, others can read/enter but not write. Very
        common for system dirs like /usr, /bin.
        """
        return FilePermissions.from_int(0o755)

    @classmethod
    def private_directory(cls) -> FilePermissions:
        """
        700 → rwx------
        Only owner can access. Used for private directories like ~/.ssh.
        """
        return FilePermissions.from_int(0o700)

    @classmethod
    def shared_directory(cls) -> FilePermissions:
        """
        775 → rwxrwxr-x
        Owner and group have full access, others can read/enter. Used in
        shared group dirs.
        """
        return FilePermissions.from_int(0o775)

    @classmethod
    def temporary_directory(cls) -> FilePermissions:
        """
        777 → rwxrwxrwx
        Everyone has full access. Rare and generally unsafe, but sometimes
        used for temporary dirs like /tmp.
        """
        return FilePermissions.from_int(0o777)

Then, we could allow users to use the FilePermissions in place of integers:

Path.chmod(self, mode: int | FilePermissions, ...) -> None: ...
Path.mkdir(self, mode: int | FilePermissions, ...) -> None: ...

This allows users to sidestep the (what I feel are) anachronistic octal values and code in an arguably more Pythonic, straightforward interface. E.g.,

if path.info.permissions().user.executable: ...
path.chmod(FilePermissions.executable_script())
path.mkdir(FilePermissions.private_directory())
2 Likes