diff options
| author | David Cramer | 2012-01-12 19:13:47 -0800 | 
|---|---|---|
| committer | David Cramer | 2012-01-12 19:13:47 -0800 | 
| commit | 01cd08518ded622d3308dd539b00ebbf7012894e (patch) | |
| tree | a9cca14ff92d4602a51d4999430574587a733d1d /debug_toolbar | |
| parent | c4eeef24faa81e7bc64ebfbd72c046f25c7b3381 (diff) | |
| download | django-debug-toolbar-01cd08518ded622d3308dd539b00ebbf7012894e.tar.bz2 | |
pep8
Diffstat (limited to 'debug_toolbar')
23 files changed, 195 insertions, 170 deletions
| diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 8f0445a..3009b5f 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -5,7 +5,6 @@ import imp  import thread  from django.conf import settings -from django.conf.urls.defaults import include, patterns  from django.http import HttpResponseRedirect  from django.shortcuts import render_to_response  from django.utils.encoding import smart_unicode @@ -16,6 +15,7 @@ from debug_toolbar.toolbar.loader import DebugToolbar  _HTML_TYPES = ('text/html', 'application/xhtml+xml') +  def replace_insensitive(string, target, replacement):      """      Similar to string.replace() but is case insensitive @@ -25,9 +25,10 @@ def replace_insensitive(string, target, replacement):      index = no_case.rfind(target.lower())      if index >= 0:          return string[:index] + replacement + string[index + len(target):] -    else: # no results so return the original string +    else:  # no results so return the original string          return string +  class DebugToolbarMiddleware(object):      """      Middleware to set up Debug Toolbar on incoming request and render toolbar @@ -43,10 +44,10 @@ class DebugToolbarMiddleware(object):          self._urlconfs = {}          # Set method to use to decide to show toolbar -        self.show_toolbar = self._show_toolbar # default +        self.show_toolbar = self._show_toolbar  # default          # The tag to attach the toolbar to -        self.tag= u'</body>' +        self.tag = u'</body>'          if hasattr(settings, 'DEBUG_TOOLBAR_CONFIG'):              show_toolbar_callback = settings.DEBUG_TOOLBAR_CONFIG.get( diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index b4f11fb..f1751d8 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -9,41 +9,41 @@ class DebugPanel(object):      """      # name = 'Base'      # template = 'debug_toolbar/panels/base.html' -    has_content = False # If content returns something, set to true in subclass -     +    has_content = False  # If content returns something, set to true in subclass +      # We'll maintain a local context instance so we can expose our template      # context variables to panels which need them:      context = {} -     +      # Panel methods      def __init__(self, context={}):          self.context.update(context)          self.slug = slugify(self.name) -     +      def dom_id(self):          return 'djDebug%sPanel' % (self.name.replace(' ', '')) -     +      def nav_title(self):          """Title showing in toolbar"""          raise NotImplementedError -     +      def nav_subtitle(self):          """Subtitle showing until title in toolbar"""          return '' -     +      def title(self):          """Title showing in panel"""          raise NotImplementedError -     +      def url(self):          raise NotImplementedError -     +      def content(self):          if self.has_content:              context = self.context.copy()              context.update(self.get_stats())              return render_to_string(self.template, context) -     +      def record_stats(self, stats):          toolbar = DebugToolbarMiddleware.get_current()          panel_stats = toolbar.stats.get(self.slug) @@ -51,17 +51,17 @@ class DebugPanel(object):              panel_stats.update(stats)          else:              toolbar.stats[self.slug] = stats -     +      def get_stats(self):          toolbar = DebugToolbarMiddleware.get_current()          return toolbar.stats.get(self.slug, {}) -     +      # Standard middleware methods      def process_request(self, request):          pass -     +      def process_view(self, request, view_func, view_args, view_kwargs):          pass -     +      def process_response(self, request, response):          pass diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index 620be86..ace343b 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -6,12 +6,13 @@ from django.core.cache.backends.base import BaseCache  from django.utils.translation import ugettext_lazy as _  from debug_toolbar.panels import DebugPanel +  class CacheStatTracker(BaseCache):      """A small class used to track cache calls."""      def __init__(self, cache):          self.cache = cache          self.reset() -     +      def reset(self):          self.calls = []          self.hits = 0 @@ -21,11 +22,11 @@ class CacheStatTracker(BaseCache):          self.get_many = 0          self.deletes = 0          self.total_time = 0 -     +      def _get_func_info(self):          stack = inspect.stack()[2]          return (stack[1], stack[2], stack[3], stack[4]) -     +      def get(self, key, default=None):          t = time.time()          value = self.cache.get(key, default) @@ -38,7 +39,7 @@ class CacheStatTracker(BaseCache):          self.gets += 1          self.calls.append((this_time, 'get', (key,), self._get_func_info()))          return value -     +      def set(self, key, value, timeout=None):          t = time.time()          self.cache.set(key, value, timeout) @@ -46,7 +47,7 @@ class CacheStatTracker(BaseCache):          self.total_time += this_time * 1000          self.sets += 1          self.calls.append((this_time, 'set', (key, value, timeout), self._get_func_info())) -     +      def delete(self, key):          t = time.time()          self.cache.delete(key) @@ -54,7 +55,7 @@ class CacheStatTracker(BaseCache):          self.total_time += this_time * 1000          self.deletes += 1          self.calls.append((this_time, 'delete', (key,), self._get_func_info())) -     +      def get_many(self, keys):          t = time.time()          results = self.cache.get_many(keys) @@ -68,6 +69,7 @@ class CacheStatTracker(BaseCache):                  self.hits += 1          self.calls.append((this_time, 'get_many', (keys,), self._get_func_info())) +  class CacheDebugPanel(DebugPanel):      """      Panel that displays the cache statistics. @@ -75,7 +77,7 @@ class CacheDebugPanel(DebugPanel):      name = 'Cache'      template = 'debug_toolbar/panels/cache.html'      has_content = True -     +      def __init__(self, *args, **kwargs):          super(CacheDebugPanel, self).__init__(*args, **kwargs)          # This is hackish but to prevent threading issues is somewhat needed @@ -85,16 +87,16 @@ class CacheDebugPanel(DebugPanel):          else:              self.cache = CacheStatTracker(cache.cache)              cache.cache = self.cache -     +      def nav_title(self):          return _('Cache: %.2fms') % self.cache.total_time -     +      def title(self):          return _('Cache Usage') -     +      def url(self):          return '' -     +      def process_response(self, request, response):          self.record_stats({              'cache_calls': len(self.cache.calls), diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index 181e88d..9824d0e 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -32,21 +32,21 @@ class HeaderDebugPanel(DebugPanel):          'SERVER_PROTOCOL',          'SERVER_SOFTWARE',      ) -     +      def nav_title(self):          return _('HTTP Headers') -     +      def title(self):          return _('HTTP Headers') -     +      def url(self):          return '' -     +      def process_request(self, request):          self.headers = dict(              [(k, request.META[k]) for k in self.header_filter if k in request.META]          ) -     +      def process_response(self, request, response):          self.record_stats({              'headers': self.headers diff --git a/debug_toolbar/panels/logger.py b/debug_toolbar/panels/logger.py index 55ae9bd..e894b50 100644 --- a/debug_toolbar/panels/logger.py +++ b/debug_toolbar/panels/logger.py @@ -13,16 +13,16 @@ class LogCollector(object):          if threading is None:              raise NotImplementedError("threading module is not available, \                  the logging panel cannot be used without it") -        self.records = {} # a dictionary that maps threads to log records -     +        self.records = {}  # a dictionary that maps threads to log records +      def add_record(self, record, thread=None):          # Avoid logging SQL queries since they are already in the SQL panel          # TODO: Make this check whether SQL panel is enabled          if record.get('channel', '') == 'django.db.backends':              return -         +          self.get_records(thread).append(record) -     +      def get_records(self, thread=None):          """          Returns a list of records for the provided thread, of if none is provided, @@ -33,7 +33,7 @@ class LogCollector(object):          if thread not in self.records:              self.records[thread] = []          return self.records[thread] -     +      def clear_records(self, thread=None):          if thread is None:              thread = threading.currentThread() @@ -45,7 +45,7 @@ class ThreadTrackingHandler(logging.Handler):      def __init__(self, collector):          logging.Handler.__init__(self)          self.collector = collector -     +      def emit(self, record):          record = {              'message': record.getMessage(), @@ -75,7 +75,7 @@ if logbook_supported:          def __init__(self, collector):              logbook.handlers.Handler.__init__(self, bubble=True)              self.collector = collector -         +          def emit(self, record):              record = {                  'message': record.message, @@ -86,37 +86,37 @@ if logbook_supported:                  'channel': record.channel,              }              self.collector.add_record(record) -     -     +      logbook_handler = LogbookThreadTrackingHandler(collector) -    logbook_handler.push_application()        # register with logbook +    logbook_handler.push_application()  # register with logbook +  class LoggingPanel(DebugPanel):      name = 'Logging'      template = 'debug_toolbar/panels/logger.html'      has_content = True -     +      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()          collector.clear_records()          return records -     +      def nav_title(self):          return _("Logging") -     +      def nav_subtitle(self):          # FIXME l10n: use ngettext          return "%s message%s" % (len(collector.get_records()), (len(collector.get_records()) == 1) and '' or 's') -     +      def title(self):          return _('Log Messages') -     +      def url(self):          return '' diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index d07fd2a..f21c345 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -32,7 +32,7 @@ class DjangoDebugToolbarStats(Stats):  class FunctionCall(object):      def __init__(self, statobj, func, depth=0, stats=None, -                 id=0, parent_ids=[], hsv=(0,0.5,1)): +                 id=0, parent_ids=[], hsv=(0, 0.5, 1)):          self.statobj = statobj          self.func = func          if stats: @@ -49,10 +49,10 @@ class FunctionCall(object):          return self.parent_classes      def background(self): -        r,g,b = hsv_to_rgb(*self.hsv) -        return 'rgb(%f%%,%f%%,%f%%)' %(r*100, g*100, b*100) +        r, g, b = hsv_to_rgb(*self.hsv) +        return 'rgb(%f%%,%f%%,%f%%)' % (r * 100, g * 100, b * 100) -    def func_std_string(self): # match what old profile produced +    def func_std_string(self):  # match what old profile produced          func_name = self.func          if func_name[:2] == ('~', 0):              # special case for built-in functions @@ -65,7 +65,7 @@ class FunctionCall(object):              file_name, line_num, method = self.func              idx = file_name.find('/site-packages/')              if idx > -1: -                file_name = file_name[idx+14:] +                file_name = file_name[(idx + 14):]              file_path, file_name = file_name.rsplit(os.sep, 1) @@ -77,23 +77,23 @@ class FunctionCall(object):              ))      def subfuncs(self): -        i=0 +        i = 0          h, s, v = self.hsv          count = len(self.statobj.all_callees[self.func])          for func, stats in self.statobj.all_callees[self.func].iteritems():              i += 1 -            h1 = h + (i/count)/(self.depth+1) +            h1 = h + (i / count) / (self.depth + 1)              if stats[3] == 0:                  s1 = 0              else: -                s1 = s*(stats[3]/self.stats[3]) +                s1 = s * (stats[3] / self.stats[3])              yield FunctionCall(self.statobj,                                 func, -                               self.depth+1, +                               self.depth + 1,                                 stats=stats,                                 id=str(self.id) + '_' + str(i),                                 parent_ids=self.parent_ids + [self.id], -                               hsv=(h1,s1,1)) +                               hsv=(h1, s1, 1))      def count(self):          return self.stats[1] @@ -111,7 +111,7 @@ class FunctionCall(object):          if nc == 0:              return 0 -        return tt/nc +        return tt / nc      def cumtime_per_call(self):          cc, nc, tt, ct = self.stats @@ -119,7 +119,7 @@ class FunctionCall(object):          if cc == 0:              return 0 -        return ct/cc +        return ct / cc      def indent(self):          return 16 * self.depth @@ -136,6 +136,7 @@ class FunctionCall(object):                  self._line_stats_text = False          return self._line_stats_text +  class ProfilingDebugPanel(DebugPanel):      """      Panel that displays the Django version. @@ -201,6 +202,6 @@ class ProfilingDebugPanel(DebugPanel):          root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0)          func_list = [] -        self.add_node(func_list, root, 10, root.stats[3]/8) +        self.add_node(func_list, root, 10, root.stats[3] / 8)          self.record_stats({'func_list': func_list}) diff --git a/debug_toolbar/panels/request_vars.py b/debug_toolbar/panels/request_vars.py index ee9cdc5..4f85052 100644 --- a/debug_toolbar/panels/request_vars.py +++ b/debug_toolbar/panels/request_vars.py @@ -3,6 +3,7 @@ from django.utils.translation import ugettext_lazy as _  from debug_toolbar.panels import DebugPanel  from debug_toolbar.utils import get_name_from_obj +  class RequestVarsDebugPanel(DebugPanel):      """      A panel to display request variables (POST/GET, session, cookies). @@ -10,49 +11,49 @@ class RequestVarsDebugPanel(DebugPanel):      name = 'RequestVars'      template = 'debug_toolbar/panels/request_vars.html'      has_content = True -     +      def __init__(self, *args, **kwargs):          DebugPanel.__init__(self, *args, **kwargs)          self.view_func = None          self.view_args = None          self.view_kwargs = None -     +      def nav_title(self):          return _('Request Vars') -     +      def title(self):          return _('Request Vars') -     +      def url(self):          return '' -     +      def process_request(self, request):          self.request = request -     +      def process_view(self, request, view_func, view_args, view_kwargs):          self.view_func = view_func          self.view_args = view_args          self.view_kwargs = view_kwargs -     +      def process_response(self, request, response):          self.record_stats({              'get': [(k, self.request.GET.getlist(k)) for k in self.request.GET],              'post': [(k, self.request.POST.getlist(k)) for k in self.request.POST],              'cookies': [(k, self.request.COOKIES.get(k)) for k in self.request.COOKIES],          }) -         +          if hasattr(self, 'view_func'):              if self.view_func is not None:                  name = get_name_from_obj(self.view_func)              else:                  name = '<no view>' -             +              self.record_stats({                  'view_func': name,                  'view_args': self.view_args,                  'view_kwargs': self.view_kwargs              }) -         +          if hasattr(self.request, 'session'):              self.record_stats({                  'session': [(k, self.request.session.get(k)) for k in self.request.session.iterkeys()] diff --git a/debug_toolbar/panels/settings_vars.py b/debug_toolbar/panels/settings_vars.py index e154dda..194295e 100644 --- a/debug_toolbar/panels/settings_vars.py +++ b/debug_toolbar/panels/settings_vars.py @@ -11,16 +11,16 @@ class SettingsVarsDebugPanel(DebugPanel):      name = 'SettingsVars'      template = 'debug_toolbar/panels/settings_vars.html'      has_content = True -     +      def nav_title(self):          return _('Settings') -     +      def title(self):          return _('Settings from <code>%s</code>') % settings.SETTINGS_MODULE -     +      def url(self):          return '' -     +      def process_response(self, request, response):          self.record_stats({              'settings': get_safe_settings(), diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py index 1d60292..b7dbffe 100644 --- a/debug_toolbar/panels/signals.py +++ b/debug_toolbar/panels/signals.py @@ -15,6 +15,7 @@ except ImportError:  from debug_toolbar.panels import DebugPanel +  class SignalDebugPanel(DebugPanel):      name = "Signals"      template = 'debug_toolbar/panels/signals.html' diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index b27e6c0..18fffdc 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -18,12 +18,12 @@ from debug_toolbar.utils.tracking import replace_call  @replace_call(BaseDatabaseWrapper.cursor)  def cursor(func, self):      result = func(self) -     +      djdt = DebugToolbarMiddleware.get_current()      if not djdt:          return result      logger = djdt.get_panel(SQLDebugPanel) -     +      return CursorWrapper(result, self, logger=logger) @@ -39,7 +39,7 @@ def get_isolation_level_display(engine, level):          }      else:          raise ValueError(engine) -     +      return choices.get(level) @@ -55,7 +55,7 @@ def get_transaction_status_display(engine, level):          }      else:          raise ValueError(engine) -     +      return choices.get(level) @@ -67,7 +67,7 @@ class SQLDebugPanel(DebugPanel):      name = 'SQL'      template = 'debug_toolbar/panels/sql.html'      has_content = True -     +      def __init__(self, *args, **kwargs):          super(SQLDebugPanel, self).__init__(*args, **kwargs)          self._offset = dict((k, len(connections[k].queries)) for k in connections) @@ -77,33 +77,33 @@ class SQLDebugPanel(DebugPanel):          self._databases = {}          self._transaction_status = {}          self._transaction_ids = {} -     +      def get_transaction_id(self, alias):          conn = connections[alias].connection          if not conn:              return None -         +          engine = conn.__class__.__module__.split('.', 1)[0]          if engine == 'psycopg2':              cur_status = conn.get_transaction_status()          else:              raise ValueError(engine) -         +          last_status = self._transaction_status.get(alias)          self._transaction_status[alias] = cur_status -         +          if not cur_status:              # No available state              return None -         +          if cur_status != last_status:              if cur_status:                  self._transaction_ids[alias] = uuid.uuid4().hex              else:                  self._transaction_ids[alias] = None -         +          return self._transaction_ids[alias] -     +      def record(self, alias, **kwargs):          self._queries.append((alias, kwargs))          if alias not in self._databases: @@ -116,10 +116,10 @@ class SQLDebugPanel(DebugPanel):              self._databases[alias]['num_queries'] += 1          self._sql_time += kwargs['duration']          self._num_queries += 1 -     +      def nav_title(self):          return _('SQL') -     +      def nav_subtitle(self):          # TODO l10n: use ngettext          return "%d %s in %.2fms" % ( @@ -127,30 +127,25 @@ class SQLDebugPanel(DebugPanel):              (self._num_queries == 1) and 'query' or 'queries',              self._sql_time          ) -     +      def title(self):          count = len(self._databases) -         +          return __('SQL Queries from %(count)d connection', 'SQL Queries from %(count)d connections', count) % dict(              count=count,          ) -     +      def url(self):          return '' -     +      def process_response(self, request, response):          if self._queries:              width_ratio_tally = 0 -            colors = [ -                (256, 0, 0), # red -                (0, 256, 0), # blue -                (0, 0, 256), # green -            ] -            factor = int(256.0/(len(self._databases)*2.5)) +            factor = int(256.0 / (len(self._databases) * 2.5))              for n, db in enumerate(self._databases.itervalues()):                  rgb = [0, 0, 0]                  color = n % 3 -                rgb[color] = 256 - n/3*factor +                rgb[color] = 256 - n / 3 * factor                  nn = color                  # XXX: pretty sure this is horrible after so many aliases                  while rgb[color] < factor: @@ -161,23 +156,23 @@ class SQLDebugPanel(DebugPanel):                          nn = 0                      rgb[nn] = nc                  db['rgb_color'] = rgb -             +              trans_ids = {}              trans_id = None              i = 0              for alias, query in self._queries:                  trans_id = query.get('trans_id')                  last_trans_id = trans_ids.get(alias) -                 +                  if trans_id != last_trans_id:                      if last_trans_id: -                        self._queries[i-1][1]['ends_trans'] = True +                        self._queries[(i - 1)][1]['ends_trans'] = True                      trans_ids[alias] = trans_id                      if trans_id:                          query['starts_trans'] = True                  if trans_id:                      query['in_trans'] = True -                 +                  query['alias'] = alias                  if 'iso_level' in query:                      query['iso_level'] = get_isolation_level_display(query['engine'], query['iso_level']) @@ -187,14 +182,14 @@ class SQLDebugPanel(DebugPanel):                  query['rgb_color'] = self._databases[alias]['rgb_color']                  try:                      query['width_ratio'] = (query['duration'] / self._sql_time) * 100 -                    query['width_ratio_relative'] =  100.0 * query['width_ratio'] / (100.0 - width_ratio_tally) +                    query['width_ratio_relative'] = 100.0 * query['width_ratio'] / (100.0 - width_ratio_tally)                  except ZeroDivisionError:                      query['width_ratio'] = 0                      query['width_ratio_relative'] = 0                  query['start_offset'] = width_ratio_tally                  query['end_offset'] = query['width_ratio'] + query['start_offset']                  width_ratio_tally += query['width_ratio'] -                 +                  stacktrace = []                  for frame in query['stacktrace']:                      params = map(escape, frame[0].rsplit('/', 1) + list(frame[1:])) @@ -205,10 +200,10 @@ class SQLDebugPanel(DebugPanel):                          continue                  query['stacktrace'] = mark_safe('\n'.join(stacktrace))                  i += 1 -             +              if trans_id: -                self._queries[i-1][1]['ends_trans'] = True -         +                self._queries[(i - 1)][1]['ends_trans'] = True +          self.record_stats({              'databases': sorted(self._databases.items(), key=lambda x: -x[1]['time_spent']),              'queries': [q for a, q in self._queries], @@ -236,6 +231,6 @@ def swap_fields(sql):  def reformat_sql(sql):      stack = sqlparse.engine.FilterStack() -    stack.preprocess.append(BoldKeywordFilter()) # add our custom filter -    stack.postprocess.append(sqlparse.filters.SerializerUnicode()) # tokens -> strings +    stack.preprocess.append(BoldKeywordFilter())  # add our custom filter +    stack.postprocess.append(sqlparse.filters.SerializerUnicode())  # tokens -> strings      return swap_fields(''.join(stack.run(sql))) diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index a69b42a..48225a0 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -19,7 +19,7 @@ from debug_toolbar.utils.tracking.db import recording, SQLQueryTriggered  from django.test.utils import instrumented_test_render  from django.template import Template -if not hasattr(Template, '_render'): # Django < 1.2 +if not hasattr(Template, '_render'):  # Django < 1.2      if Template.render != instrumented_test_render:          Template.original_render = Template.render          Template.render = instrumented_test_render @@ -31,6 +31,8 @@ else:  # MONSTER monkey-patch  old_template_init = Template.__init__ + +  def new_template_init(self, template_string, origin=None, name='<Unknown Template>'):      old_template_init(self, template_string, origin, name)      self.origin = origin @@ -44,18 +46,18 @@ class TemplateDebugPanel(DebugPanel):      name = 'Template'      template = 'debug_toolbar/panels/templates.html'      has_content = True -     +      def __init__(self, *args, **kwargs):          super(TemplateDebugPanel, self).__init__(*args, **kwargs)          self.templates = []          template_rendered.connect(self._store_template_info) -     +      def _store_template_info(self, sender, **kwargs):          t = kwargs['template']          if t.name and t.name.startswith('debug_toolbar/'):              return  # skip templates that we are generating through the debug toolbar.          context_data = kwargs['context'] -         +          context_list = []          for context_layer in context_data.dicts:              temp_layer = {} @@ -95,20 +97,20 @@ class TemplateDebugPanel(DebugPanel):                  pass          kwargs['context'] = context_list          self.templates.append(kwargs) -     +      def nav_title(self):          return _('Templates') -     +      def title(self):          num_templates = len(self.templates)          return _('Templates (%(num_templates)s rendered)') % {'num_templates': num_templates} -     +      def url(self):          return '' -     +      def process_request(self, request):          self.request = request -     +      def process_response(self, request, response):          context_processors = dict(              [ @@ -133,7 +135,7 @@ class TemplateDebugPanel(DebugPanel):                  context_list = template_data.get('context', [])                  info['context'] = '\n'.join(context_list)              template_context.append(info) -         +          self.record_stats({              'templates': template_context,              'template_dirs': [normpath(x) for x in settings.TEMPLATE_DIRS], diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index 943dd8a..7428e83 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -1,7 +1,7 @@  try:      import resource  except ImportError: -    pass # Will fail on Win32 systems +    pass  # Will fail on Win32 systems  import time  from django.template.loader import render_to_string  from django.utils.translation import ugettext_lazy as _ @@ -14,7 +14,7 @@ class TimerDebugPanel(DebugPanel):      """      name = 'Timer'      template = 'debug_toolbar/panels/timer.html' -    try: # if resource module not available, don't show content panel +    try:  # if resource module not available, don't show content panel          resource      except NameError:          has_content = False @@ -92,5 +92,5 @@ class TimerDebugPanel(DebugPanel):          )          context = self.context.copy() -        context.update({'rows': rows,}) +        context.update({'rows': rows})          return render_to_string(self.template, context) diff --git a/debug_toolbar/panels/version.py b/debug_toolbar/panels/version.py index 8ac0e82..3d4303d 100644 --- a/debug_toolbar/panels/version.py +++ b/debug_toolbar/panels/version.py @@ -14,19 +14,19 @@ class VersionDebugPanel(DebugPanel):      name = 'Version'      template = 'debug_toolbar/panels/versions.html'      has_content = True -     +      def nav_title(self):          return _('Versions') -     +      def nav_subtitle(self):          return 'Django %s' % django.get_version() -     +      def url(self):          return '' -     +      def title(self):          return _('Versions') -     +      def process_response(self, request, response):          versions = {}          versions['Python'] = '%d.%d.%d' % sys.version_info[:3] @@ -49,7 +49,7 @@ class VersionDebugPanel(DebugPanel):              if isinstance(version, (list, tuple)):                  version = '.'.join(str(o) for o in version)              versions[name] = version -         +          self.record_stats({              'versions': versions,              'paths': sys.path, diff --git a/debug_toolbar/templatetags/debug_toolbar_utils.py b/debug_toolbar/templatetags/debug_toolbar_utils.py index 6b204eb..c057312 100644 --- a/debug_toolbar/templatetags/debug_toolbar_utils.py +++ b/debug_toolbar/templatetags/debug_toolbar_utils.py @@ -4,8 +4,9 @@ from django.utils.numberformat import format  register = template.Library() +  @register.filter  def dotted_number(number):      number = float(number)      return format(number, '.', 6) -     + diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py index cf7a243..a69c314 100644 --- a/debug_toolbar/toolbar/loader.py +++ b/debug_toolbar/toolbar/loader.py @@ -1,15 +1,17 @@  """  The main DebugToolbar class that loads and renders the Toolbar.  """ -import os.path, os +import os +import os.path  from django.conf import settings  from django.template.loader import render_to_string  from django.utils.datastructures import SortedDict  from django.utils.safestring import mark_safe +  class DebugToolbar(object): -     +      def __init__(self, request):          self.request = request          self._panels = SortedDict() @@ -21,7 +23,7 @@ class DebugToolbar(object):          # Check if settings has a DEBUG_TOOLBAR_CONFIG and updated config          self.config.update(getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}))          self.template_context = { -            'BASE_URL': base_url, # for backwards compatibility +            'BASE_URL': base_url,  # for backwards compatibility              'DEBUG_TOOLBAR_MEDIA_URL': self.config.get('MEDIA_URL'),          }          # Override this tuple by copying to settings.py as `DEBUG_TOOLBAR_PANELS` @@ -39,31 +41,31 @@ class DebugToolbar(object):          )          self.load_panels()          self.stats = {} -     +      def _get_panels(self):          return self._panels.values()      panels = property(_get_panels) -     +      def get_panel(self, cls):          return self._panels[cls] -     +      def load_panels(self):          """          Populate debug panels          """          from django.conf import settings          from django.core import exceptions -         +          # Check if settings has a DEBUG_TOOLBAR_PANELS, otherwise use default          if hasattr(settings, 'DEBUG_TOOLBAR_PANELS'):              self.default_panels = settings.DEBUG_TOOLBAR_PANELS -         +          for panel_path in self.default_panels:              try:                  dot = panel_path.rindex('.')              except ValueError:                  raise exceptions.ImproperlyConfigured, '%s isn\'t a debug panel module' % panel_path -            panel_module, panel_classname = panel_path[:dot], panel_path[dot+1:] +            panel_module, panel_classname = panel_path[:dot], panel_path[(dot + 1):]              try:                  mod = __import__(panel_module, {}, {}, [''])              except ImportError, e: @@ -72,25 +74,25 @@ class DebugToolbar(object):                  panel_class = getattr(mod, panel_classname)              except AttributeError:                  raise exceptions.ImproperlyConfigured, 'Toolbar Panel module "%s" does not define a "%s" class' % (panel_module, panel_classname) -             +              try:                  panel_instance = panel_class(context=self.template_context)              except: -                raise # Bubble up problem loading panel -             +                raise  # Bubble up problem loading panel +              self._panels[panel_class] = panel_instance -     +      def render_toolbar(self):          """          Renders the overall Toolbar with panels inside.          """          media_path = os.path.join(os.path.dirname(__file__), os.pardir, 'media', 'debug_toolbar') -         +          context = self.template_context.copy()          context.update({              'panels': self.panels,              'js': mark_safe(open(os.path.join(media_path, 'js', 'toolbar.min.js'), 'r').read()),              'css': mark_safe(open(os.path.join(media_path, 'css', 'toolbar.min.css'), 'r').read()),          }) -         +          return render_to_string('debug_toolbar/base.html', context) diff --git a/debug_toolbar/urls.py b/debug_toolbar/urls.py index 77491e3..986b78e 100644 --- a/debug_toolbar/urls.py +++ b/debug_toolbar/urls.py @@ -1,11 +1,10 @@  """ -URLpatterns for the debug toolbar.  +URLpatterns for the debug toolbar.  These should not be loaded explicitly; the debug toolbar middleware will patch  this into the urlconf for the request.  """  from django.conf.urls.defaults import * -from django.conf import settings  _PREFIX = '__debug__' diff --git a/debug_toolbar/utils/__init__.py b/debug_toolbar/utils/__init__.py index 45dfc6f..01f817a 100644 --- a/debug_toolbar/utils/__init__.py +++ b/debug_toolbar/utils/__init__.py @@ -11,12 +11,14 @@ from django.views.debug import linebreak_iter  django_path = os.path.realpath(os.path.dirname(django.__file__))  socketserver_path = os.path.realpath(os.path.dirname(SocketServer.__file__)) +  def ms_from_timedelta(td):      """      Given a timedelta object, returns a float representing milliseconds      """      return (td.seconds * 1000) + (td.microseconds / 1000.0) +  def tidy_stacktrace(stack):      """      Clean up stacktrace and remove all entries that: @@ -45,6 +47,7 @@ def tidy_stacktrace(stack):          trace.append((path, line_no, func_name, text))      return trace +  def get_template_info(source, context_lines=3):      line = 0      upto = 0 @@ -79,6 +82,7 @@ def get_template_info(source, context_lines=3):          'context': context,      } +  def get_name_from_obj(obj):      if hasattr(obj, '__name__'):          name = obj.__name__ @@ -93,6 +97,7 @@ def get_name_from_obj(obj):      return name +  def getframeinfo(frame, context=1):      """      Get information about a frame or traceback object. @@ -116,7 +121,7 @@ def getframeinfo(frame, context=1):      filename = inspect.getsourcefile(frame) or inspect.getfile(frame)      if context > 0: -        start = lineno - 1 - context//2 +        start = lineno - 1 - context // 2          try:              lines, lnum = inspect.findsource(frame)          except (IOError, IndexError): @@ -124,7 +129,7 @@ def getframeinfo(frame, context=1):          else:              start = max(start, 1)              start = max(0, min(start, len(lines) - context)) -            lines = lines[start:start+context] +            lines = lines[start:(start + context)]              index = lineno - 1 - start      else:          lines = index = None @@ -134,6 +139,7 @@ def getframeinfo(frame, context=1):      else:          return (filename, lineno, frame.f_code.co_name, lines, index) +  def get_stack(context=1):      """      Get a list of records for a frame and all higher (calling) frames. @@ -148,4 +154,4 @@ def get_stack(context=1):      while frame:          framelist.append((frame,) + getframeinfo(frame, context))          frame = frame.f_back -    return framelist
\ No newline at end of file +    return framelist diff --git a/debug_toolbar/utils/compat/db.py b/debug_toolbar/utils/compat/db.py index 4273d9e..6ff09ec 100644 --- a/debug_toolbar/utils/compat/db.py +++ b/debug_toolbar/utils/compat/db.py @@ -10,4 +10,4 @@ except ImportError:          'default': {              'ENGINE': settings.DATABASE_ENGINE,          } -    }
\ No newline at end of file +    } diff --git a/debug_toolbar/utils/sqlparse/engine/filter.py b/debug_toolbar/utils/sqlparse/engine/filter.py index c1c0d6a..a31c5de 100644 --- a/debug_toolbar/utils/sqlparse/engine/filter.py +++ b/debug_toolbar/utils/sqlparse/engine/filter.py @@ -61,7 +61,7 @@ class StatementFilter(TokenFilter):          if unified == 'END':              # Should this respect a preceeding BEGIN?              # In CASE ... WHEN ... END this results in a split level -1. -            self._begin_depth = max(0, self._begin_depth-1) +            self._begin_depth = max(0, self._begin_depth - 1)              return -1          if ttype is T.Keyword.DDL and unified.startswith('CREATE'): diff --git a/debug_toolbar/utils/sqlparse/filters.py b/debug_toolbar/utils/sqlparse/filters.py index 2d247e7..897cc90 100644 --- a/debug_toolbar/utils/sqlparse/filters.py +++ b/debug_toolbar/utils/sqlparse/filters.py @@ -146,13 +146,14 @@ class ReindentFilter(Filter):          split_words = ('FROM', 'JOIN$', 'AND', 'OR',                         'GROUP', 'ORDER', 'UNION', 'VALUES',                         'SET', 'BETWEEN') +          def _next_token(i):              t = tlist.token_next_match(i, T.Keyword, split_words,                                         regex=True)              if t and t.value.upper() == 'BETWEEN': -                t = _next_token(tlist.token_index(t)+1) +                t = _next_token(tlist.token_index(t) + 1)                  if t and t.value.upper() == 'AND': -                    t = _next_token(tlist.token_index(t)+1) +                    t = _next_token(tlist.token_index(t) + 1)              return t          idx = 0 diff --git a/debug_toolbar/utils/sqlparse/sql.py b/debug_toolbar/utils/sqlparse/sql.py index 55bf804..2f9f538 100644 --- a/debug_toolbar/utils/sqlparse/sql.py +++ b/debug_toolbar/utils/sqlparse/sql.py @@ -146,7 +146,7 @@ class TokenList(Token):      def _pprint_tree(self, max_depth=None, depth=0):          """Pretty-print the object tree.""" -        indent = ' '*(depth*2) +        indent = ' ' * (depth * 2)          for idx, token in enumerate(self.tokens):              if token.is_group():                  pre = ' +-' @@ -156,7 +156,7 @@ class TokenList(Token):                                          token._get_repr_name(),                                          token._get_repr_value())              if (token.is_group() and (max_depth is None or depth < max_depth)): -                token._pprint_tree(max_depth, depth+1) +                token._pprint_tree(max_depth, depth + 1)      def flatten(self):          """Generator yielding ungrouped tokens. diff --git a/debug_toolbar/utils/tracking/__init__.py b/debug_toolbar/utils/tracking/__init__.py index db8ff18..9c72803 100644 --- a/debug_toolbar/utils/tracking/__init__.py +++ b/debug_toolbar/utils/tracking/__init__.py @@ -2,18 +2,21 @@ import logging  import time  import types +  def post_dispatch(func):      def wrapped(callback):          register_hook(func, 'after', callback)          return callback      return wrapped +  def pre_dispatch(func):      def wrapped(callback):          register_hook(func, 'before', callback)          return callback      return wrapped +  def replace_call(func):      def inner(callback):          def wrapped(*args, **kwargs): @@ -28,6 +31,7 @@ def replace_call(func):          return wrapped      return inner +  def fire_hook(hook, sender, **kwargs):      try:          for callback in callbacks[hook].get(id(sender), []): @@ -36,6 +40,7 @@ def fire_hook(hook, sender, **kwargs):          # Log the exception, dont mess w/ the underlying function          logging.exception(e) +  def _replace_function(func, wrapped):      if isinstance(func, types.FunctionType):          if func.__module__ == '__builtin__': @@ -58,6 +63,7 @@ callbacks = {      'after': {},  } +  def register_hook(func, hook, callback):      """      def myhook(sender, args, kwargs): @@ -81,10 +87,10 @@ def register_hook(func, hook, callback):      wrapped.__wrapped__ = actual      wrapped.__doc__ = getattr(actual, '__doc__', None)      wrapped.__name__ = actual.__name__ -     +      id_ = id(actual)      if id_ not in callbacks[hook]:          callbacks[hook][id_] = []      callbacks[hook][id_].append(callback) -    _replace_function(func, wrapped)
\ No newline at end of file +    _replace_function(func, wrapped) diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py index dd9916b..3fa809a 100644 --- a/debug_toolbar/views.py +++ b/debug_toolbar/views.py @@ -14,12 +14,15 @@ from django.utils.hashcompat import sha_constructor  from debug_toolbar.utils.compat.db import connections +  class InvalidSQLError(Exception):      def __init__(self, value):          self.value = value +      def __str__(self):          return repr(self.value) +  def debug_media(request, path):      root = getattr(settings, 'DEBUG_TOOLBAR_MEDIA_ROOT', None)      if root is None: @@ -27,6 +30,7 @@ def debug_media(request, path):          root = os.path.join(parent, 'media', 'debug_toolbar')      return django.views.static.serve(request, path, root) +  def sql_select(request):      """      Returns the output of the SQL SELECT statement. @@ -43,7 +47,7 @@ def sql_select(request):      alias = request.GET.get('alias', 'default')      hash = sha_constructor(settings.SECRET_KEY + sql + params).hexdigest()      if hash != request.GET.get('hash', ''): -        return HttpResponseBadRequest('Tamper alert') # SQL Tampering alert +        return HttpResponseBadRequest('Tamper alert')  # SQL Tampering alert      if sql.lower().strip().startswith('select'):          params = simplejson.loads(params)          cursor = connections[alias].cursor() @@ -61,6 +65,7 @@ def sql_select(request):          return render_to_response('debug_toolbar/panels/sql_select.html', context)      raise InvalidSQLError("Only 'select' queries are allowed.") +  def sql_explain(request):      """      Returns the output of the SQL EXPLAIN on the given query. @@ -77,7 +82,7 @@ def sql_explain(request):      alias = request.GET.get('alias', 'default')      hash = sha_constructor(settings.SECRET_KEY + sql + params).hexdigest()      if hash != request.GET.get('hash', ''): -        return HttpResponseBadRequest('Tamper alert') # SQL Tampering alert +        return HttpResponseBadRequest('Tamper alert')  # SQL Tampering alert      if sql.lower().strip().startswith('select'):          params = simplejson.loads(params)          cursor = connections[alias].cursor() @@ -106,6 +111,7 @@ def sql_explain(request):          return render_to_response('debug_toolbar/panels/sql_explain.html', context)      raise InvalidSQLError("Only 'select' queries are allowed.") +  def sql_profile(request):      """      Returns the output of running the SQL and getting the profiling statistics. @@ -122,7 +128,7 @@ def sql_profile(request):      alias = request.GET.get('alias', 'default')      hash = sha_constructor(settings.SECRET_KEY + sql + params).hexdigest()      if hash != request.GET.get('hash', ''): -        return HttpResponseBadRequest('Tamper alert') # SQL Tampering alert +        return HttpResponseBadRequest('Tamper alert')  # SQL Tampering alert      if sql.lower().strip().startswith('select'):          params = simplejson.loads(params)          cursor = connections[alias].cursor() @@ -130,9 +136,9 @@ def sql_profile(request):          headers = None          result_error = None          try: -            cursor.execute("SET PROFILING=1") # Enable profiling -            cursor.execute(sql, params) # Execute SELECT -            cursor.execute("SET PROFILING=0") # Disable profiling +            cursor.execute("SET PROFILING=1")  # Enable profiling +            cursor.execute(sql, params)  # Execute SELECT +            cursor.execute("SET PROFILING=0")  # Disable profiling              # The Query ID should always be 1 here but I'll subselect to get the last one just in case...              cursor.execute("SELECT * FROM information_schema.profiling WHERE query_id=(SELECT query_id FROM information_schema.profiling ORDER BY query_id DESC LIMIT 1)")              headers = [d[0] for d in cursor.description] @@ -151,6 +157,7 @@ def sql_profile(request):          return render_to_response('debug_toolbar/panels/sql_profile.html', context)      raise InvalidSQLError("Only 'select' queries are allowed.") +  def template_source(request):      """      Return the source of a template, syntax-highlighted by Pygments if @@ -164,7 +171,7 @@ def template_source(request):      if template_name is None:          return HttpResponseBadRequest('"template" key is required') -    try: # Django 1.2 ... +    try:  # Django 1.2 ...          from django.template.loader import find_template_loader, make_origin          loaders = []          for loader_name in settings.TEMPLATE_LOADERS: @@ -178,7 +185,7 @@ def template_source(request):                  break              except TemplateDoesNotExist:                  source = "Template Does Not Exist: %s" % (template_name,) -    except (ImportError, AttributeError): # Django 1.1 ... +    except (ImportError, AttributeError):  # Django 1.1 ...          from django.template.loader import find_template_source          source, origin = find_template_source(template_name) | 
