1+ import contextvars
12import os
23import urllib .parse
34import warnings
@@ -57,7 +58,9 @@ class DebugToolbarExtension(object):
5758
5859 def __init__ (self , app = None ):
5960 self .app = app
60- self .debug_toolbars = {}
61+ # Support threads running `flask.copy_current_request_context` without
62+ # poping toolbar during `teardown_request`
63+ self .debug_toolbars_var = contextvars .ContextVar ('debug_toolbars' )
6164 jinja_extensions = ['jinja2.ext.i18n' ]
6265
6366 if __jinja_version__ [0 ] == '2' :
@@ -167,11 +170,11 @@ def process_request(self):
167170 return
168171
169172 real_request = request ._get_current_object ()
170-
171- self .debug_toolbars [real_request ] = (
173+ self . debug_toolbars_var . set ({})
174+ self .debug_toolbars_var . get () [real_request ] = (
172175 DebugToolbar (real_request , self .jinja_env ))
173176
174- for panel in self .debug_toolbars [real_request ].panels :
177+ for panel in self .debug_toolbars_var . get () [real_request ].panels :
175178 panel .process_request (real_request )
176179
177180 def process_view (self , app , view_func , view_kwargs ):
@@ -180,7 +183,7 @@ def process_view(self, app, view_func, view_kwargs):
180183 """
181184 real_request = request ._get_current_object ()
182185 try :
183- toolbar = self .debug_toolbars [real_request ]
186+ toolbar = self .debug_toolbars_var . get ({}) [real_request ]
184187 except KeyError :
185188 return view_func
186189
@@ -193,7 +196,7 @@ def process_view(self, app, view_func, view_kwargs):
193196
194197 def process_response (self , response ):
195198 real_request = request ._get_current_object ()
196- if real_request not in self .debug_toolbars :
199+ if real_request not in self .debug_toolbars_var . get () :
197200 return response
198201
199202 # Intercept http redirect codes and display an html page with a
@@ -239,7 +242,7 @@ def process_response(self, response):
239242 ' </body> tag not found in response.' )
240243 return response
241244
242- toolbar = self .debug_toolbars [real_request ]
245+ toolbar = self .debug_toolbars_var . get () [real_request ]
243246
244247 for panel in toolbar .panels :
245248 panel .process_response (real_request , response )
@@ -256,7 +259,8 @@ def process_response(self, response):
256259 return response
257260
258261 def teardown_request (self , exc ):
259- self .debug_toolbars .pop (request ._get_current_object (), None )
262+ # debug_toolbars_var won't be set under `flask.copy_current_request_context`
263+ self .debug_toolbars_var .get ({}).pop (request ._get_current_object (), None )
260264
261265 def render (self , template_name , context ):
262266 template = self .jinja_env .get_template (template_name )
0 commit comments