Fixed #15368 - test failures due to regression with RequestContext

Thanks to cyberdelia for the reports on this.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15660 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2011-02-27 00:24:35 +00:00
parent b5b5ba6cd9
commit 2366415f48
5 changed files with 29 additions and 15 deletions

View File

@ -14,14 +14,21 @@ class ContextPopException(Exception):
"pop() has been called more times than push()" "pop() has been called more times than push()"
pass pass
class EmptyClass(object):
# No-op class which takes no args to its __init__ method, to help implement
# __copy__
pass
class BaseContext(object): class BaseContext(object):
def __init__(self, dict_=None): def __init__(self, dict_=None):
dict_ = dict_ or {} dict_ = dict_ or {}
self.dicts = [dict_] self.dicts = [dict_]
def __copy__(self): def __copy__(self):
duplicate = self._new() duplicate = EmptyClass()
duplicate.dicts = [dict_ for dict_ in self.dicts] duplicate.__class__ = self.__class__
duplicate.__dict__ = self.__dict__.copy()
duplicate.dicts = duplicate.dicts[:]
return duplicate return duplicate
def __repr__(self): def __repr__(self):
@ -31,9 +38,6 @@ class BaseContext(object):
for d in reversed(self.dicts): for d in reversed(self.dicts):
yield d yield d
def _new(self):
return self.__class__()
def push(self): def push(self):
d = {} d = {}
self.dicts.append(d) self.dicts.append(d)
@ -88,11 +92,6 @@ class Context(BaseContext):
duplicate.render_context = copy(self.render_context) duplicate.render_context = copy(self.render_context)
return duplicate return duplicate
def _new(self):
return self.__class__(autoescape=self.autoescape,
current_app=self.current_app,
use_l10n=self.use_l10n)
def update(self, other_dict): def update(self, other_dict):
"Pushes other_dict to the stack of dictionaries in the Context" "Pushes other_dict to the stack of dictionaries in the Context"
if not hasattr(other_dict, '__getitem__'): if not hasattr(other_dict, '__getitem__'):
@ -168,8 +167,3 @@ class RequestContext(Context):
processors = tuple(processors) processors = tuple(processors)
for processor in get_standard_processors() + processors: for processor in get_standard_processors() + processors:
self.update(processor(request)) self.update(processor(request))
def _new(self):
return self.__class__(request=HttpRequest(),
current_app=self.current_app,
use_l10n=self.use_l10n)

View File

@ -9,6 +9,7 @@ from django.core.exceptions import SuspiciousOperation
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.template import (TemplateDoesNotExist, TemplateSyntaxError, from django.template import (TemplateDoesNotExist, TemplateSyntaxError,
Context, Template, loader) Context, Template, loader)
import django.template.context
from django.test import Client, TestCase from django.test import Client, TestCase
from django.test.client import encode_file from django.test.client import encode_file
from django.test.utils import ContextList from django.test.utils import ContextList
@ -648,6 +649,17 @@ class ContextTests(TestCase):
except KeyError, e: except KeyError, e:
self.assertEquals(e.args[0], 'does-not-exist') self.assertEquals(e.args[0], 'does-not-exist')
def test_15368(self):
# Need to insert a context processor that assumes certain things about
# the request instance. This triggers a bug caused by some ways of
# copying RequestContext.
try:
django.template.context._standard_context_processors = (lambda request: {'path': request.special_path},)
response = self.client.get("/test_client_regress/request_context_view/")
self.assertContains(response, 'Path: /test_client_regress/request_context_view/')
finally:
django.template.context._standard_context_processors = None
class SessionTests(TestCase): class SessionTests(TestCase):
fixtures = ['testdata.json'] fixtures = ['testdata.json']

View File

@ -0,0 +1 @@
Path: {{ path }}

View File

@ -27,4 +27,5 @@ urlpatterns = patterns('',
(r'^check_headers/$', views.check_headers), (r'^check_headers/$', views.check_headers),
(r'^check_headers_redirect/$', redirect_to, {'url': '/test_client_regress/check_headers/'}), (r'^check_headers_redirect/$', redirect_to, {'url': '/test_client_regress/check_headers/'}),
(r'^raw_post_data/$', views.raw_post_data), (r'^raw_post_data/$', views.raw_post_data),
(r'^request_context_view/$', views.request_context_view),
) )

View File

@ -7,6 +7,7 @@ from django.utils import simplejson
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.test.client import CONTENT_TYPE_RE from django.test.client import CONTENT_TYPE_RE
from django.template import RequestContext
def no_template_view(request): def no_template_view(request):
"A simple view that expects a GET request, and returns a rendered template" "A simple view that expects a GET request, and returns a rendered template"
@ -94,3 +95,8 @@ def check_headers(request):
def raw_post_data(request): def raw_post_data(request):
"A view that is requested with GET and accesses request.raw_post_data. Refs #14753." "A view that is requested with GET and accesses request.raw_post_data. Refs #14753."
return HttpResponse(request.raw_post_data) return HttpResponse(request.raw_post_data)
def request_context_view(request):
# Special attribute that won't be present on a plain HttpRequest
request.special_path = request.path
return render_to_response('request_context.html', context_instance=RequestContext(request, {}))