Eden: Make TOML parser a bit more user friendly

Summary:
When parsing a TOML file and there's an error, we're just raising an exception without providing the user useful information.

This diff will show the user the specific line that is likely to have the problem in the TOML file and for the cause of incorrectly quoted backslashes, a hint about the problem.

Reviewed By: jdelliot

Differential Revision: D54075769

fbshipit-source-id: 061b85341a2d834ad8aad8c8ea18d7af2491499c
This commit is contained in:
Carlos Fernandez 2024-02-27 09:31:55 -08:00 committed by Facebook GitHub Bot
parent 092c48e66d
commit 866cdc47cc
2 changed files with 35 additions and 2 deletions

View File

@ -14,6 +14,7 @@ import functools
import json
import logging
import os
import re
import shutil
import struct
import subprocess
@ -1885,11 +1886,43 @@ def _verify_mount_point(mount_point: str) -> None:
TomlConfigDict = Mapping[str, Mapping[str, Any]]
def get_line_by_number(contents: str, line_num: int) -> Optional[str]:
lines = contents.splitlines()
if len(lines) < line_num or line_num < 1:
return None
return lines[line_num - 1]
def get_line_number_from_exception_message(s: str) -> int:
match = re.search(r"line (\d+)", s)
if match:
return int(match.group(1))
else:
return -1
def load_toml_config(path: Path) -> TomlConfigDict:
data: str = ""
hint: str = ""
try:
return typing.cast(TomlConfigDict, toml.load(str(path)))
with open(path, "r") as file:
data = file.read()
return typing.cast(TomlConfigDict, toml.loads(data))
except FileNotFoundError:
raise
except ValueError as e:
print(f"Value error: {e}")
if e.args[0].startswith(
"Reserved escape sequence used"
): # OK to hardcode this text; it's hardcoded in toml lib too
hint = "\nHint: Check that you don't have single backslashes.\n"
line_num = get_line_number_from_exception_message(e.args[0])
if line_num != -1:
line = get_line_by_number(data, line_num)
if line is not None:
hint += f"Detected here (line {line_num}): \n\n{line}\n"
raise FileError(f"toml config file {str(path)} not valid: {str(e)}{hint}")
except Exception as e:
raise FileError(
f"toml config file {str(path)} is either missing or corrupted: {str(e)}"

View File

@ -185,7 +185,7 @@ class TomlConfigTest(EdenTestCaseBase):
cfg._loadConfig()
self.assertTrue(
re.search(
"toml config file .* is either missing or corrupted",
"toml config file .* not valid",
"\n".join(logs_assertion.output),
)
)