source.py 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. #!/usr/bin/env python
  2. #
  3. # Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
  4. # Copyright (c) 2008-2016 California Institute of Technology.
  5. # Copyright (c) 2016-2024 The Uncertainty Quantification Foundation.
  6. # License: 3-clause BSD. The full license text is available at:
  7. # - https://github.com/uqfoundation/dill/blob/master/LICENSE
  8. #
  9. # inspired by inspect.py from Python-2.7.6
  10. # inspect.py author: 'Ka-Ping Yee <ping@lfw.org>'
  11. # inspect.py merged into original dill.source by Mike McKerns 4/13/14
  12. """
  13. Extensions to python's 'inspect' module, which can be used
  14. to retrieve information from live python objects. The methods
  15. defined in this module are augmented to facilitate access to
  16. source code of interactively defined functions and classes,
  17. as well as provide access to source code for objects defined
  18. in a file.
  19. """
  20. __all__ = ['findsource', 'getsourcelines', 'getsource', 'indent', 'outdent', \
  21. '_wrap', 'dumpsource', 'getname', '_namespace', 'getimport', \
  22. '_importable', 'importable','isdynamic', 'isfrommain']
  23. import linecache
  24. import re
  25. from inspect import (getblock, getfile, getmodule, getsourcefile, indentsize,
  26. isbuiltin, isclass, iscode, isframe, isfunction, ismethod,
  27. ismodule, istraceback)
  28. from tokenize import TokenError
  29. from ._dill import IS_IPYTHON
  30. def isfrommain(obj):
  31. "check if object was built in __main__"
  32. module = getmodule(obj)
  33. if module and module.__name__ == '__main__':
  34. return True
  35. return False
  36. def isdynamic(obj):
  37. "check if object was built in the interpreter"
  38. try: file = getfile(obj)
  39. except TypeError: file = None
  40. if file == '<stdin>' and isfrommain(obj):
  41. return True
  42. return False
  43. def _matchlambda(func, line):
  44. """check if lambda object 'func' matches raw line of code 'line'"""
  45. from .detect import code as getcode
  46. from .detect import freevars, globalvars, varnames
  47. dummy = lambda : '__this_is_a_big_dummy_function__'
  48. # process the line (removing leading whitespace, etc)
  49. lhs,rhs = line.split('lambda ',1)[-1].split(":", 1) #FIXME: if !1 inputs
  50. try: #FIXME: unsafe
  51. _ = eval("lambda %s : %s" % (lhs,rhs), globals(),locals())
  52. except Exception: _ = dummy
  53. # get code objects, for comparison
  54. _, code = getcode(_).co_code, getcode(func).co_code
  55. # check if func is in closure
  56. _f = [line.count(i) for i in freevars(func).keys()]
  57. if not _f: # not in closure
  58. # check if code matches
  59. if _ == code: return True
  60. return False
  61. # weak check on freevars
  62. if not all(_f): return False #XXX: VERY WEAK
  63. # weak check on varnames and globalvars
  64. _f = varnames(func)
  65. _f = [line.count(i) for i in _f[0]+_f[1]]
  66. if _f and not all(_f): return False #XXX: VERY WEAK
  67. _f = [line.count(i) for i in globalvars(func).keys()]
  68. if _f and not all(_f): return False #XXX: VERY WEAK
  69. # check if func is a double lambda
  70. if (line.count('lambda ') > 1) and (lhs in freevars(func).keys()):
  71. _lhs,_rhs = rhs.split('lambda ',1)[-1].split(":",1) #FIXME: if !1 inputs
  72. try: #FIXME: unsafe
  73. _f = eval("lambda %s : %s" % (_lhs,_rhs), globals(),locals())
  74. except Exception: _f = dummy
  75. # get code objects, for comparison
  76. _, code = getcode(_f).co_code, getcode(func).co_code
  77. if len(_) != len(code): return False
  78. #NOTE: should be same code same order, but except for 't' and '\x88'
  79. _ = set((i,j) for (i,j) in zip(_,code) if i != j)
  80. if len(_) != 1: return False #('t','\x88')
  81. return True
  82. # check indentsize
  83. if not indentsize(line): return False #FIXME: is this a good check???
  84. # check if code 'pattern' matches
  85. #XXX: or pattern match against dis.dis(code)? (or use uncompyle2?)
  86. _ = _.split(_[0]) # 't' #XXX: remove matching values if starts the same?
  87. _f = code.split(code[0]) # '\x88'
  88. #NOTE: should be same code different order, with different first element
  89. _ = dict(re.match(r'([\W\D\S])(.*)', _[i]).groups() for i in range(1,len(_)))
  90. _f = dict(re.match(r'([\W\D\S])(.*)', _f[i]).groups() for i in range(1,len(_f)))
  91. if (_.keys() == _f.keys()) and (sorted(_.values()) == sorted(_f.values())):
  92. return True
  93. return False
  94. def findsource(object):
  95. """Return the entire source file and starting line number for an object.
  96. For interactively-defined objects, the 'file' is the interpreter's history.
  97. The argument may be a module, class, method, function, traceback, frame,
  98. or code object. The source code is returned as a list of all the lines
  99. in the file and the line number indexes a line in that list. An IOError
  100. is raised if the source code cannot be retrieved, while a TypeError is
  101. raised for objects where the source code is unavailable (e.g. builtins)."""
  102. module = getmodule(object)
  103. try: file = getfile(module)
  104. except TypeError: file = None
  105. is_module_main = (module and module.__name__ == '__main__' and not file)
  106. if IS_IPYTHON and is_module_main:
  107. #FIXME: quick fix for functions and classes in IPython interpreter
  108. try:
  109. file = getfile(object)
  110. sourcefile = getsourcefile(object)
  111. except TypeError:
  112. if isclass(object):
  113. for object_method in filter(isfunction, object.__dict__.values()):
  114. # look for a method of the class
  115. file_candidate = getfile(object_method)
  116. if not file_candidate.startswith('<ipython-input-'):
  117. continue
  118. file = file_candidate
  119. sourcefile = getsourcefile(object_method)
  120. break
  121. if file:
  122. lines = linecache.getlines(file)
  123. else:
  124. # fallback to use history
  125. history = '\n'.join(get_ipython().history_manager.input_hist_parsed)
  126. lines = [line + '\n' for line in history.splitlines()]
  127. # use readline when working in interpreter (i.e. __main__ and not file)
  128. elif is_module_main:
  129. try:
  130. import readline
  131. err = ''
  132. except ImportError:
  133. import sys
  134. err = sys.exc_info()[1].args[0]
  135. if sys.platform[:3] == 'win':
  136. err += ", please install 'pyreadline'"
  137. if err:
  138. raise IOError(err)
  139. lbuf = readline.get_current_history_length()
  140. lines = [readline.get_history_item(i)+'\n' for i in range(1,lbuf+1)]
  141. else:
  142. try: # special handling for class instances
  143. if not isclass(object) and isclass(type(object)): # __class__
  144. file = getfile(module)
  145. sourcefile = getsourcefile(module)
  146. else: # builtins fail with a TypeError
  147. file = getfile(object)
  148. sourcefile = getsourcefile(object)
  149. except (TypeError, AttributeError): # fail with better error
  150. file = getfile(object)
  151. sourcefile = getsourcefile(object)
  152. if not sourcefile and file[:1] + file[-1:] != '<>':
  153. raise IOError('source code not available')
  154. file = sourcefile if sourcefile else file
  155. module = getmodule(object, file)
  156. if module:
  157. lines = linecache.getlines(file, module.__dict__)
  158. else:
  159. lines = linecache.getlines(file)
  160. if not lines:
  161. raise IOError('could not extract source code')
  162. #FIXME: all below may fail if exec used (i.e. exec('f = lambda x:x') )
  163. if ismodule(object):
  164. return lines, 0
  165. #NOTE: beneficial if search goes from end to start of buffer history
  166. name = pat1 = obj = ''
  167. pat2 = r'^(\s*@)'
  168. # pat1b = r'^(\s*%s\W*=)' % name #FIXME: finds 'f = decorate(f)', not exec
  169. if ismethod(object):
  170. name = object.__name__
  171. if name == '<lambda>': pat1 = r'(.*(?<!\w)lambda(:|\s))'
  172. else: pat1 = r'^(\s*def\s)'
  173. object = object.__func__
  174. if isfunction(object):
  175. name = object.__name__
  176. if name == '<lambda>':
  177. pat1 = r'(.*(?<!\w)lambda(:|\s))'
  178. obj = object #XXX: better a copy?
  179. else: pat1 = r'^(\s*def\s)'
  180. object = object.__code__
  181. if istraceback(object):
  182. object = object.tb_frame
  183. if isframe(object):
  184. object = object.f_code
  185. if iscode(object):
  186. if not hasattr(object, 'co_firstlineno'):
  187. raise IOError('could not find function definition')
  188. stdin = object.co_filename == '<stdin>'
  189. if stdin:
  190. lnum = len(lines) - 1 # can't get lnum easily, so leverage pat
  191. if not pat1: pat1 = r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)'
  192. else:
  193. lnum = object.co_firstlineno - 1
  194. pat1 = r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)'
  195. pat1 = re.compile(pat1); pat2 = re.compile(pat2)
  196. #XXX: candidate_lnum = [n for n in range(lnum) if pat1.match(lines[n])]
  197. while lnum > 0: #XXX: won't find decorators in <stdin> ?
  198. line = lines[lnum]
  199. if pat1.match(line):
  200. if not stdin: break # co_firstlineno does the job
  201. if name == '<lambda>': # hackery needed to confirm a match
  202. if _matchlambda(obj, line): break
  203. else: # not a lambda, just look for the name
  204. if name in line: # need to check for decorator...
  205. hats = 0
  206. for _lnum in range(lnum-1,-1,-1):
  207. if pat2.match(lines[_lnum]): hats += 1
  208. else: break
  209. lnum = lnum - hats
  210. break
  211. lnum = lnum - 1
  212. return lines, lnum
  213. try: # turn instances into classes
  214. if not isclass(object) and isclass(type(object)): # __class__
  215. object = object.__class__ #XXX: sometimes type(class) is better?
  216. #XXX: we don't find how the instance was built
  217. except AttributeError: pass
  218. if isclass(object):
  219. name = object.__name__
  220. pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
  221. # make some effort to find the best matching class definition:
  222. # use the one with the least indentation, which is the one
  223. # that's most probably not inside a function definition.
  224. candidates = []
  225. for i in range(len(lines)-1,-1,-1):
  226. match = pat.match(lines[i])
  227. if match:
  228. # if it's at toplevel, it's already the best one
  229. if lines[i][0] == 'c':
  230. return lines, i
  231. # else add whitespace to candidate list
  232. candidates.append((match.group(1), i))
  233. if candidates:
  234. # this will sort by whitespace, and by line number,
  235. # less whitespace first #XXX: should sort high lnum before low
  236. candidates.sort()
  237. return lines, candidates[0][1]
  238. else:
  239. raise IOError('could not find class definition')
  240. raise IOError('could not find code object')
  241. def getblocks(object, lstrip=False, enclosing=False, locate=False):
  242. """Return a list of source lines and starting line number for an object.
  243. Interactively-defined objects refer to lines in the interpreter's history.
  244. If enclosing=True, then also return any enclosing code.
  245. If lstrip=True, ensure there is no indentation in the first line of code.
  246. If locate=True, then also return the line number for the block of code.
  247. DEPRECATED: use 'getsourcelines' instead
  248. """
  249. lines, lnum = findsource(object)
  250. if ismodule(object):
  251. if lstrip: lines = _outdent(lines)
  252. return ([lines], [0]) if locate is True else [lines]
  253. #XXX: 'enclosing' means: closures only? or classes and files?
  254. indent = indentsize(lines[lnum])
  255. block = getblock(lines[lnum:]) #XXX: catch any TokenError here?
  256. if not enclosing or not indent:
  257. if lstrip: block = _outdent(block)
  258. return ([block], [lnum]) if locate is True else [block]
  259. pat1 = r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))'; pat1 = re.compile(pat1)
  260. pat2 = r'^(\s*@)'; pat2 = re.compile(pat2)
  261. #pat3 = r'^(\s*class\s)'; pat3 = re.compile(pat3) #XXX: enclosing class?
  262. #FIXME: bound methods need enclosing class (and then instantiation)
  263. # *or* somehow apply a partial using the instance
  264. skip = 0
  265. line = 0
  266. blocks = []; _lnum = []
  267. target = ''.join(block)
  268. while line <= lnum: #XXX: repeat lnum? or until line < lnum?
  269. # see if starts with ('def','lambda') and contains our target block
  270. if pat1.match(lines[line]):
  271. if not skip:
  272. try: code = getblock(lines[line:])
  273. except TokenError: code = [lines[line]]
  274. if indentsize(lines[line]) > indent: #XXX: should be >= ?
  275. line += len(code) - skip
  276. elif target in ''.join(code):
  277. blocks.append(code) # save code block as the potential winner
  278. _lnum.append(line - skip) # save the line number for the match
  279. line += len(code) - skip
  280. else:
  281. line += 1
  282. skip = 0
  283. # find skip: the number of consecutive decorators
  284. elif pat2.match(lines[line]):
  285. try: code = getblock(lines[line:])
  286. except TokenError: code = [lines[line]]
  287. skip = 1
  288. for _line in code[1:]: # skip lines that are decorators
  289. if not pat2.match(_line): break
  290. skip += 1
  291. line += skip
  292. # no match: reset skip and go to the next line
  293. else:
  294. line +=1
  295. skip = 0
  296. if not blocks:
  297. blocks = [block]
  298. _lnum = [lnum]
  299. if lstrip: blocks = [_outdent(block) for block in blocks]
  300. # return last match
  301. return (blocks, _lnum) if locate is True else blocks
  302. def getsourcelines(object, lstrip=False, enclosing=False):
  303. """Return a list of source lines and starting line number for an object.
  304. Interactively-defined objects refer to lines in the interpreter's history.
  305. The argument may be a module, class, method, function, traceback, frame,
  306. or code object. The source code is returned as a list of the lines
  307. corresponding to the object and the line number indicates where in the
  308. original source file the first line of code was found. An IOError is
  309. raised if the source code cannot be retrieved, while a TypeError is
  310. raised for objects where the source code is unavailable (e.g. builtins).
  311. If lstrip=True, ensure there is no indentation in the first line of code.
  312. If enclosing=True, then also return any enclosing code."""
  313. code, n = getblocks(object, lstrip=lstrip, enclosing=enclosing, locate=True)
  314. return code[-1], n[-1]
  315. #NOTE: broke backward compatibility 4/16/14 (was lstrip=True, force=True)
  316. def getsource(object, alias='', lstrip=False, enclosing=False, \
  317. force=False, builtin=False):
  318. """Return the text of the source code for an object. The source code for
  319. interactively-defined objects are extracted from the interpreter's history.
  320. The argument may be a module, class, method, function, traceback, frame,
  321. or code object. The source code is returned as a single string. An
  322. IOError is raised if the source code cannot be retrieved, while a
  323. TypeError is raised for objects where the source code is unavailable
  324. (e.g. builtins).
  325. If alias is provided, then add a line of code that renames the object.
  326. If lstrip=True, ensure there is no indentation in the first line of code.
  327. If enclosing=True, then also return any enclosing code.
  328. If force=True, catch (TypeError,IOError) and try to use import hooks.
  329. If builtin=True, force an import for any builtins
  330. """
  331. # hascode denotes a callable
  332. hascode = _hascode(object)
  333. # is a class instance type (and not in builtins)
  334. instance = _isinstance(object)
  335. # get source lines; if fail, try to 'force' an import
  336. try: # fails for builtins, and other assorted object types
  337. lines, lnum = getsourcelines(object, enclosing=enclosing)
  338. except (TypeError, IOError): # failed to get source, resort to import hooks
  339. if not force: # don't try to get types that findsource can't get
  340. raise
  341. if not getmodule(object): # get things like 'None' and '1'
  342. if not instance: return getimport(object, alias, builtin=builtin)
  343. # special handling (numpy arrays, ...)
  344. _import = getimport(object, builtin=builtin)
  345. name = getname(object, force=True)
  346. _alias = "%s = " % alias if alias else ""
  347. if alias == name: _alias = ""
  348. return _import+_alias+"%s\n" % name
  349. else: #FIXME: could use a good bit of cleanup, since using getimport...
  350. if not instance: return getimport(object, alias, builtin=builtin)
  351. # now we are dealing with an instance...
  352. name = object.__class__.__name__
  353. module = object.__module__
  354. if module in ['builtins','__builtin__']:
  355. return getimport(object, alias, builtin=builtin)
  356. else: #FIXME: leverage getimport? use 'from module import name'?
  357. lines, lnum = ["%s = __import__('%s', fromlist=['%s']).%s\n" % (name,module,name,name)], 0
  358. obj = eval(lines[0].lstrip(name + ' = '))
  359. lines, lnum = getsourcelines(obj, enclosing=enclosing)
  360. # strip leading indent (helps ensure can be imported)
  361. if lstrip or alias:
  362. lines = _outdent(lines)
  363. # instantiate, if there's a nice repr #XXX: BAD IDEA???
  364. if instance: #and force: #XXX: move into findsource or getsourcelines ?
  365. if '(' in repr(object): lines.append('%r\n' % object)
  366. #else: #XXX: better to somehow to leverage __reduce__ ?
  367. # reconstructor,args = object.__reduce__()
  368. # _ = reconstructor(*args)
  369. else: # fall back to serialization #XXX: bad idea?
  370. #XXX: better not duplicate work? #XXX: better new/enclose=True?
  371. lines = dumpsource(object, alias='', new=force, enclose=False)
  372. lines, lnum = [line+'\n' for line in lines.split('\n')][:-1], 0
  373. #else: object.__code__ # raise AttributeError
  374. # add an alias to the source code
  375. if alias:
  376. if hascode:
  377. skip = 0
  378. for line in lines: # skip lines that are decorators
  379. if not line.startswith('@'): break
  380. skip += 1
  381. #XXX: use regex from findsource / getsourcelines ?
  382. if lines[skip].lstrip().startswith('def '): # we have a function
  383. if alias != object.__name__:
  384. lines.append('\n%s = %s\n' % (alias, object.__name__))
  385. elif 'lambda ' in lines[skip]: # we have a lambda
  386. if alias != lines[skip].split('=')[0].strip():
  387. lines[skip] = '%s = %s' % (alias, lines[skip])
  388. else: # ...try to use the object's name
  389. if alias != object.__name__:
  390. lines.append('\n%s = %s\n' % (alias, object.__name__))
  391. else: # class or class instance
  392. if instance:
  393. if alias != lines[-1].split('=')[0].strip():
  394. lines[-1] = ('%s = ' % alias) + lines[-1]
  395. else:
  396. name = getname(object, force=True) or object.__name__
  397. if alias != name:
  398. lines.append('\n%s = %s\n' % (alias, name))
  399. return ''.join(lines)
  400. def _hascode(object):
  401. '''True if object has an attribute that stores it's __code__'''
  402. return getattr(object,'__code__',None) or getattr(object,'func_code',None)
  403. def _isinstance(object):
  404. '''True if object is a class instance type (and is not a builtin)'''
  405. if _hascode(object) or isclass(object) or ismodule(object):
  406. return False
  407. if istraceback(object) or isframe(object) or iscode(object):
  408. return False
  409. # special handling (numpy arrays, ...)
  410. if not getmodule(object) and getmodule(type(object)).__name__ in ['numpy']:
  411. return True
  412. # # check if is instance of a builtin
  413. # if not getmodule(object) and getmodule(type(object)).__name__ in ['__builtin__','builtins']:
  414. # return False
  415. _types = ('<class ',"<type 'instance'>")
  416. if not repr(type(object)).startswith(_types): #FIXME: weak hack
  417. return False
  418. if not getmodule(object) or object.__module__ in ['builtins','__builtin__'] or getname(object, force=True) in ['array']:
  419. return False
  420. return True # by process of elimination... it's what we want
  421. def _intypes(object):
  422. '''check if object is in the 'types' module'''
  423. import types
  424. # allow user to pass in object or object.__name__
  425. if type(object) is not type(''):
  426. object = getname(object, force=True)
  427. if object == 'ellipsis': object = 'EllipsisType'
  428. return True if hasattr(types, object) else False
  429. def _isstring(object): #XXX: isstringlike better?
  430. '''check if object is a string-like type'''
  431. return isinstance(object, (str, bytes))
  432. def indent(code, spaces=4):
  433. '''indent a block of code with whitespace (default is 4 spaces)'''
  434. indent = indentsize(code)
  435. from numbers import Integral
  436. if isinstance(spaces, Integral): spaces = ' '*spaces
  437. # if '\t' is provided, will indent with a tab
  438. nspaces = indentsize(spaces)
  439. # blank lines (etc) need to be ignored
  440. lines = code.split('\n')
  441. ## stq = "'''"; dtq = '"""'
  442. ## in_stq = in_dtq = False
  443. for i in range(len(lines)):
  444. #FIXME: works... but shouldn't indent 2nd+ lines of multiline doc
  445. _indent = indentsize(lines[i])
  446. if indent > _indent: continue
  447. lines[i] = spaces+lines[i]
  448. ## #FIXME: may fail when stq and dtq in same line (depends on ordering)
  449. ## nstq, ndtq = lines[i].count(stq), lines[i].count(dtq)
  450. ## if not in_dtq and not in_stq:
  451. ## lines[i] = spaces+lines[i] # we indent
  452. ## # entering a comment block
  453. ## if nstq%2: in_stq = not in_stq
  454. ## if ndtq%2: in_dtq = not in_dtq
  455. ## # leaving a comment block
  456. ## elif in_dtq and ndtq%2: in_dtq = not in_dtq
  457. ## elif in_stq and nstq%2: in_stq = not in_stq
  458. ## else: pass
  459. if lines[-1].strip() == '': lines[-1] = ''
  460. return '\n'.join(lines)
  461. def _outdent(lines, spaces=None, all=True):
  462. '''outdent lines of code, accounting for docs and line continuations'''
  463. indent = indentsize(lines[0])
  464. if spaces is None or spaces > indent or spaces < 0: spaces = indent
  465. for i in range(len(lines) if all else 1):
  466. #FIXME: works... but shouldn't outdent 2nd+ lines of multiline doc
  467. _indent = indentsize(lines[i])
  468. if spaces > _indent: _spaces = _indent
  469. else: _spaces = spaces
  470. lines[i] = lines[i][_spaces:]
  471. return lines
  472. def outdent(code, spaces=None, all=True):
  473. '''outdent a block of code (default is to strip all leading whitespace)'''
  474. indent = indentsize(code)
  475. if spaces is None or spaces > indent or spaces < 0: spaces = indent
  476. #XXX: will this delete '\n' in some cases?
  477. if not all: return code[spaces:]
  478. return '\n'.join(_outdent(code.split('\n'), spaces=spaces, all=all))
  479. # _wrap provides an wrapper to correctly exec and load into locals
  480. __globals__ = globals()
  481. __locals__ = locals()
  482. def _wrap(f):
  483. """ encapsulate a function and it's __import__ """
  484. def func(*args, **kwds):
  485. try:
  486. # _ = eval(getsource(f, force=True)) #XXX: safer but less robust
  487. exec(getimportable(f, alias='_'), __globals__, __locals__)
  488. except Exception:
  489. raise ImportError('cannot import name ' + f.__name__)
  490. return _(*args, **kwds)
  491. func.__name__ = f.__name__
  492. func.__doc__ = f.__doc__
  493. return func
  494. def _enclose(object, alias=''): #FIXME: needs alias to hold returned object
  495. """create a function enclosure around the source of some object"""
  496. #XXX: dummy and stub should append a random string
  497. dummy = '__this_is_a_big_dummy_enclosing_function__'
  498. stub = '__this_is_a_stub_variable__'
  499. code = 'def %s():\n' % dummy
  500. code += indent(getsource(object, alias=stub, lstrip=True, force=True))
  501. code += indent('return %s\n' % stub)
  502. if alias: code += '%s = ' % alias
  503. code += '%s(); del %s\n' % (dummy, dummy)
  504. #code += "globals().pop('%s',lambda :None)()\n" % dummy
  505. return code
  506. def dumpsource(object, alias='', new=False, enclose=True):
  507. """'dump to source', where the code includes a pickled object.
  508. If new=True and object is a class instance, then create a new
  509. instance using the unpacked class source code. If enclose, then
  510. create the object inside a function enclosure (thus minimizing
  511. any global namespace pollution).
  512. """
  513. from dill import dumps
  514. pik = repr(dumps(object))
  515. code = 'import dill\n'
  516. if enclose:
  517. stub = '__this_is_a_stub_variable__' #XXX: *must* be same _enclose.stub
  518. pre = '%s = ' % stub
  519. new = False #FIXME: new=True doesn't work with enclose=True
  520. else:
  521. stub = alias
  522. pre = '%s = ' % stub if alias else alias
  523. # if a 'new' instance is not needed, then just dump and load
  524. if not new or not _isinstance(object):
  525. code += pre + 'dill.loads(%s)\n' % pik
  526. else: #XXX: other cases where source code is needed???
  527. code += getsource(object.__class__, alias='', lstrip=True, force=True)
  528. mod = repr(object.__module__) # should have a module (no builtins here)
  529. code += pre + 'dill.loads(%s.replace(b%s,bytes(__name__,"UTF-8")))\n' % (pik,mod)
  530. #code += 'del %s' % object.__class__.__name__ #NOTE: kills any existing!
  531. if enclose:
  532. # generation of the 'enclosure'
  533. dummy = '__this_is_a_big_dummy_object__'
  534. dummy = _enclose(dummy, alias=alias)
  535. # hack to replace the 'dummy' with the 'real' code
  536. dummy = dummy.split('\n')
  537. code = dummy[0]+'\n' + indent(code) + '\n'.join(dummy[-3:])
  538. return code #XXX: better 'dumpsourcelines', returning list of lines?
  539. def getname(obj, force=False, fqn=False): #XXX: throw(?) to raise error on fail?
  540. """get the name of the object. for lambdas, get the name of the pointer """
  541. if fqn: return '.'.join(_namespace(obj)) #NOTE: returns 'type'
  542. module = getmodule(obj)
  543. if not module: # things like "None" and "1"
  544. if not force: return None #NOTE: returns 'instance' NOT 'type' #FIXME?
  545. # handle some special cases
  546. if hasattr(obj, 'dtype') and not obj.shape:
  547. return getname(obj.__class__) + "(" + repr(obj.tolist()) + ")"
  548. return repr(obj)
  549. try:
  550. #XXX: 'wrong' for decorators and curried functions ?
  551. # if obj.func_closure: ...use logic from getimportable, etc ?
  552. name = obj.__name__
  553. if name == '<lambda>':
  554. return getsource(obj).split('=',1)[0].strip()
  555. # handle some special cases
  556. if module.__name__ in ['builtins','__builtin__']:
  557. if name == 'ellipsis': name = 'EllipsisType'
  558. return name
  559. except AttributeError: #XXX: better to just throw AttributeError ?
  560. if not force: return None
  561. name = repr(obj)
  562. if name.startswith('<'): # or name.split('('):
  563. return None
  564. return name
  565. def _namespace(obj):
  566. """_namespace(obj); return namespace hierarchy (as a list of names)
  567. for the given object. For an instance, find the class hierarchy.
  568. For example:
  569. >>> from functools import partial
  570. >>> p = partial(int, base=2)
  571. >>> _namespace(p)
  572. [\'functools\', \'partial\']
  573. """
  574. # mostly for functions and modules and such
  575. #FIXME: 'wrong' for decorators and curried functions
  576. try: #XXX: needs some work and testing on different types
  577. module = qual = str(getmodule(obj)).split()[1].strip('>').strip('"').strip("'")
  578. qual = qual.split('.')
  579. if ismodule(obj):
  580. return qual
  581. # get name of a lambda, function, etc
  582. name = getname(obj) or obj.__name__ # failing, raise AttributeError
  583. # check special cases (NoneType, ...)
  584. if module in ['builtins','__builtin__']: # BuiltinFunctionType
  585. if _intypes(name): return ['types'] + [name]
  586. return qual + [name] #XXX: can be wrong for some aliased objects
  587. except Exception: pass
  588. # special case: numpy.inf and numpy.nan (we don't want them as floats)
  589. if str(obj) in ['inf','nan','Inf','NaN']: # is more, but are they needed?
  590. return ['numpy'] + [str(obj)]
  591. # mostly for classes and class instances and such
  592. module = getattr(obj.__class__, '__module__', None)
  593. qual = str(obj.__class__)
  594. try: qual = qual[qual.index("'")+1:-2]
  595. except ValueError: pass # str(obj.__class__) made the 'try' unnecessary
  596. qual = qual.split(".")
  597. if module in ['builtins','__builtin__']:
  598. # check special cases (NoneType, Ellipsis, ...)
  599. if qual[-1] == 'ellipsis': qual[-1] = 'EllipsisType'
  600. if _intypes(qual[-1]): module = 'types' #XXX: BuiltinFunctionType
  601. qual = [module] + qual
  602. return qual
  603. #NOTE: 05/25/14 broke backward compatibility: added 'alias' as 3rd argument
  604. def _getimport(head, tail, alias='', verify=True, builtin=False):
  605. """helper to build a likely import string from head and tail of namespace.
  606. ('head','tail') are used in the following context: "from head import tail"
  607. If verify=True, then test the import string before returning it.
  608. If builtin=True, then force an import for builtins where possible.
  609. If alias is provided, then rename the object on import.
  610. """
  611. # special handling for a few common types
  612. if tail in ['Ellipsis', 'NotImplemented'] and head in ['types']:
  613. head = len.__module__
  614. elif tail in ['None'] and head in ['types']:
  615. _alias = '%s = ' % alias if alias else ''
  616. if alias == tail: _alias = ''
  617. return _alias+'%s\n' % tail
  618. # we don't need to import from builtins, so return ''
  619. # elif tail in ['NoneType','int','float','long','complex']: return '' #XXX: ?
  620. if head in ['builtins','__builtin__']:
  621. # special cases (NoneType, Ellipsis, ...) #XXX: BuiltinFunctionType
  622. if tail == 'ellipsis': tail = 'EllipsisType'
  623. if _intypes(tail): head = 'types'
  624. elif not builtin:
  625. _alias = '%s = ' % alias if alias else ''
  626. if alias == tail: _alias = ''
  627. return _alias+'%s\n' % tail
  628. else: pass # handle builtins below
  629. # get likely import string
  630. if not head: _str = "import %s" % tail
  631. else: _str = "from %s import %s" % (head, tail)
  632. _alias = " as %s\n" % alias if alias else "\n"
  633. if alias == tail: _alias = "\n"
  634. _str += _alias
  635. # FIXME: fails on most decorators, currying, and such...
  636. # (could look for magic __wrapped__ or __func__ attr)
  637. # (could fix in 'namespace' to check obj for closure)
  638. if verify and not head.startswith('dill.'):# weird behavior for dill
  639. #print(_str)
  640. try: exec(_str) #XXX: check if == obj? (name collision)
  641. except ImportError: #XXX: better top-down or bottom-up recursion?
  642. _head = head.rsplit(".",1)[0] #(or get all, then compare == obj?)
  643. if not _head: raise
  644. if _head != head:
  645. _str = _getimport(_head, tail, alias, verify)
  646. return _str
  647. #XXX: rename builtin to force? vice versa? verify to force? (as in getsource)
  648. #NOTE: 05/25/14 broke backward compatibility: added 'alias' as 2nd argument
  649. def getimport(obj, alias='', verify=True, builtin=False, enclosing=False):
  650. """get the likely import string for the given object
  651. obj is the object to inspect
  652. If verify=True, then test the import string before returning it.
  653. If builtin=True, then force an import for builtins where possible.
  654. If enclosing=True, get the import for the outermost enclosing callable.
  655. If alias is provided, then rename the object on import.
  656. """
  657. if enclosing:
  658. from .detect import outermost
  659. _obj = outermost(obj)
  660. obj = _obj if _obj else obj
  661. # get the namespace
  662. qual = _namespace(obj)
  663. head = '.'.join(qual[:-1])
  664. tail = qual[-1]
  665. # for named things... with a nice repr #XXX: move into _namespace?
  666. try: # look for '<...>' and be mindful it might be in lists, dicts, etc...
  667. name = repr(obj).split('<',1)[1].split('>',1)[1]
  668. name = None # we have a 'object'-style repr
  669. except Exception: # it's probably something 'importable'
  670. if head in ['builtins','__builtin__']:
  671. name = repr(obj) #XXX: catch [1,2], (1,2), set([1,2])... others?
  672. elif _isinstance(obj):
  673. name = getname(obj, force=True).split('(')[0]
  674. else:
  675. name = repr(obj).split('(')[0]
  676. #if not repr(obj).startswith('<'): name = repr(obj).split('(')[0]
  677. #else: name = None
  678. if name: # try using name instead of tail
  679. try: return _getimport(head, name, alias, verify, builtin)
  680. except ImportError: pass
  681. except SyntaxError:
  682. if head in ['builtins','__builtin__']:
  683. _alias = '%s = ' % alias if alias else ''
  684. if alias == name: _alias = ''
  685. return _alias+'%s\n' % name
  686. else: pass
  687. try:
  688. #if type(obj) is type(abs): _builtin = builtin # BuiltinFunctionType
  689. #else: _builtin = False
  690. return _getimport(head, tail, alias, verify, builtin)
  691. except ImportError:
  692. raise # could do some checking against obj
  693. except SyntaxError:
  694. if head in ['builtins','__builtin__']:
  695. _alias = '%s = ' % alias if alias else ''
  696. if alias == tail: _alias = ''
  697. return _alias+'%s\n' % tail
  698. raise # could do some checking against obj
  699. def _importable(obj, alias='', source=None, enclosing=False, force=True, \
  700. builtin=True, lstrip=True):
  701. """get an import string (or the source code) for the given object
  702. This function will attempt to discover the name of the object, or the repr
  703. of the object, or the source code for the object. To attempt to force
  704. discovery of the source code, use source=True, to attempt to force the
  705. use of an import, use source=False; otherwise an import will be sought
  706. for objects not defined in __main__. The intent is to build a string
  707. that can be imported from a python file. obj is the object to inspect.
  708. If alias is provided, then rename the object with the given alias.
  709. If source=True, use these options:
  710. If enclosing=True, then also return any enclosing code.
  711. If force=True, catch (TypeError,IOError) and try to use import hooks.
  712. If lstrip=True, ensure there is no indentation in the first line of code.
  713. If source=False, use these options:
  714. If enclosing=True, get the import for the outermost enclosing callable.
  715. If force=True, then don't test the import string before returning it.
  716. If builtin=True, then force an import for builtins where possible.
  717. """
  718. if source is None:
  719. source = True if isfrommain(obj) else False
  720. if source: # first try to get the source
  721. try:
  722. return getsource(obj, alias, enclosing=enclosing, \
  723. force=force, lstrip=lstrip, builtin=builtin)
  724. except Exception: pass
  725. try:
  726. if not _isinstance(obj):
  727. return getimport(obj, alias, enclosing=enclosing, \
  728. verify=(not force), builtin=builtin)
  729. # first 'get the import', then 'get the instance'
  730. _import = getimport(obj, enclosing=enclosing, \
  731. verify=(not force), builtin=builtin)
  732. name = getname(obj, force=True)
  733. if not name:
  734. raise AttributeError("object has no atribute '__name__'")
  735. _alias = "%s = " % alias if alias else ""
  736. if alias == name: _alias = ""
  737. return _import+_alias+"%s\n" % name
  738. except Exception: pass
  739. if not source: # try getsource, only if it hasn't been tried yet
  740. try:
  741. return getsource(obj, alias, enclosing=enclosing, \
  742. force=force, lstrip=lstrip, builtin=builtin)
  743. except Exception: pass
  744. # get the name (of functions, lambdas, and classes)
  745. # or hope that obj can be built from the __repr__
  746. #XXX: what to do about class instances and such?
  747. obj = getname(obj, force=force)
  748. # we either have __repr__ or __name__ (or None)
  749. if not obj or obj.startswith('<'):
  750. raise AttributeError("object has no atribute '__name__'")
  751. _alias = '%s = ' % alias if alias else ''
  752. if alias == obj: _alias = ''
  753. return _alias+'%s\n' % obj
  754. #XXX: possible failsafe... (for example, for instances when source=False)
  755. # "import dill; result = dill.loads(<pickled_object>); # repr(<object>)"
  756. def _closuredimport(func, alias='', builtin=False):
  757. """get import for closured objects; return a dict of 'name' and 'import'"""
  758. import re
  759. from .detect import freevars, outermost
  760. free_vars = freevars(func)
  761. func_vars = {}
  762. # split into 'funcs' and 'non-funcs'
  763. for name,obj in list(free_vars.items()):
  764. if not isfunction(obj): continue
  765. # get import for 'funcs'
  766. fobj = free_vars.pop(name)
  767. src = getsource(fobj)
  768. if src.lstrip().startswith('@'): # we have a decorator
  769. src = getimport(fobj, alias=alias, builtin=builtin)
  770. else: # we have to "hack" a bit... and maybe be lucky
  771. encl = outermost(func)
  772. # pattern: 'func = enclosing(fobj'
  773. pat = r'.*[\w\s]=\s*'+getname(encl)+r'\('+getname(fobj)
  774. mod = getname(getmodule(encl))
  775. #HACK: get file containing 'outer' function; is func there?
  776. lines,_ = findsource(encl)
  777. candidate = [line for line in lines if getname(encl) in line and \
  778. re.match(pat, line)]
  779. if not candidate:
  780. mod = getname(getmodule(fobj))
  781. #HACK: get file containing 'inner' function; is func there?
  782. lines,_ = findsource(fobj)
  783. candidate = [line for line in lines \
  784. if getname(fobj) in line and re.match(pat, line)]
  785. if not len(candidate): raise TypeError('import could not be found')
  786. candidate = candidate[-1]
  787. name = candidate.split('=',1)[0].split()[-1].strip()
  788. src = _getimport(mod, name, alias=alias, builtin=builtin)
  789. func_vars[name] = src
  790. if not func_vars:
  791. name = outermost(func)
  792. mod = getname(getmodule(name))
  793. if not mod or name is func: # then it can be handled by getimport
  794. name = getname(func, force=True) #XXX: better key?
  795. src = getimport(func, alias=alias, builtin=builtin)
  796. else:
  797. lines,_ = findsource(name)
  798. # pattern: 'func = enclosing('
  799. candidate = [line for line in lines if getname(name) in line and \
  800. re.match(r'.*[\w\s]=\s*'+getname(name)+r'\(', line)]
  801. if not len(candidate): raise TypeError('import could not be found')
  802. candidate = candidate[-1]
  803. name = candidate.split('=',1)[0].split()[-1].strip()
  804. src = _getimport(mod, name, alias=alias, builtin=builtin)
  805. func_vars[name] = src
  806. return func_vars
  807. #XXX: should be able to use __qualname__
  808. def _closuredsource(func, alias=''):
  809. """get source code for closured objects; return a dict of 'name'
  810. and 'code blocks'"""
  811. #FIXME: this entire function is a messy messy HACK
  812. # - pollutes global namespace
  813. # - fails if name of freevars are reused
  814. # - can unnecessarily duplicate function code
  815. from .detect import freevars
  816. free_vars = freevars(func)
  817. func_vars = {}
  818. # split into 'funcs' and 'non-funcs'
  819. for name,obj in list(free_vars.items()):
  820. if not isfunction(obj):
  821. # get source for 'non-funcs'
  822. free_vars[name] = getsource(obj, force=True, alias=name)
  823. continue
  824. # get source for 'funcs'
  825. fobj = free_vars.pop(name)
  826. src = getsource(fobj, alias) # DO NOT include dependencies
  827. # if source doesn't start with '@', use name as the alias
  828. if not src.lstrip().startswith('@'): #FIXME: 'enclose' in dummy;
  829. src = importable(fobj,alias=name)# wrong ref 'name'
  830. org = getsource(func, alias, enclosing=False, lstrip=True)
  831. src = (src, org) # undecorated first, then target
  832. else: #NOTE: reproduces the code!
  833. org = getsource(func, enclosing=True, lstrip=False)
  834. src = importable(fobj, alias, source=True) # include dependencies
  835. src = (org, src) # target first, then decorated
  836. func_vars[name] = src
  837. src = ''.join(free_vars.values())
  838. if not func_vars: #FIXME: 'enclose' in dummy; wrong ref 'name'
  839. org = getsource(func, alias, force=True, enclosing=False, lstrip=True)
  840. src = (src, org) # variables first, then target
  841. else:
  842. src = (src, None) # just variables (better '' instead of None?)
  843. func_vars[None] = src
  844. # FIXME: remove duplicates (however, order is important...)
  845. return func_vars
  846. def importable(obj, alias='', source=None, builtin=True):
  847. """get an importable string (i.e. source code or the import string)
  848. for the given object, including any required objects from the enclosing
  849. and global scope
  850. This function will attempt to discover the name of the object, or the repr
  851. of the object, or the source code for the object. To attempt to force
  852. discovery of the source code, use source=True, to attempt to force the
  853. use of an import, use source=False; otherwise an import will be sought
  854. for objects not defined in __main__. The intent is to build a string
  855. that can be imported from a python file.
  856. obj is the object to inspect. If alias is provided, then rename the
  857. object with the given alias. If builtin=True, then force an import for
  858. builtins where possible.
  859. """
  860. #NOTE: we always 'force', and 'lstrip' as necessary
  861. #NOTE: for 'enclosing', use importable(outermost(obj))
  862. if source is None:
  863. source = True if isfrommain(obj) else False
  864. elif builtin and isbuiltin(obj):
  865. source = False
  866. tried_source = tried_import = False
  867. while True:
  868. if not source: # we want an import
  869. try:
  870. if _isinstance(obj): # for instances, punt to _importable
  871. return _importable(obj, alias, source=False, builtin=builtin)
  872. src = _closuredimport(obj, alias=alias, builtin=builtin)
  873. if len(src) == 0:
  874. raise NotImplementedError('not implemented')
  875. if len(src) > 1:
  876. raise NotImplementedError('not implemented')
  877. return list(src.values())[0]
  878. except Exception:
  879. if tried_source: raise
  880. tried_import = True
  881. # we want the source
  882. try:
  883. src = _closuredsource(obj, alias=alias)
  884. if len(src) == 0:
  885. raise NotImplementedError('not implemented')
  886. # groan... an inline code stitcher
  887. def _code_stitcher(block):
  888. "stitch together the strings in tuple 'block'"
  889. if block[0] and block[-1]: block = '\n'.join(block)
  890. elif block[0]: block = block[0]
  891. elif block[-1]: block = block[-1]
  892. else: block = ''
  893. return block
  894. # get free_vars first
  895. _src = _code_stitcher(src.pop(None))
  896. _src = [_src] if _src else []
  897. # get func_vars
  898. for xxx in src.values():
  899. xxx = _code_stitcher(xxx)
  900. if xxx: _src.append(xxx)
  901. # make a single source string
  902. if not len(_src):
  903. src = ''
  904. elif len(_src) == 1:
  905. src = _src[0]
  906. else:
  907. src = '\n'.join(_src)
  908. # get source code of objects referred to by obj in global scope
  909. from .detect import globalvars
  910. obj = globalvars(obj) #XXX: don't worry about alias? recurse? etc?
  911. obj = list(getsource(_obj,name,force=True) for (name,_obj) in obj.items() if not isbuiltin(_obj))
  912. obj = '\n'.join(obj) if obj else ''
  913. # combine all referred-to source (global then enclosing)
  914. if not obj: return src
  915. if not src: return obj
  916. return obj + src
  917. except Exception:
  918. if tried_import: raise
  919. tried_source = True
  920. source = not source
  921. # should never get here
  922. return
  923. # backward compatibility
  924. def getimportable(obj, alias='', byname=True, explicit=False):
  925. return importable(obj,alias,source=(not byname),builtin=explicit)
  926. #return outdent(_importable(obj,alias,source=(not byname),builtin=explicit))
  927. def likely_import(obj, passive=False, explicit=False):
  928. return getimport(obj, verify=(not passive), builtin=explicit)
  929. def _likely_import(first, last, passive=False, explicit=True):
  930. return _getimport(first, last, verify=(not passive), builtin=explicit)
  931. _get_name = getname
  932. getblocks_from_history = getblocks
  933. # EOF