improve logger

This commit is contained in:
Sina Atalay 2023-10-28 02:35:20 +02:00
parent 36db448628
commit 73a10bb124
2 changed files with 73 additions and 17 deletions

View File

@ -38,16 +38,23 @@ def user_friendly_errors(func: Callable) -> Callable:
except ValidationError as e:
# It is a Pydantic error
error_messages = []
error_messages.append("There are validation errors!")
error_messages.append("There are some problems with your input 🧐")
# Translate Pydantic's error messages to make them more user-friendly
custom_error_messages_by_type = {
"url_scheme": "This is not a valid URL 😿",
"string_type": "This is not a valid string 🤭",
"missing": "This field is required, but it is missing 😆",
"literal_error": "Only the following values are allowed: {expected} 😒",
}
custom_error_messages_by_msg = {
"value is not a valid phone number": (
"This is not a valid phone number 👺"
)
),
"String should match pattern '\\d+\\.?\\d* *(cm|in|pt|mm|ex|em)'": (
"This is not a valid length! Use a number followed by a unit "
"of length (cm, in, pt, mm, ex, em) 👺"
),
}
new_errors: list[ErrorDetails] = []
for error in e.errors():
@ -68,21 +75,34 @@ def user_friendly_errors(func: Callable) -> Callable:
if custom_message:
ctx = error.get("ctx")
error["msg"] = (
custom_message.format(**ctx) if ctx else custom_message
)
if ctx:
if ctx.get("error"):
error["msg"] = ctx["error"].args[0]
else:
error["msg"] = custom_message.format(**ctx)
else:
error["msg"] = custom_message
# If the input value is a dictionary or if the input value is in the
# error message, remove it
if isinstance(error["input"], dict) or error["input"] in error["msg"]:
if error["input"] is not None:
# If the input value is a dictionary, remove it
if isinstance(error["input"], dict):
error["input"] = None
elif isinstance(error["input"], (float, int, bool, str)):
# Or if the input value is in the error message, remove it
input_value = str(error["input"])
if input_value in error["msg"]:
error["input"] = None
new_errors.append(error)
# Create a custom error message for RenderCV users
for error in new_errors:
if len(error["loc"]) > 0:
location = ".".join(error["loc"])
error_messages.append(f"{location}:\n {error['msg']}")
else:
error_messages.append(f"{error['msg']}")
if error["input"]:
error_messages[-1] += f"\n Your input was \"{error['input']}\""
error_message = "\n\n ".join(error_messages)

View File

@ -65,6 +65,7 @@ dictionary = [
"javascript",
]
spell = SpellChecker()
all_misspelled_words = set()
def check_spelling(sentence: str) -> str:
@ -110,10 +111,7 @@ def check_spelling(sentence: str) -> str:
if word in dictionary:
continue
logger.warning(
f'The word "{word}" might be misspelled according to the'
" pyspellchecker."
)
all_misspelled_words.add(word)
return sentence
@ -1232,6 +1230,35 @@ class CurriculumVitae(BaseModel):
return model
@model_validator(mode="after")
@classmethod
def print_all_the_misspeled_words(cls, model):
"""Print all the words that are misspelled according to pyspellchecker."""
if len(all_misspelled_words) > 0:
messages = []
messages.append(
"The following words might be misspelled (according to pyspellchecker):"
)
misspelled_words = list(all_misspelled_words)
# Make misspeled_words a list of lists where each list contains 5:
misspelled_words = [
misspelled_words[i : i + 5] for i in range(0, len(misspelled_words), 5)
]
# Join the words in each list with a comma, and join the lists with a new
# line:
misspelled_words = "\n ".join(
[", ".join(words) for words in misspelled_words]
)
messages.append(f" {misspelled_words}")
# Print the messages:
logger.warning("\n".join(messages))
return model
@computed_field
@cached_property
def connections(self) -> list[Connection]:
@ -1328,6 +1355,10 @@ class CurriculumVitae(BaseModel):
link_text = custom_section.link_text
entries = custom_section.entries
break
else:
entry_type = None
link_text = None
entries = None
if entry_type is None or entries is None:
raise ValueError(
@ -1396,10 +1427,15 @@ class RenderCVDataModel(BaseModel):
section_titles = [section.title for section in cv.sections]
for title in design.options.show_timespan_in: # type: ignore
if title not in section_titles:
not_used_section_titles = list(
set(section_titles) - set(design.options.show_timespan_in)
)
not_used_section_titles = ", ".join(not_used_section_titles)
raise ValueError(
f'The section "{title}" that is specified in the'
' "show_timespan_in" option is not found in the CV 😱! The'
f" available section titles are: {section_titles}"
' "show_timespan_in" option is not found in the CV 😱 You'
" might have wanted to use one of these:"
f" {not_used_section_titles}"
)
return model