I have a use case where I need to check, whether / is mounted read-only.
Here's the module where I implemented this check:
"""Check mount points."""
from __future__ import annotations
from contextlib import suppress
from os import linesep
from pathlib import Path
from re import fullmatch
from subprocess import check_output
from typing import Any, Iterator, NamedTuple
__all__ = ['mount', 'root_mounted_ro']
MOUNT_REGEX = r'(.+) on (.+) type (.+) \((.+)\)'
class MountPoint(NamedTuple):
"""Representation of mount points."""
what: str
where: Path
type: str
flags: list[str]
@classmethod
def from_string(cls, string: str) -> MountPoint:
"""Creates a mount point from a string."""
if (match := fullmatch(MOUNT_REGEX, string)) is None:
raise ValueError('Invalid mount value:', string)
what, where, typ, flags = match.groups()
return cls(what, Path(where), typ, flags.split(','))
def to_json(self) -> dict[str, Any]:
"""Return a JSON-ish dict."""
return {
'what': self.what,
'where': str(self.where),
'type': self.type,
'flags': self.flags
}
def mount() -> Iterator[MountPoint]:
"""Yields mount points on the system."""
for line in check_output('mount', text=True).split(linesep):
with suppress(ValueError):
yield MountPoint.from_string(line)
def root_mounted_ro() -> bool | None:
"""Check whether / is mounted read-only."""
for mnt in mount():
if mnt.where == Path('/'):
return 'ro' in mnt.flags
return None
Is there a better approach than parsing the output of mount using a regex?