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()

-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to