updated wikipedia project to fix windows encoding issue
[wikipedia-api-cdsw] / win_unicode_console / runner.py
diff --git a/win_unicode_console/runner.py b/win_unicode_console/runner.py
new file mode 100644 (file)
index 0000000..4b22904
--- /dev/null
@@ -0,0 +1,96 @@
+
+from types import CodeType as Code
+import sys
+import traceback
+import __main__
+from ctypes import pythonapi, POINTER, c_long, cast
+import tokenize
+
+
+inspect_flag = cast(pythonapi.Py_InspectFlag, POINTER(c_long)).contents
+
+def set_inspect_flag(value):
+       inspect_flag.value = int(value)
+
+
+def update_code(codeobj, **kwargs):
+       fields = ["argcount", "kwonlyargcount", "nlocals", "stacksize", "flags",
+               "code", "consts", "names", "varnames", "filename", "name",
+               "firstlineno", "lnotab", "freevars", "cellvars"]
+       
+       def field_values():
+               for field in fields:
+                       value = kwargs.get(field, None)
+                       if value is None:
+                               yield getattr(codeobj, "co_{}".format(field))
+                       else:
+                               yield value
+       
+       return Code(*field_values())
+
+def update_code_recursively(codeobj, **kwargs):
+       updated = {}
+       
+       def update(codeobj, **kwargs):
+               result = updated.get(codeobj, None)
+               if result is not None:
+                       return result
+               
+               if any(isinstance(c, Code) for c in codeobj.co_consts):
+                       consts = tuple(update(c, **kwargs) if isinstance(c, Code) else c
+                               for c in codeobj.co_consts)
+               else:
+                       consts = codeobj.co_consts
+               
+               result = update_code(codeobj, consts=consts, **kwargs)
+               updated[codeobj] = result
+               return result
+       
+       return update(codeobj, **kwargs)
+
+
+def get_code(path):
+       with tokenize.open(path) as f:  # opens with detected source encoding
+               source = f.read()
+       
+       try:
+               code = compile(source, path, "exec")
+       except UnicodeEncodeError:
+               code = compile(source, "<encoding error>", "exec")
+               code = update_code_recursively(code, filename=path)
+                       # so code constains correct filename (even if it contains Unicode)
+                       # and tracebacks show contents of code lines
+       
+       return code
+
+class MainLoader:
+       # to reload __main__ properly
+       
+       def __init__(self, path):
+               self.path = path
+       
+       def load_module(self, name):
+               code = get_code(self.path)
+               exec(code, __main__.__dict__)
+               return __main__
+               
+def run_script():
+       sys.argv.pop(0) # so sys.argv looks correct from script being run
+       path = sys.argv[0]
+       __main__.__file__ = path
+       __main__.__loader__ = MainLoader(path)
+       
+       
+       try:
+               code = get_code(path)
+       except Exception as e:
+               traceback.print_exception(e.__class__, e, e.__traceback__.tb_next.tb_next, chain=False)
+       else:
+               try:
+                       exec(code, __main__.__dict__)
+               except BaseException as e:
+                       if not sys.flags.inspect and isinstance(e, SystemExit):
+                               raise
+                       else:
+                               traceback.print_exception(e.__class__, e, e.__traceback__.tb_next)
+

Benjamin Mako Hill || Want to submit a patch?