> And if you are using persistent processes, you constantly have to restart > the process, refresh cookies, etc. I'm certainly not touching mod_python until the app is more stable =). > To help with the restarting, I've been using a subclass of SessionPublisher > that sets self.exit_now if source files have changed. That's a nice hack worth sharing =). > It works ok, but I haven't used it long enough to decide if it's really less > work than all the browser reloading. Writing tests is always more work in the > short term than just testing by hand. Especially since you need to test with however many browsers you care about for a bunch of things. My contribution is attached -- a patch (probably needs tweaking) to enable cgitb if it's been enabled. With the patch applied, you can add import cgitb cgitb.enable() anywhere, and the tracebacks will be of the nice cgitb form (although I'd love a different color scheme =). I'm still quite puzzled by the "unlinking .ptlc" problem when dealing with SyntaxErrors. Is the 'os.unlink()' call in ptl_import really necessary? Also, the ptl_compile code about SyntaxError is iffy -- SyntaxError is never imported into that module, but referenced. Finally -- even with my patch, SyntaxErrors yield goofy tracebacks and not the useful real SyntaxError traceback referring to the faulty code. Any ideas welcome. --david
--- publish.py.orig Tue Jan 29 05:31:05 2002 +++ publish.py Tue Jan 29 05:34:20 2002 @@ -7,6 +7,7 @@ import sys, os, traceback, cStringIO import time, types, socket, re +import cgitb from quixote import errors, fcgi from quixote.http_request import HTTPRequest @@ -390,25 +391,33 @@ error_summary = traceback.format_exception_only(exc_type, exc_value) error_summary = error_summary[0][0:-1] # de-listify and strip newline error_file = cStringIO.StringIO() + if isinstance(sys.excepthook, cgitb.Hook): + hook = cgitb.Hook(file=error_file) + hook(exc_type, exc_value, tb) + error_file.write(' Original Request ') + error_file.write(request.dump_html()) + error_file.write(' Original Response ') + original_response.write(error_file) + error_file.write(' ') + else: + #self.debug("report_error: exception = %s: %s" % (exc_type, exc_value)) - #self.debug("report_error: exception = %s: %s" % (exc_type, exc_value)) - - # record the time of the error - now = time.localtime(time.time()) - error_file.write('Error at time: %s\n' % - time.strftime('%Y-%m-%d %H:%M:%S', now) ) - # format the traceback - error_file.write('Traceback\n' - '=========\n') - traceback.print_exception(exc_type, exc_value, tb, file=error_file) - # include request and response dumps - error_file.write('\nRequest\n' - '=======\n') - error_file.write(request.dump()) - error_file.write('\nOriginal Response\n' - '=================\n') - original_response.write(error_file) - error_file.write('='*65 + '\n') + # record the time of the error + now = time.localtime(time.time()) + error_file.write('Error at time: %s\n' % + time.strftime('%Y-%m-%d %H:%M:%S', now) ) + # format the traceback + error_file.write('Traceback\n' + '=========\n') + traceback.print_exception(exc_type, exc_value, tb, file=error_file) + # include request and response dumps + error_file.write('\nRequest\n' + '=======\n') + error_file.write(request.dump()) + error_file.write('\nOriginal Response\n' + '=================\n') + original_response.write(error_file) + error_file.write('='*65 + '\n') error_msg = error_file.getvalue() self.error_log.write(error_msg) @@ -565,7 +574,8 @@ # Determine the script name and path info script_name = request.environ['SCRIPT_NAME'] or "/" - request.environ['SCRIPT_NAME'] = script_name + "/".join(path_components) +# request.environ['SCRIPT_NAME'] = script_name + "/".join(path_components) + request.environ['SCRIPT_NAME'] += path request.environ['PATH_INFO'] = '' # we always traverse the entire path return object