1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
| import dill from contextlib import suppress import traceback def skipException(func, debug_flag=False, breakpoint_flag=False): def space_counter(line): counter = 0 for x in line: if x == " ": counter+=1 else: break return counter def remove_extra_return(code): while True: if "\n\n" in code: code = code.replace("\n\n","\n") else: break return code def isEmptyLine(line): emptyChars = ["\n","\t","\r"," "] length = len(line) emptyCounts=0 for char in line: if char in emptyChars: emptyCounts += 1 return emptyCounts == length def getCodeBlocks(lines): mBlocks=[] current_block = lines[0] lines = lines+[""] keywords = [" ", "def", "async def", "with", "class", "@"] for line in lines[1:]: if sum([line.startswith(keyword) for keyword in keywords]): current_block+="\n" current_block+=line else: mBlocks.append(current_block) current_block = line return mBlocks def getExtendedLines(splited_code): splited_code = [x.rstrip() for x in splited_code] splited_code = "\n".join(splited_code).replace("\\\n","") splited_code = remove_extra_return(splited_code) splited_code = splited_code.split("\n") return splited_code def new_func(*args, **kwargs): func_name = func.__name__ func_code = dill.source.getsource(func) if debug_flag: print("########## FUNCTION CODE #########") print(func_code) print("########## FUNCTION CODE #########") print("########## FUNCTION #########")
func_code = remove_extra_return(func_code) splited_code = func_code.split("\n") splited_code = getExtendedLines(splited_code)
try: assert splited_code[0].strip().startswith("@skipException") except: raise Exception("Do not nesting the use of @skipException decorator") function_definition = splited_code[1] function_args=function_definition[:-1].replace("def {}".format(func_name),"") if debug_flag: print("FUNCTION ARGS:", function_args) kwdefaults = func.__defaults__ pass_kwargs = {} if "=" in function_args: assert kwdefaults!=None arg_remains = function_args.split("=")[0] kwarg_remains = function_args.replace(arg_remains,"") kwarg_extra_names =[content.split(",")[-1].strip() for index, content in enumerate(kwarg_remains.split("=")) if index%2 ==1] mfunctionArgsPrimitive = arg_remains.replace("(","").split(",") kwarg_names = [mfunctionArgsPrimitive[-1].strip()]+kwarg_extra_names mfunctionArgs = mfunctionArgsPrimitive[:-1] if debug_flag: print("PASSED KEYWORD ARGS:", kwargs) print("KWARG NAMES:", kwarg_names) for key, value in zip(kwarg_names, kwdefaults): pass_kwargs.update({key: value}) for key in kwargs.keys(): assert key in kwarg_names pass_kwargs[key] = kwargs[key] else: assert kwdefaults == None mfunctionArgs = function_args.replace("(","").replace(")","").split(",") mfunctionArgs = [x.strip() for x in mfunctionArgs] mfunctionArgs = [x for x in mfunctionArgs if not isEmptyLine(x)] if debug_flag: print("POSITIONAL ARGS:",mfunctionArgs) assert len(args) == len(mfunctionArgs) for key, value in zip(mfunctionArgs, args): exec("{} = {}".format(key, value)) if kwdefaults is not None: for key, value in pass_kwargs.items(): exec("{} = {}".format(key, value)) actualCode = splited_code[2:] actualCode = [x for x in actualCode if not isEmptyLine(x)] minIndent = min([space_counter(line) for line in actualCode])
if debug_flag: print(minIndent) newLines = [line[minIndent:] for line in actualCode] codeBlocks = getCodeBlocks(newLines) for block in codeBlocks: if debug_flag: print("##########CODEBLOCK##########") print(block) print("##########CODEBLOCK##########") if not debug_flag: with suppress(Exception): exec(block) else: try: exec(block) except: traceback.print_exc() if breakpoint_flag: breakpoint() if debug_flag: print("########## FUNCTION #########") return new_func def skipExceptionVerbose(func): return skipException(func, debug_flag=True) def skipExceptionBreakpoint(func): return skipException(func, breakpoint_flag=True) def skipExceptionDebug(func): return skipException(func, breakpoint_flag=True, debug_flag=True) @skipException def someOtherShit(): amd=[1,2,3] amd[4] print("shit happens") def anotherShit(): @skipException def mySuperFunction(d,e,f): someOtherShit() print("YOU WIN") a = [1,2,3] a[3] print("YOU WIN") a[4] print("INSIDE FUNCTION",d,e,f) print("YOU WIN") mySuperFunction(1,2,3)
anotherShit()
|