PageRenderTime 46ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/sleepy/__init__.py

https://bitbucket.org/tenuki/sleepy
Python | 251 lines | 191 code | 47 blank | 13 comment | 29 complexity | 131e6713903b7923a2246e5a24e4f0ab MD5 | raw file
  1. #!/usr/bin/env python
  2. from __future__ import with_statement
  3. import sys
  4. import types
  5. import pickle
  6. import bdb
  7. import time
  8. import traceback
  9. from sleepy.imports import Importer
  10. from sleepy.other import show_tabbed, tofname
  11. from sleepy.restore import Event, Line, Call, AnyLine, AnyEvent, Do, DoMultiple, DoExit, DoJump, DoFrameUpdate
  12. from sleepy.iterator import Iterator
  13. class Commands:
  14. CMD_TRACE = "trace"
  15. CMD_RUN = "run"
  16. class DontLoad:
  17. pass
  18. class StackChain(object):
  19. def __init__(self, framelist):
  20. self.frames = framelist[2:]
  21. def __str__(self):
  22. return '\r\n'.join(str(frame) for frame in self.frames)
  23. def test_save(self, f):
  24. def test_(x):
  25. try:
  26. pickle.dumps(x)
  27. except:
  28. return False
  29. return True
  30. result = test_(f)
  31. if not result:
  32. for name, value in f.f_locals.items():
  33. if not test_(value):
  34. print 'failing to save:', name
  35. f.f_locals.__delitem__(name)
  36. def save(self):
  37. with open("dump.pck", "wb") as f:
  38. for xframe in self.frames:
  39. self.test_save(xframe)
  40. pickle.dump(self, f)
  41. print '-------------------------------------------------------'
  42. @classmethod
  43. def Load(cls):
  44. debug = True
  45. with open("dump.pck", "rb") as f:
  46. if debug:
  47. class Unpickler(pickle.Unpickler):
  48. def find_class(self, module, name):
  49. if module=="__main__":
  50. module='recipe578278'
  51. return pickle.Unpickler.find_class(self, module, name)
  52. def load(file):
  53. return Unpickler(file).load()
  54. return load(f)
  55. else:
  56. return pickle.load(f)
  57. class StackFrame(object):
  58. NotModule = staticmethod(lambda x:type(x)!=types.ModuleType)
  59. def __init__(self, frame):
  60. #'f_back','f_builtins', 'f_code', 'f_exc_traceback', 'f_exc_type',
  61. #'f_exc_value','f_globals', 'f_lasti', 'f_lineno', 'f_locals',
  62. #'f_restricted', 'f_trace'
  63. self.f_lasti = frame.f_lasti
  64. self.f_lineno = frame.f_lineno
  65. self.f_locals = dict([(key, value)
  66. for key, value in frame.f_locals.items()
  67. if StackFrame.NotModule(value)])
  68. #self.f_globals = dict([(key, value) for key, value in frame.f_globals.items()
  69. # if StackFrame.NotModule(value)])
  70. #self.f_builtins = dict([(key, value) for key, value in frame.f_builtins.items()
  71. # if StackFrame.NotModule(value)])
  72. self.f_code_filename = frame.f_code.co_filename
  73. @classmethod
  74. def Chain(cls, aFrame):
  75. rev = []
  76. while aFrame != None:
  77. rev.append(cls(aFrame))
  78. aFrame = aFrame.f_back
  79. return StackChain(rev[::-1])
  80. def __str__(self):
  81. _locals = (','.join(self.f_locals.keys()))[:25]
  82. return '\t<%s:%d(%d) (%s)>' % (self.filename, self.f_lineno,
  83. self.f_lasti, _locals)
  84. @property
  85. def filename(self):
  86. return self.f_code_filename
  87. class Tracer(bdb.Bdb):
  88. #def do_clear(self, arg):
  89. # pass
  90. def __init__(self, controller, *args, **kw):
  91. bdb.Bdb.__init__(self, *args, **kw)
  92. self.controller = controller
  93. self._already_loaded = {} # modname:set([symbols_parsed..])
  94. def user_call(self, frame, argument_list):
  95. """This method is called when there is the remote possibility
  96. that we ever need to stop in this function."""
  97. pass #frame = StackFrame(frame)
  98. def user_line(self, frame):
  99. """This method is called when we stop or break at this line."""
  100. pass #frame = StackFrame(frame)
  101. class Singleton:
  102. started = time.time()
  103. @classmethod
  104. def reset(cls):
  105. cls.started = time.time()
  106. _ALREADY = False
  107. def CheckSuspend():
  108. global _ALREADY
  109. def dump_state(frame, *args, **kw):
  110. print 'getting state from:',frame
  111. sc = StackFrame.Chain(frame)
  112. print str(sc)
  113. try:
  114. sc.save()
  115. except:
  116. traceback.print_exc()
  117. sys.exit(-5)
  118. def check_state(frame, *args, **kw):
  119. global _ALREADY
  120. now = time.time()
  121. mustSchedule = now - Singleton.started > 5
  122. if mustSchedule and not _ALREADY:
  123. _ALREADY = True
  124. sys.settrace(dump_state)
  125. return check_state
  126. sys.settrace(check_state)
  127. return True
  128. class TracerPrg(object):
  129. def __init__(self, fname):
  130. self.fname = fname
  131. def run(self):
  132. self.bdb = Tracer(self)
  133. m = 'sleepy.imports'
  134. self.bdb.run("import %s;%s.Install()"%(m, m))
  135. trigger = "import %s;%s.main()" % (self.fname, self.fname)
  136. return self.bdb.run(trigger)
  137. def show(frame):
  138. return frame.f_code.co_filename, frame.f_lineno
  139. class Restorer(object):
  140. def __init__(self, sc):
  141. self.sc = sc
  142. self.last = 0
  143. self.done = False
  144. self.wait = wait = []
  145. for idx, frame in enumerate(sc.frames[1:]):
  146. print 'frame:', frame
  147. if idx ==0:
  148. wait.append(
  149. (Line(frame.f_code_filename, frame.f_lineno), None) )
  150. else:
  151. if frame.f_lasti == -1:
  152. break
  153. wait.append( (Call(frame.f_code_filename),None) )
  154. wait.append( ( AnyLine(frame.f_code_filename),
  155. DoMultiple(DoJump(frame.f_lineno),
  156. DoFrameUpdate(frame.f_locals)
  157. )
  158. )
  159. )
  160. def __str__(self):
  161. return'\r\n'.join('%30s -> %r'%x for x in self.wait)
  162. def restorer(self, frame, event, *args, **kw):
  163. if self.done:
  164. if 0:
  165. print '*****', self.on(frame, event), repr(args), repr(kw)
  166. print frame.f_locals.keys()
  167. sys.settrace(None)
  168. return None
  169. tester, do = self.wait[self.last]
  170. self.show(frame, event, self.last, tester)
  171. match = tester._test(frame, event, *args, **kw)
  172. print match
  173. if match:
  174. if do:
  175. do.do(frame)
  176. self.last += 1
  177. if self.last>=len(self.wait):
  178. print '\t\t\twe are done!!!1'
  179. Singleton.reset()
  180. self.done = True
  181. return None
  182. return self.restorer
  183. def show(self, frame, event, last=None, tester=None):
  184. print "%10s %20s:%3d"%(event, tofname(frame.f_code.co_filename),
  185. frame.f_lineno),
  186. if not last is None:
  187. print ' - ', last, tester,
  188. def main(fname):
  189. imports.Install()
  190. exec "import %s;%s.main()"%(fname, fname)
  191. def main_restore(fname):
  192. imports.Install()
  193. sc = StackChain.Load()
  194. print 'restoring:'
  195. show_tabbed(str(sc),1)
  196. print
  197. print 'running:'
  198. res = Restorer(sc)
  199. show_tabbed(str(res),1)
  200. print
  201. sys.settrace(res.restorer)
  202. trigger = "import %s;%s.main()"%(fname, fname)
  203. print 'tracing:', trigger
  204. exec trigger