Coverage for src / rendercv / cli / create_theme_command / create_init_file_for_theme.py: 100%

12 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-25 13:49 +0000

1import pathlib 

2 

3from rendercv.exception import RenderCVUserError 

4from rendercv.schema.models.design.design import custom_theme_name_pattern 

5 

6 

7def create_init_file_for_theme(theme_name: str, init_file_path: pathlib.Path) -> None: 

8 """Generate `__init__.py` for custom theme by templating from ClassicTheme. 

9 

10 Why: 

11 Custom themes need Pydantic models defining design options. Generating 

12 from ClassicTheme provides working example with all standard fields 

13 users can modify or extend. 

14 

15 Args: 

16 theme_name: Snake_case theme identifier. 

17 init_file_path: Destination path for __init__.py. 

18 """ 

19 if not custom_theme_name_pattern.match(theme_name): 

20 message = ( 

21 "The custom theme name should only contain lowercase letters and digits." 

22 f" The provided value is `{theme_name}`." 

23 ) 

24 raise RenderCVUserError(message) 

25 

26 classic_theme_file = ( 

27 pathlib.Path(__file__).parent.parent.parent 

28 / "schema" 

29 / "models" 

30 / "design" 

31 / "classic_theme.py" 

32 ) 

33 new_init_file_contents = classic_theme_file.read_text(encoding="utf-8") 

34 

35 new_init_file_contents = new_init_file_contents.replace( 

36 "class ClassicTheme(BaseModelWithoutExtraKeys):", 

37 f"class {theme_name.capitalize()}Theme(BaseModelWithoutExtraKeys):", 

38 ) 

39 new_init_file_contents = new_init_file_contents.replace( 

40 'theme: Literal["classic"] = "classic"', 

41 f'theme: Literal["{theme_name}"] = "{theme_name}"', 

42 ) 

43 init_file_path.write_text(new_init_file_contents, encoding="utf-8")