馃悕馃悕馃悕
at dev 55 lines 1.7 kB view raw
1import dis 2 3class Errs(type): 4 def __iter__(_class): 5 return iter((k,v) for (k,v) in vars(_class).items() if not k.startswith("_")) 6 7 def __repr__(_class): 8 return str(list(k for (k,v) in _class)) 9 10def errs(errs): 11 def _errs(fn): 12 fn.errs = errs 13 return fn 14 return _errs 15 16# stuff above this line i probs move to another file 17 18class _Errs(metaclass=Errs): 19 FOUND_RETURN = "encountered return instruction" 20 IN_DEFINITION = "error in fn definition" 21 IN_EXECUTION = "error in fn execution" 22 NON_DICT_RETURN = "fn dumped a non-dict" 23 24def _modify_to_dump_locals(fn, fn_source, deftime_globals, log): 25 instructions = dis.get_instructions(fn) 26 for instruction in instructions: 27 if instruction.opcode == dis.opmap["RETURN_VALUE"]: 28 return (False, _Errs.FOUND_RETURN) 29 fn_source = fn_source 30 fn_source_modified = f"{fn_source}\n return locals()" 31 sandbox = {} 32 try: 33 exec(fn_source_modified, globals=deftime_globals, locals=sandbox) 34 except KeyboardInterrupt: 35 raise 36 except: 37 log.indented().trace(source=fn) 38 return (False, _Errs.IN_DEFINITION) 39 return (True, sandbox[fn.__name__]) 40 41@errs(_Errs) 42def try_dump_locals(fn, fn_source, args, kwargs, deftime_globals, log): 43 (success, fn_or_err) = _modify_to_dump_locals(fn, fn_source, deftime_globals, log) 44 if not success: 45 return (False, fn_or_err) 46 try: 47 res = fn_or_err(*args, **kwargs) 48 except KeyboardInterrupt: 49 raise 50 except: 51 log.indented().trace(source=fn) 52 return (False, _Errs.IN_EXECUTION) 53 if not isinstance(res, dict): 54 return (False, _Errs.NON_DICT_RETURN) 55 return (True, res)