Ticket #17476: 17476.patch

File 17476.patch, 4.5 KB (added by aaugustin, 4 years ago)
  • tests/regressiontests/cache/tests.py

     
    2828from django.utils import timezone, translation, unittest
    2929from django.utils.cache import (patch_vary_headers, get_cache_key,
    3030    learn_cache_key, patch_cache_control, patch_response_headers)
     31from django.utils.encoding import force_unicode
    3132from django.views.decorators.cache import cache_page
    3233
    3334from .models import Poll, expensive_calculation
     
    12701271    @override_settings(USE_I18N=False, USE_L10N=False, USE_TZ=True)
    12711272    def test_cache_key_i18n_timezone(self):
    12721273        request = self._get_request()
    1273         tz = timezone.get_current_timezone_name().replace(' ', '_')
     1274        # This is tightly coupled to the implementation,
     1275        # but it's the most straightforward way to test the key.
     1276        tz = force_unicode(timezone.get_current_timezone_name(), errors='ignore')
     1277        tz = tz.encode('ascii', 'ignore').replace(' ', '_')
    12741278        response = HttpResponse()
    12751279        key = learn_cache_key(request, response)
    12761280        self.assertIn(tz, key, "Cache keys should include the time zone name when time zones are active")
     
    12811285    def test_cache_key_no_i18n (self):
    12821286        request = self._get_request()
    12831287        lang = translation.get_language()
    1284         tz = timezone.get_current_timezone_name().replace(' ', '_')
     1288        tz = force_unicode(timezone.get_current_timezone_name(), errors='ignore')
     1289        tz = tz.encode('ascii', 'ignore').replace(' ', '_')
    12851290        response = HttpResponse()
    12861291        key = learn_cache_key(request, response)
    12871292        self.assertNotIn(lang, key, "Cache keys shouldn't include the language name when i18n isn't active")
    12881293        self.assertNotIn(tz, key, "Cache keys shouldn't include the time zone name when i18n isn't active")
    12891294
     1295    @override_settings(USE_I18N=False, USE_L10N=False, USE_TZ=True)
     1296    def test_cache_key_with_non_ascii_tzname(self):
     1297        # Regression test for #17476
     1298        class CustomTzName(timezone.UTC):
     1299            name = ''
     1300            def tzname(self, dt):
     1301                return self.name
     1302
     1303        request = self._get_request()
     1304        response = HttpResponse()
     1305        with timezone.override(CustomTzName()):
     1306            CustomTzName.name = 'Hora estándar de Argentina'    # UTF-8 string
     1307            sanitized_name = 'Hora_estndar_de_Argentina'
     1308            self.assertIn(sanitized_name, learn_cache_key(request, response),
     1309                    "Cache keys should include the time zone name when time zones are active")
     1310
     1311            CustomTzName.name = u'Hora estándar de Argentina'    # unicode
     1312            sanitized_name = 'Hora_estndar_de_Argentina'
     1313            self.assertIn(sanitized_name, learn_cache_key(request, response),
     1314                    "Cache keys should include the time zone name when time zones are active")
     1315
     1316
    12901317    @override_settings(
    12911318            CACHE_MIDDLEWARE_KEY_PREFIX="test",
    12921319            CACHE_MIDDLEWARE_SECONDS=60,
  • django/utils/cache.py

     
    2323
    2424from django.conf import settings
    2525from django.core.cache import get_cache
    26 from django.utils.encoding import smart_str, iri_to_uri
     26from django.utils.encoding import smart_str, iri_to_uri, force_unicode
    2727from django.utils.http import http_date
    2828from django.utils.timezone import get_current_timezone_name
    2929from django.utils.translation import get_language
     
    165165        # which in turn can also fall back to settings.LANGUAGE_CODE
    166166        cache_key += '.%s' % getattr(request, 'LANGUAGE_CODE', get_language())
    167167    if settings.USE_TZ:
    168         # Windows uses non-standard timezone names that may include spaces,
    169         # which triggers CacheKeyWarning.
    170         cache_key += '.%s' % get_current_timezone_name().replace(' ', '_')
     168        # The datetime module doesn't restrict the output of tzname().
     169        # Windows is known to use non-standard, locale-dependant names.
     170        # User-defined tzinfo classes may return absolutely anything.
     171        # Hence this paranoid conversion to create a valid cache key.
     172        tz_name = force_unicode(get_current_timezone_name(), errors='ignore')
     173        cache_key += '.%s' % tz_name.encode('ascii', 'ignore').replace(' ', '_')
    171174    return cache_key
    172175
    173176def _generate_cache_key(request, method, headerlist, key_prefix):
Back to Top