Fixed #24476 -- Added context manager/decorator for overriding script prefix.

Tests were using an undocumented keyword argument for easily overriding
script prefix while reversing. This is now changed into a test utility
which can be used as decorator or context manager.
This commit is contained in:
Bas Peschier 2015-03-15 11:26:47 +01:00 committed by Tim Graham
parent 6bff343989
commit 0339844b70
6 changed files with 54 additions and 45 deletions

View File

@ -527,14 +527,13 @@ def resolve(path, urlconf=None):
return get_resolver(urlconf).resolve(path) return get_resolver(urlconf).resolve(path)
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None): def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
if urlconf is None: if urlconf is None:
urlconf = get_urlconf() urlconf = get_urlconf()
resolver = get_resolver(urlconf) resolver = get_resolver(urlconf)
args = args or [] args = args or []
kwargs = kwargs or {} kwargs = kwargs or {}
if prefix is None:
prefix = get_script_prefix() prefix = get_script_prefix()
if not isinstance(viewname, six.string_types): if not isinstance(viewname, six.string_types):

View File

@ -12,11 +12,13 @@ from django.apps import apps
from django.conf import UserSettingsHolder, settings from django.conf import UserSettingsHolder, settings
from django.core import mail from django.core import mail
from django.core.signals import request_started from django.core.signals import request_started
from django.core.urlresolvers import get_script_prefix, set_script_prefix
from django.db import reset_queries from django.db import reset_queries
from django.http import request from django.http import request
from django.template import Template from django.template import Template
from django.test.signals import setting_changed, template_rendered from django.test.signals import setting_changed, template_rendered
from django.utils import six from django.utils import six
from django.utils.decorators import ContextDecorator
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.translation import deactivate from django.utils.translation import deactivate
@ -595,3 +597,22 @@ def require_jinja2(test_func):
'OPTIONS': {'keep_trailing_newline': True}, 'OPTIONS': {'keep_trailing_newline': True},
}])(test_func) }])(test_func)
return test_func return test_func
class ScriptPrefix(ContextDecorator):
def __enter__(self):
set_script_prefix(self.prefix)
def __exit__(self, exc_type, exc_val, traceback):
set_script_prefix(self.old_prefix)
def __init__(self, prefix):
self.prefix = prefix
self.old_prefix = get_script_prefix()
def override_script_prefix(prefix):
"""
Decorator or context manager to temporary override the script prefix.
"""
return ScriptPrefix(prefix)

View File

@ -22,15 +22,13 @@ from django.contrib.staticfiles.storage import staticfiles_storage
from django.core import mail from django.core import mail
from django.core.checks import Error from django.core.checks import Error
from django.core.files import temp as tempfile from django.core.files import temp as tempfile
from django.core.urlresolvers import ( from django.core.urlresolvers import NoReverseMatch, resolve, reverse
NoReverseMatch, get_script_prefix, resolve, reverse, set_script_prefix,
)
from django.forms.utils import ErrorList from django.forms.utils import ErrorList
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.test import ( from django.test import (
TestCase, modify_settings, override_settings, skipUnlessDBFeature, TestCase, modify_settings, override_settings, skipUnlessDBFeature,
) )
from django.test.utils import patch_logger from django.test.utils import override_script_prefix, patch_logger
from django.utils import formats, six, translation from django.utils import formats, six, translation
from django.utils._os import upath from django.utils._os import upath
from django.utils.cache import get_max_age from django.utils.cache import get_max_age
@ -5822,16 +5820,12 @@ class AdminKeepChangeListFiltersTests(TestCase):
add_preserved_filters(context, url), add_preserved_filters(context, url),
) )
original_prefix = get_script_prefix() with override_script_prefix('/prefix/'):
try:
set_script_prefix('/prefix/')
url = reverse('admin:auth_user_changelist', current_app=self.admin_site.name) url = reverse('admin:auth_user_changelist', current_app=self.admin_site.name)
self.assertURLEqual( self.assertURLEqual(
self.get_changelist_url(), self.get_changelist_url(),
add_preserved_filters(context, url), add_preserved_filters(context, url),
) )
finally:
set_script_prefix(original_prefix)
class NamespacedAdminKeepChangeListFiltersTests(AdminKeepChangeListFiltersTests): class NamespacedAdminKeepChangeListFiltersTests(AdminKeepChangeListFiltersTests):

View File

@ -3,8 +3,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.contrib.flatpages.models import FlatPage from django.contrib.flatpages.models import FlatPage
from django.core.urlresolvers import clear_script_prefix, set_script_prefix
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_script_prefix
class FlatpageModelTests(TestCase): class FlatpageModelTests(TestCase):
@ -13,10 +13,7 @@ class FlatpageModelTests(TestCase):
pf = FlatPage(title="Café!", url='/café/') pf = FlatPage(title="Café!", url='/café/')
self.assertEqual(pf.get_absolute_url(), '/caf%C3%A9/') self.assertEqual(pf.get_absolute_url(), '/caf%C3%A9/')
@override_script_prefix('/beverages/')
def test_get_absolute_url_honors_script_prefix(self): def test_get_absolute_url_honors_script_prefix(self):
pf = FlatPage(title="Tea!", url='/tea/') pf = FlatPage(title="Tea!", url='/tea/')
set_script_prefix('/beverages/')
try:
self.assertEqual(pf.get_absolute_url(), '/beverages/tea/') self.assertEqual(pf.get_absolute_url(), '/beverages/tea/')
finally:
clear_script_prefix()

View File

@ -3,13 +3,12 @@ from __future__ import unicode_literals
import os import os
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import ( from django.core.urlresolvers import clear_url_caches, reverse, translate_url
clear_url_caches, reverse, set_script_prefix, translate_url,
)
from django.http import HttpResponsePermanentRedirect from django.http import HttpResponsePermanentRedirect
from django.middleware.locale import LocaleMiddleware from django.middleware.locale import LocaleMiddleware
from django.template import Context, Template from django.template import Context, Template
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from django.test.utils import override_script_prefix
from django.utils import translation from django.utils import translation
from django.utils._os import upath from django.utils._os import upath
@ -314,19 +313,11 @@ class URLRedirectWithScriptAliasTests(URLTestCaseBase):
""" """
#21579 - LocaleMiddleware should respect the script prefix. #21579 - LocaleMiddleware should respect the script prefix.
""" """
def setUp(self):
super(URLRedirectWithScriptAliasTests, self).setUp()
self.script_prefix = '/script_prefix'
set_script_prefix(self.script_prefix)
def tearDown(self):
super(URLRedirectWithScriptAliasTests, self).tearDown()
# reset script prefix
set_script_prefix('')
def test_language_prefix_with_script_prefix(self): def test_language_prefix_with_script_prefix(self):
response = self.client.get('/prefixed/', HTTP_ACCEPT_LANGUAGE='en', SCRIPT_NAME=self.script_prefix) prefix = '/script_prefix'
self.assertRedirects(response, '%s/en/prefixed/' % self.script_prefix, target_status_code=404) with override_script_prefix(prefix):
response = self.client.get('/prefixed/', HTTP_ACCEPT_LANGUAGE='en', SCRIPT_NAME=prefix)
self.assertRedirects(response, '%s/en/prefixed/' % prefix, target_status_code=404)
class URLTagTests(URLTestCaseBase): class URLTagTests(URLTestCaseBase):

View File

@ -24,6 +24,7 @@ from django.shortcuts import redirect
from django.test import ( from django.test import (
SimpleTestCase, TestCase, ignore_warnings, override_settings, SimpleTestCase, TestCase, ignore_warnings, override_settings,
) )
from django.test.utils import override_script_prefix
from django.utils import six from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning from django.utils.deprecation import RemovedInDjango20Warning
@ -199,33 +200,38 @@ class URLPatternReverse(TestCase):
# Reversing None should raise an error, not return the last un-named view. # Reversing None should raise an error, not return the last un-named view.
self.assertRaises(NoReverseMatch, reverse, None) self.assertRaises(NoReverseMatch, reverse, None)
@override_script_prefix('/{{invalid}}/')
def test_prefix_braces(self): def test_prefix_braces(self):
self.assertEqual( self.assertEqual(
'/%7B%7Binvalid%7D%7D/includes/non_path_include/', '/%7B%7Binvalid%7D%7D/includes/non_path_include/',
reverse('non_path_include', prefix='/{{invalid}}/') reverse('non_path_include')
) )
def test_prefix_parenthesis(self): def test_prefix_parenthesis(self):
# Parentheses are allowed and should not cause errors or be escaped # Parentheses are allowed and should not cause errors or be escaped
with override_script_prefix('/bogus)/'):
self.assertEqual( self.assertEqual(
'/bogus)/includes/non_path_include/', '/bogus)/includes/non_path_include/',
reverse('non_path_include', prefix='/bogus)/') reverse('non_path_include')
) )
with override_script_prefix('/(bogus)/'):
self.assertEqual( self.assertEqual(
'/(bogus)/includes/non_path_include/', '/(bogus)/includes/non_path_include/',
reverse('non_path_include', prefix='/(bogus)/') reverse('non_path_include')
) )
@override_script_prefix('/bump%20map/')
def test_prefix_format_char(self): def test_prefix_format_char(self):
self.assertEqual( self.assertEqual(
'/bump%2520map/includes/non_path_include/', '/bump%2520map/includes/non_path_include/',
reverse('non_path_include', prefix='/bump%20map/') reverse('non_path_include')
) )
@override_script_prefix('/%7Eme/')
def test_non_urlsafe_prefix_with_args(self): def test_non_urlsafe_prefix_with_args(self):
# Regression for #20022, adjusted for #24013 because ~ is an unreserved # Regression for #20022, adjusted for #24013 because ~ is an unreserved
# character. Tests whether % is escaped. # character. Tests whether % is escaped.
self.assertEqual('/%257Eme/places/1/', reverse('places', args=[1], prefix='/%7Eme/')) self.assertEqual('/%257Eme/places/1/', reverse('places', args=[1]))
def test_patterns_reported(self): def test_patterns_reported(self):
# Regression for #17076 # Regression for #17076
@ -240,9 +246,10 @@ class URLPatternReverse(TestCase):
# exception # exception
self.fail("Expected a NoReverseMatch, but none occurred.") self.fail("Expected a NoReverseMatch, but none occurred.")
@override_script_prefix('/script:name/')
def test_script_name_escaping(self): def test_script_name_escaping(self):
self.assertEqual( self.assertEqual(
reverse('optional', args=['foo:bar'], prefix='/script:name/'), reverse('optional', args=['foo:bar']),
'/script:name/optional/foo:bar/' '/script:name/optional/foo:bar/'
) )