Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

#6412 - Check for file permissions for proper error messages #443

Closed
wants to merge 1 commit into from

2 participants

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 21, 2012
  1. @lqc
This page is out of date. Refresh to see the latest.
View
22 django/views/debug.py
@@ -219,6 +219,15 @@ def __init__(self, request, exc_type, exc_value, tb, is_email=False):
self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
self.exc_type = type(self.exc_value)
+ def format_path_status(self, path):
+ if not os.path.exists(path):
+ return "File does not exist"
+ if not os.path.isfile(path):
+ return "Not a file"
+ if not os.access(path, os.R_OK):
+ return "File is not readable"
+ return "File exists"
+
def get_traceback_data(self):
"Return a Context instance containing traceback information."
@@ -231,8 +240,9 @@ def get_traceback_data(self):
source_list_func = loader.get_template_sources
# NOTE: This assumes exc_value is the name of the template that
# the loader attempted to load.
- template_list = [{'name': t, 'exists': os.path.exists(t)} \
- for t in source_list_func(str(self.exc_value))]
+ template_list = [{
+ 'name': t, 'status': self.format_path_status(t)
+ } for t in source_list_func(str(self.exc_value))]
except AttributeError:
template_list = []
loader_name = loader.__module__ + '.' + loader.__class__.__name__
@@ -646,7 +656,9 @@ def empty_urlconf(request):
<ul>
{% for loader in loader_debug_info %}
<li>Using loader <code>{{ loader.loader }}</code>:
- <ul>{% for t in loader.templates %}<li><code>{{ t.name }}</code> (File {% if t.exists %}exists{% else %}does not exist{% endif %})</li>{% endfor %}</ul>
+ <ul>
+ {% for t in loader.templates %}<li><code>{{ t.name }}</code> ({{ t.status }})</li>{% endfor %}
+ </ul>
</li>
{% endfor %}
</ul>
@@ -749,7 +761,7 @@ def empty_urlconf(request):
{% if template_does_not_exist %}Template Loader Error:
{% if loader_debug_info %}Django tried loading these templates, in this order:
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
-{% for t in loader.templates %}{{ t.name }} (File {% if t.exists %}exists{% else %}does not exist{% endif %})
+{% for t in loader.templates %}{{ t.name }} ({{ t.status }})
{% endfor %}{% endfor %}
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
{% endif %}
@@ -939,7 +951,7 @@ def empty_urlconf(request):
{% if template_does_not_exist %}Template loader Error:
{% if loader_debug_info %}Django tried loading these templates, in this order:
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
-{% for t in loader.templates %}{{ t.name }} (File {% if t.exists %}exists{% else %}does not exist{% endif %})
+{% for t in loader.templates %}{{ t.name }} ({{ t.status }})
{% endfor %}{% endfor %}
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
{% endif %}
View
8 tests/regressiontests/views/tests/__init__.py
@@ -1,8 +1,10 @@
from __future__ import absolute_import
-from .debug import (DebugViewTests, ExceptionReporterTests,
- ExceptionReporterTests, PlainTextReportTests, ExceptionReporterFilterTests,
- AjaxResponseExceptionReporterFilter)
+from .debug import (DebugViewTests,
+ ExceptionReporterTests,
+ PlainTextReportTests,
+ ExceptionReporterFilterTests,
+ AjaxResponseExceptionReporterFilter)
from .defaults import DefaultsTests
from .i18n import JsI18NTests, I18NTests, JsI18NTestsMultiPackage
from .shortcuts import ShortcutTests
View
42 tests/regressiontests/views/tests/debug.py
@@ -6,6 +6,8 @@
import inspect
import os
import sys
+import tempfile
+import shutil
from django.conf import settings
from django.core import mail
@@ -16,9 +18,11 @@
restore_template_loaders)
from django.views.debug import ExceptionReporter
+
from .. import BrokenException, except_args
from ..views import (sensitive_view, non_sensitive_view, paranoid_view,
custom_exception_reporter_filter_view, sensitive_method_view)
+from django.utils.unittest.case import skipIf
@override_settings(DEBUG=True, TEMPLATE_DEBUG=True)
@@ -76,9 +80,41 @@ def test_template_exceptions(self):
raising_loc)
def test_template_loader_postmortem(self):
- response = self.client.get(reverse('raises_template_does_not_exist'))
- template_path = os.path.join('templates', 'i_dont_exist.html')
- self.assertContains(response, template_path, status_code=500)
+ template_name = "notfound.html"
+ tempdir = os.path.abspath(tempfile.mkdtemp(__name__))
+ try:
+ template_path = os.path.join(tempdir, template_name)
+ with override_settings(TEMPLATE_DIRS=(tempdir,)):
+ response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
+ self.assertContains(response, "%s (File does not exist)" % template_path, status_code=500, count=1)
+ finally:
+ shutil.rmtree(tempdir)
+
+ @skipIf(sys.platform == "win32", "Python on Windows doesn't have working os.chmod() and os.access().")
+ def test_template_loader_postmortem_notreadable(self):
+ template_name = "unreadable.html"
+ tempdir = os.path.abspath(tempfile.mkdtemp(__name__))
+ try:
+ template_path = os.path.join(tempdir, template_name)
+ open(template_path, "w+").close()
+ os.chmod(template_path, 0o0222)
+ with override_settings(TEMPLATE_DIRS=(tempdir,)):
+ response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
+ self.assertContains(response, "%s (File is not readable)" % template_path, status_code=500, count=1)
+ finally:
+ shutil.rmtree(tempdir)
+
+ def test_template_loader_postmortem_notafile(self):
+ template_name = "directory.html"
+ tempdir = os.path.abspath(tempfile.mkdtemp(__name__))
+ try:
+ template_path = os.path.join(tempdir, template_name)
+ os.mkdir(template_path)
+ with override_settings(TEMPLATE_DIRS=(tempdir,)):
+ response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
+ self.assertContains(response, "%s (Not a file)" % template_path, status_code=500, count=1)
+ finally:
+ shutil.rmtree(tempdir)
class ExceptionReporterTests(TestCase):
View
2  tests/regressiontests/views/urls.py
@@ -59,5 +59,5 @@
urlpatterns += patterns('regressiontests.views.views',
url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'),
- url(r'^raises_template_does_not_exist/$', 'raises_template_does_not_exist', name='raises_template_does_not_exist'),
+ url(r'^raises_template_does_not_exist/(?P<path>.+)$', 'raises_template_does_not_exist', name='raises_template_does_not_exist'),
)
View
4 tests/regressiontests/views/views.py
@@ -109,11 +109,11 @@ def render_view_with_current_app_conflict(request):
'bar': 'BAR',
}, current_app="foobar_app", context_instance=RequestContext(request))
-def raises_template_does_not_exist(request):
+def raises_template_does_not_exist(request, path='i_dont_exist.html'):
# We need to inspect the HTML generated by the fancy 500 debug view but
# the test client ignores it, so we send it explicitly.
try:
- return render_to_response('i_dont_exist.html')
+ return render_to_response(path)
except TemplateDoesNotExist:
return technical_500_response(request, *sys.exc_info())
Something went wrong with that request. Please try again.