2 from types import CodeType as Code
6 from ctypes import pythonapi, POINTER, c_long, cast
10 inspect_flag = cast(pythonapi.Py_InspectFlag, POINTER(c_long)).contents
12 def set_inspect_flag(value):
13 inspect_flag.value = int(value)
16 def update_code(codeobj, **kwargs):
17 fields = ["argcount", "kwonlyargcount", "nlocals", "stacksize", "flags",
18 "code", "consts", "names", "varnames", "filename", "name",
19 "firstlineno", "lnotab", "freevars", "cellvars"]
23 value = kwargs.get(field, None)
25 yield getattr(codeobj, "co_{}".format(field))
29 return Code(*field_values())
31 def update_code_recursively(codeobj, **kwargs):
34 def update(codeobj, **kwargs):
35 result = updated.get(codeobj, None)
36 if result is not None:
39 if any(isinstance(c, Code) for c in codeobj.co_consts):
40 consts = tuple(update(c, **kwargs) if isinstance(c, Code) else c
41 for c in codeobj.co_consts)
43 consts = codeobj.co_consts
45 result = update_code(codeobj, consts=consts, **kwargs)
46 updated[codeobj] = result
49 return update(codeobj, **kwargs)
53 with tokenize.open(path) as f: # opens with detected source encoding
57 code = compile(source, path, "exec")
58 except UnicodeEncodeError:
59 code = compile(source, "<encoding error>", "exec")
60 code = update_code_recursively(code, filename=path)
61 # so code constains correct filename (even if it contains Unicode)
62 # and tracebacks show contents of code lines
67 # to reload __main__ properly
69 def __init__(self, path):
72 def load_module(self, name):
73 code = get_code(self.path)
74 exec(code, __main__.__dict__)
78 sys.argv.pop(0) # so sys.argv looks correct from script being run
80 __main__.__file__ = path
81 __main__.__loader__ = MainLoader(path)
86 except Exception as e:
87 traceback.print_exception(e.__class__, e, e.__traceback__.tb_next.tb_next, chain=False)
90 exec(code, __main__.__dict__)
91 except BaseException as e:
92 if not sys.flags.inspect and isinstance(e, SystemExit):
95 traceback.print_exception(e.__class__, e, e.__traceback__.tb_next)