102 lines
3.0 KiB
Python
102 lines
3.0 KiB
Python
|
"""Remote
|
||
|
This module is imported by the loader and serves to control
|
||
|
the execution of the user program. It presently executes files
|
||
|
and reports exceptions to IDLE. It could be extended to provide
|
||
|
other services, such as interactive mode and debugging. To that
|
||
|
end, it could be a subclass of e.g. InteractiveInterpreter.
|
||
|
|
||
|
Two other classes, pseudoIn and pseudoOut, are file emulators also
|
||
|
used by loader.
|
||
|
"""
|
||
|
import sys, os
|
||
|
import traceback
|
||
|
|
||
|
class Remote:
|
||
|
def __init__(self, main, master):
|
||
|
self.main = main
|
||
|
self.master = master
|
||
|
self.this_file = self.canonic( self.__init__.im_func.func_code.co_filename )
|
||
|
|
||
|
def canonic(self, path):
|
||
|
return os.path.normcase(os.path.abspath(path))
|
||
|
|
||
|
def mainloop(self):
|
||
|
while 1:
|
||
|
args = self.master.get_command()
|
||
|
|
||
|
try:
|
||
|
f = getattr(self,args[0])
|
||
|
apply(f,args[1:])
|
||
|
except:
|
||
|
if not self.report_exception(): raise
|
||
|
|
||
|
def finish(self):
|
||
|
sys.exit()
|
||
|
|
||
|
def run(self, *argv):
|
||
|
sys.argv = argv
|
||
|
|
||
|
path = self.canonic( argv[0] )
|
||
|
dir = self.dir = os.path.dirname(path)
|
||
|
os.chdir(dir)
|
||
|
|
||
|
sys.path[0] = dir
|
||
|
|
||
|
usercode = open(path)
|
||
|
exec usercode in self.main
|
||
|
|
||
|
def report_exception(self):
|
||
|
try:
|
||
|
type, value, tb = sys.exc_info()
|
||
|
sys.last_type = type
|
||
|
sys.last_value = value
|
||
|
sys.last_traceback = tb
|
||
|
|
||
|
tblist = traceback.extract_tb(tb)
|
||
|
|
||
|
# Look through the traceback, canonicalizing filenames and
|
||
|
# eliminating leading and trailing system modules.
|
||
|
first = last = 1
|
||
|
for i in range(len(tblist)):
|
||
|
filename, lineno, name, line = tblist[i]
|
||
|
filename = self.canonic(filename)
|
||
|
tblist[i] = filename, lineno, name, line
|
||
|
|
||
|
dir = os.path.dirname(filename)
|
||
|
if filename == self.this_file:
|
||
|
first = i+1
|
||
|
elif dir==self.dir:
|
||
|
last = i+1
|
||
|
|
||
|
# Canonicalize the filename in a syntax error, too:
|
||
|
if type is SyntaxError:
|
||
|
try:
|
||
|
msg, (filename, lineno, offset, line) = value
|
||
|
filename = self.canonic(filename)
|
||
|
value = msg, (filename, lineno, offset, line)
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
return self.master.program_exception( type, value, tblist, first, last )
|
||
|
finally:
|
||
|
# avoid any circular reference through the traceback
|
||
|
del tb
|
||
|
|
||
|
class pseudoIn:
|
||
|
def __init__(self, readline):
|
||
|
self.readline = readline
|
||
|
def isatty():
|
||
|
return 1
|
||
|
|
||
|
class pseudoOut:
|
||
|
def __init__(self, func, **kw):
|
||
|
self.func = func
|
||
|
self.kw = kw
|
||
|
def write(self, *args):
|
||
|
return apply( self.func, args, self.kw )
|
||
|
def writelines(self, l):
|
||
|
map(self.write, l)
|
||
|
def flush(self):
|
||
|
pass
|
||
|
|