-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgenerate_files.py
162 lines (121 loc) · 4.36 KB
/
generate_files.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# ---HOW TO---
# Create one function per file you want to generate. The file will have the same name as the function.
# Each function should compute and return the content of the corresponding file as a string.
# Then call `generate`:
# ```python
# def some_function_that_will_generate_a_file():
# return "The content of the file"
#
# def another_function():
# return "Another file"
#
# generate(
# folder="generated", # The name of the output folder where the files will be generated. /!\ Don't put anything manually in that folder, it is erased and regenerated each time you call `generate()`.
# files=[
# some_function_that_will_generate_a_file,
# another_function,
# ]
# )
# ```
# ------------
def SUFFIX():
return "___TEMP"
def clear_generated_folder(files, directory):
import os
for file in os.listdir(directory):
path = os.path.join(directory, file)
if os.path.isfile(path):
if not file[:-4] in map(lambda file: file.__name__, files):
os.remove(path)
def output_folder(path_relative_to_project_root):
import os
import sys
from pathlib import Path
root_folder = Path(sys.argv[0]).parent
return os.path.join(root_folder, path_relative_to_project_root)
def generate_one(function, folder, calling_file):
generate_file(
f"{function.__name__}{SUFFIX()}",
f"{function.__name__}",
function(),
folder,
calling_file,
)
def file_path(name, folder):
import os
return os.path.join(folder, name) + ".inl"
def create_folder_ifn(path):
import os
try:
os.makedirs(path)
except FileExistsError:
pass
def create_file_ifn(path):
try:
with open(path, "x"):
pass
except FileExistsError:
pass
def generate_file(name, name_without_suffix, content, folder, calling_file):
path = file_path(name, folder)
create_file_ifn(path)
with open(path, "w") as f:
f.write(heading(name_without_suffix, calling_file) + content)
def heading(function_name, calling_file):
import os
import sys
path_to_generator = os.path.basename(calling_file if calling_file else sys.argv[0])
return f"""/* -----------------------------------------------------------------------------
* This file was automatically generated by a Python script.
* PLEASE DON'T EDIT IT DIRECTLY, your changes would be overwritten the next time the script is run.
* Instead, go to "{path_to_generator}" and edit the "{function_name}" function there.
* -----------------------------------------------------------------------------
*/
"""
def apply_clang_format_on_generated_files(folder):
from os import path
from pathlib import Path
from importlib.machinery import SourceFileLoader
apply_clang_format = SourceFileLoader(
"apply_clang_format",
path.join(Path(path.abspath(__file__)).parent, "apply_clang_format.py"),
).load_module()
apply_clang_format.apply_clang_format(
folder=folder,
print_result=False,
)
def files_are_equal(file1_path, file2_path):
with open(file1_path, "rb") as file1, open(file2_path, "rb") as file2:
while True:
byte1 = file1.read(1)
byte2 = file2.read(1)
if byte1 != byte2:
return False
if not byte1: # Reached end of file
return True
# Remove the newly created file if it the same as the old one (avoids to overwrite the old one which would force cmake to recompile it).
# Otherwise, replace the old one with the new one.
def cleanup(function, folder):
import os
path = file_path(f"{function.__name__}", folder)
path_temp = file_path(f"{function.__name__}{SUFFIX()}", folder)
if not os.path.exists(path):
os.rename(path_temp, path)
return
if files_are_equal(path, path_temp):
os.remove(path_temp)
else:
os.remove(path)
os.rename(path_temp, path)
def generate(
folder="generated", files=[], should_apply_clang_format=True, calling_file=""
):
folder = output_folder(folder)
create_folder_ifn(folder)
for function in files:
generate_one(function, folder, calling_file)
if should_apply_clang_format:
apply_clang_format_on_generated_files(folder)
for function in files:
cleanup(function, folder)
clear_generated_folder(files, folder)