home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Python 1.4 / twit / TwitCore.py < prev    next >
Encoding:
Python Source  |  1996-09-26  |  13.6 KB  |  551 lines  |  [TEXT/Pyth]

  1. # Window-interface-independent part of twit
  2. import sys
  3. import types
  4. import bdb
  5. import types
  6. import os
  7.  
  8. SIMPLE_TYPES=(
  9.     types.NoneType,
  10.     types.IntType,
  11.     types.LongType,
  12.     types.FloatType,
  13.     types.ComplexType,
  14.     types.StringType
  15. )
  16.  
  17. # XXXX Mac-specific
  18. ICON_NORMAL=512
  19. ICON_RETURN=515
  20. ICON_CALL=516
  21. ICON_ZERO=517
  22. ICON_DEAD=518
  23.  
  24. class DebuggerStuff(bdb.Bdb):
  25.  
  26.     def __init__(self, parent):
  27.         bdb.Bdb.__init__(self)
  28.         self.parent = parent
  29.         self.exception_info = (None, None)
  30.         self.reason = 'Not running'
  31.         self.icon = ICON_NORMAL
  32.         self.reset()
  33.         
  34.     def reset(self):
  35.         bdb.Bdb.reset(self)
  36.         self.forget()
  37.     
  38.     def forget(self):
  39.         self.lineno = None
  40.         self.stack = []
  41.         self.curindex = 0
  42.         self.curframe = None
  43.         
  44.     def run(self, cmd, locals, globals):
  45.         self.reason = 'Running'
  46.         bdb.Bdb.run(self, cmd, locals, globals)
  47.         print 'RETURN from run'
  48.         self.reason = 'Not running'
  49.     
  50.     def setup(self, f, t):
  51.         self.forget()
  52.         self.stack, self.curindex = self.get_stack(f, t)
  53.         self.curframe = self.stack[self.curindex][0]
  54.         
  55.     def interaction(self, frame, traceback):
  56.         self.setup(frame, traceback)
  57.         self.parent.interact()
  58.         self.exception_info = (None, None)
  59.  
  60. #    def user_call(self, frame, argument_list):
  61. #        self.reason = 'Calling'
  62. #        self.icon = ICON_CALL
  63. #        self.interaction(frame, None)
  64.             
  65.     def user_line(self, frame):
  66.         self.reason = 'Stopped'
  67.         self.icon = ICON_NORMAL
  68.         self.interaction(frame, None)
  69.         
  70.     def user_return(self, frame, return_value):
  71.         self.reason = 'Returning'
  72.         self.icon = ICON_RETURN
  73.         self.interaction(frame, None)
  74.                 
  75.     def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
  76.         self.reason = 'Exception occurred'
  77.         self.icon = ICON_DEAD
  78.         self.parent.setstate('tb')
  79.         self.exception_info = (exc_type, exc_value)
  80.         self.interaction(frame, exc_traceback)
  81.  
  82.     def getexception(self):
  83.         tp, value = self.exception_info
  84.         if tp <> None and type(tp) <> type(''):
  85.             tp = tp.__name__
  86.         if value <> None and type(value) <> type(''):
  87.             value = `value`
  88.         return tp, value
  89.         
  90.     def getstacktrace(self):
  91.         names, locations = [], []
  92.         for frame, lineno in self.stack:
  93.             name = frame.f_code.co_name
  94.             if not name:
  95.                 name = "<lambda>"
  96.             elif name == '?': 
  97.                 name = "<not a function>"
  98.             else:
  99.                 name = name + '()'
  100.             names.append(name)
  101.             
  102.             if lineno == -1:
  103.                 lineno = getframelineno(frame)
  104.                 
  105.             modname = getframemodname(frame)
  106.             if not modname: modname = "<unknown>"    
  107.  
  108.             locations.append("%s:%d" % (modname, lineno))
  109.         return names, locations
  110.         
  111.     def getframe(self, number):
  112.         if number < 0 or number >= len(self.stack):
  113.             return None
  114.         return self.stack[number][0]
  115.  
  116.     def getframevars(self, number, show_complex=1, show_system=1):
  117.         frame = self.getframe(number)
  118.         if not frame:
  119.             return [], []
  120.         return getvarsfromdict(frame.f_locals, show_complex, show_system)
  121.         
  122.     def getframevar(self, number, var):
  123.         frame = self.getframe(number)
  124.         return frame.f_locals[var]
  125.  
  126.     def getframefilepos(self, frameno):
  127.         if frameno == None or frameno < 0 or frameno >= len(self.stack):
  128.             return None, None, None
  129.         frame, line = self.stack[frameno]
  130.         if line == -1:
  131.             line = getframelineno(frame)
  132.         modname = getframemodname(frame)
  133.         filename = frame.f_code.co_filename
  134.         return filename, modname, line
  135.  
  136.     def getprogramstate(self):
  137.         return self.reason
  138.     
  139. class Application:
  140.     """Base code for the application"""
  141.     
  142.     def mi_init(self, sessiontype, arg):
  143.         self.dbg = DebuggerStuff(self)
  144.         self.run_dialog = self.new_stack_browser(self)
  145.         self.run_dialog.open()
  146.         self.module_dialog = None
  147.         self.initial_cmd = None
  148.         self.cur_string_name = None
  149.         if sessiontype == 'tb':
  150.             while arg.tb_next <> None:
  151.                 arg = arg.tb_next
  152.             self.dbg.setup(arg.tb_frame, arg)
  153.             self.run_dialog.setup()
  154.         elif sessiontype == 'run':
  155.             self.initial_cmd = arg
  156.             
  157.     def breaks_changed(self, filename):
  158.         self.run_dialog.breaks_changed(filename)
  159.         if self.module_dialog:
  160.             self.module_dialog.breaks_changed(filename)
  161.     
  162.     def to_debugger(self):
  163.         cmd = self.initial_cmd
  164.         self.initial_cmd = None
  165.         self.setstate('run')
  166.         self.switch_to_app()
  167.         apply(self.dbg.run, cmd)
  168.         self.setstate('none')
  169.         self.switch_to_dbg()
  170.         self.run_dialog.update_views()
  171.         if self.module_dialog:
  172.             self.module_dialog.update_views()
  173.         
  174.     def interact(self):
  175.         # Interact with user. First, display correct info
  176.         self.switch_to_dbg()
  177.         self.run_dialog.update_views()
  178.         if self.module_dialog:
  179.             self.module_dialog.update_views()
  180.         
  181.         # Next, go into mainloop
  182.         self.one_mainloop()
  183.         
  184.         # Finally (before we start the debuggee again) show state
  185.         self.switch_to_app()
  186.         self.run_dialog.show_it_running()
  187.         
  188.     def quit_bdb(self):
  189.         self.dbg.set_quit()
  190.         
  191.     def run(self):
  192.         cmd = self.AskString('Statement to execute:')
  193.         self.runstring(cmd)
  194.         
  195.     def runfile(self, path):
  196.         dir, file = os.path.split(path)
  197.         try:
  198.             os.chdir(dir)
  199.         except os.error, arg:
  200.             self.Message("%s: %s"%(dir, arg))
  201.             return
  202.         ns = {'__name__':'__main__', '__file__':path}
  203.         cmd = "execfile('%s')"%file
  204.         self.runstring(cmd, ns, ns)
  205.         
  206.     def runstring(self, cmd, globals={}, locals={}):
  207.         self.cur_string_name = '<string: "%s">'%cmd
  208.         try:
  209.             cmd = compile(cmd, self.cur_string_name, 'exec')
  210.         except SyntaxError, arg:
  211.             self.Message('Syntax error: %s'%`arg`)
  212.             return
  213.         self.initial_cmd = (cmd, globals, locals)
  214.         self.exit_mainloop()
  215.  
  216.     def cont(self):
  217.         self.dbg.set_continue()
  218.         self.exit_mainloop()
  219.                 
  220.     def step(self, frame):
  221.         self.dbg.set_next(frame)
  222.         self.exit_mainloop()
  223.         
  224.     def step_in(self):
  225.         self.dbg.set_step()
  226.         self.exit_mainloop()
  227.         
  228.     def step_out(self, frame):
  229.         self.dbg.set_return(frame)
  230.         self.exit_mainloop()
  231.         
  232.     def kill(self):
  233.         self.dbg.set_quit()
  234.         self.exit_mainloop()
  235.         
  236.     def quit(self):
  237.         self.do_quit()
  238.         
  239.     def browse(self, module):
  240.         if not self.module_dialog:
  241.             self.module_dialog = self.new_module_browser(self)
  242.             self.module_dialog.open(module)
  243.         else:
  244.             self.module_dialog.focus(module)
  245.     
  246.     def browse_var(self, var):
  247.         b = self.new_var_browser(self, var)
  248.         
  249. class StackBrowser:
  250.     """Base code for stack browser"""
  251.     def mi_open(self):
  252.         """Setup initial data structures"""
  253.         self.create_items()
  254.         self.cur_stackitem = None
  255.         self.cur_source = None
  256.         self.cur_modname = None
  257.         self.cur_line = None
  258.         self.show_complex = 1
  259.         self.show_system = 0
  260.         self.setup()
  261.  
  262.     # create_items(self) should create self.modules, self.vars and self.source
  263.     
  264.     def setup(self):
  265.         self.parent.SetWatch()
  266.         """Fill the various widgets with values"""
  267.         name, value = self.parent.dbg.getexception()
  268.         self.setexception(name, value)
  269.         self.setprogramstate(self.parent.dbg.getprogramstate())
  270.         
  271.         names, locations = self.parent.dbg.getstacktrace()
  272.         self.stack.setcontent(names, locations)
  273.         self.cur_stackitem = len(names)-1
  274.         self.stack.select(self.cur_stackitem)
  275.         self.setup_frame()
  276.         
  277.     def setup_frame(self):
  278.         """Setup frame-dependent widget data"""
  279.         self.parent.SetWatch()
  280.         self.cont_varnames, self.cont_varvalues = \
  281.             self.parent.dbg.getframevars(self.cur_stackitem, 
  282.             self.show_complex, self.show_system)
  283.         self.vars.setcontent(self.cont_varnames, self.cont_varvalues)
  284.         self.set_var_buttons()
  285.     
  286.         msg = ""
  287.         if self.cur_stackitem == None:
  288.             self.cur_source = None
  289.             self.cur_modname = None
  290.             self.cur_line = None
  291.             msg = "No stackframe selected"
  292.         else:
  293.             self.cur_source, self.cur_modname, optnextline = \
  294.                 self.parent.dbg.getframefilepos(self.cur_stackitem)
  295.             if optnextline >= 0:
  296.                 self.cur_line = optnextline
  297.             if self.cur_source == '<string>':
  298.                 self.cur_source = None
  299.                 msg = "Executing from unknown <string>"
  300.             elif type(self.cur_source) == types.StringType and \
  301.                         self.cur_source[:8] == '<string:':
  302.                 msg = "Executing from "+self.cur_source
  303.                 self.cur_source = None
  304.                 
  305.         self.setsource(msg)
  306.         if not self.cur_line:
  307.             self.source.setcurline(1, ICON_ZERO)
  308.         else:
  309.             self.source.setcurline(self.cur_line, self.parent.dbg.icon)
  310.         self.breaks_changed(self.cur_source)
  311.         
  312.         
  313.         self.parent.SetCursor()
  314.         
  315.     # setsource(msg) should display cur_source+content, or msg if None
  316.     
  317.     def show_it_running(self):
  318.         self.setprogramstate("Running")
  319.  
  320.     def update_views(self):
  321.         self.setup()
  322.  
  323.     def click_stack(self, number, *dummy):
  324.         if number == self.cur_stackitem: return
  325.         self.cur_stackitem = number
  326.         self.stack.select(self.cur_stackitem)
  327.         self.setup_frame()
  328.                 
  329.     def click_var(self, var, *dummy):
  330.         v = self.parent.dbg.getframevar(self.cur_stackitem, var)
  331.         self.parent.browse_var(v)
  332.         
  333.     def click_source(self, lineno, inborder):
  334.         if not inborder:
  335.             self.source.select(lineno)
  336.             self.cur_line = lineno
  337.         if lineno == None or not self.cur_source or not inborder:
  338.             return
  339.         if self.parent.dbg.get_break(self.cur_source, lineno):
  340.             self.parent.dbg.clear_break(self.cur_source, lineno)
  341.         else:
  342.             self.parent.dbg.set_break(self.cur_source, lineno)
  343.         self.parent.breaks_changed(self.cur_source)
  344.         
  345.     def breaks_changed(self, filename):
  346.         if filename == self.cur_source:
  347.             list = self.parent.dbg.get_file_breaks(filename)
  348.             self.source.setbreaks(list)
  349.         
  350.     def click_quit(self):
  351.         self.parent.quit()
  352.         
  353.     def click_run(self):
  354.         self.parent.run()
  355.         
  356.     def click_continue(self):
  357.         self.parent.cont()
  358.         
  359.     def click_step(self):
  360.         if self.cur_stackitem <> None:
  361.             frame = self.parent.dbg.getframe(self.cur_stackitem)
  362.             self.parent.step(frame)
  363.         else:
  364.             self.parent.step_in()
  365.         
  366.     def click_step_in(self):
  367.         self.parent.step_in()
  368.         
  369.     def click_step_out(self):
  370.         if self.cur_stackitem <> None:
  371.             frame = self.parent.dbg.getframe(self.cur_stackitem)
  372.             self.parent.step_out(frame)
  373.         else:
  374.             self.parent.step_in()
  375.             
  376.     def click_kill(self):
  377.         self.parent.kill()
  378.         
  379.     def click_browse(self):
  380.         self.parent.browse(self.cur_modname)
  381.         
  382.     def click_edit(self):
  383.         lino = self.cur_line
  384.         if not lino:
  385.             lino = 1
  386.         if self.cur_source:
  387.             self.parent.edit(self.cur_source, lino)
  388.  
  389. class ModuleBrowser:
  390.     """Base code for a module-browser"""
  391.  
  392.     def mi_open(self, module):
  393.         """Setup initial data structures"""
  394.         self.create_items()
  395.         self.cur_module = module
  396.         self.cur_source = None
  397.         self.cur_line = None
  398.         self.cont_modules = []
  399.         self.value_windows = []
  400.         self.setup()
  401.  
  402.     # create_items(self) should create self.modules, self.vars and self.source
  403.     
  404.     def setup(self):
  405.         """Fill the various widgets with values"""
  406.         self.parent.SetWatch()
  407.         modnames = getmodulenames()
  408.         if not self.cur_module in modnames:
  409.             self.cur_module = None
  410.         if modnames <> self.cont_modules:
  411.             self.modules.setcontent(modnames)
  412.             self.cont_modules = modnames
  413.         if self.cur_module:
  414.             self.modules.select(self.cont_modules.index(self.cur_module))
  415.         else:
  416.             self.modules.select(None)
  417.         self.setup_module()
  418.         
  419.     def setup_module(self):
  420.         """Setup module-dependent widget data"""
  421.         self.parent.SetWatch()
  422.         if not self.cur_module:
  423.             self.vars.setcontent([], [])
  424.         else:
  425.             self.cont_varnames, self.cont_varvalues = getmodulevars(self.cur_module)
  426.             self.vars.setcontent(self.cont_varnames, self.cont_varvalues)
  427.             
  428.         msg = ""
  429.         if not self.cur_module:
  430.             self.cur_source = None
  431.             msg = "No module selected"
  432.         else:
  433.             m = sys.modules[self.cur_module]
  434.             try:
  435.                 self.cur_source = m.__file__
  436.             except AttributeError:
  437.                 self.cur_source = None
  438.                 msg = "Not a python module"
  439.         self.cur_lineno = 0    
  440.         self.setsource(msg)
  441.         self.source.select(self.cur_line)
  442.         self.breaks_changed(self.cur_source)
  443.         
  444.         self.parent.SetCursor()
  445.  
  446.     # setsource(msg) should display cur_source+content, or msg if None
  447.     
  448.     def update_views(self):
  449.         self.setup_module()
  450.     
  451.     def click_module(self, module, *dummy):
  452.         if not module or module == self.cur_module: return
  453.         self.focus(module)
  454.         
  455.     def focus(self, module):
  456.         self.cur_module = module
  457.         self.setup()
  458.         
  459.     def click_var(self, var, *dummy):
  460.         if not var: return
  461.         m = sys.modules[self.cur_module]
  462.         dict = m.__dict__
  463.         self.parent.browse_var(dict[var])
  464.                 
  465.     def click_source(self, lineno, inborder):
  466.         if not inborder:
  467.             self.source.select(lineno)
  468.             self.cur_lineno = lineno
  469.         if lineno == None or not self.cur_source or not inborder:
  470.             return
  471.         if self.parent.dbg.get_break(self.cur_source, lineno):
  472.             self.parent.dbg.clear_break(self.cur_source, lineno)
  473.         else:
  474.             self.parent.dbg.set_break(self.cur_source, lineno)
  475.         self.parent.breaks_changed(self.cur_source)
  476.         
  477.     def breaks_changed(self, filename):
  478.         if filename == self.cur_source:
  479.             list = self.parent.dbg.get_file_breaks(filename)
  480.             self.source.setbreaks(list)
  481.         
  482.     def click_edit(self):
  483.         lino = self.cur_lineno
  484.         if not lino:
  485.             lino = 1
  486.         if self.cur_source:
  487.             self.parent.edit(self.cur_source, lino)
  488.         
  489.             
  490. def getmodulenames():
  491.     """Return a list of all current modules, sorted"""
  492.     list = sys.modules.keys()[:]
  493.     list.sort()
  494.     return list
  495.     
  496. def getmodulevars(name):
  497.     """For given module return lists with names and values"""
  498.     m = sys.modules[name]
  499.     try:
  500.         dict = m.__dict__
  501.     except AttributeError:
  502.         dict = {}
  503.     return getvarsfromdict(dict)
  504.     
  505. def getvarsfromdict(dict, show_complex=1, show_system=1):
  506.     allnames = dict.keys()[:]
  507.     allnames.sort()
  508.     names = []
  509.     for n in allnames:
  510.         if not show_complex:
  511.             if not type(dict[n]) in SIMPLE_TYPES:
  512.                 continue
  513.         if not show_system:
  514.             if n[:2] == '__' and n[-2:] == '__':
  515.                 continue
  516.         names.append(n)
  517.     values = []
  518.     for n in names:
  519.         v = pretty(dict[n])
  520.         values.append(v)
  521.     return names, values
  522.     
  523. def pretty(var):
  524.     t = type(var)
  525.     if t == types.FunctionType: return '<function>'
  526.     if t == types.ClassType: return '<class>'
  527.     return `var`
  528.     
  529. def getframelineno(frame):
  530.     """Given a frame return the line number"""
  531.     return getcodelineno(frame.f_code)
  532.     
  533. def getfunclineno(func):
  534.     """Given a function return the line number"""
  535.     return getcodelineno(func.func_code)
  536.     
  537. def getcodelineno(cobj):
  538.     """Given a code object return the line number"""
  539.     code = cobj.co_code
  540.     lineno = -1
  541.     if ord(code[0]) == 127: # SET_LINENO instruction
  542.         lineno = ord(code[1]) | (ord(code[2]) << 8)
  543.     return lineno
  544.  
  545. def getframemodname(frame):
  546.     """Given a frame return the module name"""
  547.     globals = frame.f_globals
  548.     if globals.has_key('__name__'):
  549.         return globals['__name__']
  550.     return None
  551.