[1.2.X] Fixed #15368 - test failures due to regression with RequestContext

Thanks to cyberdelia for the reports on this.

Backport of [15660] from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15661 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2011-02-27 00:28:53 +00:00
parent 120d01c20b
commit e233917832
5 changed files with 28 additions and 13 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)
@ -87,10 +91,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)
def update(self, other_dict): def update(self, other_dict):
"Like dict.update(). Pushes an entire dictionary's keys and values onto the context." "Like dict.update(). Pushes an entire dictionary's keys and values onto the context."
if not hasattr(other_dict, '__getitem__'): if not hasattr(other_dict, '__getitem__'):
@ -166,7 +166,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)

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, loader) Context, loader)
import django.template.context
from django.test import TestCase, Client from django.test import TestCase, Client
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

@ -26,4 +26,5 @@ urlpatterns = patterns('',
(r'^parse_unicode_json/$', views.return_json_file), (r'^parse_unicode_json/$', views.return_json_file),
(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'^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"
@ -91,3 +92,7 @@ def check_headers(request):
"A view that responds with value of the X-ARG-CHECK header" "A view that responds with value of the X-ARG-CHECK header"
return HttpResponse('HTTP_X_ARG_CHECK: %s' % request.META.get('HTTP_X_ARG_CHECK', 'Undefined')) return HttpResponse('HTTP_X_ARG_CHECK: %s' % request.META.get('HTTP_X_ARG_CHECK', 'Undefined'))
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, {}))