Coverage for src/rhiza_hooks/_toml.py: 100%
12 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-27 05:51 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-27 05:51 +0000
1#!/usr/bin/env python3
2"""Shared lenient TOML loader.
4Every hook that reads a TOML file — ``pyproject.toml``, ``Cargo.toml``,
5``rust-toolchain.toml``, ``.bumpversion.toml`` — treats a missing, malformed or
6unreadable file as "unspecified": a broken manifest is somebody else's error to
7report, not a reason to crash the commit. That stance used to be implemented
8separately in five modules, whose ``except`` tuples drifted apart until two of
9them crashed on invalid UTF-8 (#396). This module is now the only place that
10calls :func:`tomllib.load`.
11"""
13from __future__ import annotations
15import tomllib
16from pathlib import Path
17from typing import Any
20def load_toml(path: Path) -> dict[str, Any] | None:
21 """Parse a TOML file, treating unreadable or malformed input as absent.
23 Args:
24 path: File to parse.
26 Returns:
27 The parsed mapping, or None if the file is missing, malformed, not valid
28 UTF-8, or cannot be opened (for example, the path is a directory).
29 """
30 if not path.exists():
31 return None
32 try:
33 with path.open("rb") as handle:
34 return tomllib.load(handle)
35 except (tomllib.TOMLDecodeError, OSError, UnicodeDecodeError):
36 # tomllib decodes the stream itself, so invalid UTF-8 surfaces as
37 # UnicodeDecodeError rather than a TOML error. Anything else (e.g. a
38 # genuine bug) is left to surface.
39 return None