diff --git a/rendercv/__init__.py b/rendercv/__init__.py index 05b3994a..d77c8b49 100644 --- a/rendercv/__init__.py +++ b/rendercv/__init__.py @@ -5,9 +5,41 @@ you to version-control your CV/resume as source code. __version__ = "2.1" -from .api import create_contents_of_a_typst_file +from .api import ( + create_a_markdown_file_from_a_python_dictionary, + create_a_markdown_file_from_a_yaml_string, + create_a_pdf_from_a_python_dictionary, + create_a_pdf_from_a_yaml_string, + create_a_typst_file_from_a_python_dictionary, + create_a_typst_file_from_a_yaml_string, + create_an_html_file_from_a_python_dictionary, + create_an_html_file_from_a_yaml_string, + create_contents_of_a_markdown_file_from_a_python_dictionary, + create_contents_of_a_markdown_file_from_a_yaml_string, + create_contents_of_a_typst_file_from_a_python_dictionary, + create_contents_of_a_typst_file_from_a_yaml_string, + read_a_python_dictionary_and_return_a_data_model, + read_a_yaml_string_and_return_a_data_model, +) -__all__ = ["create_contents_of_a_typst_file"] +__all__ = [ + "create_a_markdown_file_from_a_python_dictionary", + "create_a_markdown_file_from_a_python_dictionary", + "create_a_markdown_file_from_a_yaml_string", + "create_a_pdf_from_a_python_dictionary", + "create_a_pdf_from_a_yaml_string", + "create_a_typst_file_from_a_python_dictionary", + "create_a_typst_file_from_a_yaml_string", + "create_an_html_file_from_a_python_dictionary", + "create_an_html_file_from_a_yaml_string", + "create_contents_of_a_markdown_file_from_a_python_dictionary", + "create_contents_of_a_markdown_file_from_a_yaml_string", + "create_contents_of_a_typst_file_from_a_python_dictionary", + "create_contents_of_a_typst_file_from_a_python_dictionary", + "create_contents_of_a_typst_file_from_a_yaml_string", + "read_a_python_dictionary_and_return_a_data_model", + "read_a_yaml_string_and_return_a_data_model", +] _parial_install_error_message = ( "It seems you have a partial installation of RenderCV, so this feature is" diff --git a/rendercv/api/__init__.py b/rendercv/api/__init__.py index 1ccc4438..f4b98fad 100644 --- a/rendercv/api/__init__.py +++ b/rendercv/api/__init__.py @@ -3,6 +3,36 @@ The `rendercv.api` package contains the functions to create a clean and simple A RenderCV. """ -from .functions import create_contents_of_a_typst_file +from .functions import ( + create_a_markdown_file_from_a_python_dictionary, + create_a_markdown_file_from_a_yaml_string, + create_a_pdf_from_a_python_dictionary, + create_a_pdf_from_a_yaml_string, + create_a_typst_file_from_a_python_dictionary, + create_a_typst_file_from_a_yaml_string, + create_an_html_file_from_a_python_dictionary, + create_an_html_file_from_a_yaml_string, + create_contents_of_a_markdown_file_from_a_python_dictionary, + create_contents_of_a_markdown_file_from_a_yaml_string, + create_contents_of_a_typst_file_from_a_python_dictionary, + create_contents_of_a_typst_file_from_a_yaml_string, + read_a_python_dictionary_and_return_a_data_model, + read_a_yaml_string_and_return_a_data_model, +) -__all__ = ["create_contents_of_a_typst_file"] +__all__ = [ + "create_a_markdown_file_from_a_python_dictionary", + "create_a_markdown_file_from_a_yaml_string", + "create_a_pdf_from_a_python_dictionary", + "create_a_pdf_from_a_yaml_string", + "create_a_typst_file_from_a_python_dictionary", + "create_a_typst_file_from_a_yaml_string", + "create_an_html_file_from_a_python_dictionary", + "create_an_html_file_from_a_yaml_string", + "create_contents_of_a_markdown_file_from_a_python_dictionary", + "create_contents_of_a_markdown_file_from_a_yaml_string", + "create_contents_of_a_typst_file_from_a_python_dictionary", + "create_contents_of_a_typst_file_from_a_yaml_string", + "read_a_python_dictionary_and_return_a_data_model", + "read_a_yaml_string_and_return_a_data_model", +] diff --git a/rendercv/api/functions.py b/rendercv/api/functions.py index b5dc0bc6..76530cd4 100644 --- a/rendercv/api/functions.py +++ b/rendercv/api/functions.py @@ -3,17 +3,135 @@ The `rendercv.api.functions` package contains the basic functions that are used interact with the RenderCV. """ +import pathlib +import shutil +import tempfile +from collections.abc import Callable +from typing import Optional + import pydantic from .. import data, renderer -def create_contents_of_a_typst_file( +def _create_contents_of_a_something_from_something( + input: dict | str, parser: Callable, renderer: Callable +) -> str | list[dict]: + """ + Validate the input, generate a file and return it as a string. If there are any + validation errors, return them as a list of dictionaries. + + Args: + input: The input file as a dictionary or a string. + parser: The parser function. + renderer: The renderer function. + + Returns: + The file as a string or a list of dictionaries that contain the error messages, + locations, and the input values. + """ + try: + data_model = parser(input) + except pydantic.ValidationError as e: + if isinstance(input, str): + return data.parse_validation_errors(e, input) + return data.parse_validation_errors(e) + + return renderer(data_model) + + +def _create_a_file_from_something( + input: dict | str, + parser: Callable, + renderer: Callable, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input, generate a file and save it to the output file path. + + Args: + input: The input file as a dictionary or a string. + parser: The parser function. + renderer: The renderer function. + output_file_path: The output file path. + + Returns: + The output file path. + """ + try: + data_model = parser(input) + except pydantic.ValidationError as e: + return data.parse_validation_errors(e) + + with tempfile.TemporaryDirectory() as temp_dir: + temporary_output_path = pathlib.Path(temp_dir) + typst_file = renderer(data_model, temporary_output_path) + shutil.move(typst_file, output_file_path) + + return None + + +def read_a_python_dictionary_and_return_a_data_model( + input_file_as_a_dict: dict, +) -> data.RenderCVDataModel: + """ + Validate the input dictionary and return the data model. + + Args: + input_file_as_a_dict: The input file as a dictionary. + + Returns: + The data model. + """ + return data.validate_input_dictionary_and_return_the_data_model( + input_file_as_a_dict, + ) + + +def read_a_yaml_string_and_return_a_data_model( + yaml_file_as_string: str, +) -> data.RenderCVDataModel: + """ + Validate the YAML input file given as a string and return the data model. + + Args: + yaml_file_as_string: The input file as a string. + + Returns: + The data model. + """ + input_file_as_a_dict = data.read_a_yaml_file(yaml_file_as_string) + return read_a_python_dictionary_and_return_a_data_model(input_file_as_a_dict) + + +def create_contents_of_a_typst_file_from_a_python_dictionary( + input_file_as_a_dict: dict, +) -> str | list[dict]: + """ + Validate the input dictionary, generate a Typst file and return it as a string. If + there are any validation errors, return them as a list of dictionaries. + + Args: + input_file_as_a_dict: The input file as a dictionary. + + Returns: + The Typst file as a string or a list of dictionaries that contain the error + messages, locations, and the input values. + """ + return _create_contents_of_a_something_from_something( + input_file_as_a_dict, + read_a_python_dictionary_and_return_a_data_model, + renderer.create_contents_of_a_typst_file, + ) + + +def create_contents_of_a_typst_file_from_a_yaml_string( yaml_file_as_string: str, ) -> str | list[dict]: """ - Validate the input file given as a string, generate a Typst file and return it as a - string. If there are any validation errors, return them as a list of dictionaries. + Validate the YAML input file given as a string, generate a Typst file and return it + as a string. If there are any validation errors, return them as a list of + dictionaries. Args: yaml_file_as_string: The input file as a string. @@ -22,13 +140,239 @@ def create_contents_of_a_typst_file( The Typst file as a string or a list of dictionaries that contain the error messages, locations, and the input values. """ + return _create_contents_of_a_something_from_something( + yaml_file_as_string, + read_a_yaml_string_and_return_a_data_model, + renderer.create_contents_of_a_typst_file, + ) - try: - input_file_as_a_dict = data.read_a_yaml_file(yaml_file_as_string) - data_model = data.validate_input_dictionary_and_return_the_data_model( - input_file_as_a_dict, - ) - except pydantic.ValidationError as e: - return data.parse_validation_errors(e, yaml_file_as_string) - return renderer.create_contents_of_a_typst_file(data_model) +def create_contents_of_a_markdown_file_from_a_python_dictionary( + input_file_as_a_dict: dict, +) -> str | list[dict]: + """ + Validate the input dictionary, generate a Markdown file and return it as a string. + If there are any validation errors, return them as a list of dictionaries. + + Args: + input_file_as_a_dict: The input file as a dictionary. + + Returns: + The Markdown file as a string or a list of dictionaries that contain the error + messages, locations, and the input values. + """ + return _create_contents_of_a_something_from_something( + input_file_as_a_dict, + read_a_python_dictionary_and_return_a_data_model, + renderer.create_contents_of_a_markdown_file, + ) + + +def create_contents_of_a_markdown_file_from_a_yaml_string( + yaml_file_as_string: str, +) -> str | list[dict]: + """ + Validate the input file given as a string, generate a Markdown file and return it as + a string. If there are any validation errors, return them as a list of dictionaries. + + Args: + yaml_file_as_string: The input file as a string. + + Returns: + The Markdown file as a string or a list of dictionaries that contain the error + messages, locations, and the input values. + """ + return _create_contents_of_a_something_from_something( + yaml_file_as_string, + read_a_yaml_string_and_return_a_data_model, + renderer.create_contents_of_a_markdown_file, + ) + + +def create_a_typst_file_from_a_yaml_string( + yaml_file_as_string: str, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input file given as a string, generate a Typst file and save it to the + output file path. + + Args: + yaml_file_as_string: The input file as a string. + output_file_path: The output file path. + + Returns: + The output file path. + """ + + return _create_a_file_from_something( + yaml_file_as_string, + read_a_yaml_string_and_return_a_data_model, + renderer.create_a_typst_file, + output_file_path, + ) + + +def create_a_typst_file_from_a_python_dictionary( + input_file_as_a_dict: dict, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input dictionary, generate a Typst file and save it to the output file + path. + + Args: + input_file_as_a_dict: The input file as a dictionary. + output_file_path: The output file path. + + Returns: + The output file path. + """ + return _create_a_file_from_something( + input_file_as_a_dict, + read_a_python_dictionary_and_return_a_data_model, + renderer.create_a_typst_file, + output_file_path, + ) + + +def create_a_markdown_file_from_a_python_dictionary( + input_file_as_a_dict: dict, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input dictionary, generate a Markdown file and save it to the output + file path. + + Args: + input_file_as_a_dict: The input file as a dictionary. + output_file_path: The output file path. + + Returns: + The output file path. + """ + return _create_a_file_from_something( + input_file_as_a_dict, + read_a_python_dictionary_and_return_a_data_model, + renderer.create_a_markdown_file, + output_file_path, + ) + + +def create_a_markdown_file_from_a_yaml_string( + yaml_file_as_string: str, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input file given as a string, generate a Markdown file and save it to + the output file path. + + Args: + yaml_file_as_string: The input file as a string. + output_file_path: The output file path. + + Returns: + The output file path. + """ + return _create_a_file_from_something( + yaml_file_as_string, + read_a_yaml_string_and_return_a_data_model, + renderer.create_a_markdown_file, + output_file_path, + ) + + +def create_an_html_file_from_a_python_dictionary( + input_file_as_a_dict: dict, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input dictionary, generate an HTML file and save it to the output file + path. + + Args: + input_file_as_a_dict: The input file as a dictionary. + output_file_path: The output file path. + + Returns: + The output file path. + """ + return _create_a_file_from_something( + input_file_as_a_dict, + read_a_python_dictionary_and_return_a_data_model, + lambda x, y: renderer.render_an_html_from_markdown( + renderer.create_a_markdown_file(x, y), + ), + output_file_path, + ) + + +def create_an_html_file_from_a_yaml_string( + yaml_file_as_string: str, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input file given as a string, generate an HTML file and save it to the + output file path. + + Args: + yaml_file_as_string: The input file as a string. + output_file_path: The output file path. + + Returns: + The output file path. + """ + return _create_a_file_from_something( + yaml_file_as_string, + read_a_yaml_string_and_return_a_data_model, + lambda x, y: renderer.render_an_html_from_markdown( + renderer.create_a_markdown_file(x, y), + ), + output_file_path, + ) + + +def create_a_pdf_from_a_yaml_string( + yaml_file_as_string: str, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input file given as a string, generate a PDF file and save it to the + output file path. + + Args: + yaml_file_as_string: The input file as a string. + output_file_path: The output file path. + + Returns: + The output file path. + """ + return _create_a_file_from_something( + yaml_file_as_string, + read_a_yaml_string_and_return_a_data_model, + renderer.create_a_typst_file, + output_file_path, + ) + + +def create_a_pdf_from_a_python_dictionary( + input_file_as_a_dict: dict, + output_file_path: pathlib.Path, +) -> Optional[list[dict]]: + """ + Validate the input dictionary, generate a PDF file and save it to the output file + path. + + Args: + input_file_as_a_dict: The input file as a dictionary. + output_file_path: The output file path. + + Returns: + The output file path. + """ + return _create_a_file_from_something( + input_file_as_a_dict, + read_a_python_dictionary_and_return_a_data_model, + renderer.create_a_typst_file, + output_file_path, + ) diff --git a/rendercv/renderer/__init__.py b/rendercv/renderer/__init__.py index d85042ca..23bb16e7 100644 --- a/rendercv/renderer/__init__.py +++ b/rendercv/renderer/__init__.py @@ -15,6 +15,7 @@ from .renderer import ( create_a_markdown_file, create_a_typst_file, create_a_typst_file_and_copy_theme_files, + create_contents_of_a_markdown_file, create_contents_of_a_typst_file, render_a_pdf_from_typst, render_an_html_from_markdown, @@ -25,6 +26,7 @@ __all__ = [ "create_a_markdown_file", "create_a_typst_file", "create_a_typst_file_and_copy_theme_files", + "create_contents_of_a_markdown_file", "create_contents_of_a_typst_file", "render_a_pdf_from_typst", "render_an_html_from_markdown", diff --git a/rendercv/renderer/renderer.py b/rendercv/renderer/renderer.py index 3fee189e..ddef5728 100644 --- a/rendercv/renderer/renderer.py +++ b/rendercv/renderer/renderer.py @@ -14,6 +14,43 @@ from .. import data from . import templater +def create_a_file_name_without_extension_from_name(name: Optional[str]) -> str: + """Create a file name from the given name by replacing the spaces with underscores + and removing typst commands. + + Args: + name: The name to be converted. + + Returns: + The converted name (without the extension). + """ + name_without_typst_commands = templater.remove_typst_commands(str(name)) + return f"{name_without_typst_commands.replace(' ', '_')}_CV" + + +def create_a_file_and_write_contents_to_it( + contents: str, file_name: str, output_directory: pathlib.Path +) -> pathlib.Path: + """Create a file with the given contents in the output directory. + + Args: + contents: The contents of the file. + file_name: The name of the file. + output_directory: Path to the output directory. + + Returns: + The path to the created file. + """ + # Create output directory if it doesn't exist: + if not output_directory.is_dir(): + output_directory.mkdir(parents=True) + + file_path = output_directory / file_name + file_path.write_text(contents, encoding="utf-8") + + return file_path + + def copy_theme_files_to_output_directory( theme_name: str, output_directory_path: pathlib.Path, @@ -102,18 +139,37 @@ def create_a_typst_file( typst_contents = create_contents_of_a_typst_file(rendercv_data_model) - # Create output directory if it doesn't exist: - if not output_directory.is_dir(): - output_directory.mkdir(parents=True) - - name_without_typst_commands = templater.remove_typst_commands( - str(rendercv_data_model.cv.name) + file_name_without_extension = create_a_file_name_without_extension_from_name( + rendercv_data_model.cv.name ) - file_name = f"{name_without_typst_commands.replace(' ', '_')}_CV.typ" - file_path = output_directory / file_name - file_path.write_text(typst_contents, encoding="utf-8") + file_name = f"{file_name_without_extension}.typ" - return file_path + return create_a_file_and_write_contents_to_it( + typst_contents, + file_name, + output_directory, + ) + + +def create_contents_of_a_markdown_file( + rendercv_data_model: data.RenderCVDataModel, +) -> str: + """Create a Markdown file with the given data model and return it as a string. + + Args: + rendercv_data_model: The data model. + + Returns: + The path to the generated Markdown file. + """ + jinja2_environment = templater.Jinja2Environment().environment + + markdown_file_object = templater.MarkdownFile( + rendercv_data_model, + jinja2_environment, + ) + + return markdown_file_object.get_full_code() def create_a_markdown_file( @@ -129,21 +185,18 @@ def create_a_markdown_file( Returns: The path to the rendered Markdown file. """ - # create output directory if it doesn't exist: - if not output_directory.is_dir(): - output_directory.mkdir(parents=True) + markdown_contents = create_contents_of_a_markdown_file(rendercv_data_model) - jinja2_environment = templater.Jinja2Environment().environment - markdown_file_object = templater.MarkdownFile( - rendercv_data_model, - jinja2_environment, + file_name_without_extension = create_a_file_name_without_extension_from_name( + rendercv_data_model.cv.name ) + file_name = f"{file_name_without_extension}.typ" - markdown_file_name = f"{str(rendercv_data_model.cv.name).replace(' ', '_')}_CV.md" - markdown_file_path = output_directory / markdown_file_name - markdown_file_object.create_file(markdown_file_path) - - return markdown_file_path + return create_a_file_and_write_contents_to_it( + markdown_contents, + file_name, + output_directory, + ) def create_a_typst_file_and_copy_theme_files( diff --git a/tests/conftest.py b/tests/conftest.py index 41b37a0f..ad7931bb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,7 @@ import copy import filecmp import itertools +import json import pathlib import shutil import typing @@ -157,6 +158,17 @@ def rendercv_data_model() -> data.RenderCVDataModel: return data.create_a_sample_data_model() +@pytest.fixture +def rendercv_data_as_python_dictionary( + rendercv_data_model, +) -> dict: + """Return a sample RenderCV data as a Python dictionary.""" + data_model_as_json = rendercv_data_model.model_dump_json( + exclude_none=False, by_alias=True, exclude={"cv": {"sections", "photo"}} + ) + return json.loads(data_model_as_json) + + @pytest.fixture def rendercv_empty_curriculum_vitae_data_model() -> data.CurriculumVitae: """Return an empty CurriculumVitae data model.""" diff --git a/tests/test_api.py b/tests/test_api.py index 14a0b003..adbf3c04 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,6 +1,134 @@ +import pathlib +import tempfile + import rendercv +import rendercv.data def test_create_contents_of_a_typst_file(input_file_path): yaml_string = input_file_path.read_text() - assert isinstance(rendercv.create_contents_of_a_typst_file(yaml_string), str) + assert isinstance( + rendercv.create_contents_of_a_typst_file_from_a_yaml_string(yaml_string), str + ) + + +def test_create_contents_of_a_typst_file_with_errors( + rendercv_data_as_python_dictionary, +): + rendercv_data_as_python_dictionary["cv"]["email"] = "invalid-email" + yaml_string = rendercv.data.generator.dictionary_to_yaml( + rendercv_data_as_python_dictionary + ) + assert isinstance( + rendercv.create_contents_of_a_typst_file_from_a_yaml_string(yaml_string), list + ) + + +def test_create_a_typst_file_from_a_yaml_string(input_file_path): + yaml_string = input_file_path.read_text() + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".typst")) + errors = rendercv.create_a_typst_file_from_a_yaml_string( + yaml_string, output_file_path + ) + assert errors is None + assert output_file_path.exists() + + +def test_create_a_typst_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary, +): + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".typst")) + errors = rendercv.create_a_typst_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary, output_file_path + ) + assert errors is None + assert output_file_path.exists() + + +def test_create_contents_of_a_markdown_file_from_a_yaml_string(input_file_path): + yaml_string = input_file_path.read_text() + result = rendercv.create_contents_of_a_markdown_file_from_a_yaml_string(yaml_string) + assert isinstance(result, str) + + +def test_create_contents_of_a_markdown_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary, +): + result = rendercv.create_contents_of_a_markdown_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary + ) + assert isinstance(result, str) + + +def test_create_a_markdown_file_from_a_yaml_string(input_file_path): + yaml_string = input_file_path.read_text() + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".md")) + errors = rendercv.create_a_markdown_file_from_a_yaml_string( + yaml_string, output_file_path + ) + assert errors is None + assert output_file_path.exists() + + +def test_create_a_markdown_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary, +): + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".md")) + errors = rendercv.create_a_markdown_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary, output_file_path + ) + assert errors is None + assert output_file_path.exists() + + +def test_create_an_html_file_from_a_yaml_string(input_file_path): + yaml_string = input_file_path.read_text() + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".html")) + errors = rendercv.create_an_html_file_from_a_yaml_string( + yaml_string, output_file_path + ) + assert errors is None + assert output_file_path.exists() + + +def test_create_an_html_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary, +): + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".html")) + errors = rendercv.create_an_html_file_from_a_python_dictionary( + rendercv_data_as_python_dictionary, output_file_path + ) + assert errors is None + assert output_file_path.exists() + + +def test_create_a_pdf_from_a_yaml_string(input_file_path): + yaml_string = input_file_path.read_text() + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".pdf")) + errors = rendercv.create_a_pdf_from_a_yaml_string(yaml_string, output_file_path) + assert errors is None + assert output_file_path.exists() + + +def test_create_a_pdf_from_a_python_dictionary(rendercv_data_as_python_dictionary): + output_file_path = pathlib.Path(tempfile.mktemp(suffix=".pdf")) + errors = rendercv.create_a_pdf_from_a_python_dictionary( + rendercv_data_as_python_dictionary, output_file_path + ) + assert errors is None + assert output_file_path.exists() + + +def test_read_a_python_dictionary_and_return_a_data_model( + rendercv_data_as_python_dictionary, +): + result = rendercv.read_a_python_dictionary_and_return_a_data_model( + rendercv_data_as_python_dictionary + ) + assert isinstance(result, rendercv.data.RenderCVDataModel) + + +def test_read_a_yaml_string_and_return_a_data_model(input_file_path): + yaml_string = input_file_path.read_text() + result = rendercv.read_a_yaml_string_and_return_a_data_model(yaml_string) + assert isinstance(result, rendercv.data.RenderCVDataModel) diff --git a/tests/test_data.py b/tests/test_data.py index 9e9d20aa..887e41ea 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -895,81 +895,93 @@ def test_make_keywords_bold_in_a_string(): def test_bold_keywords(): - data_model = data.RenderCVDataModel( - cv=data.CurriculumVitae( - name="John Doe", - sections={ - "test": [ - "test_keyword_1", - ], + data_model_as_dict = { + "cv": { + "sections": { + "test": ["test_keyword_1"], "test2": [ - data.EducationEntry( - institution="Test Institution", - area="Test Area", - highlights=["test_keyword_2"], - summary="test_keyword_3 test_keyword_4", - ), + { + "institution": "Test Institution", + "area": "Test Area", + "degree": None, + "date": None, + "start_date": None, + "end_date": None, + "location": None, + "summary": "test_keyword_3 test_keyword_4", + "highlights": ["test_keyword_2"], + } ], "test3": [ - data.ExperienceEntry( - company="Test Company", - position="Test Position", - highlights=["test_keyword_5", "test_keyword_6"], - summary="test_keyword_6 test_keyword_7", - ), + { + "company": "Test Company", + "position": "Test Position", + "date": None, + "start_date": None, + "end_date": None, + "location": None, + "summary": "test_keyword_6 test_keyword_7", + "highlights": ["test_keyword_5", "test_keyword_6"], + } ], "test4": [ - data.NormalEntry( - name="Test", - highlights=["test_keyword_2"], - summary="test_keyword_3 test_keyword_4", - ), - ], - "test5": [ - data.PublicationEntry( - title="Test Institution", - authors=["Test Author"], - ), - ], - "test6": [ - data.BulletEntry( - bullet="test_keyword_3 test_keyword_4", - ), + { + "name": "Test", + "date": None, + "start_date": None, + "end_date": None, + "location": None, + "summary": "test_keyword_3 test_keyword_4", + "highlights": ["test_keyword_2"], + } ], + "test6": [{"bullet": "test_keyword_3 test_keyword_4"}], "test7": [ - data.OneLineEntry( - label="Test Institution", - details="test_keyword_3 test_keyword_4", - ), + { + "label": "Test Institution", + "details": "test_keyword_3 test_keyword_4", + } ], }, - ) + }, + "rendercv_settings": { + "bold_keywords": [ + "test_keyword_1", + "test_keyword_2", + "test_keyword_3", + "test_keyword_4", + "test_keyword_5", + "test_keyword_6", + "test_keyword_7", + ], + }, + } + + data_model = data.validate_input_dictionary_and_return_the_data_model( + data_model_as_dict ) for section in data_model.cv.sections: for entry in section.entries: - if section.title == "test": + if section.title == "Test": assert "**test_keyword_1**" in entry - elif section.title == "test2": + elif section.title == "Test2": assert "**test_keyword_2**" in entry.highlights[0] assert "**test_keyword_3**" in entry.summary assert "**test_keyword_4**" in entry.summary - elif section.title == "test3": + elif section.title == "Test3": assert "**test_keyword_5**" in entry.highlights[0] assert "**test_keyword_6**" in entry.highlights[1] assert "**test_keyword_6**" in entry.summary assert "**test_keyword_7**" in entry.summary - elif section.title == "test4": + elif section.title == "Test4": assert "**test_keyword_2**" in entry.highlights[0] assert "**test_keyword_3**" in entry.summary assert "**test_keyword_4**" in entry.summary - elif section.title == "test5": - assert "**test_keyword_3**" in entry.summary - assert "**test_keyword_4**" in entry.summary - elif section.title == "test6": + elif section.title == "Test6": assert "**test_keyword_3**" in entry.bullet assert "**test_keyword_4**" in entry.bullet - elif section.title == "test7": + elif section.title == "Test7": assert "**test_keyword_3**" in entry.details assert "**test_keyword_4**" in entry.details