I've implemented the beginnings of a Python preprocesser I plan to implement sometime in the future, and the below code is my simple prototype. At the moment, it only converts until
and unless
statements.
py_preproc.py
"""
A simple Python utility that converts
non-valid Python code, like `until`,
and `unless` blocks to valid Python
code.
"""
from sys import argv
try:
file_path = argv[1]
execute_results = argv[2]
except IndexError:
raise Exception("Two argv arguments are required, file_path, and execute_results.")
def open_code_file():
"""
Opens the code file to do the conversion
on, and returns the read version as a
string.
"""
with open(file_path, "r+") as code_file:
return code_file.read()
def replace_items(file_string):
"""
Replace specific pieces of the code_file
with valid Python code. Currently only
`until`, and `unless` blocks are replaced.
"""
return file_string.replace(
"until", "while not"
).replace(
"unless", "if not"
)
def evaluate_result(result_string):
"""
Evaluates the converted result, after
the code has been converted to valid
Python code.
"""
py_string_compiled = compile(result_string, "fakemodule", "exec")
exec(py_string_compiled)
def main():
file_string = open_code_file()
new_file_string = replace_items(file_string)
if execute_results == "-true":
evaluate_result(new_file_string)
elif execute_results == "-false":
with open(file_path) as file_to_write:
file_to_write.truncate()
file_to_write.write(new_file_string)
else:
raise Exception("Invalid argument \"{argument}\".".format(argument=execute_results))
if __name__ == '__main__':
main()
For reference, here's an example of a code file using until
and unless
, before it's preprocessed.
iterator = 10
until iterator == 0:
print(iterator)
iterator -= 1
unless iterator != 0:
print("iterator == 0")
The above example is then converted to this:
iterator = 10
while not iterator == 0:
print(iterator)
iterator -= 1
if not iterator != 0:
print("iterator == 0")
Finally, here's the command line syntax for running the command, where file_to_execute_or_convert.py
is the Python file that you want to run or convert, and execute_or_write
is -true
if you want to just execute it, or -false
if you want to convert it.
python py_preproc.py [file_to_execute_or_convert.py] [execute_or_write]
while not (iterator == 0)
andif not (iterator == 0)
. Otherwise if the user uses a condition likeunless x and y
it then becomeswhile not x and y
which is equivalent towhile (not x) and y
. But then you can't simply usereplace
anymore... \$\endgroup\$"until"
inside a string literal, and the code itself was an example of that. That it is reserved doesn't matter either, because this script will also change the variable namerun_until_completed
intorun_while not_completed
. And what Bakuriu said. \$\endgroup\$