Skip to content

Drop Django < 3.2, modernize the code #1552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ repos:
rev: 0.10.1
hooks:
- id: doc8
- repo: https://github.com/asottile/pyupgrade
rev: v2.29.1
hooks:
- id: pyupgrade
args: [--py36-plus]
- repo: https://github.com/adamchainz/django-upgrade
rev: 1.4.0
hooks:
- id: django-upgrade
args: [--target-version, "3.2"]
- repo: https://github.com/pycqa/isort
rev: 5.10.1
hooks:
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ In addition to the built-in panels, a number of third-party panels are
contributed by the community.

The current stable version of the Debug Toolbar is 3.2.4. It works on
Django ≥ 2.2.
Django ≥ 3.2.

Documentation, including installation and configuration instructions, is
available at https://django-debug-toolbar.readthedocs.io/.
Expand Down
5 changes: 0 additions & 5 deletions debug_toolbar/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import django

from debug_toolbar.urls import app_name

__all__ = ["VERSION"]
Expand All @@ -12,6 +10,3 @@
# Code that discovers files or modules in INSTALLED_APPS imports this module.

urls = "debug_toolbar.urls", app_name

if django.VERSION < (3, 2):
default_app_config = "debug_toolbar.apps.DebugToolbarConfig"
5 changes: 2 additions & 3 deletions debug_toolbar/management/commands/debugsqlshell.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from time import time

import django
import sqlparse
from django.core.management.commands.shell import Command
from django.db import connection

if connection.vendor == "postgresql" and django.VERSION >= (3, 0, 0):
if connection.vendor == "postgresql":
from django.db.backends.postgresql import base as base_module
else:
from django.db.backends import utils as base_module
Expand All @@ -28,7 +27,7 @@ def execute(self, sql, params=()):
end_time = time()
duration = (end_time - start_time) * 1000
formatted_sql = sqlparse.format(raw_sql, reindent=True)
print("{} [{:.2f}ms]".format(formatted_sql, duration))
print(f"{formatted_sql} [{duration:.2f}ms]")


base_module.CursorDebugWrapper = PrintQueryWrapper
77 changes: 24 additions & 53 deletions debug_toolbar/panels/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,9 @@
except ImportError:
ConnectionProxy = None

import django
from django.conf import settings
from django.core import cache
from django.core.cache import (
DEFAULT_CACHE_ALIAS,
CacheHandler,
cache as original_cache,
caches as original_caches,
)
from django.core.cache import DEFAULT_CACHE_ALIAS, CacheHandler
from django.core.cache.backends.base import BaseCache
from django.dispatch import Signal
from django.middleware import cache as middleware_cache
Expand Down Expand Up @@ -69,7 +63,7 @@ def __init__(self, cache):
self.cache = cache

def __repr__(self):
return str("<CacheStatTracker for %s>") % repr(self.cache)
return "<CacheStatTracker for %s>" % repr(self.cache)

def _get_func_info(self):
frame = sys._getframe(3)
Expand Down Expand Up @@ -141,26 +135,17 @@ def decr_version(self, *args, **kwargs):
return self.cache.decr_version(*args, **kwargs)


if django.VERSION < (3, 2):
class CacheHandlerPatch(CacheHandler):
def __init__(self, settings=None):
self._djdt_wrap = True
super().__init__(settings=settings)

class CacheHandlerPatch(CacheHandler):
def __getitem__(self, alias):
actual_cache = super().__getitem__(alias)
def create_connection(self, alias):
actual_cache = super().create_connection(alias)
if self._djdt_wrap:
return CacheStatTracker(actual_cache)

else:

class CacheHandlerPatch(CacheHandler):
def __init__(self, settings=None):
self._djdt_wrap = True
super().__init__(settings=settings)

def create_connection(self, alias):
actual_cache = super().create_connection(alias)
if self._djdt_wrap:
return CacheStatTracker(actual_cache)
else:
return actual_cache
else:
return actual_cache


middleware_cache.caches = CacheHandlerPatch()
Expand Down Expand Up @@ -268,40 +253,26 @@ def title(self):
)

def enable_instrumentation(self):
if django.VERSION < (3, 2):
if isinstance(middleware_cache.caches, CacheHandlerPatch):
cache.caches = middleware_cache.caches
else:
cache.caches = CacheHandlerPatch()
else:
for alias in cache.caches:
if not isinstance(cache.caches[alias], CacheStatTracker):
cache.caches[alias] = CacheStatTracker(cache.caches[alias])
for alias in cache.caches:
if not isinstance(cache.caches[alias], CacheStatTracker):
cache.caches[alias] = CacheStatTracker(cache.caches[alias])

if not isinstance(middleware_cache.caches, CacheHandlerPatch):
middleware_cache.caches = cache.caches
if not isinstance(middleware_cache.caches, CacheHandlerPatch):
middleware_cache.caches = cache.caches

# Wrap the patched cache inside Django's ConnectionProxy
if ConnectionProxy:
cache.cache = ConnectionProxy(cache.caches, DEFAULT_CACHE_ALIAS)

def disable_instrumentation(self):
if django.VERSION < (3, 2):
cache.caches = original_caches
cache.cache = original_cache
# While it can be restored to the original, any views that were
# wrapped with the cache_page decorator will continue to use a
# monkey patched cache.
middleware_cache.caches = original_caches
else:
for alias in cache.caches:
if isinstance(cache.caches[alias], CacheStatTracker):
cache.caches[alias] = cache.caches[alias].cache
if ConnectionProxy:
cache.cache = ConnectionProxy(cache.caches, DEFAULT_CACHE_ALIAS)
# While it can be restored to the original, any views that were
# wrapped with the cache_page decorator will continue to use a
# monkey patched cache.
for alias in cache.caches:
if isinstance(cache.caches[alias], CacheStatTracker):
cache.caches[alias] = cache.caches[alias].cache
if ConnectionProxy:
cache.cache = ConnectionProxy(cache.caches, DEFAULT_CACHE_ALIAS)
# While it can be restored to the original, any views that were
# wrapped with the cache_page decorator will continue to use a
# monkey patched cache.

def generate_stats(self, request, response):
self.record_stats(
Expand Down
2 changes: 1 addition & 1 deletion debug_toolbar/panels/profiling.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def parent_classes(self):

def background(self):
r, g, b = hsv_to_rgb(*self.hsv)
return "rgb({:f}%,{:f}%,{:f}%)".format(r * 100, g * 100, b * 100)
return f"rgb({r * 100:f}%,{g * 100:f}%,{b * 100:f}%)"

def func_std_string(self): # match what old profile produced
func_name = self.func
Expand Down
9 changes: 2 additions & 7 deletions debug_toolbar/panels/settings.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
from collections import OrderedDict

import django
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from django.views.debug import get_default_exception_reporter_filter

from debug_toolbar.panels import Panel

if django.VERSION >= (3, 1):
from django.views.debug import get_default_exception_reporter_filter

get_safe_settings = get_default_exception_reporter_filter().get_safe_settings
else:
from django.views.debug import get_safe_settings
get_safe_settings = get_default_exception_reporter_filter().get_safe_settings


class SettingsPanel(Panel):
Expand Down
2 changes: 1 addition & 1 deletion debug_toolbar/panels/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def generate_stats(self, request, response):
receiver_class_name = getattr(
receiver.__self__, "__class__", type
).__name__
text = "{}.{}".format(receiver_class_name, receiver_name)
text = f"{receiver_class_name}.{receiver_name}"
else:
text = receiver_name
receivers.append(text)
Expand Down
2 changes: 0 additions & 2 deletions debug_toolbar/panels/sql/tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
class SQLQueryTriggered(Exception):
"""Thrown when template panel triggers a query"""

pass


class ThreadLocalState(local):
def __init__(self):
Expand Down
4 changes: 2 additions & 2 deletions debug_toolbar/panels/sql/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def reformat_sql(sql, with_toggle=False):
if not with_toggle:
return formatted
simple = simplify(parse_sql(sql, aligned_indent=False))
uncollapsed = '<span class="djDebugUncollapsed">{}</span>'.format(simple)
collapsed = '<span class="djDebugCollapsed djdt-hidden">{}</span>'.format(formatted)
uncollapsed = f'<span class="djDebugUncollapsed">{simple}</span>'
collapsed = f'<span class="djDebugCollapsed djdt-hidden">{formatted}</span>'
return collapsed + uncollapsed


Expand Down
6 changes: 3 additions & 3 deletions debug_toolbar/panels/sql/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ def sql_explain(request, verified_data):
# SQLite's EXPLAIN dumps the low-level opcodes generated for a query;
# EXPLAIN QUERY PLAN dumps a more human-readable summary
# See https://www.sqlite.org/lang_explain.html for details
cursor.execute("EXPLAIN QUERY PLAN {}".format(sql), params)
cursor.execute(f"EXPLAIN QUERY PLAN {sql}", params)
elif vendor == "postgresql":
cursor.execute("EXPLAIN ANALYZE {}".format(sql), params)
cursor.execute(f"EXPLAIN ANALYZE {sql}", params)
else:
cursor.execute("EXPLAIN {}".format(sql), params)
cursor.execute(f"EXPLAIN {sql}", params)
headers = [d[0] for d in cursor.description]
result = cursor.fetchall()

Expand Down
2 changes: 1 addition & 1 deletion debug_toolbar/panels/templates/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def _request_context_bind_template(self, template):
self.context_processors = OrderedDict()
updates = {}
for processor in processors:
name = "{}.{}".format(processor.__module__, processor.__name__)
name = f"{processor.__module__}.{processor.__name__}"
context = processor(self.request)
self.context_processors[name] = context
updates.update(context)
Expand Down
2 changes: 1 addition & 1 deletion debug_toolbar/panels/templates/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def template_source(request):
except TemplateDoesNotExist:
pass
else:
source = "Template Does Not Exist: {}".format(template_origin_name)
source = f"Template Does Not Exist: {template_origin_name}"

try:
from pygments import highlight
Expand Down
4 changes: 2 additions & 2 deletions debug_toolbar/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_module_path(module_name):
try:
module = import_module(module_name)
except ImportError as e:
raise ImproperlyConfigured("Error importing HIDE_IN_STACKTRACES: {}".format(e))
raise ImproperlyConfigured(f"Error importing HIDE_IN_STACKTRACES: {e}")
else:
source_path = inspect.getsourcefile(module)
if source_path.endswith("__init__.py"):
Expand Down Expand Up @@ -157,7 +157,7 @@ def get_name_from_obj(obj):

if hasattr(obj, "__module__"):
module = obj.__module__
name = "{}.{}".format(module, name)
name = f"{module}.{name}"

return name

Expand Down
3 changes: 1 addition & 2 deletions tests/commands/test_debugsqlshell.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import io
import sys

import django
from django.contrib.auth.models import User
from django.core import management
from django.db import connection
from django.test import TestCase
from django.test.utils import override_settings

if connection.vendor == "postgresql" and django.VERSION >= (3, 0, 0):
if connection.vendor == "postgresql":
from django.db.backends.postgresql import base as base_module
else:
from django.db.backends import utils as base_module
Expand Down
15 changes: 2 additions & 13 deletions tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,8 @@ class Binary(models.Model):
field = models.BinaryField()


try:
from django.db.models import JSONField
except ImportError: # Django<3.1
try:
from django.contrib.postgres.fields import JSONField
except ImportError: # psycopg2 not installed
JSONField = None


if JSONField:

class PostgresJSON(models.Model):
field = JSONField()
class JSON(models.Model):
field = models.JSONField()


if settings.USE_GIS:
Expand Down
Loading