diff options
| author | Aymeric Augustin | 2013-12-14 12:47:28 -0800 | 
|---|---|---|
| committer | Aymeric Augustin | 2013-12-14 12:47:28 -0800 | 
| commit | dbed3e7c72f930c285f17206879f6bd1d46f67a1 (patch) | |
| tree | 317b063328fab25298262db1e7ae81ad50282a4a | |
| parent | 59e4931d5880ed24cb49734e81c7ed538c98fa45 (diff) | |
| parent | bdbe57d6e13241f852860336f55bca0d88bd4384 (diff) | |
| download | django-debug-toolbar-dbed3e7c72f930c285f17206879f6bd1d46f67a1.tar.bz2 | |
Merge pull request #494 from django-debug-toolbar/staticfiles
Added staticfiles panel class.
| -rw-r--r-- | .travis.yml | 2 | ||||
| -rw-r--r-- | debug_toolbar/panels/cache.py | 7 | ||||
| -rw-r--r-- | debug_toolbar/panels/logging.py | 41 | ||||
| -rw-r--r-- | debug_toolbar/panels/settings.py | 8 | ||||
| -rw-r--r-- | debug_toolbar/panels/staticfiles.py | 179 | ||||
| -rw-r--r-- | debug_toolbar/panels/versions.py | 9 | ||||
| -rw-r--r-- | debug_toolbar/settings.py | 1 | ||||
| -rw-r--r-- | debug_toolbar/templates/debug_toolbar/panels/cache.html | 6 | ||||
| -rw-r--r-- | debug_toolbar/templates/debug_toolbar/panels/staticfiles.html | 57 | ||||
| -rw-r--r-- | debug_toolbar/toolbar.py | 9 | ||||
| -rw-r--r-- | debug_toolbar/utils.py | 33 | ||||
| -rw-r--r-- | docs/configuration.rst | 1 | ||||
| -rw-r--r-- | docs/panels.rst | 7 | ||||
| -rw-r--r-- | example/settings.py | 3 | ||||
| -rw-r--r-- | example/static/test.css | 3 | ||||
| -rw-r--r-- | requirements_dev.txt | 1 | ||||
| -rw-r--r-- | tests/additional_static/base.css | 3 | ||||
| -rw-r--r-- | tests/panels/test_staticfiles.py | 28 | ||||
| -rw-r--r-- | tests/settings.py | 7 | ||||
| -rw-r--r-- | tests/tests.py | 13 | ||||
| -rw-r--r-- | tox.ini | 1 | 
21 files changed, 360 insertions, 59 deletions
| 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 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/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/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 new file mode 100644 index 0000000..f212f2b --- /dev/null +++ b/debug_toolbar/panels/staticfiles.py @@ -0,0 +1,179 @@ +from __future__ import absolute_import, unicode_literals +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.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: +    from django.utils.datastructures import SortedDict as OrderedDict + +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. +    """ +    def __init__(self, path): +        self.path = path + +    def __str__(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): +    """ +    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) + +        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) + +_original_storage = storage.staticfiles_storage + + +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_used)s used)") % +                {'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._paths = {} + +    def enable_instrumentation(self): +        storage.staticfiles_storage = staticfiles.staticfiles_storage = DebugConfiguredStorage() + +    def disable_instrumentation(self): +        storage.staticfiles_storage = staticfiles.staticfiles_storage = _original_storage + +    @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): +        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 = OrderedDict() +        for finder in finders.get_finders(): +            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_cls = finder.__class__ +                finder_path = '.'.join([finder_cls.__module__, +                                        finder_cls.__name__]) +                real_path = finder_storage.path(path) +                payload = (prefixed_path, real_path) +                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] + +    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): +                for app in finder.apps: +                    if app not in apps: +                        apps.append(app) +        return apps 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/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/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 %} -<h3>{% trans "Summary" %}</h3> +<h4>{% trans "Summary" %}</h4>  <table>  	<thead>  	<tr> @@ -18,7 +18,7 @@  	</tr>  	</tbody>  </table> -<h3>{% trans "Commands" %}</h3> +<h4>{% trans "Commands" %}</h4>  <table>  	<thead>  	<tr> @@ -36,7 +36,7 @@  	</tbody>  </table>  {% if calls %} -<h3>{% trans "Calls" %}</h3> +<h4>{% trans "Calls" %}</h4>  <table>  	<thead>  		<tr> 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..eb413b5 --- /dev/null +++ b/debug_toolbar/templates/debug_toolbar/panels/staticfiles.html @@ -0,0 +1,57 @@ +{% load i18n %} +{% load static from staticfiles%} + +<h4>{% blocktrans count staticfiles_dirs|length as dirs_count %}Static file path{% plural %}Static file paths{% endblocktrans %}</h4> +{% if staticfiles_dirs %} +    <ol> +    {% for staticfiles_dir in staticfiles_dirs %} +        <li>{{ staticfiles_dir }}</li> +    {% endfor %} +    </ol> +{% else %} +    <p>{% trans "None" %}</p> +{% endif %} + +<h4>{% blocktrans count staticfiles_apps|length as apps_count %}Static file app{% plural %}Static file apps{% endblocktrans %}</h4> +{% if staticfiles_apps %} +    <ol> +    {% for static_app in staticfiles_apps %} +        <li>{{ static_app }}</li> +    {% endfor %} +    </ol> +{% else %} +    <p>{% trans "None" %}</p> +{% endif %} + +<h4>{% blocktrans count staticfiles|length as staticfiles_count %}Static file{% plural %}Static files{% endblocktrans %}</h4> +{% if staticfiles %} +<dl> +{% for staticfile in staticfiles %} +    <dt><strong><a class="toggleTemplate" href="{{ staticfile.url }}">{{ staticfile }}</a></strong></dt> +    <dd><samp>{{ staticfile.real_path }}</samp></dd> +{% endfor %} +</dl> +{% else %} +    <p>{% trans "None" %}</p> +{% endif %} + + +{% for finder, payload in staticfiles_finders.items %} +<h4>{{ finder }} ({% blocktrans count payload|length as payload_count %}{{ payload_count }} file{% plural %}{{ payload_count }} files{% endblocktrans %})</h4> +<table> +    <thead> +        <tr> +            <th>{% trans 'Path' %}</th> +            <th>{% trans 'Location' %}</th> +        </tr> +    </thead> +    <tbody> +    {% for path, real_path in payload %} +    <tr class="{% cycle 'djDebugOdd' 'djDebugEven' %}"> +        <td>{{ path }}</td> +        <td>{{ real_path }}</td> +    </tr> +    {% endfor %} +    </tbody> +</table> +{% endfor %} diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py index b08efeb..ec840dd 100644 --- a/debug_toolbar/toolbar.py +++ b/debug_toolbar/toolbar.py @@ -11,8 +11,11 @@ from django.conf.urls import patterns, url  from django.core.exceptions import ImproperlyConfigured  from django.template import TemplateSyntaxError  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 @@ -22,7 +25,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 @@ -73,7 +76,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/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/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  ~~~~~ diff --git a/example/settings.py b/example/settings.py index 4c29ba9..867b26f 100644 --- a/example/settings.py +++ b/example/settings.py @@ -84,9 +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',  ] + +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 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/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..70a7b96 --- /dev/null +++ b/tests/panels/test_staticfiles.py @@ -0,0 +1,28 @@ +# coding: utf-8 + +from __future__ import absolute_import, unicode_literals + +from django.conf import settings + +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', self.panel.content) +        self.assertIn('django.contrib.staticfiles.finders.' +                      'FileSystemFinder (1 file)', self.panel.content) +        self.assertEqual(self.panel.num_used, 0) +        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(), +                         settings.STATICFILES_DIRS) diff --git a/tests/settings.py b/tests/settings.py index 24e0cd4..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__)) @@ -40,6 +42,8 @@ ROOT_URLCONF = 'tests.urls'  STATIC_URL = '/static/' +STATICFILES_DIRS = [os.path.join(BASE_DIR, 'tests', 'additional_static')] +  # Cache and database @@ -62,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 1818fe7..0000000 --- a/tests/tests.py +++ /dev/null @@ -1,13 +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_template import *                                 # noqa -    from .test_integration import *                                     # noqa -    from .test_utils import *                                           # noqa @@ -17,6 +17,7 @@ commands = make test  deps =      selenium      sqlparse +    django-discover-runner  setenv =      PYTHONPATH = {toxinidir}  whitelist_externals = make | 
