Original post here. I've taken @ThomasWard's advice, and also added a couple other things.
#!/usr/bin/env python
import tokenize
import sys
import json
def handle_token(type_, token, (srow, scol), (erow, ecol), line):
# Return the info about the tokens, if it's a NAME token then replace it
if tokenize.tok_name[type_] == "NAME":
token = token_names.get(token, token)
return type_, token, (srow, scol), (erow, ecol), line
def run(assignments="assignments.txt", open_from="peoples.txt", \
to_write=True, to_exec=True):
'''
- `assignments` is the file to open the list of names from
- `open_from` is the file to get the input code from
- `to_write` is for toggling writing the compiled code to a file
- `to_exec` is for toggling executing the code
Both `to_write` and `to_exec` are for using this code in another
file by way of importing it.
'''
with open(assignments, "r") as f:
# Read the replacements into token_names
global token_names
token_names = json.load(f)
with open(open_from) as source:
# Get the tokenized version of the input, replace it, and untokenize into pretty output
tokens = tokenize.generate_tokens(source.readline)
handled_tokens = (handle_token(*token) for token in tokens)
output = tokenize.untokenize(handled_tokens)
if to_write:
with open(open_from[:-4]+"-output.txt", 'w') as outfile:
# Write to the output file
outfile.write(output)
if to_exec:
exec output in globals(), locals()
return output
if __name__ == "__main__":
token_names = None
try:
if len(sys.argv) > 1:
if len(sys.argv) > 2:
run(assignments=sys.argv[1], open_from=sys.argv[2])
else:
run(assignments=sys.argv[1])
else:
run()
except Exception as e:
print "An exception has occurred:\n%s" % str(e)
The contents of assignments.txt:
{"Martin":"False",
"Geobits":"None",
"Dennis":"True",
"adnan":"and",
"rainbolt":"as",
"buttner":"assert",
"flawr":"break",
"aditsu":"class",
"katenkyo":"continue",
"quill":"def",
"nathan":"del",
"hobbies":"elif",
"helkahomba":"else",
"irk":"except",
"ender":"finally",
"peter":"for",
"conor":"from",
"gnibbler":"global",
"calvins":"if",
"obrien":"import",
"taylor":"in",
"fryamtheeggman":"is",
"starman":"lambda",
"sp3000":"nonlocal",
"phinotpi":"not",
"xnor":"or",
"maltysen":"pass",
"mego":"raise",
"alex":"return",
"easterly":"try",
"molarmanful":"while",
"minxomat":"with",
"optimizer":"yield",
"wheat":"__import__",
"mbomb007":"abs",
"digital":"all",
"trauma":"any",
"asciionly":"ascii",
"zyabin":"bin",
"bkul":"bool",
"chris":"chr",
"jesteryoung":"classmethod",
"honnza":"complex",
"elendia":"enumerate",
"gcampbell":"eval",
"businesscat":"exec",
"poke":"dir",
"votetoclose":"delattr",
"fatalize":"filter",
"ataco":"float",
"luke":"frozenset",
"betseg":"hasattr",
"sandbox":"help",
"christopherpeart":"hex",
"zgarb":"id",
"phase":"input",
"loovjo":"int",
"minibits":"issubclass",
"lynn":"len",
"laikoni":"list",
"doorknob":"map",
"upgoat":"max",
"briantompsett":"memoryview",
"downgoat":"min",
"jimmy23013":"open",
"destructiblewatermelon":"ord",
"jan":"oct",
"ninjabearmonkey":"pow",
"you":"print",
"productions":"property",
"djmcmayhem":"range",
"erik":"repr",
"qwerpderp":"round",
"legionmammal978":"set",
"lliwtelracs":"slice",
"orlp":"sorted",
"timmyd":"staticmethod",
"eth":"str",
"muddyfish":"sum",
"balint":"super",
"trichoplax":"tuple",
"quartata":"zip",
"pavel":"sys"}
And for a test case (store in peoples.txt):
peter i taylor djmcmayhem(10):
you(i)
Should result in:
for i in range(10):
print(i)
Info and how to run:
What does the code do? It takes in an input file (by default
peoples.txtin the same dir asmain.py) and translates it from "People's Python" to standard python, and executes the result. It also writes the compiled "normal" code into<input_file_name>-output.txt, by defaultpeoples-output.txtRun as
python main.py custom/assignments.txt path/to/inputfile.txt(inputfile.txtis the People's Python code andassignments.txtis the dict of assignments you're using)
To easily test this, put main.py (the first code block), assignments.txt (the big JSON/dict), and the test case (peoples.txt) all in the same directory, and run python main.py.
The main things I'm concerned about are the exec calls and the system arguments. In addition to general best practices, how can I clean up those particular parts?