From 57a6e261c2768503e1401f99cefd4470c8dc5e8f Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sun, 24 Nov 2013 17:30:49 +0100 Subject: Update all panels to follow the public API. --- debug_toolbar/panels/cache.py | 9 ++-- debug_toolbar/panels/headers.py | 13 ++---- debug_toolbar/panels/logging.py | 31 +++++-------- debug_toolbar/panels/profiling.py | 10 +--- debug_toolbar/panels/redirects.py | 11 ++--- debug_toolbar/panels/request.py | 8 +--- debug_toolbar/panels/settings.py | 5 +- debug_toolbar/panels/signals.py | 8 +--- debug_toolbar/panels/sql/panel.py | 33 +++++++------- debug_toolbar/panels/templates/panel.py | 22 ++++----- debug_toolbar/panels/timer.py | 81 ++++++++++++++------------------- debug_toolbar/panels/versions.py | 13 ++---- tests/panels/test_profiling.py | 2 +- tests/panels/test_request.py | 4 +- tests/panels/test_sql.py | 2 +- tests/panels/test_template.py | 2 +- 16 files changed, 103 insertions(+), 151 deletions(-) diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index c2808a1..d08723f 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -131,9 +131,7 @@ class CachePanel(Panel): """ Panel that displays the cache statistics. """ - name = 'Cache' template = 'debug_toolbar/panels/cache.html' - has_content = True def __init__(self, *args, **kwargs): super(CachePanel, self).__init__(*args, **kwargs) @@ -183,9 +181,11 @@ class CachePanel(Panel): 'backend': backend }) - def nav_title(self): - return _('Cache') + # Implement the Panel API + nav_title = _('Cache') + + @property def nav_subtitle(self): cache_calls = len(self.calls) return ungettext('%(cache_calls)d call in %(time).2fms', @@ -193,6 +193,7 @@ class CachePanel(Panel): cache_calls) % {'cache_calls': cache_calls, 'time': self.total_time} + @property def title(self): count = len(getattr(settings, 'CACHES', ['default'])) return ungettext('Cache calls from %(count)d backend', diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index 3ee499d..0138299 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -12,11 +12,8 @@ class HeadersPanel(Panel): """ A panel to display HTTP headers. """ - name = 'Headers' - template = 'debug_toolbar/panels/headers.html' - has_content = True # List of environment variables we want to display - environ_filter = set(( + ENVIRON_FILTER = set(( 'CONTENT_LENGTH', 'CONTENT_TYPE', 'DJANGO_SETTINGS_MODULE', @@ -35,11 +32,9 @@ class HeadersPanel(Panel): 'TZ', )) - def nav_title(self): - return _('Headers') + title = _('Headers') - def title(self): - return _('Headers') + template = 'debug_toolbar/panels/headers.html' def process_request(self, request): wsgi_env = list(sorted(request.META.items())) @@ -48,7 +43,7 @@ class HeadersPanel(Panel): if 'Cookie' in self.request_headers: self.request_headers['Cookie'] = '=> see Request panel' self.environ = OrderedDict( - (k, v) for (k, v) in wsgi_env if k in self.environ_filter) + (k, v) for (k, v) in wsgi_env if k in self.ENVIRON_FILTER) self.record_stats({ 'request_headers': self.request_headers, 'environ': self.environ, diff --git a/debug_toolbar/panels/logging.py b/debug_toolbar/panels/logging.py index a37e000..f07281b 100644 --- a/debug_toolbar/panels/logging.py +++ b/debug_toolbar/panels/logging.py @@ -105,35 +105,28 @@ if logbook_supported: class LoggingPanel(Panel): - name = 'Logging' template = 'debug_toolbar/panels/logging.html' - has_content = True def __init__(self, *args, **kwargs): super(LoggingPanel, self).__init__(*args, **kwargs) self._records = {} - def process_request(self, request): - collector.clear_records() - - def process_response(self, request, response): - records = self.get_and_delete() - self.record_stats({'records': records}) - - def get_and_delete(self): - records = collector.get_records() - self._records[threading.currentThread()] = records - collector.clear_records() - return records - - def nav_title(self): - return _("Logging") + nav_title = _("Logging") + @property def nav_subtitle(self): records = self._records[threading.currentThread()] record_count = len(records) return ungettext('%(count)s message', '%(count)s messages', record_count) % {'count': record_count} - def title(self): - return _('Log Messages') + title = _('Log Messages') + + def process_request(self, request): + collector.clear_records() + + def process_response(self, request, response): + records = collector.get_records() + self._records[threading.currentThread()] = records + collector.clear_records() + self.record_stats({'records': records}) diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 9443e34..f4d32c4 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -144,15 +144,9 @@ class ProfilingPanel(Panel): """ Panel that displays profiling information. """ - name = 'Profiling' - template = 'debug_toolbar/panels/profiling.html' - has_content = True - - def nav_title(self): - return _('Profiling') + title = _('Profiling') - def title(self): - return _('Profiling') + template = 'debug_toolbar/panels/profiling.html' def _unwrap_closure_and_profile(self, func): if not hasattr(func, '__code__'): diff --git a/debug_toolbar/panels/redirects.py b/debug_toolbar/panels/redirects.py index 9deeb69..52b2077 100644 --- a/debug_toolbar/panels/redirects.py +++ b/debug_toolbar/panels/redirects.py @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals from django.core.handlers.wsgi import STATUS_CODE_TEXT from django.shortcuts import render -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import Panel @@ -11,15 +11,16 @@ class RedirectsPanel(Panel): """ Panel that intercepts redirects and displays a page with debug info. """ - name = 'Redirects' - - has_content = False @property def enabled(self): default = 'on' if self.toolbar.config['INTERCEPT_REDIRECTS'] else 'off' return self.toolbar.request.COOKIES.get('djdt' + self.panel_id, default) == 'on' + has_content = False + + nav_title = _('Intercept redirects') + def process_response(self, request, response): if 300 <= int(response.status_code) < 400: redirect_to = response.get('Location', None) @@ -36,5 +37,3 @@ class RedirectsPanel(Panel): response.cookies = cookies return response - def nav_title(self): - return _('Intercept redirects') diff --git a/debug_toolbar/panels/request.py b/debug_toolbar/panels/request.py index 934946a..28f5e22 100644 --- a/debug_toolbar/panels/request.py +++ b/debug_toolbar/panels/request.py @@ -13,15 +13,9 @@ class RequestPanel(Panel): """ A panel to display request variables (POST/GET, session, cookies). """ - name = 'Request' template = 'debug_toolbar/panels/request.html' - has_content = True - def nav_title(self): - return _('Request') - - def title(self): - return _('Request') + title = _('Request') def process_response(self, request, response): self.record_stats({ diff --git a/debug_toolbar/panels/settings.py b/debug_toolbar/panels/settings.py index b7af57d..2729128 100644 --- a/debug_toolbar/panels/settings.py +++ b/debug_toolbar/panels/settings.py @@ -12,12 +12,9 @@ class SettingsPanel(Panel): """ A panel to display all variables in django.conf.settings """ - name = 'Settings' template = 'debug_toolbar/panels/settings.html' - has_content = True - def nav_title(self): - return _('Settings') + nav_title = _('Settings') def title(self): return _('Settings from %s') % settings.SETTINGS_MODULE diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py index 74d1faa..269f091 100644 --- a/debug_toolbar/panels/signals.py +++ b/debug_toolbar/panels/signals.py @@ -14,9 +14,7 @@ from debug_toolbar.panels import Panel class SignalsPanel(Panel): - name = "Signals" template = 'debug_toolbar/panels/signals.html' - has_content = True SIGNALS = { 'request_started': request_started, @@ -33,9 +31,6 @@ class SignalsPanel(Panel): 'post_syncdb': post_syncdb, } - def nav_title(self): - return _("Signals") - def nav_subtitle(self): signals = self.get_stats()['signals'] num_receivers = sum(len(s[2]) for s in signals) @@ -51,8 +46,7 @@ class SignalsPanel(Panel): num_receivers) % {'num_receivers': num_receivers, 'num_signals': num_signals} - def title(self): - return _("Signals") + title = _("Signals") @property def signals(self): diff --git a/debug_toolbar/panels/sql/panel.py b/debug_toolbar/panels/sql/panel.py index 3bfbe60..f4133db 100644 --- a/debug_toolbar/panels/sql/panel.py +++ b/debug_toolbar/panels/sql/panel.py @@ -49,10 +49,6 @@ class SQLPanel(Panel): Panel that displays information about the SQL queries run while processing the request. """ - name = 'SQL' - template = 'debug_toolbar/panels/sql.html' - has_content = True - def __init__(self, *args, **kwargs): super(SQLPanel, self).__init__(*args, **kwargs) self._offset = dict((k, len(connections[k].queries)) for k in connections) @@ -104,26 +100,31 @@ class SQLPanel(Panel): self._sql_time += kwargs['duration'] self._num_queries += 1 - @classmethod - def get_urls(cls): - return patterns('debug_toolbar.panels.sql.views', # noqa - url(r'^sql_select/$', 'sql_select', name='sql_select'), - url(r'^sql_explain/$', 'sql_explain', name='sql_explain'), - url(r'^sql_profile/$', 'sql_profile', name='sql_profile'), - ) + # Implement the Panel API - def nav_title(self): - return _('SQL') + nav_title = _('SQL') + @property def nav_subtitle(self): return __("%d query in %.2fms", "%d queries in %.2fms", self._num_queries) % (self._num_queries, self._sql_time) + @property def title(self): count = len(self._databases) - return __('SQL Queries from %(count)d connection', - 'SQL Queries from %(count)d connections', - count) % dict(count=count) + return __('SQL queries from %(count)d connection', + 'SQL queries from %(count)d connections', + count) % {'count': count} + + template = 'debug_toolbar/panels/sql.html' + + @classmethod + def get_urls(cls): + return patterns('debug_toolbar.panels.sql.views', # noqa + url(r'^sql_select/$', 'sql_select', name='sql_select'), + url(r'^sql_explain/$', 'sql_explain', name='sql_explain'), + url(r'^sql_profile/$', 'sql_profile', name='sql_profile'), + ) def enable_instrumentation(self): # This is thread-safe because database connections are thread-local. diff --git a/debug_toolbar/panels/templates/panel.py b/debug_toolbar/panels/templates/panel.py index c745b83..ec0fc47 100644 --- a/debug_toolbar/panels/templates/panel.py +++ b/debug_toolbar/panels/templates/panel.py @@ -48,10 +48,6 @@ class TemplatesPanel(Panel): """ A panel that lists all templates used during processing of a response. """ - name = 'Templates' - template = 'debug_toolbar/panels/templates.html' - has_content = True - def __init__(self, *args, **kwargs): super(TemplatesPanel, self).__init__(*args, **kwargs) self.templates = [] @@ -113,19 +109,23 @@ class TemplatesPanel(Panel): kwargs['context'] = [force_text(item) for item in context_list] self.templates.append(kwargs) - @classmethod - def get_urls(cls): - return patterns('debug_toolbar.panels.templates.views', # noqa - url(r'^template_source/$', 'template_source', name='template_source'), - ) + # Implement the Panel API - def nav_title(self): - return _('Templates') + nav_title = _('Templates') + @property def title(self): num_templates = len(self.templates) return _('Templates (%(num_templates)s rendered)') % {'num_templates': num_templates} + template = 'debug_toolbar/panels/templates.html' + + @classmethod + def get_urls(cls): + return patterns('debug_toolbar.panels.templates.views', # noqa + url(r'^template_source/$', 'template_source', name='template_source'), + ) + def process_response(self, request, response): context_processors = dict( [ diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index 900b624..6df4d4d 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -1,9 +1,9 @@ from __future__ import absolute_import, unicode_literals try: - import resource + import resource # Not available on Win32 systems except ImportError: - pass # Will fail on Win32 systems + resource = None import time from django.template.loader import render_to_string from django.utils.translation import ugettext as _ @@ -14,21 +14,44 @@ class TimerPanel(Panel): """ Panel that displays the time a response took in milliseconds. """ - name = 'Timer' + + def nav_subtitle(self): + stats = self.get_stats() + if hasattr(self, '_start_rusage'): + utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime + stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime + return _('CPU: %(cum)0.2fms (%(total)0.2fms)') % { + 'cum': (utime + stime) * 1000.0, + 'total': stats['total_time'] + } + elif 'total_time' in stats: + return _('TOTAL: %0.2fms') % stats['total_time'] + else: + return '' + + has_content = resource is not None + + title = _('Time') + template = 'debug_toolbar/panels/timer.html' - try: # if resource module not available, don't show content panel - resource - except NameError: - has_content = False - has_resource = False - else: - has_content = True - has_resource = True + @property + def content(self): + stats = self.get_stats() + rows = ( + (_('User CPU time'), _('%(utime)0.3f msec') % stats), + (_('System CPU time'), _('%(stime)0.3f msec') % stats), + (_('Total CPU time'), _('%(total)0.3f msec') % stats), + (_('Elapsed time'), _('%(total_time)0.3f msec') % stats), + (_('Context switches'), _('%(vcsw)d voluntary, %(ivcsw)d involuntary') % stats), + ) + context = self.context.copy() + context.update({'rows': rows}) + return render_to_string(self.template, context) def process_request(self, request): self._start_time = time.time() - if self.has_resource: + if self.has_content: self._start_rusage = resource.getrusage(resource.RUSAGE_SELF) def process_response(self, request, response): @@ -58,39 +81,5 @@ class TimerPanel(Panel): self.record_stats(stats) - def nav_title(self): - return _('Timer') - - def nav_subtitle(self): - stats = self.get_stats() - - if hasattr(self, '_start_rusage'): - utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime - stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime - return _('CPU: %(cum)0.2fms (%(total)0.2fms)') % { - 'cum': (utime + stime) * 1000.0, - 'total': stats['total_time'] - } - elif 'total_time' in stats: - return _('TOTAL: %0.2fms') % stats['total_time'] - else: - return '' - - def title(self): - return _('Time') - def _elapsed_ru(self, name): return getattr(self._end_rusage, name) - getattr(self._start_rusage, name) - - def content(self): - stats = self.get_stats() - rows = ( - (_('User CPU time'), _('%(utime)0.3f msec') % stats), - (_('System CPU time'), _('%(stime)0.3f msec') % stats), - (_('Total CPU time'), _('%(total)0.3f msec') % stats), - (_('Elapsed time'), _('%(total_time)0.3f msec') % stats), - (_('Context switches'), _('%(vcsw)d voluntary, %(ivcsw)d involuntary') % stats), - ) - context = self.context.copy() - context.update({'rows': rows}) - return render_to_string(self.template, context) diff --git a/debug_toolbar/panels/versions.py b/debug_toolbar/panels/versions.py index 6028115..529c2b9 100644 --- a/debug_toolbar/panels/versions.py +++ b/debug_toolbar/panels/versions.py @@ -15,18 +15,13 @@ class VersionsPanel(Panel): """ Shows versions of Python, Django, and installed apps if possible. """ - name = 'Versions' - template = 'debug_toolbar/panels/versions.html' - has_content = True - - def nav_title(self): - return _('Versions') - + @property def nav_subtitle(self): return 'Django %s' % django.get_version() - def title(self): - return _('Versions') + title = _('Versions') + + template = 'debug_toolbar/panels/versions.html' def process_response(self, request, response): versions = [('Python', '%d.%d.%d' % sys.version_info[:3])] diff --git a/tests/panels/test_profiling.py b/tests/panels/test_profiling.py index ccc8f2f..7e61c62 100644 --- a/tests/panels/test_profiling.py +++ b/tests/panels/test_profiling.py @@ -28,7 +28,7 @@ class ProfilingPanelTestCase(BaseTestCase): self.panel.process_view(self.request, regular_view, ('profiling',), {}) self.panel.process_response(self.request, self.response) self.assertIn('func_list', self.panel.get_stats()) - self.assertIn('regular_view', self.panel.content()) + self.assertIn('regular_view', self.panel.content) # These two tests fail randomly for a reason I don't understand. diff --git a/tests/panels/test_request.py b/tests/panels/test_request.py index 16843c4..1c60ec7 100644 --- a/tests/panels/test_request.py +++ b/tests/panels/test_request.py @@ -19,7 +19,7 @@ class RequestPanelTestCase(BaseTestCase): self.request.session['là'.encode('utf-8')] = 'là'.encode('utf-8') self.panel.process_request(self.request) self.panel.process_response(self.request, self.response) - content = self.panel.content() + content = self.panel.content if six.PY3: self.assertIn('où', content) else: @@ -30,4 +30,4 @@ class RequestPanelTestCase(BaseTestCase): self.request.path = '/non_ascii_request/' self.panel.process_request(self.request) self.panel.process_response(self.request, self.response) - self.assertIn('nôt åscíì', self.panel.content()) + self.assertIn('nôt åscíì', self.panel.content) diff --git a/tests/panels/test_sql.py b/tests/panels/test_sql.py index a6990a3..ece533c 100644 --- a/tests/panels/test_sql.py +++ b/tests/panels/test_sql.py @@ -55,7 +55,7 @@ class SQLPanelTestCase(BaseTestCase): self.panel.process_response(self.request, self.response) # ensure the panel renders correctly - self.assertIn('café', self.panel.content()) + self.assertIn('café', self.panel.content) @unittest.skipUnless(connection.vendor == 'postgresql', 'Test valid only on PostgreSQL') diff --git a/tests/panels/test_template.py b/tests/panels/test_template.py index 8cb29f2..f964727 100644 --- a/tests/panels/test_template.py +++ b/tests/panels/test_template.py @@ -46,4 +46,4 @@ class TemplatesPanelTestCase(BaseTestCase): c = Context({'object': NonAsciiRepr()}) t.render(c) self.panel.process_response(self.request, self.response) - self.assertIn('nôt åscíì', self.panel.content()) + self.assertIn('nôt åscíì', self.panel.content) -- cgit v1.2.3