Skip to content

Commit 217238b

Browse files
committed
Don't try to undo DatabaseWrapper monkey patching
Prior to this commit, the SQLPanel would monkey patch the .cursor() and .chunked_cursor() methods of each DatabaseWrapper connection in .enable_instrumentation(), and then undo the monkey patch in .disable_instrumentation(). However, for the same reasons as a6b65a7, stop trying to undo the monkey patching in .disable_instrumentation() and simply use a .djdt_logger attribute on the DatabaseWrapper to determine if the cursors should be wrapped.
1 parent df67c89 commit 217238b

File tree

2 files changed

+19
-27
lines changed

2 files changed

+19
-27
lines changed

debug_toolbar/panels/sql/panel.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from debug_toolbar.panels import Panel
1111
from debug_toolbar.panels.sql import views
1212
from debug_toolbar.panels.sql.forms import SQLSelectForm
13-
from debug_toolbar.panels.sql.tracking import unwrap_cursor, wrap_cursor
13+
from debug_toolbar.panels.sql.tracking import wrap_cursor
1414
from debug_toolbar.panels.sql.utils import contrasting_color_generator, reformat_sql
1515
from debug_toolbar.utils import render_stacktrace
1616

@@ -190,11 +190,12 @@ def get_urls(cls):
190190
def enable_instrumentation(self):
191191
# This is thread-safe because database connections are thread-local.
192192
for connection in connections.all():
193-
wrap_cursor(connection, self)
193+
wrap_cursor(connection)
194+
connection._djdt_logger = self
194195

195196
def disable_instrumentation(self):
196197
for connection in connections.all():
197-
unwrap_cursor(connection)
198+
connection._djdt_logger = None
198199

199200
def generate_stats(self, request, response):
200201
colors = contrasting_color_generator()

debug_toolbar/panels/sql/tracking.py

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
from time import time
55

6+
import django.test.testcases
67
from django.utils.encoding import force_str
78

89
from debug_toolbar import settings as dt_settings
@@ -31,10 +32,15 @@ class SQLQueryTriggered(Exception):
3132
"""Thrown when template panel triggers a query"""
3233

3334

34-
def wrap_cursor(connection, panel):
35+
def wrap_cursor(connection):
36+
# If running a Django SimpleTestCase, which isn't allowed to access the database,
37+
# don't perform any monkey patching.
38+
if isinstance(connection.cursor, django.test.testcases._DatabaseFailure):
39+
return
3540
if not hasattr(connection, "_djdt_cursor"):
3641
connection._djdt_cursor = connection.cursor
3742
connection._djdt_chunked_cursor = connection.chunked_cursor
43+
connection._djdt_logger = None
3844

3945
def cursor(*args, **kwargs):
4046
# Per the DB API cursor() does not accept any arguments. There's
@@ -43,48 +49,33 @@ def cursor(*args, **kwargs):
4349
# See:
4450
# https://github.com/jazzband/django-debug-toolbar/pull/615
4551
# https://github.com/jazzband/django-debug-toolbar/pull/896
52+
logger = connection._djdt_logger
53+
cursor = connection._djdt_cursor(*args, **kwargs)
54+
if logger is None:
55+
return cursor
4656
if allow_sql.get():
4757
wrapper = NormalCursorWrapper
4858
else:
4959
wrapper = ExceptionCursorWrapper
50-
return wrapper(connection._djdt_cursor(*args, **kwargs), connection, panel)
60+
return wrapper(cursor, connection, logger)
5161

5262
def chunked_cursor(*args, **kwargs):
5363
# prevent double wrapping
5464
# solves https://github.com/jazzband/django-debug-toolbar/issues/1239
65+
logger = connection._djdt_logger
5566
cursor = connection._djdt_chunked_cursor(*args, **kwargs)
56-
if not isinstance(cursor, BaseCursorWrapper):
67+
if logger is not None and not isinstance(cursor, BaseCursorWrapper):
5768
if allow_sql.get():
5869
wrapper = NormalCursorWrapper
5970
else:
6071
wrapper = ExceptionCursorWrapper
61-
return wrapper(cursor, connection, panel)
72+
return wrapper(cursor, connection, logger)
6273
return cursor
6374

6475
connection.cursor = cursor
6576
connection.chunked_cursor = chunked_cursor
6677

6778

68-
def unwrap_cursor(connection):
69-
if hasattr(connection, "_djdt_cursor"):
70-
# Sometimes the cursor()/chunked_cursor() methods of the DatabaseWrapper
71-
# instance are already monkey patched before wrap_cursor() is called. (In
72-
# particular, Django's SimpleTestCase monkey patches those methods for any
73-
# disallowed databases to raise an exception if they are accessed.) Thus only
74-
# delete our monkey patch if the method we saved is the same as the class
75-
# method. Otherwise, restore the prior monkey patch from our saved method.
76-
if connection._djdt_cursor == connection.__class__.cursor:
77-
del connection.cursor
78-
else:
79-
connection.cursor = connection._djdt_cursor
80-
del connection._djdt_cursor
81-
if connection._djdt_chunked_cursor == connection.__class__.chunked_cursor:
82-
del connection.chunked_cursor
83-
else:
84-
connection.chunked_cursor = connection._djdt_chunked_cursor
85-
del connection._djdt_chunked_cursor
86-
87-
8879
class BaseCursorWrapper:
8980
pass
9081

0 commit comments

Comments
 (0)