/trunk/sleepy/__init__.py
https://bitbucket.org/tenuki/sleepy · Python · 251 lines · 191 code · 47 blank · 13 comment · 29 complexity · 131e6713903b7923a2246e5a24e4f0ab MD5 · raw file
- #!/usr/bin/env python
- from __future__ import with_statement
- import sys
- import types
- import pickle
- import bdb
- import time
- import traceback
-
- from sleepy.imports import Importer
- from sleepy.other import show_tabbed, tofname
- from sleepy.restore import Event, Line, Call, AnyLine, AnyEvent, Do, DoMultiple, DoExit, DoJump, DoFrameUpdate
- from sleepy.iterator import Iterator
-
-
- class Commands:
- CMD_TRACE = "trace"
- CMD_RUN = "run"
-
- class DontLoad:
- pass
-
-
- class StackChain(object):
- def __init__(self, framelist):
- self.frames = framelist[2:]
- def __str__(self):
- return '\r\n'.join(str(frame) for frame in self.frames)
-
- def test_save(self, f):
- def test_(x):
- try:
- pickle.dumps(x)
- except:
- return False
- return True
-
- result = test_(f)
- if not result:
- for name, value in f.f_locals.items():
- if not test_(value):
- print 'failing to save:', name
- f.f_locals.__delitem__(name)
-
- def save(self):
- with open("dump.pck", "wb") as f:
- for xframe in self.frames:
- self.test_save(xframe)
- pickle.dump(self, f)
- print '-------------------------------------------------------'
-
- @classmethod
- def Load(cls):
- debug = True
- with open("dump.pck", "rb") as f:
- if debug:
- class Unpickler(pickle.Unpickler):
- def find_class(self, module, name):
- if module=="__main__":
- module='recipe578278'
- return pickle.Unpickler.find_class(self, module, name)
- def load(file):
- return Unpickler(file).load()
- return load(f)
- else:
- return pickle.load(f)
-
-
- class StackFrame(object):
- NotModule = staticmethod(lambda x:type(x)!=types.ModuleType)
- def __init__(self, frame):
- #'f_back','f_builtins', 'f_code', 'f_exc_traceback', 'f_exc_type',
- #'f_exc_value','f_globals', 'f_lasti', 'f_lineno', 'f_locals',
- #'f_restricted', 'f_trace'
- self.f_lasti = frame.f_lasti
- self.f_lineno = frame.f_lineno
- self.f_locals = dict([(key, value)
- for key, value in frame.f_locals.items()
- if StackFrame.NotModule(value)])
- #self.f_globals = dict([(key, value) for key, value in frame.f_globals.items()
- # if StackFrame.NotModule(value)])
- #self.f_builtins = dict([(key, value) for key, value in frame.f_builtins.items()
- # if StackFrame.NotModule(value)])
- self.f_code_filename = frame.f_code.co_filename
-
- @classmethod
- def Chain(cls, aFrame):
- rev = []
- while aFrame != None:
- rev.append(cls(aFrame))
- aFrame = aFrame.f_back
- return StackChain(rev[::-1])
-
- def __str__(self):
- _locals = (','.join(self.f_locals.keys()))[:25]
- return '\t<%s:%d(%d) (%s)>' % (self.filename, self.f_lineno,
- self.f_lasti, _locals)
-
- @property
- def filename(self):
- return self.f_code_filename
-
-
- class Tracer(bdb.Bdb):
- #def do_clear(self, arg):
- # pass
- def __init__(self, controller, *args, **kw):
- bdb.Bdb.__init__(self, *args, **kw)
- self.controller = controller
- self._already_loaded = {} # modname:set([symbols_parsed..])
- def user_call(self, frame, argument_list):
- """This method is called when there is the remote possibility
- that we ever need to stop in this function."""
- pass #frame = StackFrame(frame)
- def user_line(self, frame):
- """This method is called when we stop or break at this line."""
- pass #frame = StackFrame(frame)
-
-
- class Singleton:
- started = time.time()
- @classmethod
- def reset(cls):
- cls.started = time.time()
-
- _ALREADY = False
-
- def CheckSuspend():
- global _ALREADY
-
- def dump_state(frame, *args, **kw):
- print 'getting state from:',frame
- sc = StackFrame.Chain(frame)
- print str(sc)
- try:
- sc.save()
- except:
- traceback.print_exc()
- sys.exit(-5)
-
- def check_state(frame, *args, **kw):
- global _ALREADY
- now = time.time()
- mustSchedule = now - Singleton.started > 5
- if mustSchedule and not _ALREADY:
- _ALREADY = True
- sys.settrace(dump_state)
- return check_state
-
- sys.settrace(check_state)
- return True
-
-
-
- class TracerPrg(object):
- def __init__(self, fname):
- self.fname = fname
-
- def run(self):
- self.bdb = Tracer(self)
- m = 'sleepy.imports'
- self.bdb.run("import %s;%s.Install()"%(m, m))
- trigger = "import %s;%s.main()" % (self.fname, self.fname)
- return self.bdb.run(trigger)
-
-
- def show(frame):
- return frame.f_code.co_filename, frame.f_lineno
-
-
- class Restorer(object):
- def __init__(self, sc):
- self.sc = sc
- self.last = 0
- self.done = False
- self.wait = wait = []
- for idx, frame in enumerate(sc.frames[1:]):
- print 'frame:', frame
- if idx ==0:
- wait.append(
- (Line(frame.f_code_filename, frame.f_lineno), None) )
- else:
- if frame.f_lasti == -1:
- break
- wait.append( (Call(frame.f_code_filename),None) )
- wait.append( ( AnyLine(frame.f_code_filename),
- DoMultiple(DoJump(frame.f_lineno),
- DoFrameUpdate(frame.f_locals)
- )
- )
- )
-
- def __str__(self):
- return'\r\n'.join('%30s -> %r'%x for x in self.wait)
-
- def restorer(self, frame, event, *args, **kw):
- if self.done:
- if 0:
- print '*****', self.on(frame, event), repr(args), repr(kw)
- print frame.f_locals.keys()
- sys.settrace(None)
- return None
- tester, do = self.wait[self.last]
-
- self.show(frame, event, self.last, tester)
-
- match = tester._test(frame, event, *args, **kw)
- print match
- if match:
- if do:
- do.do(frame)
- self.last += 1
-
- if self.last>=len(self.wait):
- print '\t\t\twe are done!!!1'
- Singleton.reset()
- self.done = True
- return None
- return self.restorer
-
- def show(self, frame, event, last=None, tester=None):
- print "%10s %20s:%3d"%(event, tofname(frame.f_code.co_filename),
- frame.f_lineno),
- if not last is None:
- print ' - ', last, tester,
-
-
- def main(fname):
- imports.Install()
- exec "import %s;%s.main()"%(fname, fname)
-
-
- def main_restore(fname):
- imports.Install()
- sc = StackChain.Load()
- print 'restoring:'
- show_tabbed(str(sc),1)
- print
-
- print 'running:'
- res = Restorer(sc)
- show_tabbed(str(res),1)
- print
-
- sys.settrace(res.restorer)
- trigger = "import %s;%s.main()"%(fname, fname)
- print 'tracing:', trigger
- exec trigger