text: """ 
  Author: Justin Cappos
  
  Start Date: September 17th, 2008
  
  Description:
  Module for printing clean tracebacks.   It takes the python traceback and 
  makes the output look nicer so the programmer can tell what is happening...
  
  """
  
  
  # we'll print our own exceptions
  import traceback
  # This needs hasattr.   I'll allow it...
  traceback.hasattr = hasattr
  
  # and don't want traceback to use linecache because linecache uses open
  import fakelinecache
  traceback.linecache = fakelinecache
  
  # Need to be able to reference the last traceback...
  import sys
  
  # Used to determine whether or not we use the service logger to log internal
  # errors.  Defaults to false. -Brent
  servicelog = False
  
  # this is the directory where the node manager resides.   We will use this
  # when deciding where to write our service log.
  logdirectory = None
  
  
  # We need the service logger to log internal errors -Brent
  import servicelogger
  
  # We need to be able to do a harshexit on internal errors
  import harshexit
  
  # I'd like to know if it's a "safety concern" so I can tell the user...
  # I'll import the module so I can check the exceptions
  import safety_exceptions
  
  # needed to get the PID
  import os
  
  # Armon: These set contains all the module's which are black-listed
  # from the traceback, so that if there is an exception, they will
  # not appear in the stack.
  TB_SKIP_MODULES = ["repy.py","safe.py","virtual_namespace.py","namespace.py","emulcomm.py",
                        "emultimer.py","emulmisc.py","emulfile.py","nonportable.py","socket.py"]
  
  
  # sets the user's file name.
  # also sets whether or not the servicelogger is used. -Brent
  def initialize(useservlog=False, logdir = '.'):
    global servicelog
    global logdirectory
    servicelog = useservlog
    logdirectory = logdir
  
  
  # Public: this prints the previous exception in a readable way...
  def handle_exception():
    """
    This is an example traceback:
    ---
    Uncaught exception! Following is a full traceback, and a user traceback.
    The user traceback excludes non-user modules. The most recent call is displayed last.
  
    Full debugging traceback:
      "repy.py", line 191, in main
      "/Users/adadgar/Projects/seattle/trunk/test/virtual_namespace.py", line 116, in evaluate
      "/Users/adadgar/Projects/seattle/trunk/test/safe.py", line 304, in safe_run
      "dylink.repy", line 472, in <module>
      "dylink.repy", line 360, in dylink_dispatch
      "dylink.repy", line 455, in evaluate
      "/Users/adadgar/Projects/seattle/trunk/test/namespace.py", line 1072, in __do_func_call
      "/Users/adadgar/Projects/seattle/trunk/test/namespace.py", line 1487, in wrapped_function
      "/Users/adadgar/Projects/seattle/trunk/test/virtual_namespace.py", line 116, in evaluate
      "/Users/adadgar/Projects/seattle/trunk/test/safe.py", line 304, in safe_run
      "testxmlrpc_common", line 254, in <module>
      "/Users/adadgar/Projects/seattle/trunk/test/safe.py", line 174, in fnc
  
    User traceback:
      "dylink.repy", line 472, in <module>
      "dylink.repy", line 360, in dylink_dispatch
      "dylink.repy", line 455, in evaluate
      "testxmlrpc_common", line 254, in <module>
  
    Unsafe call: ('__import__',)
    ---
    """
  
    # exc_info() gives the traceback (see the traceback module for info)
    exceptiontype, exceptionvalue, exceptiontraceback = sys.exc_info()
   
    # We store a full traceback, and a "filtered" user traceback to help the user
    full_tb = ""
    filtered_tb = ""
  
    for tracebackentry in traceback.extract_tb(exceptiontraceback):
      # the entry format is (filename, lineno, modulename, linedata)
      # linedata is always empty because we prevent the linecache from working
      # for safety reasons...
  
      # Check that this module is not black-listed
      module = tracebackentry[0]
      skip = False
  
      # Check if any of the forbidden modules are a substring of the module name
      # e.g. if the name is /home/person/seattle/repy.py, we want to see that repy.py
      # and skip this frame.
      for forbidden in TB_SKIP_MODULES:
        if forbidden in module:
          skip = True
          break
  
      # Construct a frame of output
      stack_frame = '  "'+tracebackentry[0]+'", line '+str(tracebackentry[1])+", in "+str(tracebackentry[2])+"\n"
  
      # Always add to the full traceback
      full_tb += stack_frame
  
      # If this module is not blacklisted, add it to the filtered traceback
      if not skip:
        filtered_tb += stack_frame
  
  
    # Print some general info
    print >> sys.stderr, "---\nUncaught exception! Following is a full traceback, and a user traceback.\n" \
                          "The user traceback excludes non-user modules. The most recent call is displayed last.\n"
  
    # Print the full traceback first
    print >> sys.stderr, "Full debugging traceback:\n",full_tb
        
    print >> sys.stderr, "User traceback:\n",filtered_tb
  
  
    # When I try to print an Exception object, I get:
    # "<type 'exceptions.Exception'>".   I'm going to look for this and produce
    # more sensible output if it happens.
  
    if exceptiontype is safety_exceptions.CheckNodeException:
      print >> sys.stderr, "Unsafe call with line number / type:",str(exceptionvalue)
  
    elif exceptiontype is safety_exceptions.CheckStrException:
      print >> sys.stderr, "Unsafe string on line number / string:",exceptionvalue
  
    elif exceptiontype is safety_exceptions.RunBuiltinException:
      print >> sys.stderr, "Unsafe call:",exceptionvalue
  
    elif str(exceptiontype)[0] == '<':
      print >> sys.stderr, "Exception (with "+str(exceptiontype)[1:-1]+"):", exceptionvalue
    else:
      print >> sys.stderr, "Exception (with type "+str(exceptiontype)+"):", exceptionvalue
  
    # Print another line so that the end of the output is clear
    print >> sys.stderr, "---"
  
  
  def handle_internalerror(error_string, exitcode):
    """
    <Author>
      Brent Couvrette
    <Purpose>
      When an internal error happens in repy it should be handled differently 
      than normal exceptions, because internal errors could possibly lead to
      security vulnerabilities if we aren't careful.  Therefore when an internal
      error occurs, we will not return control to the user's program.  Instead
      we will log the error to the service log if available, then terminate.
    <Arguments>
      error_string - The error string to be logged if logging is enabled.
      exitcode - The exit code to be used in the harshexit call.
    <Exceptions>
      None
    <Side Effects>
      The program will exit.
    <Return>
      Shouldn't return because harshexit will always be called.
    """
  
    try:
      print >> sys.stderr, "Internal Error"
      if not servicelog:
        # If the service log is disabled, lets just exit.
        harshexit.harshexit(exitcode)
      else:
        # Internal errors should not be given to the user's code to be caught,
        # so we print the exception to the service log and exit. -Brent
        exceptionstring = "[INTERNAL ERROR] " + error_string + '\n'
        for line in traceback.format_stack():
          exceptionstring = exceptionstring + line
    
        # This magic is determining what directory we are in, so that can be
        # used as an identifier in the log.  In a standard deployment this
        # should be of the form vXX where XX is the vessel number.  We don't
        # want any exceptions here preventing us from exitting, so we will
        # wrap this in a try-except block, and use a default value if we fail.
        try:
          identifier = os.path.basename(os.getcwd())
        except:
          # We use a blank except because if we don't, the user might be able to
          # handle the exception, which is unacceptable on internal errors.  Using
          # the current pid should avoid any attempts to write to the same file at
          # the same time.
          identifier = str(os.getpid())
        else:
          if identifier == '':
            # If the identifier is blank, use the PID.
            identifier = str(os.getpid())
      
        # Again we want to ensure that even if we fail to log, we still exit.
        try:
          servicelogger.multi_process_log(exceptionstring, identifier, logdirectory)
        except Exception, e:
          # if an exception occurs, log it (unfortunately, to the user's log)
          print 'Inner abort of servicelogger'
          print e,type(e)
          traceback.print_exc()
        finally:
          harshexit.harshexit(exitcode)
  
    except Exception, e:
      # if an exception occurs, log it (unfortunately, to the user's log)
      print 'Outer abort of servicelogger'
      print e,type(e)
      traceback.print_exc()
    finally:
      harshexit.harshexit(842)
  