Skip to content

Commit 6ec4b0c

Browse files
committed
More accurate cursor unwrapping
If the cursor()/chunked_cursor() methods of a connection had already been monkey patched by some other code before wrap_cursor() was called, unwrap_cursor() would undo the previous monkey patch as well as the one performed by wrap_cursor(). This can occur when testing if multiple databases are defined but only some of them are allowed to be used by the tests. [1] Django's SimpleTestCase wraps the connections for any disallowed databases to raise an exception if they are accessed. [2] Without this commit, unwrap_cursor() was undoing Django's monkey patch, resulting in an exception when Django tried to undo its monkey patch which was no longer there. Update unwrap_cursor() to preserve a previous monkey patch if present. [1] https://docs.djangoproject.com/en/stable/topics/testing/tools/#django.test.SimpleTestCase.databases [2] https://github.com/django/django/blob/ce586ed6931092d3a5f06df9031cdeb891793ddb/django/test/testcases.py#L350
1 parent b3e43a0 commit 6ec4b0c

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

debug_toolbar/panels/sql/tracking.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,22 @@ def chunked_cursor(*args, **kwargs):
6060

6161
def unwrap_cursor(connection):
6262
if hasattr(connection, "_djdt_cursor"):
63+
# Sometimes the cursor()/chunked_cursor() methods of the DatabaseWrapper
64+
# instance are already monkey patched before wrap_cursor() is called. (In
65+
# particular, Django's SimpleTestCase monkey patches those methods for any
66+
# disallowed databases to raise an exception if they are accessed.) Thus only
67+
# delete our monkey patch if the method we saved is the same as the class
68+
# method. Otherwise, restore the prior monkey patch from our saved method.
69+
if connection._djdt_cursor == connection.__class__.cursor:
70+
del connection.cursor
71+
else:
72+
connection.cursor = connection._djdt_cursor
6373
del connection._djdt_cursor
74+
if connection._djdt_chunked_cursor == connection.__class__.chunked_cursor:
75+
del connection.chunked_cursor
76+
else:
77+
connection.chunked_cursor = connection._djdt_chunked_cursor
6478
del connection._djdt_chunked_cursor
65-
del connection.cursor
66-
del connection.chunked_cursor
6779

6880

6981
class BaseCursorWrapper:

0 commit comments

Comments
 (0)