[FIX] script transform python to code writer: improve generated code

- Remove indent when no need
- Generate the same end of file space
- Support beautiful multiple end line
- Add automatic test
- Support """ into string like this " """ "
This commit is contained in:
Mathieu Benoit 2024-07-17 02:03:48 -04:00
parent 24a15c57f5
commit 218e17a16a
2 changed files with 173 additions and 16 deletions

View file

@ -0,0 +1,114 @@
#!./.venv/bin/python
import argparse
import os
import subprocess
import sys
import tempfile
def get_config():
"""Parse command line arguments, extracting the config file name,
returning the union of config file and command line arguments
:return: dict of config file settings and command line arguments
"""
# TODO update description
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\
Transform a python file in code writer format python file, will generate it in temp file and compare difference.
""",
epilog="""\
""",
)
parser.add_argument(
"--debug", action="store_true", help="Show debug information."
)
parser.add_argument(
"--format", action="store_true", help="Format file before test."
)
parser.add_argument(
"-f",
"--file",
dest="file",
required=True,
help="Path of file to transform to code_writer.",
)
args = parser.parse_args()
return args
def main():
config = get_config()
if config.format:
result = subprocess.run(
[
"bash",
"./script/maintenance/format_python.sh",
config.file,
],
capture_output=True,
text=True,
)
with tempfile.NamedTemporaryFile() as temp_file:
# Generate the generator
file = temp_file.name
result = subprocess.run(
[
"python",
"./script/code_generator/transform_python_to_code_writer.py",
"-f",
config.file,
"-o",
file,
],
capture_output=True,
text=True,
)
# if config.debug:
# print("-- show the generator --")
# print(result.stdout)
# print("-- end show the generator --")
# Execute the generator
result_generator = subprocess.run(
["python", file], capture_output=True, text=True
)
if result_generator.returncode != 0:
raise Exception(result_generator.stderr)
if config.debug:
print("-- show the generator result --")
print(result_generator.stdout)
print("-- end show the generator result --")
# Test the generator output
fd, temp_file_path = tempfile.mkstemp()
with os.fdopen(fd, "w+") as temp_file_test:
temp_file_test.write(result_generator.stdout)
temp_file_test.seek(0)
# Compare the output of the generator with original
result = subprocess.run(
["diff", config.file, temp_file_path],
capture_output=True,
text=True,
)
if config.debug or result.stdout:
print("-- show diff --")
print(result.stdout)
print("-- end show diff --")
if result.stdout:
print("FAIL")
result_wc = subprocess.run(
["wc", "-m", config.file], capture_output=True, text=True
)
if result_wc.returncode == 0:
line_count = int(result_wc.stdout.split()[0])
print(f"{line_count} VS {len(result_generator.stdout)}")
else:
print(f"Error with command 'wc -m {config.file}'")
return -1
else:
print("PASS")
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -1,7 +1,6 @@
#!./.venv/bin/python
import argparse
import logging
import os
import uuid
import subprocess
import sys
@ -88,6 +87,7 @@ def main():
cw.emit("from code_writer import CodeWriter")
cw.emit("cw = CodeWriter()")
unique_str = f"#{uuid.uuid4().hex}#"
no_line = 1
with open(config.file, "r") as file:
@ -95,7 +95,13 @@ def main():
nb_tab, nb_space = count_space_tab(line)
diff_tab = nb_tab - last_nb_tab
new_line = line.strip()
# Support \, because with cw.emit("\") this will break
new_line = new_line.replace("\\", "\\\\")
# Support " into string
new_line = new_line.replace('"', '\\"')
# Fix """
new_line = new_line.replace('\\"\\"\\"', unique_str)
status_no_tab = add_line(
cw, new_line, no_line, nb_tab, no_tab, no_tab, nb_space
@ -105,7 +111,16 @@ def main():
last_nb_tab = nb_tab
no_line += 1
cw.emit("print(cw.render())")
argument_print = ""
if line[-1] != "\n":
# Remove last endline if missing
argument_print = ", end=''"
# Ignore last character, it's an empty space
# TODO find another technique to support """, instead of using uuid
cw.emit(
f"print(cw.render()[:-1].replace('{unique_str}',"
f' \'"""\'){argument_print})'
)
output = cw.render()
if config.output:
@ -116,7 +131,14 @@ def main():
def add_line(
cw, line, no_line, nb_indent, no_indent, init_no_intend, nb_space
cw,
line,
no_line,
nb_indent,
no_indent,
init_no_intend,
nb_space,
deindent=False,
):
"""
Recursive check indent and write line
@ -135,22 +157,27 @@ def add_line(
sys.exit(-1)
if nb_indent == -1:
cw.emit('cw.emit("")')
return 0
if no_indent > 0:
cw.emit_raw(" " * no_indent * 4 + f"cw.emit()\n")
return no_indent
else:
cw.emit("cw.emit()")
return 0
elif nb_indent == no_indent:
if nb_indent == 0:
cw.emit(f'cw.emit("{line}")')
return 0
elif nb_indent == 1:
if no_indent != init_no_intend:
if no_indent != init_no_intend and not deindent:
cw.emit(f"with cw.indent({4 + nb_space if nb_space else ''}):")
with cw.indent():
cw.emit(f'cw.emit("{line}")')
elif nb_indent == 2:
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
# TODO support indent with cw.emit_raw
with cw.indent():
if no_indent != init_no_intend:
if no_indent != init_no_intend and not deindent:
cw.emit(
f"with cw.indent({4 + nb_space if nb_space else ''}):"
)
@ -163,7 +190,7 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if no_indent != init_no_intend and not deindent:
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -180,7 +207,7 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if no_indent != init_no_intend and not deindent:
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -200,7 +227,7 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if no_indent != init_no_intend and not deindent:
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -223,7 +250,10 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if (
no_indent != init_no_intend
and not deindent
):
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -249,7 +279,10 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if (
no_indent != init_no_intend
and not deindent
):
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -278,7 +311,10 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if (
no_indent != init_no_intend
and not deindent
):
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -310,7 +346,10 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if (
no_indent != init_no_intend
and not deindent
):
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -345,7 +384,10 @@ def add_line(
if nb_indent - 1 > init_no_intend:
cw.emit(f"with cw.indent():")
with cw.indent():
if no_indent != init_no_intend:
if (
no_indent != init_no_intend
and not deindent
):
cw.emit(
"with"
f" cw.indent({4 + nb_space if nb_space else ''}):"
@ -1137,6 +1179,7 @@ def add_line(
no_indent - 1,
init_no_intend,
nb_space,
deindent=True,
)
else:
# indent