Skip to content

Objects state panel #157

New issue

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

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

Already on GitHub? Sign in to your account

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Currently, the following panels have been written and are working:
- SQL queries including time to execute and links to EXPLAIN each query
- List of signals, their args and receivers
- Logging output via Python's built-in logging, or via the `logbook <http://logbook.pocoo.org>`_ module
- State of available objects in the project - how much objects was created/udpated/deleted
- Added HTML Validator panel which provide list of HTML warnings/errors on the page

There is also one Django management command currently:

Expand All @@ -30,6 +32,12 @@ Installation

#. Add the `debug_toolbar` directory to your Python path.

#. Execute

``pip install pytidylib``

*pytidylib required only for `HTMLValidationDebugPanel`*

#. Add the following middleware to your project's `settings.py` file:

``'debug_toolbar.middleware.DebugToolbarMiddleware',``
Expand Down Expand Up @@ -85,6 +93,8 @@ The debug toolbar has two settings that can be set in `settings.py`:
'debug_toolbar.panels.sql.SQLDebugPanel',
'debug_toolbar.panels.signals.SignalDebugPanel',
'debug_toolbar.panels.logger.LoggingPanel',
'debug_toolbar.panels.state.StateDebugPanel',
'debug_toolbar.panels.htmlvalidator.HTMLValidationDebugPanel',
)

You can change the ordering of this tuple to customize the order of the
Expand Down
5 changes: 5 additions & 0 deletions debug_toolbar/management/commands/debugsqlshell.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from optparse import make_option
from datetime import datetime

from django.core.management.base import NoArgsCommand
from django.db.backends import util
Expand All @@ -8,12 +9,16 @@

class PrintQueryWrapper(util.CursorDebugWrapper):
def execute(self, sql, params=()):
starttime = datetime.today()
try:
return self.cursor.execute(sql, params)
finally:
raw_sql = self.db.ops.last_executed_query(self.cursor, sql, params)
execution_time = datetime.today() - starttime
print sqlparse.format(raw_sql, reindent=True)
print
print 'Execution time: %fs' % execution_time.total_seconds()
print

util.CursorDebugWrapper = PrintQueryWrapper

Expand Down
155 changes: 155 additions & 0 deletions debug_toolbar/media/debug_toolbar/css/toolbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -575,3 +575,158 @@
display: none;
}
}


/**
* State panel style
*/
#djDebug .created,
#djDebug tr.created-obj {
background-color:#83F7A8;
}

#djDebug .updated,
#djDebug tr.updated-obj {
background-color:#82E3F7;
}
#djDebug .deleted,
#djDebug tr.deleted-obj {
background-color:#F79A83;
}

#djDebug span.deleted,
#djDebug span.updated,
#djDebug span.created {
display:inline;
display:inline-block;
padding:3px;
}

#djDebug .djDebug-state-summary {
overflow:hidden;
width:100%;
}
#djDebug .djDebug-state-summary legend {
font-size:1.3em;
padding-top:1em;
}

#djDebug .djDebug-state-summary dl {
clear:both;
margin-top:15px;
}
#djDebug dt.deleted {
float:left;
}
#djDebug .panelContent .djDebug-state-summary dt,
#djDebug .panelContent .djDebug-state-summary dd {
margin:0; padding:0;
float:left;
}

#djDebug .panelContent .djDebug-state-summary dt {
font-size:1.2em;
padding-left:0.3em;
padding-right:0.3em;
}

#djDebug .panelContent .djDebug-state-summary dd {
font-size:1.4em;
font-weight:bold;
padding-left:10px;
padding-right:20px;
line-height:1.2em;
}

#djDebug table th.io-cell,
#djDebug table td.io-cell {
border-top:1px solid #fff;
text-align:center;
}

/**
* HTML Validator panel style
*/
#djDebug .panelContent .djDebug-htmlvalidator-summary {
/* pass */
}

#djDebug .panelContent .djDebug-htmlvalidator-summary legend {
font-size:1.4em;
padding-bottom:0.5em;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary pre {
display:block;
font-family:"Courier New", courier, fixed;
font-weight:bold;
cursor:pointer;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary td.tidy-msg {
width:90%;
cursor:pointer;
}
#djDebug .panelContent .djDebug-htmlvalidator-summary td.validation-error {
background-color:#F79A83;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary .line-number {
display:block;
float:left;
width:35px;
padding-left:5px;
font-size:1em;
height:1em;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary table td {
border-bottom:1px solid #9a9a9a;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary table td {
border-bottom:1px solid #9a9a9a;
}


#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-content-code {
border:0;
background:transparent;
font-family:"Monaco", "Courier New", courier, fixed;
font-size:1em;
padding:0;
padding-left:40px;
border-bottom:1px dashed #8a8a8a;
margin-left:-40px;
height:1.3em;
line-height:1.3em;
font-weight:normal;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-line-sel {
background-color:#82E3F7;
-webkit-transition: background-color linear;
-webkit-transition-duration: 0.2s;
-ms-transition: background-color linear;
-ms-transition-duration: 0.2s;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-content {
background-color:#fff;
border:3px solid #676767;
width:100%;
}

#djDebug .panelContent .djDebug-htmlvalidator-summary .clean {
clear:both;
}

#djdebug .panelContent .djDebug-htmlvalidator-summary th {
text-align:left;
border-bottom:2px solid #898989;
}
#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-info-sel td.validation-error,
#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-info-sel {
background-color:#83F7A8;
}
}
2 changes: 1 addition & 1 deletion debug_toolbar/media/debug_toolbar/css/toolbar.min.css

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions debug_toolbar/media/debug_toolbar/js/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,35 @@ window.djdt = (function(window, document, jQuery) {
subcalls.hide();
}
});

$('#djDebug-htmlvalidator .handle-position').click(function(){
$('#djDebug-htmlvalidator .repr-info-sel').removeClass('repr-info-sel');
$(this).parent().parent().addClass('repr-info-sel')
var text = $(this).text();
var re = new RegExp('line\\s+([0-9]+)');
var result = text.match(re);

try{
var lineno = result[1];
}catch(e){return;}
//
var prevPos = $(document).data('reprlineselpos') || null;
if(prevPos){
prevPos.removeClass('repr-line-sel');
}
$('#djDebug-htmlvalidator .repr-line-' + lineno).addClass('repr-line-sel');
$(document).data('reprlineselpos', $('.repr-line-' + lineno));
// skip pervious link and add new one
var locationPrefix = location;
if(location.href.indexOf('#repr-line-') > -1){
var newLocation = location.href.substring(0, location.href.indexOf('#repr'));
locationPrefix = newLocation;
}
location = locationPrefix + '#' + 'repr-line-' + lineno;
});
$('#djDebug-htmlvalidator .tidy-msg').click(function(e){
$('.handle-position:first', $(this).prev()).click();
});
$('#djHideToolBarButton').click(function() {
djdt.hide_toolbar(true);
return false;
Expand Down
6 changes: 3 additions & 3 deletions debug_toolbar/media/debug_toolbar/js/toolbar.min.js

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions debug_toolbar/panels/htmlvalidator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import re

try:
from tidylib import tidy_document
except ImportError:
raise ImportError("""Please, make sure that PyTidyLib
module installed - it's required for HTMLValidationDebugPanel""")

from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe

from debug_toolbar.panels import DebugPanel


class HTMLValidationDebugPanel(DebugPanel):
name = "HTMLValidator"
has_content = True

log_data = None
errors_count = 0
warns_count = 0
src_content = ''

def nav_title(self):
return _("HTML Validator")

def nav_subtitle(self):
return mark_safe(_(u"Tidy Errors: %(errors_cnt)d "\
u"Warnings: %(warns_cnt)d") % {
'errors_cnt': self.errors_count,
'warns_cnt': self.warns_count,
})

def title(self):
return _("HTML Validator")

def url(self):
return ''

def process_response(self, request, response):
document, errors = tidy_document(response.content,
options={'numeric-entities': 1})
self.log_data = (document, errors)
self.src_content = response.content
errors_list = errors.split('\n')
self.errors_count = len([err for err in errors_list \
if 'error:' in err.lower()])
self.warns_count = len([err for err in errors_list \
if 'warning:' in err.lower()])

return response

def appearance(self, errors):
replacements = [
(re.compile(r'\<([^\>]*)\>'), \
'<strong class="code">&lt;\\1&gt;</strong>'),
(re.compile(r'(line[^\-]*)(.*)'), \
u'<td><pre class="handle-position">\\1</pre></td><td class="tidy-msg">\\2<td>'),
(re.compile(r'\s*\-\s+(Error\:|Warning\:)', re.I), \
u'<i>\\1</i>'),
]

for rx, rp in replacements:
errors = re.sub(rx, rp, errors)

errors_list = errors.split('\n')
errors_rt = []
# mark lines with error with validation-error class
for err in errors_list:
if 'error:' in err.lower():
err = err.replace('<td>', '<td class="validation-error">')
errors_rt.append(err)
continue
errors_rt.append(err)

return errors_rt

def content(self):
context = self.context.copy()

document, errors = self.log_data
lines = self.src_content.split("\n")

context.update({
'document': document,
'lines': zip(range(1, len(lines) + 1), lines),
'errors': self.appearance(errors),
})

return render_to_string(\
'debug_toolbar/panels/htmlvalidator.html', context)
Loading