Coverage for class_generator/scripts/tools.py: 20%

71 statements  

« prev     ^ index     » next       coverage.py v7.10.1, created at 2025-07-28 22:01 +0300

1import ast 

2import os 

3from concurrent.futures import Future, ThreadPoolExecutor, as_completed 

4 

5import click 

6 

7from class_generator.class_generator import class_generator 

8 

9 

10def get_generated_files() -> dict[str, dict[str, str]]: 

11 """ 

12 This function returns a dictionary containing three keys: 

13 - `with_end_comment`: A dictionary containing the kind of resources that have the end comment in their file. 

14 - `without_end_comment`: A dictionary containing the kind of resources that don't have the end comment in their file. 

15 - `not_generated`: A dictionary containing the kind of resources that are not generated by `class_generator`. 

16 """ 

17 start_comment: str = ( 

18 "# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/scripts/resource/README.md" 

19 ) 

20 end_comment: str = "# End of generated code" 

21 resources_with_end_comment: dict[str, str] = {} 

22 resources_without_end_comment: dict[str, str] = {} 

23 resources_not_generated: dict[str, str] = {} 

24 exclude_files: list[str] = ["resource.py", "__init__.py", "__pycache__"] 

25 for root, _, files in os.walk("ocp_resources"): 

26 for _file in files: 

27 _kind: str = "" 

28 

29 if _file in exclude_files: 

30 continue 

31 

32 if _file.endswith(".py"): 

33 file_path = os.path.join(root, _file) 

34 with open(file_path) as fd: 

35 content = fd.read() 

36 tree = ast.parse(content) 

37 for _cls in (node for node in tree.body if isinstance(node, ast.ClassDef)): 

38 bases = [_base.id for _base in _cls.bases if isinstance(_base, ast.Name)] 

39 if "Resource" in bases or "NamespacedResource" in bases: 

40 _kind = _cls.name 

41 

42 if not _kind: 

43 click.echo(f"Can't find kind in file {file_path}") 

44 continue 

45 

46 if start_comment in content and end_comment in content: 

47 resources_with_end_comment[_kind] = file_path 

48 

49 elif start_comment in content: 

50 resources_without_end_comment[_kind] = file_path 

51 

52 else: 

53 resources_not_generated[_kind] = file_path 

54 

55 return { 

56 "with_end_comment": resources_with_end_comment, 

57 "without_end_comment": resources_without_end_comment, 

58 "not_generated": resources_not_generated, 

59 } 

60 

61 

62def generate_resource(kinds: list[str], yes: bool) -> None: 

63 for _kind in kinds: 

64 _generate = "y" if yes else click.prompt(f"Do you want to generate {_kind} resource? (y/n) ") 

65 

66 if _generate.lower() == "y": 

67 try: 

68 class_generator(kind=_kind, called_from_cli=False) 

69 except Exception: 

70 continue 

71 

72 

73@click.command("class-generator tools") 

74@click.option( 

75 "--list-generated_file", 

76 is_flag=True, 

77 help="list all generated files by `class_generator` under `ocp_resources` directory", 

78) 

79@click.option("--yes", is_flag=True, help="Answer yes to all prompts") 

80@click.option( 

81 "--generated-missing-end-comment", 

82 is_flag=True, 

83 help="Generate missing end comment for all resources under `ocp_resources` directory", 

84) 

85@click.option("--regenerate-generated-files", is_flag=True, help="Regenerate all generated files") 

86def main( 

87 list_generated_file: bool, generated_missing_end_comment: bool, yes: bool, regenerate_generated_files: bool 

88) -> None: 

89 res = get_generated_files() 

90 

91 if regenerate_generated_files: 

92 click.echo("Regenerating files...") 

93 futures: list[Future] = [] 

94 

95 with ThreadPoolExecutor() as executor: 

96 for kind in res["with_end_comment"].keys(): 

97 futures.append(executor.submit(class_generator, kind=kind, called_from_cli=False, overwrite=True)) 

98 

99 for _ in as_completed(futures): 

100 ... 

101 

102 if generated_missing_end_comment: 

103 generate_resource(kinds=list(res["without_end_comment"].keys()), yes=yes) 

104 

105 if list_generated_file: 

106 click.echo("\nResources generated - valid:") 

107 for k, v in res["with_end_comment"].items(): 

108 click.echo(f"\t{k}: {v}") 

109 

110 click.echo("\nResources generated - missing end comment:") 

111 for k, v in res["without_end_comment"].items(): 

112 click.echo(f"\t{k}: {v}") 

113 

114 click.echo("\nResources not generated:") 

115 for k, v in res["not_generated"].items(): 

116 click.echo(f"\t{k}: {v}") 

117 

118 

119if __name__ == "__main__": 

120 main()