diff options
| -rw-r--r-- | debug_toolbar/panels/__init__.py | 11 | ||||
| -rw-r--r-- | debug_toolbar/panels/profiling.py | 6 | ||||
| -rw-r--r-- | debug_toolbar/panels/redirects.py | 5 | ||||
| -rw-r--r-- | debug_toolbar/panels/request.py | 8 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/panel.py | 21 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/tracking.py | 10 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/views.py | 8 | ||||
| -rw-r--r-- | debug_toolbar/panels/templates/panel.py | 6 | ||||
| -rw-r--r-- | debug_toolbar/settings.py | 27 | ||||
| -rw-r--r-- | debug_toolbar/static/debug_toolbar/js/toolbar.js | 2 | ||||
| -rw-r--r-- | debug_toolbar/templates/debug_toolbar/panels/sql.html | 2 | ||||
| -rw-r--r-- | docs/changes.rst | 26 | ||||
| -rw-r--r-- | docs/configuration.rst | 21 | ||||
| -rw-r--r-- | docs/panels.rst | 2 | 
14 files changed, 114 insertions, 41 deletions
| diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index 178ea6f..74b0734 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -4,6 +4,9 @@ import warnings  from django.template.loader import render_to_string +from debug_toolbar import settings as dt_settings +from debug_toolbar.utils import get_name_from_obj +  class Panel(object):      """ @@ -20,7 +23,13 @@ class Panel(object):      @property      def enabled(self): -        return self.toolbar.request.COOKIES.get('djdt' + self.panel_id, 'on') == 'on' +        # Check to see if settings has a default value for it +        if get_name_from_obj(self) in dt_settings.CONFIG['DISABLE_PANELS']: +            default = 'off' +        else: +            default = 'on' +        # The user's cookies should override the default value +        return self.toolbar.request.COOKIES.get('djdt' + self.panel_id, default) == 'on'      # Titles and content diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 7399c16..9020799 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -3,6 +3,7 @@ from __future__ import absolute_import, division, unicode_literals  from django.utils.translation import ugettext_lazy as _  from django.utils.safestring import mark_safe  from debug_toolbar.panels import Panel +from debug_toolbar import settings as dt_settings  import cProfile  from pstats import Stats @@ -152,6 +153,9 @@ class ProfilingPanel(Panel):          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, +                      dt_settings.CONFIG['PROFILER_MAX_DEPTH'], +                      root.stats[3] / 8)          self.record_stats({'func_list': func_list}) diff --git a/debug_toolbar/panels/redirects.py b/debug_toolbar/panels/redirects.py index 8bd5aba..757c65c 100644 --- a/debug_toolbar/panels/redirects.py +++ b/debug_toolbar/panels/redirects.py @@ -12,11 +12,6 @@ class RedirectsPanel(Panel):      Panel that intercepts redirects and displays a page with debug info.      """ -    @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") diff --git a/debug_toolbar/panels/request.py b/debug_toolbar/panels/request.py index b98ef22..b5caa52 100644 --- a/debug_toolbar/panels/request.py +++ b/debug_toolbar/panels/request.py @@ -17,6 +17,14 @@ class RequestPanel(Panel):      title = _("Request") +    @property +    def nav_subtitle(self): +        """ +        Show abbreviated name of view function as subtitle +        """ +        view_func = self.get_stats().get('view_func', '') +        return view_func.rsplit('.', 1)[-1] +      def process_response(self, request, response):          self.record_stats({              'get': [(k, request.GET.getlist(k)) for k in sorted(request.GET)], diff --git a/debug_toolbar/panels/sql/panel.py b/debug_toolbar/panels/sql/panel.py index f6ce954..5531964 100644 --- a/debug_toolbar/panels/sql/panel.py +++ b/debug_toolbar/panels/sql/panel.py @@ -15,8 +15,8 @@ from debug_toolbar.panels.sql.utils import reformat_sql, contrasting_color_gener  from debug_toolbar.panels.sql.tracking import wrap_cursor, unwrap_cursor -def get_isolation_level_display(engine, level): -    if engine == 'psycopg2': +def get_isolation_level_display(vendor, level): +    if vendor == 'postgresql':          import psycopg2.extensions          choices = {              psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT: _("Autocommit"), @@ -26,12 +26,12 @@ def get_isolation_level_display(engine, level):              psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE: _("Serializable"),          }      else: -        raise ValueError(engine) +        raise ValueError(vendor)      return choices.get(level) -def get_transaction_status_display(engine, level): -    if engine == 'psycopg2': +def get_transaction_status_display(vendor, level): +    if vendor == 'postgresql':          import psycopg2.extensions          choices = {              psycopg2.extensions.TRANSACTION_STATUS_IDLE: _("Idle"), @@ -41,7 +41,7 @@ def get_transaction_status_display(engine, level):              psycopg2.extensions.TRANSACTION_STATUS_UNKNOWN: _("Unknown"),          }      else: -        raise ValueError(engine) +        raise ValueError(vendor)      return choices.get(level) @@ -67,11 +67,10 @@ class SQLPanel(Panel):          if not conn:              return -        engine = conn.__class__.__module__.split('.', 1)[0] -        if engine == 'psycopg2': +        if conn.vendor == 'postgresql':              cur_status = conn.get_transaction_status()          else: -            raise ValueError(engine) +            raise ValueError(conn.vendor)          last_status = self._transaction_status.get(alias)          self._transaction_status[alias] = cur_status @@ -175,10 +174,10 @@ class SQLPanel(Panel):                  query['alias'] = alias                  if 'iso_level' in query: -                    query['iso_level'] = get_isolation_level_display(query['engine'], +                    query['iso_level'] = get_isolation_level_display(query['vendor'],                                                                       query['iso_level'])                  if 'trans_status' in query: -                    query['trans_status'] = get_transaction_status_display(query['engine'], +                    query['trans_status'] = get_transaction_status_display(query['vendor'],                                                                             query['trans_status'])                  query['form'] = SQLSelectForm(auto_id=None, initial=copy(query)) diff --git a/debug_toolbar/panels/sql/tracking.py b/debug_toolbar/panels/sql/tracking.py index 68c77e2..b6a787d 100644 --- a/debug_toolbar/panels/sql/tracking.py +++ b/debug_toolbar/panels/sql/tracking.py @@ -131,14 +131,10 @@ class NormalCursorWrapper(object):              alias = getattr(self.db, 'alias', 'default')              conn = self.db.connection -            # HACK: avoid imports -            if conn: -                engine = conn.__class__.__module__.split('.', 1)[0] -            else: -                engine = 'unknown' +            vendor = getattr(conn, 'vendor', 'unknown')              params = { -                'engine': engine, +                'vendor': vendor,                  'alias': alias,                  'sql': self.db.ops.last_executed_query(                      self.cursor, sql, self._quote_params(params)), @@ -153,7 +149,7 @@ class NormalCursorWrapper(object):                  'template_info': template_info,              } -            if engine == 'psycopg2': +            if vendor == 'postgresql':                  # If an erroneous query was ran on the connection, it might                  # be in a state where checking isolation_level raises an                  # exception. diff --git a/debug_toolbar/panels/sql/views.py b/debug_toolbar/panels/sql/views.py index 05ad74f..d8c94a0 100644 --- a/debug_toolbar/panels/sql/views.py +++ b/debug_toolbar/panels/sql/views.py @@ -39,17 +39,15 @@ def sql_explain(request):      if form.is_valid():          sql = form.cleaned_data['raw_sql']          params = form.cleaned_data['params'] +        vendor = form.connection.vendor          cursor = form.cursor -        conn = form.connection -        engine = conn.__class__.__module__.split('.', 1)[0] - -        if engine == "sqlite3": +        if vendor == 'sqlite':              # SQLite's EXPLAIN dumps the low-level opcodes generated for a query;              # EXPLAIN QUERY PLAN dumps a more human-readable summary              # See http://www.sqlite.org/lang_explain.html for details              cursor.execute("EXPLAIN QUERY PLAN %s" % (sql,), params) -        elif engine == "psycopg2": +        elif vendor == 'postgresql':              cursor.execute("EXPLAIN ANALYZE %s" % (sql,), params)          else:              cursor.execute("EXPLAIN %s" % (sql,), params) diff --git a/debug_toolbar/panels/templates/panel.py b/debug_toolbar/panels/templates/panel.py index 74f28b0..4ee7772 100644 --- a/debug_toolbar/panels/templates/panel.py +++ b/debug_toolbar/panels/templates/panel.py @@ -145,6 +145,12 @@ class TemplatesPanel(Panel):          num_templates = len(self.templates)          return _("Templates (%(num_templates)s rendered)") % {'num_templates': num_templates} +    @property +    def nav_subtitle(self): +        if self.templates: +            return self.templates[0]['template'].name +        return '' +      template = 'debug_toolbar/panels/templates.html'      @classmethod diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py index 48649fd..5c1cd3d 100644 --- a/debug_toolbar/settings.py +++ b/debug_toolbar/settings.py @@ -16,6 +16,7 @@ from django.utils import six  CONFIG_DEFAULTS = {      # Toolbar options +    'DISABLE_PANELS': set(['debug_toolbar.panels.redirects.RedirectsPanel']),      'INSERT_BEFORE': '</body>',      'RENDER_PANELS': None,      'RESULTS_STORE_SIZE': 10, @@ -32,7 +33,7 @@ CONFIG_DEFAULTS = {          'debug_toolbar',          'django',      ), -    'INTERCEPT_REDIRECTS': False, +    'PROFILER_MAX_DEPTH': 10,      'SHOW_TEMPLATE_CONTEXT': True,      'SQL_WARNING_THRESHOLD': 500,   # milliseconds  } @@ -125,6 +126,30 @@ else:              PANELS[index] = new_panel +if 'INTERCEPT_REDIRECTS' in USER_CONFIG: +    warnings.warn( +        "INTERCEPT_REDIRECTS is deprecated. Please use the " +        "DISABLE_PANELS config in the" +        "DEBUG_TOOLBAR_CONFIG setting.", DeprecationWarning) +    if USER_CONFIG['INTERCEPT_REDIRECTS']: +        if 'debug_toolbar.panels.redirects.RedirectsPanel' \ +                in CONFIG['DISABLE_PANELS']: +            # RedirectsPanel should be enabled +            try: +                CONFIG['DISABLE_PANELS'].remove( +                    'debug_toolbar.panels.redirects.RedirectsPanel' +                ) +            except KeyError: +                # We wanted to remove it, but it didn't exist. This is fine +                pass +    elif not 'debug_toolbar.panels.redirects.RedirectsPanel' \ +            in CONFIG['DISABLE_PANELS']: +        # RedirectsPanel should be disabled +        CONFIG['DISABLE_PANELS'].add( +            'debug_toolbar.panels.redirects.RedirectsPanel' +        ) + +  PATCH_SETTINGS = getattr(settings, 'DEBUG_TOOLBAR_PATCH_SETTINGS', settings.DEBUG) diff --git a/debug_toolbar/static/debug_toolbar/js/toolbar.js b/debug_toolbar/static/debug_toolbar/js/toolbar.js index 126f399..cb40205 100644 --- a/debug_toolbar/static/debug_toolbar/js/toolbar.js +++ b/debug_toolbar/static/debug_toolbar/js/toolbar.js @@ -160,8 +160,8 @@                      setTimeout(function () {                          djdt.handleDragged = false;                      }, 10); +                    return false;                  } -                return false;              });              $(document).bind('close.djDebug', function() {                  // If a sub-panel is open, close that diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index 4d95a80..7dab547 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -49,7 +49,7 @@  								<button formaction="{% url 'djdt:sql_select' %}" class="remoteCall">Sel</button>  								<button formaction="{% url 'djdt:sql_explain' %}" class="remoteCall">Expl</button> -								{% if query.engine == 'mysql' or query.engine == 'MySQLdb' %} +								{% if query.vendor == 'mysql' %}  									<button formaction="{% url 'djdt:sql_profile' %}" class="remoteCall">Prof</button>  								{% endif %}  							</form> diff --git a/docs/changes.rst b/docs/changes.rst index 4c3012a..5020466 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -1,6 +1,32 @@  Change log  ========== +1.1 +--- + +This is the first version compatible with Django 1.7. + +New features +~~~~~~~~~~~~ + +* The SQL panel colors queries depending on the stack level. +* The Profiler panel allows configuring the maximum depth. + +Bugfixes +~~~~~~~~ + +* Support languages where lowercase and uppercase strings may have different +  lengths. +* Allow using cursor as context managers. +* Make the SQL explain more helpful on SQLite. +* Various JavaScript improvements. + +Deprecated features +~~~~~~~~~~~~~~~~~~~ + +* The `INTERCEPT_REDIRECT` setting is superseded by the more generic +  `DISABLE_PANELS`. +  1.0  --- diff --git a/docs/configuration.rst b/docs/configuration.rst index 88226cd..ff4ece7 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -57,6 +57,13 @@ toolbar itself, others are specific to some panels.  Toolbar options  ~~~~~~~~~~~~~~~ +* ``DISABLE_PANELS`` + +  Default: ``set(['debug_toolbar.panels.redirects.RedirectsPanel'])`` + +  This setting is a set of the full Python paths to each panel that you +  want disabled (but still displayed) by default. +  * ``INSERT_BEFORE``    Default: ``'</body>'`` @@ -106,8 +113,8 @@ Toolbar options    This is the dotted path to a function used for determining whether the    toolbar should show or not. The default checks are that ``DEBUG`` must be    set to ``True``, the IP of the request must be in ``INTERNAL_IPS``, and the -  request must no be an AJAX request. You can provide your own function that -  accepts a request in argument and returns ``True`` or ``False``. +  request must no be an AJAX request. You can provide your own function  +  ``callback(request)`` which returns ``True`` or ``False``.  Panel options  ~~~~~~~~~~~~~ @@ -142,13 +149,14 @@ Panel options    Useful for eliminating server-related entries which can result    in enormous DOM structures and toolbar rendering delays. -* ``INTERCEPT_REDIRECTS`` +* ``PROFILER_MAX_DEPTH`` -  Default: ``False`` +  Default: ``10`` -  Panel: redirects +  Panel: profiling -  If set to ``True``, the redirect panel will be active by default. +  This setting affects the depth of function calls in the profiler's +  analysis.  * ``SHOW_TEMPLATE_CONTEXT`` @@ -178,6 +186,5 @@ Here's what a slightly customized toolbar configuration might look like::          'RESULTS_STORE_SIZE': 3,          'SHOW_COLLAPSED': True,          # Panel options -        'INTERCEPT_REDIRECTS': True,          'SQL_WARNING_THRESHOLD': 100,   # milliseconds      } diff --git a/docs/panels.rst b/docs/panels.rst index ed7abbf..58713b4 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -103,7 +103,7 @@ ready.  Since this behavior is annoying when you aren't debugging a redirect, this  panel is included but inactive by default. You can activate it by default with -the ``INTERCEPT_REDIRECTS`` configuration option. +the ``DISABLE_PANELS`` configuration option.  Non-default built-in panels | 
