mirror of https://github.com/eyhc1/rendercv.git
change data model design for a better JSON schema
This commit is contained in:
parent
e176f1bf36
commit
3070092a2b
|
@ -323,7 +323,7 @@ def generate_json_schema(output_directory: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
# ======================================================================================
|
# ======================================================================================
|
||||||
# CUSTOM DATA TYPES ====================================================================
|
# DESIGN MODELS ========================================================================
|
||||||
# ======================================================================================
|
# ======================================================================================
|
||||||
|
|
||||||
# To understand how to create custom data types, see:
|
# To understand how to create custom data types, see:
|
||||||
|
@ -337,14 +337,6 @@ LaTeXDimension = Annotated[
|
||||||
LaTeXString = Annotated[str, AfterValidator(escape_latex_characters)]
|
LaTeXString = Annotated[str, AfterValidator(escape_latex_characters)]
|
||||||
SpellCheckedString = Annotated[LaTeXString, AfterValidator(check_spelling)]
|
SpellCheckedString = Annotated[LaTeXString, AfterValidator(check_spelling)]
|
||||||
|
|
||||||
# ======================================================================================
|
|
||||||
# ======================================================================================
|
|
||||||
# ======================================================================================
|
|
||||||
|
|
||||||
# ======================================================================================
|
|
||||||
# DESIGN MODELS ========================================================================
|
|
||||||
# ======================================================================================
|
|
||||||
|
|
||||||
|
|
||||||
class ClassicThemePageMargins(BaseModel):
|
class ClassicThemePageMargins(BaseModel):
|
||||||
"""This class stores the margins of pages for the classic theme."""
|
"""This class stores the margins of pages for the classic theme."""
|
||||||
|
@ -1034,24 +1026,20 @@ class Connection(BaseModel):
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
class Section(BaseModel):
|
class SectionBase(BaseModel):
|
||||||
"""This class stores a section information."""
|
"""This class stores a section information.
|
||||||
|
|
||||||
|
It is the parent class of all the section classes like
|
||||||
|
`#!python SectionWithEducationEntries`, `#!python SectionWithExperienceEntries`,
|
||||||
|
`#!python SectionWithNormalEntries`, `#!python SectionWithOneLineEntries`, and
|
||||||
|
`#!python SectionWithPublicationEntries`.
|
||||||
|
"""
|
||||||
|
|
||||||
title: LaTeXString = Field(
|
title: LaTeXString = Field(
|
||||||
title="Section Title",
|
title="Section Title",
|
||||||
description="The title of the section.",
|
description="The title of the section.",
|
||||||
examples=["My Custom Section"],
|
examples=["My Custom Section"],
|
||||||
)
|
)
|
||||||
entry_type: Literal[
|
|
||||||
"OneLineEntry",
|
|
||||||
"NormalEntry",
|
|
||||||
"ExperienceEntry",
|
|
||||||
"EducationEntry",
|
|
||||||
"PublicationEntry",
|
|
||||||
] = Field(
|
|
||||||
title="Entry Type",
|
|
||||||
description="The type of the entries in the section.",
|
|
||||||
)
|
|
||||||
link_text: Optional[LaTeXString] = Field(
|
link_text: Optional[LaTeXString] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
title="Link Text",
|
title="Link Text",
|
||||||
|
@ -1062,12 +1050,6 @@ class Section(BaseModel):
|
||||||
),
|
),
|
||||||
examples=["view on GitHub", "view on LinkedIn"],
|
examples=["view on GitHub", "view on LinkedIn"],
|
||||||
)
|
)
|
||||||
entries: list[
|
|
||||||
OneLineEntry | NormalEntry | ExperienceEntry | EducationEntry | PublicationEntry
|
|
||||||
] = Field(
|
|
||||||
title="Entries",
|
|
||||||
description="The entries of the section. The format depends on the entry type.",
|
|
||||||
)
|
|
||||||
|
|
||||||
@field_validator("title")
|
@field_validator("title")
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -1076,6 +1058,73 @@ class Section(BaseModel):
|
||||||
return title.title()
|
return title.title()
|
||||||
|
|
||||||
|
|
||||||
|
entry_type_field = Field(
|
||||||
|
title="Entry Type",
|
||||||
|
description="The type of the entries in the section.",
|
||||||
|
)
|
||||||
|
entries_field = Field(
|
||||||
|
title="Entries",
|
||||||
|
description="The entries of the section. The format depends on the entry type.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SectionWithEducationEntries(SectionBase):
|
||||||
|
"""This class stores a section with
|
||||||
|
[EducationEntry](../user_guide.md#educationentry)s.
|
||||||
|
"""
|
||||||
|
|
||||||
|
entry_type: Literal["EducationEntry"] = entry_type_field
|
||||||
|
entries: list[EducationEntry] = entries_field
|
||||||
|
|
||||||
|
|
||||||
|
class SectionWithExperienceEntries(SectionBase):
|
||||||
|
"""This class stores a section with
|
||||||
|
[ExperienceEntry](../user_guide.md#experienceentry)s.
|
||||||
|
"""
|
||||||
|
|
||||||
|
entry_type: Literal["ExperienceEntry"] = entry_type_field
|
||||||
|
entries: list[ExperienceEntry] = entries_field
|
||||||
|
|
||||||
|
|
||||||
|
class SectionWithNormalEntries(SectionBase):
|
||||||
|
"""This class stores a section with
|
||||||
|
[NormalEntry](../user_guide.md#normalentry)s.
|
||||||
|
"""
|
||||||
|
|
||||||
|
entry_type: Literal["NormalEntry"] = entry_type_field
|
||||||
|
entries: list[NormalEntry] = entries_field
|
||||||
|
|
||||||
|
|
||||||
|
class SectionWithOneLineEntries(SectionBase):
|
||||||
|
"""This class stores a section with
|
||||||
|
[OneLineEntry](../user_guide.md#onelineentry)s.
|
||||||
|
"""
|
||||||
|
|
||||||
|
entry_type: Literal["OneLineEntry"] = entry_type_field
|
||||||
|
entries: list[OneLineEntry] = entries_field
|
||||||
|
|
||||||
|
|
||||||
|
class SectionWithPublicationEntries(SectionBase):
|
||||||
|
"""This class stores a section with
|
||||||
|
[PublicationEntry](../user_guide.md#publicationentry)s.
|
||||||
|
"""
|
||||||
|
|
||||||
|
entry_type: Literal["PublicationEntry"] = entry_type_field
|
||||||
|
entries: list[PublicationEntry] = entries_field
|
||||||
|
|
||||||
|
|
||||||
|
Section = Annotated[
|
||||||
|
SectionWithEducationEntries
|
||||||
|
| SectionWithExperienceEntries
|
||||||
|
| SectionWithNormalEntries
|
||||||
|
| SectionWithOneLineEntries
|
||||||
|
| SectionWithPublicationEntries,
|
||||||
|
Field(
|
||||||
|
discriminator="entry_type",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class CurriculumVitae(BaseModel):
|
class CurriculumVitae(BaseModel):
|
||||||
"""This class bindes all the information of a CV together."""
|
"""This class bindes all the information of a CV together."""
|
||||||
|
|
||||||
|
@ -1284,7 +1333,7 @@ class CurriculumVitae(BaseModel):
|
||||||
|
|
||||||
@computed_field
|
@computed_field
|
||||||
@cached_property
|
@cached_property
|
||||||
def sections(self) -> list[Section]:
|
def sections(self) -> list[SectionBase]:
|
||||||
sections = []
|
sections = []
|
||||||
|
|
||||||
# Pre-defined sections (i.e. sections that are not custom)):
|
# Pre-defined sections (i.e. sections that are not custom)):
|
||||||
|
@ -1368,7 +1417,15 @@ class CurriculumVitae(BaseModel):
|
||||||
" order 😷"
|
" order 😷"
|
||||||
)
|
)
|
||||||
|
|
||||||
section = Section(
|
object_map = {
|
||||||
|
"EducationEntry": SectionWithEducationEntries,
|
||||||
|
"ExperienceEntry": SectionWithExperienceEntries,
|
||||||
|
"NormalEntry": SectionWithNormalEntries,
|
||||||
|
"OneLineEntry": SectionWithOneLineEntries,
|
||||||
|
"PublicationEntry": SectionWithPublicationEntries,
|
||||||
|
}
|
||||||
|
|
||||||
|
section = object_map[entry_type](
|
||||||
title=section_name,
|
title=section_name,
|
||||||
entry_type=entry_type, # type: ignore
|
entry_type=entry_type, # type: ignore
|
||||||
entries=entries,
|
entries=entries,
|
||||||
|
|
253
schema.json
253
schema.json
|
@ -534,7 +534,33 @@
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/$defs/Section"
|
"discriminator": {
|
||||||
|
"mapping": {
|
||||||
|
"EducationEntry": "#/$defs/SectionWithEducationEntries",
|
||||||
|
"ExperienceEntry": "#/$defs/SectionWithExperienceEntries",
|
||||||
|
"NormalEntry": "#/$defs/SectionWithNormalEntries",
|
||||||
|
"OneLineEntry": "#/$defs/SectionWithOneLineEntries",
|
||||||
|
"PublicationEntry": "#/$defs/SectionWithPublicationEntries"
|
||||||
|
},
|
||||||
|
"propertyName": "entry_type"
|
||||||
|
},
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/SectionWithEducationEntries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/SectionWithExperienceEntries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/SectionWithNormalEntries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/SectionWithOneLineEntries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/SectionWithPublicationEntries"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
}
|
}
|
||||||
|
@ -1263,7 +1289,7 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"Section": {
|
"SectionWithEducationEntries": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"title": {
|
"title": {
|
||||||
"description": "The title of the section.",
|
"description": "The title of the section.",
|
||||||
|
@ -1273,18 +1299,6 @@
|
||||||
"title": "Section Title",
|
"title": "Section Title",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"entry_type": {
|
|
||||||
"description": "The type of the entries in the section.",
|
|
||||||
"enum": [
|
|
||||||
"OneLineEntry",
|
|
||||||
"NormalEntry",
|
|
||||||
"ExperienceEntry",
|
|
||||||
"EducationEntry",
|
|
||||||
"PublicationEntry"
|
|
||||||
],
|
|
||||||
"title": "Entry Type",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"link_text": {
|
"link_text": {
|
||||||
"default": null,
|
"default": null,
|
||||||
"description": "If the section has a link, then what should be the text of the link? If this field is not provided, then the link text will be generated automatically based on the URL.",
|
"description": "If the section has a link, then what should be the text of the link? If this field is not provided, then the link text will be generated automatically based on the URL.",
|
||||||
|
@ -1299,27 +1313,16 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"entry_type": {
|
||||||
|
"const": "EducationEntry",
|
||||||
|
"description": "The type of the entries in the section.",
|
||||||
|
"title": "Entry Type"
|
||||||
|
},
|
||||||
"entries": {
|
"entries": {
|
||||||
"description": "The entries of the section. The format depends on the entry type.",
|
"description": "The entries of the section. The format depends on the entry type.",
|
||||||
"items": {
|
"items": {
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/OneLineEntry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/NormalEntry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/ExperienceEntry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/EducationEntry"
|
"$ref": "#/$defs/EducationEntry"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"$ref": "#/$defs/PublicationEntry"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"title": "Entries",
|
"title": "Entries",
|
||||||
"type": "array"
|
"type": "array"
|
||||||
}
|
}
|
||||||
|
@ -1329,7 +1332,195 @@
|
||||||
"entry_type",
|
"entry_type",
|
||||||
"entries"
|
"entries"
|
||||||
],
|
],
|
||||||
"title": "Section",
|
"title": "SectionWithEducationEntries",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"SectionWithExperienceEntries": {
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"description": "The title of the section.",
|
||||||
|
"examples": [
|
||||||
|
"My Custom Section"
|
||||||
|
],
|
||||||
|
"title": "Section Title",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"link_text": {
|
||||||
|
"default": null,
|
||||||
|
"description": "If the section has a link, then what should be the text of the link? If this field is not provided, then the link text will be generated automatically based on the URL.",
|
||||||
|
"examples": [
|
||||||
|
"view on GitHub",
|
||||||
|
"view on LinkedIn"
|
||||||
|
],
|
||||||
|
"title": "Link Text",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"entry_type": {
|
||||||
|
"const": "ExperienceEntry",
|
||||||
|
"description": "The type of the entries in the section.",
|
||||||
|
"title": "Entry Type"
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"description": "The entries of the section. The format depends on the entry type.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/ExperienceEntry"
|
||||||
|
},
|
||||||
|
"title": "Entries",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"entry_type",
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"title": "SectionWithExperienceEntries",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"SectionWithNormalEntries": {
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"description": "The title of the section.",
|
||||||
|
"examples": [
|
||||||
|
"My Custom Section"
|
||||||
|
],
|
||||||
|
"title": "Section Title",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"link_text": {
|
||||||
|
"default": null,
|
||||||
|
"description": "If the section has a link, then what should be the text of the link? If this field is not provided, then the link text will be generated automatically based on the URL.",
|
||||||
|
"examples": [
|
||||||
|
"view on GitHub",
|
||||||
|
"view on LinkedIn"
|
||||||
|
],
|
||||||
|
"title": "Link Text",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"entry_type": {
|
||||||
|
"const": "NormalEntry",
|
||||||
|
"description": "The type of the entries in the section.",
|
||||||
|
"title": "Entry Type"
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"description": "The entries of the section. The format depends on the entry type.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/NormalEntry"
|
||||||
|
},
|
||||||
|
"title": "Entries",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"entry_type",
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"title": "SectionWithNormalEntries",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"SectionWithOneLineEntries": {
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"description": "The title of the section.",
|
||||||
|
"examples": [
|
||||||
|
"My Custom Section"
|
||||||
|
],
|
||||||
|
"title": "Section Title",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"link_text": {
|
||||||
|
"default": null,
|
||||||
|
"description": "If the section has a link, then what should be the text of the link? If this field is not provided, then the link text will be generated automatically based on the URL.",
|
||||||
|
"examples": [
|
||||||
|
"view on GitHub",
|
||||||
|
"view on LinkedIn"
|
||||||
|
],
|
||||||
|
"title": "Link Text",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"entry_type": {
|
||||||
|
"const": "OneLineEntry",
|
||||||
|
"description": "The type of the entries in the section.",
|
||||||
|
"title": "Entry Type"
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"description": "The entries of the section. The format depends on the entry type.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/OneLineEntry"
|
||||||
|
},
|
||||||
|
"title": "Entries",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"entry_type",
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"title": "SectionWithOneLineEntries",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"SectionWithPublicationEntries": {
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"description": "The title of the section.",
|
||||||
|
"examples": [
|
||||||
|
"My Custom Section"
|
||||||
|
],
|
||||||
|
"title": "Section Title",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"link_text": {
|
||||||
|
"default": null,
|
||||||
|
"description": "If the section has a link, then what should be the text of the link? If this field is not provided, then the link text will be generated automatically based on the URL.",
|
||||||
|
"examples": [
|
||||||
|
"view on GitHub",
|
||||||
|
"view on LinkedIn"
|
||||||
|
],
|
||||||
|
"title": "Link Text",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"entry_type": {
|
||||||
|
"const": "PublicationEntry",
|
||||||
|
"description": "The type of the entries in the section.",
|
||||||
|
"title": "Entry Type"
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"description": "The entries of the section. The format depends on the entry type.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/PublicationEntry"
|
||||||
|
},
|
||||||
|
"title": "Entries",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"entry_type",
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"title": "SectionWithPublicationEntries",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue