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
« 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
5import click
7from class_generator.class_generator import class_generator
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 = ""
29 if _file in exclude_files:
30 continue
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
42 if not _kind:
43 click.echo(f"Can't find kind in file {file_path}")
44 continue
46 if start_comment in content and end_comment in content:
47 resources_with_end_comment[_kind] = file_path
49 elif start_comment in content:
50 resources_without_end_comment[_kind] = file_path
52 else:
53 resources_not_generated[_kind] = file_path
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 }
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) ")
66 if _generate.lower() == "y":
67 try:
68 class_generator(kind=_kind, called_from_cli=False)
69 except Exception:
70 continue
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()
91 if regenerate_generated_files:
92 click.echo("Regenerating files...")
93 futures: list[Future] = []
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))
99 for _ in as_completed(futures):
100 ...
102 if generated_missing_end_comment:
103 generate_resource(kinds=list(res["without_end_comment"].keys()), yes=yes)
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}")
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}")
114 click.echo("\nResources not generated:")
115 for k, v in res["not_generated"].items():
116 click.echo(f"\t{k}: {v}")
119if __name__ == "__main__":
120 main()