This commit is contained in:
sebastien committed 2026-10-21 22:28:27 +02:00
1 parent 0d8970061e
commit c30aac0572
14 files changed
+343 -48

No files matched your search

+32 -1
View File
@@ -19,9 +19,40 @@ class JsonLockTimeout(TimeoutError):
pass
def read_json(path: str | Path, *, default: T | object = _MISSING) -> T:
def read_json(
path: str | Path, *, default: T | object = _MISSING,
repair_trailing_commas: bool = False,
) -> T:
target = Path(path)
try:
if repair_trailing_commas and target.name != "refaire.json":
original = text = target.read_text(encoding="utf-8")
while True:
try:
value = json.loads(text)
except json.JSONDecodeError as error:
# Only remove a comma immediately before a closing
# delimiter reported by the parser, never inside strings.
position = error.pos
# Python 3.14 points at the comma; older versions point
# at the closing bracket or brace.
if error.msg.startswith("Illegal trailing comma"):
position += 1
while position < len(text) and text[position] in " \t\r\n":
position += 1
before = text[:position].rstrip()
if (position >= len(text) or text[position] not in "]}"
or not before.endswith(",")
or not before[:-1].rstrip()
or before[:-1].rstrip()[-1] in "[{:,"):
raise
comma = len(before) - 1
text = text[:comma] + text[comma + 1:]
continue
break
if text != original:
atomic_write_text(target, text)
return cast(T, value)
with target.open("r", encoding="utf-8") as stream:
if target.name == "refaire.json":
# This user-edited selection supports whole-line // comments.