def _matchlambda(func, line): """check if lambda object 'func' matches raw line of code 'line'""" from dill.detect import code as getcode from dill.detect import freevars, globalvars, varnames dummy = lambda: '__this_is_a_big_dummy_function__' # process the line (removing leading whitespace, etc) lhs, rhs = line.split('lambda ', 1)[-1].split(":", 1) #FIXME: if !1 inputs try: #FIXME: unsafe _ = eval("lambda %s : %s" % (lhs, rhs), globals(), locals()) except: _ = dummy # get code objects, for comparison _, code = getcode(_).co_code, getcode(func).co_code # check if func is in closure _f = [line.count(i) for i in freevars(func).keys()] if not _f: # not in closure # check if code matches if _ == code: return True return False # weak check on freevars if not all(_f): return False #XXX: VERY WEAK # weak check on varnames and globalvars _f = varnames(func) _f = [line.count(i) for i in _f[0] + _f[1]] if _f and not all(_f): return False #XXX: VERY WEAK _f = [line.count(i) for i in globalvars(func).keys()] if _f and not all(_f): return False #XXX: VERY WEAK # check if func is a double lambda if (line.count('lambda ') > 1) and (lhs in freevars(func).keys()): _lhs, _rhs = rhs.split('lambda ', 1)[-1].split(":", 1) #FIXME: if !1 inputs try: #FIXME: unsafe _f = eval("lambda %s : %s" % (_lhs, _rhs), globals(), locals()) except: _f = dummy # get code objects, for comparison _, code = getcode(_f).co_code, getcode(func).co_code if len(_) != len(code): return False #NOTE: should be same code same order, but except for 't' and '\x88' _ = set((i, j) for (i, j) in zip(_, code) if i != j) if len(_) != 1: return False #('t','\x88') return True # check indentsize if not indentsize(line): return False #FIXME: is this a good check??? # check if code 'pattern' matches #XXX: or pattern match against dis.dis(code)? (or use uncompyle2?) _ = _.split(_[0]) # 't' #XXX: remove matching values if starts the same? _f = code.split(code[0]) # '\x88' #NOTE: should be same code different order, with different first element _ = dict( re.match('([\W\D\S])(.*)', _[i]).groups() for i in range(1, len(_))) _f = dict( re.match('([\W\D\S])(.*)', _f[i]).groups() for i in range(1, len(_f))) if (_.keys() == _f.keys()) and (sorted(_.values()) == sorted(_f.values())): return True return False
def _matchlambda(func, line): """check if lambda object 'func' matches raw line of code 'line'""" from dill.detect import code as getcode from dill.detect import freevars, globalvars, varnames dummy = lambda : '__this_is_a_big_dummy_function__' # process the line (removing leading whitespace, etc) lhs,rhs = line.split('lambda ',1)[-1].split(":", 1) #FIXME: if !1 inputs try: #FIXME: unsafe _ = eval("lambda %s : %s" % (lhs,rhs), globals(),locals()) except: _ = dummy # get code objects, for comparison _, code = getcode(_).co_code, getcode(func).co_code # check if func is in closure _f = [line.count(i) for i in freevars(func).keys()] if not _f: # not in closure # check if code matches if _ == code: return True return False # weak check on freevars if not all(_f): return False #XXX: VERY WEAK # weak check on varnames and globalvars _f = varnames(func) _f = [line.count(i) for i in _f[0]+_f[1]] if _f and not all(_f): return False #XXX: VERY WEAK _f = [line.count(i) for i in globalvars(func).keys()] if _f and not all(_f): return False #XXX: VERY WEAK # check if func is a double lambda if (line.count('lambda ') > 1) and (lhs in freevars(func).keys()): _lhs,_rhs = rhs.split('lambda ',1)[-1].split(":",1) #FIXME: if !1 inputs try: #FIXME: unsafe _f = eval("lambda %s : %s" % (_lhs,_rhs), globals(),locals()) except: _f = dummy # get code objects, for comparison _, code = getcode(_f).co_code, getcode(func).co_code if len(_) != len(code): return False #NOTE: should be same code same order, but except for 't' and '\x88' _ = set((i,j) for (i,j) in zip(_,code) if i != j) if len(_) != 1: return False #('t','\x88') return True # check indentsize if not indentsize(line): return False #FIXME: is this a good check??? # check if code 'pattern' matches #XXX: or pattern match against dis.dis(code)? (or use uncompyle2?) _ = _.split(_[0]) # 't' #XXX: remove matching values if starts the same? _f = code.split(code[0]) # '\x88' #NOTE: should be same code different order, with different first element _ = dict(re.match('([\W\D\S])(.*)', _[i]).groups() for i in range(1,len(_))) _f = dict(re.match('([\W\D\S])(.*)', _f[i]).groups() for i in range(1,len(_f))) if (_.keys() == _f.keys()) and (sorted(_.values()) == sorted(_f.values())): return True return False
def _closuredsource(func, alias=''): """get source code for closured objects; return a dict of 'name' and 'code blocks'""" from dill.detect import freevars free_vars = freevars(func) func_vars = {} # split into 'funcs' and 'non-funcs' for name, obj in list(free_vars.items()): if not isfunction(obj): # get source for 'non-funcs' free_vars[name] = getsource(obj, force=True, alias=name) continue # get source for 'funcs' fobj = free_vars.pop(name) src = getsource(fobj, alias) # if source doesn't start with '@', use name as the alias if not src.lstrip().startswith('@'): #FIXME: 'enclose' in dummy; src = getsource(fobj, alias=name) # wrong ref 'name' org = getsource(func, alias, enclosing=False, lstrip=True) src = (src, org) # undecorated first, then target else: #NOTE: reproduces the code! org = getsource(func, enclosing=True, lstrip=False) src = (org, src) # target first, then decorated func_vars[name] = src if not func_vars: #FIXME: 'enclose' in dummy; wrong ref 'name' src = ''.join(free_vars.values()) org = getsource(func, alias, force=True, enclosing=False, lstrip=True) src = (src, org) # variables first, then target func_vars[None] = src return func_vars
def _closuredsource(func, alias=''): """get source code for closured objects; return a dict of 'name' and 'code blocks'""" from dill.detect import freevars free_vars = freevars(func) func_vars = {} # split into 'funcs' and 'non-funcs' for name,obj in list(free_vars.items()): if not isfunction(obj): # get source for 'non-funcs' free_vars[name] = getsource(obj, force=True, alias=name) continue # get source for 'funcs' fobj = free_vars.pop(name) src = getsource(fobj, alias) # if source doesn't start with '@', use name as the alias if not src.lstrip().startswith('@'): #FIXME: 'enclose' in dummy; src = getsource(fobj, alias=name)# wrong ref 'name' org = getsource(func, alias, enclosing=False, lstrip=True) src = (src, org) # undecorated first, then target else: #NOTE: reproduces the code! org = getsource(func, enclosing=True, lstrip=False) src = (org, src) # target first, then decorated func_vars[name] = src if not func_vars: #FIXME: 'enclose' in dummy; wrong ref 'name' src = ''.join(free_vars.values()) org = getsource(func, alias, force=True, enclosing=False, lstrip=True) src = (src, org) # variables first, then target func_vars[None] = src return func_vars
def _closuredimport(func, alias='', builtin=False): """get import for closured objects; return a dict of 'name' and 'import'""" import re from dill.detect import freevars, outermost free_vars = freevars(func) func_vars = {} # split into 'funcs' and 'non-funcs' for name,obj in list(free_vars.items()): if not isfunction(obj): continue # get import for 'funcs' fobj = free_vars.pop(name) src = getsource(fobj) if src.lstrip().startswith('@'): # we have a decorator src = getimport(fobj, alias=alias, builtin=builtin) else: # we have to "hack" a bit... and maybe be lucky encl = outermost(func) # pattern: 'func = enclosing(fobj' pat = '.*[\w\s]=\s*'+getname(encl)+'\('+getname(fobj) mod = getname(getmodule(encl)) #HACK: get file containing 'outer' function; is func there? lines,_ = findsource(encl) candidate = [line for line in lines if getname(encl) in line and \ re.match(pat, line)] if not candidate: mod = getname(getmodule(fobj)) #HACK: get file containing 'inner' function; is func there? lines,_ = findsource(fobj) candidate = [line for line in lines \ if getname(fobj) in line and re.match(pat, line)] if not len(candidate): raise TypeError('import could not be found') candidate = candidate[-1] name = candidate.split('=',1)[0].split()[-1].strip() src = _getimport(mod, name, alias=alias, builtin=builtin) func_vars[name] = src if not func_vars: name = outermost(func) mod = getname(getmodule(name)) if not mod or name is func: # then it can be handled by getimport name = getname(func, force=True) #XXX: better key? src = getimport(func, alias=alias, builtin=builtin) else: lines,_ = findsource(name) # pattern: 'func = enclosing(' candidate = [line for line in lines if getname(name) in line and \ re.match('.*[\w\s]=\s*'+getname(name)+'\(', line)] if not len(candidate): raise TypeError('import could not be found') candidate = candidate[-1] name = candidate.split('=',1)[0].split()[-1].strip() src = _getimport(mod, name, alias=alias, builtin=builtin) func_vars[name] = src return func_vars
def _closuredsource(func, alias=''): """get source code for closured objects; return a dict of 'name' and 'code blocks'""" #FIXME: this entire function is a messy messy HACK # - pollutes global namespace # - fails if name of freevars are reused # - can unnecessarily duplicate function code from dill.detect import freevars free_vars = freevars(func) func_vars = {} # split into 'funcs' and 'non-funcs' for name,obj in list(free_vars.items()): if not isfunction(obj): # get source for 'non-funcs' free_vars[name] = getsource(obj, force=True, alias=name) continue # get source for 'funcs' fobj = free_vars.pop(name) src = getsource(fobj, alias) # DO NOT include dependencies # if source doesn't start with '@', use name as the alias if not src.lstrip().startswith('@'): #FIXME: 'enclose' in dummy; src = importable(fobj,alias=name)# wrong ref 'name' org = getsource(func, alias, enclosing=False, lstrip=True) src = (src, org) # undecorated first, then target else: #NOTE: reproduces the code! org = getsource(func, enclosing=True, lstrip=False) src = importable(fobj, alias, source=True) # include dependencies src = (org, src) # target first, then decorated func_vars[name] = src src = ''.join(free_vars.values()) if not func_vars: #FIXME: 'enclose' in dummy; wrong ref 'name' org = getsource(func, alias, force=True, enclosing=False, lstrip=True) src = (src, org) # variables first, then target else: src = (src, None) # just variables (better '' instead of None?) func_vars[None] = src # FIXME: remove duplicates (however, order is important...) return func_vars