2026-04-16 11:23:05 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from enum import Enum, auto
|
|
|
|
|
from typing import NamedTuple, TypeAlias, TYPE_CHECKING
|
|
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
from typing import Type
|
|
|
|
|
|
|
|
|
|
class InputMode(Enum):
|
|
|
|
|
Interactive = auto()
|
|
|
|
|
NonInteractive = auto()
|
|
|
|
|
OptInteractive = auto()
|
|
|
|
|
Auto = auto()
|
|
|
|
|
|
|
|
|
|
Input: TypeAlias = InputMode | bytes | str
|
|
|
|
|
|
|
|
|
|
class Result(NamedTuple):
|
|
|
|
|
|
|
|
|
|
stdout: str|None
|
|
|
|
|
stderr: str|None
|
|
|
|
|
status: int|None
|
|
|
|
|
|
|
|
|
|
def decode(self, encoding='UTF-8', errors='replace') -> Result:
|
|
|
|
|
return Result(
|
|
|
|
|
self.stdout.decode(encoding, errors=errors) if self.stdout is not None else None,
|
|
|
|
|
self.stderr.decode(encoding, errors=errors) if self.stderr is not None else None,
|
|
|
|
|
self.status
|
|
|
|
|
)
|
2026-04-17 15:26:44 +02:00
|
|
|
|
|
|
|
|
class StatResult(NamedTuple):
|
|
|
|
|
|
|
|
|
|
mode: int
|
|
|
|
|
owner: str
|
|
|
|
|
group: str
|
|
|
|
|
size: int
|
|
|
|
|
atime: int
|
|
|
|
|
mtime: int
|
|
|
|
|
ctime: int
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def from_os(cls, rhs: os.stat_result) -> StatResult:
|
|
|
|
|
import pwd, grp
|
|
|
|
|
return StatResult(
|
|
|
|
|
rhs.st_mode,
|
lib.FileContext: Add file methods
Add the following methods, meant to do the obvious:
unlink(self, path: str) -> None
erase(self, path: str) -> None
rename(self, src: str, dst: str) -> None
mktemp(self, tmpl: str, directory: bool=False) -> None
chown(self, path: str, owner: str|None=None, group: str|None=None) -> None
chmod(self, path: str, mode: int) -> None
stat(self, path: str, follow_symlinks: bool=True) -> StatResult
file_exists(self, path: str) -> bool
is_dir(self, path: str) -> bool
All methods are async and call their protected counterpart, which is
designed to be overridden. If possible, default implementations do
something meaningful, if not, they just raise plain
NotImplementedError.
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-17 09:15:06 +02:00
|
|
|
pwd.getpwuid(rhs.st_uid).pw_name,
|
|
|
|
|
grp.getgrgid(rhs.st_gid).gr_name,
|
2026-04-17 15:26:44 +02:00
|
|
|
rhs.st_size,
|
lib.FileContext: Add file methods
Add the following methods, meant to do the obvious:
unlink(self, path: str) -> None
erase(self, path: str) -> None
rename(self, src: str, dst: str) -> None
mktemp(self, tmpl: str, directory: bool=False) -> None
chown(self, path: str, owner: str|None=None, group: str|None=None) -> None
chmod(self, path: str, mode: int) -> None
stat(self, path: str, follow_symlinks: bool=True) -> StatResult
file_exists(self, path: str) -> bool
is_dir(self, path: str) -> bool
All methods are async and call their protected counterpart, which is
designed to be overridden. If possible, default implementations do
something meaningful, if not, they just raise plain
NotImplementedError.
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-04-17 09:15:06 +02:00
|
|
|
rhs.st_atime,
|
2026-04-17 15:26:44 +02:00
|
|
|
rhs.st_mtime,
|
|
|
|
|
rhs.st_ctime,
|
|
|
|
|
)
|