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: ========================================================================
|
# 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
|
url_validator = pydantic.TypeAdapter(pydantic.HttpUrl) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ class EntryWithDate(RenderCVBaseModel):
|
||||||
title="Date",
|
title="Date",
|
||||||
description=(
|
description=(
|
||||||
"The date field can be filled in YYYY-MM-DD, YYYY-MM, or YYYY formats or as"
|
"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"],
|
examples=["2020-09-24", "Fall 2023"],
|
||||||
)
|
)
|
||||||
|
@ -210,7 +210,7 @@ class EntryWithDate(RenderCVBaseModel):
|
||||||
# Check if it is a valid date:
|
# Check if it is a valid date:
|
||||||
get_date_object(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:
|
# integer:
|
||||||
if re.fullmatch(r"\d{4}", date):
|
if re.fullmatch(r"\d{4}", date):
|
||||||
# This is not required for start_date and end_date because they
|
# This is not required for start_date and end_date because they
|
||||||
|
@ -281,7 +281,7 @@ class PublicationEntryBase(RenderCVBaseModel):
|
||||||
if err.code == 404:
|
if err.code == 404:
|
||||||
raise ValueError("DOI cannot be found in the DOI System!")
|
raise ValueError("DOI cannot be found in the DOI System!")
|
||||||
except (InvalidURL, URLError):
|
except (InvalidURL, URLError):
|
||||||
raise ValueError("This DOI is not valid!")
|
raise ValueError("This DOI is invalid!")
|
||||||
|
|
||||||
return doi
|
return doi
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ class EntryBase(EntryWithDate):
|
||||||
title="End Date",
|
title="End Date",
|
||||||
description=(
|
description=(
|
||||||
"The end date of the event in YYYY-MM-DD, YYYY-MM, or YYYY format. If the"
|
"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."
|
" start_date."
|
||||||
),
|
),
|
||||||
examples=["2020-09-24", "present"],
|
examples=["2020-09-24", "present"],
|
||||||
|
@ -359,7 +359,7 @@ class EntryBase(EntryWithDate):
|
||||||
)
|
)
|
||||||
def check_and_adjust_dates(self) -> "EntryBase":
|
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
|
date_is_provided = self.date is not None
|
||||||
start_date_is_provided = self.start_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:
|
if start_date > end_date:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'"start_date" can not be after "end_date"!',
|
'"start_date" can not be after "end_date"!',
|
||||||
"start_date", # this is the location of the error
|
"start_date", # This is the location of the error
|
||||||
str(start_date), # this is value of the error
|
str(start_date), # This is value of the error
|
||||||
)
|
)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
@ -435,7 +435,7 @@ class EntryBase(EntryWithDate):
|
||||||
date_string = f"{start_date} {locale_catalog['to']} {end_date}"
|
date_string = f"{start_date} {locale_catalog['to']} {end_date}"
|
||||||
|
|
||||||
else:
|
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:
|
# string:
|
||||||
date_string = ""
|
date_string = ""
|
||||||
|
|
||||||
|
@ -488,7 +488,7 @@ class EntryBase(EntryWithDate):
|
||||||
date_string = f"{start_date} {locale_catalog['to']} {end_date}"
|
date_string = f"{start_date} {locale_catalog['to']} {end_date}"
|
||||||
|
|
||||||
else:
|
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:
|
# string:
|
||||||
date_string = ""
|
date_string = ""
|
||||||
|
|
||||||
|
@ -541,10 +541,10 @@ class EntryBase(EntryWithDate):
|
||||||
end_date = get_date_object(self.end_date) # type: ignore
|
end_date = get_date_object(self.end_date) # type: ignore
|
||||||
start_date = get_date_object(self.start_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
|
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
|
how_many_years = timespan_in_days // 365
|
||||||
if how_many_years == 0:
|
if how_many_years == 0:
|
||||||
how_many_years_string = None
|
how_many_years_string = None
|
||||||
|
@ -553,14 +553,14 @@ class EntryBase(EntryWithDate):
|
||||||
else:
|
else:
|
||||||
how_many_years_string = f"{how_many_years} {locale_catalog['years']}"
|
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)
|
how_many_months = round((timespan_in_days % 365) / 30)
|
||||||
if how_many_months <= 1:
|
if how_many_months <= 1:
|
||||||
how_many_months_string = f"1 {locale_catalog['month']}"
|
how_many_months_string = f"1 {locale_catalog['month']}"
|
||||||
else:
|
else:
|
||||||
how_many_months_string = f"{how_many_months} {locale_catalog['months']}"
|
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:
|
if how_many_years_string is None:
|
||||||
time_span_string = how_many_months_string
|
time_span_string = how_many_months_string
|
||||||
else:
|
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
|
# then the keys of the EntryBase class. The only way to achieve this in Pydantic is
|
||||||
# to do this.
|
# to do this.
|
||||||
class NormalEntry(EntryBase, NormalEntryBase):
|
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
|
# then the keys of the EntryBase class. The only way to achieve this in Pydantic is
|
||||||
# to do this.
|
# to do this.
|
||||||
class ExperienceEntry(EntryBase, ExperienceEntryBase):
|
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
|
# then the keys of the EntryBase class. The only way to achieve this in Pydantic is
|
||||||
# to do this.
|
# to do this.
|
||||||
class EducationEntry(EntryBase, EducationEntryBase):
|
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
|
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
|
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
|
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.
|
validates it directly.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -774,7 +774,7 @@ def validate_section_input(
|
||||||
SectionBase | list[Any]: The validated sections input.
|
SectionBase | list[Any]: The validated sections input.
|
||||||
"""
|
"""
|
||||||
if isinstance(sections_input, list):
|
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
|
entry_type = None
|
||||||
section_type = None
|
section_type = None
|
||||||
for entry in sections_input:
|
for entry in sections_input:
|
||||||
|
@ -786,10 +786,10 @@ def validate_section_input(
|
||||||
|
|
||||||
if entry_type is None or section_type is None:
|
if entry_type is None or section_type is None:
|
||||||
raise ValueError(
|
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.",
|
" the entries and make sure they are provided correctly.",
|
||||||
"", # this is the location of the error
|
"", # This is the location of the error
|
||||||
"", # this is value of the error
|
"", # This is value of the error
|
||||||
)
|
)
|
||||||
|
|
||||||
test_section = {
|
test_section = {
|
||||||
|
@ -903,11 +903,12 @@ class SocialNetwork(RenderCVBaseModel):
|
||||||
"GitHub": "https://github.com/",
|
"GitHub": "https://github.com/",
|
||||||
"GitLab": "https://gitlab.com/",
|
"GitLab": "https://gitlab.com/",
|
||||||
"Instagram": "https://instagram.com/",
|
"Instagram": "https://instagram.com/",
|
||||||
"Orcid": "https://orcid.org/",
|
"ORCID": "https://orcid.org/",
|
||||||
"Twitter": "https://twitter.com/",
|
"Twitter": "https://twitter.com/",
|
||||||
"StackOverflow": "https://stackoverflow.com/users/",
|
"StackOverflow": "https://stackoverflow.com/users/",
|
||||||
"ResearchGate": "https://researchgate.net/profile/",
|
"ResearchGate": "https://researchgate.net/profile/",
|
||||||
"YouTube": "https://youtube.com/",
|
"YouTube": "https://youtube.com/",
|
||||||
|
"Google Scholar": "https://scholar.google.com/citations?user=",
|
||||||
}
|
}
|
||||||
url = url_dictionary[self.network] + self.username
|
url = url_dictionary[self.network] + self.username
|
||||||
|
|
||||||
|
@ -1066,37 +1067,37 @@ class LocaleCatalog(RenderCVBaseModel):
|
||||||
default="month",
|
default="month",
|
||||||
title='Translation of "Month"',
|
title='Translation of "Month"',
|
||||||
description='Translation of the word "month" in the locale.',
|
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(
|
months: Optional[str] = pydantic.Field(
|
||||||
default="months",
|
default="months",
|
||||||
title='Translation of "Months"',
|
title='Translation of "Months"',
|
||||||
description='Translation of the word "months" in the locale.',
|
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(
|
year: Optional[str] = pydantic.Field(
|
||||||
default="year",
|
default="year",
|
||||||
title='Translation of "Year"',
|
title='Translation of "Year"',
|
||||||
description='Translation of the word "year" in the locale.',
|
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(
|
years: Optional[str] = pydantic.Field(
|
||||||
default="years",
|
default="years",
|
||||||
title='Translation of "Years"',
|
title='Translation of "Years"',
|
||||||
description='Translation of the word "years" in the locale.',
|
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(
|
present: Optional[str] = pydantic.Field(
|
||||||
default="present",
|
default="present",
|
||||||
title='Translation of "Present"',
|
title='Translation of "Present"',
|
||||||
description='Translation of the word "present" in the locale.',
|
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(
|
to: Optional[str] = pydantic.Field(
|
||||||
default="to",
|
default="to",
|
||||||
title='Translation of "To"',
|
title='Translation of "To"',
|
||||||
description='Translation of the word "to" in the locale.',
|
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[
|
abbreviations_for_months: Optional[
|
||||||
Annotated[list[str], at.Len(min_length=12, max_length=12)]
|
Annotated[list[str], at.Len(min_length=12, max_length=12)]
|
||||||
|
@ -1138,9 +1139,8 @@ class LocaleCatalog(RenderCVBaseModel):
|
||||||
|
|
||||||
# Create a custom type called Design:
|
# Create a custom type called Design:
|
||||||
# It is a union of all the design options and the correct design option is determined by
|
# 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
|
# See https://docs.pydantic.dev/2.5/concepts/fields/#discriminator for more information
|
||||||
# about discriminators.
|
|
||||||
RenderCVDesign = Annotated[
|
RenderCVDesign = Annotated[
|
||||||
ClassicThemeOptions
|
ClassicThemeOptions
|
||||||
| ModerncvThemeOptions
|
| ModerncvThemeOptions
|
||||||
|
@ -1188,15 +1188,15 @@ class RenderCVDataModel(RenderCVBaseModel):
|
||||||
theme_data_model_types = get_args(RenderCVDesign)[0]
|
theme_data_model_types = get_args(RenderCVDesign)[0]
|
||||||
|
|
||||||
if isinstance(design, theme_data_model_types):
|
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 it as is:
|
||||||
return design
|
return design
|
||||||
elif design["theme"] in available_themes: # type: ignore
|
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:
|
# yet. So, validate and return it:
|
||||||
return rendercv_design_validator.validate_python(design)
|
return rendercv_design_validator.validate_python(design)
|
||||||
else:
|
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"])
|
theme_name: str = str(design["theme"])
|
||||||
|
|
||||||
# check if the theme name is valid:
|
# check if the theme name is valid:
|
||||||
|
@ -1262,11 +1262,11 @@ class RenderCVDataModel(RenderCVBaseModel):
|
||||||
theme_module, f"{theme_name.capitalize()}ThemeOptions" # type: ignore
|
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)
|
theme_data_model = ThemeDataModel(**design)
|
||||||
else:
|
else:
|
||||||
# Then it means there is no __init__.py file in the custom theme folder.
|
# 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):
|
class ThemeOptionsAreNotProvided(RenderCVBaseModel):
|
||||||
theme: str = theme_name
|
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
|
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.
|
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.")
|
key = key.replace("sections.", "sections_input.")
|
||||||
keys = key.split(".")
|
keys = key.split(".")
|
||||||
|
|
||||||
|
@ -1315,12 +1315,12 @@ def set_or_update_a_value(
|
||||||
model = data_model
|
model = data_model
|
||||||
|
|
||||||
if len(keys) == 1:
|
if len(keys) == 1:
|
||||||
# set the value:
|
# Set the value:
|
||||||
if value.startswith("{") and value.endswith("}"):
|
if value.startswith("{") and value.endswith("}"):
|
||||||
# allow users to assign dictionaries:
|
# Allow users to assign dictionaries:
|
||||||
value = eval(value)
|
value = eval(value)
|
||||||
elif value.startswith("[") and value.endswith("]"):
|
elif value.startswith("[") and value.endswith("]"):
|
||||||
# allow users to assign lists:
|
# Allow users to assign lists:
|
||||||
value = eval(value)
|
value = eval(value)
|
||||||
|
|
||||||
if isinstance(model, pydantic.BaseModel):
|
if isinstance(model, pydantic.BaseModel):
|
||||||
|
@ -1374,14 +1374,14 @@ def read_input_file(
|
||||||
RenderCVDataModel: The data models with $\\LaTeX$ and markdown strings.
|
RenderCVDataModel: The data models with $\\LaTeX$ and markdown strings.
|
||||||
"""
|
"""
|
||||||
if isinstance(file_path_or_contents, pathlib.Path):
|
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():
|
if not file_path_or_contents.exists():
|
||||||
raise FileNotFoundError(
|
raise FileNotFoundError(
|
||||||
f"The input file [magenta]{file_path_or_contents}[/magenta] doesn't"
|
f"The input file [magenta]{file_path_or_contents}[/magenta] doesn't"
|
||||||
" exist!"
|
" exist!"
|
||||||
)
|
)
|
||||||
|
|
||||||
# check the file extension:
|
# Check the file extension:
|
||||||
accepted_extensions = [".yaml", ".yml", ".json", ".json5"]
|
accepted_extensions = [".yaml", ".yml", ".json", ".json5"]
|
||||||
if file_path_or_contents.suffix not in accepted_extensions:
|
if file_path_or_contents.suffix not in accepted_extensions:
|
||||||
user_friendly_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
|
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)
|
rendercv_data_model = RenderCVDataModel(**input_as_dictionary)
|
||||||
|
|
||||||
return rendercv_data_model
|
return rendercv_data_model
|
||||||
|
@ -1418,7 +1418,7 @@ def get_a_sample_data_model(
|
||||||
Returns:
|
Returns:
|
||||||
RenderCVDataModel: A sample data model.
|
RenderCVDataModel: A sample data model.
|
||||||
"""
|
"""
|
||||||
# check if the theme is valid:
|
# Check if the theme is valid:
|
||||||
if theme not in available_themes:
|
if theme not in available_themes:
|
||||||
available_themes_string = ", ".join(available_themes)
|
available_themes_string = ", ".join(available_themes)
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -1583,7 +1583,7 @@ def get_a_sample_data_model(
|
||||||
"projects": [
|
"projects": [
|
||||||
NormalEntry(
|
NormalEntry(
|
||||||
name="Multi-User Drawing Tool",
|
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"
|
#project_link = "github.com/username/repo"
|
||||||
highlights=[
|
highlights=[
|
||||||
(
|
(
|
||||||
|
@ -1624,7 +1624,7 @@ def get_a_sample_data_model(
|
||||||
"additional_experience_and_awards": [
|
"additional_experience_and_awards": [
|
||||||
OneLineEntry(
|
OneLineEntry(
|
||||||
label="Instructor (2003-2005)",
|
label="Instructor (2003-2005)",
|
||||||
details="Taught two full-credit computer science courses",
|
details="Taught 2 full-credit computer science courses",
|
||||||
),
|
),
|
||||||
OneLineEntry(
|
OneLineEntry(
|
||||||
label="Third Prize, Senior Design Project",
|
label="Third Prize, Senior Design Project",
|
||||||
|
@ -1772,7 +1772,7 @@ def generate_json_schema() -> dict[str, Any]:
|
||||||
field["oneOf"] = [field["anyOf"][0]]
|
field["oneOf"] = [field["anyOf"][0]]
|
||||||
del field["anyOf"]
|
del field["anyOf"]
|
||||||
|
|
||||||
# for sections field of CurriculumVitae:
|
# For sections field of CurriculumVitae:
|
||||||
if "additionalProperties" in field["oneOf"][0]:
|
if "additionalProperties" in field["oneOf"][0]:
|
||||||
field["oneOf"][0]["additionalProperties"]["oneOf"] = (
|
field["oneOf"][0]["additionalProperties"]["oneOf"] = (
|
||||||
field["oneOf"][0]["additionalProperties"]["anyOf"]
|
field["oneOf"][0]["additionalProperties"]["anyOf"]
|
||||||
|
|
Loading…
Reference in New Issue