On May 7, 7:59 pm, [EMAIL PROTECTED] wrote: > On May 7, 6:52 pm, [EMAIL PROTECTED] wrote: > > > > > Presents a console permitting inspection. Input as well as output > > saved in Python-readable form. > > Python 2.5.1 memoryconsole4.py logging to My Documents\console.log>>> class > > A: > > > ... def f( self ): > > ... print 2 > > ...>>> a=A() > > >>> import inspect > > >>> inspect.getsource( a.f ) > > > '\tdef f( self ):\n\t\tprint 2\n' > > > This enabled by a log file, optionally set to console.log. Contents > > are: > > > #Mon May 07 2007 06:33:42 PM Python win32 2.5.1 in memoryconsole4.py > > class A: > > def f( self ): > > print 2 > > > a=A() > > import inspect > > inspect.getsource( a.f ) > > #fb: '\tdef f( self ):\n\t\tprint 2\n' > > > Line 10 Microsoft Win32 convenience binding; line 49 a little > > confusing. Give it a shot. > > > from code import InteractiveConsole > > import sys > > from os import environ > > from datetime import datetime > > from StringIO import StringIO > > from re import sub > > from os.path import join,split,abspath > > > class LoggedStdOut(StringIO): > > deflog= environ['USERPROFILE']+\ > > '\\My Documents\\console.log' > > def __init__( self, log=None ): > > StringIO.__init__( self ) > > self.stdout= None > > self.trip,self.head= True,'' > > self.logname= log or LoggedStdOut.deflog > > self.prettyname=join(split(split(abspath( > > > > self.logname))[0])[1],split(abspath(self.logname))[1]) > > for x,_ in enumerate( open( self.logname,'r' ) ): continue > > self._lineno= x #can use linecache > > self._log= open( self.logname,'a' ) > > def catch( self,head='#fb: ' ): > > self.stdout= sys.stdout > > sys.stdout= self > > self.head= head > > self.trip= True > > def throw( self ): > > sys.stdout= self.stdout > > self.stdout= None > > def getlineno( self ): > > return self._lineno > > def logwrite( self, data ): > > self._log.write( data ) > > self._lineno+= data.count('\n') > > def logflush( self ): > > self._log.flush() > > def write( self, data ): > > datal= sub( '\n([^$])','\n%s\\1'%self.head,data ) > > if self.trip: self.logwrite( self.head ) > > self.logwrite( datal ) > > self.trip= data.endswith('\n') > > return self.stdout.write( data ) > > def writelines( self, data ): > > raise 'Branch uncoded' > > > class LoggedInteractiveConsole(InteractiveConsole): > > def __init__( self,log=None,locals=None,filename=None ): > > self.out= LoggedStdOut( log ) > > if filename is None: filename= split(self.out.logname)[1] > > InteractiveConsole.__init__( self,locals,filename ) > > self.locals.update( __logname__= abspath( > > self.out.logname ) ) > > def push( self,line ): > > self.out.logwrite( '%s\n'%line ) > > self.out.logflush() > > self.out.catch() > > more= InteractiveConsole.push( self,line ) > > self.out.throw() > > return more > > def write( self,data ): > > return sys.stdout.write( data ) > > def interact( self,banner=None,*args ): > > self.out.logwrite( '\n#%s Python %s %s in %s\n'%\ > > ( datetime.now().strftime( > > '%a %b %d %Y %I:%M:%S %p' ), > > sys.platform,sys.version.split()[0], > > split(sys.argv[0])[1] ) ) > > if banner is None: banner=\ > > "Python %s %s logging to %s"%\ > > ( sys.version.split()[0],split(sys.argv[0])[1], > > self.out.prettyname ) > > return InteractiveConsole.interact( self,banner,*args ) > > > import compiler > > import linecache > > class NotatedConsole(LoggedInteractiveConsole): > > """-Code object- intercepted in runsource, and rerun with > > stored source before runsource. Built-in runsource > > does not modify source between call and runcode.""" > > def runsource( self,sc,filename='<input>',*args ): > > self._runsourceargs= sc,filename > > return LoggedInteractiveConsole.runsource( self,sc, > > filename,*args ) > > def runcode( self,*args ): > > sc,filename= self._runsourceargs > > linecache.checkcache( filename ) > > #custom second compile (fourth actually) > > t= compiler.parse( sc ) > > compiler.misc.set_filename( filename,t ) > > def set_lineno( tree, initlineno ): > > worklist= [ tree ] > > while worklist: > > node= worklist.pop( 0 ) > > if node.lineno is not None: > > node.lineno+= initlineno > > worklist.extend( node.getChildNodes() ) > > set_lineno( t,self.out.getlineno()-len( self.buffer )+1 ) > > code= compiler.pycodegen.\ > > InteractiveCodeGenerator( t ).getCode() > > LoggedInteractiveConsole.runcode( self,code ) > > linecache.checkcache( filename ) > > > if __name__=='__main__': > > console= NotatedConsole() > > console.interact() > > Console-defined objects can be pickled as well. ">>>edit()" opens > console.log. Editor objects are pickled between statements. > > Python 2.5.1 furtherconsoles-display.py logging to My Documents > \console.log>>> class A: > > ... b=0 > ...>>> from pickle import loads,dumps > >>> loads(dumps(A)) > > <class workmodule.A at 0x00B28030>>>> loads(dumps(A)).b > 0 > >>> edit() > > Loaded ok > > and the few lines from console.log: > #Mon May 07 2007 07:55:30 PM Python win32 2.5.1 in furtherconsoles- > display.py > class A: > b=0 > > from pickle import loads,dumps > loads(dumps(A)) > #fb: <class workmodule.A at 0x00B28030> > loads(dumps(A)).b > #fb: 0 > edit() > > Hard coded paths on lines 24 and 67. Hope that's copy-and-pasteable > > import memoryconsole4 as memoryconsole > from os.path import join,exists,split,abspath > from os import environ > from sys import argv > import sys > import cPickle as pickle > from subprocess import Popen > from datetime import datetime,timedelta > > class Editors: > """Pickled after every statement.""" > def edit( self,filename=None ): > assert hasattr( self,'_cmdlinestr' ) and hasattr( > self,'console' ) > if filename is None: filename= abspath( > self.console.out.logname ) > parms= { 'filename': filename, 'loglen': > self.console.out.getlineno() > +len(self.console.buffer)+1 } > Popen( self._cmdlinestr % parms ) > print >>sys.stderr, "Loaded ok" > def __repr__( self ): > return '<%s at %i: %s>'%(self.__class__,id(self),repr( [ x > for x in > dir(self) if not x.startswith('__') ] )) > def __call__( self,*args ): > self.edit( *args )#what find default? > > class EditorsConsole(memoryconsole.NotatedConsole): > defdat= join( environ['USERPROFILE'],'My Documents\ > \consoleeditor.pickle' ) > def __init__( self,cmdlinestr,datname=None,*args,**kwargs ): > memoryconsole.NotatedConsole.__init__( self,*args,**kwargs ) > self._datname= datname or self.defdat > if exists( self._datname ): self.edit= > pickle.load( open( self._datname,'rb' ) ) > else: self.edit= Editors() > self.edit._cmdlinestr= cmdlinestr > self.locals.update( edit=self.edit ) > self.edit.console= self > self.lasttimestamp= datetime.now() > def push( self,*args ): > more= memoryconsole.NotatedConsole.push( self,*args ) > if not more and datetime.now()- self.lasttimestamp > > timedelta( minutes= 25 ): > self.lasttimestamp= datetime.now() > self.out.logwrite( '#%s in %s\n'%\ > ( self.lasttimestamp.strftime( '%a %b %d %Y > %I:%M:%S > %p' ),split(argv[0])[1] ) ) > del self.edit.console > pickle.dump( self.edit,open( self._datname,'wb' ) ) #don't > pickle me > self.edit.console= self > return more > def __repr__( self ): > return '<%s at %i: %s>'%(self.__class__,id(self),repr( [ x > for x in > dir(self) if not x.startswith('__') ] )) > > import compiler as c > from memory import Memory > import imp > from sys import modules > > class ModuleConsole(EditorsConsole): > def __init__( self,log=None,locals=None,filename=None ): > EditorsConsole.__init__( self,log,locals,filename ) > self.workmodule= imp.new_module( 'workmodule' ) > self.workmodule.__file__= self.out.logname > modules[self.workmodule.__name__]= self.workmodule > self.locals.update( workmodule=self.workmodule, > __name__=self.workmodule.__name__ ) > self.locals.update( __file__=self.workmodule.__file__ )#may > omit > __logname__ > del self.locals['__logname__'] > def runcode( self,*args ): > EditorsConsole.runcode( self,*args ) > for k,v in self.locals.iteritems(): > setattr( self.workmodule,k,v ) > > if __name__=='__main__': > editorscmdlinestr= '"%s" "%%(filename)s" -cursor %%(loglen)i: > 1'%join(environ['PROGRAMFILES'],'editplus 2\\editplus.exe') > console= ModuleConsole(editorscmdlinestr) > console.interact()
whoops, that line 48 is extraneous. -- http://mail.python.org/mailman/listinfo/python-list