Coverage for rendercv/data/models/rendercv_settings.py: 100%

42 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-26 00:25 +0000

1""" 

2The `rendercv.models.rendercv_settings` module contains the data model of the 

3`rendercv_settings` field of the input file. 

4""" 

5 

6import datetime 

7import pathlib 

8from typing import Optional 

9 

10import pydantic 

11 

12from .base import RenderCVBaseModelWithoutExtraKeys 

13from .computers import convert_string_to_path, replace_placeholders 

14 

15file_path_placeholder_description = ( 

16 "The following placeholders can be used:\n- FULL_MONTH_NAME: Full name of the" 

17 " month\n- MONTH_ABBREVIATION: Abbreviation of the month\n- MONTH: Month as a" 

18 " number\n- MONTH_IN_TWO_DIGITS: Month as a number in two digits\n- YEAR: Year as a" 

19 " number\n- YEAR_IN_TWO_DIGITS: Year as a number in two digits\n- NAME: The name of" 

20 " the CV owner\n- NAME_IN_SNAKE_CASE: The name of the CV owner in snake case\n-" 

21 " NAME_IN_LOWER_SNAKE_CASE: The name of the CV owner in lower snake case\n-" 

22 " NAME_IN_UPPER_SNAKE_CASE: The name of the CV owner in upper snake case\n-" 

23 " NAME_IN_KEBAB_CASE: The name of the CV owner in kebab case\n-" 

24 " NAME_IN_LOWER_KEBAB_CASE: The name of the CV owner in lower kebab case\n-" 

25 " NAME_IN_UPPER_KEBAB_CASE: The name of the CV owner in upper kebab case\n-" 

26 " FULL_MONTH_NAME: Full name of the month\n- MONTH_ABBREVIATION: Abbreviation of" 

27 " the month\n- MONTH: Month as a number\n- MONTH_IN_TWO_DIGITS: Month as a number" 

28 " in two digits\n- YEAR: Year as a number\n- YEAR_IN_TWO_DIGITS: Year as a number" 

29 ' in two digits\nThe default value is "MONTH_ABBREVIATION YEAR".\nThe default value' 

30 " is null." 

31) 

32 

33file_path_placeholder_description_without_default = ( 

34 file_path_placeholder_description.replace("\nThe default value is null.", "") 

35) 

36 

37DATE_INPUT = datetime.date.today() 

38 

39 

40class RenderCommandSettings(RenderCVBaseModelWithoutExtraKeys): 

41 """This class is the data model of the `render` command's settings.""" 

42 

43 design: Optional[pathlib.Path] = pydantic.Field( 

44 default=None, 

45 title="`design` Field's YAML File", 

46 description=( 

47 "The file path to the yaml file containing the `design` field separately." 

48 ), 

49 ) 

50 

51 rendercv_settings: Optional[pathlib.Path] = pydantic.Field( 

52 default=None, 

53 title="`rendercv_settings` Field's YAML File", 

54 description=( 

55 "The file path to the yaml file containing the `rendercv_settings` field" 

56 " separately." 

57 ), 

58 ) 

59 

60 locale: Optional[pathlib.Path] = pydantic.Field( 

61 default=None, 

62 title="`locale` Field's YAML File", 

63 description=( 

64 "The file path to the yaml file containing the `locale` field separately." 

65 ), 

66 ) 

67 

68 output_folder_name: str = pydantic.Field( 

69 default="rendercv_output", 

70 title="Output Folder Name", 

71 description=( 

72 "The name of the folder where the output files will be saved." 

73 f" {file_path_placeholder_description_without_default}\nThe default value" 

74 ' is "rendercv_output".' 

75 ), 

76 ) 

77 

78 pdf_path: Optional[pathlib.Path] = pydantic.Field( 

79 default=None, 

80 title="PDF Path", 

81 description=( 

82 "The path to copy the PDF file to. If it is not provided, the PDF file will" 

83 f" not be copied. {file_path_placeholder_description}" 

84 ), 

85 ) 

86 

87 typst_path: Optional[pathlib.Path] = pydantic.Field( 

88 default=None, 

89 title="Typst Path", 

90 description=( 

91 "The path to copy the Typst file to. If it is not provided, the Typst file" 

92 f" will not be copied. {file_path_placeholder_description}" 

93 ), 

94 ) 

95 

96 html_path: Optional[pathlib.Path] = pydantic.Field( 

97 default=None, 

98 title="HTML Path", 

99 description=( 

100 "The path to copy the HTML file to. If it is not provided, the HTML file" 

101 f" will not be copied. {file_path_placeholder_description}" 

102 ), 

103 ) 

104 

105 png_path: Optional[pathlib.Path] = pydantic.Field( 

106 default=None, 

107 title="PNG Path", 

108 description=( 

109 "The path to copy the PNG file to. If it is not provided, the PNG file will" 

110 f" not be copied. {file_path_placeholder_description}" 

111 ), 

112 ) 

113 

114 markdown_path: Optional[pathlib.Path] = pydantic.Field( 

115 default=None, 

116 title="Markdown Path", 

117 description=( 

118 "The path to copy the Markdown file to. If it is not provided, the Markdown" 

119 f" file will not be copied. {file_path_placeholder_description}" 

120 ), 

121 ) 

122 

123 dont_generate_html: bool = pydantic.Field( 

124 default=False, 

125 title="Don't Generate HTML", 

126 description=( 

127 "A boolean value to determine whether the HTML file will be generated. The" 

128 " default value is False." 

129 ), 

130 ) 

131 

132 dont_generate_markdown: bool = pydantic.Field( 

133 default=False, 

134 title="Don't Generate Markdown", 

135 description=( 

136 "A boolean value to determine whether the Markdown file will be generated." 

137 ' The default value is "false".' 

138 ), 

139 ) 

140 

141 dont_generate_png: bool = pydantic.Field( 

142 default=False, 

143 title="Don't Generate PNG", 

144 description=( 

145 "A boolean value to determine whether the PNG file will be generated. The" 

146 " default value is False." 

147 ), 

148 ) 

149 

150 watch: bool = pydantic.Field( 

151 default=False, 

152 title="Re-run RenderCV When the Input File is Updated", 

153 description=( 

154 "A boolean value to determine whether to re-run RenderCV when the input" 

155 'file is updated. The default value is "false".' 

156 ), 

157 ) 

158 

159 @pydantic.field_validator( 

160 "output_folder_name", 

161 mode="before", 

162 ) 

163 @classmethod 

164 def replace_placeholders(cls, value: str) -> str: 

165 """Replaces the placeholders in a string with the corresponding values.""" 

166 return replace_placeholders(value) 

167 

168 @pydantic.field_validator( 

169 "design", 

170 "locale", 

171 "rendercv_settings", 

172 "pdf_path", 

173 "typst_path", 

174 "html_path", 

175 "png_path", 

176 "markdown_path", 

177 mode="before", 

178 ) 

179 @classmethod 

180 def convert_string_to_path(cls, value: Optional[str]) -> Optional[pathlib.Path]: 

181 """Converts a string to a `pathlib.Path` object by replacing the placeholders 

182 with the corresponding values. If the path is not an absolute path, it is 

183 converted to an absolute path by prepending the current working directory. 

184 """ 

185 if value is None: 

186 return None 

187 

188 return convert_string_to_path(value) 

189 

190 

191class RenderCVSettings(RenderCVBaseModelWithoutExtraKeys): 

192 """This class is the data model of the RenderCV settings.""" 

193 

194 date: datetime.date = pydantic.Field( 

195 default=datetime.date.today(), 

196 title="Date", 

197 description=( 

198 "The date that will be used everywhere (e.g., in the output file names," 

199 " last updated date, computation of time spans for the events that are" 

200 " currently happening, etc.). The default value is the current date." 

201 ), 

202 json_schema_extra={ 

203 "default": None, 

204 }, 

205 ) 

206 render_command: Optional[RenderCommandSettings] = pydantic.Field( 

207 default=None, 

208 title="Render Command Settings", 

209 description=( 

210 "RenderCV's `render` command settings. They are the same as the command" 

211 " line arguments. CLI arguments have higher priority than the settings in" 

212 " the input file." 

213 ), 

214 ) 

215 bold_keywords: list[str] = pydantic.Field( 

216 default=[], 

217 title="Bold Keywords", 

218 description=( 

219 "The keywords that will be bold in the output. The default value is an" 

220 " empty list." 

221 ), 

222 ) 

223 

224 @pydantic.field_validator("date") 

225 @classmethod 

226 def mock_today(cls, value: datetime.date) -> datetime.date: 

227 """Mocks the current date for testing.""" 

228 

229 global DATE_INPUT # NOQA: PLW0603 

230 

231 DATE_INPUT = value 

232 

233 return value