aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAymeric Augustin2013-11-12 22:05:52 +0100
committerAymeric Augustin2013-11-12 22:15:50 +0100
commitf48039e3bad9e24a59a25ed5636b428e11784da9 (patch)
treedbb6471cbf1ceb504d9932639b3ca40a57b89a31
parentc1d50fc79645c71987ae156d371777dd371c422d (diff)
downloaddjango-debug-toolbar-f48039e3bad9e24a59a25ed5636b428e11784da9.tar.bz2
Move the logic to load panels inside the DebugToolbar class.
This has the additional advantage of eliminating a side-effect that happened at import time unnecessarily. It justified refactoring the way we handle settings and defaults.
-rw-r--r--debug_toolbar/middleware.py6
-rw-r--r--debug_toolbar/models.py5
-rw-r--r--debug_toolbar/panels/cache.py4
-rw-r--r--debug_toolbar/panels/signals.py4
-rw-r--r--debug_toolbar/panels/template.py4
-rw-r--r--debug_toolbar/toolbar.py80
-rw-r--r--debug_toolbar/utils/settings.py24
-rw-r--r--debug_toolbar/utils/tracking/db.py6
-rw-r--r--tests/__init__.py14
9 files changed, 78 insertions, 69 deletions
diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py
index 80e8ae0..44d0700 100644
--- a/debug_toolbar/middleware.py
+++ b/debug_toolbar/middleware.py
@@ -12,7 +12,7 @@ from django.shortcuts import render
from django.utils.encoding import force_text
from debug_toolbar.toolbar import DebugToolbar
-from debug_toolbar.utils.settings import CONFIG
+from debug_toolbar.utils import settings as dt_settings
_HTML_TYPES = ('text/html', 'application/xhtml+xml')
# Handles python threading module bug - http://bugs.python.org/issue14308
@@ -52,10 +52,10 @@ class DebugToolbarMiddleware(object):
def __init__(self):
# The method to call to decide to show the toolbar
- self.show_toolbar = CONFIG['SHOW_TOOLBAR_CALLBACK'] or show_toolbar
+ self.show_toolbar = dt_settings.CONFIG['SHOW_TOOLBAR_CALLBACK'] or show_toolbar
# The tag to attach the toolbar to
- self.tag = '</%s>' % CONFIG['TAG']
+ self.tag = '</%s>' % dt_settings.CONFIG['TAG']
def process_request(self, request):
__traceback_hide__ = True # noqa
diff --git a/debug_toolbar/models.py b/debug_toolbar/models.py
index d39e7ec..a204b13 100644
--- a/debug_toolbar/models.py
+++ b/debug_toolbar/models.py
@@ -5,7 +5,6 @@ from django.conf.urls import include, patterns, url
from django.core.urlresolvers import reverse, NoReverseMatch
from django.utils.importlib import import_module
-from debug_toolbar.toolbar import load_panel_classes
from debug_toolbar.middleware import DebugToolbarMiddleware
@@ -59,7 +58,3 @@ if settings.DEBUG:
patch_internal_ips()
patch_middleware_classes()
patch_root_urlconf()
-
-
-if is_toolbar_middleware_installed():
- load_panel_classes()
diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py
index 831eacb..7d42c1f 100644
--- a/debug_toolbar/panels/cache.py
+++ b/debug_toolbar/panels/cache.py
@@ -16,7 +16,7 @@ from django.utils.translation import ugettext_lazy as _, ungettext
from debug_toolbar.panels import DebugPanel
from debug_toolbar.utils import (tidy_stacktrace, render_stacktrace,
get_template_info, get_stack)
-from debug_toolbar.utils.settings import CONFIG
+from debug_toolbar.utils import settings as dt_settings
cache_called = Signal(providing_args=[
@@ -29,7 +29,7 @@ def send_signal(method):
value = method(self, *args, **kwargs)
t = time.time() - t
- if CONFIG['ENABLE_STACKTRACES']:
+ if dt_settings.CONFIG['ENABLE_STACKTRACES']:
stacktrace = tidy_stacktrace(reversed(get_stack()))
else:
stacktrace = []
diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py
index 3dd035a..1d24b80 100644
--- a/debug_toolbar/panels/signals.py
+++ b/debug_toolbar/panels/signals.py
@@ -16,7 +16,7 @@ except ImportError:
connection_created = None
from debug_toolbar.panels import DebugPanel
-from debug_toolbar.utils.settings import CONFIG
+from debug_toolbar.utils import settings as dt_settings
class SignalDebugPanel(DebugPanel):
@@ -63,7 +63,7 @@ class SignalDebugPanel(DebugPanel):
@property
def signals(self):
signals = self.SIGNALS.copy()
- for signal in CONFIG['EXTRA_SIGNALS']:
+ for signal in dt_settings.CONFIG['EXTRA_SIGNALS']:
mod_path, signal_name = signal.rsplit('.', 1)
signals_mod = import_module(mod_path)
signals[signal_name] = getattr(signals_mod, signal_name)
diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py
index 172765a..d918cd7 100644
--- a/debug_toolbar/panels/template.py
+++ b/debug_toolbar/panels/template.py
@@ -15,7 +15,7 @@ from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
from debug_toolbar.utils.tracking.db import recording, SQLQueryTriggered
-from debug_toolbar.utils.settings import CONFIG
+from debug_toolbar.utils import settings as dt_settings
# Code taken and adapted from Simon Willison and Django Snippets:
# http://www.djangosnippets.org/snippets/766/
@@ -140,7 +140,7 @@ class TemplateDebugPanel(DebugPanel):
template.origin_name = 'No origin'
info['template'] = template
# Clean up context for better readability
- if CONFIG['SHOW_TEMPLATE_CONTEXT']:
+ if dt_settings.CONFIG['SHOW_TEMPLATE_CONTEXT']:
context_list = template_data.get('context', [])
info['context'] = '\n'.join(context_list)
template_context.append(info)
diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py
index c0c210f..32dc1b7 100644
--- a/debug_toolbar/toolbar.py
+++ b/debug_toolbar/toolbar.py
@@ -5,11 +5,12 @@ The main DebugToolbar class that loads and renders the Toolbar.
from __future__ import unicode_literals
from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
from django.template.loader import render_to_string
from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module
-from debug_toolbar.utils.settings import CONFIG
+from debug_toolbar.utils import settings as dt_settings
class DebugToolbar(object):
@@ -19,7 +20,7 @@ class DebugToolbar(object):
self._panels = SortedDict()
base_url = self.request.META.get('SCRIPT_NAME', '')
self.config = {}
- self.config.update(CONFIG)
+ self.config.update(dt_settings.CONFIG)
self.template_context = {
'BASE_URL': base_url, # for backwards compatibility
'STATIC_URL': settings.STATIC_URL,
@@ -40,8 +41,7 @@ class DebugToolbar(object):
"""
Populate debug panels
"""
- global panel_classes
- for panel_class in panel_classes:
+ for panel_class in self.get_panel_classes():
panel_instance = panel_class(self, context=self.template_context)
self._panels[panel_class] = panel_instance
@@ -65,7 +65,7 @@ class DebugToolbar(object):
cls = type(self)
cls._counter += 1
cls._storage[cls._counter] = self
- for _ in range(len(cls._storage) - CONFIG['RESULTS_CACHE_SIZE']):
+ for _ in range(len(cls._storage) - dt_settings.CONFIG['RESULTS_CACHE_SIZE']):
# When we drop support for Python 2.6 and switch to
# collections.OrderedDict, use popitem(last=False).
del cls._storage[cls._storage.keyOrder[0]]
@@ -75,45 +75,35 @@ class DebugToolbar(object):
def fetch(cls, storage_id):
return cls._storage.get(storage_id)
+ # Manually implement class-level caching of the list of panels because
+ # it's more obvious than going through an abstraction.
+ _panel_classes = None
-panel_classes = []
-
-
-def load_panel_classes():
- from django.conf import settings
- from django.core.exceptions import ImproperlyConfigured
-
- # Check if settings has a DEBUG_TOOLBAR_PANELS, otherwise use default
- panels = getattr(settings, 'DEBUG_TOOLBAR_PANELS', (
- 'debug_toolbar.panels.version.VersionDebugPanel',
- 'debug_toolbar.panels.timer.TimerDebugPanel',
- 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel',
- 'debug_toolbar.panels.headers.HeaderDebugPanel',
- 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
- 'debug_toolbar.panels.sql.SQLDebugPanel',
- 'debug_toolbar.panels.template.TemplateDebugPanel',
- 'debug_toolbar.panels.cache.CacheDebugPanel',
- 'debug_toolbar.panels.signals.SignalDebugPanel',
- 'debug_toolbar.panels.logger.LoggingPanel',
- ))
- for panel_path in panels:
- try:
- dot = panel_path.rindex('.')
- except ValueError:
- raise ImproperlyConfigured(
- "%s isn't a debug panel module" % panel_path)
- panel_module, panel_classname = panel_path[:dot], panel_path[dot + 1:]
- try:
- mod = import_module(panel_module)
- except ImportError as e:
- raise ImproperlyConfigured(
- 'Error importing debug panel %s: "%s"' %
- (panel_module, e))
- try:
- panel_class = getattr(mod, panel_classname)
- except AttributeError:
- raise ImproperlyConfigured(
- 'Toolbar Panel module "%s" does not define a "%s" class' %
- (panel_module, panel_classname))
- panel_classes.append(panel_class)
+ @classmethod
+ def get_panel_classes(cls):
+ if cls._panel_classes is None:
+ # Load panels in a temporary variable for thread safety.
+ panel_classes = []
+ for panel_path in dt_settings.PANELS:
+ # This logic could be replaced with import_by_path in Django 1.6.
+ try:
+ panel_module, panel_classname = panel_path.rsplit('.', 1)
+ except ValueError:
+ raise ImproperlyConfigured(
+ "%s isn't a debug panel module" % panel_path)
+ try:
+ mod = import_module(panel_module)
+ except ImportError as e:
+ raise ImproperlyConfigured(
+ 'Error importing debug panel %s: "%s"' %
+ (panel_module, e))
+ try:
+ panel_class = getattr(mod, panel_classname)
+ except AttributeError:
+ raise ImproperlyConfigured(
+ 'Toolbar Panel module "%s" does not define a "%s" class' %
+ (panel_module, panel_classname))
+ panel_classes.append(panel_class)
+ cls._panel_classes = panel_classes
+ return cls._panel_classes
diff --git a/debug_toolbar/utils/settings.py b/debug_toolbar/utils/settings.py
index 12dc231..45f661f 100644
--- a/debug_toolbar/utils/settings.py
+++ b/debug_toolbar/utils/settings.py
@@ -4,6 +4,13 @@ from django.conf import settings
from django.utils import six
+# Always import this module as follows:
+# from debug_toolbar.utils import settings [as dt_settings]
+
+# Don't import directly CONFIG or PANELs, or you will miss changes performed
+# with override_settings in tests.
+
+
CONFIG_DEFAULTS = {
'INTERCEPT_REDIRECTS': False,
'SHOW_TOOLBAR_CALLBACK': None,
@@ -27,3 +34,20 @@ CONFIG_DEFAULTS = {
CONFIG = {}
CONFIG.update(CONFIG_DEFAULTS)
CONFIG.update(getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}))
+
+
+PANELS_DEFAULTS = (
+ 'debug_toolbar.panels.version.VersionDebugPanel',
+ 'debug_toolbar.panels.timer.TimerDebugPanel',
+ 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel',
+ 'debug_toolbar.panels.headers.HeaderDebugPanel',
+ 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
+ 'debug_toolbar.panels.sql.SQLDebugPanel',
+ 'debug_toolbar.panels.template.TemplateDebugPanel',
+ 'debug_toolbar.panels.cache.CacheDebugPanel',
+ 'debug_toolbar.panels.signals.SignalDebugPanel',
+ 'debug_toolbar.panels.logger.LoggingPanel',
+)
+
+
+PANELS = getattr(settings, 'DEBUG_TOOLBAR_PANELS', PANELS_DEFAULTS)
diff --git a/debug_toolbar/utils/tracking/db.py b/debug_toolbar/utils/tracking/db.py
index 157334a..fd56ff9 100644
--- a/debug_toolbar/utils/tracking/db.py
+++ b/debug_toolbar/utils/tracking/db.py
@@ -11,7 +11,7 @@ from django.utils.encoding import force_text
from django.utils import six
from debug_toolbar.utils import tidy_stacktrace, get_template_info, get_stack
-from debug_toolbar.utils.settings import CONFIG
+from debug_toolbar.utils import settings as dt_settings
class SQLQueryTriggered(Exception):
@@ -92,7 +92,7 @@ class NormalCursorWrapper(object):
finally:
stop_time = time()
duration = (stop_time - start_time) * 1000
- if CONFIG['ENABLE_STACKTRACES']:
+ if dt_settings.CONFIG['ENABLE_STACKTRACES']:
stacktrace = tidy_stacktrace(reversed(get_stack()))
else:
stacktrace = []
@@ -135,7 +135,7 @@ class NormalCursorWrapper(object):
'stacktrace': stacktrace,
'start_time': start_time,
'stop_time': stop_time,
- 'is_slow': duration > CONFIG['SQL_WARNING_THRESHOLD'],
+ 'is_slow': duration > dt_settings.CONFIG['SQL_WARNING_THRESHOLD'],
'is_select': sql.lower().strip().startswith('select'),
'template_info': template_info,
}
diff --git a/tests/__init__.py b/tests/__init__.py
index 0abb8a3..b3b9440 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,7 +1,7 @@
# Refresh the debug toolbar's configuration when overriding settings.
-from debug_toolbar.utils.settings import CONFIG, CONFIG_DEFAULTS
-from debug_toolbar.toolbar import load_panel_classes, panel_classes # noqa
+from debug_toolbar.toolbar import DebugToolbar
+from debug_toolbar.utils import settings as dt_settings
from django.dispatch import receiver
from django.test.signals import setting_changed
@@ -10,13 +10,13 @@ from django.test.signals import setting_changed
@receiver(setting_changed)
def update_toolbar_config(**kwargs):
if kwargs['setting'] == 'DEBUG_TOOLBAR_CONFIG':
- CONFIG.update(CONFIG_DEFAULTS)
- CONFIG.update(kwargs['value'] or {})
+ dt_settings.CONFIG = {}
+ dt_settings.CONFIG.update(dt_settings.CONFIG_DEFAULTS)
+ dt_settings.CONFIG.update(kwargs['value'] or {})
@receiver(setting_changed)
def update_toolbar_panels(**kwargs):
if kwargs['setting'] == 'DEBUG_TOOLBAR_PANELS':
- global panel_classes
- panel_classes = [] # noqa
- load_panel_classes()
+ dt_settings.PANELS = kwargs['value'] or dt_settings.PANELS_DEFAULTS
+ DebugToolbar._panel_classes = None