mirror of
https://github.com/pallets-eco/flask-debugtoolbar.git
synced 2026-05-03 14:59:09 -05:00
Trigger the Panel.process_view by monkey-patching the Flask.dispatch_request method. Use this for the profiling panel to make it threadsafe
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import os
|
||||
|
||||
from flask import request
|
||||
from flask import signals
|
||||
from flask import current_app, request, signals
|
||||
from flask.globals import _request_ctx_stack
|
||||
from flask.helpers import send_from_directory
|
||||
from jinja2 import Environment, PackageLoader
|
||||
from werkzeug.routing import Rule, Submount
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from flaskext.debugtoolbar.toolbar import DebugToolbar
|
||||
|
||||
@@ -34,6 +34,9 @@ class DebugToolbarExtension(object):
|
||||
signals.request_started.connect(self.process_request, app)
|
||||
signals.request_finished.connect(self.process_response, app)
|
||||
|
||||
# Monkey-patch the Flask.dispatch_request method
|
||||
app.dispatch_request = self.dispatch_request
|
||||
|
||||
# Configure jinja for the internal templates and add url rules
|
||||
# for static data
|
||||
self.jinja_env = Environment(
|
||||
@@ -43,6 +46,37 @@ class DebugToolbarExtension(object):
|
||||
app.add_url_rule('/_debug_toolbar/static/<path:filename>',
|
||||
'_debug_toolbar.static', self.send_static_file)
|
||||
|
||||
|
||||
def dispatch_request(self):
|
||||
"""Does the request dispatching. Matches the URL and returns the
|
||||
return value of the view or error handler. This does not have to
|
||||
be a response object. In order to convert the return value to a
|
||||
proper response object, call :func:`make_response`.
|
||||
|
||||
This is a modified version of the default Flask.dispatch_request
|
||||
"""
|
||||
req = _request_ctx_stack.top.request
|
||||
app = current_app
|
||||
try:
|
||||
if req.routing_exception is not None:
|
||||
raise req.routing_exception
|
||||
rule = req.url_rule
|
||||
# if we provide automatic options for this URL and the
|
||||
# request came with the OPTIONS method, reply automatically
|
||||
if getattr(rule, 'provide_automatic_options', False) \
|
||||
and req.method == 'OPTIONS':
|
||||
return app.make_default_options_response()
|
||||
|
||||
# otherwise dispatch to the handler for that endpoint, give the
|
||||
# panels the ability to wrap the view_func
|
||||
view_func = app.view_functions[rule.endpoint]
|
||||
view_func = self.process_view(app, view_func, req.view_args)
|
||||
|
||||
return view_func(**req.view_args)
|
||||
|
||||
except HTTPException, e:
|
||||
return app.handle_http_exception(e)
|
||||
|
||||
def _show_toolbar(self):
|
||||
if request.path.startswith('/_debug_toolbar/'):
|
||||
return False
|
||||
@@ -60,10 +94,13 @@ class DebugToolbarExtension(object):
|
||||
for panel in self.debug_toolbars[request].panels:
|
||||
panel.process_request(request)
|
||||
|
||||
def process_view(self, app, template, context):
|
||||
def process_view(self, app, view_func, view_kwargs):
|
||||
if request in self.debug_toolbars:
|
||||
for panel in self.debug_toolbars[request].panels:
|
||||
panel.process_view(request, template, [], context)
|
||||
new_view = panel.process_view(request, view_func, view_kwargs)
|
||||
if new_view:
|
||||
view_func = new_view
|
||||
return view_func
|
||||
|
||||
def process_response(self, sender, response):
|
||||
if request not in self.debug_toolbars:
|
||||
|
||||
@@ -52,7 +52,7 @@ class DebugPanel(object):
|
||||
def process_request(self, request):
|
||||
pass
|
||||
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
def process_view(self, request, view_func, view_kwargs):
|
||||
pass
|
||||
|
||||
def process_response(self, request, response):
|
||||
|
||||
@@ -2,6 +2,7 @@ try:
|
||||
import cProfile as profile
|
||||
except ImportError:
|
||||
import profile
|
||||
import functools
|
||||
import pstats
|
||||
|
||||
from flask import current_app
|
||||
@@ -25,13 +26,9 @@ class ProfilerDebugPanel(DebugPanel):
|
||||
self.profiler = profile.Profile()
|
||||
self.stats = None
|
||||
|
||||
# Monkey-patch Flask.dispatch_request for profiling
|
||||
org_dispatch_request = current_app.dispatch_request
|
||||
def dispatch_request():
|
||||
content = self.profiler.runcall(org_dispatch_request)
|
||||
current_app.dispatch_request = org_dispatch_request
|
||||
return content
|
||||
current_app.dispatch_request = dispatch_request
|
||||
def process_view(self, request, view_func, view_kwargs):
|
||||
if self.is_active:
|
||||
return functools.partial(self.profiler.runcall, view_func)
|
||||
|
||||
def process_response(self, request, response):
|
||||
if not self.is_active:
|
||||
@@ -64,7 +61,6 @@ class ProfilerDebugPanel(DebugPanel):
|
||||
# destroy the profiler just in case
|
||||
return response
|
||||
|
||||
|
||||
def title(self):
|
||||
if not self.is_active:
|
||||
return "Profiler not active"
|
||||
|
||||
@@ -22,11 +22,10 @@ class RequestVarsDebugPanel(DebugPanel):
|
||||
self.request = request
|
||||
self.view_func = None
|
||||
self.view_args = []
|
||||
self.view_kwargs = request.view_args
|
||||
self.view_kwargs = {}
|
||||
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
def process_view(self, request, view_func, view_kwargs):
|
||||
self.view_func = view_func
|
||||
self.view_args = view_args
|
||||
self.view_kwargs = view_kwargs
|
||||
|
||||
def content(self):
|
||||
|
||||
Reference in New Issue
Block a user