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 getimport(obj, alias='', verify=True, builtin=False, enclosing=False): """get the likely import string for the given object obj is the object to inspect If verify=True, then test the import string before returning it. If builtin=True, then force an import for builtins where possible. If enclosing=True, get the import for the outermost enclosing callable. If alias is provided, then rename the object on import. """ if enclosing: from dill.detect import outermost _obj = outermost(obj) obj = _obj if _obj else obj # get the namespace qual = _namespace(obj) head = '.'.join(qual[:-1]) tail = qual[-1] # for named things... with a nice repr #XXX: move into _namespace? try: # look for '<...>' and be mindful it might be in lists, dicts, etc... name = repr(obj).split('<', 1)[1].split('>', 1)[1] name = None # we have a 'object'-style repr except: # it's probably something 'importable' if head in ['builtins', '__builtin__']: name = repr(obj) #XXX: catch [1,2], (1,2), set([1,2])... others? else: name = repr(obj).split('(')[0] #if not repr(obj).startswith('<'): name = repr(obj).split('(')[0] #else: name = None if name: # try using name instead of tail try: return _getimport(head, name, alias, verify, builtin) except ImportError: pass except SyntaxError: if head in ['builtins', '__builtin__']: _alias = '%s = ' % alias if alias else '' if alias == name: _alias = '' return _alias + '%s\n' % name else: pass try: #if type(obj) is type(abs): _builtin = builtin # BuiltinFunctionType #else: _builtin = False return _getimport(head, tail, alias, verify, builtin) except ImportError: raise # could do some checking against obj except SyntaxError: if head in ['builtins', '__builtin__']: _alias = '%s = ' % alias if alias else '' if alias == tail: _alias = '' return _alias + '%s\n' % tail raise # could do some checking against obj
def getimport(obj, alias='', verify=True, builtin=False, enclosing=False): """get the likely import string for the given object obj is the object to inspect If verify=True, then test the import string before returning it. If builtin=True, then force an import for builtins where possible. If enclosing=True, get the import for the outermost enclosing callable. If alias is provided, then rename the object on import. """ if enclosing: from dill.detect import outermost _obj = outermost(obj) obj = _obj if _obj else obj # get the namespace qual = _namespace(obj) head = '.'.join(qual[:-1]) tail = qual[-1] # for named things... with a nice repr #XXX: move into _namespace? try: # look for '<...>' and be mindful it might be in lists, dicts, etc... name = repr(obj).split('<',1)[1].split('>',1)[1] name = None # we have a 'object'-style repr except: # it's probably something 'importable' if head in ['builtins','__builtin__']: name = repr(obj) #XXX: catch [1,2], (1,2), set([1,2])... others? else: name = repr(obj).split('(')[0] #if not repr(obj).startswith('<'): name = repr(obj).split('(')[0] #else: name = None if name: # try using name instead of tail try: return _getimport(head, name, alias, verify, builtin) except ImportError: pass except SyntaxError: if head in ['builtins','__builtin__']: _alias = '%s = ' % alias if alias else '' if alias == name: _alias = '' return _alias+'%s\n' % name else: pass try: #if type(obj) is type(abs): _builtin = builtin # BuiltinFunctionType #else: _builtin = False return _getimport(head, tail, alias, verify, builtin) except ImportError: raise # could do some checking against obj except SyntaxError: if head in ['builtins','__builtin__']: _alias = '%s = ' % alias if alias else '' if alias == tail: _alias = '' return _alias+'%s\n' % tail raise # could do some checking against obj