Merge pull request #1 from akib1689/add-settings

feat: Added render cv settings
This commit is contained in:
Akibur Rahman
2024-09-01 23:23:37 +06:00
committed by GitHub
17 changed files with 430 additions and 35 deletions

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 KiB

After

Width:  |  Height:  |  Size: 474 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 KiB

After

Width:  |  Height:  |  Size: 564 KiB

View File

Binary file not shown.

View File

@@ -141,3 +141,8 @@ design:
bottom: 0.3 cm
horizontal_between_connections: 0.5 cm
show_timespan_in: []
rendercv_settings:
output_folder_name: rendercv_output
no_html: false
no_markdown: false
no_png: false

View File

Binary file not shown.

View File

@@ -139,3 +139,8 @@ design:
vertical_between_name_and_connections: 5 pt
bottom: 5 pt
horizontal_between_connections: 10 pt
rendercv_settings:
output_folder_name: rendercv_output
no_html: false
no_markdown: false
no_png: false

View File

Binary file not shown.

View File

@@ -112,3 +112,8 @@ design:
content_scale: 0.75
show_only_years: false
disable_page_numbers: false
rendercv_settings:
output_folder_name: rendercv_output
no_html: false
no_markdown: false
no_png: false

View File

Binary file not shown.

View File

@@ -139,3 +139,8 @@ design:
vertical_between_name_and_connections: 0.3 cm
bottom: 0.3 cm
horizontal_between_connections: 0.5 cm
rendercv_settings:
output_folder_name: rendercv_output
no_html: false
no_markdown: false
no_png: false

View File

@@ -5,7 +5,7 @@ commands of RenderCV.
import os
import pathlib
from typing import Annotated, Literal, Optional
from typing import Annotated, Optional
import typer
from rich import print
@@ -141,18 +141,38 @@ def cli_command_render(
input_file_path: pathlib.Path = utilities.string_to_file_path(
input_file_name
) # type: ignore
output_directory = pathlib.Path.cwd() / output_folder_name
paths: dict[
Literal["latex", "pdf", "markdown", "html", "png"], Optional[pathlib.Path]
] = {
"latex": utilities.string_to_file_path(latex_path),
"pdf": utilities.string_to_file_path(pdf_path),
"markdown": utilities.string_to_file_path(markdown_path),
"html": utilities.string_to_file_path(html_path),
"png": utilities.string_to_file_path(png_path),
# dictionary for command line arguments:
cli_args = {
"use_local_latex_command": use_local_latex_command,
"output_folder_name": output_folder_name,
"latex_path": utilities.string_to_file_path(latex_path),
"pdf_path": utilities.string_to_file_path(pdf_path),
"markdown_path": utilities.string_to_file_path(markdown_path),
"html_path": utilities.string_to_file_path(html_path),
"png_path": utilities.string_to_file_path(png_path),
"no_markdown": dont_generate_markdown,
"no_html": dont_generate_html,
"no_png": dont_generate_png,
}
# Create the default values for the cli_args:
cli_args_default = {
"use_local_latex_command": None,
"output_folder_name": "rendercv_output",
"latex_path": None,
"pdf_path": None,
"markdown_path": None,
"html_path": None,
"png_path": None,
"no_markdown": False,
"no_html": False,
"no_png": False,
}
# keep the current working directory:
working_directory = pathlib.Path.cwd()
# change the current working directory to the input file's directory (because
# the template overrides are looked up in the current working directory):
os.chdir(input_file_path.parent)
@@ -164,17 +184,8 @@ def cli_command_render(
# 4. render PNG files from the PDF
# 5. generate the Markdown file
# 6. render the Markdown file to a HTML (for Grammarly)
number_of_steps = 6
if dont_generate_png:
number_of_steps = number_of_steps - 1
if dont_generate_markdown:
# if the Markdown file is not generated, then the HTML file is not generated
number_of_steps = number_of_steps - 2
else:
if dont_generate_html:
number_of_steps = number_of_steps - 1
with printer.LiveProgressReporter(number_of_steps) as progress:
initial_steps = 1
with printer.LiveProgressReporter(number_of_steps=initial_steps) as progress:
progress.start_a_step("Reading and validating the input file")
data_as_a_dict = data.read_a_yaml_file(input_file_path)
@@ -187,60 +198,96 @@ def cli_command_render(
data_as_a_dict = utilities.set_or_update_values(
data_as_a_dict, key_and_values
)
# update the data of the rendercv settings:
render_cv_settings = data_as_a_dict.get("rendercv_settings", dict())
render_cv_settings = utilities.build_rendercv_settings(
render_cv_settings, cli_args, cli_args_default
)
# update the data model with the rendercv settings:
data_as_a_dict["rendercv_settings"] = render_cv_settings
data_model = data.validate_input_dictionary_and_return_the_data_model(
data_as_a_dict
)
output_directory = (
working_directory / data_model.rendercv_settings.output_folder_name
)
progress.finish_the_current_step()
# Calculate the number of steps:
number_of_steps = 6
if data_model.rendercv_settings.no_png:
number_of_steps -= 1
if data_model.rendercv_settings.no_markdown:
number_of_steps -= 2
else:
if data_model.rendercv_settings.no_html:
number_of_steps -= 1
progress.update_total_steps(number_of_steps)
progress.start_a_step("Generating the LaTeX file")
latex_file_path_in_output_folder = (
renderer.create_a_latex_file_and_copy_theme_files(
data_model, output_directory
)
)
if paths["latex"]:
utilities.copy_files(latex_file_path_in_output_folder, paths["latex"])
if data_model.rendercv_settings.latex_path:
utilities.copy_files(
latex_file_path_in_output_folder,
data_model.rendercv_settings.latex_path,
)
progress.finish_the_current_step()
progress.start_a_step("Rendering the LaTeX file to a PDF")
pdf_file_path_in_output_folder = renderer.render_a_pdf_from_latex(
latex_file_path_in_output_folder, use_local_latex_command
)
if paths["pdf"]:
utilities.copy_files(pdf_file_path_in_output_folder, paths["pdf"])
if data_model.rendercv_settings.pdf_path:
utilities.copy_files(
pdf_file_path_in_output_folder, data_model.rendercv_settings.pdf_path
)
progress.finish_the_current_step()
if not dont_generate_png:
if not data_model.rendercv_settings.no_png:
progress.start_a_step("Rendering PNG files from the PDF")
png_file_paths_in_output_folder = renderer.render_pngs_from_pdf(
pdf_file_path_in_output_folder
)
if paths["png"]:
utilities.copy_files(png_file_paths_in_output_folder, paths["png"])
if data_model.rendercv_settings.png_path:
utilities.copy_files(
png_file_paths_in_output_folder,
data_model.rendercv_settings.png_path,
)
progress.finish_the_current_step()
if not dont_generate_markdown:
if not data_model.rendercv_settings.no_markdown:
progress.start_a_step("Generating the Markdown file")
markdown_file_path_in_output_folder = renderer.create_a_markdown_file(
data_model, output_directory
)
if paths["markdown"]:
if data_model.rendercv_settings.markdown_path:
utilities.copy_files(
markdown_file_path_in_output_folder, paths["markdown"]
markdown_file_path_in_output_folder,
data_model.rendercv_settings.markdown_path,
)
progress.finish_the_current_step()
if not dont_generate_html:
if not data_model.rendercv_settings.no_html:
progress.start_a_step(
"Rendering the Markdown file to a HTML (for Grammarly)"
)
html_file_path_in_output_folder = renderer.render_an_html_from_markdown(
markdown_file_path_in_output_folder
)
if paths["html"]:
utilities.copy_files(html_file_path_in_output_folder, paths["html"])
if data_model.rendercv_settings.html_path:
utilities.copy_files(
html_file_path_in_output_folder,
data_model.rendercv_settings.html_path,
)
progress.finish_the_current_step()

View File

@@ -84,6 +84,22 @@ class LiveProgressReporter(rich.live.Live):
f"{self.current_step_name} has started."
)
def update_total_steps(self, total_steps: int):
"""Update the total number of steps.
Args:
total_steps (int): The total number of steps.
"""
self.number_of_steps = total_steps
self.overall_progress.update(
self.overall_task_id,
total=total_steps,
description=(
f"[bold #AAAAAA]({self.current_step} out of"
f" {self.number_of_steps} steps finished)"
),
)
def finish_the_current_step(self):
"""Finish the current step and update the progress bars."""
self.step_progress.stop_task(self.current_step_id)

View File

@@ -260,3 +260,35 @@ def parse_render_command_override_arguments(
key_and_values[key] = value
return key_and_values
def build_rendercv_settings(
dictionary: dict,
command_line_arguments: dict[str, str],
command_line_arguments_default_values: dict[str, str],
) -> dict[str, str]:
"""Build the RenderCV settings dictionary by combining the dictionary and the command line arguments.
Args:
dictionary (dict): The dictionary to be combined with the command line
arguments.
command_line_arguments (dict[str, str]): The command line arguments.
Returns:
dict[str, str]: The combined dictionary.
"""
# Combine the dictionary and the command line arguments if the values are not None:
for key, value in command_line_arguments.items():
# check if the key is present in the both command line arguments and the default values:
if key in command_line_arguments_default_values:
default_value = command_line_arguments_default_values[key]
if value != default_value:
dictionary = set_or_update_a_value(dictionary, key, str(value))
else:
# The key is not present in the default values, set the value:
# throw an error reporting this
raise ValueError(
f"The key ({key}) is not present in the default values of the command"
" line arguments!"
)
return dictionary

View File

@@ -12,6 +12,7 @@ from .base import RenderCVBaseModelWithoutExtraKeys
from .curriculum_vitae import CurriculumVitae
from .design import RenderCVDesign
from .locale_catalog import LocaleCatalog
from .rendercv_settings import RenderCVSettings
class RenderCVDataModel(RenderCVBaseModelWithoutExtraKeys):
@@ -36,6 +37,11 @@ class RenderCVDataModel(RenderCVBaseModelWithoutExtraKeys):
),
validate_default=True,
)
rendercv_settings: RenderCVSettings = pydantic.Field(
default=RenderCVSettings(),
title="RenderCV Settings",
description="The settings of the RenderCV.",
)
@pydantic.field_validator("locale_catalog")
@classmethod
@@ -46,3 +52,15 @@ class RenderCVDataModel(RenderCVBaseModelWithoutExtraKeys):
LocaleCatalog()
return locale_catalog
@pydantic.field_validator("rendercv_settings")
@classmethod
def initialize_rendercv_settings(
cls, rendercv_settings: RenderCVSettings
) -> RenderCVSettings:
"""Even if the rendercv settings are not provided, initialize them with the default
values."""
if rendercv_settings is None:
RenderCVSettings()
return rendercv_settings

View File

@@ -0,0 +1,134 @@
"""
The `rendercv.models.rendercv_settings` module contains the data model of the
`rendercv_settings` field of the input file.
"""
from typing import Optional
import pydantic
class RenderCVSettings(pydantic.BaseModel):
"""This class is the data model of the rendercv settings. The values of each field
updates the `rendercv_settings` dictionary.
"""
model_config = pydantic.ConfigDict(
extra="forbid",
validate_default=True, # To initialize the rendercv settings with the default values
)
output_folder_name: Optional[str] = pydantic.Field(
default="rendercv_output",
title="Output Folder Name",
description=(
"The name of the folder where the output files will be saved. The default"
' value is "rendercv_output".'
),
)
use_local_latex_command: Optional[str] = pydantic.Field(
default=None,
title="Local LaTeX Command",
description=(
"The command to compile the LaTeX file to a PDF file. The default value is"
' "pdflatex".'
),
)
pdf_path: Optional[str] = pydantic.Field(
default=None,
title="PDF Path",
description=(
"The path of the PDF file. If it is not provided, the PDF file will not be"
" generated. The default value is an empty string."
),
)
latex_path: Optional[str] = pydantic.Field(
default=None,
title="LaTeX Path",
description=(
"The path of the LaTeX file. If it is not provided, the LaTeX file will not"
" be generated. The default value is an empty string."
),
)
html_path: Optional[str] = pydantic.Field(
default=None,
title="HTML Path",
description=(
"The path of the HTML file. If it is not provided, the HTML file will not"
" be generated. The default value is an empty string."
),
)
png_path: Optional[str] = pydantic.Field(
default=None,
title="PNG Path",
description=(
"The path of the PNG file. If it is not provided, the PNG file will not be"
" generated. The default value is an empty string."
),
)
markdown_path: Optional[str] = pydantic.Field(
default=None,
title="Markdown Path",
description=(
"The path of the Markdown file. If it is not provided, the Markdown file"
" will not be generated. The default value is an empty string."
),
)
no_html: Optional[bool] = pydantic.Field(
default=False,
title="Generate HTML Flag",
description=(
"A boolean value to determine whether the HTML file will be generated. The"
" default value is False."
),
)
no_markdown: Optional[bool] = pydantic.Field(
default=False,
title="Generate Markdown Flag",
description=(
"A boolean value to determine whether the Markdown file will be generated."
" The default value is False."
),
)
no_png: Optional[bool] = pydantic.Field(
default=False,
title="Generate PNG Flag",
description=(
"A boolean value to determine whether the PNG file will be generated. The"
" default value is False."
),
)
@pydantic.field_validator(
"output_folder_name",
"pdf_path",
"latex_path",
"html_path",
"png_path",
"no_html",
"no_markdown",
"no_png",
)
@classmethod
def update_settings(
cls, value: Optional[str], info: pydantic.ValidationInfo
) -> Optional[str]:
"""Update the `rendercv_settings` dictionary with the provided values."""
if value:
rendercv_settings[info.field_name] = value # type: ignore
return value
# Initialize the rendercv settings with the default values
rendercv_settings: dict[str, str] = {}
RenderCVSettings() # Initialize the rendercv settings with the default values

View File

@@ -12,7 +12,6 @@ import sys
from typing import Optional
import fitz
import markdown
from .. import data

View File

@@ -1687,6 +1687,114 @@
"title": "PublicationEntry",
"type": "object"
},
"RenderCVSettings": {
"additionalProperties": false,
"description": "This class is the data model of the rendercv settings. The values of each field\nupdates the `rendercv_settings` dictionary.",
"properties": {
"output_folder_name": {
"default": "rendercv_output",
"description": "The name of the folder where the output files will be saved. The default value is \"rendercv_output\".",
"title": "Output Folder Name",
"oneOf": [
{
"type": "string"
}
]
},
"use_local_latex_command": {
"default": null,
"description": "The command to compile the LaTeX file to a PDF file. The default value is \"pdflatex\".",
"title": "Local LaTeX Command",
"oneOf": [
{
"type": "string"
}
]
},
"pdf_path": {
"default": null,
"description": "The path of the PDF file. If it is not provided, the PDF file will not be generated. The default value is an empty string.",
"title": "PDF Path",
"oneOf": [
{
"type": "string"
}
]
},
"latex_path": {
"default": null,
"description": "The path of the LaTeX file. If it is not provided, the LaTeX file will not be generated. The default value is an empty string.",
"title": "LaTeX Path",
"oneOf": [
{
"type": "string"
}
]
},
"html_path": {
"default": null,
"description": "The path of the HTML file. If it is not provided, the HTML file will not be generated. The default value is an empty string.",
"title": "HTML Path",
"oneOf": [
{
"type": "string"
}
]
},
"png_path": {
"default": null,
"description": "The path of the PNG file. If it is not provided, the PNG file will not be generated. The default value is an empty string.",
"title": "PNG Path",
"oneOf": [
{
"type": "string"
}
]
},
"markdown_path": {
"default": null,
"description": "The path of the Markdown file. If it is not provided, the Markdown file will not be generated. The default value is an empty string.",
"title": "Markdown Path",
"oneOf": [
{
"type": "string"
}
]
},
"no_html": {
"default": false,
"description": "A boolean value to determine whether the HTML file will be generated. The default value is False.",
"title": "Generate HTML Flag",
"oneOf": [
{
"type": "boolean"
}
]
},
"no_markdown": {
"default": false,
"description": "A boolean value to determine whether the Markdown file will be generated. The default value is False.",
"title": "Generate Markdown Flag",
"oneOf": [
{
"type": "boolean"
}
]
},
"no_png": {
"default": false,
"description": "A boolean value to determine whether the PNG file will be generated. The default value is False.",
"title": "Generate PNG Flag",
"oneOf": [
{
"type": "boolean"
}
]
}
},
"title": "RenderCVSettings",
"type": "object"
},
"Sb2novThemeOptions": {
"additionalProperties": false,
"description": "This class is the data model of the theme options for the `sb2nov` theme.",
@@ -2002,6 +2110,27 @@
"default": null,
"description": "The locale catalog of the CV to allow the support of multiple languages.",
"title": "Locale Catalog"
},
"rendercv_settings": {
"allOf": [
{
"$ref": "#/$defs/RenderCVSettings"
}
],
"default": {
"output_folder_name": "rendercv_output",
"use_local_latex_command": null,
"pdf_path": null,
"latex_path": null,
"html_path": null,
"png_path": null,
"markdown_path": null,
"no_html": false,
"no_markdown": false,
"no_png": false
},
"description": "The settings of the RenderCV.",
"title": "RenderCV Settings"
}
},
"required": [