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())