Coverage for rendercv/data/reader.py: 100%

27 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-12-25 23:06 +0000

1""" 

2The `rendercv.data.reader` module contains the functions that are used to read the input 

3file (YAML or JSON) and return them as an instance of `RenderCVDataModel`, which is a 

4Pydantic data model of RenderCV's data format. 

5""" 

6 

7import pathlib 

8from typing import Optional 

9 

10import ruamel.yaml 

11 

12from . import models 

13 

14 

15def read_a_yaml_file(file_path_or_contents: pathlib.Path | str) -> dict: 

16 """Read a YAML file and return its content as a dictionary. The YAML file can be 

17 given as a path to the file or as the contents of the file as a string. 

18 

19 Args: 

20 file_path_or_contents: The path to the YAML file or the contents of the YAML 

21 file as a string. 

22 

23 Returns: 

24 The content of the YAML file as a dictionary. 

25 """ 

26 if isinstance(file_path_or_contents, pathlib.Path): 

27 # Check if the file exists: 

28 if not file_path_or_contents.exists(): 

29 message = f"The input file {file_path_or_contents} doesn't exist!" 

30 raise FileNotFoundError(message) 

31 

32 # Check the file extension: 

33 accepted_extensions = [".yaml", ".yml", ".json", ".json5"] 

34 if file_path_or_contents.suffix not in accepted_extensions: 

35 user_friendly_accepted_extensions = [ 

36 f"[green]{ext}[/green]" for ext in accepted_extensions 

37 ] 

38 user_friendly_accepted_extensions = ", ".join( 

39 user_friendly_accepted_extensions 

40 ) 

41 message = ( 

42 "The input file should have one of the following extensions:" 

43 f" {user_friendly_accepted_extensions}. The input file is" 

44 f" {file_path_or_contents}." 

45 ) 

46 raise ValueError(message) 

47 

48 file_content = file_path_or_contents.read_text(encoding="utf-8") 

49 else: 

50 file_content = file_path_or_contents 

51 

52 yaml_as_a_dictionary: dict = ruamel.yaml.YAML().load(file_content) 

53 

54 if yaml_as_a_dictionary is None: 

55 message = "The input file is empty!" 

56 raise ValueError(message) 

57 

58 return yaml_as_a_dictionary 

59 

60 

61def validate_input_dictionary_and_return_the_data_model( 

62 input_dictionary: dict, 

63 context: Optional[dict] = None, 

64) -> models.RenderCVDataModel: 

65 """Validate the input dictionary by creating an instance of `RenderCVDataModel`, 

66 which is a Pydantic data model of RenderCV's data format. 

67 

68 Args: 

69 input_dictionary: The input dictionary. 

70 context: The context dictionary that is used to validate the input dictionary. 

71 It's used to send the input file path with the context object, but it's not 

72 required. 

73 

74 Returns: 

75 The data model. 

76 """ 

77 # Validate the parsed dictionary by creating an instance of RenderCVDataModel: 

78 return models.RenderCVDataModel.model_validate(input_dictionary, context=context) 

79 

80 

81def read_input_file( 

82 file_path_or_contents: pathlib.Path | str, 

83) -> models.RenderCVDataModel: 

84 """Read the input file (YAML or JSON) and return them as an instance of 

85 `RenderCVDataModel`, which is a Pydantic data model of RenderCV's data format. 

86 

87 Args: 

88 file_path_or_contents: The path to the input file or the contents of the input 

89 file as a string. 

90 

91 Returns: 

92 The data model. 

93 """ 

94 input_as_dictionary = read_a_yaml_file(file_path_or_contents) 

95 

96 return validate_input_dictionary_and_return_the_data_model(input_as_dictionary)