diff options
Diffstat (limited to 'websdk/werkzeug/debug/__init__.py')
-rw-r--r-- | websdk/werkzeug/debug/__init__.py | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/websdk/werkzeug/debug/__init__.py b/websdk/werkzeug/debug/__init__.py new file mode 100644 index 0000000..db91b74 --- /dev/null +++ b/websdk/werkzeug/debug/__init__.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.debug + ~~~~~~~~~~~~~~ + + WSGI application traceback debugger. + + :copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import mimetypes +from os.path import join, dirname, basename, isfile +from werkzeug.wrappers import BaseRequest as Request, BaseResponse as Response +from werkzeug.debug.tbtools import get_current_traceback, render_console_html +from werkzeug.debug.console import Console +from werkzeug.security import gen_salt + + +#: import this here because it once was documented as being available +#: from this module. In case there are users left ... +from werkzeug.debug.repr import debug_repr + + +class _ConsoleFrame(object): + """Helper class so that we can reuse the frame console code for the + standalone console. + """ + + def __init__(self, namespace): + self.console = Console(namespace) + self.id = 0 + + +class DebuggedApplication(object): + """Enables debugging support for a given application:: + + from werkzeug.debug import DebuggedApplication + from myapp import app + app = DebuggedApplication(app, evalex=True) + + The `evalex` keyword argument allows evaluating expressions in a + traceback's frame context. + + .. versionadded:: 0.7 + The `lodgeit_url` parameter was added. + + :param app: the WSGI application to run debugged. + :param evalex: enable exception evaluation feature (interactive + debugging). This requires a non-forking server. + :param request_key: The key that points to the request object in ths + environment. This parameter is ignored in current + versions. + :param console_path: the URL for a general purpose console. + :param console_init_func: the function that is executed before starting + the general purpose console. The return value + is used as initial namespace. + :param show_hidden_frames: by default hidden traceback frames are skipped. + You can show them by setting this parameter + to `True`. + :param lodgeit_url: the base URL of the LodgeIt instance to use for + pasting tracebacks. + """ + + # this class is public + __module__ = 'werkzeug' + + def __init__(self, app, evalex=False, request_key='werkzeug.request', + console_path='/console', console_init_func=None, + show_hidden_frames=False, + lodgeit_url='http://paste.pocoo.org/'): + if not console_init_func: + console_init_func = dict + self.app = app + self.evalex = evalex + self.frames = {} + self.tracebacks = {} + self.request_key = request_key + self.console_path = console_path + self.console_init_func = console_init_func + self.show_hidden_frames = show_hidden_frames + self.lodgeit_url = lodgeit_url + self.secret = gen_salt(20) + + def debug_application(self, environ, start_response): + """Run the application and conserve the traceback frames.""" + app_iter = None + try: + app_iter = self.app(environ, start_response) + for item in app_iter: + yield item + if hasattr(app_iter, 'close'): + app_iter.close() + except Exception: + if hasattr(app_iter, 'close'): + app_iter.close() + traceback = get_current_traceback(skip=1, show_hidden_frames= + self.show_hidden_frames, + ignore_system_exceptions=True) + for frame in traceback.frames: + self.frames[frame.id] = frame + self.tracebacks[traceback.id] = traceback + + try: + start_response('500 INTERNAL SERVER ERROR', [ + ('Content-Type', 'text/html; charset=utf-8') + ]) + except Exception: + # if we end up here there has been output but an error + # occurred. in that situation we can do nothing fancy any + # more, better log something into the error log and fall + # back gracefully. + environ['wsgi.errors'].write( + 'Debugging middleware caught exception in streamed ' + 'response at a point where response headers were already ' + 'sent.\n') + else: + yield traceback.render_full(evalex=self.evalex, + lodgeit_url=self.lodgeit_url, + secret=self.secret) \ + .encode('utf-8', 'replace') + + traceback.log(environ['wsgi.errors']) + + def execute_command(self, request, command, frame): + """Execute a command in a console.""" + return Response(frame.console.eval(command), mimetype='text/html') + + def display_console(self, request): + """Display a standalone shell.""" + if 0 not in self.frames: + self.frames[0] = _ConsoleFrame(self.console_init_func()) + return Response(render_console_html(secret=self.secret), + mimetype='text/html') + + def paste_traceback(self, request, traceback): + """Paste the traceback and return a JSON response.""" + paste_id = traceback.paste(self.lodgeit_url) + return Response('{"url": "%sshow/%s/", "id": "%s"}' + % (self.lodgeit_url, paste_id, paste_id), + mimetype='application/json') + + def get_source(self, request, frame): + """Render the source viewer.""" + return Response(frame.render_source(), mimetype='text/html') + + def get_resource(self, request, filename): + """Return a static resource from the shared folder.""" + filename = join(dirname(__file__), 'shared', basename(filename)) + if isfile(filename): + mimetype = mimetypes.guess_type(filename)[0] \ + or 'application/octet-stream' + f = file(filename, 'rb') + try: + return Response(f.read(), mimetype=mimetype) + finally: + f.close() + return Response('Not Found', status=404) + + def __call__(self, environ, start_response): + """Dispatch the requests.""" + # important: don't ever access a function here that reads the incoming + # form data! Otherwise the application won't have access to that data + # any more! + request = Request(environ) + response = self.debug_application + if request.args.get('__debugger__') == 'yes': + cmd = request.args.get('cmd') + arg = request.args.get('f') + secret = request.args.get('s') + traceback = self.tracebacks.get(request.args.get('tb', type=int)) + frame = self.frames.get(request.args.get('frm', type=int)) + if cmd == 'resource' and arg: + response = self.get_resource(request, arg) + elif cmd == 'paste' and traceback is not None and \ + secret == self.secret: + response = self.paste_traceback(request, traceback) + elif cmd == 'source' and frame and self.secret == secret: + response = self.get_source(request, frame) + elif self.evalex and cmd is not None and frame is not None and \ + self.secret == secret: + response = self.execute_command(request, cmd, frame) + elif self.evalex and self.console_path is not None and \ + request.path == self.console_path: + response = self.display_console(request) + return response(environ, start_response) |