aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--README.rst11
-rw-r--r--debug_toolbar/locale/pt_BR/LC_MESSAGES/django.mobin0 -> 4694 bytes
-rw-r--r--debug_toolbar/locale/pt_BR/LC_MESSAGES/django.po367
-rw-r--r--debug_toolbar/management/commands/debugsqlshell.py60
-rw-r--r--debug_toolbar/media/debug_toolbar/Makefile9
-rw-r--r--debug_toolbar/media/debug_toolbar/css/toolbar.css29
-rw-r--r--debug_toolbar/media/debug_toolbar/css/toolbar.min.css2
-rw-r--r--debug_toolbar/media/debug_toolbar/js/toolbar.js9
-rw-r--r--debug_toolbar/media/debug_toolbar/js/toolbar.min.js2
-rw-r--r--debug_toolbar/middleware.py51
-rw-r--r--debug_toolbar/panels/__init__.py49
-rw-r--r--debug_toolbar/panels/cache.py32
-rw-r--r--debug_toolbar/panels/headers.py19
-rw-r--r--debug_toolbar/panels/logger.py42
-rw-r--r--debug_toolbar/panels/profiling.py109
-rw-r--r--debug_toolbar/panels/request_vars.py55
-rw-r--r--debug_toolbar/panels/settings_vars.py16
-rw-r--r--debug_toolbar/panels/signals.py23
-rw-r--r--debug_toolbar/panels/sql.py55
-rw-r--r--debug_toolbar/panels/template.py94
-rw-r--r--debug_toolbar/panels/timer.py105
-rw-r--r--debug_toolbar/panels/version.py20
-rw-r--r--debug_toolbar/templates/debug_toolbar/panels/profiling.html19
-rw-r--r--debug_toolbar/templates/debug_toolbar/panels/sql.html3
-rw-r--r--debug_toolbar/templatetags/__init__.py (renamed from debug_toolbar/tests/templates/404.html)0
-rw-r--r--debug_toolbar/templatetags/debug_toolbar_utils.py11
-rw-r--r--debug_toolbar/tests/__init__.py1
-rw-r--r--debug_toolbar/tests/tests.py174
-rw-r--r--debug_toolbar/toolbar/loader.py19
-rw-r--r--debug_toolbar/utils/__init__.py30
-rw-r--r--debug_toolbar/utils/sqlparse/__init__.py6
-rw-r--r--debug_toolbar/utils/sqlparse/engine/__init__.py20
-rw-r--r--debug_toolbar/utils/sqlparse/engine/filter.py15
-rw-r--r--debug_toolbar/utils/sqlparse/engine/grouping.py170
-rw-r--r--debug_toolbar/utils/sqlparse/filters.py174
-rw-r--r--debug_toolbar/utils/sqlparse/formatter.py6
-rw-r--r--debug_toolbar/utils/sqlparse/keywords.py1141
-rw-r--r--debug_toolbar/utils/sqlparse/lexer.py106
-rw-r--r--debug_toolbar/utils/sqlparse/sql.py136
-rw-r--r--debug_toolbar/utils/sqlparse/tokens.py84
-rw-r--r--debug_toolbar/utils/tracking/db.py39
-rw-r--r--example/example.dbbin55296 -> 55296 bytes
-rw-r--r--example/settings.py8
-rw-r--r--example/templates/index.html20
-rw-r--r--runtests.py (renamed from debug_toolbar/runtests.py)28
-rw-r--r--setup.py8
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/models.py0
-rw-r--r--tests/templates/404.html0
-rw-r--r--tests/tests.py354
-rw-r--r--tests/urls.py (renamed from debug_toolbar/tests/urls.py)3
-rw-r--r--tests/views.py (renamed from debug_toolbar/tests/views.py)0
53 files changed, 2250 insertions, 1493 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..01f598b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+# Make file to compress and join all JS files
+all: compress_js compress_css
+
+compress_js:
+ java -jar ~/bin/yuicompressor.jar debug_toolbar/media/debug_toolbar/js/jquery.js > debug_toolbar/media/debug_toolbar/js/toolbar.min.js
+ java -jar ~/bin/yuicompressor.jar debug_toolbar/media/debug_toolbar/js/toolbar.js >> debug_toolbar/media/debug_toolbar/js/toolbar.min.js
+
+compress_css:
+ java -jar ~/bin/yuicompressor.jar --type css debug_toolbar/media/debug_toolbar/css/toolbar.css > debug_toolbar/media/debug_toolbar/css/toolbar.min.css
diff --git a/README.rst b/README.rst
index e7888c5..1ea9d25 100644
--- a/README.rst
+++ b/README.rst
@@ -25,6 +25,8 @@ There is also one Django management command currently:
If you have ideas for other panels please let us know.
+* Note: The Debug Toolbar only works on Django 1.1 and newer.
+
Installation
============
@@ -104,7 +106,7 @@ The debug toolbar has two settings that can be set in `settings.py`:
* `SHOW_TOOLBAR_CALLBACK`: If not set or set to None, the debug_toolbar
middleware will use its built-in show_toolbar method for determining whether
the toolbar should show or not. The default checks are that DEBUG must be
- set to True and the IP of the request must be in INTERNAL_IPS. You can
+ set to True or the IP of the request must be in INTERNAL_IPS. You can
provide your own method for displaying the toolbar which contains your
custom logic. This method should return True or False.
@@ -190,6 +192,13 @@ adding proper coverage (especially if it has a chance for a regression) in the t
python setup.py test
+
+3rd Party Panels
+================
+
+A list of 3rd party panels can be found on the Django Debug Toolbar Github wiki:
+https://github.com/django-debug-toolbar/django-debug-toolbar/wiki/3rd-Party-Panels
+
TODOs and BUGS
==============
See: https://github.com/django-debug-toolbar/django-debug-toolbar/issues
diff --git a/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.mo b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.mo
new file mode 100644
index 0000000..0fa0a13
--- /dev/null
+++ b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.mo
Binary files differ
diff --git a/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.po b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.po
new file mode 100644
index 0000000..80a1bd2
--- /dev/null
+++ b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.po
@@ -0,0 +1,367 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Percy Pérez-Pinedo, 2009.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Django Debug Toolbar 0.8.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-01-22 08:58+0000\n"
+"PO-Revision-Date: 2011-01-22 08:58+0000\n"
+"Last-Translator: Eduardo Cereto Carvalho <eduardocereto@gmail.com>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: panels/cache.py:92
+#, python-format
+msgid "Cache: %.2fms"
+msgstr "Cache: %.2fms"
+
+#: panels/cache.py:95
+msgid "Cache Usage"
+msgstr "Uso do Cache"
+
+#: panels/headers.py:36 panels/headers.py:39
+msgid "HTTP Headers"
+msgstr "Cabeçalhos HTTP"
+
+#: panels/logger.py:56
+msgid "Logging"
+msgstr "Logs"
+
+#: panels/logger.py:63
+msgid "Log Messages"
+msgstr "Mensagens de Log"
+
+#: panels/request_vars.py:13 panels/request_vars.py:16
+msgid "Request Vars"
+msgstr "Variáveis do Request"
+
+#: panels/settings_vars.py:16
+msgid "Settings"
+msgstr "Configurações"
+
+#: panels/settings_vars.py:19
+#, python-format
+msgid "Settings from <code>%s</code>"
+msgstr "Configurações de <code>%s</code>"
+
+#: panels/signals.py:39 panels/signals.py:42
+msgid "Signals"
+msgstr "Sinais"
+
+#: panels/sql.py:146
+msgid "SQL"
+msgstr "SQL"
+
+#: panels/sql.py:160
+msgid "SQL Queries"
+msgstr "Queries SQL"
+
+#: panels/template.py:47
+msgid "Templates"
+msgstr "Templates"
+
+#: panels/template.py:52
+#, python-format
+msgid "Templates (%(num_templates)s rendered)"
+msgstr "Templates (%(num_templates)s renderizados)"
+
+#: panels/timer.py:35 templates/debug_toolbar/panels/cache.html:39
+#: templates/debug_toolbar/panels/logger.html:7
+#: templates/debug_toolbar/panels/sql.html:5
+#: templates/debug_toolbar/panels/sql_explain.html:11
+#: templates/debug_toolbar/panels/sql_profile.html:12
+#: templates/debug_toolbar/panels/sql_select.html:11
+msgid "Time"
+msgstr "Tempo"
+
+#: panels/timer.py:47
+msgid "Resource Usage"
+msgstr "Uso de Recursos"
+
+#: panels/timer.py:78
+msgid "User CPU time"
+msgstr "Tempo de CPU do usuário"
+
+#: panels/timer.py:79
+msgid "System CPU time"
+msgstr "Tempo de CPU do sistema"
+
+#: panels/timer.py:80
+msgid "Total CPU time"
+msgstr "Tempo de CPU total"
+
+#: panels/timer.py:81
+msgid "Elapsed time"
+msgstr "Tempo decorrido"
+
+#: panels/timer.py:82
+msgid "Context switches"
+msgstr "Alterações de contexto"
+
+#: panels/version.py:20 panels/version.py:29
+msgid "Versions"
+msgstr "Versões"
+
+#: templates/debug_toolbar/base.html:23
+msgid "Hide Toolbar"
+msgstr "Esconder Barra"
+
+#: templates/debug_toolbar/base.html:23
+msgid "Hide"
+msgstr "Esconder"
+
+#: templates/debug_toolbar/base.html:48
+msgid "Show Toolbar"
+msgstr "Mostrar Barra"
+
+#: templates/debug_toolbar/base.html:54
+msgid "Close"
+msgstr "Fechar"
+
+#: templates/debug_toolbar/redirect.html:7
+#: templates/debug_toolbar/panels/logger.html:9
+msgid "Location"
+msgstr "Localização"
+
+#: templates/debug_toolbar/redirect.html:9
+msgid ""
+"The Django Debug Toolbar has intercepted a redirect to the above URL for "
+"debug viewing purposes. You can click the above link to continue with the "
+"redirect as normal. If you'd like to disable this feature, set the "
+"<code>DEBUG_TOOLBAR_CONFIG</code> dictionary's key "
+"<code>INTERCEPT_REDIRECTS</code> to <code>False</code>."
+msgstr ""
+"A Barra de Debug do Django interceptou um redirecionamento para a URL acima por "
+"propósito de debug. Você pode clicar no link acima para continuar com o "
+"redirecionamento normal. Se você gostaria de desabilitar essa funcionalidade, configure a "
+"chave <code></code> do dicionário "
+"<code>DEBUG_TOOLBAR_CONFIG</code> para <code>False</code>"
+
+#: templates/debug_toolbar/panels/cache.html:14
+msgid "Total Calls"
+msgstr "Total de Chamadas"
+
+#: templates/debug_toolbar/panels/cache.html:16
+msgid "Total Time"
+msgstr "Tempo Total"
+
+#: templates/debug_toolbar/panels/cache.html:18
+msgid "Hits"
+msgstr "Hits"
+
+#: templates/debug_toolbar/panels/cache.html:20
+msgid "Misses"
+msgstr "Misses"
+
+#: templates/debug_toolbar/panels/cache.html:35
+msgid "Breakdown"
+msgstr "Breakdown"
+
+#: templates/debug_toolbar/panels/cache.html:40
+msgid "Type"
+msgstr "Tipo"
+
+#: templates/debug_toolbar/panels/cache.html:41
+msgid "Parameters"
+msgstr "Parâmetros"
+
+#: templates/debug_toolbar/panels/cache.html:42
+msgid "Function"
+msgstr "Função"
+
+#: templates/debug_toolbar/panels/headers.html:5
+msgid "Key"
+msgstr "Chave"
+
+#: templates/debug_toolbar/panels/headers.html:6
+#: templates/debug_toolbar/panels/request_vars.html:37
+#: templates/debug_toolbar/panels/request_vars.html:63
+#: templates/debug_toolbar/panels/request_vars.html:85
+#: templates/debug_toolbar/panels/request_vars.html:107
+#: templates/debug_toolbar/panels/settings_vars.html:6
+#: templates/debug_toolbar/panels/timer.html:10
+msgid "Value"
+msgstr "Valor"
+
+#: templates/debug_toolbar/panels/logger.html:6
+msgid "Level"
+msgstr "Nível"
+
+#: templates/debug_toolbar/panels/logger.html:8
+msgid "Message"
+msgstr "Mensagem"
+
+#: templates/debug_toolbar/panels/logger.html:24
+msgid "No messages logged"
+msgstr "Nenhuma mensagem logada"
+
+#: templates/debug_toolbar/panels/request_vars.html:3
+msgid "View information"
+msgstr "Informações da View"
+
+#: templates/debug_toolbar/panels/request_vars.html:7
+msgid "View Function"
+msgstr "Função View"
+
+#: templates/debug_toolbar/panels/request_vars.html:8
+msgid "args"
+msgstr "args"
+
+#: templates/debug_toolbar/panels/request_vars.html:9
+msgid "kwargs"
+msgstr "kwargs"
+
+#: templates/debug_toolbar/panels/request_vars.html:27
+msgid "COOKIES Variables"
+msgstr "Variáveis do COOKIE"
+
+#: templates/debug_toolbar/panels/request_vars.html:36
+#: templates/debug_toolbar/panels/request_vars.html:62
+#: templates/debug_toolbar/panels/request_vars.html:84
+#: templates/debug_toolbar/panels/request_vars.html:106
+msgid "Variable"
+msgstr "Variável"
+
+#: templates/debug_toolbar/panels/request_vars.html:50
+msgid "No COOKIE data"
+msgstr "Não há dados de COOKIE"
+
+#: templates/debug_toolbar/panels/request_vars.html:53
+msgid "SESSION Variables"
+msgstr "Variáveis de SESSION"
+
+#: templates/debug_toolbar/panels/request_vars.html:76
+msgid "No SESSION data"
+msgstr "Não há dados de SESSION"
+
+#: templates/debug_toolbar/panels/request_vars.html:79
+msgid "GET Variables"
+msgstr "Variáveis de GET"
+
+#: templates/debug_toolbar/panels/request_vars.html:98
+msgid "No GET data"
+msgstr "Não há dados de GET"
+
+#: templates/debug_toolbar/panels/request_vars.html:101
+msgid "POST Variables"
+msgstr "Variáveis de POST"
+
+#: templates/debug_toolbar/panels/request_vars.html:120
+msgid "No POST data"
+msgstr "Não há dados de POST"
+
+#: templates/debug_toolbar/panels/settings_vars.html:5
+msgid "Setting"
+msgstr "Configuração"
+
+#: templates/debug_toolbar/panels/signals.html:5
+msgid "Signal"
+msgstr "Sinais"
+
+#: templates/debug_toolbar/panels/signals.html:6
+msgid "Providing Args"
+msgstr "Argumentos Fornecidos"
+
+#: templates/debug_toolbar/panels/signals.html:7
+msgid "Receivers"
+msgstr "Recebedores"
+
+#: templates/debug_toolbar/panels/sql.html:6
+msgid "Action"
+msgstr "Ação"
+
+#: templates/debug_toolbar/panels/sql.html:7
+msgid "Stacktrace"
+msgstr "Stacktrace"
+
+#: templates/debug_toolbar/panels/sql.html:8
+msgid "Query"
+msgstr "Query"
+
+#: templates/debug_toolbar/panels/sql.html:38
+msgid "Line"
+msgstr "Linha"
+
+#: templates/debug_toolbar/panels/sql.html:39
+msgid "Method"
+msgstr "Método"
+
+#: templates/debug_toolbar/panels/sql.html:40
+msgid "File"
+msgstr "Arquivo"
+
+#: templates/debug_toolbar/panels/sql_explain.html:3
+#: templates/debug_toolbar/panels/sql_profile.html:3
+#: templates/debug_toolbar/panels/sql_select.html:3
+#: templates/debug_toolbar/panels/template_source.html:3
+msgid "Back"
+msgstr "Voltar"
+
+#: templates/debug_toolbar/panels/sql_explain.html:4
+msgid "SQL Explained"
+msgstr "SQL Explicada"
+
+#: templates/debug_toolbar/panels/sql_explain.html:9
+#: templates/debug_toolbar/panels/sql_profile.html:10
+#: templates/debug_toolbar/panels/sql_select.html:9
+msgid "Executed SQL"
+msgstr "SQL Executada"
+
+#: templates/debug_toolbar/panels/sql_profile.html:4
+msgid "SQL Profiled"
+msgstr "Perfil da SQL"
+
+#: templates/debug_toolbar/panels/sql_profile.html:35
+msgid "Error"
+msgstr "Erro"
+
+#: templates/debug_toolbar/panels/sql_select.html:4
+msgid "SQL Selected"
+msgstr "SQL Selecionada"
+
+#: templates/debug_toolbar/panels/sql_select.html:34
+msgid "Empty set"
+msgstr "Conjunto vazio"
+
+#: templates/debug_toolbar/panels/template_source.html:4
+msgid "Template Source"
+msgstr "Origem do Template"
+
+#: templates/debug_toolbar/panels/templates.html:2
+msgid "Template path"
+msgstr "Caminho do Template"
+
+#: templates/debug_toolbar/panels/templates.html:13
+msgid "Template"
+msgstr "Template"
+
+#: templates/debug_toolbar/panels/templates.html:21
+#: templates/debug_toolbar/panels/templates.html:37
+msgid "Toggle Context"
+msgstr "Mostrar/Esconder Contexto"
+
+#: templates/debug_toolbar/panels/templates.html:28
+#: templates/debug_toolbar/panels/templates.html:43
+msgid "None"
+msgstr "Nenhum"
+
+#: templates/debug_toolbar/panels/templates.html:31
+msgid "Context processor"
+msgstr "Processador do Contexto"
+
+#: templates/debug_toolbar/panels/timer.html:9
+msgid "Resource"
+msgstr "Recurso"
+
+#: templates/debug_toolbar/panels/versions.html:6
+msgid "Package"
+msgstr "Pacote"
+
+#: templates/debug_toolbar/panels/versions.html:7
+msgid "Version"
+msgstr "Versão"
diff --git a/debug_toolbar/management/commands/debugsqlshell.py b/debug_toolbar/management/commands/debugsqlshell.py
index 6bb16de..8878d25 100644
--- a/debug_toolbar/management/commands/debugsqlshell.py
+++ b/debug_toolbar/management/commands/debugsqlshell.py
@@ -2,8 +2,8 @@ import os
from optparse import make_option
from datetime import datetime
-from django.core.management.base import NoArgsCommand
from django.db.backends import util
+from django.core.management.commands.shell import Command
from debug_toolbar.utils import sqlparse
@@ -21,61 +21,3 @@ class PrintQueryWrapper(util.CursorDebugWrapper):
print
util.CursorDebugWrapper = PrintQueryWrapper
-
-# The rest is copy/paste from django/core/management/commands/shell.py
-
-class Command(NoArgsCommand):
- option_list = NoArgsCommand.option_list + (
- make_option('--plain', action='store_true', dest='plain',
- help='Tells Django to use plain Python, not IPython.'),
- )
- help = "Runs a Python interactive interpreter. Tries to use IPython, if it's available."
-
- requires_model_validation = False
-
- def handle_noargs(self, **options):
- # XXX: (Temporary) workaround for ticket #1796: force early loading of all
- # models from installed apps.
- from django.db.models.loading import get_models
- loaded_models = get_models()
-
- use_plain = options.get('plain', False)
-
- try:
- if use_plain:
- # Don't bother loading IPython, because the user wants plain Python.
- raise ImportError
- import IPython
- # Explicitly pass an empty list as arguments, because otherwise IPython
- # would use sys.argv from this script.
- shell = IPython.Shell.IPShell(argv=[])
- shell.mainloop()
- except ImportError:
- import code
- # Set up a dictionary to serve as the environment for the shell, so
- # that tab completion works on objects that are imported at runtime.
- # See ticket 5082.
- imported_objects = {}
- try: # Try activating rlcompleter, because it's handy.
- import readline
- except ImportError:
- pass
- else:
- # We don't have to wrap the following import in a 'try', because
- # we already know 'readline' was imported successfully.
- import rlcompleter
- readline.set_completer(rlcompleter.Completer(imported_objects).complete)
- readline.parse_and_bind("tab:complete")
-
- # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
- # conventions and get $PYTHONSTARTUP first then import user.
- if not use_plain:
- pythonrc = os.environ.get("PYTHONSTARTUP")
- if pythonrc and os.path.isfile(pythonrc):
- try:
- execfile(pythonrc)
- except NameError:
- pass
- # This will import .pythonrc.py as a side-effect
- import user
- code.interact(local=imported_objects)
diff --git a/debug_toolbar/media/debug_toolbar/Makefile b/debug_toolbar/media/debug_toolbar/Makefile
deleted file mode 100644
index 95f91bb..0000000
--- a/debug_toolbar/media/debug_toolbar/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# Make file to compress and join all JS files
-all: compress_js compress_css
-
-compress_js:
- java -jar ~/bin/yuicompressor.jar js/jquery.js > js/toolbar.min.js
- java -jar ~/bin/yuicompressor.jar js/toolbar.js >> js/toolbar.min.js
-
-compress_css:
- java -jar ~/bin/yuicompressor.jar --type css css/toolbar.css > css/toolbar.min.css
diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.css b/debug_toolbar/media/debug_toolbar/css/toolbar.css
index 820617f..4770ade 100644
--- a/debug_toolbar/media/debug_toolbar/css/toolbar.css
+++ b/debug_toolbar/media/debug_toolbar/css/toolbar.css
@@ -369,19 +369,17 @@
position:relative;
}
-#djDebug .djDebugCollapse {
- display: inline-block;
- background: #ddd;
- background: url(data:image/gif;base64,R0lGODlhBgAKAJEDAJGRkdra2qysrP///yH5BAEAAAMALAAAAAAGAAoAAAIPnI+JIRImABBQ0sGc2qoAADs=) 0 3px repeat-x;
- width: 18px;
- text-indent: -10000em;
+#djDebug .djDebugCollapsed {
+ display: none;
+ text-decoration: none;
+ color: #333;
}
-#djDebug .djSelected .djDebugCollapse {
- background: inherit;
- text-indent: 0;
- width: auto;
- display: inline;
+
+#djDebug .djDebugUncollapsed {
+ color: #333;
+ text-decoration: none;
}
+
#djDebug .djUnselected {
display: none;
}
@@ -547,8 +545,13 @@
#djDebug .djSQLDetailsDiv {
margin-top:0.8em;
}
-#djDebug .djSQLDetailsDiv pre {
- color: #777;
+#djDebug pre {
+ white-space: pre-wrap; /* CSS-3 */
+ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ word-wrap: break-word; /* Internet Explorer 5.5+ */
+ color: #555;
border:1px solid #ccc;
border-collapse:collapse;
background-color:#fff;
diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
index 5088442..aa30728 100644
--- a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
+++ b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
@@ -1 +1 @@
-.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{display:inline-block;}/* Hides from IE-mac \*/ .clearfix{display:block;}* html .clearfix{height:1%;}/* end hide from IE-mac */ #djDebug{color:#000;background:#FFF;}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left;}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9;}#djDebug #djDebugToolbar small{color:#999;}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none;}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto;}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff;}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc;}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAgFJREFUeNqUlE1LAmEQx11fesNeDLt08hZ4KcgvIF7EgxcR9CT4IQwErx47WhFBdvPgwUNQeOiogiLRQSQUQaKD6Vpba7ar20izMe4+bjTwY5/Zl//OMzPPcCaTaRUwAxbTjynAdAHq84XGARuADQXN+MGEIJG1QmCaOZVK7WKUdmCdYMf7K/hDKwagwjRLPp9/cLvdzUKh8Ab+GgosExGz5hvFSJAbDAYKmFSpVM4DgUABX57l6wsYAR/AO64/MQUyyauiE1SdTqdTC4fDZ61W6x0FRUAAXvEqElGJCP5qzG3H5XIdFovFdCgUOgB3B3AC28AmyekSKSDH3LL2piRJcjabvU4kEnfg8sAL0Me1GulYE+ViQdWq1ep9NBrN9vv9J3B7KPyKOf3EtNAe1VVwzjwez36pVDoKBoMu3KpNs13dlg0FZ+ZwOJx+v3+PHATO6H2r0UOe54fJZPIil8vVSLtMjE7LQsFGo/EYiUSuut3uM/aimjPJSFQnCE0+hVNzE4/Hb1FoyOjBCasHdYKiKPLpdPo0k8k0GY1NKyvTyjIFe71eLRaLHZfLZYFx9AS8jhgR6gXb7faJ1+u9FATBglWU8cMxRjki0RmOMmu9Xo/4fL4y9pmVzEMZBcakGPJfw3YWzRY2rA19dWLLBMNCaAXXNHNPIVFO/zOtZ/YtwADKQgq0l7HbRAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px;}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent;}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps;}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75;}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABLCAYAAAACnsWZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAATCSURBVGiB7ZlvSBtnHMe/sckZY5aMw06r7aTLjGOwTKOMEWYs7M2EaaUdjG6+GDoQ9mIyupUxGIONwVZfDHwxg2E4igym24s5sFB0oDRq1yi1G0RijTjhjJBI86fR/LvbC+nFs7ncXR7jMsgXDp67e57vffI8v/s9z3NRAeBQxCr7rwGkVAIkVQmQVCVAUpUASVX0gGqxGxaLBTabDVqtFn6/H5OTk4jFYifJxovLdgwNDXGH1dDQkLVeoY+iH+KiBxSNwaOy2+0wmUyKzH0+H7xer2Koo5IVg/loZGSkuGOwtraW2KOggHt7e8QesmMwEomAZVlF5uvr64qBjko2YEtLC9bW1ogfqFRFn2b+v4CpVIovsyyrOP6OSyrksS8uKysDTdNQq9XY3d1FIpEoAFpGshJma2sr53A4OI/Hw7EsK0jIDMNw4+PjXFdXVyEWDLkr6PV6bmJiQvbs4XK5uJqampMBpCiKW1hYUDzF+Xw+zmAwFB5wcHBQMdxjDQ8PHwug6EtC0zS2trag0+kE16enp7G4uAiv14tUKgWz2Qyr1YrOzk6oVCq+XjweR11dHYLBYDZ7RcpK3tvbK+iRcDjMdXR0iP5Sm83GMQwjaNPX11e4IR4dHRU8bGBgQNKsp6dH0MbpdBYO0OVyCR5mNBolzTQaDZdOp/k2c3NzxICiMwlN03x5e3sboVBIrCqvZDIJhmH4c6PRKNlGSqKrGYqi+HJFRQX6+/tlGWq12qxlEmXt2pWVlbxTzGMtLS0VbogjkQjxLw+Hw8QeooA7OzvE5n6/n9hDNAbdbrfibeZRLS8vE7UH8lxunaSKfkUte9MEAAa6EhrqVNZ7HAc8DETBpo935a1oiJ1zH6O5rUH0fmI/iQ2PH1Nji/jpuxlwHHn0KOpBKVFaDRqbz6Gx+RysdjOudn9P7FmwGGy/+DLa3rQQ++QNmEykEA3t8UcsGn+izhvvvEIEBxAM8c2xO/iy74bgWu35KjhmPkLt+SoAwFnTaTI6HPMQMxsBLM1mvgdqdVSO2vKkqAdvXL+FuzOrYFkOd/9YzVqHfsbAlze95NNlnht3FQx0JU6pyxDejSGZyHyFOGs6DWu7GVVnjLh3+wGWZ8m+sMoGfLG1Ht3vvwZruxn1jdWCDVJgO4R7tx9gauwO5iZXiIAUA+r05fhi9D28/pZVluH9+XV8ctmBoJ98qQVIAGooNUZmr+KlV59TZMpsBHCl6Ss8Cu+T8uV+iz/4+qJiOOAg3Xz47eW8oQ5LtAcNdCWmtr55IlX8Oe3BX4sb2PTuIJ1Ko95cjResz6Kt0yKIy0Q8hY66awgFHxEBiqaZC91NArhYZB+fvu3E/M2/s9a32Ey4/ks/qs4c7OSocjUudDfhtx9cRICiQ9zc9rzgfPjzSVE44ODlGLr2q+BaPuFxVKKA9eZqwfnvP85Lmt362Q2WzURMfWN1jtryJApooCv5cmA7hGhI+j+PVDKNAPOQP9cbKwjxcsSghsrcKq/Q4FK/XZYhpdVk2h0q5ytRwFg0k8OeelqHzxzvKjbPtgRTKtEhjkXIzQuaqIM75FNV0C/9wUlKokPscW8SLzhXl/8hag+UNu7kKgGSqgRIqhIgqUqApCp6wH8B9cAOKo9Os8wAAAAASUVORK5CYII=);opacity:.5;}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#FFE761;border-left-color:#FFE761;border-bottom-color:#FFE761;opacity:1.0;}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto;}#djDebug tr.djDebugOdd{background-color:#f5f5f5;}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000;}#djDebug .panelContent>div{border-bottom:1px solid #ddd;}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px;}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit;}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:5px 0 0 20px;}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0;}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px;}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em;}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto;}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px;}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px;}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em;}#djDebug .djTemplateHideContextDiv{background-color:#fff;}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7dJREFUeNqsWM1PE0EU3+7ShdJKoTRA8UYgIUKM3rmaEI0euXsw0YMHIZEbxBijEiIHLkb/A44SDYlXzkYPGBM+ri1NWz7aUmhp6+9tps10mLfdfrzkl2535r39zc77mvUdHh4abUoUCAD3xP/fQAFItWJkYmLC+e1p8eGPgQcC08ycf8BPgW2vhr0SeQa8AWIe5k4LvATiwCrwtZmS2WT8IfAL+OKRhCoxoftH2GqLyBLwHbhvdC53ha2lVrfmE/DKzbLP5yubplnt7e310f+rq6tqpVLxVatVy0VtHbgNLHohsupGIhQKFQG7v79f+8CLiwsjl8sVAZsxQbYTwFrDwpTwpaj4ptPu6+vLDw4OBkHA014QobOzs3yhUAgyUx4BP2rhq/rIe53GwMBAeXx83DMJEpobi8WCpMtMWeOc9TkwoyMRjUattrMedBkyM+KZN4isqDMDgUCuExIyGbKlGVpRiSzo8kQ4HA4ZXRLGVuzo6GhBJjKviw6dT5TLZSOTyRinp6cGQrV+n67hnEY6nTaur6+1PkM2NWTm5fCd0xDRhh89CKHpXCMijLGxMef6+PjYiRSSUqlUv6/arOlKMlcjQlV0qsGDTZPehpYIxurXRCSRSFByq5NQ56hvhWwj8cm2p7A9UdKYVBX8fn+F2+tIJGIgmzaQkUnYtm0MDw+zvsLYniQiEc2q/WxxwmqRHxrISA9xxiyLDzTGdsRsJwJoK3QPo3vctnhpAzLqTexhiVOg6JAdU5bLy0vHZ+Ro8mg7Q0QO1LvwenZZJycnN3yCIPsMRRYnjO0DU/SY+wprW7fiWmjKJMgnUIcafEaeoxZCJWJI9lH4UjV2u6pSPp/XJR9jaGiIKrERDAbrjllzYOQJZ4zm6ISxuSsntB3gqTyazWZtMowa0aBFb4HegC6aRkZG2C2hLSObmqEdOcVvUdJUZyBlZ7tVa1ASdEUvjW3ZUqvvO82e3kqlUuVOSZANvBFd0fugawM2VKclOT8/tzohQ7pkgzn/rHNdvLbLJkPxeDzHRRIXIaTDkCB57XacoJPZW8bZQpSskslk0Y0QjdEcmstsB8myegrsYbqmENfJU3dOpZyOEwjdCqLIWUyxWKygVzHFccJ2eVkbar/qdq5ZFC3/R5dUb6EBsqQmyEtLuawj0eykRwpPgL0uRO+esLXW7tmX9nEWeAEk2yCQFLqzzb4MeK3Zn4FRsapNEXqGy2eJTTF3VOh27bOE/Ia2pQ81YeCO+P+XknGrH2pq8l+AAQDv/n2Gmq99BgAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABCVJREFUeNqsWG1IU1EYfjfd0i1bTc2WFTW3tG2aFWlEf4KkMIrCvhH6U9DnjxTyV0ZEXxIVGBH1JyKIPiBK8kf1syCKwu8M3VQsK7OV6ba2udZ7bmd6d+85827zhYftnnPe5z73nvc95z1X5XQ6IUHLQqQjiul1E8KHGIqHxGw2C7+pcd58E6KMooAzphPxnKJBKbFSIfsRpxAmBWMLKI4iviBOIm5O5qSepL8c8R5xQ6EIqZmobzPlSkhINeIpYhkkb0WUqzreqbmEOBaTOjQGf/0+CHz7Klxqc+aAehrGbkrM2b6IyEVUKRFyMpYI38dW8HS0gc/5kdmfnpcPepsD0vMLeRSEm6ivEzeqJOlLsuIJyzs40Au/Xr+CP64uRXORZraCoXQ1aHMX8YZsRDRG0lcqpA1hl3p4mt+C+/nThILDWLYR9EtXsrraEY6IEHGwHmCJGG16k7AIYsTX0/KO1WWn95QJqZWODHxyws8XjUmnjPtZg8DFsFqpkB2sdWL4zWuYKuNwmVwu1w6xkA2s7GAFpnaGAcxbd8H8snJQa7QTUZ+aCrlr10NexR5Iy8yW+REuwsmwDeL0XSOLjfYW5pNZtldC9orS/4FoK4LWa5cgHP4L9n1HILNoudCuM82F1qsXgcXJSOs1ESFkF7WKe8JBfxifQMVMY8/o+P+Z+TYoPFwNoYAfMh3FE2udz8d8CPJWCLdKM03MbcXpySJTY5EtmsNuFW+uex4/gJFe14SYxUuiRHi/fIaue7f5CzKb20KEGKWtYx4Pl2jM54WW+joY6euR9Xm/DkDT5bMQHB3h+7O5jepEMiAUDDBvRtpCfn9CWUWEuGUbkF7PdSDZQQLTaC+S9Rks+VB4qCoqmxRyu4mQbmlrisEY5hEtLN8ynh2RmBjt74sK4LyK3VwhHO5uNa0xoxYMEtVk02KZbk7uxB400C/ERPOVc1EBrMsxcTdCScYQ68L9ZiiyjryUprC+wM5c0PoaH4EmIwMCv4eh6+6t8VghAWzdtVdYzHoaHjKFEE6GvRTvvmSZvScd8f3hHfjT2z0lS3zaQgtkb6tkde3EN3I/kjX3ET9kwVdSOmV7jaF0Fav5BxEh3X3PyPaVBVaYta48aRGkJtHOt7C6zrPKgMvSoCU2vbhEIEpGBKcw6qQ1LLNmrWaVioRIk2kUtvK4SsWSVaCdl8cbcjxW8UxOZqcRJ2TThITZCO+HZvB2dsQsnnUFNtAtWRpLZ430FKjinH0VHSdCXg8EhwaFS03WbEjR6Sc7TkRCoErp2beKlvwX+EtkKqRkGATEYTXSY4SSkx5x2Eyr7WStnXLVJXr2JfPoQBxEDCYgYJD6Oib7MqC0DLiOyKFPVU9TD2J8lqinY3Oo75R9lhC/oQbRhxoSIDZ63UGK9Xg/1ETsnwADAJrrTk7nZiozAAAAAElFTkSuQmCC);}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7FJREFUeNrMWM1PE0EU3+7S7bZdKSFNSIFgJJAgINE7VxOi0SP/gYkePAiJ3CDGGJUQOXAx+h9wlGhIvHI2fgQ08mEkkjZNIZR2+7Httr63zMoyOzPdthx8yS+bnZn3m9/OvDcfG9jd3ZVatDggDLhO3j8DioBMMySDg4P2s6PJzu8AbhKMcNr8AHwkWPNL7FfIPcATQMJH2xGCh4AkYAHwtpGT3KD+FuAT4I1PEbQliO8XwtWSkFnAe8ANqX2bIFyzzU7NK8AjEXMgELBkWa6HQqEAvpfL5XqtVgvU63VF4LYE6APM+BGyIBKh67oJUCORCLPDQqEg5fN5E6ByKJA7BVg892FU+mJWvGN5a5pmdHV1RUGAr7lAQdls1igWi1FOk9uAD0760jHynOXR2dlp9fb2+haBhm0TiUQUfTlNFnnBeh8wxhIRj8eVllc98OWIGSN9eoTM0y3D4XC+HRFuMcjFqJqnhUyz1olYLKa730uVCrMjXrmIy1ln9vb2pt1CpljZQcdE1ihIW/sHHrayWbHLq1ZNGDPIyaiacguZZAhhph+K+fpr39Ppqcg/wtHhcE46QnAXHT4XwbJssjJECwbtp1EqS99AjNNpSD0r//77wH7yRgW5qeJhmJ44ChmiHYLBIHOMY9GINDrQ9y8uHDEoEMs7FNl+x5HhieFwD6GQbs8GJMtBbtCBmIkrA3anOD0YH2ci+21RWJ4vldibG5u7W5b+E8O95oguhM0LP1PhBauTOfj1Tnxg+c+DpD0aOFq6pjE75HAfoZAdunGlUpH9iLh6uc9+nsaFt5xlHO4dmZwxtynVKm5avIUrqoWkaxAnTmdOnGC5SARyIjdVvA0bX8ZRt0E7GYZhNgpWb0b1c0UIODfcC9o6XZvL5VTYwrnp6zaMEyd9eYZcyMmoWncLWQUcemIim82xFjTeQiey4+Nj1qZ3CNOySu++zxhzeimTyVjtpiZywIiwNr0XrGPAMh20aCcnJ0o7YtAXOTj3nyXeKZ55ykaiZDKZZ2WS6KiIPhwRaI9F1wm8mT3lBJueSqWkdDptigRhHbbBtpzpQJujb4EdnFOTzjvJ4+kcYF8nFEWpqapqf4xpmjXLsmRynVAFg7VMn1dF95oZcuR/yWPDDqvVKsIp8nOknGOJaHTTQ4e7gM0L2NM2Cddiq3dfnMdxwANAugUBaeI73ujPgN9jwGtAD/mqFZJ6kuC3xApp20N8L+y3hHuE1lw/amKAUfK+hYtxsz9qHPsrwACHs5P9Qys/0AAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA6hJREFUeNrMWF1Ik1EYPtt0pkuGa/aDJTY3nNvSfkglvEwQpa7CbrosKAghBedNikKgEgVe1m03SVeJXmSXBmIozpxpuiUS/eicSc75m73vx/nGt7Nzvm8/BR14+Pjec85znp297znv++kCgQBJs1kBuYDz9H0KEAWEUiGx2WzSMyvFxa8B6iicgjFzgBGKwWSJdUnuyB1AF+BUisK/AToBz7V2RK9B1ACYBDxLQwShc3Cuj3IJm5qQVsAQ4ALJvFVQrlbRAJGPPAE8UKU+2Ce/d6Jk98d36dV44iTR54DvGlTd7jGgCNCSjJBONRHR+Q8kMjtDooF5bn9uaRkxuTwkt+yciAK5UX2fmrNiVLzmzd77ukR+jr0j28GFpP6LIzYHMVdfIcais6IhjYBh2VlZITMANzsj4ntPwiNDaTmHpa6RmCov87r8AA8vau7yRGxOjactAhvOjUxP8LrcdM0EIR3syN0vAbL+djjjkAm/GZS4OK2DFdLEOyc2xsfi/3frcb4/COxqXPI5EwwGm5RC6nnRwTpmgdNNKpq9iZFiLZTsWXkmoRDkQk5Oq1cKqU3wDf80lxDFXGzvTlhUFqm2OwLOWlkI3qIOZc/h3s4hL0y3QyvSM7+4hFxq74otGg2txuyVzW3SU7QryM2YHfD3WFGIPeHQ3AjreETrc34y3d8b8wtZDApE+/5WRHrHnRGJEXDbUYiFte5HIsLtRTGTPR3Sovj3oH8oRaIotB8t5h9kAm6LnvwnDe+acILRJPZ+ZeTgr5f9A+2u2/el3cDd2lz+zF+Qzx1GIYus1WC2oEPptET4+vukp+wXrJ3XBNyLeppjxoWILjtHh5eW6OD6tbxEJno6Y4vJfoJ2NRHIidyMeQHum5DsI6PsJJPTremsvIgSiVDhHFXevnjMvmRHrL56QbaXFuN2hLeQyB43psROCm/c4nXdhB0ZkHdkALDGjjBXVXMPNNFBp9bM1TU88xqKYG/fR+woY7GDFFxtyDg0MScxnrHzunpEGdon9rj/h4kR1j/logKrlZcqIlH2MYt0laeUKlbVEOPpUtGQNq0CqxvwUDR766OPbM3NqibPeU4XySuvVNPplZNnUc6aUjlxACG8Rx01GyLHgKmBQbOKfaosJ7Rq3xaa8vcK6WBBQ75ZQgrNy5YRyVR6OOE6zbYzbX7K1ZdOyUloNe8B3AOspCFghc71aH0Z0KX4feSvf5bQctZkP9Sgg7jo+ywm6+l+qPkjwADNS26fFM/O1QAAAABJRU5ErkJggg==);}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block;}#djDebug .panelContent dt{margin-top:.75em;}#djDebug .panelContent dd{margin-left:10px;}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999;}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer;}#djDebug .djDebugSqlWrap{position:relative;}#djDebug .djDebugCollapse{display:inline-block;background:#ddd;background:url(data:image/gif;base64,R0lGODlhBgAKAJEDAJGRkdra2qysrP///yH5BAEAAAMALAAAAAAGAAoAAAIPnI+JIRImABBQ0sGc2qoAADs=) 0 3px repeat-x;width:18px;text-indent:-10000em;}#djDebug .djSelected .djDebugCollapse{background:inherit;text-indent:0;width:auto;display:inline;}#djDebug .djUnselected{display:none;}#djDebug tr.djHiddenByDefault{display:none;}#djDebug tr.djSelected{display:table-row;}#djDebug .djDebugSql{z-index:100000002;}#djDebug .djSQLDetailsDiv tbody th{text-align:left;}#djDebug .djSqlExplain td{white-space:pre;}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001;}#djDebug span.djDebugLineChartWarning{background-color:#900;}#djDebug .highlight{color:#000;}#djDebug .highlight .err{color:#000;}#djDebug .highlight .g{color:#000;}#djDebug .highlight .k{color:#000;font-weight:bold;}#djDebug .highlight .o{color:#000;}#djDebug .highlight .n{color:#000;}#djDebug .highlight .mi{color:#000;font-weight:bold;}#djDebug .highlight .l{color:#000;}#djDebug .highlight .x{color:#000;}#djDebug .highlight .p{color:#000;}#djDebug .highlight .m{color:#000;font-weight:bold;}#djDebug .highlight .s{color:#333;}#djDebug .highlight .w{color:#888;}#djDebug .highlight .il{color:#000;font-weight:bold;}#djDebug .highlight .na{color:#333;}#djDebug .highlight .nt{color:#000;font-weight:bold;}#djDebug .highlight .nv{color:#333;}#djDebug .highlight .s2{color:#333;}#djDebug .highlight .cp{color:#333;}#djDebug .timeline{width:30%;}#djDebug .djDebugTimeline{position:relative;height:100%;min-height:100%;}#djDebug div.djDebugLineChart{position:absolute;left:0;right:0;top:0;bottom:0;vertical-align:middle;}#djDebug div.djDebugLineChart strong{text-indent:-10000em;display:block;font-weight:normal;vertical-align:middle;background-color:#ccc;}#djDebug div.djDebugLineChartWarning strong{background-color:#900;}#djDebug .djDebugInTransaction div.djDebugLineChart strong{background-color:#d3ff82;}#djDebug .djDebugStartTransaction div.djDebugLineChart strong{border-left:1px solid #94b24d;}#djDebug .djDebugEndTransaction div.djDebugLineChart strong{border-right:1px solid #94b24d;}#djDebug .djDebugHover div.djDebugLineChart strong{background-color:#000;}#djDebug .djDebugInTransaction.djDebugHover div.djDebugLineChart strong{background-color:#94b24d;}#djDebug .panelContent ul.stats{position:relative;}#djDebug .panelContent ul.stats li{width:30%;float:left;}#djDebug .panelContent ul.stats li strong.label{display:block;}#djDebug .panelContent ul.stats li span.color{height:12px;width:3px;display:inline-block;}#djDebug .panelContent ul.stats li span.info{display:block;padding-left:5px;}#djDebug .panelcontent thead th{white-space:nowrap;}#djDebug .djDebugRowWarning .time{color:red;}#djdebug .panelcontent table .toggle{width:14px;padding-top:3px;}#djdebug .panelcontent table .actions{min-width:70px;}#djdebug .panelcontent table .color{width:3px;}#djdebug .panelcontent table .color span{width:3px;height:12px;overflow:hidden;padding:0;}#djDebug .djToggleSwitch{text-decoration:none;border:1px solid #999;height:12px;width:12px;line-height:12px;text-align:center;color:#777;display:inline-block;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF',endColorstr='#DCDCDC');background:-webkit-gradient(linear,left top,left bottom,from(#FFF),to(#DCDCDC));background:-moz-linear-gradient(center top,#FFF 0,#DCDCDC 100%) repeat scroll 0 0 transparent;}#djDebug .djNoToggleSwitch{height:14px;width:14px;display:inline-block;}#djDebug .djSQLDetailsDiv{margin-top:.8em;}#djDebug .djSQLDetailsDiv pre{color:#777;border:1px solid #ccc;border-collapse:collapse;background-color:#fff;display:block;overflow:auto;padding:2px 3px;margin-bottom:3px;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;}#djDebug .stack span{color:#000;font-weight:bold;}#djDebug .stack span.path{color:#777;font-weight:normal;}#djDebug .stack span.code{font-weight:normal;}@media print{#djDebug{display:none;}} \ No newline at end of file
+.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{display:inline-block;}/* Hides from IE-mac \*/ .clearfix{display:block;}* html .clearfix{height:1%;}/* end hide from IE-mac */ #djDebug{color:#000;background:#FFF;}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left;}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9;}#djDebug #djDebugToolbar small{color:#999;}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none;}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto;}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff;}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc;}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAgFJREFUeNqUlE1LAmEQx11fesNeDLt08hZ4KcgvIF7EgxcR9CT4IQwErx47WhFBdvPgwUNQeOiogiLRQSQUQaKD6Vpba7ar20izMe4+bjTwY5/Zl//OMzPPcCaTaRUwAxbTjynAdAHq84XGARuADQXN+MGEIJG1QmCaOZVK7WKUdmCdYMf7K/hDKwagwjRLPp9/cLvdzUKh8Ab+GgosExGz5hvFSJAbDAYKmFSpVM4DgUABX57l6wsYAR/AO64/MQUyyauiE1SdTqdTC4fDZ61W6x0FRUAAXvEqElGJCP5qzG3H5XIdFovFdCgUOgB3B3AC28AmyekSKSDH3LL2piRJcjabvU4kEnfg8sAL0Me1GulYE+ViQdWq1ep9NBrN9vv9J3B7KPyKOf3EtNAe1VVwzjwez36pVDoKBoMu3KpNs13dlg0FZ+ZwOJx+v3+PHATO6H2r0UOe54fJZPIil8vVSLtMjE7LQsFGo/EYiUSuut3uM/aimjPJSFQnCE0+hVNzE4/Hb1FoyOjBCasHdYKiKPLpdPo0k8k0GY1NKyvTyjIFe71eLRaLHZfLZYFx9AS8jhgR6gXb7faJ1+u9FATBglWU8cMxRjki0RmOMmu9Xo/4fL4y9pmVzEMZBcakGPJfw3YWzRY2rA19dWLLBMNCaAXXNHNPIVFO/zOtZ/YtwADKQgq0l7HbRAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px;}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent;}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps;}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75;}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABLCAYAAAACnsWZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAATCSURBVGiB7ZlvSBtnHMe/sckZY5aMw06r7aTLjGOwTKOMEWYs7M2EaaUdjG6+GDoQ9mIyupUxGIONwVZfDHwxg2E4igym24s5sFB0oDRq1yi1G0RijTjhjJBI86fR/LvbC+nFs7ncXR7jMsgXDp67e57vffI8v/s9z3NRAeBQxCr7rwGkVAIkVQmQVCVAUpUASVX0gGqxGxaLBTabDVqtFn6/H5OTk4jFYifJxovLdgwNDXGH1dDQkLVeoY+iH+KiBxSNwaOy2+0wmUyKzH0+H7xer2Koo5IVg/loZGSkuGOwtraW2KOggHt7e8QesmMwEomAZVlF5uvr64qBjko2YEtLC9bW1ogfqFRFn2b+v4CpVIovsyyrOP6OSyrksS8uKysDTdNQq9XY3d1FIpEoAFpGshJma2sr53A4OI/Hw7EsK0jIDMNw4+PjXFdXVyEWDLkr6PV6bmJiQvbs4XK5uJqampMBpCiKW1hYUDzF+Xw+zmAwFB5wcHBQMdxjDQ8PHwug6EtC0zS2trag0+kE16enp7G4uAiv14tUKgWz2Qyr1YrOzk6oVCq+XjweR11dHYLBYDZ7RcpK3tvbK+iRcDjMdXR0iP5Sm83GMQwjaNPX11e4IR4dHRU8bGBgQNKsp6dH0MbpdBYO0OVyCR5mNBolzTQaDZdOp/k2c3NzxICiMwlN03x5e3sboVBIrCqvZDIJhmH4c6PRKNlGSqKrGYqi+HJFRQX6+/tlGWq12qxlEmXt2pWVlbxTzGMtLS0VbogjkQjxLw+Hw8QeooA7OzvE5n6/n9hDNAbdbrfibeZRLS8vE7UH8lxunaSKfkUte9MEAAa6EhrqVNZ7HAc8DETBpo935a1oiJ1zH6O5rUH0fmI/iQ2PH1Nji/jpuxlwHHn0KOpBKVFaDRqbz6Gx+RysdjOudn9P7FmwGGy/+DLa3rQQ++QNmEykEA3t8UcsGn+izhvvvEIEBxAM8c2xO/iy74bgWu35KjhmPkLt+SoAwFnTaTI6HPMQMxsBLM1mvgdqdVSO2vKkqAdvXL+FuzOrYFkOd/9YzVqHfsbAlze95NNlnht3FQx0JU6pyxDejSGZyHyFOGs6DWu7GVVnjLh3+wGWZ8m+sMoGfLG1Ht3vvwZruxn1jdWCDVJgO4R7tx9gauwO5iZXiIAUA+r05fhi9D28/pZVluH9+XV8ctmBoJ98qQVIAGooNUZmr+KlV59TZMpsBHCl6Ss8Cu+T8uV+iz/4+qJiOOAg3Xz47eW8oQ5LtAcNdCWmtr55IlX8Oe3BX4sb2PTuIJ1Ko95cjResz6Kt0yKIy0Q8hY66awgFHxEBiqaZC91NArhYZB+fvu3E/M2/s9a32Ey4/ks/qs4c7OSocjUudDfhtx9cRICiQ9zc9rzgfPjzSVE44ODlGLr2q+BaPuFxVKKA9eZqwfnvP85Lmt362Q2WzURMfWN1jtryJApooCv5cmA7hGhI+j+PVDKNAPOQP9cbKwjxcsSghsrcKq/Q4FK/XZYhpdVk2h0q5ytRwFg0k8OeelqHzxzvKjbPtgRTKtEhjkXIzQuaqIM75FNV0C/9wUlKokPscW8SLzhXl/8hag+UNu7kKgGSqgRIqhIgqUqApCp6wH8B9cAOKo9Os8wAAAAASUVORK5CYII=);opacity:.5;}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#FFE761;border-left-color:#FFE761;border-bottom-color:#FFE761;opacity:1.0;}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto;}#djDebug tr.djDebugOdd{background-color:#f5f5f5;}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000;}#djDebug .panelContent>div{border-bottom:1px solid #ddd;}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px;}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit;}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:5px 0 0 20px;}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0;}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px;}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em;}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto;}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px;}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px;}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em;}#djDebug .djTemplateHideContextDiv{background-color:#fff;}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7dJREFUeNqsWM1PE0EU3+7ShdJKoTRA8UYgIUKM3rmaEI0euXsw0YMHIZEbxBijEiIHLkb/A44SDYlXzkYPGBM+ri1NWz7aUmhp6+9tps10mLfdfrzkl2535r39zc77mvUdHh4abUoUCAD3xP/fQAFItWJkYmLC+e1p8eGPgQcC08ycf8BPgW2vhr0SeQa8AWIe5k4LvATiwCrwtZmS2WT8IfAL+OKRhCoxoftH2GqLyBLwHbhvdC53ha2lVrfmE/DKzbLP5yubplnt7e310f+rq6tqpVLxVatVy0VtHbgNLHohsupGIhQKFQG7v79f+8CLiwsjl8sVAZsxQbYTwFrDwpTwpaj4ptPu6+vLDw4OBkHA014QobOzs3yhUAgyUx4BP2rhq/rIe53GwMBAeXx83DMJEpobi8WCpMtMWeOc9TkwoyMRjUattrMedBkyM+KZN4isqDMDgUCuExIyGbKlGVpRiSzo8kQ4HA4ZXRLGVuzo6GhBJjKviw6dT5TLZSOTyRinp6cGQrV+n67hnEY6nTaur6+1PkM2NWTm5fCd0xDRhh89CKHpXCMijLGxMef6+PjYiRSSUqlUv6/arOlKMlcjQlV0qsGDTZPehpYIxurXRCSRSFByq5NQ56hvhWwj8cm2p7A9UdKYVBX8fn+F2+tIJGIgmzaQkUnYtm0MDw+zvsLYniQiEc2q/WxxwmqRHxrISA9xxiyLDzTGdsRsJwJoK3QPo3vctnhpAzLqTexhiVOg6JAdU5bLy0vHZ+Ro8mg7Q0QO1LvwenZZJycnN3yCIPsMRRYnjO0DU/SY+wprW7fiWmjKJMgnUIcafEaeoxZCJWJI9lH4UjV2u6pSPp/XJR9jaGiIKrERDAbrjllzYOQJZ4zm6ISxuSsntB3gqTyazWZtMowa0aBFb4HegC6aRkZG2C2hLSObmqEdOcVvUdJUZyBlZ7tVa1ASdEUvjW3ZUqvvO82e3kqlUuVOSZANvBFd0fugawM2VKclOT8/tzohQ7pkgzn/rHNdvLbLJkPxeDzHRRIXIaTDkCB57XacoJPZW8bZQpSskslk0Y0QjdEcmstsB8myegrsYbqmENfJU3dOpZyOEwjdCqLIWUyxWKygVzHFccJ2eVkbar/qdq5ZFC3/R5dUb6EBsqQmyEtLuawj0eykRwpPgL0uRO+esLXW7tmX9nEWeAEk2yCQFLqzzb4MeK3Zn4FRsapNEXqGy2eJTTF3VOh27bOE/Ia2pQ81YeCO+P+XknGrH2pq8l+AAQDv/n2Gmq99BgAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABCVJREFUeNqsWG1IU1EYfjfd0i1bTc2WFTW3tG2aFWlEf4KkMIrCvhH6U9DnjxTyV0ZEXxIVGBH1JyKIPiBK8kf1syCKwu8M3VQsK7OV6ba2udZ7bmd6d+85827zhYftnnPe5z73nvc95z1X5XQ6IUHLQqQjiul1E8KHGIqHxGw2C7+pcd58E6KMooAzphPxnKJBKbFSIfsRpxAmBWMLKI4iviBOIm5O5qSepL8c8R5xQ6EIqZmobzPlSkhINeIpYhkkb0WUqzreqbmEOBaTOjQGf/0+CHz7Klxqc+aAehrGbkrM2b6IyEVUKRFyMpYI38dW8HS0gc/5kdmfnpcPepsD0vMLeRSEm6ivEzeqJOlLsuIJyzs40Au/Xr+CP64uRXORZraCoXQ1aHMX8YZsRDRG0lcqpA1hl3p4mt+C+/nThILDWLYR9EtXsrraEY6IEHGwHmCJGG16k7AIYsTX0/KO1WWn95QJqZWODHxyws8XjUmnjPtZg8DFsFqpkB2sdWL4zWuYKuNwmVwu1w6xkA2s7GAFpnaGAcxbd8H8snJQa7QTUZ+aCrlr10NexR5Iy8yW+REuwsmwDeL0XSOLjfYW5pNZtldC9orS/4FoK4LWa5cgHP4L9n1HILNoudCuM82F1qsXgcXJSOs1ESFkF7WKe8JBfxifQMVMY8/o+P+Z+TYoPFwNoYAfMh3FE2udz8d8CPJWCLdKM03MbcXpySJTY5EtmsNuFW+uex4/gJFe14SYxUuiRHi/fIaue7f5CzKb20KEGKWtYx4Pl2jM54WW+joY6euR9Xm/DkDT5bMQHB3h+7O5jepEMiAUDDBvRtpCfn9CWUWEuGUbkF7PdSDZQQLTaC+S9Rks+VB4qCoqmxRyu4mQbmlrisEY5hEtLN8ynh2RmBjt74sK4LyK3VwhHO5uNa0xoxYMEtVk02KZbk7uxB400C/ERPOVc1EBrMsxcTdCScYQ68L9ZiiyjryUprC+wM5c0PoaH4EmIwMCv4eh6+6t8VghAWzdtVdYzHoaHjKFEE6GvRTvvmSZvScd8f3hHfjT2z0lS3zaQgtkb6tkde3EN3I/kjX3ET9kwVdSOmV7jaF0Fav5BxEh3X3PyPaVBVaYta48aRGkJtHOt7C6zrPKgMvSoCU2vbhEIEpGBKcw6qQ1LLNmrWaVioRIk2kUtvK4SsWSVaCdl8cbcjxW8UxOZqcRJ2TThITZCO+HZvB2dsQsnnUFNtAtWRpLZ430FKjinH0VHSdCXg8EhwaFS03WbEjR6Sc7TkRCoErp2beKlvwX+EtkKqRkGATEYTXSY4SSkx5x2Eyr7WStnXLVJXr2JfPoQBxEDCYgYJD6Oib7MqC0DLiOyKFPVU9TD2J8lqinY3Oo75R9lhC/oQbRhxoSIDZ63UGK9Xg/1ETsnwADAJrrTk7nZiozAAAAAElFTkSuQmCC);}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7FJREFUeNrMWM1PE0EU3+7S7bZdKSFNSIFgJJAgINE7VxOi0SP/gYkePAiJ3CDGGJUQOXAx+h9wlGhIvHI2fgQ08mEkkjZNIZR2+7Httr63zMoyOzPdthx8yS+bnZn3m9/OvDcfG9jd3ZVatDggDLhO3j8DioBMMySDg4P2s6PJzu8AbhKMcNr8AHwkWPNL7FfIPcATQMJH2xGCh4AkYAHwtpGT3KD+FuAT4I1PEbQliO8XwtWSkFnAe8ANqX2bIFyzzU7NK8AjEXMgELBkWa6HQqEAvpfL5XqtVgvU63VF4LYE6APM+BGyIBKh67oJUCORCLPDQqEg5fN5E6ByKJA7BVg892FU+mJWvGN5a5pmdHV1RUGAr7lAQdls1igWi1FOk9uAD0760jHynOXR2dlp9fb2+haBhm0TiUQUfTlNFnnBeh8wxhIRj8eVllc98OWIGSN9eoTM0y3D4XC+HRFuMcjFqJqnhUyz1olYLKa730uVCrMjXrmIy1ln9vb2pt1CpljZQcdE1ihIW/sHHrayWbHLq1ZNGDPIyaiacguZZAhhph+K+fpr39Ppqcg/wtHhcE46QnAXHT4XwbJssjJECwbtp1EqS99AjNNpSD0r//77wH7yRgW5qeJhmJ44ChmiHYLBIHOMY9GINDrQ9y8uHDEoEMs7FNl+x5HhieFwD6GQbs8GJMtBbtCBmIkrA3anOD0YH2ci+21RWJ4vldibG5u7W5b+E8O95oguhM0LP1PhBauTOfj1Tnxg+c+DpD0aOFq6pjE75HAfoZAdunGlUpH9iLh6uc9+nsaFt5xlHO4dmZwxtynVKm5avIUrqoWkaxAnTmdOnGC5SARyIjdVvA0bX8ZRt0E7GYZhNgpWb0b1c0UIODfcC9o6XZvL5VTYwrnp6zaMEyd9eYZcyMmoWncLWQUcemIim82xFjTeQiey4+Nj1qZ3CNOySu++zxhzeimTyVjtpiZywIiwNr0XrGPAMh20aCcnJ0o7YtAXOTj3nyXeKZ55ykaiZDKZZ2WS6KiIPhwRaI9F1wm8mT3lBJueSqWkdDptigRhHbbBtpzpQJujb4EdnFOTzjvJ4+kcYF8nFEWpqapqf4xpmjXLsmRynVAFg7VMn1dF95oZcuR/yWPDDqvVKsIp8nOknGOJaHTTQ4e7gM0L2NM2Cddiq3dfnMdxwANAugUBaeI73ujPgN9jwGtAD/mqFZJ6kuC3xApp20N8L+y3hHuE1lw/amKAUfK+hYtxsz9qHPsrwACHs5P9Qys/0AAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA6hJREFUeNrMWF1Ik1EYPtt0pkuGa/aDJTY3nNvSfkglvEwQpa7CbrosKAghBedNikKgEgVe1m03SVeJXmSXBmIozpxpuiUS/eicSc75m73vx/nGt7Nzvm8/BR14+Pjec85znp297znv++kCgQBJs1kBuYDz9H0KEAWEUiGx2WzSMyvFxa8B6iicgjFzgBGKwWSJdUnuyB1AF+BUisK/AToBz7V2RK9B1ACYBDxLQwShc3Cuj3IJm5qQVsAQ4ALJvFVQrlbRAJGPPAE8UKU+2Ce/d6Jk98d36dV44iTR54DvGlTd7jGgCNCSjJBONRHR+Q8kMjtDooF5bn9uaRkxuTwkt+yciAK5UX2fmrNiVLzmzd77ukR+jr0j28GFpP6LIzYHMVdfIcais6IhjYBh2VlZITMANzsj4ntPwiNDaTmHpa6RmCov87r8AA8vau7yRGxOjactAhvOjUxP8LrcdM0EIR3syN0vAbL+djjjkAm/GZS4OK2DFdLEOyc2xsfi/3frcb4/COxqXPI5EwwGm5RC6nnRwTpmgdNNKpq9iZFiLZTsWXkmoRDkQk5Oq1cKqU3wDf80lxDFXGzvTlhUFqm2OwLOWlkI3qIOZc/h3s4hL0y3QyvSM7+4hFxq74otGg2txuyVzW3SU7QryM2YHfD3WFGIPeHQ3AjreETrc34y3d8b8wtZDApE+/5WRHrHnRGJEXDbUYiFte5HIsLtRTGTPR3Sovj3oH8oRaIotB8t5h9kAm6LnvwnDe+acILRJPZ+ZeTgr5f9A+2u2/el3cDd2lz+zF+Qzx1GIYus1WC2oEPptET4+vukp+wXrJ3XBNyLeppjxoWILjtHh5eW6OD6tbxEJno6Y4vJfoJ2NRHIidyMeQHum5DsI6PsJJPTremsvIgSiVDhHFXevnjMvmRHrL56QbaXFuN2hLeQyB43psROCm/c4nXdhB0ZkHdkALDGjjBXVXMPNNFBp9bM1TU88xqKYG/fR+woY7GDFFxtyDg0MScxnrHzunpEGdon9rj/h4kR1j/logKrlZcqIlH2MYt0laeUKlbVEOPpUtGQNq0CqxvwUDR766OPbM3NqibPeU4XySuvVNPplZNnUc6aUjlxACG8Rx01GyLHgKmBQbOKfaosJ7Rq3xaa8vcK6WBBQ75ZQgrNy5YRyVR6OOE6zbYzbX7K1ZdOyUloNe8B3AOspCFghc71aH0Z0KX4feSvf5bQctZkP9Sgg7jo+ywm6+l+qPkjwADNS26fFM/O1QAAAABJRU5ErkJggg==);}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block;}#djDebug .panelContent dt{margin-top:.75em;}#djDebug .panelContent dd{margin-left:10px;}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999;}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer;}#djDebug .djDebugSqlWrap{position:relative;}#djDebug .djDebugCollapsed{display:none;text-decoration:none;color:#333;}#djDebug .djDebugUncollapsed{color:#333;text-decoration:none;}#djDebug .djUnselected{display:none;}#djDebug tr.djHiddenByDefault{display:none;}#djDebug tr.djSelected{display:table-row;}#djDebug .djDebugSql{z-index:100000002;}#djDebug .djSQLDetailsDiv tbody th{text-align:left;}#djDebug .djSqlExplain td{white-space:pre;}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001;}#djDebug span.djDebugLineChartWarning{background-color:#900;}#djDebug .highlight{color:#000;}#djDebug .highlight .err{color:#000;}#djDebug .highlight .g{color:#000;}#djDebug .highlight .k{color:#000;font-weight:bold;}#djDebug .highlight .o{color:#000;}#djDebug .highlight .n{color:#000;}#djDebug .highlight .mi{color:#000;font-weight:bold;}#djDebug .highlight .l{color:#000;}#djDebug .highlight .x{color:#000;}#djDebug .highlight .p{color:#000;}#djDebug .highlight .m{color:#000;font-weight:bold;}#djDebug .highlight .s{color:#333;}#djDebug .highlight .w{color:#888;}#djDebug .highlight .il{color:#000;font-weight:bold;}#djDebug .highlight .na{color:#333;}#djDebug .highlight .nt{color:#000;font-weight:bold;}#djDebug .highlight .nv{color:#333;}#djDebug .highlight .s2{color:#333;}#djDebug .highlight .cp{color:#333;}#djDebug .timeline{width:30%;}#djDebug .djDebugTimeline{position:relative;height:100%;min-height:100%;}#djDebug div.djDebugLineChart{position:absolute;left:0;right:0;top:0;bottom:0;vertical-align:middle;}#djDebug div.djDebugLineChart strong{text-indent:-10000em;display:block;font-weight:normal;vertical-align:middle;background-color:#ccc;}#djDebug div.djDebugLineChartWarning strong{background-color:#900;}#djDebug .djDebugInTransaction div.djDebugLineChart strong{background-color:#d3ff82;}#djDebug .djDebugStartTransaction div.djDebugLineChart strong{border-left:1px solid #94b24d;}#djDebug .djDebugEndTransaction div.djDebugLineChart strong{border-right:1px solid #94b24d;}#djDebug .djDebugHover div.djDebugLineChart strong{background-color:#000;}#djDebug .djDebugInTransaction.djDebugHover div.djDebugLineChart strong{background-color:#94b24d;}#djDebug .panelContent ul.stats{position:relative;}#djDebug .panelContent ul.stats li{width:30%;float:left;}#djDebug .panelContent ul.stats li strong.label{display:block;}#djDebug .panelContent ul.stats li span.color{height:12px;width:3px;display:inline-block;}#djDebug .panelContent ul.stats li span.info{display:block;padding-left:5px;}#djDebug .panelcontent thead th{white-space:nowrap;}#djDebug .djDebugRowWarning .time{color:red;}#djdebug .panelcontent table .toggle{width:14px;padding-top:3px;}#djdebug .panelcontent table .actions{min-width:70px;}#djdebug .panelcontent table .color{width:3px;}#djdebug .panelcontent table .color span{width:3px;height:12px;overflow:hidden;padding:0;}#djDebug .djToggleSwitch{text-decoration:none;border:1px solid #999;height:12px;width:12px;line-height:12px;text-align:center;color:#777;display:inline-block;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF',endColorstr='#DCDCDC');background:-webkit-gradient(linear,left top,left bottom,from(#FFF),to(#DCDCDC));background:-moz-linear-gradient(center top,#FFF 0,#DCDCDC 100%) repeat scroll 0 0 transparent;}#djDebug .djNoToggleSwitch{height:14px;width:14px;display:inline-block;}#djDebug .djSQLDetailsDiv{margin-top:.8em;}#djDebug pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;color:#555;border:1px solid #ccc;border-collapse:collapse;background-color:#fff;display:block;overflow:auto;padding:2px 3px;margin-bottom:3px;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;}#djDebug .stack span{color:#000;font-weight:bold;}#djDebug .stack span.path{color:#777;font-weight:normal;}#djDebug .stack span.code{font-weight:normal;}@media print{#djDebug{display:none;}} \ No newline at end of file
diff --git a/debug_toolbar/media/debug_toolbar/js/toolbar.js b/debug_toolbar/media/debug_toolbar/js/toolbar.js
index c763fd2..3d66769 100644
--- a/debug_toolbar/media/debug_toolbar/js/toolbar.js
+++ b/debug_toolbar/media/debug_toolbar/js/toolbar.js
@@ -51,6 +51,11 @@ window.djdt = (function(window, document, jQuery) {
djdt.toggle_content($(this).parent().next());
return false;
});
+ $('#djDebug a.djDebugToggle').click(function(e) {
+ e.preventDefault();
+ $(this).parent().find('.djDebugCollapsed').toggle();
+ $(this).parent().find('.djDebugUncollapsed').toggle()
+ });
$('#djDebug a.djToggleSwitch').click(function(e) {
e.preventDefault();
var btn = $(this);
@@ -60,6 +65,8 @@ window.djdt = (function(window, document, jQuery) {
return;
}
+ btn.parents('.djDebugPanelContent').find('#sqlMain_' + id).find('.djDebugCollapsed').toggle(open_me);
+ btn.parents('.djDebugPanelContent').find('#sqlMain_' + id).find('.djDebugUncollapsed').toggle(!open_me);
$(this).parents('.djDebugPanelContent').find('.djToggleDetails_' + id).each(function(){
var $this = $(this);
if (open_me) {
@@ -198,4 +205,4 @@ window.djdt = (function(window, document, jQuery) {
djdt.init();
});
return djdt;
-}(window, document, jQuery.noConflict()));
+}(window, document, jQuery.noConflict(true)));
diff --git a/debug_toolbar/media/debug_toolbar/js/toolbar.min.js b/debug_toolbar/media/debug_toolbar/js/toolbar.min.js
index b72b0b5..4f843e2 100644
--- a/debug_toolbar/media/debug_toolbar/js/toolbar.min.js
+++ b/debug_toolbar/media/debug_toolbar/js/toolbar.min.js
@@ -20,4 +20,4 @@
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
-}(function(){var a5=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,a6=0,a8=Object.prototype.toString,a0=false,aZ=true;[0,0].sort(function(){aZ=false;return 0});var aW=function(bh,bc,bk,bl){bk=bk||[];var bn=bc=bc||aa;if(bc.nodeType!==1&&bc.nodeType!==9){return[]}if(!bh||typeof bh!=="string"){return bk}var bi=[],be,bp,bs,bd,bg=true,bf=aX(bc),bm=bh;while((a5.exec(""),be=a5.exec(bm))!==null){bm=be[3];bi.push(be[1]);if(be[2]){bd=be[3];break}}if(bi.length>1&&a1.exec(bh)){if(bi.length===2&&a2.relative[bi[0]]){bp=a9(bi[0]+bi[1],bc)}else{bp=a2.relative[bi[0]]?[bc]:aW(bi.shift(),bc);while(bi.length){bh=bi.shift();if(a2.relative[bh]){bh+=bi.shift()}bp=a9(bh,bp)}}}else{if(!bl&&bi.length>1&&bc.nodeType===9&&!bf&&a2.match.ID.test(bi[0])&&!a2.match.ID.test(bi[bi.length-1])){var bo=aW.find(bi.shift(),bc,bf);bc=bo.expr?aW.filter(bo.expr,bo.set)[0]:bo.set[0]}if(bc){var bo=bl?{expr:bi.pop(),set:a4(bl)}:aW.find(bi.pop(),bi.length===1&&(bi[0]==="~"||bi[0]==="+")&&bc.parentNode?bc.parentNode:bc,bf);bp=bo.expr?aW.filter(bo.expr,bo.set):bo.set;if(bi.length>0){bs=a4(bp)}else{bg=false}while(bi.length){var br=bi.pop(),bq=br;if(!a2.relative[br]){br=""}else{bq=bi.pop()}if(bq==null){bq=bc}a2.relative[br](bs,bq,bf)}}else{bs=bi=[]}}if(!bs){bs=bp}if(!bs){aW.error(br||bh)}if(a8.call(bs)==="[object Array]"){if(!bg){bk.push.apply(bk,bs)}else{if(bc&&bc.nodeType===1){for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&(bs[bj]===true||bs[bj].nodeType===1&&a3(bc,bs[bj]))){bk.push(bp[bj])}}}else{for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&bs[bj].nodeType===1){bk.push(bp[bj])}}}}}else{a4(bs,bk)}if(bd){aW(bd,bn,bk,bl);aW.uniqueSort(bk)}return bk};aW.uniqueSort=function(bd){if(a7){a0=aZ;bd.sort(a7);if(a0){for(var bc=1;bc<bd.length;bc++){if(bd[bc]===bd[bc-1]){bd.splice(bc--,1)}}}}return bd};aW.matches=function(bc,bd){return aW(bc,null,null,bd)};aW.find=function(bj,bc,bk){var bi,bg;if(!bj){return[]}for(var bf=0,be=a2.order.length;bf<be;bf++){var bh=a2.order[bf],bg;if((bg=a2.leftMatch[bh].exec(bj))){var bd=bg[1];bg.splice(1,1);if(bd.substr(bd.length-1)!=="\\"){bg[1]=(bg[1]||"").replace(/\\/g,"");bi=a2.find[bh](bg,bc,bk);if(bi!=null){bj=bj.replace(a2.match[bh],"");break}}}}if(!bi){bi=bc.getElementsByTagName("*")}return{set:bi,expr:bj}};aW.filter=function(bn,bm,bq,bg){var be=bn,bs=[],bk=bm,bi,bc,bj=bm&&bm[0]&&aX(bm[0]);while(bn&&bm.length){for(var bl in a2.filter){if((bi=a2.leftMatch[bl].exec(bn))!=null&&bi[2]){var bd=a2.filter[bl],br,bp,bf=bi[1];bc=false;bi.splice(1,1);if(bf.substr(bf.length-1)==="\\"){continue}if(bk===bs){bs=[]}if(a2.preFilter[bl]){bi=a2.preFilter[bl](bi,bk,bq,bs,bg,bj);if(!bi){bc=br=true}else{if(bi===true){continue}}}if(bi){for(var bh=0;(bp=bk[bh])!=null;bh++){if(bp){br=bd(bp,bi,bh,bk);var bo=bg^!!br;if(bq&&br!=null){if(bo){bc=true}else{bk[bh]=false}}else{if(bo){bs.push(bp);bc=true}}}}}if(br!==B){if(!bq){bk=bs}bn=bn.replace(a2.match[bl],"");if(!bc){return[]}break}}}if(bn===be){if(bc==null){aW.error(bn)}else{break}}be=bn}return bk};aW.error=function(bc){throw"Syntax error, unrecognized expression: "+bc};var a2=aW.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(bc){return bc.getAttribute("href")}},relative:{"+":function(bi,bd){var bf=typeof bd==="string",bh=bf&&!/\W/.test(bd),bj=bf&&!bh;if(bh){bd=bd.toLowerCase()}for(var be=0,bc=bi.length,bg;be<bc;be++){if((bg=bi[be])){while((bg=bg.previousSibling)&&bg.nodeType!==1){}bi[be]=bj||bg&&bg.nodeName.toLowerCase()===bd?bg||false:bg===bd}}if(bj){aW.filter(bd,bi,true)}},">":function(bi,bd){var bg=typeof bd==="string";if(bg&&!/\W/.test(bd)){bd=bd.toLowerCase();for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){var bf=bh.parentNode;bi[be]=bf.nodeName.toLowerCase()===bd?bf:false}}}else{for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){bi[be]=bg?bh.parentNode:bh.parentNode===bd}}if(bg){aW.filter(bd,bi,true)}}},"":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("parentNode",bd,be,bf,bg,bh)},"~":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("previousSibling",bd,be,bf,bg,bh)}},find:{ID:function(bd,be,bf){if(typeof be.getElementById!=="undefined"&&!bf){var bc=be.getElementById(bd[1]);return bc?[bc]:[]}},NAME:function(be,bh){if(typeof bh.getElementsByName!=="undefined"){var bd=[],bg=bh.getElementsByName(be[1]);for(var bf=0,bc=bg.length;bf<bc;bf++){if(bg[bf].getAttribute("name")===be[1]){bd.push(bg[bf])}}return bd.length===0?null:bd}},TAG:function(bc,bd){return bd.getElementsByTagName(bc[1])}},preFilter:{CLASS:function(bf,bd,be,bc,bi,bj){bf=" "+bf[1].replace(/\\/g,"")+" ";if(bj){return bf}for(var bg=0,bh;(bh=bd[bg])!=null;bg++){if(bh){if(bi^(bh.className&&(" "+bh.className+" ").replace(/[\t\n]/g," ").indexOf(bf)>=0)){if(!be){bc.push(bh)}}else{if(be){bd[bg]=false}}}}return false},ID:function(bc){return bc[1].replace(/\\/g,"")},TAG:function(bd,bc){return bd[1].toLowerCase()},CHILD:function(bc){if(bc[1]==="nth"){var bd=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(bc[2]==="even"&&"2n"||bc[2]==="odd"&&"2n+1"||!/\D/.test(bc[2])&&"0n+"+bc[2]||bc[2]);bc[2]=(bd[1]+(bd[2]||1))-0;bc[3]=bd[3]-0}bc[0]=a6++;return bc},ATTR:function(bg,bd,be,bc,bh,bi){var bf=bg[1].replace(/\\/g,"");if(!bi&&a2.attrMap[bf]){bg[1]=a2.attrMap[bf]}if(bg[2]==="~="){bg[4]=" "+bg[4]+" "}return bg},PSEUDO:function(bg,bd,be,bc,bh){if(bg[1]==="not"){if((a5.exec(bg[3])||"").length>1||/^\w/.test(bg[3])){bg[3]=aW(bg[3],null,null,bd)}else{var bf=aW.filter(bg[3],bd,be,true^bh);if(!be){bc.push.apply(bc,bf)}return false}}else{if(a2.match.POS.test(bg[0])||a2.match.CHILD.test(bg[0])){return true}}return bg},POS:function(bc){bc.unshift(true);return bc}},filters:{enabled:function(bc){return bc.disabled===false&&bc.type!=="hidden"},disabled:function(bc){return bc.disabled===true},checked:function(bc){return bc.checked===true},selected:function(bc){bc.parentNode.selectedIndex;return bc.selected===true},parent:function(bc){return !!bc.firstChild},empty:function(bc){return !bc.firstChild},has:function(be,bd,bc){return !!aW(bc[3],be).length},header:function(bc){return/h\d/i.test(bc.nodeName)},text:function(bc){return"text"===bc.type},radio:function(bc){return"radio"===bc.type},checkbox:function(bc){return"checkbox"===bc.type},file:function(bc){return"file"===bc.type},password:function(bc){return"password"===bc.type},submit:function(bc){return"submit"===bc.type},image:function(bc){return"image"===bc.type},reset:function(bc){return"reset"===bc.type},button:function(bc){return"button"===bc.type||bc.nodeName.toLowerCase()==="button"},input:function(bc){return/input|select|textarea|button/i.test(bc.nodeName)}},setFilters:{first:function(bd,bc){return bc===0},last:function(be,bd,bc,bf){return bd===bf.length-1},even:function(bd,bc){return bc%2===0},odd:function(bd,bc){return bc%2===1},lt:function(be,bd,bc){return bd<bc[3]-0},gt:function(be,bd,bc){return bd>bc[3]-0},nth:function(be,bd,bc){return bc[3]-0===bd},eq:function(be,bd,bc){return bc[3]-0===bd}},filter:{PSEUDO:function(bi,be,bf,bj){var bd=be[1],bg=a2.filters[bd];if(bg){return bg(bi,bf,be,bj)}else{if(bd==="contains"){return(bi.textContent||bi.innerText||aV([bi])||"").indexOf(be[3])>=0}else{if(bd==="not"){var bh=be[3];for(var bf=0,bc=bh.length;bf<bc;bf++){if(bh[bf]===bi){return false}}return true}else{aW.error("Syntax error, unrecognized expression: "+bd)}}}},CHILD:function(bc,bf){var bi=bf[1],bd=bc;switch(bi){case"only":case"first":while((bd=bd.previousSibling)){if(bd.nodeType===1){return false}}if(bi==="first"){return true}bd=bc;case"last":while((bd=bd.nextSibling)){if(bd.nodeType===1){return false}}return true;case"nth":var be=bf[2],bl=bf[3];if(be===1&&bl===0){return true}var bh=bf[0],bk=bc.parentNode;if(bk&&(bk.sizcache!==bh||!bc.nodeIndex)){var bg=0;for(bd=bk.firstChild;bd;bd=bd.nextSibling){if(bd.nodeType===1){bd.nodeIndex=++bg}}bk.sizcache=bh}var bj=bc.nodeIndex-bl;if(be===0){return bj===0}else{return(bj%be===0&&bj/be>=0)}}},ID:function(bd,bc){return bd.nodeType===1&&bd.getAttribute("id")===bc},TAG:function(bd,bc){return(bc==="*"&&bd.nodeType===1)||bd.nodeName.toLowerCase()===bc},CLASS:function(bd,bc){return(" "+(bd.className||bd.getAttribute("class"))+" ").indexOf(bc)>-1},ATTR:function(bh,bf){var be=bf[1],bc=a2.attrHandle[be]?a2.attrHandle[be](bh):bh[be]!=null?bh[be]:bh.getAttribute(be),bi=bc+"",bg=bf[2],bd=bf[4];return bc==null?bg==="!=":bg==="="?bi===bd:bg==="*="?bi.indexOf(bd)>=0:bg==="~="?(" "+bi+" ").indexOf(bd)>=0:!bd?bi&&bc!==false:bg==="!="?bi!==bd:bg==="^="?bi.indexOf(bd)===0:bg==="$="?bi.substr(bi.length-bd.length)===bd:bg==="|="?bi===bd||bi.substr(0,bd.length+1)===bd+"-":false},POS:function(bg,bd,be,bh){var bc=bd[2],bf=a2.setFilters[bc];if(bf){return bf(bg,be,bd,bh)}}}};var a1=a2.match.POS;for(var aY in a2.match){a2.match[aY]=new RegExp(a2.match[aY].source+/(?![^\[]*\])(?![^\(]*\))/.source);a2.leftMatch[aY]=new RegExp(/(^(?:.|\r|\n)*?)/.source+a2.match[aY].source.replace(/\\(\d+)/g,function(bd,bc){return"\\"+(bc-0+1)}))}var a4=function(bd,bc){bd=Array.prototype.slice.call(bd,0);if(bc){bc.push.apply(bc,bd);return bc}return bd};try{Array.prototype.slice.call(aa.documentElement.childNodes,0)}catch(bb){a4=function(bg,bf){var bd=bf||[];if(a8.call(bg)==="[object Array]"){Array.prototype.push.apply(bd,bg)}else{if(typeof bg.length==="number"){for(var be=0,bc=bg.length;be<bc;be++){bd.push(bg[be])}}else{for(var be=0;bg[be];be++){bd.push(bg[be])}}}return bd}}var a7;if(aa.documentElement.compareDocumentPosition){a7=function(bd,bc){if(!bd.compareDocumentPosition||!bc.compareDocumentPosition){if(bd==bc){a0=true}return bd.compareDocumentPosition?-1:1}var be=bd.compareDocumentPosition(bc)&4?-1:bd===bc?0:1;if(be===0){a0=true}return be}}else{if("sourceIndex" in aa.documentElement){a7=function(bd,bc){if(!bd.sourceIndex||!bc.sourceIndex){if(bd==bc){a0=true}return bd.sourceIndex?-1:1}var be=bd.sourceIndex-bc.sourceIndex;if(be===0){a0=true}return be}}else{if(aa.createRange){a7=function(bf,bd){if(!bf.ownerDocument||!bd.ownerDocument){if(bf==bd){a0=true}return bf.ownerDocument?-1:1}var be=bf.ownerDocument.createRange(),bc=bd.ownerDocument.createRange();be.setStart(bf,0);be.setEnd(bf,0);bc.setStart(bd,0);bc.setEnd(bd,0);var bg=be.compareBoundaryPoints(Range.START_TO_END,bc);if(bg===0){a0=true}return bg}}}}function aV(bc){var bd="",bf;for(var be=0;bc[be];be++){bf=bc[be];if(bf.nodeType===3||bf.nodeType===4){bd+=bf.nodeValue}else{if(bf.nodeType!==8){bd+=aV(bf.childNodes)}}}return bd}(function(){var bd=aa.createElement("div"),be="script"+(new Date).getTime();bd.innerHTML="<a name='"+be+"'/>";var bc=aa.documentElement;bc.insertBefore(bd,bc.firstChild);if(aa.getElementById(be)){a2.find.ID=function(bg,bh,bi){if(typeof bh.getElementById!=="undefined"&&!bi){var bf=bh.getElementById(bg[1]);return bf?bf.id===bg[1]||typeof bf.getAttributeNode!=="undefined"&&bf.getAttributeNode("id").nodeValue===bg[1]?[bf]:B:[]}};a2.filter.ID=function(bh,bf){var bg=typeof bh.getAttributeNode!=="undefined"&&bh.getAttributeNode("id");return bh.nodeType===1&&bg&&bg.nodeValue===bf}}bc.removeChild(bd);bc=bd=null})();(function(){var bc=aa.createElement("div");bc.appendChild(aa.createComment(""));if(bc.getElementsByTagName("*").length>0){a2.find.TAG=function(bd,bh){var bg=bh.getElementsByTagName(bd[1]);if(bd[1]==="*"){var bf=[];for(var be=0;bg[be];be++){if(bg[be].nodeType===1){bf.push(bg[be])}}bg=bf}return bg}}bc.innerHTML="<a href='#'></a>";if(bc.firstChild&&typeof bc.firstChild.getAttribute!=="undefined"&&bc.firstChild.getAttribute("href")!=="#"){a2.attrHandle.href=function(bd){return bd.getAttribute("href",2)}}bc=null})();if(aa.querySelectorAll){(function(){var bc=aW,be=aa.createElement("div");be.innerHTML="<p class='TEST'></p>";if(be.querySelectorAll&&be.querySelectorAll(".TEST").length===0){return}aW=function(bi,bh,bf,bg){bh=bh||aa;if(!bg&&bh.nodeType===9&&!aX(bh)){try{return a4(bh.querySelectorAll(bi),bf)}catch(bj){}}return bc(bi,bh,bf,bg)};for(var bd in bc){aW[bd]=bc[bd]}be=null})()}(function(){var bc=aa.createElement("div");bc.innerHTML="<div class='test e'></div><div class='test'></div>";if(!bc.getElementsByClassName||bc.getElementsByClassName("e").length===0){return}bc.lastChild.className="e";if(bc.getElementsByClassName("e").length===1){return}a2.order.splice(1,0,"CLASS");a2.find.CLASS=function(bd,be,bf){if(typeof be.getElementsByClassName!=="undefined"&&!bf){return be.getElementsByClassName(bd[1])}};bc=null})();function aU(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1&&!bk){bc.sizcache=bh;bc.sizset=bf}if(bc.nodeName.toLowerCase()===bi){bg=bc;break}bc=bc[bd]}bl[bf]=bg}}}function ba(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1){if(!bk){bc.sizcache=bh;bc.sizset=bf}if(typeof bi!=="string"){if(bc===bi){bg=true;break}}else{if(aW.filter(bi,[bc]).length>0){bg=bc;break}}}bc=bc[bd]}bl[bf]=bg}}}var a3=aa.compareDocumentPosition?function(bd,bc){return bd.compareDocumentPosition(bc)&16}:function(bd,bc){return bd!==bc&&(bd.contains?bd.contains(bc):true)};var aX=function(bc){var bd=(bc?bc.ownerDocument||bc:0).documentElement;return bd?bd.nodeName!=="HTML":false};var a9=function(bc,bj){var bf=[],bg="",bh,be=bj.nodeType?[bj]:bj;while((bh=a2.match.PSEUDO.exec(bc))){bg+=bh[0];bc=bc.replace(a2.match.PSEUDO,"")}bc=a2.relative[bc]?bc+"*":bc;for(var bi=0,bd=be.length;bi<bd;bi++){aW(bc,be[bi],bf)}return aW.filter(bg,bf)};a.find=aW;a.expr=aW.selectors;a.expr[":"]=a.expr.filters;a.unique=aW.uniqueSort;a.getText=aV;a.isXMLDoc=aX;a.contains=a3;return;aI.Sizzle=aW})();var M=/Until$/,X=/^(?:parents|prevUntil|prevAll)/,aH=/,/,D=Array.prototype.slice;var ag=function(aX,aW,aU){if(a.isFunction(aW)){return a.grep(aX,function(aZ,aY){return !!aW.call(aZ,aY,aZ)===aU})}else{if(aW.nodeType){return a.grep(aX,function(aZ,aY){return(aZ===aW)===aU})}else{if(typeof aW==="string"){var aV=a.grep(aX,function(aY){return aY.nodeType===1});if(aS.test(aW)){return a.filter(aW,aV,!aU)}else{aW=a.filter(aW,aV)}}}}return a.grep(aX,function(aZ,aY){return(a.inArray(aZ,aW)>=0)===aU})};a.fn.extend({find:function(aU){var aW=this.pushStack("","find",aU),aZ=0;for(var aX=0,aV=this.length;aX<aV;aX++){aZ=aW.length;a.find(aU,this[aX],aW);if(aX>0){for(var a0=aZ;a0<aW.length;a0++){for(var aY=0;aY<aZ;aY++){if(aW[aY]===aW[a0]){aW.splice(a0--,1);break}}}}}return aW},has:function(aV){var aU=a(aV);return this.filter(function(){for(var aX=0,aW=aU.length;aX<aW;aX++){if(a.contains(this,aU[aX])){return true}}})},not:function(aU){return this.pushStack(ag(this,aU,false),"not",aU)},filter:function(aU){return this.pushStack(ag(this,aU,true),"filter",aU)},is:function(aU){return !!aU&&a.filter(aU,this).length>0},closest:function(a3,aU){if(a.isArray(a3)){var a0=[],a2=this[0],aZ,aY={},aW;if(a2&&a3.length){for(var aX=0,aV=a3.length;aX<aV;aX++){aW=a3[aX];if(!aY[aW]){aY[aW]=a.expr.match.POS.test(aW)?a(aW,aU||this.context):aW}}while(a2&&a2.ownerDocument&&a2!==aU){for(aW in aY){aZ=aY[aW];if(aZ.jquery?aZ.index(a2)>-1:a(a2).is(aZ)){a0.push({selector:aW,elem:a2});delete aY[aW]}}a2=a2.parentNode}}return a0}var a1=a.expr.match.POS.test(a3)?a(a3,aU||this.context):null;return this.map(function(a4,a5){while(a5&&a5.ownerDocument&&a5!==aU){if(a1?a1.index(a5)>-1:a(a5).is(a3)){return a5}a5=a5.parentNode}return null})},index:function(aU){if(!aU||typeof aU==="string"){return a.inArray(this[0],aU?a(aU):this.parent().children())}return a.inArray(aU.jquery?aU[0]:aU,this)},add:function(aU,aV){var aX=typeof aU==="string"?a(aU,aV||this.context):a.makeArray(aU),aW=a.merge(this.get(),aX);return this.pushStack(x(aX[0])||x(aW[0])?aW:a.unique(aW))},andSelf:function(){return this.add(this.prevObject)}});function x(aU){return !aU||!aU.parentNode||aU.parentNode.nodeType===11}a.each({parent:function(aV){var aU=aV.parentNode;return aU&&aU.nodeType!==11?aU:null},parents:function(aU){return a.dir(aU,"parentNode")},parentsUntil:function(aV,aU,aW){return a.dir(aV,"parentNode",aW)},next:function(aU){return a.nth(aU,2,"nextSibling")},prev:function(aU){return a.nth(aU,2,"previousSibling")},nextAll:function(aU){return a.dir(aU,"nextSibling")},prevAll:function(aU){return a.dir(aU,"previousSibling")},nextUntil:function(aV,aU,aW){return a.dir(aV,"nextSibling",aW)},prevUntil:function(aV,aU,aW){return a.dir(aV,"previousSibling",aW)},siblings:function(aU){return a.sibling(aU.parentNode.firstChild,aU)},children:function(aU){return a.sibling(aU.firstChild)},contents:function(aU){return a.nodeName(aU,"iframe")?aU.contentDocument||aU.contentWindow.document:a.makeArray(aU.childNodes)}},function(aU,aV){a.fn[aU]=function(aY,aW){var aX=a.map(this,aV,aY);if(!M.test(aU)){aW=aY}if(aW&&typeof aW==="string"){aX=a.filter(aW,aX)}aX=this.length>1?a.unique(aX):aX;if((this.length>1||aH.test(aW))&&X.test(aU)){aX=aX.reverse()}return this.pushStack(aX,aU,D.call(arguments).join(","))}});a.extend({filter:function(aW,aU,aV){if(aV){aW=":not("+aW+")"}return a.find.matches(aW,aU)},dir:function(aW,aV,aY){var aU=[],aX=aW[aV];while(aX&&aX.nodeType!==9&&(aY===B||aX.nodeType!==1||!a(aX).is(aY))){if(aX.nodeType===1){aU.push(aX)}aX=aX[aV]}return aU},nth:function(aY,aU,aW,aX){aU=aU||1;var aV=0;for(;aY;aY=aY[aW]){if(aY.nodeType===1&&++aV===aU){break}}return aY},sibling:function(aW,aV){var aU=[];for(;aW;aW=aW.nextSibling){if(aW.nodeType===1&&aW!==aV){aU.push(aW)}}return aU}});var S=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,F=/(<([\w:]+)[^>]*?)\/>/g,aj=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,c=/<([\w:]+)/,t=/<tbody/i,J=/<|&\w+;/,l=/checked\s*(?:[^=]|=\s*.checked.)/i,p=function(aV,aW,aU){return aj.test(aU)?aV:aW+"></"+aU+">"},ab={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};ab.optgroup=ab.option;ab.tbody=ab.tfoot=ab.colgroup=ab.caption=ab.thead;ab.th=ab.td;if(!a.support.htmlSerialize){ab._default=[1,"div<div>","</div>"]}a.fn.extend({text:function(aU){if(a.isFunction(aU)){return this.each(function(aW){var aV=a(this);aV.text(aU.call(this,aW,aV.text()))})}if(typeof aU!=="object"&&aU!==B){return this.empty().append((this[0]&&this[0].ownerDocument||aa).createTextNode(aU))}return a.getText(this)},wrapAll:function(aU){if(a.isFunction(aU)){return this.each(function(aW){a(this).wrapAll(aU.call(this,aW))})}if(this[0]){var aV=a(aU,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){aV.insertBefore(this[0])}aV.map(function(){var aW=this;while(aW.firstChild&&aW.firstChild.nodeType===1){aW=aW.firstChild}return aW}).append(this)}return this},wrapInner:function(aU){if(a.isFunction(aU)){return this.each(function(aV){a(this).wrapInner(aU.call(this,aV))})}return this.each(function(){var aV=a(this),aW=aV.contents();if(aW.length){aW.wrapAll(aU)}else{aV.append(aU)}})},wrap:function(aU){return this.each(function(){a(this).wrapAll(aU)})},unwrap:function(){return this.parent().each(function(){if(!a.nodeName(this,"body")){a(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.appendChild(aU)}})},prepend:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.insertBefore(aU,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this)})}else{if(arguments.length){var aU=a(arguments[0]);aU.push.apply(aU,this.toArray());return this.pushStack(aU,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this.nextSibling)})}else{if(arguments.length){var aU=this.pushStack(this,"after",arguments);aU.push.apply(aU,a(arguments[0]).toArray());return aU}}},clone:function(aV){var aU=this.map(function(){if(!a.support.noCloneEvent&&!a.isXMLDoc(this)){var aX=this.outerHTML,aW=this.ownerDocument;if(!aX){var aY=aW.createElement("div");aY.appendChild(this.cloneNode(true));aX=aY.innerHTML}return a.clean([aX.replace(S,"").replace(Y,"")],aW)[0]}else{return this.cloneNode(true)}});if(aV===true){q(this,aU);q(this.find("*"),aU.find("*"))}return aU},html:function(aW){if(aW===B){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(S,""):null}else{if(typeof aW==="string"&&!/<script/i.test(aW)&&(a.support.leadingWhitespace||!Y.test(aW))&&!ab[(c.exec(aW)||["",""])[1].toLowerCase()]){aW=aW.replace(F,p);try{for(var aV=0,aU=this.length;aV<aU;aV++){if(this[aV].nodeType===1){a.cleanData(this[aV].getElementsByTagName("*"));this[aV].innerHTML=aW}}}catch(aX){this.empty().append(aW)}}else{if(a.isFunction(aW)){this.each(function(a0){var aZ=a(this),aY=aZ.html();aZ.empty().append(function(){return aW.call(this,a0,aY)})})}else{this.empty().append(aW)}}}return this},replaceWith:function(aU){if(this[0]&&this[0].parentNode){if(!a.isFunction(aU)){aU=a(aU).detach()}else{return this.each(function(aX){var aW=a(this),aV=aW.html();aW.replaceWith(aU.call(this,aX,aV))})}return this.each(function(){var aW=this.nextSibling,aV=this.parentNode;a(this).remove();if(aW){a(aW).before(aU)}else{a(aV).append(aU)}})}else{return this.pushStack(a(a.isFunction(aU)?aU():aU),"replaceWith",aU)}},detach:function(aU){return this.remove(aU,true)},domManip:function(aZ,a3,a2){var aW,aY,a1=aZ[0],aV=[];if(!a.support.checkClone&&arguments.length===3&&typeof a1==="string"&&l.test(a1)){return this.each(function(){a(this).domManip(aZ,a3,a2,true)})}if(a.isFunction(a1)){return this.each(function(a5){var a4=a(this);aZ[0]=a1.call(this,a5,a3?a4.html():B);a4.domManip(aZ,a3,a2)})}if(this[0]){if(aZ[0]&&aZ[0].parentNode&&aZ[0].parentNode.nodeType===11){aW={fragment:aZ[0].parentNode}}else{aW=H(aZ,this,aV)}aY=aW.fragment.firstChild;if(aY){a3=a3&&a.nodeName(aY,"tr");for(var aX=0,aU=this.length;aX<aU;aX++){a2.call(a3?a0(this[aX],aY):this[aX],aW.cacheable||this.length>1||aX>0?aW.fragment.cloneNode(true):aW.fragment)}}if(aV){a.each(aV,aR)}}return this;function a0(a4,a5){return a.nodeName(a4,"table")?(a4.getElementsByTagName("tbody")[0]||a4.appendChild(a4.ownerDocument.createElement("tbody"))):a4}}});function q(aW,aU){var aV=0;aU.each(function(){if(this.nodeName!==(aW[aV]&&aW[aV].nodeName)){return}var a1=a.data(aW[aV++]),a0=a.data(this,a1),aX=a1&&a1.events;if(aX){delete a0.handle;a0.events={};for(var aZ in aX){for(var aY in aX[aZ]){a.event.add(this,aZ,aX[aZ][aY],aX[aZ][aY].data)}}}})}function H(aZ,aX,aV){var aY,aU,aW,a0;if(aZ.length===1&&typeof aZ[0]==="string"&&aZ[0].length<512&&aZ[0].indexOf("<option")<0&&(a.support.checkClone||!l.test(aZ[0]))){aU=true;aW=a.fragments[aZ[0]];if(aW){if(aW!==1){aY=aW}}}if(!aY){a0=(aX&&aX[0]?aX[0].ownerDocument||aX[0]:aa);aY=a0.createDocumentFragment();a.clean(aZ,a0,aY,aV)}if(aU){a.fragments[aZ[0]]=aW?aY:1}return{fragment:aY,cacheable:aU}}a.fragments={};a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(aU,aV){a.fn[aU]=function(aW){var aZ=[],a1=a(aW);for(var a0=0,aX=a1.length;a0<aX;a0++){var aY=(a0>0?this.clone(true):this).get();a.fn[aV].apply(a(a1[a0]),aY);aZ=aZ.concat(aY)}return this.pushStack(aZ,aU,a1.selector)}});a.each({remove:function(aU,aV){if(!aU||a.filter(aU,[this]).length){if(!aV&&this.nodeType===1){a.cleanData(this.getElementsByTagName("*"));a.cleanData([this])}if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){if(this.nodeType===1){a.cleanData(this.getElementsByTagName("*"))}while(this.firstChild){this.removeChild(this.firstChild)}}},function(aU,aV){a.fn[aU]=function(){return this.each(aV,arguments)}});a.extend({clean:function(aV,aZ,aX,aU){aZ=aZ||aa;if(typeof aZ.createElement==="undefined"){aZ=aZ.ownerDocument||aZ[0]&&aZ[0].ownerDocument||aa}var aW=[];a.each(aV,function(a6,a3){if(typeof a3==="number"){a3+=""}if(!a3){return}if(typeof a3==="string"&&!J.test(a3)){a3=aZ.createTextNode(a3)}else{if(typeof a3==="string"){a3=a3.replace(F,p);var a8=(c.exec(a3)||["",""])[1].toLowerCase(),a2=ab[a8]||ab._default,a5=a2[0],a0=aZ.createElement("div");a0.innerHTML=a2[1]+a3+a2[2];while(a5--){a0=a0.lastChild}if(!a.support.tbody){var a1=t.test(a3),a7=a8==="table"&&!a1?a0.firstChild&&a0.firstChild.childNodes:a2[1]==="<table>"&&!a1?a0.childNodes:[];for(var a4=a7.length-1;a4>=0;--a4){if(a.nodeName(a7[a4],"tbody")&&!a7[a4].childNodes.length){a7[a4].parentNode.removeChild(a7[a4])}}}if(!a.support.leadingWhitespace&&Y.test(a3)){a0.insertBefore(aZ.createTextNode(Y.exec(a3)[0]),a0.firstChild)}a3=a.makeArray(a0.childNodes)}}if(a3.nodeType){aW.push(a3)}else{aW=a.merge(aW,a3)}});if(aX){for(var aY=0;aW[aY];aY++){if(aU&&a.nodeName(aW[aY],"script")&&(!aW[aY].type||aW[aY].type.toLowerCase()==="text/javascript")){aU.push(aW[aY].parentNode?aW[aY].parentNode.removeChild(aW[aY]):aW[aY])}else{if(aW[aY].nodeType===1){aW.splice.apply(aW,[aY+1,0].concat(a.makeArray(aW[aY].getElementsByTagName("script"))))}aX.appendChild(aW[aY])}}}return aW},cleanData:function(aU){for(var aV=0,aW,aX;(aW=aU[aV])!=null;aV++){a.event.remove(aW);a.removeData(aW)}}});var ap=/z-?index|font-?weight|opacity|zoom|line-?height/i,T=/alpha\([^)]*\)/,Z=/opacity=([^)]*)/,af=/float/i,aw=/-([a-z])/ig,v=/([A-Z])/g,aK=/^-?\d+(?:px)?$/i,aQ=/^-?\d/,aG={position:"absolute",visibility:"hidden",display:"block"},V=["Left","Right"],aA=["Top","Bottom"],ai=aa.defaultView&&aa.defaultView.getComputedStyle,aJ=a.support.cssFloat?"cssFloat":"styleFloat",k=function(aU,aV){return aV.toUpperCase()};a.fn.css=function(aU,aV){return al(this,aU,aV,true,function(aX,aW,aY){if(aY===B){return a.curCSS(aX,aW)}if(typeof aY==="number"&&!ap.test(aW)){aY+="px"}a.style(aX,aW,aY)})};a.extend({style:function(aY,aV,aZ){if(!aY||aY.nodeType===3||aY.nodeType===8){return B}if((aV==="width"||aV==="height")&&parseFloat(aZ)<0){aZ=B}var aX=aY.style||aY,a0=aZ!==B;if(!a.support.opacity&&aV==="opacity"){if(a0){aX.zoom=1;var aU=parseInt(aZ,10)+""==="NaN"?"":"alpha(opacity="+aZ*100+")";var aW=aX.filter||a.curCSS(aY,"filter")||"";aX.filter=T.test(aW)?aW.replace(T,aU):aU}return aX.filter&&aX.filter.indexOf("opacity=")>=0?(parseFloat(Z.exec(aX.filter)[1])/100)+"":""}if(af.test(aV)){aV=aJ}aV=aV.replace(aw,k);if(a0){aX[aV]=aZ}return aX[aV]},css:function(aX,aV,aZ,aU){if(aV==="width"||aV==="height"){var a1,aW=aG,a0=aV==="width"?V:aA;function aY(){a1=aV==="width"?aX.offsetWidth:aX.offsetHeight;if(aU==="border"){return}a.each(a0,function(){if(!aU){a1-=parseFloat(a.curCSS(aX,"padding"+this,true))||0}if(aU==="margin"){a1+=parseFloat(a.curCSS(aX,"margin"+this,true))||0}else{a1-=parseFloat(a.curCSS(aX,"border"+this+"Width",true))||0}})}if(aX.offsetWidth!==0){aY()}else{a.swap(aX,aW,aY)}return Math.max(0,Math.round(a1))}return a.curCSS(aX,aV,aZ)},curCSS:function(a0,aV,aW){var a3,aU=a0.style,aX;if(!a.support.opacity&&aV==="opacity"&&a0.currentStyle){a3=Z.test(a0.currentStyle.filter||"")?(parseFloat(RegExp.$1)/100)+"":"";return a3===""?"1":a3}if(af.test(aV)){aV=aJ}if(!aW&&aU&&aU[aV]){a3=aU[aV]}else{if(ai){if(af.test(aV)){aV="float"}aV=aV.replace(v,"-$1").toLowerCase();var a2=a0.ownerDocument.defaultView;if(!a2){return null}var a4=a2.getComputedStyle(a0,null);if(a4){a3=a4.getPropertyValue(aV)}if(aV==="opacity"&&a3===""){a3="1"}}else{if(a0.currentStyle){var aZ=aV.replace(aw,k);a3=a0.currentStyle[aV]||a0.currentStyle[aZ];if(!aK.test(a3)&&aQ.test(a3)){var aY=aU.left,a1=a0.runtimeStyle.left;a0.runtimeStyle.left=a0.currentStyle.left;aU.left=aZ==="fontSize"?"1em":(a3||0);a3=aU.pixelLeft+"px";aU.left=aY;a0.runtimeStyle.left=a1}}}}return a3},swap:function(aX,aW,aY){var aU={};for(var aV in aW){aU[aV]=aX.style[aV];aX.style[aV]=aW[aV]}aY.call(aX);for(var aV in aW){aX.style[aV]=aU[aV]}}});if(a.expr&&a.expr.filters){a.expr.filters.hidden=function(aX){var aV=aX.offsetWidth,aU=aX.offsetHeight,aW=aX.nodeName.toLowerCase()==="tr";return aV===0&&aU===0&&!aW?true:aV>0&&aU>0&&!aW?false:a.curCSS(aX,"display")==="none"};a.expr.filters.visible=function(aU){return !a.expr.filters.hidden(aU)}}var ae=aL(),aF=/<script(.|\s)*?\/script>/gi,o=/select|textarea/i,ay=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,r=/=\?(&|$)/,C=/\?/,aT=/(\?|&)_=.*?(&|$)/,A=/^(\w+:)?\/\/([^\/?#]+)/,h=/%20/g;a.fn.extend({_load:a.fn.load,load:function(aW,aZ,a0){if(typeof aW!=="string"){return this._load(aW)}else{if(!this.length){return this}}var aY=aW.indexOf(" ");if(aY>=0){var aU=aW.slice(aY,aW.length);aW=aW.slice(0,aY)}var aX="GET";if(aZ){if(a.isFunction(aZ)){a0=aZ;aZ=null}else{if(typeof aZ==="object"){aZ=a.param(aZ,a.ajaxSettings.traditional);aX="POST"}}}var aV=this;a.ajax({url:aW,type:aX,dataType:"html",data:aZ,complete:function(a2,a1){if(a1==="success"||a1==="notmodified"){aV.html(aU?a("<div />").append(a2.responseText.replace(aF,"")).find(aU):a2.responseText)}if(a0){aV.each(a0,[a2.responseText,a1,a2])}}});return this},serialize:function(){return a.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?a.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||o.test(this.nodeName)||ay.test(this.type))}).map(function(aU,aV){var aW=a(this).val();return aW==null?null:a.isArray(aW)?a.map(aW,function(aY,aX){return{name:aV.name,value:aY}}):{name:aV.name,value:aW}}).get()}});a.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(aU,aV){a.fn[aV]=function(aW){return this.bind(aV,aW)}});a.extend({get:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW=null}return a.ajax({type:"GET",url:aU,data:aW,success:aX,dataType:aV})},getScript:function(aU,aV){return a.get(aU,null,aV,"script")},getJSON:function(aU,aV,aW){return a.get(aU,aV,aW,"json")},post:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW={}}return a.ajax({type:"POST",url:aU,data:aW,success:aX,dataType:aV})},ajaxSetup:function(aU){a.extend(a.ajaxSettings,aU)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:aI.XMLHttpRequest&&(aI.location.protocol!=="file:"||!aI.ActiveXObject)?function(){return new aI.XMLHttpRequest()}:function(){try{return new aI.ActiveXObject("Microsoft.XMLHTTP")}catch(aU){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a9){var a4=a.extend(true,{},a.ajaxSettings,a9);var be,a8,bd,bf=a9&&a9.context||a4,aW=a4.type.toUpperCase();if(a4.data&&a4.processData&&typeof a4.data!=="string"){a4.data=a.param(a4.data,a4.traditional)}if(a4.dataType==="jsonp"){if(aW==="GET"){if(!r.test(a4.url)){a4.url+=(C.test(a4.url)?"&":"?")+(a4.jsonp||"callback")+"=?"}}else{if(!a4.data||!r.test(a4.data)){a4.data=(a4.data?a4.data+"&":"")+(a4.jsonp||"callback")+"=?"}}a4.dataType="json"}if(a4.dataType==="json"&&(a4.data&&r.test(a4.data)||r.test(a4.url))){be=a4.jsonpCallback||("jsonp"+ae++);if(a4.data){a4.data=(a4.data+"").replace(r,"="+be+"$1")}a4.url=a4.url.replace(r,"="+be+"$1");a4.dataType="script";aI[be]=aI[be]||function(bg){bd=bg;aZ();a2();aI[be]=B;try{delete aI[be]}catch(bh){}if(aX){aX.removeChild(bb)}}}if(a4.dataType==="script"&&a4.cache===null){a4.cache=false}if(a4.cache===false&&aW==="GET"){var aU=aL();var bc=a4.url.replace(aT,"$1_="+aU+"$2");a4.url=bc+((bc===a4.url)?(C.test(a4.url)?"&":"?")+"_="+aU:"")}if(a4.data&&aW==="GET"){a4.url+=(C.test(a4.url)?"&":"?")+a4.data}if(a4.global&&!a.active++){a.event.trigger("ajaxStart")}var a7=A.exec(a4.url),aY=a7&&(a7[1]&&a7[1]!==location.protocol||a7[2]!==location.host);if(a4.dataType==="script"&&aW==="GET"&&aY){var aX=aa.getElementsByTagName("head")[0]||aa.documentElement;var bb=aa.createElement("script");bb.src=a4.url;if(a4.scriptCharset){bb.charset=a4.scriptCharset}if(!be){var a6=false;bb.onload=bb.onreadystatechange=function(){if(!a6&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){a6=true;aZ();a2();bb.onload=bb.onreadystatechange=null;if(aX&&bb.parentNode){aX.removeChild(bb)}}}}aX.insertBefore(bb,aX.firstChild);return B}var a1=false;var a0=a4.xhr();if(!a0){return}if(a4.username){a0.open(aW,a4.url,a4.async,a4.username,a4.password)}else{a0.open(aW,a4.url,a4.async)}try{if(a4.data||a9&&a9.contentType){a0.setRequestHeader("Content-Type",a4.contentType)}if(a4.ifModified){if(a.lastModified[a4.url]){a0.setRequestHeader("If-Modified-Since",a.lastModified[a4.url])}if(a.etag[a4.url]){a0.setRequestHeader("If-None-Match",a.etag[a4.url])}}if(!aY){a0.setRequestHeader("X-Requested-With","XMLHttpRequest")}a0.setRequestHeader("Accept",a4.dataType&&a4.accepts[a4.dataType]?a4.accepts[a4.dataType]+", */*":a4.accepts._default)}catch(ba){}if(a4.beforeSend&&a4.beforeSend.call(bf,a0,a4)===false){if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}a0.abort();return false}if(a4.global){a5("ajaxSend",[a0,a4])}var a3=a0.onreadystatechange=function(bg){if(!a0||a0.readyState===0||bg==="abort"){if(!a1){a2()}a1=true;if(a0){a0.onreadystatechange=a.noop}}else{if(!a1&&a0&&(a0.readyState===4||bg==="timeout")){a1=true;a0.onreadystatechange=a.noop;a8=bg==="timeout"?"timeout":!a.httpSuccess(a0)?"error":a4.ifModified&&a.httpNotModified(a0,a4.url)?"notmodified":"success";var bi;if(a8==="success"){try{bd=a.httpData(a0,a4.dataType,a4)}catch(bh){a8="parsererror";bi=bh}}if(a8==="success"||a8==="notmodified"){if(!be){aZ()}}else{a.handleError(a4,a0,a8,bi)}a2();if(bg==="timeout"){a0.abort()}if(a4.async){a0=null}}}};try{var aV=a0.abort;a0.abort=function(){if(a0){aV.call(a0)}a3("abort")}}catch(ba){}if(a4.async&&a4.timeout>0){setTimeout(function(){if(a0&&!a1){a3("timeout")}},a4.timeout)}try{a0.send(aW==="POST"||aW==="PUT"||aW==="DELETE"?a4.data:null)}catch(ba){a.handleError(a4,a0,null,ba);a2()}if(!a4.async){a3()}function aZ(){if(a4.success){a4.success.call(bf,bd,a8,a0)}if(a4.global){a5("ajaxSuccess",[a0,a4])}}function a2(){if(a4.complete){a4.complete.call(bf,a0,a8)}if(a4.global){a5("ajaxComplete",[a0,a4])}if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}}function a5(bh,bg){(a4.context?a(a4.context):a.event).trigger(bh,bg)}return a0},handleError:function(aV,aX,aU,aW){if(aV.error){aV.error.call(aV.context||aV,aX,aU,aW)}if(aV.global){(aV.context?a(aV.context):a.event).trigger("ajaxError",[aX,aV,aW])}},active:0,httpSuccess:function(aV){try{return !aV.status&&location.protocol==="file:"||(aV.status>=200&&aV.status<300)||aV.status===304||aV.status===1223||aV.status===0}catch(aU){}return false},httpNotModified:function(aX,aU){var aW=aX.getResponseHeader("Last-Modified"),aV=aX.getResponseHeader("Etag");if(aW){a.lastModified[aU]=aW}if(aV){a.etag[aU]=aV}return aX.status===304||aX.status===0},httpData:function(aZ,aX,aW){var aV=aZ.getResponseHeader("content-type")||"",aU=aX==="xml"||!aX&&aV.indexOf("xml")>=0,aY=aU?aZ.responseXML:aZ.responseText;if(aU&&aY.documentElement.nodeName==="parsererror"){a.error("parsererror")}if(aW&&aW.dataFilter){aY=aW.dataFilter(aY,aX)}if(typeof aY==="string"){if(aX==="json"||!aX&&aV.indexOf("json")>=0){aY=a.parseJSON(aY)}else{if(aX==="script"||!aX&&aV.indexOf("javascript")>=0){a.globalEval(aY)}}}return aY},param:function(aU,aX){var aV=[];if(aX===B){aX=a.ajaxSettings.traditional}if(a.isArray(aU)||aU.jquery){a.each(aU,function(){aZ(this.name,this.value)})}else{for(var aY in aU){aW(aY,aU[aY])}}return aV.join("&").replace(h,"+");function aW(a0,a1){if(a.isArray(a1)){a.each(a1,function(a3,a2){if(aX){aZ(a0,a2)}else{aW(a0+"["+(typeof a2==="object"||a.isArray(a2)?a3:"")+"]",a2)}})}else{if(!aX&&a1!=null&&typeof a1==="object"){a.each(a1,function(a3,a2){aW(a0+"["+a3+"]",a2)})}else{aZ(a0,a1)}}}function aZ(a0,a1){a1=a.isFunction(a1)?a1():a1;aV[aV.length]=encodeURIComponent(a0)+"="+encodeURIComponent(a1)}}});var E={},ad=/toggle|show|hide/,ar=/^([+-]=)?([\d+-.]+)(.*)$/,aB,ah=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];a.fn.extend({show:function(aV,a3){if(aV||aV===0){return this.animate(az("show",3),aV,a3)}else{for(var a0=0,aX=this.length;a0<aX;a0++){var aU=a.data(this[a0],"olddisplay");this[a0].style.display=aU||"";if(a.css(this[a0],"display")==="none"){var a2=this[a0].nodeName,a1;if(E[a2]){a1=E[a2]}else{var aW=a("<"+a2+" />").appendTo("body");a1=aW.css("display");if(a1==="none"){a1="block"}aW.remove();E[a2]=a1}a.data(this[a0],"olddisplay",a1)}}for(var aZ=0,aY=this.length;aZ<aY;aZ++){this[aZ].style.display=a.data(this[aZ],"olddisplay")||""}return this}},hide:function(aZ,a0){if(aZ||aZ===0){return this.animate(az("hide",3),aZ,a0)}else{for(var aY=0,aV=this.length;aY<aV;aY++){var aU=a.data(this[aY],"olddisplay");if(!aU&&aU!=="none"){a.data(this[aY],"olddisplay",a.css(this[aY],"display"))}}for(var aX=0,aW=this.length;aX<aW;aX++){this[aX].style.display="none"}return this}},_toggle:a.fn.toggle,toggle:function(aW,aV){var aU=typeof aW==="boolean";if(a.isFunction(aW)&&a.isFunction(aV)){this._toggle.apply(this,arguments)}else{if(aW==null||aU){this.each(function(){var aX=aU?aW:a(this).is(":hidden");a(this)[aX?"show":"hide"]()})}else{this.animate(az("toggle",3),aW,aV)}}return this},fadeTo:function(aU,aW,aV){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:aW},aU,aV)},animate:function(aY,aV,aX,aW){var aU=a.speed(aV,aX,aW);if(a.isEmptyObject(aY)){return this.each(aU.complete)}return this[aU.queue===false?"each":"queue"](function(){var a1=a.extend({},aU),a3,a2=this.nodeType===1&&a(this).is(":hidden"),aZ=this;for(a3 in aY){var a0=a3.replace(aw,k);if(a3!==a0){aY[a0]=aY[a3];delete aY[a3];a3=a0}if(aY[a3]==="hide"&&a2||aY[a3]==="show"&&!a2){return a1.complete.call(this)}if((a3==="height"||a3==="width")&&this.style){a1.display=a.css(this,"display");a1.overflow=this.style.overflow}if(a.isArray(aY[a3])){(a1.specialEasing=a1.specialEasing||{})[a3]=aY[a3][1];aY[a3]=aY[a3][0]}}if(a1.overflow!=null){this.style.overflow="hidden"}a1.curAnim=a.extend({},aY);a.each(aY,function(a5,a9){var a8=new a.fx(aZ,a1,a5);if(ad.test(a9)){a8[a9==="toggle"?a2?"show":"hide":a9](aY)}else{var a7=ar.exec(a9),ba=a8.cur(true)||0;if(a7){var a4=parseFloat(a7[2]),a6=a7[3]||"px";if(a6!=="px"){aZ.style[a5]=(a4||1)+a6;ba=((a4||1)/a8.cur(true))*ba;aZ.style[a5]=ba+a6}if(a7[1]){a4=((a7[1]==="-="?-1:1)*a4)+ba}a8.custom(ba,a4,a6)}else{a8.custom(ba,a9,"")}}});return true})},stop:function(aV,aU){var aW=a.timers;if(aV){this.queue([])}this.each(function(){for(var aX=aW.length-1;aX>=0;aX--){if(aW[aX].elem===this){if(aU){aW[aX](true)}aW.splice(aX,1)}}});if(!aU){this.dequeue()}return this}});a.each({slideDown:az("show",1),slideUp:az("hide",1),slideToggle:az("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(aU,aV){a.fn[aU]=function(aW,aX){return this.animate(aV,aW,aX)}});a.extend({speed:function(aW,aX,aV){var aU=aW&&typeof aW==="object"?aW:{complete:aV||!aV&&aX||a.isFunction(aW)&&aW,duration:aW,easing:aV&&aX||aX&&!a.isFunction(aX)&&aX};aU.duration=a.fx.off?0:typeof aU.duration==="number"?aU.duration:a.fx.speeds[aU.duration]||a.fx.speeds._default;aU.old=aU.complete;aU.complete=function(){if(aU.queue!==false){a(this).dequeue()}if(a.isFunction(aU.old)){aU.old.call(this)}};return aU},easing:{linear:function(aW,aX,aU,aV){return aU+aV*aW},swing:function(aW,aX,aU,aV){return((-Math.cos(aW*Math.PI)/2)+0.5)*aV+aU}},timers:[],fx:function(aV,aU,aW){this.options=aU;this.elem=aV;this.prop=aW;if(!aU.orig){aU.orig={}}}});a.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(a.fx.step[this.prop]||a.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(aV){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var aU=parseFloat(a.css(this.elem,this.prop,aV));return aU&&aU>-10000?aU:parseFloat(a.curCSS(this.elem,this.prop))||0},custom:function(aY,aX,aW){this.startTime=aL();this.start=aY;this.end=aX;this.unit=aW||this.unit||"px";this.now=this.start;this.pos=this.state=0;var aU=this;function aV(aZ){return aU.step(aZ)}aV.elem=this.elem;if(aV()&&a.timers.push(aV)&&!aB){aB=setInterval(a.fx.tick,13)}},show:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());a(this.elem).show()},hide:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(aX){var a2=aL(),aY=true;if(aX||a2>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var aZ in this.options.curAnim){if(this.options.curAnim[aZ]!==true){aY=false}}if(aY){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;var aW=a.data(this.elem,"olddisplay");this.elem.style.display=aW?aW:this.options.display;if(a.css(this.elem,"display")==="none"){this.elem.style.display="block"}}if(this.options.hide){a(this.elem).hide()}if(this.options.hide||this.options.show){for(var aU in this.options.curAnim){a.style(this.elem,aU,this.options.orig[aU])}}this.options.complete.call(this.elem)}return false}else{var aV=a2-this.startTime;this.state=aV/this.options.duration;var a0=this.options.specialEasing&&this.options.specialEasing[this.prop];var a1=this.options.easing||(a.easing.swing?"swing":"linear");this.pos=a.easing[a0||a1](this.state,aV,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};a.extend(a.fx,{tick:function(){var aV=a.timers;for(var aU=0;aU<aV.length;aU++){if(!aV[aU]()){aV.splice(aU--,1)}}if(!aV.length){a.fx.stop()}},stop:function(){clearInterval(aB);aB=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(aU){a.style(aU.elem,"opacity",aU.now)},_default:function(aU){if(aU.elem.style&&aU.elem.style[aU.prop]!=null){aU.elem.style[aU.prop]=(aU.prop==="width"||aU.prop==="height"?Math.max(0,aU.now):aU.now)+aU.unit}else{aU.elem[aU.prop]=aU.now}}}});if(a.expr&&a.expr.filters){a.expr.filters.animated=function(aU){return a.grep(a.timers,function(aV){return aU===aV.elem}).length}}function az(aV,aU){var aW={};a.each(ah.concat.apply([],ah.slice(0,aU)),function(){aW[this]=aV});return aW}if("getBoundingClientRect" in aa.documentElement){a.fn.offset=function(a3){var aW=this[0];if(a3){return this.each(function(a4){a.offset.setOffset(this,a3,a4)})}if(!aW||!aW.ownerDocument){return null}if(aW===aW.ownerDocument.body){return a.offset.bodyOffset(aW)}var aY=aW.getBoundingClientRect(),a2=aW.ownerDocument,aZ=a2.body,aU=a2.documentElement,aX=aU.clientTop||aZ.clientTop||0,a0=aU.clientLeft||aZ.clientLeft||0,a1=aY.top+(self.pageYOffset||a.support.boxModel&&aU.scrollTop||aZ.scrollTop)-aX,aV=aY.left+(self.pageXOffset||a.support.boxModel&&aU.scrollLeft||aZ.scrollLeft)-a0;return{top:a1,left:aV}}}else{a.fn.offset=function(a5){var aZ=this[0];if(a5){return this.each(function(a6){a.offset.setOffset(this,a5,a6)})}if(!aZ||!aZ.ownerDocument){return null}if(aZ===aZ.ownerDocument.body){return a.offset.bodyOffset(aZ)}a.offset.initialize();var aW=aZ.offsetParent,aV=aZ,a4=aZ.ownerDocument,a2,aX=a4.documentElement,a0=a4.body,a1=a4.defaultView,aU=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle,a3=aZ.offsetTop,aY=aZ.offsetLeft;while((aZ=aZ.parentNode)&&aZ!==a0&&aZ!==aX){if(a.offset.supportsFixedPosition&&aU.position==="fixed"){break}a2=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle;a3-=aZ.scrollTop;aY-=aZ.scrollLeft;if(aZ===aW){a3+=aZ.offsetTop;aY+=aZ.offsetLeft;if(a.offset.doesNotAddBorder&&!(a.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(aZ.nodeName))){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aV=aW,aW=aZ.offsetParent}if(a.offset.subtractsBorderForOverflowNotVisible&&a2.overflow!=="visible"){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aU=a2}if(aU.position==="relative"||aU.position==="static"){a3+=a0.offsetTop;aY+=a0.offsetLeft}if(a.offset.supportsFixedPosition&&aU.position==="fixed"){a3+=Math.max(aX.scrollTop,a0.scrollTop);aY+=Math.max(aX.scrollLeft,a0.scrollLeft)}return{top:a3,left:aY}}}a.offset={initialize:function(){var aU=aa.body,aV=aa.createElement("div"),aY,a0,aZ,a1,aW=parseFloat(a.curCSS(aU,"marginTop",true))||0,aX="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.extend(aV.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});aV.innerHTML=aX;aU.insertBefore(aV,aU.firstChild);aY=aV.firstChild;a0=aY.firstChild;a1=aY.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(a0.offsetTop!==5);this.doesAddBorderForTableAndCells=(a1.offsetTop===5);a0.style.position="fixed",a0.style.top="20px";this.supportsFixedPosition=(a0.offsetTop===20||a0.offsetTop===15);a0.style.position=a0.style.top="";aY.style.overflow="hidden",aY.style.position="relative";this.subtractsBorderForOverflowNotVisible=(a0.offsetTop===-5);this.doesNotIncludeMarginInBodyOffset=(aU.offsetTop!==aW);aU.removeChild(aV);aU=aV=aY=a0=aZ=a1=null;a.offset.initialize=a.noop},bodyOffset:function(aU){var aW=aU.offsetTop,aV=aU.offsetLeft;a.offset.initialize();if(a.offset.doesNotIncludeMarginInBodyOffset){aW+=parseFloat(a.curCSS(aU,"marginTop",true))||0;aV+=parseFloat(a.curCSS(aU,"marginLeft",true))||0}return{top:aW,left:aV}},setOffset:function(aZ,aV,aW){if(/static/.test(a.curCSS(aZ,"position"))){aZ.style.position="relative"}var aY=a(aZ),a1=aY.offset(),aU=parseInt(a.curCSS(aZ,"top",true),10)||0,a0=parseInt(a.curCSS(aZ,"left",true),10)||0;if(a.isFunction(aV)){aV=aV.call(aZ,aW,a1)}var aX={top:(aV.top-a1.top)+aU,left:(aV.left-a1.left)+a0};if("using" in aV){aV.using.call(aZ,aX)}else{aY.css(aX)}}};a.fn.extend({position:function(){if(!this[0]){return null}var aW=this[0],aV=this.offsetParent(),aX=this.offset(),aU=/^body|html$/i.test(aV[0].nodeName)?{top:0,left:0}:aV.offset();aX.top-=parseFloat(a.curCSS(aW,"marginTop",true))||0;aX.left-=parseFloat(a.curCSS(aW,"marginLeft",true))||0;aU.top+=parseFloat(a.curCSS(aV[0],"borderTopWidth",true))||0;aU.left+=parseFloat(a.curCSS(aV[0],"borderLeftWidth",true))||0;return{top:aX.top-aU.top,left:aX.left-aU.left}},offsetParent:function(){return this.map(function(){var aU=this.offsetParent||aa.body;while(aU&&(!/^body|html$/i.test(aU.nodeName)&&a.css(aU,"position")==="static")){aU=aU.offsetParent}return aU})}});a.each(["Left","Top"],function(aV,aU){var aW="scroll"+aU;a.fn[aW]=function(aZ){var aX=this[0],aY;if(!aX){return null}if(aZ!==B){return this.each(function(){aY=ak(this);if(aY){aY.scrollTo(!aV?aZ:a(aY).scrollLeft(),aV?aZ:a(aY).scrollTop())}else{this[aW]=aZ}})}else{aY=ak(aX);return aY?("pageXOffset" in aY)?aY[aV?"pageYOffset":"pageXOffset"]:a.support.boxModel&&aY.document.documentElement[aW]||aY.document.body[aW]:aX[aW]}}});function ak(aU){return("scrollTo" in aU&&aU.document)?aU:aU.nodeType===9?aU.defaultView||aU.parentWindow:false}a.each(["Height","Width"],function(aV,aU){var aW=aU.toLowerCase();a.fn["inner"+aU]=function(){return this[0]?a.css(this[0],aW,false,"padding"):null};a.fn["outer"+aU]=function(aX){return this[0]?a.css(this[0],aW,false,aX?"margin":"border"):null};a.fn[aW]=function(aX){var aY=this[0];if(!aY){return aX==null?null:this}if(a.isFunction(aX)){return this.each(function(a0){var aZ=a(this);aZ[aW](aX.call(this,a0,aZ[aW]()))})}return("scrollTo" in aY&&aY.document)?aY.document.compatMode==="CSS1Compat"&&aY.document.documentElement["client"+aU]||aY.document.body["client"+aU]:(aY.nodeType===9)?Math.max(aY.documentElement["client"+aU],aY.body["scroll"+aU],aY.documentElement["scroll"+aU],aY.body["offset"+aU],aY.documentElement["offset"+aU]):aX===B?a.css(aY,aW):this.css(aW,typeof aX==="string"?aX:aX+"px")}});aI.jQuery=aI.$=a})(window);window.djdt=(function(b,a,e){e.cookie=function(h,p,s){if(typeof p!="undefined"){s=s||{};if(p===null){p="";s.expires=-1}var l="";if(s.expires&&(typeof s.expires=="number"||s.expires.toUTCString)){var m;if(typeof s.expires=="number"){m=new Date();m.setTime(m.getTime()+(s.expires*24*60*60*1000))}else{m=s.expires}l="; expires="+m.toUTCString()}var r=s.path?"; path="+(s.path):"";var n=s.domain?"; domain="+(s.domain):"";var g=s.secure?"; secure":"";a.cookie=[h,"=",encodeURIComponent(p),l,r,n,g].join("")}else{var k=null;if(a.cookie&&a.cookie!=""){var q=a.cookie.split(";");for(var o=0;o<q.length;o++){var j=c.trim(q[o]);if(j.substring(0,h.length+1)==(h+"=")){k=decodeURIComponent(j.substring(h.length+1));break}}}return k}};var c=e;var f="djdt";var d={jQuery:e,events:{ready:[]},isReady:false,init:function(){c("#djDebug").show();var i=null;c("#djDebugPanelList li a").click(function(){if(!this.className){return false}i=c("#djDebug #"+this.className);if(i.is(":visible")){c(a).trigger("close.djDebug");c(this).parent().removeClass("active")}else{c(".panelContent").hide();i.show();c("#djDebugToolbar li").removeClass("active");c(this).parent().addClass("active")}return false});c("#djDebug a.djDebugClose").click(function(){c(a).trigger("close.djDebug");c("#djDebugToolbar li").removeClass("active");return false});c("#djDebug a.remoteCall").click(function(){c("#djDebugWindow").load(this.href,function(k,j,m){if(j=="error"){var l='<div class="djDebugPanelTitle"><a class="djDebugClose djDebugBack" href="">Back</a><h3>'+m.status+": "+m.statusText+"</h3></div>";c("#djDebugWindow").html(l)}c("#djDebugWindow a.djDebugBack").click(function(){c(this).parent().parent().hide();return false})});c("#djDebugWindow").show();return false});c("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){d.toggle_arrow(c(this).children(".toggleArrow"));d.toggle_content(c(this).parent().next());return false});c("#djDebug a.djToggleSwitch").click(function(l){l.preventDefault();var j=c(this);var m=j.attr("data-toggle-id");var k=j.text()==j.attr("data-toggle-open");if(m==""||!m){return}c(this).parents(".djDebugPanelContent").find(".djToggleDetails_"+m).each(function(){var n=c(this);if(k){n.addClass("djSelected");n.removeClass("djUnselected");j.text(j.attr("data-toggle-close"));n.find(".djToggleSwitch").text(j.text())}else{n.removeClass("djSelected");n.addClass("djUnselected");j.text(j.attr("data-toggle-open"));n.find(".djToggleSwitch").text(j.text())}});return});function g(j){id=j.attr("id");return c('.djDebugProfileRow[id^="'+id+'_"]')}function h(j){subcalls=g(j);depth=parseInt(j.attr("depth"))+1;return subcalls.filter("[depth="+depth+"]")}c(".djDebugProfileRow .djDebugProfileToggle").click(function(){row=c(this).closest(".djDebugProfileRow");subcalls=g(row);if(subcalls.css("display")=="none"){h(row).show()}else{subcalls.hide()}});c("#djHideToolBarButton").click(function(){d.hide_toolbar(true);return false});c("#djShowToolBarButton").click(function(){d.show_toolbar();return false});c(a).bind("close.djDebug",function(){if(c("#djDebugWindow").is(":visible")){c("#djDebugWindow").hide();return}if(c(".panelContent").is(":visible")){c(".panelContent").hide();return}if(c("#djDebugToolbar").is(":visible")){d.hide_toolbar(true);return}});if(c.cookie(f)){d.hide_toolbar(false)}else{d.show_toolbar(false)}c("#djDebug .djDebugHoverable").hover(function(){c(this).addClass("djDebugHover")},function(){c(this).removeClass("djDebugHover")});d.isReady=true;c.each(d.events.ready,function(j,k){k(d)})},toggle_content:function(g){if(g.is(":visible")){g.hide()}else{g.show()}},close:function(){c(a).trigger("close.djDebug");return false},hide_toolbar:function(g){c("#djDebugWindow").hide();c(".panelContent").hide();c("#djDebugToolbar li").removeClass("active");c("#djDebugToolbar").hide("fast");c("#djDebugToolbarHandle").show();c(a).unbind("keydown.djDebug");if(g){c.cookie(f,"hide",{path:"/",expires:10})}},show_toolbar:function(g){c(a).bind("keydown.djDebug",function(h){if(h.keyCode==27){d.close()}});c("#djDebugToolbarHandle").hide();if(g){c("#djDebugToolbar").show("fast")}else{c("#djDebugToolbar").show()}c.cookie(f,null,{path:"/",expires:-1})},toggle_arrow:function(h){var g=String.fromCharCode(9654);var i=String.fromCharCode(9660);h.html(h.html()==g?i:g)},ready:function(g){if(d.isReady){g(d)}else{d.events.ready.push(g)}}};c(a).ready(function(){d.init()});return d}(window,document,jQuery.noConflict())); \ No newline at end of file
+}(function(){var a5=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,a6=0,a8=Object.prototype.toString,a0=false,aZ=true;[0,0].sort(function(){aZ=false;return 0});var aW=function(bh,bc,bk,bl){bk=bk||[];var bn=bc=bc||aa;if(bc.nodeType!==1&&bc.nodeType!==9){return[]}if(!bh||typeof bh!=="string"){return bk}var bi=[],be,bp,bs,bd,bg=true,bf=aX(bc),bm=bh;while((a5.exec(""),be=a5.exec(bm))!==null){bm=be[3];bi.push(be[1]);if(be[2]){bd=be[3];break}}if(bi.length>1&&a1.exec(bh)){if(bi.length===2&&a2.relative[bi[0]]){bp=a9(bi[0]+bi[1],bc)}else{bp=a2.relative[bi[0]]?[bc]:aW(bi.shift(),bc);while(bi.length){bh=bi.shift();if(a2.relative[bh]){bh+=bi.shift()}bp=a9(bh,bp)}}}else{if(!bl&&bi.length>1&&bc.nodeType===9&&!bf&&a2.match.ID.test(bi[0])&&!a2.match.ID.test(bi[bi.length-1])){var bo=aW.find(bi.shift(),bc,bf);bc=bo.expr?aW.filter(bo.expr,bo.set)[0]:bo.set[0]}if(bc){var bo=bl?{expr:bi.pop(),set:a4(bl)}:aW.find(bi.pop(),bi.length===1&&(bi[0]==="~"||bi[0]==="+")&&bc.parentNode?bc.parentNode:bc,bf);bp=bo.expr?aW.filter(bo.expr,bo.set):bo.set;if(bi.length>0){bs=a4(bp)}else{bg=false}while(bi.length){var br=bi.pop(),bq=br;if(!a2.relative[br]){br=""}else{bq=bi.pop()}if(bq==null){bq=bc}a2.relative[br](bs,bq,bf)}}else{bs=bi=[]}}if(!bs){bs=bp}if(!bs){aW.error(br||bh)}if(a8.call(bs)==="[object Array]"){if(!bg){bk.push.apply(bk,bs)}else{if(bc&&bc.nodeType===1){for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&(bs[bj]===true||bs[bj].nodeType===1&&a3(bc,bs[bj]))){bk.push(bp[bj])}}}else{for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&bs[bj].nodeType===1){bk.push(bp[bj])}}}}}else{a4(bs,bk)}if(bd){aW(bd,bn,bk,bl);aW.uniqueSort(bk)}return bk};aW.uniqueSort=function(bd){if(a7){a0=aZ;bd.sort(a7);if(a0){for(var bc=1;bc<bd.length;bc++){if(bd[bc]===bd[bc-1]){bd.splice(bc--,1)}}}}return bd};aW.matches=function(bc,bd){return aW(bc,null,null,bd)};aW.find=function(bj,bc,bk){var bi,bg;if(!bj){return[]}for(var bf=0,be=a2.order.length;bf<be;bf++){var bh=a2.order[bf],bg;if((bg=a2.leftMatch[bh].exec(bj))){var bd=bg[1];bg.splice(1,1);if(bd.substr(bd.length-1)!=="\\"){bg[1]=(bg[1]||"").replace(/\\/g,"");bi=a2.find[bh](bg,bc,bk);if(bi!=null){bj=bj.replace(a2.match[bh],"");break}}}}if(!bi){bi=bc.getElementsByTagName("*")}return{set:bi,expr:bj}};aW.filter=function(bn,bm,bq,bg){var be=bn,bs=[],bk=bm,bi,bc,bj=bm&&bm[0]&&aX(bm[0]);while(bn&&bm.length){for(var bl in a2.filter){if((bi=a2.leftMatch[bl].exec(bn))!=null&&bi[2]){var bd=a2.filter[bl],br,bp,bf=bi[1];bc=false;bi.splice(1,1);if(bf.substr(bf.length-1)==="\\"){continue}if(bk===bs){bs=[]}if(a2.preFilter[bl]){bi=a2.preFilter[bl](bi,bk,bq,bs,bg,bj);if(!bi){bc=br=true}else{if(bi===true){continue}}}if(bi){for(var bh=0;(bp=bk[bh])!=null;bh++){if(bp){br=bd(bp,bi,bh,bk);var bo=bg^!!br;if(bq&&br!=null){if(bo){bc=true}else{bk[bh]=false}}else{if(bo){bs.push(bp);bc=true}}}}}if(br!==B){if(!bq){bk=bs}bn=bn.replace(a2.match[bl],"");if(!bc){return[]}break}}}if(bn===be){if(bc==null){aW.error(bn)}else{break}}be=bn}return bk};aW.error=function(bc){throw"Syntax error, unrecognized expression: "+bc};var a2=aW.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(bc){return bc.getAttribute("href")}},relative:{"+":function(bi,bd){var bf=typeof bd==="string",bh=bf&&!/\W/.test(bd),bj=bf&&!bh;if(bh){bd=bd.toLowerCase()}for(var be=0,bc=bi.length,bg;be<bc;be++){if((bg=bi[be])){while((bg=bg.previousSibling)&&bg.nodeType!==1){}bi[be]=bj||bg&&bg.nodeName.toLowerCase()===bd?bg||false:bg===bd}}if(bj){aW.filter(bd,bi,true)}},">":function(bi,bd){var bg=typeof bd==="string";if(bg&&!/\W/.test(bd)){bd=bd.toLowerCase();for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){var bf=bh.parentNode;bi[be]=bf.nodeName.toLowerCase()===bd?bf:false}}}else{for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){bi[be]=bg?bh.parentNode:bh.parentNode===bd}}if(bg){aW.filter(bd,bi,true)}}},"":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("parentNode",bd,be,bf,bg,bh)},"~":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("previousSibling",bd,be,bf,bg,bh)}},find:{ID:function(bd,be,bf){if(typeof be.getElementById!=="undefined"&&!bf){var bc=be.getElementById(bd[1]);return bc?[bc]:[]}},NAME:function(be,bh){if(typeof bh.getElementsByName!=="undefined"){var bd=[],bg=bh.getElementsByName(be[1]);for(var bf=0,bc=bg.length;bf<bc;bf++){if(bg[bf].getAttribute("name")===be[1]){bd.push(bg[bf])}}return bd.length===0?null:bd}},TAG:function(bc,bd){return bd.getElementsByTagName(bc[1])}},preFilter:{CLASS:function(bf,bd,be,bc,bi,bj){bf=" "+bf[1].replace(/\\/g,"")+" ";if(bj){return bf}for(var bg=0,bh;(bh=bd[bg])!=null;bg++){if(bh){if(bi^(bh.className&&(" "+bh.className+" ").replace(/[\t\n]/g," ").indexOf(bf)>=0)){if(!be){bc.push(bh)}}else{if(be){bd[bg]=false}}}}return false},ID:function(bc){return bc[1].replace(/\\/g,"")},TAG:function(bd,bc){return bd[1].toLowerCase()},CHILD:function(bc){if(bc[1]==="nth"){var bd=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(bc[2]==="even"&&"2n"||bc[2]==="odd"&&"2n+1"||!/\D/.test(bc[2])&&"0n+"+bc[2]||bc[2]);bc[2]=(bd[1]+(bd[2]||1))-0;bc[3]=bd[3]-0}bc[0]=a6++;return bc},ATTR:function(bg,bd,be,bc,bh,bi){var bf=bg[1].replace(/\\/g,"");if(!bi&&a2.attrMap[bf]){bg[1]=a2.attrMap[bf]}if(bg[2]==="~="){bg[4]=" "+bg[4]+" "}return bg},PSEUDO:function(bg,bd,be,bc,bh){if(bg[1]==="not"){if((a5.exec(bg[3])||"").length>1||/^\w/.test(bg[3])){bg[3]=aW(bg[3],null,null,bd)}else{var bf=aW.filter(bg[3],bd,be,true^bh);if(!be){bc.push.apply(bc,bf)}return false}}else{if(a2.match.POS.test(bg[0])||a2.match.CHILD.test(bg[0])){return true}}return bg},POS:function(bc){bc.unshift(true);return bc}},filters:{enabled:function(bc){return bc.disabled===false&&bc.type!=="hidden"},disabled:function(bc){return bc.disabled===true},checked:function(bc){return bc.checked===true},selected:function(bc){bc.parentNode.selectedIndex;return bc.selected===true},parent:function(bc){return !!bc.firstChild},empty:function(bc){return !bc.firstChild},has:function(be,bd,bc){return !!aW(bc[3],be).length},header:function(bc){return/h\d/i.test(bc.nodeName)},text:function(bc){return"text"===bc.type},radio:function(bc){return"radio"===bc.type},checkbox:function(bc){return"checkbox"===bc.type},file:function(bc){return"file"===bc.type},password:function(bc){return"password"===bc.type},submit:function(bc){return"submit"===bc.type},image:function(bc){return"image"===bc.type},reset:function(bc){return"reset"===bc.type},button:function(bc){return"button"===bc.type||bc.nodeName.toLowerCase()==="button"},input:function(bc){return/input|select|textarea|button/i.test(bc.nodeName)}},setFilters:{first:function(bd,bc){return bc===0},last:function(be,bd,bc,bf){return bd===bf.length-1},even:function(bd,bc){return bc%2===0},odd:function(bd,bc){return bc%2===1},lt:function(be,bd,bc){return bd<bc[3]-0},gt:function(be,bd,bc){return bd>bc[3]-0},nth:function(be,bd,bc){return bc[3]-0===bd},eq:function(be,bd,bc){return bc[3]-0===bd}},filter:{PSEUDO:function(bi,be,bf,bj){var bd=be[1],bg=a2.filters[bd];if(bg){return bg(bi,bf,be,bj)}else{if(bd==="contains"){return(bi.textContent||bi.innerText||aV([bi])||"").indexOf(be[3])>=0}else{if(bd==="not"){var bh=be[3];for(var bf=0,bc=bh.length;bf<bc;bf++){if(bh[bf]===bi){return false}}return true}else{aW.error("Syntax error, unrecognized expression: "+bd)}}}},CHILD:function(bc,bf){var bi=bf[1],bd=bc;switch(bi){case"only":case"first":while((bd=bd.previousSibling)){if(bd.nodeType===1){return false}}if(bi==="first"){return true}bd=bc;case"last":while((bd=bd.nextSibling)){if(bd.nodeType===1){return false}}return true;case"nth":var be=bf[2],bl=bf[3];if(be===1&&bl===0){return true}var bh=bf[0],bk=bc.parentNode;if(bk&&(bk.sizcache!==bh||!bc.nodeIndex)){var bg=0;for(bd=bk.firstChild;bd;bd=bd.nextSibling){if(bd.nodeType===1){bd.nodeIndex=++bg}}bk.sizcache=bh}var bj=bc.nodeIndex-bl;if(be===0){return bj===0}else{return(bj%be===0&&bj/be>=0)}}},ID:function(bd,bc){return bd.nodeType===1&&bd.getAttribute("id")===bc},TAG:function(bd,bc){return(bc==="*"&&bd.nodeType===1)||bd.nodeName.toLowerCase()===bc},CLASS:function(bd,bc){return(" "+(bd.className||bd.getAttribute("class"))+" ").indexOf(bc)>-1},ATTR:function(bh,bf){var be=bf[1],bc=a2.attrHandle[be]?a2.attrHandle[be](bh):bh[be]!=null?bh[be]:bh.getAttribute(be),bi=bc+"",bg=bf[2],bd=bf[4];return bc==null?bg==="!=":bg==="="?bi===bd:bg==="*="?bi.indexOf(bd)>=0:bg==="~="?(" "+bi+" ").indexOf(bd)>=0:!bd?bi&&bc!==false:bg==="!="?bi!==bd:bg==="^="?bi.indexOf(bd)===0:bg==="$="?bi.substr(bi.length-bd.length)===bd:bg==="|="?bi===bd||bi.substr(0,bd.length+1)===bd+"-":false},POS:function(bg,bd,be,bh){var bc=bd[2],bf=a2.setFilters[bc];if(bf){return bf(bg,be,bd,bh)}}}};var a1=a2.match.POS;for(var aY in a2.match){a2.match[aY]=new RegExp(a2.match[aY].source+/(?![^\[]*\])(?![^\(]*\))/.source);a2.leftMatch[aY]=new RegExp(/(^(?:.|\r|\n)*?)/.source+a2.match[aY].source.replace(/\\(\d+)/g,function(bd,bc){return"\\"+(bc-0+1)}))}var a4=function(bd,bc){bd=Array.prototype.slice.call(bd,0);if(bc){bc.push.apply(bc,bd);return bc}return bd};try{Array.prototype.slice.call(aa.documentElement.childNodes,0)}catch(bb){a4=function(bg,bf){var bd=bf||[];if(a8.call(bg)==="[object Array]"){Array.prototype.push.apply(bd,bg)}else{if(typeof bg.length==="number"){for(var be=0,bc=bg.length;be<bc;be++){bd.push(bg[be])}}else{for(var be=0;bg[be];be++){bd.push(bg[be])}}}return bd}}var a7;if(aa.documentElement.compareDocumentPosition){a7=function(bd,bc){if(!bd.compareDocumentPosition||!bc.compareDocumentPosition){if(bd==bc){a0=true}return bd.compareDocumentPosition?-1:1}var be=bd.compareDocumentPosition(bc)&4?-1:bd===bc?0:1;if(be===0){a0=true}return be}}else{if("sourceIndex" in aa.documentElement){a7=function(bd,bc){if(!bd.sourceIndex||!bc.sourceIndex){if(bd==bc){a0=true}return bd.sourceIndex?-1:1}var be=bd.sourceIndex-bc.sourceIndex;if(be===0){a0=true}return be}}else{if(aa.createRange){a7=function(bf,bd){if(!bf.ownerDocument||!bd.ownerDocument){if(bf==bd){a0=true}return bf.ownerDocument?-1:1}var be=bf.ownerDocument.createRange(),bc=bd.ownerDocument.createRange();be.setStart(bf,0);be.setEnd(bf,0);bc.setStart(bd,0);bc.setEnd(bd,0);var bg=be.compareBoundaryPoints(Range.START_TO_END,bc);if(bg===0){a0=true}return bg}}}}function aV(bc){var bd="",bf;for(var be=0;bc[be];be++){bf=bc[be];if(bf.nodeType===3||bf.nodeType===4){bd+=bf.nodeValue}else{if(bf.nodeType!==8){bd+=aV(bf.childNodes)}}}return bd}(function(){var bd=aa.createElement("div"),be="script"+(new Date).getTime();bd.innerHTML="<a name='"+be+"'/>";var bc=aa.documentElement;bc.insertBefore(bd,bc.firstChild);if(aa.getElementById(be)){a2.find.ID=function(bg,bh,bi){if(typeof bh.getElementById!=="undefined"&&!bi){var bf=bh.getElementById(bg[1]);return bf?bf.id===bg[1]||typeof bf.getAttributeNode!=="undefined"&&bf.getAttributeNode("id").nodeValue===bg[1]?[bf]:B:[]}};a2.filter.ID=function(bh,bf){var bg=typeof bh.getAttributeNode!=="undefined"&&bh.getAttributeNode("id");return bh.nodeType===1&&bg&&bg.nodeValue===bf}}bc.removeChild(bd);bc=bd=null})();(function(){var bc=aa.createElement("div");bc.appendChild(aa.createComment(""));if(bc.getElementsByTagName("*").length>0){a2.find.TAG=function(bd,bh){var bg=bh.getElementsByTagName(bd[1]);if(bd[1]==="*"){var bf=[];for(var be=0;bg[be];be++){if(bg[be].nodeType===1){bf.push(bg[be])}}bg=bf}return bg}}bc.innerHTML="<a href='#'></a>";if(bc.firstChild&&typeof bc.firstChild.getAttribute!=="undefined"&&bc.firstChild.getAttribute("href")!=="#"){a2.attrHandle.href=function(bd){return bd.getAttribute("href",2)}}bc=null})();if(aa.querySelectorAll){(function(){var bc=aW,be=aa.createElement("div");be.innerHTML="<p class='TEST'></p>";if(be.querySelectorAll&&be.querySelectorAll(".TEST").length===0){return}aW=function(bi,bh,bf,bg){bh=bh||aa;if(!bg&&bh.nodeType===9&&!aX(bh)){try{return a4(bh.querySelectorAll(bi),bf)}catch(bj){}}return bc(bi,bh,bf,bg)};for(var bd in bc){aW[bd]=bc[bd]}be=null})()}(function(){var bc=aa.createElement("div");bc.innerHTML="<div class='test e'></div><div class='test'></div>";if(!bc.getElementsByClassName||bc.getElementsByClassName("e").length===0){return}bc.lastChild.className="e";if(bc.getElementsByClassName("e").length===1){return}a2.order.splice(1,0,"CLASS");a2.find.CLASS=function(bd,be,bf){if(typeof be.getElementsByClassName!=="undefined"&&!bf){return be.getElementsByClassName(bd[1])}};bc=null})();function aU(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1&&!bk){bc.sizcache=bh;bc.sizset=bf}if(bc.nodeName.toLowerCase()===bi){bg=bc;break}bc=bc[bd]}bl[bf]=bg}}}function ba(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1){if(!bk){bc.sizcache=bh;bc.sizset=bf}if(typeof bi!=="string"){if(bc===bi){bg=true;break}}else{if(aW.filter(bi,[bc]).length>0){bg=bc;break}}}bc=bc[bd]}bl[bf]=bg}}}var a3=aa.compareDocumentPosition?function(bd,bc){return bd.compareDocumentPosition(bc)&16}:function(bd,bc){return bd!==bc&&(bd.contains?bd.contains(bc):true)};var aX=function(bc){var bd=(bc?bc.ownerDocument||bc:0).documentElement;return bd?bd.nodeName!=="HTML":false};var a9=function(bc,bj){var bf=[],bg="",bh,be=bj.nodeType?[bj]:bj;while((bh=a2.match.PSEUDO.exec(bc))){bg+=bh[0];bc=bc.replace(a2.match.PSEUDO,"")}bc=a2.relative[bc]?bc+"*":bc;for(var bi=0,bd=be.length;bi<bd;bi++){aW(bc,be[bi],bf)}return aW.filter(bg,bf)};a.find=aW;a.expr=aW.selectors;a.expr[":"]=a.expr.filters;a.unique=aW.uniqueSort;a.getText=aV;a.isXMLDoc=aX;a.contains=a3;return;aI.Sizzle=aW})();var M=/Until$/,X=/^(?:parents|prevUntil|prevAll)/,aH=/,/,D=Array.prototype.slice;var ag=function(aX,aW,aU){if(a.isFunction(aW)){return a.grep(aX,function(aZ,aY){return !!aW.call(aZ,aY,aZ)===aU})}else{if(aW.nodeType){return a.grep(aX,function(aZ,aY){return(aZ===aW)===aU})}else{if(typeof aW==="string"){var aV=a.grep(aX,function(aY){return aY.nodeType===1});if(aS.test(aW)){return a.filter(aW,aV,!aU)}else{aW=a.filter(aW,aV)}}}}return a.grep(aX,function(aZ,aY){return(a.inArray(aZ,aW)>=0)===aU})};a.fn.extend({find:function(aU){var aW=this.pushStack("","find",aU),aZ=0;for(var aX=0,aV=this.length;aX<aV;aX++){aZ=aW.length;a.find(aU,this[aX],aW);if(aX>0){for(var a0=aZ;a0<aW.length;a0++){for(var aY=0;aY<aZ;aY++){if(aW[aY]===aW[a0]){aW.splice(a0--,1);break}}}}}return aW},has:function(aV){var aU=a(aV);return this.filter(function(){for(var aX=0,aW=aU.length;aX<aW;aX++){if(a.contains(this,aU[aX])){return true}}})},not:function(aU){return this.pushStack(ag(this,aU,false),"not",aU)},filter:function(aU){return this.pushStack(ag(this,aU,true),"filter",aU)},is:function(aU){return !!aU&&a.filter(aU,this).length>0},closest:function(a3,aU){if(a.isArray(a3)){var a0=[],a2=this[0],aZ,aY={},aW;if(a2&&a3.length){for(var aX=0,aV=a3.length;aX<aV;aX++){aW=a3[aX];if(!aY[aW]){aY[aW]=a.expr.match.POS.test(aW)?a(aW,aU||this.context):aW}}while(a2&&a2.ownerDocument&&a2!==aU){for(aW in aY){aZ=aY[aW];if(aZ.jquery?aZ.index(a2)>-1:a(a2).is(aZ)){a0.push({selector:aW,elem:a2});delete aY[aW]}}a2=a2.parentNode}}return a0}var a1=a.expr.match.POS.test(a3)?a(a3,aU||this.context):null;return this.map(function(a4,a5){while(a5&&a5.ownerDocument&&a5!==aU){if(a1?a1.index(a5)>-1:a(a5).is(a3)){return a5}a5=a5.parentNode}return null})},index:function(aU){if(!aU||typeof aU==="string"){return a.inArray(this[0],aU?a(aU):this.parent().children())}return a.inArray(aU.jquery?aU[0]:aU,this)},add:function(aU,aV){var aX=typeof aU==="string"?a(aU,aV||this.context):a.makeArray(aU),aW=a.merge(this.get(),aX);return this.pushStack(x(aX[0])||x(aW[0])?aW:a.unique(aW))},andSelf:function(){return this.add(this.prevObject)}});function x(aU){return !aU||!aU.parentNode||aU.parentNode.nodeType===11}a.each({parent:function(aV){var aU=aV.parentNode;return aU&&aU.nodeType!==11?aU:null},parents:function(aU){return a.dir(aU,"parentNode")},parentsUntil:function(aV,aU,aW){return a.dir(aV,"parentNode",aW)},next:function(aU){return a.nth(aU,2,"nextSibling")},prev:function(aU){return a.nth(aU,2,"previousSibling")},nextAll:function(aU){return a.dir(aU,"nextSibling")},prevAll:function(aU){return a.dir(aU,"previousSibling")},nextUntil:function(aV,aU,aW){return a.dir(aV,"nextSibling",aW)},prevUntil:function(aV,aU,aW){return a.dir(aV,"previousSibling",aW)},siblings:function(aU){return a.sibling(aU.parentNode.firstChild,aU)},children:function(aU){return a.sibling(aU.firstChild)},contents:function(aU){return a.nodeName(aU,"iframe")?aU.contentDocument||aU.contentWindow.document:a.makeArray(aU.childNodes)}},function(aU,aV){a.fn[aU]=function(aY,aW){var aX=a.map(this,aV,aY);if(!M.test(aU)){aW=aY}if(aW&&typeof aW==="string"){aX=a.filter(aW,aX)}aX=this.length>1?a.unique(aX):aX;if((this.length>1||aH.test(aW))&&X.test(aU)){aX=aX.reverse()}return this.pushStack(aX,aU,D.call(arguments).join(","))}});a.extend({filter:function(aW,aU,aV){if(aV){aW=":not("+aW+")"}return a.find.matches(aW,aU)},dir:function(aW,aV,aY){var aU=[],aX=aW[aV];while(aX&&aX.nodeType!==9&&(aY===B||aX.nodeType!==1||!a(aX).is(aY))){if(aX.nodeType===1){aU.push(aX)}aX=aX[aV]}return aU},nth:function(aY,aU,aW,aX){aU=aU||1;var aV=0;for(;aY;aY=aY[aW]){if(aY.nodeType===1&&++aV===aU){break}}return aY},sibling:function(aW,aV){var aU=[];for(;aW;aW=aW.nextSibling){if(aW.nodeType===1&&aW!==aV){aU.push(aW)}}return aU}});var S=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,F=/(<([\w:]+)[^>]*?)\/>/g,aj=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,c=/<([\w:]+)/,t=/<tbody/i,J=/<|&\w+;/,l=/checked\s*(?:[^=]|=\s*.checked.)/i,p=function(aV,aW,aU){return aj.test(aU)?aV:aW+"></"+aU+">"},ab={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};ab.optgroup=ab.option;ab.tbody=ab.tfoot=ab.colgroup=ab.caption=ab.thead;ab.th=ab.td;if(!a.support.htmlSerialize){ab._default=[1,"div<div>","</div>"]}a.fn.extend({text:function(aU){if(a.isFunction(aU)){return this.each(function(aW){var aV=a(this);aV.text(aU.call(this,aW,aV.text()))})}if(typeof aU!=="object"&&aU!==B){return this.empty().append((this[0]&&this[0].ownerDocument||aa).createTextNode(aU))}return a.getText(this)},wrapAll:function(aU){if(a.isFunction(aU)){return this.each(function(aW){a(this).wrapAll(aU.call(this,aW))})}if(this[0]){var aV=a(aU,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){aV.insertBefore(this[0])}aV.map(function(){var aW=this;while(aW.firstChild&&aW.firstChild.nodeType===1){aW=aW.firstChild}return aW}).append(this)}return this},wrapInner:function(aU){if(a.isFunction(aU)){return this.each(function(aV){a(this).wrapInner(aU.call(this,aV))})}return this.each(function(){var aV=a(this),aW=aV.contents();if(aW.length){aW.wrapAll(aU)}else{aV.append(aU)}})},wrap:function(aU){return this.each(function(){a(this).wrapAll(aU)})},unwrap:function(){return this.parent().each(function(){if(!a.nodeName(this,"body")){a(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.appendChild(aU)}})},prepend:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.insertBefore(aU,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this)})}else{if(arguments.length){var aU=a(arguments[0]);aU.push.apply(aU,this.toArray());return this.pushStack(aU,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this.nextSibling)})}else{if(arguments.length){var aU=this.pushStack(this,"after",arguments);aU.push.apply(aU,a(arguments[0]).toArray());return aU}}},clone:function(aV){var aU=this.map(function(){if(!a.support.noCloneEvent&&!a.isXMLDoc(this)){var aX=this.outerHTML,aW=this.ownerDocument;if(!aX){var aY=aW.createElement("div");aY.appendChild(this.cloneNode(true));aX=aY.innerHTML}return a.clean([aX.replace(S,"").replace(Y,"")],aW)[0]}else{return this.cloneNode(true)}});if(aV===true){q(this,aU);q(this.find("*"),aU.find("*"))}return aU},html:function(aW){if(aW===B){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(S,""):null}else{if(typeof aW==="string"&&!/<script/i.test(aW)&&(a.support.leadingWhitespace||!Y.test(aW))&&!ab[(c.exec(aW)||["",""])[1].toLowerCase()]){aW=aW.replace(F,p);try{for(var aV=0,aU=this.length;aV<aU;aV++){if(this[aV].nodeType===1){a.cleanData(this[aV].getElementsByTagName("*"));this[aV].innerHTML=aW}}}catch(aX){this.empty().append(aW)}}else{if(a.isFunction(aW)){this.each(function(a0){var aZ=a(this),aY=aZ.html();aZ.empty().append(function(){return aW.call(this,a0,aY)})})}else{this.empty().append(aW)}}}return this},replaceWith:function(aU){if(this[0]&&this[0].parentNode){if(!a.isFunction(aU)){aU=a(aU).detach()}else{return this.each(function(aX){var aW=a(this),aV=aW.html();aW.replaceWith(aU.call(this,aX,aV))})}return this.each(function(){var aW=this.nextSibling,aV=this.parentNode;a(this).remove();if(aW){a(aW).before(aU)}else{a(aV).append(aU)}})}else{return this.pushStack(a(a.isFunction(aU)?aU():aU),"replaceWith",aU)}},detach:function(aU){return this.remove(aU,true)},domManip:function(aZ,a3,a2){var aW,aY,a1=aZ[0],aV=[];if(!a.support.checkClone&&arguments.length===3&&typeof a1==="string"&&l.test(a1)){return this.each(function(){a(this).domManip(aZ,a3,a2,true)})}if(a.isFunction(a1)){return this.each(function(a5){var a4=a(this);aZ[0]=a1.call(this,a5,a3?a4.html():B);a4.domManip(aZ,a3,a2)})}if(this[0]){if(aZ[0]&&aZ[0].parentNode&&aZ[0].parentNode.nodeType===11){aW={fragment:aZ[0].parentNode}}else{aW=H(aZ,this,aV)}aY=aW.fragment.firstChild;if(aY){a3=a3&&a.nodeName(aY,"tr");for(var aX=0,aU=this.length;aX<aU;aX++){a2.call(a3?a0(this[aX],aY):this[aX],aW.cacheable||this.length>1||aX>0?aW.fragment.cloneNode(true):aW.fragment)}}if(aV){a.each(aV,aR)}}return this;function a0(a4,a5){return a.nodeName(a4,"table")?(a4.getElementsByTagName("tbody")[0]||a4.appendChild(a4.ownerDocument.createElement("tbody"))):a4}}});function q(aW,aU){var aV=0;aU.each(function(){if(this.nodeName!==(aW[aV]&&aW[aV].nodeName)){return}var a1=a.data(aW[aV++]),a0=a.data(this,a1),aX=a1&&a1.events;if(aX){delete a0.handle;a0.events={};for(var aZ in aX){for(var aY in aX[aZ]){a.event.add(this,aZ,aX[aZ][aY],aX[aZ][aY].data)}}}})}function H(aZ,aX,aV){var aY,aU,aW,a0;if(aZ.length===1&&typeof aZ[0]==="string"&&aZ[0].length<512&&aZ[0].indexOf("<option")<0&&(a.support.checkClone||!l.test(aZ[0]))){aU=true;aW=a.fragments[aZ[0]];if(aW){if(aW!==1){aY=aW}}}if(!aY){a0=(aX&&aX[0]?aX[0].ownerDocument||aX[0]:aa);aY=a0.createDocumentFragment();a.clean(aZ,a0,aY,aV)}if(aU){a.fragments[aZ[0]]=aW?aY:1}return{fragment:aY,cacheable:aU}}a.fragments={};a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(aU,aV){a.fn[aU]=function(aW){var aZ=[],a1=a(aW);for(var a0=0,aX=a1.length;a0<aX;a0++){var aY=(a0>0?this.clone(true):this).get();a.fn[aV].apply(a(a1[a0]),aY);aZ=aZ.concat(aY)}return this.pushStack(aZ,aU,a1.selector)}});a.each({remove:function(aU,aV){if(!aU||a.filter(aU,[this]).length){if(!aV&&this.nodeType===1){a.cleanData(this.getElementsByTagName("*"));a.cleanData([this])}if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){if(this.nodeType===1){a.cleanData(this.getElementsByTagName("*"))}while(this.firstChild){this.removeChild(this.firstChild)}}},function(aU,aV){a.fn[aU]=function(){return this.each(aV,arguments)}});a.extend({clean:function(aV,aZ,aX,aU){aZ=aZ||aa;if(typeof aZ.createElement==="undefined"){aZ=aZ.ownerDocument||aZ[0]&&aZ[0].ownerDocument||aa}var aW=[];a.each(aV,function(a6,a3){if(typeof a3==="number"){a3+=""}if(!a3){return}if(typeof a3==="string"&&!J.test(a3)){a3=aZ.createTextNode(a3)}else{if(typeof a3==="string"){a3=a3.replace(F,p);var a8=(c.exec(a3)||["",""])[1].toLowerCase(),a2=ab[a8]||ab._default,a5=a2[0],a0=aZ.createElement("div");a0.innerHTML=a2[1]+a3+a2[2];while(a5--){a0=a0.lastChild}if(!a.support.tbody){var a1=t.test(a3),a7=a8==="table"&&!a1?a0.firstChild&&a0.firstChild.childNodes:a2[1]==="<table>"&&!a1?a0.childNodes:[];for(var a4=a7.length-1;a4>=0;--a4){if(a.nodeName(a7[a4],"tbody")&&!a7[a4].childNodes.length){a7[a4].parentNode.removeChild(a7[a4])}}}if(!a.support.leadingWhitespace&&Y.test(a3)){a0.insertBefore(aZ.createTextNode(Y.exec(a3)[0]),a0.firstChild)}a3=a.makeArray(a0.childNodes)}}if(a3.nodeType){aW.push(a3)}else{aW=a.merge(aW,a3)}});if(aX){for(var aY=0;aW[aY];aY++){if(aU&&a.nodeName(aW[aY],"script")&&(!aW[aY].type||aW[aY].type.toLowerCase()==="text/javascript")){aU.push(aW[aY].parentNode?aW[aY].parentNode.removeChild(aW[aY]):aW[aY])}else{if(aW[aY].nodeType===1){aW.splice.apply(aW,[aY+1,0].concat(a.makeArray(aW[aY].getElementsByTagName("script"))))}aX.appendChild(aW[aY])}}}return aW},cleanData:function(aU){for(var aV=0,aW,aX;(aW=aU[aV])!=null;aV++){a.event.remove(aW);a.removeData(aW)}}});var ap=/z-?index|font-?weight|opacity|zoom|line-?height/i,T=/alpha\([^)]*\)/,Z=/opacity=([^)]*)/,af=/float/i,aw=/-([a-z])/ig,v=/([A-Z])/g,aK=/^-?\d+(?:px)?$/i,aQ=/^-?\d/,aG={position:"absolute",visibility:"hidden",display:"block"},V=["Left","Right"],aA=["Top","Bottom"],ai=aa.defaultView&&aa.defaultView.getComputedStyle,aJ=a.support.cssFloat?"cssFloat":"styleFloat",k=function(aU,aV){return aV.toUpperCase()};a.fn.css=function(aU,aV){return al(this,aU,aV,true,function(aX,aW,aY){if(aY===B){return a.curCSS(aX,aW)}if(typeof aY==="number"&&!ap.test(aW)){aY+="px"}a.style(aX,aW,aY)})};a.extend({style:function(aY,aV,aZ){if(!aY||aY.nodeType===3||aY.nodeType===8){return B}if((aV==="width"||aV==="height")&&parseFloat(aZ)<0){aZ=B}var aX=aY.style||aY,a0=aZ!==B;if(!a.support.opacity&&aV==="opacity"){if(a0){aX.zoom=1;var aU=parseInt(aZ,10)+""==="NaN"?"":"alpha(opacity="+aZ*100+")";var aW=aX.filter||a.curCSS(aY,"filter")||"";aX.filter=T.test(aW)?aW.replace(T,aU):aU}return aX.filter&&aX.filter.indexOf("opacity=")>=0?(parseFloat(Z.exec(aX.filter)[1])/100)+"":""}if(af.test(aV)){aV=aJ}aV=aV.replace(aw,k);if(a0){aX[aV]=aZ}return aX[aV]},css:function(aX,aV,aZ,aU){if(aV==="width"||aV==="height"){var a1,aW=aG,a0=aV==="width"?V:aA;function aY(){a1=aV==="width"?aX.offsetWidth:aX.offsetHeight;if(aU==="border"){return}a.each(a0,function(){if(!aU){a1-=parseFloat(a.curCSS(aX,"padding"+this,true))||0}if(aU==="margin"){a1+=parseFloat(a.curCSS(aX,"margin"+this,true))||0}else{a1-=parseFloat(a.curCSS(aX,"border"+this+"Width",true))||0}})}if(aX.offsetWidth!==0){aY()}else{a.swap(aX,aW,aY)}return Math.max(0,Math.round(a1))}return a.curCSS(aX,aV,aZ)},curCSS:function(a0,aV,aW){var a3,aU=a0.style,aX;if(!a.support.opacity&&aV==="opacity"&&a0.currentStyle){a3=Z.test(a0.currentStyle.filter||"")?(parseFloat(RegExp.$1)/100)+"":"";return a3===""?"1":a3}if(af.test(aV)){aV=aJ}if(!aW&&aU&&aU[aV]){a3=aU[aV]}else{if(ai){if(af.test(aV)){aV="float"}aV=aV.replace(v,"-$1").toLowerCase();var a2=a0.ownerDocument.defaultView;if(!a2){return null}var a4=a2.getComputedStyle(a0,null);if(a4){a3=a4.getPropertyValue(aV)}if(aV==="opacity"&&a3===""){a3="1"}}else{if(a0.currentStyle){var aZ=aV.replace(aw,k);a3=a0.currentStyle[aV]||a0.currentStyle[aZ];if(!aK.test(a3)&&aQ.test(a3)){var aY=aU.left,a1=a0.runtimeStyle.left;a0.runtimeStyle.left=a0.currentStyle.left;aU.left=aZ==="fontSize"?"1em":(a3||0);a3=aU.pixelLeft+"px";aU.left=aY;a0.runtimeStyle.left=a1}}}}return a3},swap:function(aX,aW,aY){var aU={};for(var aV in aW){aU[aV]=aX.style[aV];aX.style[aV]=aW[aV]}aY.call(aX);for(var aV in aW){aX.style[aV]=aU[aV]}}});if(a.expr&&a.expr.filters){a.expr.filters.hidden=function(aX){var aV=aX.offsetWidth,aU=aX.offsetHeight,aW=aX.nodeName.toLowerCase()==="tr";return aV===0&&aU===0&&!aW?true:aV>0&&aU>0&&!aW?false:a.curCSS(aX,"display")==="none"};a.expr.filters.visible=function(aU){return !a.expr.filters.hidden(aU)}}var ae=aL(),aF=/<script(.|\s)*?\/script>/gi,o=/select|textarea/i,ay=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,r=/=\?(&|$)/,C=/\?/,aT=/(\?|&)_=.*?(&|$)/,A=/^(\w+:)?\/\/([^\/?#]+)/,h=/%20/g;a.fn.extend({_load:a.fn.load,load:function(aW,aZ,a0){if(typeof aW!=="string"){return this._load(aW)}else{if(!this.length){return this}}var aY=aW.indexOf(" ");if(aY>=0){var aU=aW.slice(aY,aW.length);aW=aW.slice(0,aY)}var aX="GET";if(aZ){if(a.isFunction(aZ)){a0=aZ;aZ=null}else{if(typeof aZ==="object"){aZ=a.param(aZ,a.ajaxSettings.traditional);aX="POST"}}}var aV=this;a.ajax({url:aW,type:aX,dataType:"html",data:aZ,complete:function(a2,a1){if(a1==="success"||a1==="notmodified"){aV.html(aU?a("<div />").append(a2.responseText.replace(aF,"")).find(aU):a2.responseText)}if(a0){aV.each(a0,[a2.responseText,a1,a2])}}});return this},serialize:function(){return a.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?a.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||o.test(this.nodeName)||ay.test(this.type))}).map(function(aU,aV){var aW=a(this).val();return aW==null?null:a.isArray(aW)?a.map(aW,function(aY,aX){return{name:aV.name,value:aY}}):{name:aV.name,value:aW}}).get()}});a.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(aU,aV){a.fn[aV]=function(aW){return this.bind(aV,aW)}});a.extend({get:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW=null}return a.ajax({type:"GET",url:aU,data:aW,success:aX,dataType:aV})},getScript:function(aU,aV){return a.get(aU,null,aV,"script")},getJSON:function(aU,aV,aW){return a.get(aU,aV,aW,"json")},post:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW={}}return a.ajax({type:"POST",url:aU,data:aW,success:aX,dataType:aV})},ajaxSetup:function(aU){a.extend(a.ajaxSettings,aU)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:aI.XMLHttpRequest&&(aI.location.protocol!=="file:"||!aI.ActiveXObject)?function(){return new aI.XMLHttpRequest()}:function(){try{return new aI.ActiveXObject("Microsoft.XMLHTTP")}catch(aU){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a9){var a4=a.extend(true,{},a.ajaxSettings,a9);var be,a8,bd,bf=a9&&a9.context||a4,aW=a4.type.toUpperCase();if(a4.data&&a4.processData&&typeof a4.data!=="string"){a4.data=a.param(a4.data,a4.traditional)}if(a4.dataType==="jsonp"){if(aW==="GET"){if(!r.test(a4.url)){a4.url+=(C.test(a4.url)?"&":"?")+(a4.jsonp||"callback")+"=?"}}else{if(!a4.data||!r.test(a4.data)){a4.data=(a4.data?a4.data+"&":"")+(a4.jsonp||"callback")+"=?"}}a4.dataType="json"}if(a4.dataType==="json"&&(a4.data&&r.test(a4.data)||r.test(a4.url))){be=a4.jsonpCallback||("jsonp"+ae++);if(a4.data){a4.data=(a4.data+"").replace(r,"="+be+"$1")}a4.url=a4.url.replace(r,"="+be+"$1");a4.dataType="script";aI[be]=aI[be]||function(bg){bd=bg;aZ();a2();aI[be]=B;try{delete aI[be]}catch(bh){}if(aX){aX.removeChild(bb)}}}if(a4.dataType==="script"&&a4.cache===null){a4.cache=false}if(a4.cache===false&&aW==="GET"){var aU=aL();var bc=a4.url.replace(aT,"$1_="+aU+"$2");a4.url=bc+((bc===a4.url)?(C.test(a4.url)?"&":"?")+"_="+aU:"")}if(a4.data&&aW==="GET"){a4.url+=(C.test(a4.url)?"&":"?")+a4.data}if(a4.global&&!a.active++){a.event.trigger("ajaxStart")}var a7=A.exec(a4.url),aY=a7&&(a7[1]&&a7[1]!==location.protocol||a7[2]!==location.host);if(a4.dataType==="script"&&aW==="GET"&&aY){var aX=aa.getElementsByTagName("head")[0]||aa.documentElement;var bb=aa.createElement("script");bb.src=a4.url;if(a4.scriptCharset){bb.charset=a4.scriptCharset}if(!be){var a6=false;bb.onload=bb.onreadystatechange=function(){if(!a6&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){a6=true;aZ();a2();bb.onload=bb.onreadystatechange=null;if(aX&&bb.parentNode){aX.removeChild(bb)}}}}aX.insertBefore(bb,aX.firstChild);return B}var a1=false;var a0=a4.xhr();if(!a0){return}if(a4.username){a0.open(aW,a4.url,a4.async,a4.username,a4.password)}else{a0.open(aW,a4.url,a4.async)}try{if(a4.data||a9&&a9.contentType){a0.setRequestHeader("Content-Type",a4.contentType)}if(a4.ifModified){if(a.lastModified[a4.url]){a0.setRequestHeader("If-Modified-Since",a.lastModified[a4.url])}if(a.etag[a4.url]){a0.setRequestHeader("If-None-Match",a.etag[a4.url])}}if(!aY){a0.setRequestHeader("X-Requested-With","XMLHttpRequest")}a0.setRequestHeader("Accept",a4.dataType&&a4.accepts[a4.dataType]?a4.accepts[a4.dataType]+", */*":a4.accepts._default)}catch(ba){}if(a4.beforeSend&&a4.beforeSend.call(bf,a0,a4)===false){if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}a0.abort();return false}if(a4.global){a5("ajaxSend",[a0,a4])}var a3=a0.onreadystatechange=function(bg){if(!a0||a0.readyState===0||bg==="abort"){if(!a1){a2()}a1=true;if(a0){a0.onreadystatechange=a.noop}}else{if(!a1&&a0&&(a0.readyState===4||bg==="timeout")){a1=true;a0.onreadystatechange=a.noop;a8=bg==="timeout"?"timeout":!a.httpSuccess(a0)?"error":a4.ifModified&&a.httpNotModified(a0,a4.url)?"notmodified":"success";var bi;if(a8==="success"){try{bd=a.httpData(a0,a4.dataType,a4)}catch(bh){a8="parsererror";bi=bh}}if(a8==="success"||a8==="notmodified"){if(!be){aZ()}}else{a.handleError(a4,a0,a8,bi)}a2();if(bg==="timeout"){a0.abort()}if(a4.async){a0=null}}}};try{var aV=a0.abort;a0.abort=function(){if(a0){aV.call(a0)}a3("abort")}}catch(ba){}if(a4.async&&a4.timeout>0){setTimeout(function(){if(a0&&!a1){a3("timeout")}},a4.timeout)}try{a0.send(aW==="POST"||aW==="PUT"||aW==="DELETE"?a4.data:null)}catch(ba){a.handleError(a4,a0,null,ba);a2()}if(!a4.async){a3()}function aZ(){if(a4.success){a4.success.call(bf,bd,a8,a0)}if(a4.global){a5("ajaxSuccess",[a0,a4])}}function a2(){if(a4.complete){a4.complete.call(bf,a0,a8)}if(a4.global){a5("ajaxComplete",[a0,a4])}if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}}function a5(bh,bg){(a4.context?a(a4.context):a.event).trigger(bh,bg)}return a0},handleError:function(aV,aX,aU,aW){if(aV.error){aV.error.call(aV.context||aV,aX,aU,aW)}if(aV.global){(aV.context?a(aV.context):a.event).trigger("ajaxError",[aX,aV,aW])}},active:0,httpSuccess:function(aV){try{return !aV.status&&location.protocol==="file:"||(aV.status>=200&&aV.status<300)||aV.status===304||aV.status===1223||aV.status===0}catch(aU){}return false},httpNotModified:function(aX,aU){var aW=aX.getResponseHeader("Last-Modified"),aV=aX.getResponseHeader("Etag");if(aW){a.lastModified[aU]=aW}if(aV){a.etag[aU]=aV}return aX.status===304||aX.status===0},httpData:function(aZ,aX,aW){var aV=aZ.getResponseHeader("content-type")||"",aU=aX==="xml"||!aX&&aV.indexOf("xml")>=0,aY=aU?aZ.responseXML:aZ.responseText;if(aU&&aY.documentElement.nodeName==="parsererror"){a.error("parsererror")}if(aW&&aW.dataFilter){aY=aW.dataFilter(aY,aX)}if(typeof aY==="string"){if(aX==="json"||!aX&&aV.indexOf("json")>=0){aY=a.parseJSON(aY)}else{if(aX==="script"||!aX&&aV.indexOf("javascript")>=0){a.globalEval(aY)}}}return aY},param:function(aU,aX){var aV=[];if(aX===B){aX=a.ajaxSettings.traditional}if(a.isArray(aU)||aU.jquery){a.each(aU,function(){aZ(this.name,this.value)})}else{for(var aY in aU){aW(aY,aU[aY])}}return aV.join("&").replace(h,"+");function aW(a0,a1){if(a.isArray(a1)){a.each(a1,function(a3,a2){if(aX){aZ(a0,a2)}else{aW(a0+"["+(typeof a2==="object"||a.isArray(a2)?a3:"")+"]",a2)}})}else{if(!aX&&a1!=null&&typeof a1==="object"){a.each(a1,function(a3,a2){aW(a0+"["+a3+"]",a2)})}else{aZ(a0,a1)}}}function aZ(a0,a1){a1=a.isFunction(a1)?a1():a1;aV[aV.length]=encodeURIComponent(a0)+"="+encodeURIComponent(a1)}}});var E={},ad=/toggle|show|hide/,ar=/^([+-]=)?([\d+-.]+)(.*)$/,aB,ah=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];a.fn.extend({show:function(aV,a3){if(aV||aV===0){return this.animate(az("show",3),aV,a3)}else{for(var a0=0,aX=this.length;a0<aX;a0++){var aU=a.data(this[a0],"olddisplay");this[a0].style.display=aU||"";if(a.css(this[a0],"display")==="none"){var a2=this[a0].nodeName,a1;if(E[a2]){a1=E[a2]}else{var aW=a("<"+a2+" />").appendTo("body");a1=aW.css("display");if(a1==="none"){a1="block"}aW.remove();E[a2]=a1}a.data(this[a0],"olddisplay",a1)}}for(var aZ=0,aY=this.length;aZ<aY;aZ++){this[aZ].style.display=a.data(this[aZ],"olddisplay")||""}return this}},hide:function(aZ,a0){if(aZ||aZ===0){return this.animate(az("hide",3),aZ,a0)}else{for(var aY=0,aV=this.length;aY<aV;aY++){var aU=a.data(this[aY],"olddisplay");if(!aU&&aU!=="none"){a.data(this[aY],"olddisplay",a.css(this[aY],"display"))}}for(var aX=0,aW=this.length;aX<aW;aX++){this[aX].style.display="none"}return this}},_toggle:a.fn.toggle,toggle:function(aW,aV){var aU=typeof aW==="boolean";if(a.isFunction(aW)&&a.isFunction(aV)){this._toggle.apply(this,arguments)}else{if(aW==null||aU){this.each(function(){var aX=aU?aW:a(this).is(":hidden");a(this)[aX?"show":"hide"]()})}else{this.animate(az("toggle",3),aW,aV)}}return this},fadeTo:function(aU,aW,aV){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:aW},aU,aV)},animate:function(aY,aV,aX,aW){var aU=a.speed(aV,aX,aW);if(a.isEmptyObject(aY)){return this.each(aU.complete)}return this[aU.queue===false?"each":"queue"](function(){var a1=a.extend({},aU),a3,a2=this.nodeType===1&&a(this).is(":hidden"),aZ=this;for(a3 in aY){var a0=a3.replace(aw,k);if(a3!==a0){aY[a0]=aY[a3];delete aY[a3];a3=a0}if(aY[a3]==="hide"&&a2||aY[a3]==="show"&&!a2){return a1.complete.call(this)}if((a3==="height"||a3==="width")&&this.style){a1.display=a.css(this,"display");a1.overflow=this.style.overflow}if(a.isArray(aY[a3])){(a1.specialEasing=a1.specialEasing||{})[a3]=aY[a3][1];aY[a3]=aY[a3][0]}}if(a1.overflow!=null){this.style.overflow="hidden"}a1.curAnim=a.extend({},aY);a.each(aY,function(a5,a9){var a8=new a.fx(aZ,a1,a5);if(ad.test(a9)){a8[a9==="toggle"?a2?"show":"hide":a9](aY)}else{var a7=ar.exec(a9),ba=a8.cur(true)||0;if(a7){var a4=parseFloat(a7[2]),a6=a7[3]||"px";if(a6!=="px"){aZ.style[a5]=(a4||1)+a6;ba=((a4||1)/a8.cur(true))*ba;aZ.style[a5]=ba+a6}if(a7[1]){a4=((a7[1]==="-="?-1:1)*a4)+ba}a8.custom(ba,a4,a6)}else{a8.custom(ba,a9,"")}}});return true})},stop:function(aV,aU){var aW=a.timers;if(aV){this.queue([])}this.each(function(){for(var aX=aW.length-1;aX>=0;aX--){if(aW[aX].elem===this){if(aU){aW[aX](true)}aW.splice(aX,1)}}});if(!aU){this.dequeue()}return this}});a.each({slideDown:az("show",1),slideUp:az("hide",1),slideToggle:az("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(aU,aV){a.fn[aU]=function(aW,aX){return this.animate(aV,aW,aX)}});a.extend({speed:function(aW,aX,aV){var aU=aW&&typeof aW==="object"?aW:{complete:aV||!aV&&aX||a.isFunction(aW)&&aW,duration:aW,easing:aV&&aX||aX&&!a.isFunction(aX)&&aX};aU.duration=a.fx.off?0:typeof aU.duration==="number"?aU.duration:a.fx.speeds[aU.duration]||a.fx.speeds._default;aU.old=aU.complete;aU.complete=function(){if(aU.queue!==false){a(this).dequeue()}if(a.isFunction(aU.old)){aU.old.call(this)}};return aU},easing:{linear:function(aW,aX,aU,aV){return aU+aV*aW},swing:function(aW,aX,aU,aV){return((-Math.cos(aW*Math.PI)/2)+0.5)*aV+aU}},timers:[],fx:function(aV,aU,aW){this.options=aU;this.elem=aV;this.prop=aW;if(!aU.orig){aU.orig={}}}});a.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(a.fx.step[this.prop]||a.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(aV){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var aU=parseFloat(a.css(this.elem,this.prop,aV));return aU&&aU>-10000?aU:parseFloat(a.curCSS(this.elem,this.prop))||0},custom:function(aY,aX,aW){this.startTime=aL();this.start=aY;this.end=aX;this.unit=aW||this.unit||"px";this.now=this.start;this.pos=this.state=0;var aU=this;function aV(aZ){return aU.step(aZ)}aV.elem=this.elem;if(aV()&&a.timers.push(aV)&&!aB){aB=setInterval(a.fx.tick,13)}},show:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());a(this.elem).show()},hide:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(aX){var a2=aL(),aY=true;if(aX||a2>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var aZ in this.options.curAnim){if(this.options.curAnim[aZ]!==true){aY=false}}if(aY){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;var aW=a.data(this.elem,"olddisplay");this.elem.style.display=aW?aW:this.options.display;if(a.css(this.elem,"display")==="none"){this.elem.style.display="block"}}if(this.options.hide){a(this.elem).hide()}if(this.options.hide||this.options.show){for(var aU in this.options.curAnim){a.style(this.elem,aU,this.options.orig[aU])}}this.options.complete.call(this.elem)}return false}else{var aV=a2-this.startTime;this.state=aV/this.options.duration;var a0=this.options.specialEasing&&this.options.specialEasing[this.prop];var a1=this.options.easing||(a.easing.swing?"swing":"linear");this.pos=a.easing[a0||a1](this.state,aV,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};a.extend(a.fx,{tick:function(){var aV=a.timers;for(var aU=0;aU<aV.length;aU++){if(!aV[aU]()){aV.splice(aU--,1)}}if(!aV.length){a.fx.stop()}},stop:function(){clearInterval(aB);aB=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(aU){a.style(aU.elem,"opacity",aU.now)},_default:function(aU){if(aU.elem.style&&aU.elem.style[aU.prop]!=null){aU.elem.style[aU.prop]=(aU.prop==="width"||aU.prop==="height"?Math.max(0,aU.now):aU.now)+aU.unit}else{aU.elem[aU.prop]=aU.now}}}});if(a.expr&&a.expr.filters){a.expr.filters.animated=function(aU){return a.grep(a.timers,function(aV){return aU===aV.elem}).length}}function az(aV,aU){var aW={};a.each(ah.concat.apply([],ah.slice(0,aU)),function(){aW[this]=aV});return aW}if("getBoundingClientRect" in aa.documentElement){a.fn.offset=function(a3){var aW=this[0];if(a3){return this.each(function(a4){a.offset.setOffset(this,a3,a4)})}if(!aW||!aW.ownerDocument){return null}if(aW===aW.ownerDocument.body){return a.offset.bodyOffset(aW)}var aY=aW.getBoundingClientRect(),a2=aW.ownerDocument,aZ=a2.body,aU=a2.documentElement,aX=aU.clientTop||aZ.clientTop||0,a0=aU.clientLeft||aZ.clientLeft||0,a1=aY.top+(self.pageYOffset||a.support.boxModel&&aU.scrollTop||aZ.scrollTop)-aX,aV=aY.left+(self.pageXOffset||a.support.boxModel&&aU.scrollLeft||aZ.scrollLeft)-a0;return{top:a1,left:aV}}}else{a.fn.offset=function(a5){var aZ=this[0];if(a5){return this.each(function(a6){a.offset.setOffset(this,a5,a6)})}if(!aZ||!aZ.ownerDocument){return null}if(aZ===aZ.ownerDocument.body){return a.offset.bodyOffset(aZ)}a.offset.initialize();var aW=aZ.offsetParent,aV=aZ,a4=aZ.ownerDocument,a2,aX=a4.documentElement,a0=a4.body,a1=a4.defaultView,aU=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle,a3=aZ.offsetTop,aY=aZ.offsetLeft;while((aZ=aZ.parentNode)&&aZ!==a0&&aZ!==aX){if(a.offset.supportsFixedPosition&&aU.position==="fixed"){break}a2=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle;a3-=aZ.scrollTop;aY-=aZ.scrollLeft;if(aZ===aW){a3+=aZ.offsetTop;aY+=aZ.offsetLeft;if(a.offset.doesNotAddBorder&&!(a.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(aZ.nodeName))){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aV=aW,aW=aZ.offsetParent}if(a.offset.subtractsBorderForOverflowNotVisible&&a2.overflow!=="visible"){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aU=a2}if(aU.position==="relative"||aU.position==="static"){a3+=a0.offsetTop;aY+=a0.offsetLeft}if(a.offset.supportsFixedPosition&&aU.position==="fixed"){a3+=Math.max(aX.scrollTop,a0.scrollTop);aY+=Math.max(aX.scrollLeft,a0.scrollLeft)}return{top:a3,left:aY}}}a.offset={initialize:function(){var aU=aa.body,aV=aa.createElement("div"),aY,a0,aZ,a1,aW=parseFloat(a.curCSS(aU,"marginTop",true))||0,aX="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.extend(aV.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});aV.innerHTML=aX;aU.insertBefore(aV,aU.firstChild);aY=aV.firstChild;a0=aY.firstChild;a1=aY.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(a0.offsetTop!==5);this.doesAddBorderForTableAndCells=(a1.offsetTop===5);a0.style.position="fixed",a0.style.top="20px";this.supportsFixedPosition=(a0.offsetTop===20||a0.offsetTop===15);a0.style.position=a0.style.top="";aY.style.overflow="hidden",aY.style.position="relative";this.subtractsBorderForOverflowNotVisible=(a0.offsetTop===-5);this.doesNotIncludeMarginInBodyOffset=(aU.offsetTop!==aW);aU.removeChild(aV);aU=aV=aY=a0=aZ=a1=null;a.offset.initialize=a.noop},bodyOffset:function(aU){var aW=aU.offsetTop,aV=aU.offsetLeft;a.offset.initialize();if(a.offset.doesNotIncludeMarginInBodyOffset){aW+=parseFloat(a.curCSS(aU,"marginTop",true))||0;aV+=parseFloat(a.curCSS(aU,"marginLeft",true))||0}return{top:aW,left:aV}},setOffset:function(aZ,aV,aW){if(/static/.test(a.curCSS(aZ,"position"))){aZ.style.position="relative"}var aY=a(aZ),a1=aY.offset(),aU=parseInt(a.curCSS(aZ,"top",true),10)||0,a0=parseInt(a.curCSS(aZ,"left",true),10)||0;if(a.isFunction(aV)){aV=aV.call(aZ,aW,a1)}var aX={top:(aV.top-a1.top)+aU,left:(aV.left-a1.left)+a0};if("using" in aV){aV.using.call(aZ,aX)}else{aY.css(aX)}}};a.fn.extend({position:function(){if(!this[0]){return null}var aW=this[0],aV=this.offsetParent(),aX=this.offset(),aU=/^body|html$/i.test(aV[0].nodeName)?{top:0,left:0}:aV.offset();aX.top-=parseFloat(a.curCSS(aW,"marginTop",true))||0;aX.left-=parseFloat(a.curCSS(aW,"marginLeft",true))||0;aU.top+=parseFloat(a.curCSS(aV[0],"borderTopWidth",true))||0;aU.left+=parseFloat(a.curCSS(aV[0],"borderLeftWidth",true))||0;return{top:aX.top-aU.top,left:aX.left-aU.left}},offsetParent:function(){return this.map(function(){var aU=this.offsetParent||aa.body;while(aU&&(!/^body|html$/i.test(aU.nodeName)&&a.css(aU,"position")==="static")){aU=aU.offsetParent}return aU})}});a.each(["Left","Top"],function(aV,aU){var aW="scroll"+aU;a.fn[aW]=function(aZ){var aX=this[0],aY;if(!aX){return null}if(aZ!==B){return this.each(function(){aY=ak(this);if(aY){aY.scrollTo(!aV?aZ:a(aY).scrollLeft(),aV?aZ:a(aY).scrollTop())}else{this[aW]=aZ}})}else{aY=ak(aX);return aY?("pageXOffset" in aY)?aY[aV?"pageYOffset":"pageXOffset"]:a.support.boxModel&&aY.document.documentElement[aW]||aY.document.body[aW]:aX[aW]}}});function ak(aU){return("scrollTo" in aU&&aU.document)?aU:aU.nodeType===9?aU.defaultView||aU.parentWindow:false}a.each(["Height","Width"],function(aV,aU){var aW=aU.toLowerCase();a.fn["inner"+aU]=function(){return this[0]?a.css(this[0],aW,false,"padding"):null};a.fn["outer"+aU]=function(aX){return this[0]?a.css(this[0],aW,false,aX?"margin":"border"):null};a.fn[aW]=function(aX){var aY=this[0];if(!aY){return aX==null?null:this}if(a.isFunction(aX)){return this.each(function(a0){var aZ=a(this);aZ[aW](aX.call(this,a0,aZ[aW]()))})}return("scrollTo" in aY&&aY.document)?aY.document.compatMode==="CSS1Compat"&&aY.document.documentElement["client"+aU]||aY.document.body["client"+aU]:(aY.nodeType===9)?Math.max(aY.documentElement["client"+aU],aY.body["scroll"+aU],aY.documentElement["scroll"+aU],aY.body["offset"+aU],aY.documentElement["offset"+aU]):aX===B?a.css(aY,aW):this.css(aW,typeof aX==="string"?aX:aX+"px")}});aI.jQuery=aI.$=a})(window);window.djdt=(function(b,a,e){e.cookie=function(h,p,s){if(typeof p!="undefined"){s=s||{};if(p===null){p="";s.expires=-1}var l="";if(s.expires&&(typeof s.expires=="number"||s.expires.toUTCString)){var m;if(typeof s.expires=="number"){m=new Date();m.setTime(m.getTime()+(s.expires*24*60*60*1000))}else{m=s.expires}l="; expires="+m.toUTCString()}var r=s.path?"; path="+(s.path):"";var n=s.domain?"; domain="+(s.domain):"";var g=s.secure?"; secure":"";a.cookie=[h,"=",encodeURIComponent(p),l,r,n,g].join("")}else{var k=null;if(a.cookie&&a.cookie!=""){var q=a.cookie.split(";");for(var o=0;o<q.length;o++){var j=c.trim(q[o]);if(j.substring(0,h.length+1)==(h+"=")){k=decodeURIComponent(j.substring(h.length+1));break}}}return k}};var c=e;var f="djdt";var d={jQuery:e,events:{ready:[]},isReady:false,init:function(){c("#djDebug").show();var i=null;c("#djDebugPanelList li a").click(function(){if(!this.className){return false}i=c("#djDebug #"+this.className);if(i.is(":visible")){c(a).trigger("close.djDebug");c(this).parent().removeClass("active")}else{c(".panelContent").hide();i.show();c("#djDebugToolbar li").removeClass("active");c(this).parent().addClass("active")}return false});c("#djDebug a.djDebugClose").click(function(){c(a).trigger("close.djDebug");c("#djDebugToolbar li").removeClass("active");return false});c("#djDebug a.remoteCall").click(function(){c("#djDebugWindow").load(this.href,function(k,j,m){if(j=="error"){var l='<div class="djDebugPanelTitle"><a class="djDebugClose djDebugBack" href="">Back</a><h3>'+m.status+": "+m.statusText+"</h3></div>";c("#djDebugWindow").html(l)}c("#djDebugWindow a.djDebugBack").click(function(){c(this).parent().parent().hide();return false})});c("#djDebugWindow").show();return false});c("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){d.toggle_arrow(c(this).children(".toggleArrow"));d.toggle_content(c(this).parent().next());return false});c("#djDebug a.djDebugToggle").click(function(j){j.preventDefault();c(this).parent().find(".djDebugCollapsed").toggle();c(this).parent().find(".djDebugUncollapsed").toggle()});c("#djDebug a.djToggleSwitch").click(function(l){l.preventDefault();var j=c(this);var m=j.attr("data-toggle-id");var k=j.text()==j.attr("data-toggle-open");if(m==""||!m){return}j.parents(".djDebugPanelContent").find("#sqlMain_"+m).find(".djDebugCollapsed").toggle(k);j.parents(".djDebugPanelContent").find("#sqlMain_"+m).find(".djDebugUncollapsed").toggle(!k);c(this).parents(".djDebugPanelContent").find(".djToggleDetails_"+m).each(function(){var n=c(this);if(k){n.addClass("djSelected");n.removeClass("djUnselected");j.text(j.attr("data-toggle-close"));n.find(".djToggleSwitch").text(j.text())}else{n.removeClass("djSelected");n.addClass("djUnselected");j.text(j.attr("data-toggle-open"));n.find(".djToggleSwitch").text(j.text())}});return});function g(j){id=j.attr("id");return c('.djDebugProfileRow[id^="'+id+'_"]')}function h(j){subcalls=g(j);depth=parseInt(j.attr("depth"))+1;return subcalls.filter("[depth="+depth+"]")}c(".djDebugProfileRow .djDebugProfileToggle").click(function(){row=c(this).closest(".djDebugProfileRow");subcalls=g(row);if(subcalls.css("display")=="none"){h(row).show()}else{subcalls.hide()}});c("#djHideToolBarButton").click(function(){d.hide_toolbar(true);return false});c("#djShowToolBarButton").click(function(){d.show_toolbar();return false});c(a).bind("close.djDebug",function(){if(c("#djDebugWindow").is(":visible")){c("#djDebugWindow").hide();return}if(c(".panelContent").is(":visible")){c(".panelContent").hide();return}if(c("#djDebugToolbar").is(":visible")){d.hide_toolbar(true);return}});if(c.cookie(f)){d.hide_toolbar(false)}else{d.show_toolbar(false)}c("#djDebug .djDebugHoverable").hover(function(){c(this).addClass("djDebugHover")},function(){c(this).removeClass("djDebugHover")});d.isReady=true;c.each(d.events.ready,function(j,k){k(d)})},toggle_content:function(g){if(g.is(":visible")){g.hide()}else{g.show()}},close:function(){c(a).trigger("close.djDebug");return false},hide_toolbar:function(g){c("#djDebugWindow").hide();c(".panelContent").hide();c("#djDebugToolbar li").removeClass("active");c("#djDebugToolbar").hide("fast");c("#djDebugToolbarHandle").show();c(a).unbind("keydown.djDebug");if(g){c.cookie(f,"hide",{path:"/",expires:10})}},show_toolbar:function(g){c(a).bind("keydown.djDebug",function(h){if(h.keyCode==27){d.close()}});c("#djDebugToolbarHandle").hide();if(g){c("#djDebugToolbar").show("fast")}else{c("#djDebugToolbar").show()}c.cookie(f,null,{path:"/",expires:-1})},toggle_arrow:function(h){var g=String.fromCharCode(9654);var i=String.fromCharCode(9660);h.html(h.html()==g?i:g)},ready:function(g){if(d.isReady){g(d)}else{d.events.ready.push(g)}}};c(a).ready(function(){d.init()});return d}(window,document,jQuery.noConflict(true))); \ No newline at end of file
diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py
index de4ae9c..f49a29f 100644
--- a/debug_toolbar/middleware.py
+++ b/debug_toolbar/middleware.py
@@ -1,13 +1,15 @@
"""
Debug Toolbar middleware
"""
+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
-from django.conf.urls.defaults import include, patterns
+from django.utils.importlib import import_module
import debug_toolbar.urls
from debug_toolbar.toolbar.loader import DebugToolbar
@@ -32,13 +34,13 @@ class DebugToolbarMiddleware(object):
on outgoing response.
"""
debug_toolbars = {}
-
+
@classmethod
def get_current(cls):
return cls.debug_toolbars.get(thread.get_ident())
def __init__(self):
- self.override_url = True
+ self._urlconfs = {}
# Set method to use to decide to show toolbar
self.show_toolbar = self._show_toolbar # default
@@ -57,32 +59,39 @@ class DebugToolbarMiddleware(object):
self.tag = u'</' + tag + u'>'
def _show_toolbar(self, request):
+ if getattr(settings, 'TEST', False):
+ return False
+
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', None)
if x_forwarded_for:
remote_addr = x_forwarded_for.split(',')[0].strip()
else:
remote_addr = request.META.get('REMOTE_ADDR', None)
- if not remote_addr in settings.INTERNAL_IPS \
- or (request.is_ajax() and \
- not debug_toolbar.urls._PREFIX in request.path) \
- or not (settings.DEBUG or getattr(settings, 'TEST', False)):
- return False
- return True
+
+ # if not internal ip, and not DEBUG
+ return remote_addr in settings.INTERNAL_IPS and bool(settings.DEBUG)
def process_request(self, request):
__traceback_hide__ = True
if self.show_toolbar(request):
- if self.override_url:
- original_urlconf = __import__(getattr(request, 'urlconf', settings.ROOT_URLCONF), {}, {}, ['*'])
- debug_toolbar.urls.urlpatterns += patterns('',
- ('', include(original_urlconf)),
- )
- if hasattr(original_urlconf, 'handler404'):
- debug_toolbar.urls.handler404 = original_urlconf.handler404
- if hasattr(original_urlconf, 'handler500'):
- debug_toolbar.urls.handler500 = original_urlconf.handler500
- self.override_url = False
- request.urlconf = 'debug_toolbar.urls'
+
+ urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF)
+ if isinstance(urlconf, basestring):
+ urlconf = import_module(getattr(request, 'urlconf', settings.ROOT_URLCONF))
+
+ if urlconf not in self._urlconfs:
+ new_urlconf = imp.new_module('urlconf')
+ new_urlconf.urlpatterns = debug_toolbar.urls.urlpatterns + \
+ urlconf.urlpatterns
+
+ if hasattr(urlconf, 'handler404'):
+ new_urlconf.handler404 = urlconf.handler404
+ if hasattr(urlconf, 'handler500'):
+ new_urlconf.handler500 = urlconf.handler500
+
+ self._urlconfs[urlconf] = new_urlconf
+
+ request.urlconf = self._urlconfs[urlconf]
toolbar = DebugToolbar(request)
for panel in toolbar.panels:
@@ -119,7 +128,7 @@ class DebugToolbarMiddleware(object):
for panel in toolbar.panels:
panel.process_response(request, response)
response.content = replace_insensitive(
- smart_unicode(response.content),
+ smart_unicode(response.content),
self.tag,
smart_unicode(toolbar.render_toolbar() + self.tag))
if response.get('Content-Length', None):
diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py
index fa2e4b6..b4f11fb 100644
--- a/debug_toolbar/panels/__init__.py
+++ b/debug_toolbar/panels/__init__.py
@@ -1,48 +1,67 @@
-"""Base DebugPanel class"""
+from django.template.defaultfilters import slugify
+from django.template.loader import render_to_string
+from debug_toolbar.middleware import DebugToolbarMiddleware
+
class DebugPanel(object):
"""
Base class for debug panels.
"""
- # name = Base
+ # name = 'Base'
+ # template = 'debug_toolbar/panels/base.html'
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):
- raise NotImplementedError
-
+ 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)
+ if panel_stats:
+ 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 5617ec2..620be86 100644
--- a/debug_toolbar/panels/cache.py
+++ b/debug_toolbar/panels/cache.py
@@ -3,7 +3,6 @@ import inspect
from django.core import cache
from django.core.cache.backends.base import BaseCache
-from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
@@ -12,7 +11,7 @@ class CacheStatTracker(BaseCache):
def __init__(self, cache):
self.cache = cache
self.reset()
-
+
def reset(self):
self.calls = []
self.hits = 0
@@ -22,11 +21,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)
@@ -39,7 +38,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)
@@ -47,7 +46,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)
@@ -55,7 +54,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)
@@ -74,10 +73,11 @@ class CacheDebugPanel(DebugPanel):
Panel that displays the cache statistics.
"""
name = 'Cache'
+ template = 'debug_toolbar/panels/cache.html'
has_content = True
-
+
def __init__(self, *args, **kwargs):
- super(self.__class__, self).__init__(*args, **kwargs)
+ super(CacheDebugPanel, self).__init__(*args, **kwargs)
# This is hackish but to prevent threading issues is somewhat needed
if isinstance(cache.cache, CacheStatTracker):
cache.cache.reset()
@@ -85,21 +85,19 @@ 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 content(self):
- context = self.context.copy()
- context.update({
+
+ def process_response(self, request, response):
+ self.record_stats({
'cache_calls': len(self.cache.calls),
'cache_time': self.cache.total_time,
'cache': self.cache,
})
- return render_to_string('debug_toolbar/panels/cache.html', context)
diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py
index 1e929f6..181e88d 100644
--- a/debug_toolbar/panels/headers.py
+++ b/debug_toolbar/panels/headers.py
@@ -1,12 +1,13 @@
-from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
+
class HeaderDebugPanel(DebugPanel):
"""
A panel to display HTTP headers.
"""
name = 'Header'
+ template = 'debug_toolbar/panels/headers.html'
has_content = True
# List of headers we want to display
header_filter = (
@@ -31,24 +32,22 @@ 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 content(self):
- context = self.context.copy()
- context.update({
+
+ def process_response(self, request, response):
+ self.record_stats({
'headers': self.headers
})
- return render_to_string('debug_toolbar/panels/headers.html', context)
diff --git a/debug_toolbar/panels/logger.py b/debug_toolbar/panels/logger.py
index 5e82a13..55ae9bd 100644
--- a/debug_toolbar/panels/logger.py
+++ b/debug_toolbar/panels/logger.py
@@ -4,7 +4,6 @@ try:
import threading
except ImportError:
threading = None
-from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
@@ -15,15 +14,15 @@ class LogCollector(object):
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
-
+
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,
@@ -34,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()
@@ -46,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(),
@@ -76,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,
@@ -87,40 +86,37 @@ if logbook_supported:
'channel': record.channel,
}
self.collector.add_record(record)
-
-
+
+
logbook_handler = LogbookThreadTrackingHandler(collector)
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 ''
-
- def content(self):
- records = self.get_and_delete()
- context = self.context.copy()
- context.update({'records': records})
-
- return render_to_string('debug_toolbar/panels/logger.html', context)
-
diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py
index 95a1a4d..8913621 100644
--- a/debug_toolbar/panels/profiling.py
+++ b/debug_toolbar/panels/profiling.py
@@ -1,13 +1,22 @@
from __future__ import division
-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
+try:
+ from line_profiler import LineProfiler, show_func
+ DJ_PROFILE_USE_LINE_PROFILER = True
+except ImportError:
+ DJ_PROFILE_USE_LINE_PROFILER = False
+
+
+from cStringIO import StringIO
import cProfile
from pstats import Stats
from colorsys import hsv_to_rgb
+import os
+
class DjangoDebugToolbarStats(Stats):
__root = None
@@ -19,16 +28,11 @@ class DjangoDebugToolbarStats(Stats):
self.__root = func
break
return self.__root
-
- def print_call_tree_node(self, function, depth, max_depth, cum_filter=0.1):
- self.print_line(function, depth=depth)
- if depth < max_depth:
- for called in self.all_callees[function].keys():
- if self.stats[called][3] >= cum_filter:
- self.print_call_tree_node(called, depth+1, max_depth, cum_filter=cum_filter)
+
class FunctionCall(object):
- def __init__(self, statobj, func, depth=0, stats=None, id=0, parent_ids=[], hsv=(0,0.5,1)):
+ def __init__(self, statobj, func, depth=0, stats=None,
+ id=0, parent_ids=[], hsv=(0,0.5,1)):
self.statobj = statobj
self.func = func
if stats:
@@ -39,6 +43,7 @@ class FunctionCall(object):
self.id = id
self.parent_ids = parent_ids
self.hsv = hsv
+ self._line_stats_text = None
def parent_classes(self):
return self.parent_classes
@@ -60,9 +65,9 @@ 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('/', 1)
+ file_path, file_name = file_name.rsplit(os.sep, 1)
return mark_safe('<span class="path">{0}/</span><span class="file">{1}</span> in <span class="func">{3}</span>(<span class="lineno">{2}</span>)'.format(
file_path,
@@ -73,7 +78,7 @@ class FunctionCall(object):
def subfuncs(self):
i=0
- h,s,v = self.hsv
+ 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
@@ -83,8 +88,8 @@ class FunctionCall(object):
else:
s1 = s*(stats[3]/self.stats[3])
yield FunctionCall(self.statobj,
- func,
- self.depth+1,
+ func,
+ self.depth+1,
stats=stats,
id=str(self.id) + '_' + str(i),
parent_ids=self.parent_ids + [self.id],
@@ -102,69 +107,97 @@ class FunctionCall(object):
def tottime_per_call(self):
cc, nc, tt, ct = self.stats
-
+
if nc == 0:
return 0
-
+
return tt/nc
def cumtime_per_call(self):
cc, nc, tt, ct = self.stats
-
+
if cc == 0:
return 0
-
+
return ct/cc
-
+
def indent(self):
return 16 * self.depth
+
+ def line_stats_text(self):
+ if self._line_stats_text is None and DJ_PROFILE_USE_LINE_PROFILER:
+ lstats = self.statobj.line_stats
+ if self.func in lstats.timings:
+ out = StringIO()
+ fn, lineno, name = self.func
+ show_func(fn, lineno, name, lstats.timings[self.func], lstats.unit, stream=out)
+ self._line_stats_text = out.getvalue()
+ else:
+ self._line_stats_text = False
+ return self._line_stats_text
class ProfilingDebugPanel(DebugPanel):
"""
Panel that displays the Django version.
"""
name = 'Profiling'
+ template = 'debug_toolbar/panels/profiling.html'
has_content = True
-
+
def nav_title(self):
return _('Profiling')
-
+
def url(self):
return ''
def title(self):
return _('Profiling')
-
+
+ def _unwrap_closure_and_profile(self, func):
+ if not hasattr(func, 'func_code'):
+ return
+ self.line_profiler.add_function(func)
+ if func.func_closure:
+ for cell in func.func_closure:
+ if hasattr(cell.cell_contents, 'func_code'):
+ self._unwrap_closure_and_profile(cell.cell_contents)
+
def process_view(self, request, view_func, view_args, view_kwargs):
__traceback_hide__ = True
self.profiler = cProfile.Profile()
args = (request,) + view_args
- return self.profiler.runcall(view_func, *args, **view_kwargs)
-
- def process_response(self, request, response):
- self.profiler.create_stats()
- self.stats = DjangoDebugToolbarStats(self.profiler)
- return response
-
+ if DJ_PROFILE_USE_LINE_PROFILER:
+ self.line_profiler = LineProfiler()
+ self._unwrap_closure_and_profile(view_func)
+ self.line_profiler.enable_by_count()
+ out = self.profiler.runcall(view_func, *args, **view_kwargs)
+ self.line_profiler.disable_by_count()
+ else:
+ self.line_profiler = None
+ out = self.profiler.runcall(view_func, *args, **view_kwargs)
+ return out
+
def add_node(self, func_list, func, max_depth, cum_time=0.1):
func_list.append(func)
func.has_subfuncs = False
if func.depth < max_depth:
for subfunc in func.subfuncs():
- if subfunc.stats[3] >= cum_time:
+ if (subfunc.stats[3] >= cum_time or
+ (hasattr(self.stats, 'line_stats') and
+ (subfunc.func in self.stats.line_stats.timings))):
func.has_subfuncs = True
self.add_node(func_list, subfunc, max_depth, cum_time=cum_time)
- def content(self):
-
+ def process_response(self, request, response):
+ self.profiler.create_stats()
+ self.stats = DjangoDebugToolbarStats(self.profiler)
+ if DJ_PROFILE_USE_LINE_PROFILER:
+ self.stats.line_stats = self.line_profiler.get_stats()
self.stats.calc_callees()
+
root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0)
func_list = []
self.add_node(func_list, root, 10, root.stats[3]/8)
- context = self.context.copy()
- context.update({
- 'func_list': func_list,
- })
-
- return render_to_string('debug_toolbar/panels/profiling.html', context)
+
+ self.stats_record({'func_list': func_list})
diff --git a/debug_toolbar/panels/request_vars.py b/debug_toolbar/panels/request_vars.py
index 632068e..ee9cdc5 100644
--- a/debug_toolbar/panels/request_vars.py
+++ b/debug_toolbar/panels/request_vars.py
@@ -1,52 +1,59 @@
-from django.template.loader import render_to_string
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).
"""
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 content(self):
- context = self.context.copy()
-
- if hasattr(self.view_func, '__name__'):
- view_name = self.view_func.__name__
- elif hasattr(self.view_func, '__class__'):
- view_name = self.view_func.__class__.__name__
- else:
- view_name = '<unknown>'
-
- context.update({
+
+ 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],
- 'view_func': '%s.%s' % (self.view_func.__module__, view_name),
- 'view_args': self.view_args,
- 'view_kwargs': self.view_kwargs
})
+
+ 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'):
- context.update({
+ self.record_stats({
'session': [(k, self.request.session.get(k)) for k in self.request.session.iterkeys()]
})
-
- return render_to_string('debug_toolbar/panels/request_vars.html', context)
diff --git a/debug_toolbar/panels/settings_vars.py b/debug_toolbar/panels/settings_vars.py
index ebb4464..e154dda 100644
--- a/debug_toolbar/panels/settings_vars.py
+++ b/debug_toolbar/panels/settings_vars.py
@@ -1,5 +1,4 @@
from django.conf import settings
-from django.template.loader import render_to_string
from django.views.debug import get_safe_settings
from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
@@ -10,20 +9,19 @@ class SettingsVarsDebugPanel(DebugPanel):
A panel to display all variables in django.conf.settings
"""
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 content(self):
- context = self.context.copy()
- context.update({
+
+ def process_response(self, request, response):
+ self.record_stats({
'settings': get_safe_settings(),
})
- return render_to_string('debug_toolbar/panels/settings_vars.html', context)
diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py
index dbd3725..205b3c5 100644
--- a/debug_toolbar/panels/signals.py
+++ b/debug_toolbar/panels/signals.py
@@ -6,7 +6,6 @@ from django.core.signals import request_started, request_finished, \
from django.db.models.signals import class_prepared, pre_init, post_init, \
pre_save, post_save, pre_delete, post_delete, post_syncdb
from django.dispatch.dispatcher import WEAKREF_TYPES
-from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
try:
@@ -18,8 +17,9 @@ from debug_toolbar.panels import DebugPanel
class SignalDebugPanel(DebugPanel):
name = "Signals"
+ template = 'debug_toolbar/panels/signals.html'
has_content = True
-
+
SIGNALS = {
'request_started': request_started,
'request_finished': request_finished,
@@ -34,16 +34,16 @@ class SignalDebugPanel(DebugPanel):
'post_delete': post_delete,
'post_syncdb': post_syncdb,
}
-
+
def nav_title(self):
return _("Signals")
-
+
def title(self):
return _("Signals")
-
+
def url(self):
return ''
-
+
def signals(self):
signals = self.SIGNALS.copy()
if hasattr(settings, 'DEBUG_TOOLBAR_CONFIG'):
@@ -57,8 +57,8 @@ class SignalDebugPanel(DebugPanel):
signals[parts[-1]] = getattr(sys.modules[path], parts[-1])
return signals
signals = property(signals)
-
- def content(self):
+
+ def process_response(self, request, response):
signals = []
keys = self.signals.keys()
keys.sort()
@@ -80,8 +80,5 @@ class SignalDebugPanel(DebugPanel):
text = "function %s" % receiver.__name__
receivers.append(text)
signals.append((name, signal, receivers))
-
- context = self.context.copy()
- context.update({'signals': signals})
-
- return render_to_string('debug_toolbar/panels/signals.html', context)
+
+ self.record_stats({'signals': signals})
diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py
index c6b5996..b27e6c0 100644
--- a/debug_toolbar/panels/sql.py
+++ b/debug_toolbar/panels/sql.py
@@ -2,7 +2,6 @@ import re
import uuid
from django.db.backends import BaseDatabaseWrapper
-from django.template.loader import render_to_string
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _, ungettext_lazy as __
@@ -14,11 +13,12 @@ from debug_toolbar.utils import sqlparse
from debug_toolbar.utils.tracking.db import CursorWrapper
from debug_toolbar.utils.tracking import replace_call
+
# Inject our tracking cursor
@replace_call(BaseDatabaseWrapper.cursor)
def cursor(func, self):
result = func(self)
-
+
djdt = DebugToolbarMiddleware.get_current()
if not djdt:
return result
@@ -26,6 +26,7 @@ def cursor(func, self):
return CursorWrapper(result, self, logger=logger)
+
def get_isolation_level_display(engine, level):
if engine == 'psycopg2':
import psycopg2.extensions
@@ -41,6 +42,7 @@ def get_isolation_level_display(engine, level):
return choices.get(level)
+
def get_transaction_status_display(engine, level):
if engine == 'psycopg2':
import psycopg2.extensions
@@ -56,16 +58,18 @@ def get_transaction_status_display(engine, level):
return choices.get(level)
+
class SQLDebugPanel(DebugPanel):
"""
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(self.__class__, self).__init__(*args, **kwargs)
+ super(SQLDebugPanel, self).__init__(*args, **kwargs)
self._offset = dict((k, len(connections[k].queries)) for k in connections)
self._sql_time = 0
self._num_queries = 0
@@ -78,20 +82,20 @@ class SQLDebugPanel(DebugPanel):
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
@@ -112,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" % (
@@ -123,18 +127,18 @@ 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 content(self):
+
+ def process_response(self, request, response):
if self._queries:
width_ratio_tally = 0
colors = [
@@ -157,7 +161,7 @@ class SQLDebugPanel(DebugPanel):
nn = 0
rgb[nn] = nc
db['rgb_color'] = rgb
-
+
trans_ids = {}
trans_id = None
i = 0
@@ -183,30 +187,34 @@ 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)
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:]))
- stacktrace.append('<span class="path">{0}/</span><span class="file">{1}</span> in <span class="func">{3}</span>(<span class="lineno">{2}</span>)\n <span class="code">{4}</span>'.format(*params))
+ try:
+ stacktrace.append(u'<span class="path">{0}/</span><span class="file">{1}</span> in <span class="func">{3}</span>(<span class="lineno">{2}</span>)\n <span class="code">{4}</span>'.format(*params))
+ except IndexError:
+ # This frame doesn't have the expected format, so skip it and move on to the next one
+ continue
query['stacktrace'] = mark_safe('\n'.join(stacktrace))
i += 1
-
+
if trans_id:
self._queries[i-1][1]['ends_trans'] = True
- context = self.context.copy()
- context.update({
+ self.record_stats({
'databases': sorted(self._databases.items(), key=lambda x: -x[1]['time_spent']),
'queries': [q for a, q in self._queries],
'sql_time': self._sql_time,
})
- return render_to_string('debug_toolbar/panels/sql.html', context)
class BoldKeywordFilter(sqlparse.filters.Filter):
"""sqlparse filter to bold SQL keywords"""
@@ -220,8 +228,11 @@ class BoldKeywordFilter(sqlparse.filters.Filter):
if is_keyword:
yield sqlparse.tokens.Text, '</strong>'
+
def swap_fields(sql):
- return re.sub('SELECT</strong> (.*) <strong>FROM', 'SELECT</strong> <span class="djDebugCollapse">\g<1></span> <strong>FROM', sql)
+ return re.sub('SELECT</strong> (.*) <strong>FROM', 'SELECT</strong> <a class="djDebugUncollapsed djDebugToggle" href="#">&bull;&bull;&bull;</a> ' +
+ '<a class="djDebugCollapsed djDebugToggle" href="#">\g<1></a> <strong>FROM', sql)
+
def reformat_sql(sql):
stack = sqlparse.engine.FilterStack()
diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py
index 44b8b3e..5c20fcd 100644
--- a/debug_toolbar/panels/template.py
+++ b/debug_toolbar/panels/template.py
@@ -4,10 +4,11 @@ from pprint import pformat
from django import http
from django.conf import settings
from django.template.context import get_standard_processors
-from django.template.loader import render_to_string
from django.test.signals import template_rendered
from django.utils.translation import ugettext_lazy as _
+from django.db.models.query import QuerySet
from debug_toolbar.panels import DebugPanel
+from debug_toolbar.utils.tracking.db import recording, SQLQueryTriggered
# Code taken and adapted from Simon Willison and Django Snippets:
# http://www.djangosnippets.org/snippets/766/
@@ -27,6 +28,7 @@ else:
Template.original_render = Template._render
Template._render = instrumented_test_render
+
# MONSTER monkey-patch
old_template_init = Template.__init__
def new_template_init(self, template_string, origin=None, name='<Unknown Template>'):
@@ -34,36 +36,76 @@ def new_template_init(self, template_string, origin=None, name='<Unknown Templat
self.origin = origin
Template.__init__ = new_template_init
+
class TemplateDebugPanel(DebugPanel):
"""
A panel that lists all templates used during processing of a response.
"""
name = 'Template'
+ template = 'debug_toolbar/panels/templates.html'
has_content = True
-
+
def __init__(self, *args, **kwargs):
- super(self.__class__, self).__init__(*args, **kwargs)
+ super(TemplateDebugPanel, self).__init__(*args, **kwargs)
self.templates = []
template_rendered.connect(self._store_template_info)
-
+
def _store_template_info(self, sender, **kwargs):
+ context_data = kwargs['context']
+
+ context_list = []
+ for context_layer in context_data.dicts:
+ temp_layer = {}
+ if hasattr(context_layer, 'items'):
+ for key, value in context_layer.items():
+ # Replace any request elements - they have a large
+ # unicode representation and the request data is
+ # already made available from the Request Vars panel.
+ if isinstance(value, http.HttpRequest):
+ temp_layer[key] = '<<request>>'
+ # Replace the debugging sql_queries element. The SQL
+ # data is already made available from the SQL panel.
+ elif key == 'sql_queries' and isinstance(value, list):
+ temp_layer[key] = '<<sql_queries>>'
+ # Replace LANGUAGES, which is available in i18n context processor
+ elif key == 'LANGUAGES' and isinstance(value, tuple):
+ temp_layer[key] = '<<languages>>'
+ # QuerySet would trigger the database: user can run the query from SQL Panel
+ elif isinstance(value, QuerySet):
+ model_name = "%s.%s" % (value.model._meta.app_label, value.model.__name__)
+ temp_layer[key] = '<<queryset of %s>>' % model_name
+ else:
+ try:
+ recording(False)
+ pformat(value) # this MAY trigger a db query
+ except SQLQueryTriggered:
+ temp_layer[key] = '<<triggers database query>>'
+ else:
+ temp_layer[key] = value
+ finally:
+ recording(True)
+ try:
+ context_list.append(pformat(temp_layer))
+ except UnicodeEncodeError:
+ pass
+ kwargs['context'] = context_list
self.templates.append(kwargs)
-
+
def nav_title(self):
return _('Templates')
-
+
def title(self):
num_templates = len([t for t in self.templates
if not (t['template'].name and t['template'].name.startswith('debug_toolbar/'))])
return _('Templates (%(num_templates)s rendered)') % {'num_templates': num_templates}
-
+
def url(self):
return ''
-
+
def process_request(self, request):
self.request = request
-
- def content(self):
+
+ def process_response(self, request, response):
context_processors = dict(
[
("%s.%s" % (k.__module__, k.__name__),
@@ -78,6 +120,8 @@ class TemplateDebugPanel(DebugPanel):
# Skip templates that we are generating through the debug toolbar.
if template.name and template.name.startswith('debug_toolbar/'):
continue
+ if not hasattr(template, 'origin'):
+ continue
if template.origin and template.origin.name:
template.origin_name = template.origin.name
else:
@@ -85,36 +129,12 @@ class TemplateDebugPanel(DebugPanel):
info['template'] = template
# Clean up context for better readability
if getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}).get('SHOW_TEMPLATE_CONTEXT', True):
- context_data = template_data.get('context', None)
-
- context_list = []
- for context_layer in context_data.dicts:
- if hasattr(context_layer, 'items'):
- for key, value in context_layer.items():
- # Replace any request elements - they have a large
- # unicode representation and the request data is
- # already made available from the Request Vars panel.
- if isinstance(value, http.HttpRequest):
- context_layer[key] = '<<request>>'
- # Replace the debugging sql_queries element. The SQL
- # data is already made available from the SQL panel.
- elif key == 'sql_queries' and isinstance(value, list):
- context_layer[key] = '<<sql_queries>>'
- # Replace LANGUAGES, which is available in i18n context processor
- elif key == 'LANGUAGES' and isinstance(value, tuple):
- context_layer[key] = '<<languages>>'
- try:
- context_list.append(pformat(context_layer))
- except UnicodeEncodeError:
- pass
+ context_list = template_data.get('context', [])
info['context'] = '\n'.join(context_list)
template_context.append(info)
-
- context = self.context.copy()
- context.update({
+
+ self.record_stats({
'templates': template_context,
'template_dirs': [normpath(x) for x in settings.TEMPLATE_DIRS],
'context_processors': context_processors,
})
-
- return render_to_string('debug_toolbar/panels/templates.html', context)
diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py
index d866166..7c0febf 100644
--- a/debug_toolbar/panels/timer.py
+++ b/debug_toolbar/panels/timer.py
@@ -7,11 +7,13 @@ from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import DebugPanel
+
class TimerDebugPanel(DebugPanel):
"""
Panel that displays the time a response took in milliseconds.
"""
name = 'Timer'
+ template = 'debug_toolbar/panels/timer.html'
try: # if resource module not available, don't show content panel
resource
except NameError:
@@ -20,47 +22,23 @@ class TimerDebugPanel(DebugPanel):
else:
has_content = True
has_resource = True
-
+
def process_request(self, request):
self._start_time = time.time()
if self.has_resource:
self._start_rusage = resource.getrusage(resource.RUSAGE_SELF)
-
+
def process_response(self, request, response):
- self.total_time = (time.time() - self._start_time) * 1000
+ total_time = (time.time() - self._start_time) * 1000
if self.has_resource:
self._end_rusage = resource.getrusage(resource.RUSAGE_SELF)
-
- def nav_title(self):
- return _('Time')
-
- def nav_subtitle(self):
- # TODO l10n
- if self.has_resource:
- utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime
- stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime
- return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, self.total_time)
- else:
- return 'TOTAL: %0.2fms' % (self.total_time)
-
- def title(self):
- return _('Resource Usage')
-
- def url(self):
- return ''
-
- def _elapsed_ru(self, name):
- return getattr(self._end_rusage, name) - getattr(self._start_rusage, name)
-
- def content(self):
-
+
utime = 1000 * self._elapsed_ru('ru_utime')
stime = 1000 * self._elapsed_ru('ru_stime')
vcsw = self._elapsed_ru('ru_nvcsw')
ivcsw = self._elapsed_ru('ru_nivcsw')
minflt = self._elapsed_ru('ru_minflt')
majflt = self._elapsed_ru('ru_majflt')
-
# these are documented as not meaningful under Linux. If you're running BSD
# feel free to enable them, and add any others that I hadn't gotten to before
# I noticed that I was getting nothing but zeroes and that the docs agreed. :-(
@@ -72,22 +50,63 @@ class TimerDebugPanel(DebugPanel):
# srss = self._end_rusage.ru_ixrss
# urss = self._end_rusage.ru_idrss
# usrss = self._end_rusage.ru_isrss
-
+
+ self.record_stats({
+ 'total_time': total_time,
+ 'utime': utime,
+ 'stime': stime,
+ 'vcsw': vcsw,
+ 'ivcsw': ivcsw,
+ 'minflt': minflt,
+ 'majflt': majflt,
+# 'blkin': blkin,
+# 'blkout': blkout,
+# 'swap': swap,
+# 'rss': rss,
+# 'urss': urss,
+# 'srss': srss,
+# 'usrss': usrss,
+ })
+
+ def nav_title(self):
+ return _('Time')
+
+ def nav_subtitle(self):
+ stats = self.get_stats()
+
+ # TODO l10n
+ if self.has_resource:
+ utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime
+ stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime
+ return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, stats['total_time'])
+ else:
+ return 'TOTAL: %0.2fms' % (stats['total_time'])
+
+ def title(self):
+ return _('Resource Usage')
+
+ def url(self):
+ return ''
+
+ def _elapsed_ru(self, name):
+ return getattr(self._end_rusage, name) - getattr(self._start_rusage, name)
+
+ def content(self):
+ stats = self.get_stats()
+
# TODO l10n on values
rows = (
- (_('User CPU time'), '%0.3f msec' % utime),
- (_('System CPU time'), '%0.3f msec' % stime),
- (_('Total CPU time'), '%0.3f msec' % (utime + stime)),
- (_('Elapsed time'), '%0.3f msec' % self.total_time),
- (_('Context switches'), '%d voluntary, %d involuntary' % (vcsw, ivcsw)),
-# ('Memory use', '%d max RSS, %d shared, %d unshared' % (rss, srss, urss + usrss)),
-# ('Page faults', '%d no i/o, %d requiring i/o' % (minflt, majflt)),
-# ('Disk operations', '%d in, %d out, %d swapout' % (blkin, blkout, swap)),
+ (_('User CPU time'), '%0.3f msec' % stats['utime']),
+ (_('System CPU time'), '%0.3f msec' % stats['stime']),
+ (_('Total CPU time'), '%0.3f msec' % (stats['utime'] + stats['stime'])),
+ (_('Elapsed time'), '%0.3f msec' % stats['total_time']),
+ (_('Context switches'), '%d voluntary, %d involuntary' % (stats['vcsw'], stats['ivcsw'])),
+# ('Memory use', '%d max RSS, %d shared, %d unshared' % (stats['rss'], stats.['srss'],
+# stats['urss'] + stats['usrss'])),
+# ('Page faults', '%d no i/o, %d requiring i/o' % (stats['minflt'], stats['majflt'])),
+# ('Disk operations', '%d in, %d out, %d swapout' % (stats['blkin'], stats['blkout'], stats['swap'])),
)
-
+
context = self.context.copy()
- context.update({
- 'rows': rows,
- })
-
- return render_to_string('debug_toolbar/panels/timer.html', context)
+ 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 f0d8fbc..4e58971 100644
--- a/debug_toolbar/panels/version.py
+++ b/debug_toolbar/panels/version.py
@@ -2,10 +2,8 @@ import sys
import django
from django.conf import settings
-from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
-import debug_toolbar
from debug_toolbar.panels import DebugPanel
@@ -14,21 +12,22 @@ class VersionDebugPanel(DebugPanel):
Panel that displays the Django version.
"""
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 content(self):
+
+ def process_response(self, request, response):
versions = {}
versions['Python'] = '%d.%d.%d' % sys.version_info[:3]
for app in settings.INSTALLED_APPS + ['django']:
@@ -50,11 +49,8 @@ class VersionDebugPanel(DebugPanel):
if isinstance(version, (list, tuple)):
version = '.'.join(str(o) for o in version)
versions[name] = version
-
- context = self.context.copy()
- context.update({
+
+ self.record_stats({
'versions': versions,
'paths': sys.path,
})
-
- return render_to_string('debug_toolbar/panels/versions.html', context)
diff --git a/debug_toolbar/templates/debug_toolbar/panels/profiling.html b/debug_toolbar/templates/debug_toolbar/panels/profiling.html
index ebc91cc..f2d43de 100644
--- a/debug_toolbar/templates/debug_toolbar/panels/profiling.html
+++ b/debug_toolbar/templates/debug_toolbar/panels/profiling.html
@@ -4,17 +4,17 @@
<thead>
<tr>
<th>{% trans "Call" %}</th>
- <th>{% trans "TotTime" %}</th>
- <th>{% trans "Per" %}</th>
<th>{% trans "CumTime" %}</th>
<th>{% trans "Per" %}</th>
+ <th>{% trans "TotTime" %}</th>
+ <th>{% trans "Per" %}</th>
<th>{% trans "Count" %}</th>
</tr>
</thead>
<tbody>
{% for call in func_list %}
<!-- style="background:{{ call.background }}" -->
- <tr id="{{ call.id }}" class="djDebugProfileRow{% for parent_id in call.parent_ids %} djToggleDetails_{{ parent_id }}{% endfor %}" depth="{{ call.depth }}">
+ <tr class="djDebugProfileRow{% for parent_id in call.parent_ids %} djToggleDetails_{{ parent_id }}{% endfor %}" depth="{{ call.depth }}">
<td>
<div style="padding-left: {{ call.indent }}px;">
{% if call.has_subfuncs %}
@@ -25,12 +25,19 @@
<span class="stack">{{ call.func_std_string }}</span>
</div>
</td>
- <td>{{ call.tottime|floatformat:3 }}</td>
- <td>{{ call.tottime_per_call|floatformat:3 }}</td>
<td>{{ call.cumtime|floatformat:3 }}</td>
<td>{{ call.cumtime_per_call|floatformat:3 }}</td>
+ <td>{{ call.tottime|floatformat:3 }}</td>
+ <td>{{ call.tottime_per_call|floatformat:3 }}</td>
<td>{{ call.count }}</td>
</tr>
+ {% if call.line_stats_text %}
+ <tr class="djToggleDetails_{{ call.id }}{% for parent_id in call.parent_ids %} djToggleDetails_{{ parent_id }}{% endfor %}">
+ <td colspan="6">
+ <div style="padding-left: {{ call.indent }}px;"><pre>{{ call.line_stats_text }}</pre></div>
+ </td>
+ </tr>
+ {% endif %}
{% endfor %}
</tbody>
-</table>
+</table> \ No newline at end of file
diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html
index f6f231c..9b282ca 100644
--- a/debug_toolbar/templates/debug_toolbar/panels/sql.html
+++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html
@@ -1,4 +1,5 @@
{% load i18n %}
+{% load debug_toolbar_utils %}
<div class="clearfix">
<ul class="stats">
{% for alias, info in databases %}
@@ -34,7 +35,7 @@
</div>
</td>
<td class="timeline">
- <div class="djDebugTimeline"><div class="djDebugLineChart{% if query.is_slow %} djDebugLineChartWarning{% endif %}" style="left:{{ query.start_offset }}%;"><strong style="width:{{ query.width_ratio }}%;">{{ query.width_ratio }}%</strong></div></div>
+ <div class="djDebugTimeline"><div class="djDebugLineChart{% if query.is_slow %} djDebugLineChartWarning{% endif %}" style="left:{{ query.start_offset|dotted_number }}%;"><strong style="width:{{ query.width_ratio_relative|dotted_number }}%;">{{ query.width_ratio }}%</strong></div></div>
</td>
<td class="time">
{{ query.duration|floatformat:"2" }}
diff --git a/debug_toolbar/tests/templates/404.html b/debug_toolbar/templatetags/__init__.py
index e69de29..e69de29 100644
--- a/debug_toolbar/tests/templates/404.html
+++ b/debug_toolbar/templatetags/__init__.py
diff --git a/debug_toolbar/templatetags/debug_toolbar_utils.py b/debug_toolbar/templatetags/debug_toolbar_utils.py
new file mode 100644
index 0000000..6b204eb
--- /dev/null
+++ b/debug_toolbar/templatetags/debug_toolbar_utils.py
@@ -0,0 +1,11 @@
+
+from django import template
+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/tests/__init__.py b/debug_toolbar/tests/__init__.py
deleted file mode 100644
index f853b10..0000000
--- a/debug_toolbar/tests/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from tests import * \ No newline at end of file
diff --git a/debug_toolbar/tests/tests.py b/debug_toolbar/tests/tests.py
deleted file mode 100644
index fe1904a..0000000
--- a/debug_toolbar/tests/tests.py
+++ /dev/null
@@ -1,174 +0,0 @@
-from debug_toolbar.middleware import DebugToolbarMiddleware
-from debug_toolbar.panels.sql import SQLDebugPanel
-from debug_toolbar.toolbar.loader import DebugToolbar
-from debug_toolbar.utils.tracking import pre_dispatch, post_dispatch, callbacks
-
-from django.contrib.auth.models import User
-from django.test import TestCase
-
-from dingus import Dingus
-import thread
-
-class BaseTestCase(TestCase):
- def setUp(self):
- request = Dingus('request')
- toolbar = DebugToolbar(request)
- DebugToolbarMiddleware.debug_toolbars[thread.get_ident()] = toolbar
- self.toolbar = toolbar
-
-class DebugToolbarTestCase(BaseTestCase):
- urls = 'debug_toolbar.tests.urls'
-
- def test_middleware(self):
- resp = self.client.get('/execute_sql/')
- self.assertEquals(resp.status_code, 200)
-
-class SQLPanelTestCase(BaseTestCase):
- def test_recording(self):
- panel = self.toolbar.get_panel(SQLDebugPanel)
- self.assertEquals(len(panel._queries), 0)
-
- list(User.objects.all())
-
- # ensure query was logged
- self.assertEquals(len(panel._queries), 1)
- query = panel._queries[0]
- self.assertEquals(query[0], 'default')
- self.assertTrue('sql' in query[1])
- self.assertTrue('duration' in query[1])
- self.assertTrue('stacktrace' in query[1])
-
-def module_func(*args, **kwargs):
- """Used by dispatch tests"""
- return 'blah'
-
-class TrackingTestCase(BaseTestCase):
- @classmethod
- def class_method(cls, *args, **kwargs):
- return 'blah'
-
- def class_func(self, *args, **kwargs):
- """Used by dispatch tests"""
- return 'blah'
-
- def test_pre_hook(self):
- foo = {}
-
- @pre_dispatch(module_func)
- def test(**kwargs):
- foo.update(kwargs)
-
- self.assertTrue(hasattr(module_func, '__wrapped__'))
- self.assertEquals(len(callbacks['before']), 1)
-
- module_func('hi', foo='bar')
-
- self.assertTrue('sender' in foo, foo)
- # best we can do
- self.assertEquals(foo['sender'].__name__, 'module_func')
- self.assertTrue('start' in foo, foo)
- self.assertTrue(foo['start'] > 0)
- self.assertTrue('stop' not in foo, foo)
- self.assertTrue('args' in foo, foo)
- self.assertTrue(len(foo['args']), 1)
- self.assertEquals(foo['args'][0], 'hi')
- self.assertTrue('kwargs' in foo, foo)
- self.assertTrue(len(foo['kwargs']), 1)
- self.assertTrue('foo' in foo['kwargs'])
- self.assertEquals(foo['kwargs']['foo'], 'bar')
-
- callbacks['before'] = {}
-
- @pre_dispatch(TrackingTestCase.class_func)
- def test(**kwargs):
- foo.update(kwargs)
-
- self.assertTrue(hasattr(TrackingTestCase.class_func, '__wrapped__'))
- self.assertEquals(len(callbacks['before']), 1)
-
- self.class_func('hello', foo='bar')
-
- self.assertTrue('sender' in foo, foo)
- # best we can do
- self.assertEquals(foo['sender'].__name__, 'class_func')
- self.assertTrue('start' in foo, foo)
- self.assertTrue(foo['start'] > 0)
- self.assertTrue('stop' not in foo, foo)
- self.assertTrue('args' in foo, foo)
- self.assertTrue(len(foo['args']), 2)
- self.assertEquals(foo['args'][1], 'hello')
- self.assertTrue('kwargs' in foo, foo)
- self.assertTrue(len(foo['kwargs']), 1)
- self.assertTrue('foo' in foo['kwargs'])
- self.assertEquals(foo['kwargs']['foo'], 'bar')
-
- # callbacks['before'] = {}
- #
- # @pre_dispatch(TrackingTestCase.class_method)
- # def test(**kwargs):
- # foo.update(kwargs)
- #
- # self.assertTrue(hasattr(TrackingTestCase.class_method, '__wrapped__'))
- # self.assertEquals(len(callbacks['before']), 1)
- #
- # TrackingTestCase.class_method()
- #
- # self.assertTrue('sender' in foo, foo)
- # # best we can do
- # self.assertEquals(foo['sender'].__name__, 'class_method')
- # self.assertTrue('start' in foo, foo)
- # self.assertTrue('stop' not in foo, foo)
- # self.assertTrue('args' in foo, foo)
-
- def test_post_hook(self):
- foo = {}
-
- @post_dispatch(module_func)
- def test(**kwargs):
- foo.update(kwargs)
-
- self.assertTrue(hasattr(module_func, '__wrapped__'))
- self.assertEquals(len(callbacks['after']), 1)
-
- module_func('hi', foo='bar')
-
- self.assertTrue('sender' in foo, foo)
- # best we can do
- self.assertEquals(foo['sender'].__name__, 'module_func')
- self.assertTrue('start' in foo, foo)
- self.assertTrue(foo['start'] > 0)
- self.assertTrue('stop' in foo, foo)
- self.assertTrue(foo['stop'] > foo['start'])
- self.assertTrue('args' in foo, foo)
- self.assertTrue(len(foo['args']), 1)
- self.assertEquals(foo['args'][0], 'hi')
- self.assertTrue('kwargs' in foo, foo)
- self.assertTrue(len(foo['kwargs']), 1)
- self.assertTrue('foo' in foo['kwargs'])
- self.assertEquals(foo['kwargs']['foo'], 'bar')
-
- callbacks['after'] = {}
-
- @post_dispatch(TrackingTestCase.class_func)
- def test(**kwargs):
- foo.update(kwargs)
-
- self.assertTrue(hasattr(TrackingTestCase.class_func, '__wrapped__'))
- self.assertEquals(len(callbacks['after']), 1)
-
- self.class_func('hello', foo='bar')
-
- self.assertTrue('sender' in foo, foo)
- # best we can do
- self.assertEquals(foo['sender'].__name__, 'class_func')
- self.assertTrue('start' in foo, foo)
- self.assertTrue(foo['start'] > 0)
- self.assertTrue('stop' in foo, foo)
- self.assertTrue(foo['stop'] > foo['start'])
- self.assertTrue('args' in foo, foo)
- self.assertTrue(len(foo['args']), 2)
- self.assertEquals(foo['args'][1], 'hello')
- self.assertTrue('kwargs' in foo, foo)
- self.assertTrue(len(foo['kwargs']), 1)
- self.assertTrue('foo' in foo['kwargs'])
- self.assertEquals(foo['kwargs']['foo'], 'bar') \ No newline at end of file
diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py
index 3501c69..cf7a243 100644
--- a/debug_toolbar/toolbar/loader.py
+++ b/debug_toolbar/toolbar/loader.py
@@ -9,7 +9,7 @@ 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()
@@ -38,25 +38,26 @@ class DebugToolbar(object):
'debug_toolbar.panels.logger.LoggingPanel',
)
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('.')
@@ -71,14 +72,14 @@ 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
-
+
self._panels[panel_class] = panel_instance
-
+
def render_toolbar(self):
"""
Renders the overall Toolbar with panels inside.
@@ -91,5 +92,5 @@ class DebugToolbar(object):
'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/utils/__init__.py b/debug_toolbar/utils/__init__.py
index 3f035e6..c4dc160 100644
--- a/debug_toolbar/utils/__init__.py
+++ b/debug_toolbar/utils/__init__.py
@@ -36,14 +36,18 @@ def tidy_stacktrace(stack):
continue
if socketserver_path in s_path:
continue
- trace.append((path, line_no, func_name, (''.join(text)).strip()))
+ if not text:
+ text = ''
+ else:
+ text = (''.join(text)).strip()
+ trace.append((path, line_no, func_name, text))
return trace
def get_template_info(source, context_lines=3):
line = 0
upto = 0
source_lines = []
- before = during = after = ""
+ # before = during = after = ""
origin, (start, end) = source
template_source = origin.reload()
@@ -51,9 +55,9 @@ def get_template_info(source, context_lines=3):
for num, next in enumerate(linebreak_iter(template_source)):
if start >= upto and end <= next:
line = num
- before = template_source[upto:start]
- during = template_source[start:end]
- after = template_source[end:next]
+ # before = template_source[upto:start]
+ # during = template_source[start:end]
+ # after = template_source[end:next]
source_lines.append((num, template_source[upto:next]))
upto = next
@@ -71,4 +75,18 @@ def get_template_info(source, context_lines=3):
return {
'name': origin.name,
'context': context,
- } \ No newline at end of file
+ }
+
+def get_name_from_obj(obj):
+ if hasattr(obj, '__name__'):
+ name = obj.__name__
+ elif hasattr(obj, '__class__') and hasattr(obj.__class__, '__name__'):
+ name = obj.__class__.__name__
+ else:
+ name = '<unknown>'
+
+ if hasattr(obj, '__module__'):
+ module = obj.__module__
+ name = '%s.%s' % (module, name)
+
+ return name \ No newline at end of file
diff --git a/debug_toolbar/utils/sqlparse/__init__.py b/debug_toolbar/utils/sqlparse/__init__.py
index 69873ca..99db30e 100644
--- a/debug_toolbar/utils/sqlparse/__init__.py
+++ b/debug_toolbar/utils/sqlparse/__init__.py
@@ -6,10 +6,7 @@
"""Parse SQL statements."""
-__version__ = '0.1.1'
-
-
-import os
+__version__ = '0.1.3'
class SQLParseError(Exception):
@@ -56,4 +53,3 @@ def split(sql):
stack = engine.FilterStack()
stack.split_statements = True
return [unicode(stmt) for stmt in stack.run(sql)]
-
diff --git a/debug_toolbar/utils/sqlparse/engine/__init__.py b/debug_toolbar/utils/sqlparse/engine/__init__.py
index cae0793..e838a3e 100644
--- a/debug_toolbar/utils/sqlparse/engine/__init__.py
+++ b/debug_toolbar/utils/sqlparse/engine/__init__.py
@@ -5,9 +5,7 @@
"""filter"""
-import re
-
-from debug_toolbar.utils.sqlparse import lexer, SQLParseError
+from debug_toolbar.utils.sqlparse import lexer
from debug_toolbar.utils.sqlparse.engine import grouping
from debug_toolbar.utils.sqlparse.engine.filter import StatementFilter
@@ -42,8 +40,8 @@ class FilterStack(object):
stream = lexer.tokenize(sql)
# Process token stream
if self.preprocess:
- for filter_ in self.preprocess:
- stream = filter_.process(self, stream)
+ for filter_ in self.preprocess:
+ stream = filter_.process(self, stream)
if (self.stmtprocess or self.postprocess or self.split_statements
or self._grouping):
@@ -51,6 +49,7 @@ class FilterStack(object):
stream = splitter.process(self, stream)
if self._grouping:
+
def _group(stream):
for stmt in stream:
grouping.group(stmt)
@@ -58,23 +57,24 @@ class FilterStack(object):
stream = _group(stream)
if self.stmtprocess:
- def _run(stream):
+
+ def _run1(stream):
ret = []
for stmt in stream:
for filter_ in self.stmtprocess:
filter_.process(self, stmt)
ret.append(stmt)
return ret
- stream = _run(stream)
+ stream = _run1(stream)
if self.postprocess:
- def _run(stream):
+
+ def _run2(stream):
for stmt in stream:
stmt.tokens = list(self._flatten(stmt.tokens))
for filter_ in self.postprocess:
stmt = filter_.process(self, stmt)
yield stmt
- stream = _run(stream)
+ stream = _run2(stream)
return stream
-
diff --git a/debug_toolbar/utils/sqlparse/engine/filter.py b/debug_toolbar/utils/sqlparse/engine/filter.py
index 8d1c7b2..c1c0d6a 100644
--- a/debug_toolbar/utils/sqlparse/engine/filter.py
+++ b/debug_toolbar/utils/sqlparse/engine/filter.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
+from debug_toolbar.utils.sqlparse.sql import Statement, Token
from debug_toolbar.utils.sqlparse import tokens as T
-from debug_toolbar.utils.sqlparse.engine.grouping import Statement, Token
class TokenFilter(object):
@@ -21,11 +21,13 @@ class StatementFilter(TokenFilter):
self._in_declare = False
self._in_dbldollar = False
self._is_create = False
+ self._begin_depth = 0
def _reset(self):
self._in_declare = False
self._in_dbldollar = False
self._is_create = False
+ self._begin_depth = 0
def _change_splitlevel(self, ttype, value):
# PostgreSQL
@@ -41,29 +43,32 @@ class StatementFilter(TokenFilter):
return 0
# ANSI
- if ttype is not T.Keyword:
+ if ttype not in T.Keyword:
return 0
unified = value.upper()
- if unified == 'DECLARE':
+ if unified == 'DECLARE' and self._is_create:
self._in_declare = True
return 1
if unified == 'BEGIN':
- if self._in_declare:
+ self._begin_depth += 1
+ if self._in_declare: # FIXME(andi): This makes no sense.
return 0
return 0
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)
return -1
if ttype is T.Keyword.DDL and unified.startswith('CREATE'):
self._is_create = True
+ return 0
- if unified in ('IF', 'FOR') and self._is_create:
+ if unified in ('IF', 'FOR') and self._is_create and self._begin_depth > 0:
return 1
# Default
diff --git a/debug_toolbar/utils/sqlparse/engine/grouping.py b/debug_toolbar/utils/sqlparse/engine/grouping.py
index 532ccec..4e50c7b 100644
--- a/debug_toolbar/utils/sqlparse/engine/grouping.py
+++ b/debug_toolbar/utils/sqlparse/engine/grouping.py
@@ -1,16 +1,19 @@
# -*- coding: utf-8 -*-
import itertools
-import re
-import types
+from debug_toolbar.utils.sqlparse import sql
from debug_toolbar.utils.sqlparse import tokens as T
-from debug_toolbar.utils.sqlparse.sql import *
+try:
+ next
+except NameError: # Python < 2.6
+ next = lambda i: i.next()
def _group_left_right(tlist, ttype, value, cls,
check_right=lambda t: True,
+ check_left=lambda t: True,
include_semicolon=False):
[_group_left_right(sgroup, ttype, value, cls, check_right,
include_semicolon) for sgroup in tlist.get_sublists()
@@ -20,14 +23,20 @@ def _group_left_right(tlist, ttype, value, cls,
while token:
right = tlist.token_next(tlist.token_index(token))
left = tlist.token_prev(tlist.token_index(token))
- if (right is None or not check_right(right)
- or left is None):
- token = tlist.token_next_match(tlist.token_index(token)+1,
+ if right is None or not check_right(right):
+ token = tlist.token_next_match(tlist.token_index(token) + 1,
+ ttype, value)
+ elif left is None or not check_right(left):
+ token = tlist.token_next_match(tlist.token_index(token) + 1,
ttype, value)
else:
if include_semicolon:
- right = tlist.token_next_match(tlist.token_index(right),
- T.Punctuation, ';')
+ sright = tlist.token_next_match(tlist.token_index(right),
+ T.Punctuation, ';')
+ if sright is not None:
+ # only overwrite "right" if a semicolon is actually
+ # present.
+ right = sright
tokens = tlist.tokens_between(left, right)[1:]
if not isinstance(left, cls):
new = cls([left])
@@ -38,9 +47,10 @@ def _group_left_right(tlist, ttype, value, cls,
left.tokens.extend(tokens)
for t in tokens:
tlist.tokens.remove(t)
- token = tlist.token_next_match(tlist.token_index(left)+1,
+ token = tlist.token_next_match(tlist.token_index(left) + 1,
ttype, value)
+
def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value,
cls, include_semicolon=False, recurse=False):
def _find_matching(i, tl, stt, sva, ett, eva):
@@ -66,7 +76,7 @@ def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value,
end = _find_matching(tidx, tlist, start_ttype, start_value,
end_ttype, end_value)
if end is None:
- idx = tidx+1
+ idx = tidx + 1
else:
if include_semicolon:
next_ = tlist.token_next(tlist.token_index(end))
@@ -75,71 +85,102 @@ def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value,
group = tlist.group_tokens(cls, tlist.tokens_between(token, end))
_group_matching(group, start_ttype, start_value,
end_ttype, end_value, cls, include_semicolon)
- idx = tlist.token_index(group)+1
+ idx = tlist.token_index(group) + 1
token = tlist.token_next_match(idx, start_ttype, start_value)
+
def group_if(tlist):
- _group_matching(tlist, T.Keyword, 'IF', T.Keyword, 'END IF', If, True)
+ _group_matching(tlist, T.Keyword, 'IF', T.Keyword, 'END IF', sql.If, True)
+
def group_for(tlist):
- _group_matching(tlist, T.Keyword, 'FOR', T.Keyword, 'END LOOP', For, True)
+ _group_matching(tlist, T.Keyword, 'FOR', T.Keyword, 'END LOOP',
+ sql.For, True)
+
def group_as(tlist):
- _group_left_right(tlist, T.Keyword, 'AS', Identifier)
+
+ def _right_valid(token):
+ # Currently limited to DML/DDL. Maybe additional more non SQL reserved
+ # keywords should appear here (see issue8).
+ return not token.ttype in (T.DML, T.DDL)
+ _group_left_right(tlist, T.Keyword, 'AS', sql.Identifier,
+ check_right=_right_valid)
+
def group_assignment(tlist):
- _group_left_right(tlist, T.Assignment, ':=', Assignment,
+ _group_left_right(tlist, T.Assignment, ':=', sql.Assignment,
include_semicolon=True)
-def group_comparsion(tlist):
- _group_left_right(tlist, T.Operator, None, Comparsion)
+
+def group_comparison(tlist):
+
+ def _parts_valid(token):
+ return (token.ttype in (T.String.Symbol, T.Name, T.Number,
+ T.Number.Integer, T.Literal,
+ T.Literal.Number.Integer)
+ or isinstance(token, (sql.Identifier,)))
+ _group_left_right(tlist, T.Operator.Comparison, None, sql.Comparison,
+ check_left=_parts_valid, check_right=_parts_valid)
def group_case(tlist):
- _group_matching(tlist, T.Keyword, 'CASE', T.Keyword, 'END', Case,
+ _group_matching(tlist, T.Keyword, 'CASE', T.Keyword, 'END', sql.Case,
include_semicolon=True, recurse=True)
def group_identifier(tlist):
def _consume_cycle(tl, i):
- x = itertools.cycle((lambda y: y.match(T.Punctuation, '.'),
- lambda y: y.ttype in (T.String.Symbol,
- T.Name,
- T.Wildcard)))
+ x = itertools.cycle((
+ lambda y: (y.match(T.Punctuation, '.')
+ or y.ttype is T.Operator),
+ lambda y: (y.ttype in (T.String.Symbol,
+ T.Name,
+ T.Wildcard,
+ T.Literal.Number.Integer))))
for t in tl.tokens[i:]:
- if x.next()(t):
+ if next(x)(t):
yield t
else:
raise StopIteration
# bottom up approach: group subgroups first
[group_identifier(sgroup) for sgroup in tlist.get_sublists()
- if not isinstance(sgroup, Identifier)]
+ if not isinstance(sgroup, sql.Identifier)]
# real processing
idx = 0
- token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name))
+ token = tlist.token_next_by_instance(idx, sql.Function)
+ if token is None:
+ token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name))
while token:
- identifier_tokens = [token]+list(
+ identifier_tokens = [token] + list(
_consume_cycle(tlist,
- tlist.token_index(token)+1))
- group = tlist.group_tokens(Identifier, identifier_tokens)
- idx = tlist.token_index(group)+1
- token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name))
+ tlist.token_index(token) + 1))
+ if not (len(identifier_tokens) == 1
+ and isinstance(identifier_tokens[0], sql.Function)):
+ group = tlist.group_tokens(sql.Identifier, identifier_tokens)
+ idx = tlist.token_index(group) + 1
+ else:
+ idx += 1
+ token = tlist.token_next_by_instance(idx, sql.Function)
+ if token is None:
+ token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name))
def group_identifier_list(tlist):
[group_identifier_list(sgroup) for sgroup in tlist.get_sublists()
- if not isinstance(sgroup, (Identifier, IdentifierList))]
+ if not isinstance(sgroup, sql.IdentifierList)]
idx = 0
# Allowed list items
- fend1_funcs = [lambda t: isinstance(t, Identifier),
+ fend1_funcs = [lambda t: isinstance(t, (sql.Identifier, sql.Function)),
lambda t: t.is_whitespace(),
+ lambda t: t.ttype == T.Name,
lambda t: t.ttype == T.Wildcard,
lambda t: t.match(T.Keyword, 'null'),
lambda t: t.ttype == T.Number.Integer,
lambda t: t.ttype == T.String.Single,
- lambda t: isinstance(t, Comparsion),
+ lambda t: isinstance(t, sql.Comparison),
]
tcomma = tlist.token_next_match(idx, T.Punctuation, ',')
start = None
@@ -156,7 +197,7 @@ def group_identifier_list(tlist):
if not bpassed or not apassed:
# Something's wrong here, skip ahead to next ","
start = None
- tcomma = tlist.token_next_match(tlist.token_index(tcomma)+1,
+ tcomma = tlist.token_next_match(tlist.token_index(tcomma) + 1,
T.Punctuation, ',')
else:
if start is None:
@@ -165,25 +206,27 @@ def group_identifier_list(tlist):
if next_ is None or not next_.match(T.Punctuation, ','):
# Reached the end of the list
tokens = tlist.tokens_between(start, after)
- group = tlist.group_tokens(IdentifierList, tokens)
+ group = tlist.group_tokens(sql.IdentifierList, tokens)
start = None
- tcomma = tlist.token_next_match(tlist.token_index(group)+1,
+ tcomma = tlist.token_next_match(tlist.token_index(group) + 1,
T.Punctuation, ',')
else:
tcomma = next_
def group_parenthesis(tlist):
- _group_matching(tlist, T.Punctuation, '(', T.Punctuation, ')', Parenthesis)
+ _group_matching(tlist, T.Punctuation, '(', T.Punctuation, ')',
+ sql.Parenthesis)
+
def group_comments(tlist):
[group_comments(sgroup) for sgroup in tlist.get_sublists()
- if not isinstance(sgroup, Comment)]
+ if not isinstance(sgroup, sql.Comment)]
idx = 0
token = tlist.token_next_by_type(idx, T.Comment)
while token:
tidx = tlist.token_index(token)
- end = tlist.token_not_matching(tidx+1,
+ end = tlist.token_not_matching(tidx + 1,
[lambda t: t.ttype in T.Comment,
lambda t: t.is_whitespace()])
if end is None:
@@ -192,49 +235,70 @@ def group_comments(tlist):
eidx = tlist.token_index(end)
grp_tokens = tlist.tokens_between(token,
tlist.token_prev(eidx, False))
- group = tlist.group_tokens(Comment, grp_tokens)
+ group = tlist.group_tokens(sql.Comment, grp_tokens)
idx = tlist.token_index(group)
token = tlist.token_next_by_type(idx, T.Comment)
+
def group_where(tlist):
[group_where(sgroup) for sgroup in tlist.get_sublists()
- if not isinstance(sgroup, Where)]
+ if not isinstance(sgroup, sql.Where)]
idx = 0
token = tlist.token_next_match(idx, T.Keyword, 'WHERE')
stopwords = ('ORDER', 'GROUP', 'LIMIT', 'UNION')
while token:
tidx = tlist.token_index(token)
- end = tlist.token_next_match(tidx+1, T.Keyword, stopwords)
+ end = tlist.token_next_match(tidx + 1, T.Keyword, stopwords)
if end is None:
- end = tlist.tokens[-1]
+ end = tlist._groupable_tokens[-1]
else:
- end = tlist.tokens[tlist.token_index(end)-1]
- group = tlist.group_tokens(Where, tlist.tokens_between(token, end))
+ end = tlist.tokens[tlist.token_index(end) - 1]
+ group = tlist.group_tokens(sql.Where,
+ tlist.tokens_between(token, end),
+ ignore_ws=True)
idx = tlist.token_index(group)
token = tlist.token_next_match(idx, T.Keyword, 'WHERE')
+
def group_aliased(tlist):
[group_aliased(sgroup) for sgroup in tlist.get_sublists()
- if not isinstance(sgroup, Identifier)]
+ if not isinstance(sgroup, (sql.Identifier, sql.Function))]
idx = 0
- token = tlist.token_next_by_instance(idx, Identifier)
+ token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function))
while token:
next_ = tlist.token_next(tlist.token_index(token))
- if next_ is not None and isinstance(next_, Identifier):
+ if next_ is not None and isinstance(next_, (sql.Identifier, sql.Function)):
grp = tlist.tokens_between(token, next_)[1:]
token.tokens.extend(grp)
for t in grp:
tlist.tokens.remove(t)
- idx = tlist.token_index(token)+1
- token = tlist.token_next_by_instance(idx, Identifier)
+ idx = tlist.token_index(token) + 1
+ token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function))
def group_typecasts(tlist):
- _group_left_right(tlist, T.Punctuation, '::', Identifier)
+ _group_left_right(tlist, T.Punctuation, '::', sql.Identifier)
+
+
+def group_functions(tlist):
+ [group_functions(sgroup) for sgroup in tlist.get_sublists()
+ if not isinstance(sgroup, sql.Function)]
+ idx = 0
+ token = tlist.token_next_by_type(idx, T.Name)
+ while token:
+ next_ = tlist.token_next(token)
+ if not isinstance(next_, sql.Parenthesis):
+ idx = tlist.token_index(token) + 1
+ else:
+ func = tlist.group_tokens(sql.Function,
+ tlist.tokens_between(token, next_))
+ idx = tlist.token_index(func) + 1
+ token = tlist.token_next_by_type(idx, T.Name)
def group(tlist):
for func in [group_parenthesis,
+ group_functions,
group_comments,
group_where,
group_case,
@@ -243,8 +307,8 @@ def group(tlist):
group_as,
group_aliased,
group_assignment,
- group_comparsion,
+ group_comparison,
group_identifier_list,
group_if,
- group_for,]:
+ group_for]:
func(tlist)
diff --git a/debug_toolbar/utils/sqlparse/filters.py b/debug_toolbar/utils/sqlparse/filters.py
index 3c92791..2d247e7 100644
--- a/debug_toolbar/utils/sqlparse/filters.py
+++ b/debug_toolbar/utils/sqlparse/filters.py
@@ -2,7 +2,6 @@
import re
-from debug_toolbar.utils.sqlparse.engine import grouping
from debug_toolbar.utils.sqlparse import tokens as T
from debug_toolbar.utils.sqlparse import sql
@@ -19,34 +18,6 @@ class TokenFilter(Filter):
raise NotImplementedError
-# FIXME: Should be removed
-def rstrip(stream):
- buff = []
- for token in stream:
- if token.is_whitespace() and '\n' in token.value:
- # assuming there's only one \n in value
- before, rest = token.value.split('\n', 1)
- token.value = '\n%s' % rest
- buff = []
- yield token
- elif token.is_whitespace():
- buff.append(token)
- elif token.is_group():
- token.tokens = list(rstrip(token.tokens))
- # process group and look if it starts with a nl
- if token.tokens and token.tokens[0].is_whitespace():
- before, rest = token.tokens[0].value.split('\n', 1)
- token.tokens[0].value = '\n%s' % rest
- buff = []
- while buff:
- yield buff.pop(0)
- yield token
- else:
- while buff:
- yield buff.pop(0)
- yield token
-
-
# --------------------------
# token process
@@ -74,17 +45,28 @@ class KeywordCaseFilter(_CaseFilter):
class IdentifierCaseFilter(_CaseFilter):
ttype = (T.Name, T.String.Symbol)
+ def process(self, stack, stream):
+ for ttype, value in stream:
+ if ttype in self.ttype and not value.strip()[0] == '"':
+ value = self.convert(value)
+ yield ttype, value
+
# ----------------------
# statement process
class StripCommentsFilter(Filter):
+ def _get_next_comment(self, tlist):
+ # TODO(andi) Comment types should be unified, see related issue38
+ token = tlist.token_next_by_instance(0, sql.Comment)
+ if token is None:
+ token = tlist.token_next_by_type(0, T.Comment)
+ return token
+
def _process(self, tlist):
- idx = 0
- clss = set([x.__class__ for x in tlist.tokens])
- while grouping.Comment in clss:
- token = tlist.token_next_by_instance(0, grouping.Comment)
+ token = self._get_next_comment(tlist)
+ while token:
tidx = tlist.token_index(token)
prev = tlist.token_prev(tidx, False)
next_ = tlist.token_next(tidx, False)
@@ -94,10 +76,10 @@ class StripCommentsFilter(Filter):
and not prev.is_whitespace() and not next_.is_whitespace()
and not (prev.match(T.Punctuation, '(')
or next_.match(T.Punctuation, ')'))):
- tlist.tokens[tidx] = grouping.Token(T.Whitespace, ' ')
+ tlist.tokens[tidx] = sql.Token(T.Whitespace, ' ')
else:
tlist.tokens.pop(tidx)
- clss = set([x.__class__ for x in tlist.tokens])
+ token = self._get_next_comment(tlist)
def process(self, stack, stmt):
[self.process(stack, sgroup) for sgroup in stmt.get_sublists()]
@@ -149,24 +131,32 @@ class ReindentFilter(Filter):
def _get_offset(self, token):
all_ = list(self._curr_stmt.flatten())
idx = all_.index(token)
- raw = ''.join(unicode(x) for x in all_[:idx+1])
+ raw = ''.join(unicode(x) for x in all_[:idx + 1])
line = raw.splitlines()[-1]
# Now take current offset into account and return relative offset.
- full_offset = len(line)-(len(self.char*(self.width*self.indent)))
+ full_offset = len(line) - len(self.char * (self.width * self.indent))
return full_offset - self.offset
def nl(self):
# TODO: newline character should be configurable
- ws = '\n'+(self.char*((self.indent*self.width)+self.offset))
- return grouping.Token(T.Whitespace, ws)
+ ws = '\n' + (self.char * ((self.indent * self.width) + self.offset))
+ return sql.Token(T.Whitespace, ws)
def _split_kwds(self, tlist):
split_words = ('FROM', 'JOIN$', 'AND', 'OR',
'GROUP', 'ORDER', 'UNION', 'VALUES',
- 'SET')
- idx = 0
- token = tlist.token_next_match(idx, T.Keyword, split_words,
+ '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)
+ if t and t.value.upper() == 'AND':
+ t = _next_token(tlist.token_index(t)+1)
+ return t
+
+ idx = 0
+ token = _next_token(idx)
while token:
prev = tlist.token_prev(tlist.token_index(token), False)
offset = 1
@@ -181,8 +171,7 @@ class ReindentFilter(Filter):
else:
nl = self.nl()
tlist.insert_before(token, nl)
- token = tlist.token_next_match(tlist.token_index(nl)+offset,
- T.Keyword, split_words, regex=True)
+ token = _next_token(tlist.token_index(nl) + offset)
def _split_statements(self, tlist):
idx = 0
@@ -195,7 +184,7 @@ class ReindentFilter(Filter):
if prev:
nl = self.nl()
tlist.insert_before(token, nl)
- token = tlist.token_next_by_type(tlist.token_index(token)+1,
+ token = tlist.token_next_by_type(tlist.token_index(token) + 1,
(T.Keyword.DDL, T.Keyword.DML))
def _process(self, tlist):
@@ -227,9 +216,9 @@ class ReindentFilter(Filter):
def _process_identifierlist(self, tlist):
identifiers = tlist.get_identifiers()
- if len(identifiers) > 1:
+ if len(identifiers) > 1 and not tlist.within(sql.Function):
first = list(identifiers[0].flatten())[0]
- num_offset = self._get_offset(first)-len(first.value)
+ num_offset = self._get_offset(first) - len(first.value)
self.offset += num_offset
for token in identifiers[1:]:
tlist.insert_before(token, self.nl())
@@ -237,16 +226,16 @@ class ReindentFilter(Filter):
self._process_default(tlist)
def _process_case(self, tlist):
- cases = tlist.get_cases()
is_first = True
num_offset = None
case = tlist.tokens[0]
- outer_offset = self._get_offset(case)-len(case.value)
+ outer_offset = self._get_offset(case) - len(case.value)
self.offset += outer_offset
for cond, value in tlist.get_cases():
if is_first:
+ tcond = list(cond[0].flatten())[0]
is_first = False
- num_offset = self._get_offset(cond[0])-len(cond[0].value)
+ num_offset = self._get_offset(tcond) - len(tcond.value)
self.offset += num_offset
continue
if cond is None:
@@ -273,17 +262,17 @@ class ReindentFilter(Filter):
[self._process(sgroup) for sgroup in tlist.get_sublists()]
def process(self, stack, stmt):
- if isinstance(stmt, grouping.Statement):
+ if isinstance(stmt, sql.Statement):
self._curr_stmt = stmt
self._process(stmt)
- if isinstance(stmt, grouping.Statement):
+ if isinstance(stmt, sql.Statement):
if self._last_stmt is not None:
if self._last_stmt.to_unicode().endswith('\n'):
nl = '\n'
else:
nl = '\n\n'
stmt.tokens.insert(0,
- grouping.Token(T.Whitespace, nl))
+ sql.Token(T.Whitespace, nl))
if self._last_stmt != stmt:
self._last_stmt = stmt
@@ -292,7 +281,7 @@ class ReindentFilter(Filter):
class RightMarginFilter(Filter):
keep_together = (
-# grouping.TypeCast, grouping.Identifier, grouping.Alias,
+# sql.TypeCast, sql.Identifier, sql.Alias,
)
def __init__(self, width=79):
@@ -317,7 +306,7 @@ class RightMarginFilter(Filter):
indent = match.group()
else:
indent = ''
- yield grouping.Token(T.Whitespace, '\n%s' % indent)
+ yield sql.Token(T.Whitespace, '\n%s' % indent)
self.line = indent
self.line += val
yield token
@@ -349,14 +338,14 @@ class OutputPythonFilter(Filter):
def _process(self, stream, varname, count, has_nl):
if count > 1:
- yield grouping.Token(T.Whitespace, '\n')
- yield grouping.Token(T.Name, varname)
- yield grouping.Token(T.Whitespace, ' ')
- yield grouping.Token(T.Operator, '=')
- yield grouping.Token(T.Whitespace, ' ')
+ yield sql.Token(T.Whitespace, '\n')
+ yield sql.Token(T.Name, varname)
+ yield sql.Token(T.Whitespace, ' ')
+ yield sql.Token(T.Operator, '=')
+ yield sql.Token(T.Whitespace, ' ')
if has_nl:
- yield grouping.Token(T.Operator, '(')
- yield grouping.Token(T.Text, "'")
+ yield sql.Token(T.Operator, '(')
+ yield sql.Token(T.Text, "'")
cnt = 0
for token in stream:
cnt += 1
@@ -364,20 +353,20 @@ class OutputPythonFilter(Filter):
if cnt == 1:
continue
after_lb = token.value.split('\n', 1)[1]
- yield grouping.Token(T.Text, " '")
- yield grouping.Token(T.Whitespace, '\n')
- for i in range(len(varname)+4):
- yield grouping.Token(T.Whitespace, ' ')
- yield grouping.Token(T.Text, "'")
+ yield sql.Token(T.Text, " '")
+ yield sql.Token(T.Whitespace, '\n')
+ for i in range(len(varname) + 4):
+ yield sql.Token(T.Whitespace, ' ')
+ yield sql.Token(T.Text, "'")
if after_lb: # it's the indendation
- yield grouping.Token(T.Whitespace, after_lb)
+ yield sql.Token(T.Whitespace, after_lb)
continue
elif token.value and "'" in token.value:
token.value = token.value.replace("'", "\\'")
- yield grouping.Token(T.Text, token.value or '')
- yield grouping.Token(T.Text, "'")
+ yield sql.Token(T.Text, token.value or '')
+ yield sql.Token(T.Text, "'")
if has_nl:
- yield grouping.Token(T.Operator, ')')
+ yield sql.Token(T.Operator, ')')
def process(self, stack, stmt):
self.cnt += 1
@@ -398,36 +387,32 @@ class OutputPHPFilter(Filter):
def _process(self, stream, varname):
if self.count > 1:
- yield grouping.Token(T.Whitespace, '\n')
- yield grouping.Token(T.Name, varname)
- yield grouping.Token(T.Whitespace, ' ')
- yield grouping.Token(T.Operator, '=')
- yield grouping.Token(T.Whitespace, ' ')
- yield grouping.Token(T.Text, '"')
- cnt = 0
+ yield sql.Token(T.Whitespace, '\n')
+ yield sql.Token(T.Name, varname)
+ yield sql.Token(T.Whitespace, ' ')
+ yield sql.Token(T.Operator, '=')
+ yield sql.Token(T.Whitespace, ' ')
+ yield sql.Token(T.Text, '"')
for token in stream:
if token.is_whitespace() and '\n' in token.value:
-# cnt += 1
-# if cnt == 1:
-# continue
after_lb = token.value.split('\n', 1)[1]
- yield grouping.Token(T.Text, ' "')
- yield grouping.Token(T.Operator, ';')
- yield grouping.Token(T.Whitespace, '\n')
- yield grouping.Token(T.Name, varname)
- yield grouping.Token(T.Whitespace, ' ')
- yield grouping.Token(T.Punctuation, '.')
- yield grouping.Token(T.Operator, '=')
- yield grouping.Token(T.Whitespace, ' ')
- yield grouping.Token(T.Text, '"')
+ yield sql.Token(T.Text, ' "')
+ yield sql.Token(T.Operator, ';')
+ yield sql.Token(T.Whitespace, '\n')
+ yield sql.Token(T.Name, varname)
+ yield sql.Token(T.Whitespace, ' ')
+ yield sql.Token(T.Punctuation, '.')
+ yield sql.Token(T.Operator, '=')
+ yield sql.Token(T.Whitespace, ' ')
+ yield sql.Token(T.Text, '"')
if after_lb:
- yield grouping.Token(T.Text, after_lb)
+ yield sql.Token(T.Text, after_lb)
continue
elif '"' in token.value:
token.value = token.value.replace('"', '\\"')
- yield grouping.Token(T.Text, token.value)
- yield grouping.Token(T.Text, '"')
- yield grouping.Token(T.Punctuation, ';')
+ yield sql.Token(T.Text, token.value)
+ yield sql.Token(T.Text, '"')
+ yield sql.Token(T.Punctuation, ';')
def process(self, stack, stmt):
self.count += 1
@@ -437,4 +422,3 @@ class OutputPHPFilter(Filter):
varname = self.varname
stmt.tokens = tuple(self._process(stmt.tokens, varname))
return stmt
-
diff --git a/debug_toolbar/utils/sqlparse/formatter.py b/debug_toolbar/utils/sqlparse/formatter.py
index 34e9fe0..3acece9 100644
--- a/debug_toolbar/utils/sqlparse/formatter.py
+++ b/debug_toolbar/utils/sqlparse/formatter.py
@@ -76,11 +76,11 @@ def build_filter_stack(stack, options):
options: Dictionary with options validated by validate_options.
"""
# Token filter
- if 'keyword_case' in options:
+ if options.get('keyword_case', None):
stack.preprocess.append(
filters.KeywordCaseFilter(options['keyword_case']))
- if 'identifier_case' in options:
+ if options.get('identifier_case', None):
stack.preprocess.append(
filters.IdentifierCaseFilter(options['identifier_case']))
@@ -118,5 +118,3 @@ def build_filter_stack(stack, options):
stack.postprocess.append(fltr)
return stack
-
-
diff --git a/debug_toolbar/utils/sqlparse/keywords.py b/debug_toolbar/utils/sqlparse/keywords.py
index cada139..4782cfe 100644
--- a/debug_toolbar/utils/sqlparse/keywords.py
+++ b/debug_toolbar/utils/sqlparse/keywords.py
@@ -1,590 +1,565 @@
-from debug_toolbar.utils.sqlparse.tokens import *
+from debug_toolbar.utils.sqlparse import tokens
KEYWORDS = {
- 'ABORT': Keyword,
- 'ABS': Keyword,
- 'ABSOLUTE': Keyword,
- 'ACCESS': Keyword,
- 'ADA': Keyword,
- 'ADD': Keyword,
- 'ADMIN': Keyword,
- 'AFTER': Keyword,
- 'AGGREGATE': Keyword,
- 'ALIAS': Keyword,
- 'ALL': Keyword,
- 'ALLOCATE': Keyword,
- 'ANALYSE': Keyword,
- 'ANALYZE': Keyword,
- 'AND': Keyword,
- 'ANY': Keyword,
- 'ARE': Keyword,
- 'AS': Keyword,
- 'ASC': Keyword,
- 'ASENSITIVE': Keyword,
- 'ASSERTION': Keyword,
- 'ASSIGNMENT': Keyword,
- 'ASYMMETRIC': Keyword,
- 'AT': Keyword,
- 'ATOMIC': Keyword,
- 'AUTHORIZATION': Keyword,
- 'AVG': Keyword,
-
- 'BACKWARD': Keyword,
- 'BEFORE': Keyword,
- 'BEGIN': Keyword,
- 'BETWEEN': Keyword,
- 'BITVAR': Keyword,
- 'BIT_LENGTH': Keyword,
- 'BOTH': Keyword,
- 'BREADTH': Keyword,
- 'BY': Keyword,
-
-# 'C': Keyword, # most likely this is an alias
- 'CACHE': Keyword,
- 'CALL': Keyword,
- 'CALLED': Keyword,
- 'CARDINALITY': Keyword,
- 'CASCADE': Keyword,
- 'CASCADED': Keyword,
- 'CASE': Keyword,
- 'CAST': Keyword,
- 'CATALOG': Keyword,
- 'CATALOG_NAME': Keyword,
- 'CHAIN': Keyword,
- 'CHARACTERISTICS': Keyword,
- 'CHARACTER_LENGTH': Keyword,
- 'CHARACTER_SET_CATALOG': Keyword,
- 'CHARACTER_SET_NAME': Keyword,
- 'CHARACTER_SET_SCHEMA': Keyword,
- 'CHAR_LENGTH': Keyword,
- 'CHECK': Keyword,
- 'CHECKED': Keyword,
- 'CHECKPOINT': Keyword,
- 'CLASS': Keyword,
- 'CLASS_ORIGIN': Keyword,
- 'CLOB': Keyword,
- 'CLOSE': Keyword,
- 'CLUSTER': Keyword,
- 'COALSECE': Keyword,
- 'COBOL': Keyword,
- 'COLLATE': Keyword,
- 'COLLATION': Keyword,
- 'COLLATION_CATALOG': Keyword,
- 'COLLATION_NAME': Keyword,
- 'COLLATION_SCHEMA': Keyword,
- 'COLUMN': Keyword,
- 'COLUMN_NAME': Keyword,
- 'COMMAND_FUNCTION': Keyword,
- 'COMMAND_FUNCTION_CODE': Keyword,
- 'COMMENT': Keyword,
- 'COMMIT': Keyword,
- 'COMMITTED': Keyword,
- 'COMPLETION': Keyword,
- 'CONDITION_NUMBER': Keyword,
- 'CONNECT': Keyword,
- 'CONNECTION': Keyword,
- 'CONNECTION_NAME': Keyword,
- 'CONSTRAINT': Keyword,
- 'CONSTRAINTS': Keyword,
- 'CONSTRAINT_CATALOG': Keyword,
- 'CONSTRAINT_NAME': Keyword,
- 'CONSTRAINT_SCHEMA': Keyword,
- 'CONSTRUCTOR': Keyword,
- 'CONTAINS': Keyword,
- 'CONTINUE': Keyword,
- 'CONVERSION': Keyword,
- 'CONVERT': Keyword,
- 'COPY': Keyword,
- 'CORRESPONTING': Keyword,
- 'COUNT': Keyword,
- 'CREATEDB': Keyword,
- 'CREATEUSER': Keyword,
- 'CROSS': Keyword,
- 'CUBE': Keyword,
- 'CURRENT': Keyword,
- 'CURRENT_DATE': Keyword,
- 'CURRENT_PATH': Keyword,
- 'CURRENT_ROLE': Keyword,
- 'CURRENT_TIME': Keyword,
- 'CURRENT_TIMESTAMP': Keyword,
- 'CURRENT_USER': Keyword,
- 'CURSOR': Keyword,
- 'CURSOR_NAME': Keyword,
- 'CYCLE': Keyword,
-
- 'DATA': Keyword,
- 'DATABASE': Keyword,
- 'DATETIME_INTERVAL_CODE': Keyword,
- 'DATETIME_INTERVAL_PRECISION': Keyword,
- 'DAY': Keyword,
- 'DEALLOCATE': Keyword,
- 'DECLARE': Keyword,
- 'DEFAULT': Keyword,
- 'DEFAULTS': Keyword,
- 'DEFERRABLE': Keyword,
- 'DEFERRED': Keyword,
- 'DEFINED': Keyword,
- 'DEFINER': Keyword,
- 'DELIMITER': Keyword,
- 'DELIMITERS': Keyword,
- 'DEREF': Keyword,
- 'DESC': Keyword,
- 'DESCRIBE': Keyword,
- 'DESCRIPTOR': Keyword,
- 'DESTROY': Keyword,
- 'DESTRUCTOR': Keyword,
- 'DETERMINISTIC': Keyword,
- 'DIAGNOSTICS': Keyword,
- 'DICTIONARY': Keyword,
- 'DISCONNECT': Keyword,
- 'DISPATCH': Keyword,
- 'DISTINCT': Keyword,
- 'DO': Keyword,
- 'DOMAIN': Keyword,
- 'DYNAMIC': Keyword,
- 'DYNAMIC_FUNCTION': Keyword,
- 'DYNAMIC_FUNCTION_CODE': Keyword,
-
- 'EACH': Keyword,
- 'ELSE': Keyword,
- 'ENCODING': Keyword,
- 'ENCRYPTED': Keyword,
- 'END': Keyword,
- 'END-EXEC': Keyword,
- 'EQUALS': Keyword,
- 'ESCAPE': Keyword,
- 'EVERY': Keyword,
- 'EXCEPT': Keyword,
- 'ESCEPTION': Keyword,
- 'EXCLUDING': Keyword,
- 'EXCLUSIVE': Keyword,
- 'EXEC': Keyword,
- 'EXECUTE': Keyword,
- 'EXISTING': Keyword,
- 'EXISTS': Keyword,
- 'EXTERNAL': Keyword,
- 'EXTRACT': Keyword,
-
- 'FALSE': Keyword,
- 'FETCH': Keyword,
- 'FINAL': Keyword,
- 'FIRST': Keyword,
- 'FOR': Keyword,
- 'FORCE': Keyword,
- 'FOREIGN': Keyword,
- 'FORTRAN': Keyword,
- 'FORWARD': Keyword,
- 'FOUND': Keyword,
- 'FREE': Keyword,
- 'FREEZE': Keyword,
- 'FROM': Keyword,
- 'FULL': Keyword,
- 'FUNCTION': Keyword,
-
- 'G': Keyword,
- 'GENERAL': Keyword,
- 'GENERATED': Keyword,
- 'GET': Keyword,
- 'GLOBAL': Keyword,
- 'GO': Keyword,
- 'GOTO': Keyword,
- 'GRANT': Keyword,
- 'GRANTED': Keyword,
- 'GROUP': Keyword,
- 'GROUPING': Keyword,
-
- 'HANDLER': Keyword,
- 'HAVING': Keyword,
- 'HIERARCHY': Keyword,
- 'HOLD': Keyword,
- 'HOST': Keyword,
-
- 'IDENTITY': Keyword,
- 'IF': Keyword,
- 'IGNORE': Keyword,
- 'ILIKE': Keyword,
- 'IMMEDIATE': Keyword,
- 'IMMUTABLE': Keyword,
-
- 'IMPLEMENTATION': Keyword,
- 'IMPLICIT': Keyword,
- 'IN': Keyword,
- 'INCLUDING': Keyword,
- 'INCREMENT': Keyword,
- 'INDEX': Keyword,
-
- 'INDITCATOR': Keyword,
- 'INFIX': Keyword,
- 'INHERITS': Keyword,
- 'INITIALIZE': Keyword,
- 'INITIALLY': Keyword,
- 'INNER': Keyword,
- 'INOUT': Keyword,
- 'INPUT': Keyword,
- 'INSENSITIVE': Keyword,
- 'INSTANTIABLE': Keyword,
- 'INSTEAD': Keyword,
- 'INTERSECT': Keyword,
- 'INTO': Keyword,
- 'INVOKER': Keyword,
- 'IS': Keyword,
- 'ISNULL': Keyword,
- 'ISOLATION': Keyword,
- 'ITERATE': Keyword,
-
- 'JOIN': Keyword,
-
- 'K': Keyword,
- 'KEY': Keyword,
- 'KEY_MEMBER': Keyword,
- 'KEY_TYPE': Keyword,
-
- 'LANCOMPILER': Keyword,
- 'LANGUAGE': Keyword,
- 'LARGE': Keyword,
- 'LAST': Keyword,
- 'LATERAL': Keyword,
- 'LEADING': Keyword,
- 'LEFT': Keyword,
- 'LENGTH': Keyword,
- 'LESS': Keyword,
- 'LEVEL': Keyword,
- 'LIKE': Keyword,
- 'LIMIT': Keyword,
- 'LISTEN': Keyword,
- 'LOAD': Keyword,
- 'LOCAL': Keyword,
- 'LOCALTIME': Keyword,
- 'LOCALTIMESTAMP': Keyword,
- 'LOCATION': Keyword,
- 'LOCATOR': Keyword,
- 'LOCK': Keyword,
- 'LOWER': Keyword,
-
- 'M': Keyword,
- 'MAP': Keyword,
- 'MATCH': Keyword,
- 'MAX': Keyword,
- 'MAXVALUE': Keyword,
- 'MESSAGE_LENGTH': Keyword,
- 'MESSAGE_OCTET_LENGTH': Keyword,
- 'MESSAGE_TEXT': Keyword,
- 'METHOD': Keyword,
- 'MIN': Keyword,
- 'MINUTE': Keyword,
- 'MINVALUE': Keyword,
- 'MOD': Keyword,
- 'MODE': Keyword,
- 'MODIFIES': Keyword,
- 'MODIFY': Keyword,
- 'MONTH': Keyword,
- 'MORE': Keyword,
- 'MOVE': Keyword,
- 'MUMPS': Keyword,
-
- 'NAMES': Keyword,
- 'NATIONAL': Keyword,
- 'NATURAL': Keyword,
- 'NCHAR': Keyword,
- 'NCLOB': Keyword,
- 'NEW': Keyword,
- 'NEXT': Keyword,
- 'NO': Keyword,
- 'NOCREATEDB': Keyword,
- 'NOCREATEUSER': Keyword,
- 'NONE': Keyword,
- 'NOT': Keyword,
- 'NOTHING': Keyword,
- 'NOTIFY': Keyword,
- 'NOTNULL': Keyword,
- 'NULL': Keyword,
- 'NULLABLE': Keyword,
- 'NULLIF': Keyword,
-
- 'OBJECT': Keyword,
- 'OCTET_LENGTH': Keyword,
- 'OF': Keyword,
- 'OFF': Keyword,
- 'OFFSET': Keyword,
- 'OIDS': Keyword,
- 'OLD': Keyword,
- 'ON': Keyword,
- 'ONLY': Keyword,
- 'OPEN': Keyword,
- 'OPERATION': Keyword,
- 'OPERATOR': Keyword,
- 'OPTION': Keyword,
- 'OPTIONS': Keyword,
- 'OR': Keyword,
- 'ORDER': Keyword,
- 'ORDINALITY': Keyword,
- 'OUT': Keyword,
- 'OUTER': Keyword,
- 'OUTPUT': Keyword,
- 'OVERLAPS': Keyword,
- 'OVERLAY': Keyword,
- 'OVERRIDING': Keyword,
- 'OWNER': Keyword,
-
- 'PAD': Keyword,
- 'PARAMETER': Keyword,
- 'PARAMETERS': Keyword,
- 'PARAMETER_MODE': Keyword,
- 'PARAMATER_NAME': Keyword,
- 'PARAMATER_ORDINAL_POSITION': Keyword,
- 'PARAMETER_SPECIFIC_CATALOG': Keyword,
- 'PARAMETER_SPECIFIC_NAME': Keyword,
- 'PARAMATER_SPECIFIC_SCHEMA': Keyword,
- 'PARTIAL': Keyword,
- 'PASCAL': Keyword,
- 'PENDANT': Keyword,
- 'PLACING': Keyword,
- 'PLI': Keyword,
- 'POSITION': Keyword,
- 'POSTFIX': Keyword,
- 'PRECISION': Keyword,
- 'PREFIX': Keyword,
- 'PREORDER': Keyword,
- 'PREPARE': Keyword,
- 'PRESERVE': Keyword,
- 'PRIMARY': Keyword,
- 'PRIOR': Keyword,
- 'PRIVILEGES': Keyword,
- 'PROCEDURAL': Keyword,
- 'PROCEDURE': Keyword,
- 'PUBLIC': Keyword,
-
- 'RAISE': Keyword,
- 'READ': Keyword,
- 'READS': Keyword,
- 'RECHECK': Keyword,
- 'RECURSIVE': Keyword,
- 'REF': Keyword,
- 'REFERENCES': Keyword,
- 'REFERENCING': Keyword,
- 'REINDEX': Keyword,
- 'RELATIVE': Keyword,
- 'RENAME': Keyword,
- 'REPEATABLE': Keyword,
- 'REPLACE': Keyword,
- 'RESET': Keyword,
- 'RESTART': Keyword,
- 'RESTRICT': Keyword,
- 'RESULT': Keyword,
- 'RETURN': Keyword,
- 'RETURNED_LENGTH': Keyword,
- 'RETURNED_OCTET_LENGTH': Keyword,
- 'RETURNED_SQLSTATE': Keyword,
- 'RETURNS': Keyword,
- 'REVOKE': Keyword,
- 'RIGHT': Keyword,
- 'ROLE': Keyword,
- 'ROLLBACK': Keyword,
- 'ROLLUP': Keyword,
- 'ROUTINE': Keyword,
- 'ROUTINE_CATALOG': Keyword,
- 'ROUTINE_NAME': Keyword,
- 'ROUTINE_SCHEMA': Keyword,
- 'ROW': Keyword,
- 'ROWS': Keyword,
- 'ROW_COUNT': Keyword,
- 'RULE': Keyword,
-
- 'SAVE_POINT': Keyword,
- 'SCALE': Keyword,
- 'SCHEMA': Keyword,
- 'SCHEMA_NAME': Keyword,
- 'SCOPE': Keyword,
- 'SCROLL': Keyword,
- 'SEARCH': Keyword,
- 'SECOND': Keyword,
- 'SECURITY': Keyword,
- 'SELF': Keyword,
- 'SENSITIVE': Keyword,
- 'SERIALIZABLE': Keyword,
- 'SERVER_NAME': Keyword,
- 'SESSION': Keyword,
- 'SESSION_USER': Keyword,
- 'SETOF': Keyword,
- 'SETS': Keyword,
- 'SHARE': Keyword,
- 'SHOW': Keyword,
- 'SIMILAR': Keyword,
- 'SIMPLE': Keyword,
- 'SIZE': Keyword,
- 'SOME': Keyword,
- 'SOURCE': Keyword,
- 'SPACE': Keyword,
- 'SPECIFIC': Keyword,
- 'SPECIFICTYPE': Keyword,
- 'SPECIFIC_NAME': Keyword,
- 'SQL': Keyword,
- 'SQLCODE': Keyword,
- 'SQLERROR': Keyword,
- 'SQLEXCEPTION': Keyword,
- 'SQLSTATE': Keyword,
- 'SQLWARNINIG': Keyword,
- 'STABLE': Keyword,
- 'START': Keyword,
- 'STATE': Keyword,
- 'STATEMENT': Keyword,
- 'STATIC': Keyword,
- 'STATISTICS': Keyword,
- 'STDIN': Keyword,
- 'STDOUT': Keyword,
- 'STORAGE': Keyword,
- 'STRICT': Keyword,
- 'STRUCTURE': Keyword,
- 'STYPE': Keyword,
- 'SUBCLASS_ORIGIN': Keyword,
- 'SUBLIST': Keyword,
- 'SUBSTRING': Keyword,
- 'SUM': Keyword,
- 'SYMMETRIC': Keyword,
- 'SYSID': Keyword,
- 'SYSTEM': Keyword,
- 'SYSTEM_USER': Keyword,
-
- 'TABLE': Keyword,
- 'TABLE_NAME': Keyword,
- ' TEMP': Keyword,
- 'TEMPLATE': Keyword,
- 'TEMPORARY': Keyword,
- 'TERMINATE': Keyword,
- 'THAN': Keyword,
- 'THEN': Keyword,
- 'TIMESTAMP': Keyword,
- 'TIMEZONE_HOUR': Keyword,
- 'TIMEZONE_MINUTE': Keyword,
- 'TO': Keyword,
- 'TOAST': Keyword,
- 'TRAILING': Keyword,
- 'TRANSATION': Keyword,
- 'TRANSACTIONS_COMMITTED': Keyword,
- 'TRANSACTIONS_ROLLED_BACK': Keyword,
- 'TRANSATION_ACTIVE': Keyword,
- 'TRANSFORM': Keyword,
- 'TRANSFORMS': Keyword,
- 'TRANSLATE': Keyword,
- 'TRANSLATION': Keyword,
- 'TREAT': Keyword,
- 'TRIGGER': Keyword,
- 'TRIGGER_CATALOG': Keyword,
- 'TRIGGER_NAME': Keyword,
- 'TRIGGER_SCHEMA': Keyword,
- 'TRIM': Keyword,
- 'TRUE': Keyword,
- 'TRUNCATE': Keyword,
- 'TRUSTED': Keyword,
- 'TYPE': Keyword,
-
- 'UNCOMMITTED': Keyword,
- 'UNDER': Keyword,
- 'UNENCRYPTED': Keyword,
- 'UNION': Keyword,
- 'UNIQUE': Keyword,
- 'UNKNOWN': Keyword,
- 'UNLISTEN': Keyword,
- 'UNNAMED': Keyword,
- 'UNNEST': Keyword,
- 'UNTIL': Keyword,
- 'UPPER': Keyword,
- 'USAGE': Keyword,
- 'USER': Keyword,
- 'USER_DEFINED_TYPE_CATALOG': Keyword,
- 'USER_DEFINED_TYPE_NAME': Keyword,
- 'USER_DEFINED_TYPE_SCHEMA': Keyword,
- 'USING': Keyword,
-
- 'VACUUM': Keyword,
- 'VALID': Keyword,
- 'VALIDATOR': Keyword,
- 'VALUES': Keyword,
- 'VARIABLE': Keyword,
- 'VERBOSE': Keyword,
- 'VERSION': Keyword,
- 'VIEW': Keyword,
- 'VOLATILE': Keyword,
-
- 'WHEN': Keyword,
- 'WHENEVER': Keyword,
- 'WHERE': Keyword,
- 'WITH': Keyword,
- 'WITHOUT': Keyword,
- 'WORK': Keyword,
- 'WRITE': Keyword,
-
- 'YEAR': Keyword,
-
- 'ZONE': Keyword,
-
-
- 'ARRAY': Name.Builtin,
- 'BIGINT': Name.Builtin,
- 'BINARY': Name.Builtin,
- 'BIT': Name.Builtin,
- 'BLOB': Name.Builtin,
- 'BOOLEAN': Name.Builtin,
- 'CHAR': Name.Builtin,
- 'CHARACTER': Name.Builtin,
- 'DATE': Name.Builtin,
- 'DEC': Name.Builtin,
- 'DECIMAL': Name.Builtin,
- 'FLOAT': Name.Builtin,
- 'INT': Name.Builtin,
- 'INTEGER': Name.Builtin,
- 'INTERVAL': Name.Builtin,
- 'NUMBER': Name.Builtin,
- 'NUMERIC': Name.Builtin,
- 'REAL': Name.Builtin,
- 'SERIAL': Name.Builtin,
- 'SMALLINT': Name.Builtin,
- 'VARCHAR': Name.Builtin,
- 'VARYING': Name.Builtin,
- 'INT8': Name.Builtin,
- 'SERIAL8': Name.Builtin,
- 'TEXT': Name.Builtin,
+ 'ABORT': tokens.Keyword,
+ 'ABS': tokens.Keyword,
+ 'ABSOLUTE': tokens.Keyword,
+ 'ACCESS': tokens.Keyword,
+ 'ADA': tokens.Keyword,
+ 'ADD': tokens.Keyword,
+ 'ADMIN': tokens.Keyword,
+ 'AFTER': tokens.Keyword,
+ 'AGGREGATE': tokens.Keyword,
+ 'ALIAS': tokens.Keyword,
+ 'ALL': tokens.Keyword,
+ 'ALLOCATE': tokens.Keyword,
+ 'ANALYSE': tokens.Keyword,
+ 'ANALYZE': tokens.Keyword,
+ 'ANY': tokens.Keyword,
+ 'ARE': tokens.Keyword,
+ 'ASC': tokens.Keyword,
+ 'ASENSITIVE': tokens.Keyword,
+ 'ASSERTION': tokens.Keyword,
+ 'ASSIGNMENT': tokens.Keyword,
+ 'ASYMMETRIC': tokens.Keyword,
+ 'AT': tokens.Keyword,
+ 'ATOMIC': tokens.Keyword,
+ 'AUTHORIZATION': tokens.Keyword,
+ 'AVG': tokens.Keyword,
+
+ 'BACKWARD': tokens.Keyword,
+ 'BEFORE': tokens.Keyword,
+ 'BEGIN': tokens.Keyword,
+ 'BETWEEN': tokens.Keyword,
+ 'BITVAR': tokens.Keyword,
+ 'BIT_LENGTH': tokens.Keyword,
+ 'BOTH': tokens.Keyword,
+ 'BREADTH': tokens.Keyword,
+
+# 'C': tokens.Keyword, # most likely this is an alias
+ 'CACHE': tokens.Keyword,
+ 'CALL': tokens.Keyword,
+ 'CALLED': tokens.Keyword,
+ 'CARDINALITY': tokens.Keyword,
+ 'CASCADE': tokens.Keyword,
+ 'CASCADED': tokens.Keyword,
+ 'CAST': tokens.Keyword,
+ 'CATALOG': tokens.Keyword,
+ 'CATALOG_NAME': tokens.Keyword,
+ 'CHAIN': tokens.Keyword,
+ 'CHARACTERISTICS': tokens.Keyword,
+ 'CHARACTER_LENGTH': tokens.Keyword,
+ 'CHARACTER_SET_CATALOG': tokens.Keyword,
+ 'CHARACTER_SET_NAME': tokens.Keyword,
+ 'CHARACTER_SET_SCHEMA': tokens.Keyword,
+ 'CHAR_LENGTH': tokens.Keyword,
+ 'CHECK': tokens.Keyword,
+ 'CHECKED': tokens.Keyword,
+ 'CHECKPOINT': tokens.Keyword,
+ 'CLASS': tokens.Keyword,
+ 'CLASS_ORIGIN': tokens.Keyword,
+ 'CLOB': tokens.Keyword,
+ 'CLOSE': tokens.Keyword,
+ 'CLUSTER': tokens.Keyword,
+ 'COALSECE': tokens.Keyword,
+ 'COBOL': tokens.Keyword,
+ 'COLLATE': tokens.Keyword,
+ 'COLLATION': tokens.Keyword,
+ 'COLLATION_CATALOG': tokens.Keyword,
+ 'COLLATION_NAME': tokens.Keyword,
+ 'COLLATION_SCHEMA': tokens.Keyword,
+ 'COLUMN': tokens.Keyword,
+ 'COLUMN_NAME': tokens.Keyword,
+ 'COMMAND_FUNCTION': tokens.Keyword,
+ 'COMMAND_FUNCTION_CODE': tokens.Keyword,
+ 'COMMENT': tokens.Keyword,
+ 'COMMIT': tokens.Keyword,
+ 'COMMITTED': tokens.Keyword,
+ 'COMPLETION': tokens.Keyword,
+ 'CONDITION_NUMBER': tokens.Keyword,
+ 'CONNECT': tokens.Keyword,
+ 'CONNECTION': tokens.Keyword,
+ 'CONNECTION_NAME': tokens.Keyword,
+ 'CONSTRAINT': tokens.Keyword,
+ 'CONSTRAINTS': tokens.Keyword,
+ 'CONSTRAINT_CATALOG': tokens.Keyword,
+ 'CONSTRAINT_NAME': tokens.Keyword,
+ 'CONSTRAINT_SCHEMA': tokens.Keyword,
+ 'CONSTRUCTOR': tokens.Keyword,
+ 'CONTAINS': tokens.Keyword,
+ 'CONTINUE': tokens.Keyword,
+ 'CONVERSION': tokens.Keyword,
+ 'CONVERT': tokens.Keyword,
+ 'COPY': tokens.Keyword,
+ 'CORRESPONTING': tokens.Keyword,
+ 'COUNT': tokens.Keyword,
+ 'CREATEDB': tokens.Keyword,
+ 'CREATEUSER': tokens.Keyword,
+ 'CROSS': tokens.Keyword,
+ 'CUBE': tokens.Keyword,
+ 'CURRENT': tokens.Keyword,
+ 'CURRENT_DATE': tokens.Keyword,
+ 'CURRENT_PATH': tokens.Keyword,
+ 'CURRENT_ROLE': tokens.Keyword,
+ 'CURRENT_TIME': tokens.Keyword,
+ 'CURRENT_TIMESTAMP': tokens.Keyword,
+ 'CURRENT_USER': tokens.Keyword,
+ 'CURSOR': tokens.Keyword,
+ 'CURSOR_NAME': tokens.Keyword,
+ 'CYCLE': tokens.Keyword,
+
+ 'DATA': tokens.Keyword,
+ 'DATABASE': tokens.Keyword,
+ 'DATETIME_INTERVAL_CODE': tokens.Keyword,
+ 'DATETIME_INTERVAL_PRECISION': tokens.Keyword,
+ 'DAY': tokens.Keyword,
+ 'DEALLOCATE': tokens.Keyword,
+ 'DECLARE': tokens.Keyword,
+ 'DEFAULT': tokens.Keyword,
+ 'DEFAULTS': tokens.Keyword,
+ 'DEFERRABLE': tokens.Keyword,
+ 'DEFERRED': tokens.Keyword,
+ 'DEFINED': tokens.Keyword,
+ 'DEFINER': tokens.Keyword,
+ 'DELIMITER': tokens.Keyword,
+ 'DELIMITERS': tokens.Keyword,
+ 'DEREF': tokens.Keyword,
+ 'DESC': tokens.Keyword,
+ 'DESCRIBE': tokens.Keyword,
+ 'DESCRIPTOR': tokens.Keyword,
+ 'DESTROY': tokens.Keyword,
+ 'DESTRUCTOR': tokens.Keyword,
+ 'DETERMINISTIC': tokens.Keyword,
+ 'DIAGNOSTICS': tokens.Keyword,
+ 'DICTIONARY': tokens.Keyword,
+ 'DISCONNECT': tokens.Keyword,
+ 'DISPATCH': tokens.Keyword,
+ 'DO': tokens.Keyword,
+ 'DOMAIN': tokens.Keyword,
+ 'DYNAMIC': tokens.Keyword,
+ 'DYNAMIC_FUNCTION': tokens.Keyword,
+ 'DYNAMIC_FUNCTION_CODE': tokens.Keyword,
+
+ 'EACH': tokens.Keyword,
+ 'ENCODING': tokens.Keyword,
+ 'ENCRYPTED': tokens.Keyword,
+ 'END-EXEC': tokens.Keyword,
+ 'EQUALS': tokens.Keyword,
+ 'ESCAPE': tokens.Keyword,
+ 'EVERY': tokens.Keyword,
+ 'EXCEPT': tokens.Keyword,
+ 'ESCEPTION': tokens.Keyword,
+ 'EXCLUDING': tokens.Keyword,
+ 'EXCLUSIVE': tokens.Keyword,
+ 'EXEC': tokens.Keyword,
+ 'EXECUTE': tokens.Keyword,
+ 'EXISTING': tokens.Keyword,
+ 'EXISTS': tokens.Keyword,
+ 'EXTERNAL': tokens.Keyword,
+ 'EXTRACT': tokens.Keyword,
+
+ 'FALSE': tokens.Keyword,
+ 'FETCH': tokens.Keyword,
+ 'FINAL': tokens.Keyword,
+ 'FIRST': tokens.Keyword,
+ 'FORCE': tokens.Keyword,
+ 'FOREIGN': tokens.Keyword,
+ 'FORTRAN': tokens.Keyword,
+ 'FORWARD': tokens.Keyword,
+ 'FOUND': tokens.Keyword,
+ 'FREE': tokens.Keyword,
+ 'FREEZE': tokens.Keyword,
+ 'FULL': tokens.Keyword,
+ 'FUNCTION': tokens.Keyword,
+
+# 'G': tokens.Keyword,
+ 'GENERAL': tokens.Keyword,
+ 'GENERATED': tokens.Keyword,
+ 'GET': tokens.Keyword,
+ 'GLOBAL': tokens.Keyword,
+ 'GO': tokens.Keyword,
+ 'GOTO': tokens.Keyword,
+ 'GRANT': tokens.Keyword,
+ 'GRANTED': tokens.Keyword,
+ 'GROUPING': tokens.Keyword,
+
+ 'HANDLER': tokens.Keyword,
+ 'HAVING': tokens.Keyword,
+ 'HIERARCHY': tokens.Keyword,
+ 'HOLD': tokens.Keyword,
+ 'HOST': tokens.Keyword,
+
+ 'IDENTITY': tokens.Keyword,
+ 'IGNORE': tokens.Keyword,
+ 'ILIKE': tokens.Keyword,
+ 'IMMEDIATE': tokens.Keyword,
+ 'IMMUTABLE': tokens.Keyword,
+
+ 'IMPLEMENTATION': tokens.Keyword,
+ 'IMPLICIT': tokens.Keyword,
+ 'INCLUDING': tokens.Keyword,
+ 'INCREMENT': tokens.Keyword,
+ 'INDEX': tokens.Keyword,
+
+ 'INDITCATOR': tokens.Keyword,
+ 'INFIX': tokens.Keyword,
+ 'INHERITS': tokens.Keyword,
+ 'INITIALIZE': tokens.Keyword,
+ 'INITIALLY': tokens.Keyword,
+ 'INOUT': tokens.Keyword,
+ 'INPUT': tokens.Keyword,
+ 'INSENSITIVE': tokens.Keyword,
+ 'INSTANTIABLE': tokens.Keyword,
+ 'INSTEAD': tokens.Keyword,
+ 'INTERSECT': tokens.Keyword,
+ 'INTO': tokens.Keyword,
+ 'INVOKER': tokens.Keyword,
+ 'IS': tokens.Keyword,
+ 'ISNULL': tokens.Keyword,
+ 'ISOLATION': tokens.Keyword,
+ 'ITERATE': tokens.Keyword,
+
+# 'K': tokens.Keyword,
+ 'KEY': tokens.Keyword,
+ 'KEY_MEMBER': tokens.Keyword,
+ 'KEY_TYPE': tokens.Keyword,
+
+ 'LANCOMPILER': tokens.Keyword,
+ 'LANGUAGE': tokens.Keyword,
+ 'LARGE': tokens.Keyword,
+ 'LAST': tokens.Keyword,
+ 'LATERAL': tokens.Keyword,
+ 'LEADING': tokens.Keyword,
+ 'LENGTH': tokens.Keyword,
+ 'LESS': tokens.Keyword,
+ 'LEVEL': tokens.Keyword,
+ 'LIMIT': tokens.Keyword,
+ 'LISTEN': tokens.Keyword,
+ 'LOAD': tokens.Keyword,
+ 'LOCAL': tokens.Keyword,
+ 'LOCALTIME': tokens.Keyword,
+ 'LOCALTIMESTAMP': tokens.Keyword,
+ 'LOCATION': tokens.Keyword,
+ 'LOCATOR': tokens.Keyword,
+ 'LOCK': tokens.Keyword,
+ 'LOWER': tokens.Keyword,
+
+# 'M': tokens.Keyword,
+ 'MAP': tokens.Keyword,
+ 'MATCH': tokens.Keyword,
+ 'MAXVALUE': tokens.Keyword,
+ 'MESSAGE_LENGTH': tokens.Keyword,
+ 'MESSAGE_OCTET_LENGTH': tokens.Keyword,
+ 'MESSAGE_TEXT': tokens.Keyword,
+ 'METHOD': tokens.Keyword,
+ 'MINUTE': tokens.Keyword,
+ 'MINVALUE': tokens.Keyword,
+ 'MOD': tokens.Keyword,
+ 'MODE': tokens.Keyword,
+ 'MODIFIES': tokens.Keyword,
+ 'MODIFY': tokens.Keyword,
+ 'MONTH': tokens.Keyword,
+ 'MORE': tokens.Keyword,
+ 'MOVE': tokens.Keyword,
+ 'MUMPS': tokens.Keyword,
+
+ 'NAMES': tokens.Keyword,
+ 'NATIONAL': tokens.Keyword,
+ 'NATURAL': tokens.Keyword,
+ 'NCHAR': tokens.Keyword,
+ 'NCLOB': tokens.Keyword,
+ 'NEW': tokens.Keyword,
+ 'NEXT': tokens.Keyword,
+ 'NO': tokens.Keyword,
+ 'NOCREATEDB': tokens.Keyword,
+ 'NOCREATEUSER': tokens.Keyword,
+ 'NONE': tokens.Keyword,
+ 'NOT': tokens.Keyword,
+ 'NOTHING': tokens.Keyword,
+ 'NOTIFY': tokens.Keyword,
+ 'NOTNULL': tokens.Keyword,
+ 'NULL': tokens.Keyword,
+ 'NULLABLE': tokens.Keyword,
+ 'NULLIF': tokens.Keyword,
+
+ 'OBJECT': tokens.Keyword,
+ 'OCTET_LENGTH': tokens.Keyword,
+ 'OF': tokens.Keyword,
+ 'OFF': tokens.Keyword,
+ 'OFFSET': tokens.Keyword,
+ 'OIDS': tokens.Keyword,
+ 'OLD': tokens.Keyword,
+ 'ONLY': tokens.Keyword,
+ 'OPEN': tokens.Keyword,
+ 'OPERATION': tokens.Keyword,
+ 'OPERATOR': tokens.Keyword,
+ 'OPTION': tokens.Keyword,
+ 'OPTIONS': tokens.Keyword,
+ 'ORDINALITY': tokens.Keyword,
+ 'OUT': tokens.Keyword,
+ 'OUTPUT': tokens.Keyword,
+ 'OVERLAPS': tokens.Keyword,
+ 'OVERLAY': tokens.Keyword,
+ 'OVERRIDING': tokens.Keyword,
+ 'OWNER': tokens.Keyword,
+
+ 'PAD': tokens.Keyword,
+ 'PARAMETER': tokens.Keyword,
+ 'PARAMETERS': tokens.Keyword,
+ 'PARAMETER_MODE': tokens.Keyword,
+ 'PARAMATER_NAME': tokens.Keyword,
+ 'PARAMATER_ORDINAL_POSITION': tokens.Keyword,
+ 'PARAMETER_SPECIFIC_CATALOG': tokens.Keyword,
+ 'PARAMETER_SPECIFIC_NAME': tokens.Keyword,
+ 'PARAMATER_SPECIFIC_SCHEMA': tokens.Keyword,
+ 'PARTIAL': tokens.Keyword,
+ 'PASCAL': tokens.Keyword,
+ 'PENDANT': tokens.Keyword,
+ 'PLACING': tokens.Keyword,
+ 'PLI': tokens.Keyword,
+ 'POSITION': tokens.Keyword,
+ 'POSTFIX': tokens.Keyword,
+ 'PRECISION': tokens.Keyword,
+ 'PREFIX': tokens.Keyword,
+ 'PREORDER': tokens.Keyword,
+ 'PREPARE': tokens.Keyword,
+ 'PRESERVE': tokens.Keyword,
+ 'PRIMARY': tokens.Keyword,
+ 'PRIOR': tokens.Keyword,
+ 'PRIVILEGES': tokens.Keyword,
+ 'PROCEDURAL': tokens.Keyword,
+ 'PROCEDURE': tokens.Keyword,
+ 'PUBLIC': tokens.Keyword,
+
+ 'RAISE': tokens.Keyword,
+ 'READ': tokens.Keyword,
+ 'READS': tokens.Keyword,
+ 'RECHECK': tokens.Keyword,
+ 'RECURSIVE': tokens.Keyword,
+ 'REF': tokens.Keyword,
+ 'REFERENCES': tokens.Keyword,
+ 'REFERENCING': tokens.Keyword,
+ 'REINDEX': tokens.Keyword,
+ 'RELATIVE': tokens.Keyword,
+ 'RENAME': tokens.Keyword,
+ 'REPEATABLE': tokens.Keyword,
+ 'RESET': tokens.Keyword,
+ 'RESTART': tokens.Keyword,
+ 'RESTRICT': tokens.Keyword,
+ 'RESULT': tokens.Keyword,
+ 'RETURN': tokens.Keyword,
+ 'RETURNED_LENGTH': tokens.Keyword,
+ 'RETURNED_OCTET_LENGTH': tokens.Keyword,
+ 'RETURNED_SQLSTATE': tokens.Keyword,
+ 'RETURNS': tokens.Keyword,
+ 'REVOKE': tokens.Keyword,
+ 'RIGHT': tokens.Keyword,
+ 'ROLE': tokens.Keyword,
+ 'ROLLBACK': tokens.Keyword,
+ 'ROLLUP': tokens.Keyword,
+ 'ROUTINE': tokens.Keyword,
+ 'ROUTINE_CATALOG': tokens.Keyword,
+ 'ROUTINE_NAME': tokens.Keyword,
+ 'ROUTINE_SCHEMA': tokens.Keyword,
+ 'ROW': tokens.Keyword,
+ 'ROWS': tokens.Keyword,
+ 'ROW_COUNT': tokens.Keyword,
+ 'RULE': tokens.Keyword,
+
+ 'SAVE_POINT': tokens.Keyword,
+ 'SCALE': tokens.Keyword,
+ 'SCHEMA': tokens.Keyword,
+ 'SCHEMA_NAME': tokens.Keyword,
+ 'SCOPE': tokens.Keyword,
+ 'SCROLL': tokens.Keyword,
+ 'SEARCH': tokens.Keyword,
+ 'SECOND': tokens.Keyword,
+ 'SECURITY': tokens.Keyword,
+ 'SELF': tokens.Keyword,
+ 'SENSITIVE': tokens.Keyword,
+ 'SERIALIZABLE': tokens.Keyword,
+ 'SERVER_NAME': tokens.Keyword,
+ 'SESSION': tokens.Keyword,
+ 'SESSION_USER': tokens.Keyword,
+ 'SETOF': tokens.Keyword,
+ 'SETS': tokens.Keyword,
+ 'SHARE': tokens.Keyword,
+ 'SHOW': tokens.Keyword,
+ 'SIMILAR': tokens.Keyword,
+ 'SIMPLE': tokens.Keyword,
+ 'SIZE': tokens.Keyword,
+ 'SOME': tokens.Keyword,
+ 'SOURCE': tokens.Keyword,
+ 'SPACE': tokens.Keyword,
+ 'SPECIFIC': tokens.Keyword,
+ 'SPECIFICTYPE': tokens.Keyword,
+ 'SPECIFIC_NAME': tokens.Keyword,
+ 'SQL': tokens.Keyword,
+ 'SQLCODE': tokens.Keyword,
+ 'SQLERROR': tokens.Keyword,
+ 'SQLEXCEPTION': tokens.Keyword,
+ 'SQLSTATE': tokens.Keyword,
+ 'SQLWARNING': tokens.Keyword,
+ 'STABLE': tokens.Keyword,
+ 'START': tokens.Keyword,
+ 'STATE': tokens.Keyword,
+ 'STATEMENT': tokens.Keyword,
+ 'STATIC': tokens.Keyword,
+ 'STATISTICS': tokens.Keyword,
+ 'STDIN': tokens.Keyword,
+ 'STDOUT': tokens.Keyword,
+ 'STORAGE': tokens.Keyword,
+ 'STRICT': tokens.Keyword,
+ 'STRUCTURE': tokens.Keyword,
+ 'STYPE': tokens.Keyword,
+ 'SUBCLASS_ORIGIN': tokens.Keyword,
+ 'SUBLIST': tokens.Keyword,
+ 'SUBSTRING': tokens.Keyword,
+ 'SUM': tokens.Keyword,
+ 'SYMMETRIC': tokens.Keyword,
+ 'SYSID': tokens.Keyword,
+ 'SYSTEM': tokens.Keyword,
+ 'SYSTEM_USER': tokens.Keyword,
+
+ 'TABLE': tokens.Keyword,
+ 'TABLE_NAME': tokens.Keyword,
+ ' TEMP': tokens.Keyword,
+ 'TEMPLATE': tokens.Keyword,
+ 'TEMPORARY': tokens.Keyword,
+ 'TERMINATE': tokens.Keyword,
+ 'THAN': tokens.Keyword,
+ 'TIMESTAMP': tokens.Keyword,
+ 'TIMEZONE_HOUR': tokens.Keyword,
+ 'TIMEZONE_MINUTE': tokens.Keyword,
+ 'TO': tokens.Keyword,
+ 'TOAST': tokens.Keyword,
+ 'TRAILING': tokens.Keyword,
+ 'TRANSATION': tokens.Keyword,
+ 'TRANSACTIONS_COMMITTED': tokens.Keyword,
+ 'TRANSACTIONS_ROLLED_BACK': tokens.Keyword,
+ 'TRANSATION_ACTIVE': tokens.Keyword,
+ 'TRANSFORM': tokens.Keyword,
+ 'TRANSFORMS': tokens.Keyword,
+ 'TRANSLATE': tokens.Keyword,
+ 'TRANSLATION': tokens.Keyword,
+ 'TREAT': tokens.Keyword,
+ 'TRIGGER': tokens.Keyword,
+ 'TRIGGER_CATALOG': tokens.Keyword,
+ 'TRIGGER_NAME': tokens.Keyword,
+ 'TRIGGER_SCHEMA': tokens.Keyword,
+ 'TRIM': tokens.Keyword,
+ 'TRUE': tokens.Keyword,
+ 'TRUNCATE': tokens.Keyword,
+ 'TRUSTED': tokens.Keyword,
+ 'TYPE': tokens.Keyword,
+
+ 'UNCOMMITTED': tokens.Keyword,
+ 'UNDER': tokens.Keyword,
+ 'UNENCRYPTED': tokens.Keyword,
+ 'UNION': tokens.Keyword,
+ 'UNIQUE': tokens.Keyword,
+ 'UNKNOWN': tokens.Keyword,
+ 'UNLISTEN': tokens.Keyword,
+ 'UNNAMED': tokens.Keyword,
+ 'UNNEST': tokens.Keyword,
+ 'UNTIL': tokens.Keyword,
+ 'UPPER': tokens.Keyword,
+ 'USAGE': tokens.Keyword,
+ 'USER': tokens.Keyword,
+ 'USER_DEFINED_TYPE_CATALOG': tokens.Keyword,
+ 'USER_DEFINED_TYPE_NAME': tokens.Keyword,
+ 'USER_DEFINED_TYPE_SCHEMA': tokens.Keyword,
+ 'USING': tokens.Keyword,
+
+ 'VACUUM': tokens.Keyword,
+ 'VALID': tokens.Keyword,
+ 'VALIDATOR': tokens.Keyword,
+ 'VALUES': tokens.Keyword,
+ 'VARIABLE': tokens.Keyword,
+ 'VERBOSE': tokens.Keyword,
+ 'VERSION': tokens.Keyword,
+ 'VIEW': tokens.Keyword,
+ 'VOLATILE': tokens.Keyword,
+
+ 'WHENEVER': tokens.Keyword,
+ 'WITH': tokens.Keyword,
+ 'WITHOUT': tokens.Keyword,
+ 'WORK': tokens.Keyword,
+ 'WRITE': tokens.Keyword,
+
+ 'YEAR': tokens.Keyword,
+
+ 'ZONE': tokens.Keyword,
+
+
+ 'ARRAY': tokens.Name.Builtin,
+ 'BIGINT': tokens.Name.Builtin,
+ 'BINARY': tokens.Name.Builtin,
+ 'BIT': tokens.Name.Builtin,
+ 'BLOB': tokens.Name.Builtin,
+ 'BOOLEAN': tokens.Name.Builtin,
+ 'CHAR': tokens.Name.Builtin,
+ 'CHARACTER': tokens.Name.Builtin,
+ 'DATE': tokens.Name.Builtin,
+ 'DEC': tokens.Name.Builtin,
+ 'DECIMAL': tokens.Name.Builtin,
+ 'FLOAT': tokens.Name.Builtin,
+ 'INT': tokens.Name.Builtin,
+ 'INTEGER': tokens.Name.Builtin,
+ 'INTERVAL': tokens.Name.Builtin,
+ 'LONG': tokens.Name.Builtin,
+ 'NUMBER': tokens.Name.Builtin,
+ 'NUMERIC': tokens.Name.Builtin,
+ 'REAL': tokens.Name.Builtin,
+ 'SERIAL': tokens.Name.Builtin,
+ 'SMALLINT': tokens.Name.Builtin,
+ 'VARCHAR': tokens.Name.Builtin,
+ 'VARCHAR2': tokens.Name.Builtin,
+ 'VARYING': tokens.Name.Builtin,
+ 'INT8': tokens.Name.Builtin,
+ 'SERIAL8': tokens.Name.Builtin,
+ 'TEXT': tokens.Name.Builtin,
}
KEYWORDS_COMMON = {
- 'SELECT': Keyword.DML,
- 'INSERT': Keyword.DML,
- 'DELETE': Keyword.DML,
- 'UPDATE': Keyword.DML,
- 'DROP': Keyword.DDL,
- 'CREATE': Keyword.DDL,
- 'ALTER': Keyword.DDL,
-
- 'WHERE': Keyword,
- 'FROM': Keyword,
- 'INNER': Keyword,
- 'JOIN': Keyword,
- 'AND': Keyword,
- 'OR': Keyword,
- 'LIKE': Keyword,
- 'ON': Keyword,
- 'IN': Keyword,
- 'SET': Keyword,
-
- 'BY': Keyword,
- 'GROUP': Keyword,
- 'ORDER': Keyword,
- 'LEFT': Keyword,
- 'OUTER': Keyword,
-
- 'IF': Keyword,
- 'END': Keyword,
- 'THEN': Keyword,
- 'LOOP': Keyword,
- 'AS': Keyword,
- 'ELSE': Keyword,
- 'FOR': Keyword,
-
- 'CASE': Keyword,
- 'WHEN': Keyword,
- 'MIN': Keyword,
- 'MAX': Keyword,
- 'DISTINCT': Keyword,
-
+ 'SELECT': tokens.Keyword.DML,
+ 'INSERT': tokens.Keyword.DML,
+ 'DELETE': tokens.Keyword.DML,
+ 'UPDATE': tokens.Keyword.DML,
+ 'REPLACE': tokens.Keyword.DML,
+ 'DROP': tokens.Keyword.DDL,
+ 'CREATE': tokens.Keyword.DDL,
+ 'ALTER': tokens.Keyword.DDL,
+
+ 'WHERE': tokens.Keyword,
+ 'FROM': tokens.Keyword,
+ 'INNER': tokens.Keyword,
+ 'JOIN': tokens.Keyword,
+ 'AND': tokens.Keyword,
+ 'OR': tokens.Keyword,
+ 'LIKE': tokens.Keyword,
+ 'ON': tokens.Keyword,
+ 'IN': tokens.Keyword,
+ 'SET': tokens.Keyword,
+
+ 'BY': tokens.Keyword,
+ 'GROUP': tokens.Keyword,
+ 'ORDER': tokens.Keyword,
+ 'LEFT': tokens.Keyword,
+ 'OUTER': tokens.Keyword,
+
+ 'IF': tokens.Keyword,
+ 'END': tokens.Keyword,
+ 'THEN': tokens.Keyword,
+ 'LOOP': tokens.Keyword,
+ 'AS': tokens.Keyword,
+ 'ELSE': tokens.Keyword,
+ 'FOR': tokens.Keyword,
+
+ 'CASE': tokens.Keyword,
+ 'WHEN': tokens.Keyword,
+ 'MIN': tokens.Keyword,
+ 'MAX': tokens.Keyword,
+ 'DISTINCT': tokens.Keyword,
}
diff --git a/debug_toolbar/utils/sqlparse/lexer.py b/debug_toolbar/utils/sqlparse/lexer.py
index 727a4ff..ae3fc2e 100644
--- a/debug_toolbar/utils/sqlparse/lexer.py
+++ b/debug_toolbar/utils/sqlparse/lexer.py
@@ -14,14 +14,14 @@
import re
+from debug_toolbar.utils.sqlparse import tokens
from debug_toolbar.utils.sqlparse.keywords import KEYWORDS, KEYWORDS_COMMON
-from debug_toolbar.utils.sqlparse.tokens import *
-from debug_toolbar.utils.sqlparse.tokens import _TokenType
class include(str):
pass
+
class combined(tuple):
"""Indicates a state combined from multiple states."""
@@ -32,9 +32,10 @@ class combined(tuple):
# tuple.__init__ doesn't do anything
pass
+
def is_keyword(value):
test = value.upper()
- return KEYWORDS_COMMON.get(test, KEYWORDS.get(test, Name)), value
+ return KEYWORDS_COMMON.get(test, KEYWORDS.get(test, tokens.Name)), value
def apply_filters(stream, filters, lexer=None):
@@ -43,9 +44,11 @@ def apply_filters(stream, filters, lexer=None):
a stream. If lexer is given it's forwarded to the
filter, otherwise the filter receives `None`.
"""
+
def _apply(filter_, stream):
for token in filter_.filter(lexer, stream):
yield token
+
for filter_ in filters:
stream = _apply(filter_, stream)
return stream
@@ -62,13 +65,14 @@ class LexerMeta(type):
assert state[0] != '#', "invalid state name %r" % state
if state in processed:
return processed[state]
- tokens = processed[state] = []
+ tokenlist = processed[state] = []
rflags = cls.flags
for tdef in unprocessed[state]:
if isinstance(tdef, include):
# it's a state reference
assert tdef != state, "circular state reference %r" % state
- tokens.extend(cls._process_state(unprocessed, processed, str(tdef)))
+ tokenlist.extend(cls._process_state(
+ unprocessed, processed, str(tdef)))
continue
assert type(tdef) is tuple, "wrong rule def %r" % tdef
@@ -76,11 +80,13 @@ class LexerMeta(type):
try:
rex = re.compile(tdef[0], rflags).match
except Exception, err:
- raise ValueError("uncompilable regex %r in state %r of %r: %s" %
- (tdef[0], state, cls, err))
+ raise ValueError(("uncompilable regex %r in state"
+ " %r of %r: %s"
+ % (tdef[0], state, cls, err)))
- assert type(tdef[1]) is _TokenType or callable(tdef[1]), \
- 'token type must be simple type or callable, not %r' % (tdef[1],)
+ assert type(tdef[1]) is tokens._TokenType or callable(tdef[1]), \
+ ('token type must be simple type or callable, not %r'
+ % (tdef[1],))
if len(tdef) == 2:
new_state = None
@@ -104,7 +110,8 @@ class LexerMeta(type):
cls._tmpname += 1
itokens = []
for istate in tdef2:
- assert istate != state, 'circular state ref %r' % istate
+ assert istate != state, \
+ 'circular state ref %r' % istate
itokens.extend(cls._process_state(unprocessed,
processed, istate))
processed[new_state] = itokens
@@ -118,8 +125,8 @@ class LexerMeta(type):
new_state = tdef2
else:
assert False, 'unknown new state def %r' % tdef2
- tokens.append((rex, tdef[1], new_state))
- return tokens
+ tokenlist.append((rex, tdef[1], new_state))
+ return tokenlist
def process_tokendef(cls):
cls._all_tokens = {}
@@ -143,9 +150,7 @@ class LexerMeta(type):
return type.__call__(cls, *args, **kwds)
-
-
-class Lexer:
+class Lexer(object):
__metaclass__ = LexerMeta
@@ -157,41 +162,53 @@ class Lexer:
tokens = {
'root': [
- (r'--.*?(\r|\n|\r\n)', Comment.Single),
- (r'(\r|\n|\r\n)', Newline),
- (r'\s+', Whitespace),
- (r'/\*', Comment.Multiline, 'multiline-comments'),
- (r':=', Assignment),
- (r'::', Punctuation),
- (r'[*]', Wildcard),
- (r"`(``|[^`])*`", Name),
- (r"´(´´|[^´])*´", Name),
- (r'@[a-zA-Z_][a-zA-Z0-9_]+', Name),
- (r'[+/<>=~!@#%^&|`?^-]', Operator),
- (r'[0-9]+', Number.Integer),
+ (r'--.*?(\r\n|\r|\n)', tokens.Comment.Single),
+ # $ matches *before* newline, therefore we have two patterns
+ # to match Comment.Single
+ (r'--.*?$', tokens.Comment.Single),
+ (r'(\r|\n|\r\n)', tokens.Newline),
+ (r'\s+', tokens.Whitespace),
+ (r'/\*', tokens.Comment.Multiline, 'multiline-comments'),
+ (r':=', tokens.Assignment),
+ (r'::', tokens.Punctuation),
+ (r'[*]', tokens.Wildcard),
+ (r'CASE\b', tokens.Keyword), # extended CASE(foo)
+ (r"`(``|[^`])*`", tokens.Name),
+ (r"´(´´|[^´])*´", tokens.Name),
+ (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', tokens.Name.Builtin),
+ (r'\?{1}', tokens.Name.Placeholder),
+ (r'[$:?%][a-zA-Z0-9_]+[^$:?%]?', tokens.Name.Placeholder),
+ (r'@[a-zA-Z_][a-zA-Z0-9_]+', tokens.Name),
+ (r'[a-zA-Z_][a-zA-Z0-9_]*(?=[.(])', tokens.Name), # see issue39
+ (r'[<>=~!]+', tokens.Operator.Comparison),
+ (r'[+/@#%^&|`?^-]+', tokens.Operator),
+ (r'0x[0-9a-fA-F]+', tokens.Number.Hexadecimal),
+ (r'[0-9]*\.[0-9]+', tokens.Number.Float),
+ (r'[0-9]+', tokens.Number.Integer),
# TODO: Backslash escapes?
- (r"'(''|[^'])*'", String.Single),
- (r'"(""|[^"])*"', String.Symbol), # not a real string literal in ANSI SQL
- (r'(LEFT |RIGHT )?(INNER |OUTER )?JOIN', Keyword),
- (r'END( IF| LOOP)?', Keyword),
- (r'CREATE( OR REPLACE)?', Keyword.DDL),
+ (r"(''|'.*?[^\\]')", tokens.String.Single),
+ # not a real string literal in ANSI SQL:
+ (r'(""|".*?[^\\]")', tokens.String.Symbol),
+ (r'(\[.*[^\]]\])', tokens.Name),
+ (r'(LEFT |RIGHT )?(INNER |OUTER )?JOIN\b', tokens.Keyword),
+ (r'END( IF| LOOP)?\b', tokens.Keyword),
+ (r'NOT NULL\b', tokens.Keyword),
+ (r'CREATE( OR REPLACE)?\b', tokens.Keyword.DDL),
(r'[a-zA-Z_][a-zA-Z0-9_]*', is_keyword),
- (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', Name.Builtin),
- (r'[;:()\[\],\.]', Punctuation),
+ (r'[;:()\[\],\.]', tokens.Punctuation),
],
'multiline-comments': [
- (r'/\*', Comment.Multiline, 'multiline-comments'),
- (r'\*/', Comment.Multiline, '#pop'),
- (r'[^/\*]+', Comment.Multiline),
- (r'[/*]', Comment.Multiline)
- ]
- }
+ (r'/\*', tokens.Comment.Multiline, 'multiline-comments'),
+ (r'\*/', tokens.Comment.Multiline, '#pop'),
+ (r'[^/\*]+', tokens.Comment.Multiline),
+ (r'[/*]', tokens.Comment.Multiline)
+ ]}
def __init__(self):
self.filters = []
def add_filter(self, filter_, **options):
- from sqlparse.filters import Filter
+ from debug_toolbar.utils.sqlparse.filters import Filter
if not isinstance(filter_, Filter):
filter_ = filter_(**options)
self.filters.append(filter_)
@@ -241,7 +258,6 @@ class Lexer:
stream = apply_filters(stream, self.filters, self)
return stream
-
def get_tokens_unprocessed(self, text, stack=('root',)):
"""
Split ``text`` into (tokentype, text) pairs.
@@ -261,7 +277,7 @@ class Lexer:
value = m.group()
if value in known_names:
yield pos, known_names[value], value
- elif type(action) is _TokenType:
+ elif type(action) is tokens._TokenType:
yield pos, action, value
elif hasattr(action, '__call__'):
ttype, value = action(value)
@@ -297,9 +313,9 @@ class Lexer:
pos += 1
statestack = ['root']
statetokens = tokendefs['root']
- yield pos, Text, u'\n'
+ yield pos, tokens.Text, u'\n'
continue
- yield pos, Error, text[pos]
+ yield pos, tokens.Error, text[pos]
pos += 1
except IndexError:
break
diff --git a/debug_toolbar/utils/sqlparse/sql.py b/debug_toolbar/utils/sqlparse/sql.py
index 5bbb977..55bf804 100644
--- a/debug_toolbar/utils/sqlparse/sql.py
+++ b/debug_toolbar/utils/sqlparse/sql.py
@@ -3,7 +3,6 @@
"""This module contains classes representing syntactical elements of SQL."""
import re
-import types
from debug_toolbar.utils.sqlparse import tokens as T
@@ -16,14 +15,15 @@ class Token(object):
the type of the token.
"""
- __slots__ = ('value', 'ttype',)
+ __slots__ = ('value', 'ttype', 'parent')
def __init__(self, ttype, value):
self.value = value
self.ttype = ttype
+ self.parent = None
def __str__(self):
- return unicode(self).encode('latin-1')
+ return unicode(self).encode('utf-8')
def __repr__(self):
short = self._get_repr_value()
@@ -43,7 +43,7 @@ class Token(object):
def _get_repr_value(self):
raw = unicode(self)
if len(raw) > 7:
- short = raw[:6]+u'...'
+ short = raw[:6] + u'...'
else:
short = raw
return re.sub('\s+', ' ', short)
@@ -59,12 +59,12 @@ class Token(object):
type.
*values* is a list of possible values for this token. The values
are OR'ed together so if only one of the values matches ``True``
- is returned. Except for keyword tokens the comparsion is
+ is returned. Except for keyword tokens the comparison is
case-sensitive. For convenience it's ok to pass in a single string.
If *regex* is ``True`` (default is ``False``) the given values are
treated as regular expressions.
"""
- type_matched = self.ttype in ttype
+ type_matched = self.ttype is ttype
if not type_matched or values is None:
return type_matched
if isinstance(values, basestring):
@@ -79,7 +79,7 @@ class Token(object):
return True
return False
else:
- if self.ttype is T.Keyword:
+ if self.ttype in T.Keyword:
values = set([v.upper() for v in values])
return self.value.upper() in values
else:
@@ -93,6 +93,32 @@ class Token(object):
"""Return ``True`` if this token is a whitespace token."""
return self.ttype and self.ttype in T.Whitespace
+ def within(self, group_cls):
+ """Returns ``True`` if this token is within *group_cls*.
+
+ Use this method for example to check if an identifier is within
+ a function: ``t.within(sql.Function)``.
+ """
+ parent = self.parent
+ while parent:
+ if isinstance(parent, group_cls):
+ return True
+ parent = parent.parent
+ return False
+
+ def is_child_of(self, other):
+ """Returns ``True`` if this token is a direct child of *other*."""
+ return self.parent == other
+
+ def has_ancestor(self, other):
+ """Returns ``True`` if *other* is in this tokens ancestry."""
+ parent = self.parent
+ while parent:
+ if parent == other:
+ return True
+ parent = parent.parent
+ return False
+
class TokenList(Token):
"""A group of tokens.
@@ -113,24 +139,24 @@ class TokenList(Token):
return ''.join(unicode(x) for x in self.flatten())
def __str__(self):
- return unicode(self).encode('latin-1')
+ return unicode(self).encode('utf-8')
def _get_repr_name(self):
return self.__class__.__name__
- ## def _pprint_tree(self, max_depth=None, depth=0):
- ## """Pretty-print the object tree."""
- ## indent = ' '*(depth*2)
- ## for token in self.tokens:
- ## if token.is_group():
- ## pre = ' | '
- ## else:
- ## pre = ' | '
- ## print '%s%s%s \'%s\'' % (indent, pre, token._get_repr_name(),
- ## token._get_repr_value())
- ## if (token.is_group() and max_depth is not None
- ## and depth < max_depth):
- ## token._pprint_tree(max_depth, depth+1)
+ def _pprint_tree(self, max_depth=None, depth=0):
+ """Pretty-print the object tree."""
+ indent = ' '*(depth*2)
+ for idx, token in enumerate(self.tokens):
+ if token.is_group():
+ pre = ' +-'
+ else:
+ pre = ' | '
+ print '%s%s%d %s \'%s\'' % (indent, pre, idx,
+ 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)
def flatten(self):
"""Generator yielding ungrouped tokens.
@@ -150,6 +176,10 @@ class TokenList(Token):
def get_sublists(self):
return [x for x in self.tokens if isinstance(x, TokenList)]
+ @property
+ def _groupable_tokens(self):
+ return self.tokens
+
def token_first(self, ignore_whitespace=True):
"""Returns the first child token.
@@ -190,7 +220,7 @@ class TokenList(Token):
def token_next_match(self, idx, ttype, value, regex=False):
"""Returns next token where it's ``match`` method returns ``True``."""
- if type(idx) != types.IntType:
+ if not isinstance(idx, int):
idx = self.token_index(idx)
for token in self.tokens[idx:]:
if token.match(ttype, value, regex):
@@ -202,8 +232,8 @@ class TokenList(Token):
passed = False
for func in funcs:
if func(token):
- passed = True
- break
+ passed = True
+ break
if not passed:
return token
return None
@@ -241,7 +271,7 @@ class TokenList(Token):
return None
if not isinstance(idx, int):
idx = self.token_index(idx)
- while idx < len(self.tokens)-1:
+ while idx < len(self.tokens) - 1:
idx += 1
if self.tokens[idx].is_whitespace() and skip_ws:
continue
@@ -257,18 +287,27 @@ class TokenList(Token):
If *exclude_end* is ``True`` (default is ``False``) the end token
is included too.
"""
+ # FIXME(andi): rename exclude_end to inlcude_end
if exclude_end:
offset = 0
else:
offset = 1
- return self.tokens[self.token_index(start):self.token_index(end)+offset]
+ end_idx = self.token_index(end) + offset
+ start_idx = self.token_index(start)
+ return self.tokens[start_idx:end_idx]
- def group_tokens(self, grp_cls, tokens):
+ def group_tokens(self, grp_cls, tokens, ignore_ws=False):
"""Replace tokens by an instance of *grp_cls*."""
idx = self.token_index(tokens[0])
+ if ignore_ws:
+ while tokens and tokens[-1].is_whitespace():
+ tokens = tokens[:-1]
for t in tokens:
self.tokens.remove(t)
grp = grp_cls(tokens)
+ for token in tokens:
+ token.parent = grp
+ grp.parent = self
self.tokens.insert(idx, grp)
return grp
@@ -290,7 +329,11 @@ class Statement(TokenList):
isn't a DML or DDL keyword "UNKNOWN" is returned.
"""
first_token = self.token_first()
- if first_token.ttype in (T.Keyword.DML, T.Keyword.DDL):
+ if first_token is None:
+ # An "empty" statement that either has not tokens at all
+ # or only whitespace tokens.
+ return 'UNKNOWN'
+ elif first_token.ttype in (T.Keyword.DML, T.Keyword.DDL):
return first_token.value.upper()
else:
return 'UNKNOWN'
@@ -397,27 +440,36 @@ class Parenthesis(TokenList):
"""Tokens between parenthesis."""
__slots__ = ('value', 'ttype', 'tokens')
+ @property
+ def _groupable_tokens(self):
+ return self.tokens[1:-1]
+
class Assignment(TokenList):
"""An assignment like 'var := val;'"""
__slots__ = ('value', 'ttype', 'tokens')
+
class If(TokenList):
"""An 'if' clause with possible 'else if' or 'else' parts."""
__slots__ = ('value', 'ttype', 'tokens')
+
class For(TokenList):
"""A 'FOR' loop."""
__slots__ = ('value', 'ttype', 'tokens')
-class Comparsion(TokenList):
- """A comparsion used for example in WHERE clauses."""
+
+class Comparison(TokenList):
+ """A comparison used for example in WHERE clauses."""
__slots__ = ('value', 'ttype', 'tokens')
+
class Comment(TokenList):
"""A comment."""
__slots__ = ('value', 'ttype', 'tokens')
+
class Where(TokenList):
"""A WHERE clause."""
__slots__ = ('value', 'ttype', 'tokens')
@@ -434,9 +486,12 @@ class Case(TokenList):
If an ELSE exists condition is None.
"""
ret = []
- in_condition = in_value = False
+ in_value = False
+ in_condition = True
for token in self.tokens:
- if token.match(T.Keyword, 'WHEN'):
+ if token.match(T.Keyword, 'CASE'):
+ continue
+ elif token.match(T.Keyword, 'WHEN'):
ret.append(([], []))
in_condition = True
in_value = False
@@ -450,8 +505,25 @@ class Case(TokenList):
elif token.match(T.Keyword, 'END'):
in_condition = False
in_value = False
+ if (in_condition or in_value) and not ret:
+ # First condition withou preceding WHEN
+ ret.append(([], []))
if in_condition:
ret[-1][0].append(token)
elif in_value:
ret[-1][1].append(token)
return ret
+
+
+class Function(TokenList):
+ """A function or procedure call."""
+
+ __slots__ = ('value', 'ttype', 'tokens')
+
+ def get_parameters(self):
+ """Return a list of parameters."""
+ parenthesis = self.tokens[-1]
+ for t in parenthesis.tokens:
+ if isinstance(t, IdentifierList):
+ return t.get_identifiers()
+ return []
diff --git a/debug_toolbar/utils/sqlparse/tokens.py b/debug_toolbar/utils/sqlparse/tokens.py
index 2c63c41..01a9b89 100644
--- a/debug_toolbar/utils/sqlparse/tokens.py
+++ b/debug_toolbar/utils/sqlparse/tokens.py
@@ -9,11 +9,6 @@
"""Tokens"""
-try:
- set
-except NameError:
- from sets import Set as set
-
class _TokenType(tuple):
parent = None
@@ -27,22 +22,14 @@ class _TokenType(tuple):
buf.reverse()
return buf
- def __init__(self, *args):
- # no need to call super.__init__
- self.subtypes = set()
-
def __contains__(self, val):
- return self is val or (
- type(val) is self.__class__ and
- val[:len(self)] == self
- )
+ return val is not None and (self is val or val[:len(self)] == self)
def __getattr__(self, val):
if not val or not val[0].isupper():
return tuple.__getattribute__(self, val)
new = _TokenType(self + (val,))
setattr(self, val, new)
- self.subtypes.add(new)
new.parent = self
return new
@@ -53,30 +40,31 @@ class _TokenType(tuple):
return 'Token' + (self and '.' or '') + '.'.join(self)
-Token = _TokenType()
+Token = _TokenType()
# Special token types
-Text = Token.Text
-Whitespace = Text.Whitespace
-Newline = Whitespace.Newline
-Error = Token.Error
+Text = Token.Text
+Whitespace = Text.Whitespace
+Newline = Whitespace.Newline
+Error = Token.Error
# Text that doesn't belong to this lexer (e.g. HTML in PHP)
-Other = Token.Other
+Other = Token.Other
# Common token types for source code
-Keyword = Token.Keyword
-Name = Token.Name
-Literal = Token.Literal
-String = Literal.String
-Number = Literal.Number
+Keyword = Token.Keyword
+Name = Token.Name
+Literal = Token.Literal
+String = Literal.String
+Number = Literal.Number
Punctuation = Token.Punctuation
-Operator = Token.Operator
-Wildcard = Token.Wildcard
-Comment = Token.Comment
-Assignment = Token.Assignement
+Operator = Token.Operator
+Comparison = Operator.Comparison
+Wildcard = Token.Wildcard
+Comment = Token.Comment
+Assignment = Token.Assignement
# Generic types for non-source code
-Generic = Token.Generic
+Generic = Token.Generic
# String and some others are not direct childs of Token.
# alias them:
@@ -93,39 +81,3 @@ Group = Token.Group
Group.Parenthesis = Token.Group.Parenthesis
Group.Comment = Token.Group.Comment
Group.Where = Token.Group.Where
-
-
-def is_token_subtype(ttype, other):
- """
- Return True if ``ttype`` is a subtype of ``other``.
-
- exists for backwards compatibility. use ``ttype in other`` now.
- """
- return ttype in other
-
-
-def string_to_tokentype(s):
- """
- Convert a string into a token type::
-
- >>> string_to_token('String.Double')
- Token.Literal.String.Double
- >>> string_to_token('Token.Literal.Number')
- Token.Literal.Number
- >>> string_to_token('')
- Token
-
- Tokens that are already tokens are returned unchanged:
-
- >>> string_to_token(String)
- Token.Literal.String
- """
- if isinstance(s, _TokenType):
- return s
- if not s:
- return Token
- node = Token
- for item in s.split('.'):
- node = getattr(node, item)
- return node
-
diff --git a/debug_toolbar/utils/tracking/db.py b/debug_toolbar/utils/tracking/db.py
index 7ffacef..97a9241 100644
--- a/debug_toolbar/utils/tracking/db.py
+++ b/debug_toolbar/utils/tracking/db.py
@@ -2,6 +2,7 @@ import inspect
import sys
from datetime import datetime
+from threading import local
from django.conf import settings
from django.template import Node
@@ -16,7 +17,41 @@ from debug_toolbar.utils.compat.db import connections
SQL_WARNING_THRESHOLD = getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}) \
.get('SQL_WARNING_THRESHOLD', 500)
-class CursorWrapper(object):
+class SQLQueryTriggered(Exception):
+ """Thrown when template panel triggers a query"""
+ pass
+
+class ThreadLocalState(local):
+ def __init__(self):
+ self.enabled = True
+
+ @property
+ def Wrapper(self):
+ if self.enabled:
+ return NormalCursorWrapper
+ return ExceptionCursorWrapper
+
+ def recording(self, v):
+ self.enabled = v
+
+state = ThreadLocalState()
+recording = state.recording # export function
+
+def CursorWrapper(*args, **kwds): # behave like a class
+ return state.Wrapper(*args, **kwds)
+
+class ExceptionCursorWrapper(object):
+ """
+ Wraps a cursor and raises an exception on any operation.
+ Used in Templates panel.
+ """
+ def __init__(self, cursor, db, logger):
+ pass
+
+ def __getattr__(self, attr):
+ raise SQLQueryTriggered()
+
+class NormalCursorWrapper(object):
"""
Wraps a cursor and logs queries.
"""
@@ -103,4 +138,4 @@ class CursorWrapper(object):
return getattr(self.cursor, attr)
def __iter__(self):
- return iter(self.cursor) \ No newline at end of file
+ return iter(self.cursor)
diff --git a/example/example.db b/example/example.db
index 1339622..7acdc0d 100644
--- a/example/example.db
+++ b/example/example.db
Binary files differ
diff --git a/example/settings.py b/example/settings.py
index 11b0117..fac99af 100644
--- a/example/settings.py
+++ b/example/settings.py
@@ -41,7 +41,11 @@ DEBUG_TOOLBAR_PANELS = (
'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
'debug_toolbar.panels.sql.SQLDebugPanel',
'debug_toolbar.panels.template.TemplateDebugPanel',
- #'debug_toolbar.panels.cache.CacheDebugPanel',
+ 'debug_toolbar.panels.cache.CacheDebugPanel',
'debug_toolbar.panels.signals.SignalDebugPanel',
'debug_toolbar.panels.logger.LoggingPanel',
-) \ No newline at end of file
+)
+
+CACHE_BACKEND = 'dummy://'
+#CACHE_BACKEND = 'memcached://127.0.0.1:11211'
+
diff --git a/example/templates/index.html b/example/templates/index.html
index 6fd3a92..d7d8a2b 100644
--- a/example/templates/index.html
+++ b/example/templates/index.html
@@ -1,16 +1,18 @@
+{% load cache %}
<html>
<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8">
- <title>Index of Tests</title>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Index of Tests</title>
</head>
<body>
- <h1>Index of Tests</h1>
- <ul>
- <li><a href="/jquery/index/">jQuery 1.2.6</a></li>
- <li><a href="/mootools/index/">MooTools 1.2.4</a></li>
- <li><a href="/prototype/index/">Prototype 1.6.1</a></li>
- </ul>
-
+ <h1>Index of Tests</h1>
+ {% cache 10 index_cache %}
+ <ul>
+ <li><a href="/jquery/index/">jQuery 1.2.6</a></li>
+ <li><a href="/mootools/index/">MooTools 1.2.4</a></li>
+ <li><a href="/prototype/index/">Prototype 1.6.1</a></li>
+ </ul>
+ {% endcache %}
</body>
</html>
diff --git a/debug_toolbar/runtests.py b/runtests.py
index f16882a..dc5f6d0 100644
--- a/debug_toolbar/runtests.py
+++ b/runtests.py
@@ -1,8 +1,9 @@
#!/usr/bin/env python
import sys
from os.path import dirname, abspath
+from optparse import OptionParser
-from django.conf import settings
+from django.conf import settings, global_settings
if not settings.configured:
settings.configure(
@@ -16,32 +17,37 @@ if not settings.configured:
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
-
+
'debug_toolbar',
- 'debug_toolbar.tests',
+ 'tests',
],
+ MIDDLEWARE_CLASSES = global_settings.MIDDLEWARE_CLASSES + (
+ 'debug_toolbar.middleware.DebugToolbarMiddleware',
+ ),
ROOT_URLCONF='',
DEBUG=False,
SITE_ID=1,
)
- import djcelery
- djcelery.setup_loader()
from django.test.simple import run_tests
-def runtests(*test_args):
+def runtests(*test_args, **kwargs):
if 'south' in settings.INSTALLED_APPS:
from south.management.commands import patch_for_test_db_setup
patch_for_test_db_setup()
-
+
if not test_args:
- test_args = ['debug_toolbar']
+ test_args = ['tests']
parent = dirname(abspath(__file__))
sys.path.insert(0, parent)
- failures = run_tests(test_args, verbosity=1, interactive=True)
+ failures = run_tests(test_args, verbosity=kwargs.get('verbosity', 1), interactive=kwargs.get('interactive', False), failfast=kwargs.get('failfast'))
sys.exit(failures)
-
if __name__ == '__main__':
- runtests(*sys.argv[1:]) \ No newline at end of file
+ parser = OptionParser()
+ parser.add_option('--failfast', action='store_true', default=False, dest='failfast')
+
+ (options, args) = parser.parse_args()
+
+ runtests(failfast=options.failfast, *args) \ No newline at end of file
diff --git a/setup.py b/setup.py
index 773c5c6..b6b9449 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name='django-debug-toolbar',
- version='0.8.6-dev',
+ version='0.9.0-dev',
description='A configurable set of panels that display various debug information about the current request/response.',
long_description=open('README.rst').read(),
# Get more strings from http://www.python.org/pypi?:action=list_classifiers
@@ -11,12 +11,12 @@ setup(
url='https://github.com/django-debug-toolbar/django-debug-toolbar',
download_url='https://github.com/django-debug-toolbar/django-debug-toolbar/downloads',
license='BSD',
- packages=find_packages(exclude=['ez_setup']),
+ packages=find_packages(exclude=('ez_setup', 'tests', 'example')),
tests_require=[
- 'django',
+ 'django>=1.1,<1.4',
'dingus',
],
- test_suite='debug_toolbar.runtests.runtests',
+ test_suite='runtests.runtests',
include_package_data=True,
zip_safe=False, # because we're including media that Django needs
classifiers=[
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/tests/models.py b/tests/models.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/models.py
diff --git a/tests/templates/404.html b/tests/templates/404.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/templates/404.html
diff --git a/tests/tests.py b/tests/tests.py
new file mode 100644
index 0000000..154615a
--- /dev/null
+++ b/tests/tests.py
@@ -0,0 +1,354 @@
+from debug_toolbar.middleware import DebugToolbarMiddleware
+from debug_toolbar.panels.sql import SQLDebugPanel
+from debug_toolbar.panels.request_vars import RequestVarsDebugPanel
+from debug_toolbar.panels.template import TemplateDebugPanel
+from debug_toolbar.toolbar.loader import DebugToolbar
+from debug_toolbar.utils import get_name_from_obj
+from debug_toolbar.utils.tracking import pre_dispatch, post_dispatch, callbacks
+
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.http import HttpResponse
+from django.test import TestCase
+from django.template import Template, Context
+
+from dingus import Dingus
+import thread
+
+
+class Settings(object):
+ """Allows you to define settings that are required for this function to work"""
+
+ NotDefined = object()
+
+ def __init__(self, **overrides):
+ self.overrides = overrides
+ self._orig = {}
+
+ def __enter__(self):
+ for k, v in self.overrides.iteritems():
+ self._orig[k] = getattr(settings, k, self.NotDefined)
+ setattr(settings, k, v)
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ for k, v in self._orig.iteritems():
+ if v is self.NotDefined:
+ delattr(settings, k)
+ else:
+ setattr(settings, k, v)
+
+class BaseTestCase(TestCase):
+ def setUp(self):
+ request = Dingus('request')
+ response = Dingus('response')
+ toolbar = DebugToolbar(request)
+
+ DebugToolbarMiddleware.debug_toolbars[thread.get_ident()] = toolbar
+
+ self.request = request
+ self.response = response
+ self.toolbar = toolbar
+ self.toolbar.stats = {}
+
+class DebugToolbarTestCase(BaseTestCase):
+ urls = 'tests.urls'
+
+ def test_middleware(self):
+ with Settings(INTERNAL_IPS=['127.0.0.1'], DEBUG=True):
+ resp = self.client.get('/execute_sql/')
+ self.assertEquals(resp.status_code, 200)
+
+ def test_show_toolbar_DEBUG(self):
+ request = self.request
+
+ request.META = {'REMOTE_ADDR': '127.0.0.1'}
+ middleware = DebugToolbarMiddleware()
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], DEBUG=True):
+ self.assertTrue(middleware._show_toolbar(request))
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], DEBUG=False):
+ self.assertFalse(middleware._show_toolbar(request))
+
+ def test_show_toolbar_TEST(self):
+ request = self.request
+
+ request.META = {'REMOTE_ADDR': '127.0.0.1'}
+ middleware = DebugToolbarMiddleware()
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], TEST=True, DEBUG=True):
+ self.assertFalse(middleware._show_toolbar(request))
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], TEST=False, DEBUG=True):
+ self.assertTrue(middleware._show_toolbar(request))
+
+ def test_show_toolbar_INTERNAL_IPS(self):
+ request = self.request
+
+ request.META = {'REMOTE_ADDR': '127.0.0.1'}
+ middleware = DebugToolbarMiddleware()
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], DEBUG=True):
+ self.assertTrue(middleware._show_toolbar(request))
+
+ with Settings(INTERNAL_IPS=[], DEBUG=True):
+ self.assertFalse(middleware._show_toolbar(request))
+
+ def test_request_urlconf_string(self):
+ request = self.request
+
+ request.urlconf = 'tests.urls'
+ request.META = {'REMOTE_ADDR': '127.0.0.1'}
+ middleware = DebugToolbarMiddleware()
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], DEBUG=True):
+ middleware.process_request(request)
+
+ self.assertFalse(isinstance(request.urlconf, basestring))
+
+ self.assertTrue(hasattr(request.urlconf.urlpatterns[0], '_callback_str'))
+ self.assertEquals(request.urlconf.urlpatterns[0]._callback_str, 'debug_toolbar.views.debug_media')
+ self.assertTrue(hasattr(request.urlconf.urlpatterns[1], '_callback_str'))
+ self.assertEquals(request.urlconf.urlpatterns[-1]._callback_str, 'tests.views.execute_sql')
+
+ def test_request_urlconf_string_per_request(self):
+ request = self.request
+
+ request.urlconf = 'debug_toolbar.urls'
+ request.META = {'REMOTE_ADDR': '127.0.0.1'}
+ middleware = DebugToolbarMiddleware()
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], DEBUG=True):
+ middleware.process_request(request)
+ request.urlconf = 'tests.urls'
+ middleware.process_request(request)
+
+ self.assertFalse(isinstance(request.urlconf, basestring))
+
+ self.assertTrue(hasattr(request.urlconf.urlpatterns[0], '_callback_str'))
+ self.assertEquals(request.urlconf.urlpatterns[0]._callback_str, 'debug_toolbar.views.debug_media')
+ self.assertTrue(hasattr(request.urlconf.urlpatterns[1], '_callback_str'))
+ self.assertEquals(request.urlconf.urlpatterns[-1]._callback_str, 'tests.views.execute_sql')
+
+ def test_request_urlconf_module(self):
+ request = self.request
+
+ request.urlconf = __import__('tests.urls').urls
+ request.META = {'REMOTE_ADDR': '127.0.0.1'}
+ middleware = DebugToolbarMiddleware()
+
+ with Settings(INTERNAL_IPS=['127.0.0.1'], DEBUG=True):
+ middleware.process_request(request)
+
+ self.assertFalse(isinstance(request.urlconf, basestring))
+
+ self.assertTrue(hasattr(request.urlconf.urlpatterns[0], '_callback_str'))
+ self.assertEquals(request.urlconf.urlpatterns[0]._callback_str, 'debug_toolbar.views.debug_media')
+ self.assertTrue(hasattr(request.urlconf.urlpatterns[1], '_callback_str'))
+ self.assertEquals(request.urlconf.urlpatterns[-1]._callback_str, 'tests.views.execute_sql')
+
+ def test_with_process_view(self):
+ request = self.request
+ response = self.response
+
+ def _test_view(request):
+ return HttpResponse('')
+
+ with Settings(DEBUG=True):
+ panel = self.toolbar.get_panel(RequestVarsDebugPanel)
+ panel.process_request(request)
+ panel.process_view(request, _test_view, [], {})
+ panel.process_response(request, response)
+ content = panel.content()
+ self.assertTrue('tests.tests._test_view' in content, content)
+
+ def test_without_process_view(self):
+ request = self.request
+ response = self.response
+
+ with Settings(DEBUG=True):
+ panel = self.toolbar.get_panel(RequestVarsDebugPanel)
+ panel.process_request(request)
+ panel.process_response(request, response)
+ content = panel.content()
+ self.assertTrue('&lt;no view&gt;' in content, content)
+
+class DebugToolbarNameFromObjectTest(BaseTestCase):
+ def test_func(self):
+ def x():
+ return 1
+ res = get_name_from_obj(x)
+ self.assertEquals(res, 'tests.tests.x')
+
+ def test_lambda(self):
+ res = get_name_from_obj(lambda:1)
+ self.assertEquals(res, 'tests.tests.<lambda>')
+
+ def test_class(self):
+ class A: pass
+ res = get_name_from_obj(A)
+ self.assertEquals(res, 'tests.tests.A')
+
+class SQLPanelTestCase(BaseTestCase):
+ def test_recording(self):
+ panel = self.toolbar.get_panel(SQLDebugPanel)
+ self.assertEquals(len(panel._queries), 0)
+
+ list(User.objects.all())
+
+ # ensure query was logged
+ self.assertEquals(len(panel._queries), 1)
+ query = panel._queries[0]
+ self.assertEquals(query[0], 'default')
+ self.assertTrue('sql' in query[1])
+ self.assertTrue('duration' in query[1])
+ self.assertTrue('stacktrace' in query[1])
+
+class TemplatePanelTestCase(BaseTestCase):
+ def test_queryset_hook(self):
+ template_panel = self.toolbar.get_panel(TemplateDebugPanel)
+ sql_panel = self.toolbar.get_panel(SQLDebugPanel)
+ t = Template("No context variables here!")
+ c = Context({ 'queryset' : User.objects.all(), 'deep_queryset' : { 'queryset' : User.objects.all() } })
+ t.render(c)
+ # ensure the query was NOT logged
+ self.assertEquals(len(sql_panel._queries), 0)
+ ctx = template_panel.templates[0]['context'][0]
+ ctx = eval(ctx) # convert back to Python
+ self.assertEquals(ctx['queryset'], '<<queryset of auth.User>>')
+ self.assertEquals(ctx['deep_queryset'], '<<triggers database query>>')
+
+def module_func(*args, **kwargs):
+ """Used by dispatch tests"""
+ return 'blah'
+
+class TrackingTestCase(BaseTestCase):
+ @classmethod
+ def class_method(cls, *args, **kwargs):
+ return 'blah'
+
+ def class_func(self, *args, **kwargs):
+ """Used by dispatch tests"""
+ return 'blah'
+
+ def test_pre_hook(self):
+ foo = {}
+
+ @pre_dispatch(module_func)
+ def test(**kwargs):
+ foo.update(kwargs)
+
+ self.assertTrue(hasattr(module_func, '__wrapped__'))
+ self.assertEquals(len(callbacks['before']), 1)
+
+ module_func('hi', foo='bar')
+
+ self.assertTrue('sender' in foo, foo)
+ # best we can do
+ self.assertEquals(foo['sender'].__name__, 'module_func')
+ self.assertTrue('start' in foo, foo)
+ self.assertTrue(foo['start'] > 0)
+ self.assertTrue('stop' not in foo, foo)
+ self.assertTrue('args' in foo, foo)
+ self.assertTrue(len(foo['args']), 1)
+ self.assertEquals(foo['args'][0], 'hi')
+ self.assertTrue('kwargs' in foo, foo)
+ self.assertTrue(len(foo['kwargs']), 1)
+ self.assertTrue('foo' in foo['kwargs'])
+ self.assertEquals(foo['kwargs']['foo'], 'bar')
+
+ callbacks['before'] = {}
+
+ @pre_dispatch(TrackingTestCase.class_func)
+ def test(**kwargs):
+ foo.update(kwargs)
+
+ self.assertTrue(hasattr(TrackingTestCase.class_func, '__wrapped__'))
+ self.assertEquals(len(callbacks['before']), 1)
+
+ self.class_func('hello', foo='bar')
+
+ self.assertTrue('sender' in foo, foo)
+ # best we can do
+ self.assertEquals(foo['sender'].__name__, 'class_func')
+ self.assertTrue('start' in foo, foo)
+ self.assertTrue(foo['start'] > 0)
+ self.assertTrue('stop' not in foo, foo)
+ self.assertTrue('args' in foo, foo)
+ self.assertTrue(len(foo['args']), 2)
+ self.assertEquals(foo['args'][1], 'hello')
+ self.assertTrue('kwargs' in foo, foo)
+ self.assertTrue(len(foo['kwargs']), 1)
+ self.assertTrue('foo' in foo['kwargs'])
+ self.assertEquals(foo['kwargs']['foo'], 'bar')
+
+ # callbacks['before'] = {}
+ #
+ # @pre_dispatch(TrackingTestCase.class_method)
+ # def test(**kwargs):
+ # foo.update(kwargs)
+ #
+ # self.assertTrue(hasattr(TrackingTestCase.class_method, '__wrapped__'))
+ # self.assertEquals(len(callbacks['before']), 1)
+ #
+ # TrackingTestCase.class_method()
+ #
+ # self.assertTrue('sender' in foo, foo)
+ # # best we can do
+ # self.assertEquals(foo['sender'].__name__, 'class_method')
+ # self.assertTrue('start' in foo, foo)
+ # self.assertTrue('stop' not in foo, foo)
+ # self.assertTrue('args' in foo, foo)
+
+ def test_post_hook(self):
+ foo = {}
+
+ @post_dispatch(module_func)
+ def test(**kwargs):
+ foo.update(kwargs)
+
+ self.assertTrue(hasattr(module_func, '__wrapped__'))
+ self.assertEquals(len(callbacks['after']), 1)
+
+ module_func('hi', foo='bar')
+
+ self.assertTrue('sender' in foo, foo)
+ # best we can do
+ self.assertEquals(foo['sender'].__name__, 'module_func')
+ self.assertTrue('start' in foo, foo)
+ self.assertTrue(foo['start'] > 0)
+ self.assertTrue('stop' in foo, foo)
+ self.assertTrue(foo['stop'] > foo['start'])
+ self.assertTrue('args' in foo, foo)
+ self.assertTrue(len(foo['args']), 1)
+ self.assertEquals(foo['args'][0], 'hi')
+ self.assertTrue('kwargs' in foo, foo)
+ self.assertTrue(len(foo['kwargs']), 1)
+ self.assertTrue('foo' in foo['kwargs'])
+ self.assertEquals(foo['kwargs']['foo'], 'bar')
+
+ callbacks['after'] = {}
+
+ @post_dispatch(TrackingTestCase.class_func)
+ def test(**kwargs):
+ foo.update(kwargs)
+
+ self.assertTrue(hasattr(TrackingTestCase.class_func, '__wrapped__'))
+ self.assertEquals(len(callbacks['after']), 1)
+
+ self.class_func('hello', foo='bar')
+
+ self.assertTrue('sender' in foo, foo)
+ # best we can do
+ self.assertEquals(foo['sender'].__name__, 'class_func')
+ self.assertTrue('start' in foo, foo)
+ self.assertTrue(foo['start'] > 0)
+ self.assertTrue('stop' in foo, foo)
+ self.assertTrue(foo['stop'] > foo['start'])
+ self.assertTrue('args' in foo, foo)
+ self.assertTrue(len(foo['args']), 2)
+ self.assertEquals(foo['args'][1], 'hello')
+ self.assertTrue('kwargs' in foo, foo)
+ self.assertTrue(len(foo['kwargs']), 1)
+ self.assertTrue('foo' in foo['kwargs'])
+ self.assertEquals(foo['kwargs']['foo'], 'bar')
diff --git a/debug_toolbar/tests/urls.py b/tests/urls.py
index 7c99b03..359fd8f 100644
--- a/debug_toolbar/tests/urls.py
+++ b/tests/urls.py
@@ -10,5 +10,6 @@ from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
- url(r'^execute_sql/$', 'debug_toolbar.tests.views.execute_sql'),
+ # This pattern should be last to ensure tests still work
+ url(r'^execute_sql/$', 'tests.views.execute_sql'),
)
diff --git a/debug_toolbar/tests/views.py b/tests/views.py
index f989dcd..f989dcd 100644
--- a/debug_toolbar/tests/views.py
+++ b/tests/views.py