From 184992f2d5773016e2c8315c91acbf8f601775bf Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Fri, 6 Apr 2012 12:59:56 +0200
Subject: Added staticfiles panel class.
---
debug_toolbar/panels/logging.py | 41 ++----
debug_toolbar/panels/staticfiles.py | 142 +++++++++++++++++++++
.../templates/debug_toolbar/panels/cache.html | 6 +-
.../debug_toolbar/panels/staticfiles.html | 57 +++++++++
debug_toolbar/utils.py | 33 +++++
example/settings.py | 3 +
example/static/test.css | 3 +
7 files changed, 250 insertions(+), 35 deletions(-)
create mode 100644 debug_toolbar/panels/staticfiles.py
create mode 100644 debug_toolbar/templates/debug_toolbar/panels/staticfiles.html
create mode 100644 example/static/test.css
diff --git a/debug_toolbar/panels/logging.py b/debug_toolbar/panels/logging.py
index 051d5a3..1ee19ce 100644
--- a/debug_toolbar/panels/logging.py
+++ b/debug_toolbar/panels/logging.py
@@ -8,42 +8,19 @@ except ImportError:
threading = None
from django.utils.translation import ungettext, ugettext_lazy as _
from debug_toolbar.panels import Panel
+from debug_toolbar.utils import ThreadCollector
MESSAGE_IF_STRING_REPRESENTATION_INVALID = '[Could not get log message]'
-class LogCollector(object):
- def __init__(self):
- if threading is None:
- raise NotImplementedError(
- "threading module is not available, "
- "the logging panel cannot be used without it")
- self.records = {} # a dictionary that maps threads to log records
+class LogCollector(ThreadCollector):
- def add_record(self, record, thread=None):
+ def collect(self, item, 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':
+ if item.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,
- returns a list for the current thread.
- """
- if thread is None:
- thread = threading.currentThread()
- 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()
- if thread in self.records:
- del self.records[thread]
+ super(LogCollector, self).collect(item, thread)
class ThreadTrackingHandler(logging.Handler):
@@ -65,7 +42,7 @@ class ThreadTrackingHandler(logging.Handler):
'line': record.lineno,
'channel': record.name,
}
- self.collector.add_record(record)
+ self.collector.collect(record)
# We don't use enable/disable_instrumentation because logging is global.
@@ -96,10 +73,10 @@ class LoggingPanel(Panel):
title = _("Log messages")
def process_request(self, request):
- collector.clear_records()
+ collector.clear_collection()
def process_response(self, request, response):
- records = collector.get_records()
+ records = collector.get_collection()
self._records[threading.currentThread()] = records
- collector.clear_records()
+ collector.clear_collection()
self.record_stats({'records': records})
diff --git a/debug_toolbar/panels/staticfiles.py b/debug_toolbar/panels/staticfiles.py
new file mode 100644
index 0000000..9b3829d
--- /dev/null
+++ b/debug_toolbar/panels/staticfiles.py
@@ -0,0 +1,142 @@
+from __future__ import absolute_import
+from os.path import normpath, join
+try:
+ import threading
+except ImportError:
+ threading = None
+
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+from django.core.files.storage import get_storage_class
+from django.contrib.staticfiles import finders, storage
+from django.contrib.staticfiles.templatetags import staticfiles
+
+from django.utils.translation import ungettext, ugettext_lazy as _
+from django.utils.datastructures import SortedDict
+from django.utils.functional import LazyObject
+
+from debug_toolbar import panels
+from debug_toolbar.utils import ThreadCollector
+
+
+class StaticFile(object):
+
+ def __init__(self, path):
+ self.path = path
+
+ def __unicode__(self):
+ return self.path
+
+ def real_path(self):
+ return finders.find(self.path)
+
+ def url(self):
+ return storage.staticfiles_storage.url(self.path)
+
+
+class FileCollector(ThreadCollector):
+
+ def collect(self, path, thread=None):
+ # handle the case of {% static "admin/" %}
+ if path.endswith('/'):
+ return
+ super(FileCollector, self).collect(StaticFile(path), thread)
+
+
+collector = FileCollector()
+
+
+class DebugConfiguredStorage(LazyObject):
+ def _setup(self):
+
+ configured_storage_cls = get_storage_class(settings.STATICFILES_STORAGE)
+
+ class DebugStaticFilesStorage(configured_storage_cls):
+
+ def __init__(self, collector, *args, **kwargs):
+ super(DebugStaticFilesStorage, self).__init__(*args, **kwargs)
+ self.collector = collector
+
+ def url(self, path):
+ self.collector.collect(path)
+ return super(DebugStaticFilesStorage, self).url(path)
+
+ self._wrapped = DebugStaticFilesStorage(collector)
+
+storage.staticfiles_storage = staticfiles.staticfiles_storage = DebugConfiguredStorage()
+
+
+class StaticFilesPanel(panels.Panel):
+ """
+ A panel to display the found staticfiles.
+ """
+ name = 'Static files'
+ template = 'debug_toolbar/panels/staticfiles.html'
+
+ @property
+ def title(self):
+ return (_("Static files (%(num_found)s found)") %
+ {'num_found': self.num_found, 'num_used': self.num_used})
+
+ def __init__(self, *args, **kwargs):
+ super(StaticFilesPanel, self).__init__(*args, **kwargs)
+ self.num_found = 0
+ self.ignore_patterns = []
+ self._paths = {}
+
+ @property
+ def has_content(self):
+ if "django.contrib.staticfiles" not in settings.INSTALLED_APPS:
+ raise ImproperlyConfigured("Could not find staticfiles in "
+ "INSTALLED_APPS setting.")
+ return True
+
+ @property
+ def num_used(self):
+ return len(self._paths[threading.currentThread()])
+
+ nav_title = _('Static files')
+
+ @property
+ def nav_subtitle(self):
+ num_used = self.num_used
+ return ungettext("%(num_used)s file used", "%(num_used)s files used",
+ num_used) % {'num_used': num_used}
+
+ def process_request(self, request):
+ collector.clear_collection()
+
+ def process_response(self, request, response):
+ staticfiles_finders = SortedDict()
+ for finder in finders.get_finders():
+ for path, finder_storage in finder.list(self.ignore_patterns):
+ if getattr(finder_storage, 'prefix', None):
+ prefixed_path = join(finder_storage.prefix, path)
+ else:
+ prefixed_path = path
+ finder_path = '.'.join([finder.__class__.__module__,
+ finder.__class__.__name__])
+ real_path = finder_storage.path(path)
+ payload = (prefixed_path, real_path)
+ staticfiles_finders.setdefault(finder_path, []).append(payload)
+ self.num_found += 1
+
+ dirs = getattr(settings, 'STATICFILES_DIRS', ())
+
+ used_paths = collector.get_collection()
+ self._paths[threading.currentThread()] = used_paths
+
+ self.record_stats({
+ 'num_found': self.num_found,
+ 'num_used': self.num_used,
+ 'staticfiles': used_paths,
+ 'staticfiles_apps': self.get_static_apps(),
+ 'staticfiles_dirs': [normpath(d) for d in dirs],
+ 'staticfiles_finders': staticfiles_finders,
+ })
+
+ def get_static_apps(self):
+ for finder in finders.get_finders():
+ if isinstance(finder, finders.AppDirectoriesFinder):
+ return finder.apps
+ return []
diff --git a/debug_toolbar/templates/debug_toolbar/panels/cache.html b/debug_toolbar/templates/debug_toolbar/panels/cache.html
index 595afd6..82ccc49 100644
--- a/debug_toolbar/templates/debug_toolbar/panels/cache.html
+++ b/debug_toolbar/templates/debug_toolbar/panels/cache.html
@@ -1,5 +1,5 @@
{% load i18n %}
-
{% trans "Summary" %}
+{% trans "Summary" %}
-{% trans "Commands" %}
+{% trans "Commands" %}
{% if calls %}
-{% trans "Calls" %}
+{% trans "Calls" %}
diff --git a/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html b/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html
new file mode 100644
index 0000000..e405a25
--- /dev/null
+++ b/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html
@@ -0,0 +1,57 @@
+{% load i18n %}
+{% load static from staticfiles%}
+
+{% blocktrans count staticfiles_dirs|length as dirs_count %}Static file path{% plural %}Static file paths{% endblocktrans %}
+{% if staticfiles_dirs %}
+
+ {% for staticfiles_dir in staticfiles_dirs %}
+ - {{ staticfiles_dir }}
+ {% endfor %}
+
+{% else %}
+ {% trans "None" %}
+{% endif %}
+
+{% blocktrans count staticfiles_apps|length as apps_count %}Static file app{% plural %}Static file apps{% endblocktrans %}
+{% if staticfiles_apps %}
+
+ {% for static_app in staticfiles_apps %}
+ - {{ static_app }}
+ {% endfor %}
+
+{% else %}
+ {% trans "None" %}
+{% endif %}
+
+{% blocktrans count staticfiles|length as staticfiles_count %}Static file{% plural %}Static files{% endblocktrans %}
+{% if staticfiles %}
+
+{% for staticfile in staticfiles %}
+ - {{ staticfile }}
+ - {{ staticfile.real_path }}
+{% endfor %}
+
+{% else %}
+ {% trans "None" %}
+{% endif %}
+
+
+{% for finder, payload in staticfiles_finders.items %}
+{{ finder }} ({{ payload|length }} files)
+
+
+
+ | {% trans 'Path' %} |
+ {% trans 'Location' %} |
+
+
+
+ {% for path, real_path in payload %}
+
+ | {{ path }} |
+ {{ real_path }} |
+
+ {% endfor %}
+
+
+{% endfor %}
diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py
index d84c79c..0aedb54 100644
--- a/debug_toolbar/utils.py
+++ b/debug_toolbar/utils.py
@@ -4,6 +4,10 @@ import inspect
import os.path
import re
import sys
+try:
+ import threading
+except ImportError:
+ threading = None
import django
from django.core.exceptions import ImproperlyConfigured
@@ -199,3 +203,32 @@ def get_stack(context=1):
framelist.append((frame,) + getframeinfo(frame, context))
frame = frame.f_back
return framelist
+
+
+class ThreadCollector(object):
+ def __init__(self):
+ if threading is None:
+ raise NotImplementedError(
+ "threading module is not available, "
+ "this panel cannot be used without it")
+ self.collections = {} # a dictionary that maps threads to collections
+
+ def get_collection(self, thread=None):
+ """
+ Returns a list of collected items for the provided thread, of if none
+ is provided, returns a list for the current thread.
+ """
+ if thread is None:
+ thread = threading.currentThread()
+ if thread not in self.collections:
+ self.collections[thread] = []
+ return self.collections[thread]
+
+ def clear_collection(self, thread=None):
+ if thread is None:
+ thread = threading.currentThread()
+ if thread in self.collections:
+ del self.collections[thread]
+
+ def collect(self, item, thread=None):
+ self.get_collection(thread).append(item)
diff --git a/example/settings.py b/example/settings.py
index 4c29ba9..ca78f70 100644
--- a/example/settings.py
+++ b/example/settings.py
@@ -89,4 +89,7 @@ DEBUG_TOOLBAR_PANELS = [
'debug_toolbar.panels.logging.LoggingPanel',
'debug_toolbar.panels.redirects.RedirectsPanel',
'debug_toolbar.panels.profiling.ProfilingPanel',
+ 'debug_toolbar.panels.staticfiles.StaticFilesPanel',
]
+
+STATICFILES_DIRS = [os.path.join(BASE_DIR, 'example', 'static')]
diff --git a/example/static/test.css b/example/static/test.css
new file mode 100644
index 0000000..8d7d127
--- /dev/null
+++ b/example/static/test.css
@@ -0,0 +1,3 @@
+body {
+ color: green;
+}
\ No newline at end of file
--
cgit v1.2.3
From 2359b2e61d4f6018049042b3213a91af2b4db9fc Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Sun, 8 Dec 2013 23:47:30 +0100
Subject: Actual show the number of used static files in panel title.
---
debug_toolbar/panels/staticfiles.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/debug_toolbar/panels/staticfiles.py b/debug_toolbar/panels/staticfiles.py
index 9b3829d..791cbbc 100644
--- a/debug_toolbar/panels/staticfiles.py
+++ b/debug_toolbar/panels/staticfiles.py
@@ -75,7 +75,7 @@ class StaticFilesPanel(panels.Panel):
@property
def title(self):
- return (_("Static files (%(num_found)s found)") %
+ return (_("Static files (%(num_found)s found, %(num_used)s used)") %
{'num_found': self.num_found, 'num_used': self.num_used})
def __init__(self, *args, **kwargs):
--
cgit v1.2.3
From e75309b712537f3ee53005bf6330057c9640be21 Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 17:42:04 +0100
Subject: Another pass over the staticfiles panel.
- adds some docstrings
- adds some basic tests
- adds the staticfiles panel to the default list of panels
- fixed a pluralization bug in the template
- refactored some things into own methods for easier testing
---
debug_toolbar/panels/staticfiles.py | 72 +++++++++++++++-------
debug_toolbar/settings.py | 1 +
.../debug_toolbar/panels/staticfiles.html | 2 +-
example/settings.py | 2 +-
tests/additional_static/base.css | 3 +
tests/panels/test_staticfiles.py | 30 +++++++++
tests/settings.py | 2 +
tests/tests.py | 1 +
8 files changed, 88 insertions(+), 25 deletions(-)
create mode 100644 tests/additional_static/base.css
create mode 100644 tests/panels/test_staticfiles.py
diff --git a/debug_toolbar/panels/staticfiles.py b/debug_toolbar/panels/staticfiles.py
index 791cbbc..4ccac71 100644
--- a/debug_toolbar/panels/staticfiles.py
+++ b/debug_toolbar/panels/staticfiles.py
@@ -20,7 +20,9 @@ from debug_toolbar.utils import ThreadCollector
class StaticFile(object):
-
+ """
+ Representing the different properties of a static file.
+ """
def __init__(self, path):
self.path = path
@@ -47,6 +49,11 @@ collector = FileCollector()
class DebugConfiguredStorage(LazyObject):
+ """
+ A staticfiles storage class to be used for collecting which paths
+ are resolved by using the {% static %} template tag (which uses the
+ `url` method).
+ """
def _setup(self):
configured_storage_cls = get_storage_class(settings.STATICFILES_STORAGE)
@@ -81,7 +88,6 @@ class StaticFilesPanel(panels.Panel):
def __init__(self, *args, **kwargs):
super(StaticFilesPanel, self).__init__(*args, **kwargs)
self.num_found = 0
- self.ignore_patterns = []
self._paths = {}
@property
@@ -100,43 +106,63 @@ class StaticFilesPanel(panels.Panel):
@property
def nav_subtitle(self):
num_used = self.num_used
- return ungettext("%(num_used)s file used", "%(num_used)s files used",
+ return ungettext("%(num_used)s file used",
+ "%(num_used)s files used",
num_used) % {'num_used': num_used}
def process_request(self, request):
collector.clear_collection()
def process_response(self, request, response):
- staticfiles_finders = SortedDict()
+ used_paths = collector.get_collection()
+ self._paths[threading.currentThread()] = used_paths
+
+ self.record_stats({
+ 'num_found': self.num_found,
+ 'num_used': self.num_used,
+ 'staticfiles': used_paths,
+ 'staticfiles_apps': self.get_staticfiles_apps(),
+ 'staticfiles_dirs': self.get_staticfiles_dirs(),
+ 'staticfiles_finders': self.get_staticfiles_finders(),
+ })
+
+ def get_staticfiles_finders(self):
+ """
+ Returns a sorted mapping between the finder path and the list
+ of relative and file system paths which that finder was able
+ to find.
+ """
+ finders_mapping = SortedDict()
for finder in finders.get_finders():
- for path, finder_storage in finder.list(self.ignore_patterns):
+ for path, finder_storage in finder.list([]):
if getattr(finder_storage, 'prefix', None):
prefixed_path = join(finder_storage.prefix, path)
else:
prefixed_path = path
- finder_path = '.'.join([finder.__class__.__module__,
- finder.__class__.__name__])
+ finder_cls = finder.__class__
+ finder_path = '.'.join([finder_cls.__module__,
+ finder_cls.__name__])
real_path = finder_storage.path(path)
payload = (prefixed_path, real_path)
- staticfiles_finders.setdefault(finder_path, []).append(payload)
+ finders_mapping.setdefault(finder_path, []).append(payload)
self.num_found += 1
+ return finders_mapping
+ def get_staticfiles_dirs(self):
+ """
+ Returns a list of paths to inspect for additional static files
+ """
dirs = getattr(settings, 'STATICFILES_DIRS', ())
+ return [normpath(d) for d in dirs]
- used_paths = collector.get_collection()
- self._paths[threading.currentThread()] = used_paths
-
- self.record_stats({
- 'num_found': self.num_found,
- 'num_used': self.num_used,
- 'staticfiles': used_paths,
- 'staticfiles_apps': self.get_static_apps(),
- 'staticfiles_dirs': [normpath(d) for d in dirs],
- 'staticfiles_finders': staticfiles_finders,
- })
-
- def get_static_apps(self):
+ def get_staticfiles_apps(self):
+ """
+ Returns a list of app paths that have a static directory
+ """
+ apps = []
for finder in finders.get_finders():
if isinstance(finder, finders.AppDirectoriesFinder):
- return finder.apps
- return []
+ for app in finder.apps:
+ if app not in apps:
+ apps.append(app)
+ return apps
diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py
index bde8a1c..5ed0005 100644
--- a/debug_toolbar/settings.py
+++ b/debug_toolbar/settings.py
@@ -76,6 +76,7 @@ PANELS_DEFAULTS = [
'debug_toolbar.panels.request.RequestPanel',
'debug_toolbar.panels.sql.SQLPanel',
'debug_toolbar.panels.templates.TemplatesPanel',
+ 'debug_toolbar.panels.staticfiles.StaticFilesPanel',
'debug_toolbar.panels.cache.CachePanel',
'debug_toolbar.panels.signals.SignalsPanel',
'debug_toolbar.panels.logging.LoggingPanel',
diff --git a/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html b/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html
index e405a25..eb413b5 100644
--- a/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html
+++ b/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html
@@ -37,7 +37,7 @@
{% for finder, payload in staticfiles_finders.items %}
-{{ finder }} ({{ payload|length }} files)
+{{ finder }} ({% blocktrans count payload|length as payload_count %}{{ payload_count }} file{% plural %}{{ payload_count }} files{% endblocktrans %})
diff --git a/example/settings.py b/example/settings.py
index ca78f70..867b26f 100644
--- a/example/settings.py
+++ b/example/settings.py
@@ -84,12 +84,12 @@ DEBUG_TOOLBAR_PANELS = [
'debug_toolbar.panels.request.RequestPanel',
'debug_toolbar.panels.sql.SQLPanel',
'debug_toolbar.panels.templates.TemplatesPanel',
+ 'debug_toolbar.panels.staticfiles.StaticFilesPanel',
'debug_toolbar.panels.cache.CachePanel',
'debug_toolbar.panels.signals.SignalsPanel',
'debug_toolbar.panels.logging.LoggingPanel',
'debug_toolbar.panels.redirects.RedirectsPanel',
'debug_toolbar.panels.profiling.ProfilingPanel',
- 'debug_toolbar.panels.staticfiles.StaticFilesPanel',
]
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'example', 'static')]
diff --git a/tests/additional_static/base.css b/tests/additional_static/base.css
new file mode 100644
index 0000000..8d7d127
--- /dev/null
+++ b/tests/additional_static/base.css
@@ -0,0 +1,3 @@
+body {
+ color: green;
+}
\ No newline at end of file
diff --git a/tests/panels/test_staticfiles.py b/tests/panels/test_staticfiles.py
new file mode 100644
index 0000000..7f68205
--- /dev/null
+++ b/tests/panels/test_staticfiles.py
@@ -0,0 +1,30 @@
+# coding: utf-8
+
+from __future__ import absolute_import, unicode_literals
+
+from django.conf import settings
+from django.contrib.staticfiles.templatetags import staticfiles
+from django.template import Context, RequestContext, Template
+
+from ..base import BaseTestCase
+
+
+class StaticFilesPanelTestCase(BaseTestCase):
+
+ def setUp(self):
+ super(StaticFilesPanelTestCase, self).setUp()
+ self.panel = self.toolbar.get_panel_by_id('StaticFilesPanel')
+
+ def test_default_case(self):
+ self.panel.process_request(self.request)
+ self.panel.process_response(self.request, self.response)
+ self.assertIn('django.contrib.staticfiles.finders.'
+ 'AppDirectoriesFinder (87 files)', self.panel.content)
+ self.assertIn('django.contrib.staticfiles.finders.'
+ 'FileSystemFinder (1 file)', self.panel.content)
+ self.assertEqual(self.panel.num_used, 0)
+ self.assertEqual(self.panel.num_found, 88)
+ self.assertEqual(self.panel.get_staticfiles_apps(),
+ ['django.contrib.admin', 'debug_toolbar'])
+ self.assertEqual(self.panel.get_staticfiles_dirs(),
+ settings.STATICFILES_DIRS)
diff --git a/tests/settings.py b/tests/settings.py
index 24e0cd4..9ff9fb6 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -40,6 +40,8 @@ ROOT_URLCONF = 'tests.urls'
STATIC_URL = '/static/'
+STATICFILES_DIRS = [os.path.join(BASE_DIR, 'tests', 'additional_static')]
+
# Cache and database
diff --git a/tests/tests.py b/tests/tests.py
index 1818fe7..ca77f5b 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -8,6 +8,7 @@ if django.VERSION[:2] < (1, 6): # unittest-style discovery isn't available
from .panels.test_redirects import * # noqa
from .panels.test_request import * # noqa
from .panels.test_sql import * # noqa
+ from .panels.test_staticfiles import * # noqa
from .panels.test_template import * # noqa
from .test_integration import * # noqa
from .test_utils import * # noqa
--
cgit v1.2.3
From 4e37f8bd430d30807c56372a372e570fe346c0fb Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 17:46:41 +0100
Subject: Use django-discover-runner on older Djangos.
---
requirements_dev.txt | 1 +
tests/settings.py | 5 +++++
tests/tests.py | 14 --------------
tox.ini | 1 +
4 files changed, 7 insertions(+), 14 deletions(-)
delete mode 100644 tests/tests.py
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 8d7af92..74ef847 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -13,6 +13,7 @@ coverage
flake8
selenium
tox
+django-discover-runner
# Documentation
diff --git a/tests/settings.py b/tests/settings.py
index 9ff9fb6..68346ff 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -1,6 +1,8 @@
"""Django settings for tests."""
import os
+import django
+
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
@@ -64,3 +66,6 @@ DEBUG_TOOLBAR_CONFIG = {
# Django's test client sets wsgi.multiprocess to True inappropriately
'RENDER_PANELS': False,
}
+
+if django.VERSION[:2] < (1, 6):
+ TEST_RUNNER = 'discover_runner.DiscoverRunner'
diff --git a/tests/tests.py b/tests/tests.py
deleted file mode 100644
index ca77f5b..0000000
--- a/tests/tests.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import django
-
-if django.VERSION[:2] < (1, 6): # unittest-style discovery isn't available
- from .commands.test_debugsqlshell import * # noqa
- from .panels.test_cache import * # noqa
- from .panels.test_logging import * # noqa
- from .panels.test_profiling import * # noqa
- from .panels.test_redirects import * # noqa
- from .panels.test_request import * # noqa
- from .panels.test_sql import * # noqa
- from .panels.test_staticfiles import * # noqa
- from .panels.test_template import * # noqa
- from .test_integration import * # noqa
- from .test_utils import * # noqa
diff --git a/tox.ini b/tox.ini
index 00941f4..98c487e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -17,6 +17,7 @@ commands = make test
deps =
selenium
sqlparse
+ django-discover-runner
setenv =
PYTHONPATH = {toxinidir}
whitelist_externals = make
--
cgit v1.2.3
From 6bc2eaa6d629e3626645ca2ac0d7f4673576fd44 Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 18:07:16 +0100
Subject: Added the staticfiles panel to the docs.
---
docs/configuration.rst | 1 +
docs/panels.rst | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/docs/configuration.rst b/docs/configuration.rst
index b0a67b1..88226cd 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -33,6 +33,7 @@ setting. The default value is::
'debug_toolbar.panels.headers.HeadersPanel',
'debug_toolbar.panels.request.RequestPanel',
'debug_toolbar.panels.sql.SQLPanel',
+ 'debug_toolbar.panels.staticfiles.StaticFilesPanel',
'debug_toolbar.panels.templates.TemplatesPanel',
'debug_toolbar.panels.cache.CachePanel',
'debug_toolbar.panels.signals.SignalsPanel',
diff --git a/docs/panels.rst b/docs/panels.rst
index 9a6d12c..ed7abbf 100644
--- a/docs/panels.rst
+++ b/docs/panels.rst
@@ -63,6 +63,13 @@ Path: ``debug_toolbar.panels.templates.TemplatesPanel``
Templates and context used, and their template paths.
+Static files
+~~~~~~~~~~~~
+
+Path: ``debug_toolbar.panels.staticfiles.StaticFilesPanel``
+
+Used static files and their locations (via the staticfiles finders).
+
Cache
~~~~~
--
cgit v1.2.3
From e1ba0713fdc24d191b61cb10436fa4621b0bb3b5 Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 18:15:08 +0100
Subject: Added django-discover-runner to travis config, too.
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index ed22c6b..5e1dbf1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,5 +16,5 @@ matrix:
env: DJANGO_VERSION=1.4.10
install:
- pip install -e .
- - pip install Django==$DJANGO_VERSION sqlparse
+ - pip install Django==$DJANGO_VERSION sqlparse django-discover-runner
script: make test
--
cgit v1.2.3
From f55a48addf5d737f3a4b449283bc53b1a0931bd9 Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 18:25:36 +0100
Subject: Made a test less Django version dependent.
---
tests/panels/test_staticfiles.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/panels/test_staticfiles.py b/tests/panels/test_staticfiles.py
index 7f68205..6b3128a 100644
--- a/tests/panels/test_staticfiles.py
+++ b/tests/panels/test_staticfiles.py
@@ -19,7 +19,7 @@ class StaticFilesPanelTestCase(BaseTestCase):
self.panel.process_request(self.request)
self.panel.process_response(self.request, self.response)
self.assertIn('django.contrib.staticfiles.finders.'
- 'AppDirectoriesFinder (87 files)', self.panel.content)
+ 'AppDirectoriesFinder', self.panel.content)
self.assertIn('django.contrib.staticfiles.finders.'
'FileSystemFinder (1 file)', self.panel.content)
self.assertEqual(self.panel.num_used, 0)
--
cgit v1.2.3
From e4fafb92377221201f9089aa972ac6c5504b45dd Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 18:39:25 +0100
Subject: More test relaxing.
---
tests/panels/test_staticfiles.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/panels/test_staticfiles.py b/tests/panels/test_staticfiles.py
index 6b3128a..cc4616a 100644
--- a/tests/panels/test_staticfiles.py
+++ b/tests/panels/test_staticfiles.py
@@ -23,7 +23,7 @@ class StaticFilesPanelTestCase(BaseTestCase):
self.assertIn('django.contrib.staticfiles.finders.'
'FileSystemFinder (1 file)', self.panel.content)
self.assertEqual(self.panel.num_used, 0)
- self.assertEqual(self.panel.num_found, 88)
+ self.assertNotEqual(self.panel.num_found, 0)
self.assertEqual(self.panel.get_staticfiles_apps(),
['django.contrib.admin', 'debug_toolbar'])
self.assertEqual(self.panel.get_staticfiles_dirs(),
--
cgit v1.2.3
From 810a2fbc5157f619eb3d74c73c882f059360506b Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 18:58:15 +0100
Subject: Use collections.OrderedDict if available.
---
debug_toolbar/panels/cache.py | 7 +++++--
debug_toolbar/panels/settings.py | 8 ++++++--
debug_toolbar/panels/staticfiles.py | 7 +++++--
debug_toolbar/panels/versions.py | 9 ++++++---
debug_toolbar/toolbar.py | 9 ++++++---
tests/panels/test_staticfiles.py | 2 --
6 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py
index 1c37c6b..bdc8a4d 100644
--- a/debug_toolbar/panels/cache.py
+++ b/debug_toolbar/panels/cache.py
@@ -10,8 +10,11 @@ from django.core.cache import cache as original_cache, get_cache as original_get
from django.core.cache.backends.base import BaseCache
from django.dispatch import Signal
from django.template import Node
-from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext_lazy as _, ungettext
+try:
+ from collections import OrderedDict
+except ImportError:
+ from django.utils.datastructures import SortedDict as OrderedDict
from debug_toolbar.panels import Panel
from debug_toolbar.utils import (tidy_stacktrace, render_stacktrace,
@@ -139,7 +142,7 @@ class CachePanel(Panel):
self.hits = 0
self.misses = 0
self.calls = []
- self.counts = SortedDict((
+ self.counts = OrderedDict((
('add', 0),
('get', 0),
('set', 0),
diff --git a/debug_toolbar/panels/settings.py b/debug_toolbar/panels/settings.py
index c59d1d1..b054f8b 100644
--- a/debug_toolbar/panels/settings.py
+++ b/debug_toolbar/panels/settings.py
@@ -3,7 +3,10 @@ from __future__ import absolute_import, unicode_literals
from django.conf import settings
from django.views.debug import get_safe_settings
from django.utils.translation import ugettext_lazy as _
-from django.utils.datastructures import SortedDict
+try:
+ from collections import OrderedDict
+except ImportError:
+ from django.utils.datastructures import SortedDict as OrderedDict
from debug_toolbar.panels import Panel
@@ -21,5 +24,6 @@ class SettingsPanel(Panel):
def process_response(self, request, response):
self.record_stats({
- 'settings': SortedDict(sorted(get_safe_settings().items(), key=lambda s: s[0])),
+ 'settings': OrderedDict(sorted(get_safe_settings().items(),
+ key=lambda s: s[0])),
})
diff --git a/debug_toolbar/panels/staticfiles.py b/debug_toolbar/panels/staticfiles.py
index 4ccac71..94bc35a 100644
--- a/debug_toolbar/panels/staticfiles.py
+++ b/debug_toolbar/panels/staticfiles.py
@@ -12,8 +12,11 @@ from django.contrib.staticfiles import finders, storage
from django.contrib.staticfiles.templatetags import staticfiles
from django.utils.translation import ungettext, ugettext_lazy as _
-from django.utils.datastructures import SortedDict
from django.utils.functional import LazyObject
+try:
+ from collections import OrderedDict
+except ImportError:
+ from django.utils.datastructures import SortedDict as OrderedDict
from debug_toolbar import panels
from debug_toolbar.utils import ThreadCollector
@@ -132,7 +135,7 @@ class StaticFilesPanel(panels.Panel):
of relative and file system paths which that finder was able
to find.
"""
- finders_mapping = SortedDict()
+ finders_mapping = OrderedDict()
for finder in finders.get_finders():
for path, finder_storage in finder.list([]):
if getattr(finder_storage, 'prefix', None):
diff --git a/debug_toolbar/panels/versions.py b/debug_toolbar/panels/versions.py
index 85672b8..321ba6e 100644
--- a/debug_toolbar/panels/versions.py
+++ b/debug_toolbar/panels/versions.py
@@ -4,9 +4,12 @@ import sys
import django
from django.conf import settings
-from django.utils.translation import ugettext_lazy as _
-from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module
+from django.utils.translation import ugettext_lazy as _
+try:
+ from collections import OrderedDict
+except ImportError:
+ from django.utils.datastructures import SortedDict as OrderedDict
from debug_toolbar.panels import Panel
@@ -46,6 +49,6 @@ class VersionsPanel(Panel):
versions = sorted(versions, key=lambda version: version[0])
self.record_stats({
- 'versions': SortedDict(versions),
+ 'versions': OrderedDict(versions),
'paths': sys.path,
})
diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py
index 36c301a..82851b3 100644
--- a/debug_toolbar/toolbar.py
+++ b/debug_toolbar/toolbar.py
@@ -9,8 +9,11 @@ import uuid
from django.conf.urls import patterns, url
from django.core.exceptions import ImproperlyConfigured
from django.template.loader import render_to_string
-from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module
+try:
+ from collections import OrderedDict
+except ImportError:
+ from django.utils.datastructures import SortedDict as OrderedDict
from debug_toolbar import settings as dt_settings
@@ -20,7 +23,7 @@ class DebugToolbar(object):
def __init__(self, request):
self.request = request
self.config = dt_settings.CONFIG.copy()
- self._panels = SortedDict()
+ self._panels = OrderedDict()
for panel_class in self.get_panel_classes():
panel_instance = panel_class(self)
self._panels[panel_instance.panel_id] = panel_instance
@@ -61,7 +64,7 @@ class DebugToolbar(object):
# Handle storing toolbars in memory and fetching them later on
- _store = SortedDict()
+ _store = OrderedDict()
def should_render_panels(self):
render_panels = self.config['RENDER_PANELS']
diff --git a/tests/panels/test_staticfiles.py b/tests/panels/test_staticfiles.py
index cc4616a..70a7b96 100644
--- a/tests/panels/test_staticfiles.py
+++ b/tests/panels/test_staticfiles.py
@@ -3,8 +3,6 @@
from __future__ import absolute_import, unicode_literals
from django.conf import settings
-from django.contrib.staticfiles.templatetags import staticfiles
-from django.template import Context, RequestContext, Template
from ..base import BaseTestCase
--
cgit v1.2.3
From 7a04ec6c4f808f59d9f689f72efb182640308494 Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 19:02:24 +0100
Subject: Some imports.
---
debug_toolbar/panels/staticfiles.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/debug_toolbar/panels/staticfiles.py b/debug_toolbar/panels/staticfiles.py
index 94bc35a..0ecba51 100644
--- a/debug_toolbar/panels/staticfiles.py
+++ b/debug_toolbar/panels/staticfiles.py
@@ -1,4 +1,4 @@
-from __future__ import absolute_import
+from __future__ import absolute_import, unicode_literals
from os.path import normpath, join
try:
import threading
@@ -11,8 +11,9 @@ from django.core.files.storage import get_storage_class
from django.contrib.staticfiles import finders, storage
from django.contrib.staticfiles.templatetags import staticfiles
-from django.utils.translation import ungettext, ugettext_lazy as _
+from django.utils.encoding import python_2_unicode_compatible
from django.utils.functional import LazyObject
+from django.utils.translation import ungettext, ugettext_lazy as _
try:
from collections import OrderedDict
except ImportError:
@@ -22,6 +23,7 @@ from debug_toolbar import panels
from debug_toolbar.utils import ThreadCollector
+@python_2_unicode_compatible
class StaticFile(object):
"""
Representing the different properties of a static file.
--
cgit v1.2.3
From ebc16cb2a5c9098d91ca3033626808f73e58afad Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 19:06:09 +0100
Subject: Use enable_instrumentation/disable_instrumentation instead of module
level monkey patching.
---
debug_toolbar/panels/staticfiles.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/debug_toolbar/panels/staticfiles.py b/debug_toolbar/panels/staticfiles.py
index 0ecba51..9813609 100644
--- a/debug_toolbar/panels/staticfiles.py
+++ b/debug_toolbar/panels/staticfiles.py
@@ -31,7 +31,7 @@ class StaticFile(object):
def __init__(self, path):
self.path = path
- def __unicode__(self):
+ def __str__(self):
return self.path
def real_path(self):
@@ -75,8 +75,6 @@ class DebugConfiguredStorage(LazyObject):
self._wrapped = DebugStaticFilesStorage(collector)
-storage.staticfiles_storage = staticfiles.staticfiles_storage = DebugConfiguredStorage()
-
class StaticFilesPanel(panels.Panel):
"""
@@ -95,6 +93,13 @@ class StaticFilesPanel(panels.Panel):
self.num_found = 0
self._paths = {}
+ def enable_instrumentation(self):
+ self._unpatched_staticfiles_storage = storage.staticfiles_storage
+ storage.staticfiles_storage = staticfiles.staticfiles_storage = DebugConfiguredStorage()
+
+ def disable_instrumentation(self):
+ storage.staticfiles_storage = staticfiles.staticfiles_storage = self._unpatched_staticfiles_storage
+
@property
def has_content(self):
if "django.contrib.staticfiles" not in settings.INSTALLED_APPS:
--
cgit v1.2.3
From bdbe57d6e13241f852860336f55bca0d88bd4384 Mon Sep 17 00:00:00 2001
From: Jannis Leidel
Date: Mon, 9 Dec 2013 19:11:38 +0100
Subject: Storing the original on module level.
---
debug_toolbar/panels/staticfiles.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/debug_toolbar/panels/staticfiles.py b/debug_toolbar/panels/staticfiles.py
index 9813609..f212f2b 100644
--- a/debug_toolbar/panels/staticfiles.py
+++ b/debug_toolbar/panels/staticfiles.py
@@ -75,6 +75,8 @@ class DebugConfiguredStorage(LazyObject):
self._wrapped = DebugStaticFilesStorage(collector)
+_original_storage = storage.staticfiles_storage
+
class StaticFilesPanel(panels.Panel):
"""
@@ -94,11 +96,10 @@ class StaticFilesPanel(panels.Panel):
self._paths = {}
def enable_instrumentation(self):
- self._unpatched_staticfiles_storage = storage.staticfiles_storage
storage.staticfiles_storage = staticfiles.staticfiles_storage = DebugConfiguredStorage()
def disable_instrumentation(self):
- storage.staticfiles_storage = staticfiles.staticfiles_storage = self._unpatched_staticfiles_storage
+ storage.staticfiles_storage = staticfiles.staticfiles_storage = _original_storage
@property
def has_content(self):
--
cgit v1.2.3