mirror of https://github.com/eyhc1/rendercv.git
proofread
This commit is contained in:
parent
e1403b537e
commit
9b5deee285
|
@ -143,7 +143,7 @@ class RenderCVBaseModel(pydantic.BaseModel):
|
|||
# Entry models: ========================================================================
|
||||
# ======================================================================================
|
||||
|
||||
# Create an URL validator to validate social network URLs:
|
||||
# Create a URL validator to validate social network URLs:
|
||||
url_validator = pydantic.TypeAdapter(pydantic.HttpUrl) # type: ignore
|
||||
|
||||
|
||||
|
@ -189,7 +189,7 @@ class EntryWithDate(RenderCVBaseModel):
|
|||
title="Date",
|
||||
description=(
|
||||
"The date field can be filled in YYYY-MM-DD, YYYY-MM, or YYYY formats or as"
|
||||
' an arbitrary string like "Fall 2023".'
|
||||
" an arbitrary string like \"Fall 2023\"."
|
||||
),
|
||||
examples=["2020-09-24", "Fall 2023"],
|
||||
)
|
||||
|
@ -210,7 +210,7 @@ class EntryWithDate(RenderCVBaseModel):
|
|||
# Check if it is a valid date:
|
||||
get_date_object(date)
|
||||
|
||||
# check if it is in YYYY format, and if so, convert it to an
|
||||
# Check if it is in YYYY format, and if so, convert it to an
|
||||
# integer:
|
||||
if re.fullmatch(r"\d{4}", date):
|
||||
# This is not required for start_date and end_date because they
|
||||
|
@ -281,7 +281,7 @@ class PublicationEntryBase(RenderCVBaseModel):
|
|||
if err.code == 404:
|
||||
raise ValueError("DOI cannot be found in the DOI System!")
|
||||
except (InvalidURL, URLError):
|
||||
raise ValueError("This DOI is not valid!")
|
||||
raise ValueError("This DOI is invalid!")
|
||||
|
||||
return doi
|
||||
|
||||
|
@ -322,7 +322,7 @@ class EntryBase(EntryWithDate):
|
|||
title="End Date",
|
||||
description=(
|
||||
"The end date of the event in YYYY-MM-DD, YYYY-MM, or YYYY format. If the"
|
||||
' event is still ongoing, then type "present" or provide only the'
|
||||
" event is still ongoing, then type \"present\" or provide only the"
|
||||
" start_date."
|
||||
),
|
||||
examples=["2020-09-24", "present"],
|
||||
|
@ -359,7 +359,7 @@ class EntryBase(EntryWithDate):
|
|||
)
|
||||
def check_and_adjust_dates(self) -> "EntryBase":
|
||||
"""
|
||||
Check if the dates are provided correctly and do the necessary adjustments.
|
||||
Check if the dates are provided correctly and make the necessary adjustments.
|
||||
"""
|
||||
date_is_provided = self.date is not None
|
||||
start_date_is_provided = self.start_date is not None
|
||||
|
@ -388,8 +388,8 @@ class EntryBase(EntryWithDate):
|
|||
if start_date > end_date:
|
||||
raise ValueError(
|
||||
'"start_date" can not be after "end_date"!',
|
||||
"start_date", # this is the location of the error
|
||||
str(start_date), # this is value of the error
|
||||
"start_date", # This is the location of the error
|
||||
str(start_date), # This is value of the error
|
||||
)
|
||||
|
||||
return self
|
||||
|
@ -435,7 +435,7 @@ class EntryBase(EntryWithDate):
|
|||
date_string = f"{start_date} {locale_catalog['to']} {end_date}"
|
||||
|
||||
else:
|
||||
# Neither date, start_date, nor end_date is provided, so return an empty
|
||||
# Neither date, start_date, nor end_date are provided, so return an empty
|
||||
# string:
|
||||
date_string = ""
|
||||
|
||||
|
@ -488,7 +488,7 @@ class EntryBase(EntryWithDate):
|
|||
date_string = f"{start_date} {locale_catalog['to']} {end_date}"
|
||||
|
||||
else:
|
||||
# Neither date, start_date, nor end_date is provided, so return an empty
|
||||
# Neither date, start_date, nor end_date are provided, so return an empty
|
||||
# string:
|
||||
date_string = ""
|
||||
|
||||
|
@ -541,10 +541,10 @@ class EntryBase(EntryWithDate):
|
|||
end_date = get_date_object(self.end_date) # type: ignore
|
||||
start_date = get_date_object(self.start_date) # type: ignore
|
||||
|
||||
# calculate the number of days between start_date and end_date:
|
||||
# Calculate the number of days between start_date and end_date:
|
||||
timespan_in_days = (end_date - start_date).days # type: ignore
|
||||
|
||||
# calculate the number of years between start_date and end_date:
|
||||
# Calculate the number of years between start_date and end_date:
|
||||
how_many_years = timespan_in_days // 365
|
||||
if how_many_years == 0:
|
||||
how_many_years_string = None
|
||||
|
@ -553,14 +553,14 @@ class EntryBase(EntryWithDate):
|
|||
else:
|
||||
how_many_years_string = f"{how_many_years} {locale_catalog['years']}"
|
||||
|
||||
# calculate the number of months between start_date and end_date:
|
||||
# Calculate the number of months between start_date and end_date:
|
||||
how_many_months = round((timespan_in_days % 365) / 30)
|
||||
if how_many_months <= 1:
|
||||
how_many_months_string = f"1 {locale_catalog['month']}"
|
||||
else:
|
||||
how_many_months_string = f"{how_many_months} {locale_catalog['months']}"
|
||||
|
||||
# combine howManyYearsString and howManyMonthsString:
|
||||
# Combine howManyYearsString and howManyMonthsString:
|
||||
if how_many_years_string is None:
|
||||
time_span_string = how_many_months_string
|
||||
else:
|
||||
|
@ -576,7 +576,7 @@ class NormalEntryBase(RenderCVBaseModel):
|
|||
)
|
||||
|
||||
|
||||
# The following class is to make sure NormalEntryBase keys comes first,
|
||||
# The following class is to make sure NormalEntryBase keys come first,
|
||||
# then the keys of the EntryBase class. The only way to achieve this in Pydantic is
|
||||
# to do this.
|
||||
class NormalEntry(EntryBase, NormalEntryBase):
|
||||
|
@ -596,7 +596,7 @@ class ExperienceEntryBase(RenderCVBaseModel):
|
|||
)
|
||||
|
||||
|
||||
# The following class is to make sure ExperienceEntryBase keys comes first,
|
||||
# The following class is to make sure ExperienceEntryBase keys come first,
|
||||
# then the keys of the EntryBase class. The only way to achieve this in Pydantic is
|
||||
# to do this.
|
||||
class ExperienceEntry(EntryBase, ExperienceEntryBase):
|
||||
|
@ -622,7 +622,7 @@ class EducationEntryBase(RenderCVBaseModel):
|
|||
)
|
||||
|
||||
|
||||
# The following class is to make sure EducationEntryBase keys comes first,
|
||||
# The following class is to make sure EducationEntryBase keys come first,
|
||||
# then the keys of the EntryBase class. The only way to achieve this in Pydantic is
|
||||
# to do this.
|
||||
class EducationEntry(EntryBase, EducationEntryBase):
|
||||
|
@ -765,7 +765,7 @@ def validate_section_input(
|
|||
entries. Since there are multiple entry types, it is not possible to validate it
|
||||
directly. This function looks at the entry list's first element and determines the
|
||||
section's entry type based on the first element. Then, it validates the rest of the
|
||||
list based on the determined entry type. If it is a `Section` object, then it
|
||||
list based on the determined entry type. If it is a `Section` object, it then
|
||||
validates it directly.
|
||||
|
||||
Args:
|
||||
|
@ -774,7 +774,7 @@ def validate_section_input(
|
|||
SectionBase | list[Any]: The validated sections input.
|
||||
"""
|
||||
if isinstance(sections_input, list):
|
||||
# find the entry type based on the first identifiable entry:
|
||||
# Find the entry type based on the first identifiable entry:
|
||||
entry_type = None
|
||||
section_type = None
|
||||
for entry in sections_input:
|
||||
|
@ -786,10 +786,10 @@ def validate_section_input(
|
|||
|
||||
if entry_type is None or section_type is None:
|
||||
raise ValueError(
|
||||
"RenderCV couldn't match this section with any entry type! Please check"
|
||||
"RenderCV couldn't match this section with any entry types! Please check"
|
||||
" the entries and make sure they are provided correctly.",
|
||||
"", # this is the location of the error
|
||||
"", # this is value of the error
|
||||
"", # This is the location of the error
|
||||
"", # This is value of the error
|
||||
)
|
||||
|
||||
test_section = {
|
||||
|
@ -903,11 +903,12 @@ class SocialNetwork(RenderCVBaseModel):
|
|||
"GitHub": "https://github.com/",
|
||||
"GitLab": "https://gitlab.com/",
|
||||
"Instagram": "https://instagram.com/",
|
||||
"Orcid": "https://orcid.org/",
|
||||
"ORCID": "https://orcid.org/",
|
||||
"Twitter": "https://twitter.com/",
|
||||
"StackOverflow": "https://stackoverflow.com/users/",
|
||||
"ResearchGate": "https://researchgate.net/profile/",
|
||||
"YouTube": "https://youtube.com/",
|
||||
"Google Scholar": "https://scholar.google.com/citations?user=",
|
||||
}
|
||||
url = url_dictionary[self.network] + self.username
|
||||
|
||||
|
@ -1066,37 +1067,37 @@ class LocaleCatalog(RenderCVBaseModel):
|
|||
default="month",
|
||||
title='Translation of "Month"',
|
||||
description='Translation of the word "month" in the locale.',
|
||||
validate_default=True, # to initialize the locale catalog with the default values
|
||||
validate_default=True, # To initialize the locale catalog with the default values
|
||||
)
|
||||
months: Optional[str] = pydantic.Field(
|
||||
default="months",
|
||||
title='Translation of "Months"',
|
||||
description='Translation of the word "months" in the locale.',
|
||||
validate_default=True, # to initialize the locale catalog with the default values
|
||||
validate_default=True, # To initialize the locale catalog with the default values
|
||||
)
|
||||
year: Optional[str] = pydantic.Field(
|
||||
default="year",
|
||||
title='Translation of "Year"',
|
||||
description='Translation of the word "year" in the locale.',
|
||||
validate_default=True, # to initialize the locale catalog with the default values
|
||||
validate_default=True, # To initialize the locale catalog with the default values
|
||||
)
|
||||
years: Optional[str] = pydantic.Field(
|
||||
default="years",
|
||||
title='Translation of "Years"',
|
||||
description='Translation of the word "years" in the locale.',
|
||||
validate_default=True, # to initialize the locale catalog with the default values
|
||||
validate_default=True, # To initialize the locale catalog with the default values
|
||||
)
|
||||
present: Optional[str] = pydantic.Field(
|
||||
default="present",
|
||||
title='Translation of "Present"',
|
||||
description='Translation of the word "present" in the locale.',
|
||||
validate_default=True, # to initialize the locale catalog with the default values
|
||||
validate_default=True, # To initialize the locale catalog with the default values
|
||||
)
|
||||
to: Optional[str] = pydantic.Field(
|
||||
default="to",
|
||||
title='Translation of "To"',
|
||||
description='Translation of the word "to" in the locale.',
|
||||
validate_default=True, # to initialize the locale catalog with the default values
|
||||
validate_default=True, # To initialize the locale catalog with the default values
|
||||
)
|
||||
abbreviations_for_months: Optional[
|
||||
Annotated[list[str], at.Len(min_length=12, max_length=12)]
|
||||
|
@ -1138,9 +1139,8 @@ class LocaleCatalog(RenderCVBaseModel):
|
|||
|
||||
# Create a custom type called Design:
|
||||
# It is a union of all the design options and the correct design option is determined by
|
||||
# the theme field, thanks Pydantic's discriminator feature.
|
||||
# the theme field, thanks to Pydantic's discriminator feature.
|
||||
# See https://docs.pydantic.dev/2.5/concepts/fields/#discriminator for more information
|
||||
# about discriminators.
|
||||
RenderCVDesign = Annotated[
|
||||
ClassicThemeOptions
|
||||
| ModerncvThemeOptions
|
||||
|
@ -1188,15 +1188,15 @@ class RenderCVDataModel(RenderCVBaseModel):
|
|||
theme_data_model_types = get_args(RenderCVDesign)[0]
|
||||
|
||||
if isinstance(design, theme_data_model_types):
|
||||
# then it means RenderCVDataModel is already initialized with a design, so
|
||||
# Then it means RenderCVDataModel is already initialized with a design, so
|
||||
# return it as is:
|
||||
return design
|
||||
elif design["theme"] in available_themes: # type: ignore
|
||||
# then it means it's a built-in theme, but it is not initialized (validated)
|
||||
# Then it means it's a built-in theme, but it is not initialized (validated)
|
||||
# yet. So, validate and return it:
|
||||
return rendercv_design_validator.validate_python(design)
|
||||
else:
|
||||
# then it means it is a custom theme, so initialize and validate it:
|
||||
# Then it means it is a custom theme, so initialize and validate it:
|
||||
theme_name: str = str(design["theme"])
|
||||
|
||||
# check if the theme name is valid:
|
||||
|
@ -1262,11 +1262,11 @@ class RenderCVDataModel(RenderCVBaseModel):
|
|||
theme_module, f"{theme_name.capitalize()}ThemeOptions" # type: ignore
|
||||
)
|
||||
|
||||
# initialize and validate the custom theme data model:
|
||||
# Initialize and validate the custom theme data model:
|
||||
theme_data_model = ThemeDataModel(**design)
|
||||
else:
|
||||
# Then it means there is no __init__.py file in the custom theme folder.
|
||||
# So, create a dummy data model and use that instead.
|
||||
# Create a dummy data model and use that instead.
|
||||
class ThemeOptionsAreNotProvided(RenderCVBaseModel):
|
||||
theme: str = theme_name
|
||||
|
||||
|
@ -1303,9 +1303,9 @@ def set_or_update_a_value(
|
|||
update the value. This is used for recursive calls. When the value is set
|
||||
to a sub model, the original data model is validated. Defaults to None.
|
||||
"""
|
||||
# recursively call this function until the last key is reached:
|
||||
# Recursively call this function until the last key is reached:
|
||||
|
||||
# rename `sections` with `sections_input` since the key is `sections` is an alias:
|
||||
# Rename `sections` with `sections_input` since the key is `sections` is an alias:
|
||||
key = key.replace("sections.", "sections_input.")
|
||||
keys = key.split(".")
|
||||
|
||||
|
@ -1315,12 +1315,12 @@ def set_or_update_a_value(
|
|||
model = data_model
|
||||
|
||||
if len(keys) == 1:
|
||||
# set the value:
|
||||
# Set the value:
|
||||
if value.startswith("{") and value.endswith("}"):
|
||||
# allow users to assign dictionaries:
|
||||
# Allow users to assign dictionaries:
|
||||
value = eval(value)
|
||||
elif value.startswith("[") and value.endswith("]"):
|
||||
# allow users to assign lists:
|
||||
# Allow users to assign lists:
|
||||
value = eval(value)
|
||||
|
||||
if isinstance(model, pydantic.BaseModel):
|
||||
|
@ -1374,14 +1374,14 @@ def read_input_file(
|
|||
RenderCVDataModel: The data models with $\\LaTeX$ and markdown strings.
|
||||
"""
|
||||
if isinstance(file_path_or_contents, pathlib.Path):
|
||||
# check if the file exists:
|
||||
# Check if the file exists:
|
||||
if not file_path_or_contents.exists():
|
||||
raise FileNotFoundError(
|
||||
f"The input file [magenta]{file_path_or_contents}[/magenta] doesn't"
|
||||
" exist!"
|
||||
)
|
||||
|
||||
# check the file extension:
|
||||
# Check the file extension:
|
||||
accepted_extensions = [".yaml", ".yml", ".json", ".json5"]
|
||||
if file_path_or_contents.suffix not in accepted_extensions:
|
||||
user_friendly_accepted_extensions = [
|
||||
|
@ -1402,7 +1402,7 @@ def read_input_file(
|
|||
|
||||
input_as_dictionary: dict[str, Any] = ruamel.yaml.YAML().load(file_content) # type: ignore
|
||||
|
||||
# validate the parsed dictionary by creating an instance of RenderCVDataModel:
|
||||
# Validate the parsed dictionary by creating an instance of RenderCVDataModel:
|
||||
rendercv_data_model = RenderCVDataModel(**input_as_dictionary)
|
||||
|
||||
return rendercv_data_model
|
||||
|
@ -1418,7 +1418,7 @@ def get_a_sample_data_model(
|
|||
Returns:
|
||||
RenderCVDataModel: A sample data model.
|
||||
"""
|
||||
# check if the theme is valid:
|
||||
# Check if the theme is valid:
|
||||
if theme not in available_themes:
|
||||
available_themes_string = ", ".join(available_themes)
|
||||
raise ValueError(
|
||||
|
@ -1583,7 +1583,7 @@ def get_a_sample_data_model(
|
|||
"projects": [
|
||||
NormalEntry(
|
||||
name="Multi-User Drawing Tool",
|
||||
date="2004", # would omit start/end dates and replace with a project link as the date is largely irrelevant
|
||||
date="2004", # I would omit start/end dates and replace with a project link as the date is largely irrelevant
|
||||
#project_link = "github.com/username/repo"
|
||||
highlights=[
|
||||
(
|
||||
|
@ -1624,7 +1624,7 @@ def get_a_sample_data_model(
|
|||
"additional_experience_and_awards": [
|
||||
OneLineEntry(
|
||||
label="Instructor (2003-2005)",
|
||||
details="Taught two full-credit computer science courses",
|
||||
details="Taught 2 full-credit computer science courses",
|
||||
),
|
||||
OneLineEntry(
|
||||
label="Third Prize, Senior Design Project",
|
||||
|
@ -1772,7 +1772,7 @@ def generate_json_schema() -> dict[str, Any]:
|
|||
field["oneOf"] = [field["anyOf"][0]]
|
||||
del field["anyOf"]
|
||||
|
||||
# for sections field of CurriculumVitae:
|
||||
# For sections field of CurriculumVitae:
|
||||
if "additionalProperties" in field["oneOf"][0]:
|
||||
field["oneOf"][0]["additionalProperties"]["oneOf"] = (
|
||||
field["oneOf"][0]["additionalProperties"]["anyOf"]
|
||||
|
|
Loading…
Reference in New Issue