Read a JSON file, returning empty dict on any error.
(path: Path)
| 88 | # --------------------------------------------------------------------------- |
| 89 | |
| 90 | def _read_json(path: Path) -> dict[str, Any]: |
| 91 | """Read a JSON file, returning empty dict on any error.""" |
| 92 | if not path.exists(): |
| 93 | return {} |
| 94 | try: |
| 95 | with open(path, "r", encoding="utf-8") as f: |
| 96 | data = json.load(f) |
| 97 | except Exception as exc: |
| 98 | logger.debug("Failed to read config %s: %s", path, exc) |
| 99 | return {} |
| 100 | if not isinstance(data, dict): |
| 101 | # A non-object top level previously flowed into _deep_merge and |
| 102 | # raised AttributeError at the call site (C6 review M2) — treat |
| 103 | # it like any other unreadable config: ignored. |
| 104 | logger.debug("Ignoring non-object config %s", path) |
| 105 | return {} |
| 106 | return data |
| 107 | |
| 108 | |
| 109 | def _atomic_write_json(path: Path, data: dict[str, Any]) -> None: |