[Python-modules-commits] [python-django-debug-toolbar] 02/08: New upstream version 1.9.1
Andrew Starr-Bochicchio
asb at moszumanska.debian.org
Mon Dec 25 15:47:28 UTC 2017
This is an automated email from the git hooks/post-receive script.
asb pushed a commit to branch master
in repository python-django-debug-toolbar.
commit 6c405cb14c38548a87b28805e4d15b764737c18d
Author: Andrew Starr-Bochicchio <a.starr.b at gmail.com>
Date: Mon Dec 25 09:11:37 2017 -0500
New upstream version 1.9.1
---
.travis.yml | 13 +++---
Makefile | 6 +--
README.rst | 2 +-
debug_toolbar/panels/profiling.py | 33 +++++++-------
debug_toolbar/panels/redirects.py | 6 ++-
debug_toolbar/panels/request.py | 2 +-
debug_toolbar/panels/sql/views.py | 14 +++---
debug_toolbar/panels/templates/panel.py | 3 ++
debug_toolbar/panels/templates/views.py | 11 +++--
debug_toolbar/panels/versions.py | 29 +++++++-----
debug_toolbar/static/debug_toolbar/js/toolbar.js | 7 ++-
debug_toolbar/templates/debug_toolbar/base.html | 5 ++-
.../templates/debug_toolbar/panels/templates.html | 2 +-
docs/changes.rst | 27 +++++++++++
docs/conf.py | 4 +-
docs/configuration.rst | 13 ++++--
requirements_dev.txt | 3 +-
setup.cfg | 5 ++-
setup.py | 3 +-
tests/base.py | 14 ++++++
tests/panels/test_cache.py | 1 +
tests/panels/test_logging.py | 1 +
tests/panels/test_profiling.py | 31 ++++++++++++-
tests/panels/test_redirects.py | 2 -
tests/panels/test_request.py | 1 +
tests/panels/test_sql.py | 1 +
tests/panels/test_staticfiles.py | 1 +
tests/panels/test_template.py | 1 +
tests/panels/test_versions.py | 52 ++++++++++++++++++++++
tests/settings.py | 4 +-
tests/test_integration.py | 23 +++++++++-
tests/urls.py | 2 +
tests/views.py | 16 ++++++-
tox.ini | 17 +++----
34 files changed, 271 insertions(+), 84 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index dd5722f..7c8a4c6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -27,14 +27,15 @@ matrix:
env: TOXENV=py34-dj111
- python: 3.5
env: TOXENV=py35-dj111
+ - python: 3.5
+ env: TOXENV=py35-dj20
- python: 3.6
env: TOXENV=py36-dj111
- - python: 2.7
- env: TOXENV=flake8
- - python: 2.7
- env: TOXENV=isort
- - python: 2.7
- env: TOXENV=readme
+ - python: 3.6
+ env: TOXENV=py36-dj20
+ - env: TOXENV=flake8
+ - env: TOXENV=isort
+ - env: TOXENV=readme
install:
- pip install tox codecov
script:
diff --git a/Makefile b/Makefile
index 3d6d015..1cb754a 100644
--- a/Makefile
+++ b/Makefile
@@ -21,17 +21,17 @@ node_modules/jshint/bin/jshint:
test:
DJANGO_SETTINGS_MODULE=tests.settings \
- django-admin test tests
+ django-admin test $${TEST_ARGS:-tests}
test_selenium:
DJANGO_SELENIUM_TESTS=true DJANGO_SETTINGS_MODULE=tests.settings \
- django-admin test tests
+ django-admin test $${TEST_ARGS:-tests}
coverage:
python --version
coverage erase
DJANGO_SETTINGS_MODULE=tests.settings \
- coverage run `which django-admin` test -v2 tests
+ coverage run `which django-admin` test -v2 $${TEST_ARGS:-tests}
coverage report
coverage html
diff --git a/README.rst b/README.rst
index 343c05c..476c8c5 100644
--- a/README.rst
+++ b/README.rst
@@ -31,7 +31,7 @@ Here's a screenshot of the toolbar in action:
In addition to the built-in panels, a number of third-party panels are
contributed by the community.
-The current version of the Debug Toolbar is 1.8. It works on Django ≥ 1.8.
+The current version of the Debug Toolbar is 1.9. It works on Django ≥ 1.8.
Documentation, including installation and configuration instructions, is
available at https://django-debug-toolbar.readthedocs.io/.
diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py
index 370a58c..e64fd1d 100644
--- a/debug_toolbar/panels/profiling.py
+++ b/debug_toolbar/panels/profiling.py
@@ -6,7 +6,7 @@ from colorsys import hsv_to_rgb
from pstats import Stats
from django.utils import six
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
from debug_toolbar import settings as dt_settings
@@ -78,15 +78,15 @@ class FunctionCall(object):
file_path, file_name = file_name.rsplit(os.sep, 1)
- return mark_safe(
+ return format_html(
'<span class="djdt-path">{0}/</span>'
'<span class="djdt-file">{1}</span>'
' in <span class="djdt-func">{3}</span>'
- '(<span class="djdt-lineno">{2}</span>)'.format(
- file_path,
- file_name,
- line_num,
- method))
+ '(<span class="djdt-lineno">{2}</span>)',
+ file_path,
+ file_name,
+ line_num,
+ method)
def subfuncs(self):
i = 0
@@ -167,12 +167,13 @@ class ProfilingPanel(Panel):
self.stats = DjangoDebugToolbarStats(self.profiler)
self.stats.calc_callees()
- root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0)
-
- func_list = []
- self.add_node(func_list,
- root,
- dt_settings.get_config()['PROFILER_MAX_DEPTH'],
- root.stats[3] / 8)
-
- self.record_stats({'func_list': func_list})
+ root_func = self.stats.get_root_func()
+ # Ensure root function exists before continuing with function call analysis
+ if root_func:
+ root = FunctionCall(self.stats, root_func, depth=0)
+ func_list = []
+ self.add_node(func_list,
+ root,
+ dt_settings.get_config()['PROFILER_MAX_DEPTH'],
+ root.stats[3] / 8)
+ self.record_stats({'func_list': func_list})
diff --git a/debug_toolbar/panels/redirects.py b/debug_toolbar/panels/redirects.py
index 14dc7ac..01a6016 100644
--- a/debug_toolbar/panels/redirects.py
+++ b/debug_toolbar/panels/redirects.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import, unicode_literals
-from django.shortcuts import render_to_response
+from django.template.response import SimpleTemplateResponse
from django.utils.translation import ugettext_lazy as _
from debug_toolbar.panels import Panel
@@ -22,6 +22,8 @@ class RedirectsPanel(Panel):
status_line = '%s %s' % (response.status_code, response.reason_phrase)
cookies = response.cookies
context = {'redirect_to': redirect_to, 'status_line': status_line}
- response = render_to_response('debug_toolbar/redirect.html', context)
+ # Using SimpleTemplateResponse avoids running global context processors.
+ response = SimpleTemplateResponse('debug_toolbar/redirect.html', context)
response.cookies = cookies
+ response.render()
return response
diff --git a/debug_toolbar/panels/request.py b/debug_toolbar/panels/request.py
index ae5b2a3..bf202f5 100644
--- a/debug_toolbar/panels/request.py
+++ b/debug_toolbar/panels/request.py
@@ -9,7 +9,7 @@ from debug_toolbar.utils import get_name_from_obj
try:
from django.urls import resolve
-except: # Django < 1.10 pragma: no cover
+except ImportError: # Django < 1.10 pragma: no cover
from django.core.urlresolvers import resolve
diff --git a/debug_toolbar/panels/sql/views.py b/debug_toolbar/panels/sql/views.py
index 0d6b4e3..47fca42 100644
--- a/debug_toolbar/panels/sql/views.py
+++ b/debug_toolbar/panels/sql/views.py
@@ -1,7 +1,7 @@
from __future__ import absolute_import, unicode_literals
from django.http import HttpResponseBadRequest
-from django.shortcuts import render_to_response
+from django.template.response import SimpleTemplateResponse
from django.views.decorators.csrf import csrf_exempt
from debug_toolbar.decorators import require_show_toolbar
@@ -29,8 +29,8 @@ def sql_select(request):
'headers': headers,
'alias': form.cleaned_data['alias'],
}
- # Using render_to_response avoids running global context processors.
- return render_to_response('debug_toolbar/panels/sql_select.html', context)
+ # Using SimpleTemplateResponse avoids running global context processors.
+ return SimpleTemplateResponse('debug_toolbar/panels/sql_select.html', context)
return HttpResponseBadRequest('Form errors')
@@ -66,8 +66,8 @@ def sql_explain(request):
'headers': headers,
'alias': form.cleaned_data['alias'],
}
- # Using render_to_response avoids running global context processors.
- return render_to_response('debug_toolbar/panels/sql_explain.html', context)
+ # Using SimpleTemplateResponse avoids running global context processors.
+ return SimpleTemplateResponse('debug_toolbar/panels/sql_explain.html', context)
return HttpResponseBadRequest('Form errors')
@@ -113,6 +113,6 @@ def sql_profile(request):
'headers': headers,
'alias': form.cleaned_data['alias'],
}
- # Using render_to_response avoids running global context processors.
- return render_to_response('debug_toolbar/panels/sql_profile.html', context)
+ # Using SimpleTemplateResponse avoids running global context processors.
+ return SimpleTemplateResponse('debug_toolbar/panels/sql_profile.html', context)
return HttpResponseBadRequest('Form errors')
diff --git a/debug_toolbar/panels/templates/panel.py b/debug_toolbar/panels/templates/panel.py
index 7367cc1..ace5a6b 100644
--- a/debug_toolbar/panels/templates/panel.py
+++ b/debug_toolbar/panels/templates/panel.py
@@ -7,6 +7,7 @@ from pprint import pformat
from django import http
from django.conf.urls import url
+from django.core import signing
from django.db.models.query import QuerySet, RawQuerySet
from django.template import RequestContext, Template
from django.test.signals import template_rendered
@@ -192,8 +193,10 @@ class TemplatesPanel(Panel):
template = template_data.get('template', None)
if hasattr(template, 'origin') and template.origin and template.origin.name:
template.origin_name = template.origin.name
+ template.origin_hash = signing.dumps(template.origin.name)
else:
template.origin_name = _('No origin')
+ template.origin_hash = ''
info['template'] = template
# Clean up context for better readability
if self.toolbar.config['SHOW_TEMPLATE_CONTEXT']:
diff --git a/debug_toolbar/panels/templates/views.py b/debug_toolbar/panels/templates/views.py
index 3ab2a6d..b458f17 100644
--- a/debug_toolbar/panels/templates/views.py
+++ b/debug_toolbar/panels/templates/views.py
@@ -1,9 +1,10 @@
from __future__ import absolute_import, unicode_literals
+from django.core import signing
from django.http import HttpResponseBadRequest
-from django.shortcuts import render_to_response
from django.template import TemplateDoesNotExist
from django.template.engine import Engine
+from django.template.response import SimpleTemplateResponse
from django.utils.safestring import mark_safe
from debug_toolbar.decorators import require_show_toolbar
@@ -23,6 +24,10 @@ def template_source(request):
template_origin_name = request.GET.get('template_origin', None)
if template_origin_name is None:
return HttpResponseBadRequest('"template_origin" key is required')
+ try:
+ template_origin_name = signing.loads(template_origin_name)
+ except Exception:
+ return HttpResponseBadRequest('"template_origin" is invalid')
template_name = request.GET.get('template', template_origin_name)
final_loaders = []
@@ -66,8 +71,8 @@ def template_source(request):
except ImportError:
pass
- # Using render_to_response avoids running global context processors.
- return render_to_response('debug_toolbar/panels/template_source.html', {
+ # Using SimpleTemplateResponse avoids running global context processors.
+ return SimpleTemplateResponse('debug_toolbar/panels/template_source.html', {
'source': source,
'template_name': template_name
})
diff --git a/debug_toolbar/panels/versions.py b/debug_toolbar/panels/versions.py
index 26650d7..2e8d588 100644
--- a/debug_toolbar/panels/versions.py
+++ b/debug_toolbar/panels/versions.py
@@ -41,18 +41,25 @@ class VersionsPanel(Panel):
yield app.__name__, name, version
def get_app_version(self, app):
+ version = self.get_version_from_app(app)
+ if isinstance(version, (list, tuple)):
+ # We strip dots from the right because we do not want to show
+ # trailing dots if there are empty elements in the list/tuple
+ version = '.'.join(str(o) for o in version).rstrip('.')
+ return version
+
+ def get_version_from_app(self, app):
if hasattr(app, 'get_version'):
get_version = app.get_version
if callable(get_version):
- version = get_version()
+ try:
+ return get_version()
+ except TypeError:
+ pass
else:
- version = get_version
- elif hasattr(app, 'VERSION'):
- version = app.VERSION
- elif hasattr(app, '__version__'):
- version = app.__version__
- else:
- return
- if isinstance(version, (list, tuple)):
- version = '.'.join(str(o) for o in version)
- return version
+ return get_version
+ if hasattr(app, 'VERSION'):
+ return app.VERSION
+ if hasattr(app, '__version__'):
+ return app.__version__
+ return
diff --git a/debug_toolbar/static/debug_toolbar/js/toolbar.js b/debug_toolbar/static/debug_toolbar/js/toolbar.js
index 5fbdaf1..7fddbb2 100644
--- a/debug_toolbar/static/debug_toolbar/js/toolbar.js
+++ b/debug_toolbar/static/debug_toolbar/js/toolbar.js
@@ -19,16 +19,15 @@
} else {
$('.djdt-panelContent').hide(); // Hide any that are already open
var inner = current.find('.djDebugPanelContent .djdt-scroll'),
- store_id = $('#djDebug').data('store-id'),
- render_panel_url = $('#djDebug').data('render-panel-url');
- if (store_id !== '' && inner.children().length === 0) {
+ store_id = $('#djDebug').data('store-id');
+ if (store_id && inner.children().length === 0) {
var ajax_data = {
data: {
store_id: store_id,
panel_id: this.className
},
type: 'GET',
- url: render_panel_url
+ url: $('#djDebug').data('render-panel-url')
};
$.ajax(ajax_data).done(function(data){
inner.prev().remove(); // Remove AJAX loader
diff --git a/debug_toolbar/templates/debug_toolbar/base.html b/debug_toolbar/templates/debug_toolbar/base.html
index deaae80..e5df55c 100644
--- a/debug_toolbar/templates/debug_toolbar/base.html
+++ b/debug_toolbar/templates/debug_toolbar/base.html
@@ -11,7 +11,10 @@
{% endif %}
<script src="{% static 'debug_toolbar/js/toolbar.js' %}"></script>
<div id="djDebug" class="djdt-hidden" dir="ltr"
- data-store-id="{{ toolbar.store_id }}" data-render-panel-url="{% url 'djdt:render_panel' %}"
+ {% if toolbar.store_id %}
+ data-store-id="{{ toolbar.store_id }}"
+ data-render-panel-url="{% url 'djdt:render_panel' %}"
+ {% endif %}
{{ toolbar.config.ROOT_TAG_EXTRA_ATTRS|safe }}>
<div class="djdt-hidden" id="djDebugToolbar">
<ul id="djDebugPanelList">
diff --git a/debug_toolbar/templates/debug_toolbar/panels/templates.html b/debug_toolbar/templates/debug_toolbar/panels/templates.html
index c657f0b..0440dc3 100644
--- a/debug_toolbar/templates/debug_toolbar/panels/templates.html
+++ b/debug_toolbar/templates/debug_toolbar/panels/templates.html
@@ -14,7 +14,7 @@
{% if templates %}
<dl>
{% for template in templates %}
-<dt><strong><a class="remoteCall toggleTemplate" href="{% url 'djdt:template_source' %}?template={{ template.template.name }}&template_origin={{ template.template.origin_name }}">{{ template.template.name|addslashes }}</a></strong></dt>
+<dt><strong><a class="remoteCall toggleTemplate" href="{% url 'djdt:template_source' %}?template={{ template.template.name }}&template_origin={{ template.template.origin_hash }}">{{ template.template.name|addslashes }}</a></strong></dt>
<dd><samp>{{ template.template.origin_name|addslashes }}</samp></dd>
{% if template.context %}
<dd>
diff --git a/docs/changes.rst b/docs/changes.rst
index e1c6fdf..c8e0cbe 100644
--- a/docs/changes.rst
+++ b/docs/changes.rst
@@ -1,12 +1,39 @@
Change log
==========
+UNRELEASED
+----------
+
+* Fix erroneous ``ContentNotRenderedError`` raised by the redirects panel.
+
+1.9
+---
+
+This version is compatible with Django 2.0 and requires Django 1.8 or
+later.
+
+Bugfixes
+~~~~~~~~
+
+* The profiling panel now escapes reported data resulting in valid HTML.
+* Many minor cleanups and bugfixes.
+
1.8
---
This version is compatible with Django 1.11 and requires Django 1.8 or
later.
+**Backwards incompatible changes**
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* ``debug_toolbar.middleware.show_toolbar`` (the default value of setting
+ ``SHOW_TOOLBAR_CALLBACK``) no longer returns ``False`` for AJAX requests.
+ This is to allow reusing the ``SHOW_TOOLBAR_CALLBACK`` function to verify
+ access to panel views requested via AJAX. Projects defining a custom
+ ``SHOW_TOOLBAR_CALLBACK`` should remove checks for AJAX requests in order to
+ continue to allow access to these panels.
+
Features
~~~~~~~~
diff --git a/docs/conf.py b/docs/conf.py
index 90e406b..c567460 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -59,9 +59,9 @@ copyright = copyright.format(datetime.date.today().year)
# built documents.
#
# The short X.Y version.
-version = '1.8'
+version = '1.9'
# The full version, including alpha/beta/rc tags.
-release = '1.8'
+release = '1.9'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/configuration.rst b/docs/configuration.rst
index babc6ec..3be92b9 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -112,10 +112,15 @@ Toolbar options
Default: 'debug_toolbar.middleware.show_toolbar'
This is the dotted path to a function used for determining whether the
- toolbar should show or not. The default checks are that ``DEBUG`` must be
- set to ``True``, the IP of the request must be in ``INTERNAL_IPS``, and the
- request must not be an AJAX request. You can provide your own function
- ``callback(request)`` which returns ``True`` or ``False``.
+ 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
+ provide your own function ``callback(request)`` which returns ``True`` or
+ ``False``.
+
+ For versions < 1.8, the callback should also return ``False`` for AJAX
+ requests. Since version 1.8, AJAX requests are checked in the middleware, not
+ the callback. This allows reusing the callback to verify access to panel
+ views requested via AJAX.
Panel options
~~~~~~~~~~~~~
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 200ab13..7b3c6e6 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -11,8 +11,9 @@ django_jinja
# Testing
coverage
-isort
flake8
+html5lib
+isort
selenium
tox
diff --git a/setup.cfg b/setup.cfg
index 7ba8b74..aeef374 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -13,5 +13,8 @@ known_first_party = debug_toolbar
multi_line_output = 5
not_skip = __init__.py
-[wheel]
+[bdist_wheel]
universal = 1
+
+[metadata]
+license-file = LICENSE
diff --git a/setup.py b/setup.py
index 05e3f15..255d732 100755
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ from setuptools import find_packages, setup
setup(
name='django-debug-toolbar',
- version='1.8',
+ version='1.9.1',
description='A configurable set of panels that display various debug '
'information about the current request/response.',
long_description=open('README.rst', encoding='utf-8').read(),
@@ -30,6 +30,7 @@ setup(
'Framework :: Django :: 1.9',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11',
+ 'Framework :: Django :: 2.0',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
diff --git a/tests/base.py b/tests/base.py
index 2518d8c..a7b57e5 100644
--- a/tests/base.py
+++ b/tests/base.py
@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
import threading
+import html5lib
from django.http import HttpResponse
from django.test import RequestFactory, TestCase
@@ -24,3 +25,16 @@ class BaseTestCase(TestCase):
self.response = response
self.toolbar = toolbar
self.toolbar.stats = {}
+
+ def assertValidHTML(self, content, msg=None):
+ parser = html5lib.HTMLParser()
+ parser.parseFragment(self.panel.content)
+ if parser.errors:
+ default_msg = ['Content is invalid HTML:']
+ lines = content.split('\n')
+ for position, errorcode, datavars in parser.errors:
+ default_msg.append(' %s' % html5lib.constants.E[errorcode] % datavars)
+ default_msg.append(' %s' % lines[position[0] - 1])
+
+ msg = self._formatMessage(msg, '\n'.join(default_msg))
+ raise self.failureException(msg)
diff --git a/tests/panels/test_cache.py b/tests/panels/test_cache.py
index 940b5a5..e6f3fb1 100644
--- a/tests/panels/test_cache.py
+++ b/tests/panels/test_cache.py
@@ -47,3 +47,4 @@ class CachePanelTestCase(BaseTestCase):
self.panel.generate_stats(self.request, self.response)
# ensure the panel renders correctly.
self.assertIn('café', self.panel.content)
+ self.assertValidHTML(self.panel.content)
diff --git a/tests/panels/test_logging.py b/tests/panels/test_logging.py
index 3168668..cb5a631 100644
--- a/tests/panels/test_logging.py
+++ b/tests/panels/test_logging.py
@@ -57,6 +57,7 @@ class LoggingPanelTestCase(BaseTestCase):
self.panel.generate_stats(self.request, self.response)
# ensure the panel renders correctly.
self.assertIn('café', self.panel.content)
+ self.assertValidHTML(self.panel.content)
def test_failing_formatting(self):
class BadClass(object):
diff --git a/tests/panels/test_profiling.py b/tests/panels/test_profiling.py
index 0b57bf1..7e0ef25 100644
--- a/tests/panels/test_profiling.py
+++ b/tests/panels/test_profiling.py
@@ -1,12 +1,15 @@
from __future__ import absolute_import, unicode_literals
+import unittest
+
from django.contrib.auth.models import User
from django.db import IntegrityError, transaction
from django.test import TestCase
from django.test.utils import override_settings
+from django.utils import six
from ..base import BaseTestCase
-from ..views import regular_view
+from ..views import listcomp_view, regular_view
@override_settings(DEBUG_TOOLBAR_PANELS=['debug_toolbar.panels.profiling.ProfilingPanel'])
@@ -35,6 +38,32 @@ class ProfilingPanelTestCase(BaseTestCase):
self.panel.generate_stats(self.request, self.response)
# ensure the panel renders correctly.
self.assertIn('regular_view', self.panel.content)
+ self.assertValidHTML(self.panel.content)
+
+ @unittest.skipIf(six.PY2, 'list comprehension not listed on Python 2')
+ def test_listcomp_escaped(self):
+ self.panel.process_view(self.request, listcomp_view, (), {})
+ self.panel.generate_stats(self.request, self.response)
+ self.assertNotIn('<span class="djdt-func"><listcomp></span>', self.panel.content)
+ self.assertIn('<span class="djdt-func"><listcomp></span>', self.panel.content)
+
+ def test_generate_stats_no_profiler(self):
+ """
+ Test generating stats with no profiler.
+ """
+ self.assertIsNone(self.panel.generate_stats(self.request, self.response))
+
+ def test_generate_stats_no_root_func(self):
+ """
+ Test generating stats using profiler without root function.
+ """
+ self.panel.process_view(self.request, regular_view, ('profiling',), {})
+ self.panel.process_response(self.request, self.response)
+ self.panel.profiler.clear()
+ self.panel.profiler.enable()
+ self.panel.profiler.disable()
+ self.panel.generate_stats(self.request, self.response)
+ self.assertNotIn('func_list', self.panel.get_stats())
@override_settings(DEBUG=True,
diff --git a/tests/panels/test_redirects.py b/tests/panels/test_redirects.py
index d6fe5a3..980130e 100644
--- a/tests/panels/test_redirects.py
+++ b/tests/panels/test_redirects.py
@@ -4,12 +4,10 @@ import copy
from django.conf import settings
from django.http import HttpResponse
-from django.test.utils import override_settings
from ..base import BaseTestCase
- at override_settings(DEBUG_TOOLBAR_CONFIG={'INTERCEPT_REDIRECTS': True})
class RedirectsPanelTestCase(BaseTestCase):
def setUp(self):
diff --git a/tests/panels/test_request.py b/tests/panels/test_request.py
index 452086f..17119b6 100644
--- a/tests/panels/test_request.py
+++ b/tests/panels/test_request.py
@@ -46,3 +46,4 @@ class RequestPanelTestCase(BaseTestCase):
self.panel.generate_stats(self.request, self.response)
# ensure the panel renders correctly.
self.assertIn('nôt åscíì', self.panel.content)
+ self.assertValidHTML(self.panel.content)
diff --git a/tests/panels/test_sql.py b/tests/panels/test_sql.py
index 827758b..886c8f2 100644
--- a/tests/panels/test_sql.py
+++ b/tests/panels/test_sql.py
@@ -81,6 +81,7 @@ class SQLPanelTestCase(BaseTestCase):
self.panel.generate_stats(self.request, self.response)
# ensure the panel renders correctly.
self.assertIn('café', self.panel.content)
+ self.assertValidHTML(self.panel.content)
@unittest.skipUnless(connection.vendor == 'postgresql',
'Test valid only on PostgreSQL')
diff --git a/tests/panels/test_staticfiles.py b/tests/panels/test_staticfiles.py
index 4002087..3773af6 100644
--- a/tests/panels/test_staticfiles.py
+++ b/tests/panels/test_staticfiles.py
@@ -42,3 +42,4 @@ class StaticFilesPanelTestCase(BaseTestCase):
# ensure the panel renders correctly.
self.assertIn('django.contrib.staticfiles.finders.'
'AppDirectoriesFinder', self.panel.content)
+ self.assertValidHTML(self.panel.content)
diff --git a/tests/panels/test_template.py b/tests/panels/test_template.py
index 1d5a24b..ea80763 100644
--- a/tests/panels/test_template.py
+++ b/tests/panels/test_template.py
@@ -64,6 +64,7 @@ class TemplatesPanelTestCase(BaseTestCase):
self.panel.generate_stats(self.request, self.response)
# ensure the panel renders correctly.
self.assertIn('nôt åscíì', self.panel.content)
+ self.assertValidHTML(self.panel.content)
def test_custom_context_processor(self):
self.panel.process_request(self.request)
diff --git a/tests/panels/test_versions.py b/tests/panels/test_versions.py
new file mode 100644
index 0000000..d6541a9
--- /dev/null
+++ b/tests/panels/test_versions.py
@@ -0,0 +1,52 @@
+# coding: utf-8
+
+from __future__ import absolute_import, unicode_literals
+
+from collections import namedtuple
+
+from ..base import BaseTestCase
+
+version_info_t = namedtuple('version_info_t', (
+ 'major', 'minor', 'micro', 'releaselevel', 'serial',
+))
+
+
+class VersionsPanelTestCase(BaseTestCase):
+
+ def setUp(self):
+ super(VersionsPanelTestCase, self).setUp()
+ self.panel = self.toolbar.get_panel_by_id('VersionsPanel')
+
+ def test_app_version_from_get_version_fn(self):
+
+ class FakeApp:
+ def get_version(self):
+ return version_info_t(1, 2, 3, '', '')
+
+ self.assertEqual(self.panel.get_app_version(FakeApp()), '1.2.3')
+
+ def test_incompatible_app_version_fn(self):
+
+ class FakeApp:
+
+ def get_version(self, some_other_arg):
+ # This should be ignored by the get_version_from_app
+ return version_info_t(0, 0, 0, '', '')
+
+ VERSION = version_info_t(1, 2, 3, '', '')
+
+ self.assertEqual(self.panel.get_app_version(FakeApp()), '1.2.3')
+
+ def test_app_version_from_VERSION(self):
+
+ class FakeApp:
+ VERSION = version_info_t(1, 2, 3, '', '')
+
+ self.assertEqual(self.panel.get_app_version(FakeApp()), '1.2.3')
+
+ def test_app_version_from_underscore_version(self):
+
+ class FakeApp:
+ __version__ = version_info_t(1, 2, 3, '', '')
+
+ self.assertEqual(self.panel.get_app_version(FakeApp()), '1.2.3')
diff --git a/tests/settings.py b/tests/settings.py
index a9de290..6ea78f3 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -30,7 +30,7 @@ INSTALLED_APPS = [
MEDIA_URL = '/media/' # Avoids https://code.djangoproject.com/ticket/21451
-MIDDLEWARE_CLASSES = [
+MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
@@ -40,6 +40,8 @@ MIDDLEWARE_CLASSES = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
+# Django < 1.10
+MIDDLEWARE_CLASSES = MIDDLEWARE
ROOT_URLCONF = 'tests.urls'
diff --git a/tests/test_integration.py b/tests/test_integration.py
index d9b8743..b177bec 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -8,6 +8,7 @@ from xml.etree import ElementTree as ET
import django
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
+from django.core import signing
from django.core.checks import Error, run_checks
from django.template.loader import get_template
from django.test import RequestFactory, TestCase
@@ -143,7 +144,7 @@ class DebugToolbarIntegrationTestCase(TestCase):
url = '/__debug__/template_source/'
data = {
'template': template.template.name,
- 'template_origin': template.template.origin.name
+ 'template_origin': signing.dumps(template.template.origin.name)
}
response = self.client.get(url, data)
@@ -219,6 +220,24 @@ class DebugToolbarIntegrationTestCase(TestCase):
response = self.client.post(url, data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 404)
+ @override_settings(DEBUG_TOOLBAR_CONFIG={'RENDER_PANELS': True})
+ def test_data_store_id_not_rendered_when_none(self):
+ url = '/regular/basic/'
+ response = self.client.get(url)
+ self.assertIn(b'id="djDebug"', response.content)
+ self.assertNotIn(b'data-store-id', response.content)
+
+ def test_view_returns_template_response(self):
+ response = self.client.get('/template_response/basic/')
+ self.assertEqual(response.status_code, 200)
+
+ @override_settings(DEBUG_TOOLBAR_CONFIG={'DISABLE_PANELS': set()})
+ def test_incercept_redirects(self):
+ response = self.client.get('/redirect/')
+ self.assertEqual(response.status_code, 200)
+ # Link to LOCATION header.
+ self.assertIn(b'href="/regular/redirect/"', response.content)
+
@unittest.skipIf(webdriver is None, "selenium isn't installed")
@unittest.skipUnless('DJANGO_SELENIUM_TESTS' in os.environ, "selenium tests not requested")
@@ -368,7 +387,7 @@ class DebugToolbarSystemChecksTestCase(BaseTestCase):
def test_middleware_factory_functions_supported(self):
messages = run_checks()
- if django.VERSION[:2] < (1, 10):
+ if django.VERSION[:2] < (1, 10) or django.VERSION[:2] >= (2, 0):
self.assertEqual(messages, [])
else:
self.assertEqual(messages[0].id, '1_10.W001')
diff --git a/tests/urls.py b/tests/urls.py
index 4c377c9..9cee7e5 100644
--- a/tests/urls.py
+++ b/tests/urls.py
@@ -14,10 +14,12 @@ urlpatterns = [
url(r'^resolving2/(?P<arg1>.+)/(?P<arg2>.+)/$', views.resolving_view),
url(r'^resolving3/(.+)/$', views.resolving_view, {'arg2': 'default'}),
url(r'^regular/(?P<title>.*)/$', views.regular_view),
+ url(r'^template_response/(?P<title>.*)/$', views.template_response_view),
url(r'^regular_jinja/(?P<title>.*)/$', views.regular_jinjia_view),
url(r'^non_ascii_request/$', views.regular_view, {'title': NonAsciiRepr()}),
url(r'^new_user/$', views.new_user),
url(r'^execute_sql/$', views.execute_sql),
url(r'^cached_view/$', views.cached_view),
+ url(r'^redirect/$', views.redirect_view),
url(r'^__debug__/', include(debug_toolbar.urls)),
]
diff --git a/tests/views.py b/tests/views.py
index bc2ebce..1811394 100644
--- a/tests/views.py
+++ b/tests/views.py
@@ -3,8 +3,9 @@
from __future__ import absolute_import, unicode_literals
from django.contrib.auth.models import User
-from django.http import HttpResponse
+from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
+from django.template.response import TemplateResponse
from django.views.decorators.cache import cache_page
@@ -17,6 +18,10 @@ def regular_view(request, title):
return render(request, 'basic.html', {'title': title})
+def template_response_view(request, title):
+ return TemplateResponse(request, 'basic.html', {'title': title})
+
+
def new_user(request, username='joe'):
User.objects.create_user(username=username)
return render(request, 'basic.html', {'title': 'new user'})
@@ -34,3 +39,12 @@ def cached_view(request):
def regular_jinjia_view(request, title):
return render(request, 'jinja2/basic.jinja', {'title': title})
+
+
+def listcomp_view(request):
+ lst = [i for i in range(50000) if i % 2 == 0]
+ return render(request, 'basic.html', {'title': 'List comprehension', 'lst': lst})
+
+
+def redirect_view(request):
+ return HttpResponseRedirect('/regular/redirect/')
diff --git a/tox.ini b/tox.ini
index d24a67d..4fce4a6 100644
--- a/tox.ini
+++ b/tox.ini
@@ -3,48 +3,41 @@ envlist =
py{27,33,34}-dj18,
py{27,34,35}-dj{19,110,111},
py36-dj111
+ py{35,36}-dj20
flake8,
isort,
readme
[testenv]
-basepython =
- py27: python2.7
- py33: python3.3
- py34: python3.4
- py35: python3.5
- py36: python3.6
deps =
dj18: Django>=1.8,<1.9
dj19: Django>=1.9,<1.10
dj110: Django>=1.10,<1.11
dj111: Django>=1.11,<2.0
+ dj20: Django==2.0b1
coverage
+ django_jinja
+ html5lib
selenium<4.0
sqlparse
- django_jinja
setenv =
PYTHONPATH = {toxinidir}
whitelist_externals = make
pip_pre = True
usedevelop = true
-commands = make coverage
+commands = make coverage TEST_ARGS='{posargs:tests}'
[testenv:flake8]
-basepython = python2.7
commands = make flake8
deps = flake8
[testenv:isort]
-basepython = python2.7
commands = make isort_check_only
deps = isort
[testenv:jshint]
-basepython = python2.7
commands = make jshint
[testenv:readme]
-basepython = python2.7
commands = python setup.py check -r -s
deps = readme_renderer
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django-debug-toolbar.git
More information about the Python-modules-commits
mailing list