diff options
48 files changed, 328 insertions, 141 deletions
diff --git a/django/conf/__init__.py b/django/conf/__init__.py index 628b1f7e4d..f8018f723b 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -9,9 +9,11 @@ for a list of all possible variables. import importlib import os import time +import traceback import warnings from pathlib import Path +import django from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured from django.utils.deprecation import RemovedInDjango50Warning @@ -19,6 +21,12 @@ from django.utils.functional import LazyObject, empty ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" +USE_L10N_DEPRECATED_MSG = ( + 'The USE_L10N setting is deprecated. Starting with Django 5.0, localized ' + 'formatting of data will always be enabled. For example Django will ' + 'display numbers and dates using the format of the current locale.' +) + class SettingsReference(str): """ @@ -129,6 +137,27 @@ class LazySettings(LazyObject): """Return True if the settings have already been configured.""" return self._wrapped is not empty + @property + def USE_L10N(self): + stack = traceback.extract_stack() + # Show a warning if the setting is used outside of Django. + # Stack index: -1 this line, -2 the caller. + filename, _, _, _ = stack[-2] + if not filename.startswith(os.path.dirname(django.__file__)): + warnings.warn( + USE_L10N_DEPRECATED_MSG, + RemovedInDjango50Warning, + stacklevel=2, + ) + return self.__getattr__('USE_L10N') + + # RemovedInDjango50Warning. + @property + def _USE_L10N_INTERNAL(self): + # Special hook to avoid checking a traceback in internal use on hot + # paths. + return self.__getattr__('USE_L10N') + class Settings: def __init__(self, settings_module): @@ -179,6 +208,9 @@ class Settings: os.environ['TZ'] = self.TIME_ZONE time.tzset() + if self.is_overridden('USE_L10N'): + warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning) + def is_overridden(self, setting): return setting in self._explicit_settings @@ -210,6 +242,8 @@ class UserSettingsHolder: def __setattr__(self, name, value): self._deleted.discard(name) + if name == 'USE_L10N': + warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning) super().__setattr__(name, value) def __delattr__(self, name): diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index b9541d81b5..ab69316314 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -167,7 +167,7 @@ LANGUAGE_COOKIE_SAMESITE = None # If you set this to True, Django will format dates, numbers and calendars # according to user current locale. -USE_L10N = False +USE_L10N = True # Not-necessarily-technical managers of the site. They get broken link # notifications and other various emails. diff --git a/django/conf/locale/en/formats.py b/django/conf/locale/en/formats.py index ccace3d2b3..f5af6509c6 100644 --- a/django/conf/locale/en/formats.py +++ b/django/conf/locale/en/formats.py @@ -2,24 +2,36 @@ # # The *_FORMAT strings use the Django date format syntax, # see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date + +# Formatting for date objects. DATE_FORMAT = 'N j, Y' +# Formatting for time objects. TIME_FORMAT = 'P' +# Formatting for datetime objects. DATETIME_FORMAT = 'N j, Y, P' +# Formatting for date objects when only the year and month are relevant. YEAR_MONTH_FORMAT = 'F Y' +# Formatting for date objects when only the month and day are relevant. MONTH_DAY_FORMAT = 'F j' +# Short formatting for date objects. SHORT_DATE_FORMAT = 'm/d/Y' +# Short formatting for datetime objects. SHORT_DATETIME_FORMAT = 'm/d/Y P' -FIRST_DAY_OF_WEEK = 0 # Sunday +# First day of week, to be used on calendars. +# 0 means Sunday, 1 means Monday... +FIRST_DAY_OF_WEEK = 0 +# Formats to be used when parsing dates from input boxes, in order. # The *_INPUT_FORMATS strings use the Python strftime format syntax, # see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Note that these format strings are different from the ones to display dates. # Kept ISO formats as they are in first position DATE_INPUT_FORMATS = [ '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' - # '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' - # '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' - # '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' - # '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' + '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' + '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' + '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' ] DATETIME_INPUT_FORMATS = [ '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' @@ -32,6 +44,16 @@ DATETIME_INPUT_FORMATS = [ '%m/%d/%y %H:%M:%S.%f', # '10/25/06 14:30:59.000200' '%m/%d/%y %H:%M', # '10/25/06 14:30' ] +TIME_INPUT_FORMATS = [ + '%H:%M:%S', # '14:30:59' + '%H:%M:%S.%f', # '14:30:59.000200' + '%H:%M', # '14:30' +] + +# Decimal separator symbol. DECIMAL_SEPARATOR = '.' +# Thousand separator symbol. THOUSAND_SEPARATOR = ',' +# Number of digits that will be together, when splitting them by +# THOUSAND_SEPARATOR. 0 means no grouping, 3 means splitting by thousands. NUMBER_GROUPING = 3 diff --git a/django/conf/project_template/project_name/settings.py-tpl b/django/conf/project_template/project_name/settings.py-tpl index e949752df4..3b6caab333 100644 --- a/django/conf/project_template/project_name/settings.py-tpl +++ b/django/conf/project_template/project_name/settings.py-tpl @@ -109,8 +109,6 @@ TIME_ZONE = 'UTC' USE_I18N = True -USE_L10N = True - USE_TZ = True diff --git a/django/utils/formats.py b/django/utils/formats.py index cffbb34398..781d334a8e 100644 --- a/django/utils/formats.py +++ b/django/utils/formats.py @@ -104,7 +104,11 @@ def get_format(format_type, lang=None, use_l10n=None): If use_l10n is provided and is not None, it forces the value to be localized (or not), overriding the value of settings.USE_L10N. """ - use_l10n = use_l10n or (use_l10n is None and settings.USE_L10N) + use_l10n = use_l10n or (use_l10n is None and ( + settings._USE_L10N_INTERNAL + if hasattr(settings, '_USE_L10N_INTERNAL') + else settings.USE_L10N + )) if use_l10n and lang is None: lang = get_language() cache_key = (format_type, lang) @@ -168,7 +172,11 @@ def number_format(value, decimal_pos=None, use_l10n=None, force_grouping=False): If use_l10n is provided and is not None, it forces the value to be localized (or not), overriding the value of settings.USE_L10N. """ - use_l10n = use_l10n or (use_l10n is None and settings.USE_L10N) + use_l10n = use_l10n or (use_l10n is None and ( + settings._USE_L10N_INTERNAL + if hasattr(settings, '_USE_L10N_INTERNAL') + else settings.USE_L10N + )) lang = get_language() if use_l10n else None return numberformat.format( value, diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 77642cffd1..6154fefa3b 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -34,6 +34,8 @@ details on these changes. ``StringAgg`` aggregates will return ``None`` when there are no rows instead of ``[]``, ``[]``, and ``''`` respectively. +* The ``USE_L10N`` setting will be removed. + .. _deprecation-removed-in-4.1: 4.1 diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index cc58192bd4..12d89142d1 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -2774,7 +2774,7 @@ See also :setting:`LANGUAGE_CODE`, :setting:`USE_L10N` and :setting:`USE_TZ`. ``USE_L10N`` ------------ -Default: ``False`` +Default: ``True`` A boolean that specifies if localized formatting of data will be enabled by default or not. If this is set to ``True``, e.g. Django will display numbers and @@ -2782,10 +2782,15 @@ dates using the format of the current locale. See also :setting:`LANGUAGE_CODE`, :setting:`USE_I18N` and :setting:`USE_TZ`. -.. note:: +.. versionchanged:: 4.0 - The default :file:`settings.py` file created by :djadmin:`django-admin - startproject <startproject>` includes ``USE_L10N = True`` for convenience. + In older versions, the default value is ``False``. + +.. deprecated:: 4.0 + + This setting is deprecated. Starting with Django 5.0, localized formatting + of data will always be enabled. For example Django will display numbers and + dates using the format of the current locale. .. setting:: USE_THOUSAND_SEPARATOR diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index d2f804b8c1..8b0303352a 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -918,7 +918,7 @@ Miscellaneous To adapt, move the fragment outside the template tag: ``{% static 'img.svg' %}#fragment``. -* When :setting:`USE_L10N` is ``True``, localization is now applied for the +* When ``USE_L10N`` is ``True``, localization is now applied for the :tfilter:`date` and :tfilter:`time` filters when no format string is specified. The ``DATE_FORMAT`` and ``TIME_FORMAT`` specifiers from the active locale are used instead of the settings of the same name. diff --git a/docs/releases/1.2.txt b/docs/releases/1.2.txt index 30e39ac1be..5d7d6cc836 100644 --- a/docs/releases/1.2.txt +++ b/docs/releases/1.2.txt @@ -936,7 +936,7 @@ Date format helper functions ``django.utils.translation.get_date_formats()`` and ``django.utils.translation.get_partial_date_formats()`` have been deprecated in favor of the appropriate calls to ``django.utils.formats.get_format()``, -which is locale-aware when :setting:`USE_L10N` is set to ``True``, and falls +which is locale-aware when ``USE_L10N`` is set to ``True``, and falls back to default settings if set to ``False``. To get the different date formats, instead of writing this:: diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt index 7ad0a27ed4..c3730a794b 100644 --- a/docs/releases/2.0.txt +++ b/docs/releases/2.0.txt @@ -558,7 +558,7 @@ Miscellaneous * :class:`~django.views.generic.base.RedirectView` no longer silences ``NoReverseMatch`` if the ``pattern_name`` doesn't exist. -* When :setting:`USE_L10N` is off, :class:`~django.forms.FloatField` and +* When ``USE_L10N`` is off, :class:`~django.forms.FloatField` and :class:`~django.forms.DecimalField` now respect :setting:`DECIMAL_SEPARATOR` and :setting:`THOUSAND_SEPARATOR` during validation. For example, with the settings:: diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt index 828add0fea..76d1ade6d5 100644 --- a/docs/releases/3.2.txt +++ b/docs/releases/3.2.txt @@ -672,7 +672,7 @@ Miscellaneous and underscores. * The :tfilter:`intcomma` and :tfilter:`intword` template filters no longer - depend on the :setting:`USE_L10N` setting. + depend on the ``USE_L10N`` setting. * Support for ``argon2-cffi`` < 19.1.0 is removed. diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index 8f910ad9db..709363a08f 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -579,8 +579,11 @@ Miscellaneous Django 3.2. * The :tfilter:`floatformat` template filter no longer depends on the - :setting:`USE_L10N` setting and always returns localized output. Use the - ``u`` suffix to disable localization. + ``USE_L10N`` setting and always returns localized output. Use the ``u`` + suffix to disable localization. + +* The default value of the ``USE_L10N`` setting is changed to ``True``. See the + :ref:`Localization section <use_l10n_deprecation>` above for more details. .. _deprecated-features-4.0: @@ -601,6 +604,20 @@ Note that the default :file:`settings.py` file created by You can set ``USE_TZ`` to ``False`` in your project settings before then to opt-out. +.. _use_l10n_deprecation: + +Localization +------------ + +In order to follow good practice, the default value of the ``USE_L10N`` setting +is changed from ``False`` to ``True``. + +Moreover ``USE_L10N`` is deprecated as of this release. Starting with Django +5.0, by default, any date or number displayed by Django will be localized. + +The :ttag:`{% localize %} <localize>` tag and the :tfilter:`localize`/ +:tfilter:`unlocalize` filters will still be honored by Django. + Miscellaneous ------------- diff --git a/docs/topics/i18n/formatting.txt b/docs/topics/i18n/formatting.txt index 16fd7ca0cb..671901dcdc 100644 --- a/docs/topics/i18n/formatting.txt +++ b/docs/topics/i18n/formatting.txt @@ -18,18 +18,16 @@ necessary to set :setting:`USE_L10N = True <USE_L10N>` in your settings file. .. note:: - The default :file:`settings.py` file created by :djadmin:`django-admin - startproject <startproject>` includes :setting:`USE_L10N = True <USE_L10N>` - for convenience. Note, however, that to enable number formatting with - thousand separators it is necessary to set :setting:`USE_THOUSAND_SEPARATOR - = True <USE_THOUSAND_SEPARATOR>` in your settings file. Alternatively, you - could use :tfilter:`intcomma` to format numbers in your template. + To enable number formatting with thousand separators, it is necessary to + set :setting:`USE_THOUSAND_SEPARATOR = True <USE_THOUSAND_SEPARATOR>` in + your settings file. Alternatively, you could use :tfilter:`intcomma` to + format numbers in your template. .. note:: - There is also an independent but related :setting:`USE_I18N` setting that - controls if Django should activate translation. See - :doc:`/topics/i18n/translation` for more details. + There is a related :setting:`USE_I18N` setting that controls if Django + should activate translation. See :doc:`/topics/i18n/translation` for more + details. Locale aware input in forms =========================== diff --git a/docs/topics/i18n/timezones.txt b/docs/topics/i18n/timezones.txt index 847e5ff593..5b475bd44f 100644 --- a/docs/topics/i18n/timezones.txt +++ b/docs/topics/i18n/timezones.txt @@ -47,12 +47,6 @@ functions in :mod:`django.utils.timezone`. startproject <startproject>` includes :setting:`USE_TZ = True <USE_TZ>` for convenience. -.. note:: - - There is also an independent but related :setting:`USE_L10N` setting that - controls whether Django should activate format localization. See - :doc:`/topics/i18n/formatting` for more details. - If you're wrestling with a particular problem, start with the :ref:`time zone FAQ <time-zones-faq>`. diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt index 4c5b8181bc..99fc41ebb6 100644 --- a/docs/topics/i18n/translation.txt +++ b/docs/topics/i18n/translation.txt @@ -31,12 +31,6 @@ make some optimizations so as not to load the internationalization machinery. .. note:: - There is also an independent but related :setting:`USE_L10N` setting that - controls if Django should implement format localization. See - :doc:`/topics/i18n/formatting` for more details. - -.. note:: - Make sure you've activated translation for your project (the fastest way is to check if :setting:`MIDDLEWARE` includes :mod:`django.middleware.locale.LocaleMiddleware`). If you haven't yet, diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py index 12f36f4483..c50ad8cf1d 100644 --- a/tests/admin_inlines/tests.py +++ b/tests/admin_inlines/tests.py @@ -382,7 +382,7 @@ class TestInline(TestDataMixin, TestCase): html=True ) - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_localize_pk_shortcut(self): """ The "View on Site" link is correct for locales that use thousand diff --git a/tests/admin_utils/test_logentry.py b/tests/admin_utils/test_logentry.py index ca7c7a4c41..8d8f4ef9ee 100644 --- a/tests/admin_utils/test_logentry.py +++ b/tests/admin_utils/test_logentry.py @@ -74,7 +74,6 @@ class LogEntryTests(TestCase): logentry = LogEntry(change_message='non-JSON string') self.assertEqual(logentry.get_change_message(), logentry.change_message) - @override_settings(USE_L10N=True) def test_logentry_change_message_localized_datetime_input(self): """ Localized date/time inputs shouldn't affect changed form data detection. diff --git a/tests/admin_utils/tests.py b/tests/admin_utils/tests.py index 5960759a4d..77db318693 100644 --- a/tests/admin_utils/tests.py +++ b/tests/admin_utils/tests.py @@ -201,7 +201,7 @@ class UtilsTests(SimpleTestCase): display_value = display_for_field(12345, models.IntegerField(), self.empty_value) self.assertEqual(display_value, '12345') - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_number_formats_with_thousand_separator_display_for_field(self): display_value = display_for_field(12345.6789, models.FloatField(), self.empty_value) self.assertEqual(display_value, '12,345.6789') @@ -219,7 +219,7 @@ class UtilsTests(SimpleTestCase): display_value = display_for_value([1, 2, 'buckle', 'my', 'shoe'], self.empty_value) self.assertEqual(display_value, '1, 2, buckle, my, shoe') - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_list_display_for_value_boolean(self): self.assertEqual( display_for_value(True, '', boolean=True), diff --git a/tests/admin_views/test_actions.py b/tests/admin_views/test_actions.py index 445e437fc2..6c5aa5ad53 100644 --- a/tests/admin_views/test_actions.py +++ b/tests/admin_views/test_actions.py @@ -72,7 +72,7 @@ class AdminActionsTest(TestCase): self.assertContains(response, 'Are you sure you want to delete the selected subscribers?') self.assertContains(response, '<ul></ul>', html=True) - @override_settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=True, NUMBER_GROUPING=3) + @override_settings(USE_THOUSAND_SEPARATOR=True, NUMBER_GROUPING=3) def test_non_localized_pk(self): """ If USE_THOUSAND_SEPARATOR is set, the ids for the objects selected for diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index b277476296..a8524379f8 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -109,7 +109,7 @@ class AdminFieldExtractionMixin: return field -@override_settings(ROOT_URLCONF='admin_views.urls', USE_I18N=True, USE_L10N=False, LANGUAGE_CODE='en') +@override_settings(ROOT_URLCONF='admin_views.urls', USE_I18N=True, LANGUAGE_CODE='en') class AdminViewBasicTestCase(TestCase): @classmethod @@ -802,12 +802,12 @@ class AdminViewBasicTest(AdminViewBasicTestCase): response = self.client.get(reverse('admin-extra-context:jsi18n')) self.assertEqual(response.status_code, 200) - def test_L10N_deactivated(self): + def test_jsi18n_format_fallback(self): """ - Check if L10N is deactivated, the JavaScript i18n view doesn't - return localized date/time formats. Refs #14824. + The JavaScript i18n view doesn't return localized date/time formats + when the selected language cannot be found. """ - with self.settings(LANGUAGE_CODE='ru', USE_L10N=False), translation.override('none'): + with self.settings(LANGUAGE_CODE='ru'), translation.override('none'): response = self.client.get(reverse('admin:jsi18n')) self.assertNotContains(response, '%d.%m.%Y %H:%M:%S') self.assertContains(response, '%Y-%m-%d %H:%M:%S') @@ -4541,7 +4541,7 @@ class PrePopulatedTest(TestCase): ""id": "#id_prepopulatedsubpost_set-0-subslug"" ) - @override_settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_prepopulated_maxlength_localized(self): """ Regression test for #15938: if USE_THOUSAND_SEPARATOR is set, make sure @@ -5704,7 +5704,7 @@ class ValidXHTMLTests(TestCase): self.assertNotContains(response, ' xml:lang=""') -@override_settings(ROOT_URLCONF='admin_views.urls', USE_THOUSAND_SEPARATOR=True, USE_L10N=True) +@override_settings(ROOT_URLCONF='admin_views.urls', USE_THOUSAND_SEPARATOR=True) class DateHierarchyTests(TestCase): @classmethod diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py index 1896279ec7..1bb4c9a9b1 100644 --- a/tests/admin_widgets/tests.py +++ b/tests/admin_widgets/tests.py @@ -338,7 +338,7 @@ class AdminSplitDateTimeWidgetTest(SimpleTestCase): def test_localization(self): w = widgets.AdminSplitDateTime() - with self.settings(USE_L10N=True), translation.override('de-at'): + with translation.override('de-at'): w.is_localized = True self.assertHTMLEqual( w.render('test', datetime(2007, 12, 1, 9, 30)), @@ -939,7 +939,7 @@ class DateTimePickerSeleniumTests(AdminWidgetSeleniumTestCase): expected_caption = '{:s} {:d}'.format(may_translation.upper(), 1984) # Test with every locale - with override_settings(LANGUAGE_CODE=language_code, USE_L10N=True): + with override_settings(LANGUAGE_CODE=language_code): # Open a page that has a date picker widget url = reverse('admin:admin_widgets_member_change', args=(member.pk,)) diff --git a/tests/deprecation/test_use_l10n.py b/tests/deprecation/test_use_l10n.py new file mode 100644 index 0000000000..0744e34ea0 --- /dev/null +++ b/tests/deprecation/test_use_l10n.py @@ -0,0 +1,43 @@ +import sys +from types import ModuleType + +from django.conf import USE_L10N_DEPRECATED_MSG, Settings, settings +from django.test import TestCase, ignore_warnings +from django.utils.deprecation import RemovedInDjango50Warning + + +class DeprecationTests(TestCase): + msg = USE_L10N_DEPRECATED_MSG + + def test_override_settings_warning(self): + # Warning is raised when USE_L10N is set in UserSettingsHolder (used by + # the @override_settings decorator). + with self.assertRaisesMessage(RemovedInDjango50Warning, self.msg): + with self.settings(USE_L10N=True): + pass + + def test_settings_init_warning(self): + settings_module = ModuleType('fake_settings_module') + settings_module.SECRET_KEY = 'foo' + settings_module.USE_TZ = True + settings_module.USE_L10N = False + sys.modules['fake_settings_module'] = settings_module + try: + with self.assertRaisesMessage(RemovedInDjango50Warning, self.msg): + Settings('fake_settings_module') + finally: + del sys.modules['fake_settings_module'] + + def test_access_warning(self): + with self.assertRaisesMessage(RemovedInDjango50Warning, self.msg): + settings.USE_L10N + # Works a second time. + with self.assertRaisesMessage(RemovedInDjango50Warning, self.msg): + settings.USE_L10N + + @ignore_warnings(category=RemovedInDjango50Warning) + def test_access(self): + with self.settings(USE_L10N=False): + self.assertIs(settings.USE_L10N, False) + # Works a second time. + self.assertIs(settings.USE_L10N, False) diff --git a/tests/forms_tests/field_tests/test_datefield.py b/tests/forms_tests/field_tests/test_datefield.py index c0e369cd0c..10d77bf1bb 100644 --- a/tests/forms_tests/field_tests/test_datefield.py +++ b/tests/forms_tests/field_tests/test_datefield.py @@ -2,7 +2,7 @@ from datetime import date, datetime from django.core.exceptions import ValidationError from django.forms import DateField, Form, HiddenInput, SelectDateWidget -from django.test import SimpleTestCase, override_settings +from django.test import SimpleTestCase from django.utils import translation @@ -37,7 +37,6 @@ class DateFieldTest(SimpleTestCase): d = GetDate({'mydate_month': '1', 'mydate_day': '1', 'mydate_year': '2010'}) self.assertIn('<label for="id_mydate_month">', d.as_p()) - @override_settings(USE_L10N=True) @translation.override('nl') def test_l10n_date_changed(self): """ @@ -95,7 +94,6 @@ class DateFieldTest(SimpleTestCase): }, initial={'mydate': date(2008, 4, 1)}) self.assertFalse(b.has_changed()) - @override_settings(USE_L10N=True) @translation.override('nl') def test_l10n_invalid_date_in(self): # Invalid dates shouldn't be allowed @@ -104,7 +102,6 @@ class DateFieldTest(SimpleTestCase): # 'Geef een geldige datum op.' = 'Enter a valid date.' self.assertEqual(a.errors, {'mydate': ['Voer een geldige datum in.']}) - @override_settings(USE_L10N=True) @translation.override('nl') def test_form_label_association(self): # label tag is correctly associated with first rendered dropdown diff --git a/tests/forms_tests/field_tests/test_decimalfield.py b/tests/forms_tests/field_tests/test_decimalfield.py index f58c678176..1dd0984ac7 100644 --- a/tests/forms_tests/field_tests/test_decimalfield.py +++ b/tests/forms_tests/field_tests/test_decimalfield.py @@ -2,8 +2,9 @@ import decimal from django.core.exceptions import ValidationError from django.forms import DecimalField, NumberInput, Widget -from django.test import SimpleTestCase, override_settings +from django.test import SimpleTestCase, ignore_warnings, override_settings from django.utils import formats, translation +from django.utils.deprecation import RemovedInDjango50Warning from . import FormFieldAssertionsMixin @@ -153,17 +154,27 @@ class DecimalFieldTest(FormFieldAssertionsMixin, SimpleTestCase): self.assertFalse(f.has_changed(d, '0.10')) self.assertTrue(f.has_changed(d, '0.101')) - with translation.override('fr'), self.settings(USE_L10N=True): + with translation.override('fr'): f = DecimalField(max_digits=2, decimal_places=2, localize=True) localized_d = formats.localize_input(d) # -> '0,1' in French self.assertFalse(f.has_changed(d, localized_d)) + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The test should remain because + # format-related settings will take precedence over locale-dictated + # formats. + @ignore_warnings(category=RemovedInDjango50Warning) @override_settings(USE_L10N=False, DECIMAL_SEPARATOR=',') def test_decimalfield_support_decimal_separator(self): f = DecimalField(localize=True) self.assertEqual(f.clean('1001,10'), decimal.Decimal("1001.10")) self.assertEqual(f.clean('1001.10'), decimal.Decimal("1001.10")) + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The test should remain because + # format-related settings will take precedence over locale-dictated + # formats. + @ignore_warnings(category=RemovedInDjango50Warning) @override_settings(USE_L10N=False, DECIMAL_SEPARATOR=',', USE_THOUSAND_SEPARATOR=True, THOUSAND_SEPARATOR='.') def test_decimalfield_support_thousands_separator(self): diff --git a/tests/forms_tests/field_tests/test_floatfield.py b/tests/forms_tests/field_tests/test_floatfield.py index d97bbfc13e..d6dffaccb1 100644 --- a/tests/forms_tests/field_tests/test_floatfield.py +++ b/tests/forms_tests/field_tests/test_floatfield.py @@ -1,8 +1,9 @@ from django.core.exceptions import ValidationError from django.forms import FloatField, NumberInput from django.test import SimpleTestCase -from django.test.utils import override_settings +from django.test.utils import ignore_warnings, override_settings from django.utils import formats, translation +from django.utils.deprecation import RemovedInDjango50Warning from . import FormFieldAssertionsMixin @@ -81,17 +82,27 @@ class FloatFieldTest(FormFieldAssertionsMixin, SimpleTestCase): n = 4.35 self.assertFalse(f.has_changed(n, '4.3500')) - with translation.override('fr'), self.settings(USE_L10N=True): + with translation.override('fr'): f = FloatField(localize=True) localized_n = formats.localize_input(n) # -> '4,35' in French self.assertFalse(f.has_changed(n, localized_n)) + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The test should remain because + # format-related settings will take precedence over locale-dictated + # formats. + @ignore_warnings(category=RemovedInDjango50Warning) @override_settings(USE_L10N=False, DECIMAL_SEPARATOR=',') def test_decimalfield_support_decimal_separator(self): f = FloatField(localize=True) self.assertEqual(f.clean('1001,10'), 1001.10) self.assertEqual(f.clean('1001.10'), 1001.10) + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The test should remain because + # format-related settings will take precedence over locale-dictated + # formats. + @ignore_warnings(category=RemovedInDjango50Warning) @override_settings(USE_L10N=False, DECIMAL_SEPARATOR=',', USE_THOUSAND_SEPARATOR=True, THOUSAND_SEPARATOR='.') def test_decimalfield_support_thousands_separator(self): diff --git a/tests/forms_tests/tests/test_input_formats.py b/tests/forms_tests/tests/test_input_formats.py index 81ba9eb943..7b9da02a0c 100644 --- a/tests/forms_tests/tests/test_input_formats.py +++ b/tests/forms_tests/tests/test_input_formats.py @@ -3,10 +3,10 @@ from datetime import date, datetime, time from django import forms from django.core.exceptions import ValidationError from django.test import SimpleTestCase, override_settings +from django.utils import translation from django.utils.translation import activate, deactivate -@override_settings(TIME_INPUT_FORMATS=["%I:%M:%S %p", "%I:%M %p"], USE_L10N=True) class LocalizedTimeTests(SimpleTestCase): def setUp(self): # nl/formats.py has customized TIME_INPUT_FORMATS: @@ -117,6 +117,7 @@ class LocalizedTimeTests(SimpleTestCase): self.assertEqual(text, "13:30:00") +@translation.override(None) # RemovedInDjango50Warning. @override_settings(TIME_INPUT_FORMATS=["%I:%M:%S %p", "%I:%M %p"]) class CustomTimeInputFormatsTests(SimpleTestCase): def test_timeField(self): @@ -310,7 +311,6 @@ class SimpleTimeFormatTests(SimpleTestCase): self.assertEqual(text, "13:30:00") -@override_settings(DATE_INPUT_FORMATS=["%d/%m/%Y", "%d-%m-%Y"], USE_L10N=True) class LocalizedDateTests(SimpleTestCase): def setUp(self): activate('de') @@ -422,6 +422,7 @@ class LocalizedDateTests(SimpleTestCase): self.assertEqual(text, "21.12.2010") +@translation.override(None) # RemovedInDjango50Warning. @override_settings(DATE_INPUT_FORMATS=["%d.%m.%Y", "%d-%m-%Y"]) class CustomDateInputFormatsTests(SimpleTestCase): def test_dateField(self): @@ -615,7 +616,6 @@ class SimpleDateFormatTests(SimpleTestCase): self.assertEqual(text, "2010-12-21") -@override_settings(DATETIME_INPUT_FORMATS=["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"], USE_L10N=True) class LocalizedDateTimeTests(SimpleTestCase): def setUp(self): activate('de') @@ -731,6 +731,7 @@ class LocalizedDateTimeTests(SimpleTestCase): self.assertEqual(text, "21.12.2010 13:30:00") +@translation.override(None) # RemovedInDjango50Warning. @override_settings(DATETIME_INPUT_FORMATS=["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"]) class CustomDateTimeInputFormatsTests(SimpleTestCase): def test_dateTimeField(self): diff --git a/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py b/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py index 05406894dd..e831038e02 100644 --- a/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py +++ b/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py @@ -133,7 +133,7 @@ class CheckboxSelectMultipleTest(WidgetTest): """ self.check_html(widget, 'letters', ['a', 'c'], html=html) - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_doesnt_localize_input_value(self): choices = [ (1, 'One'), diff --git a/tests/forms_tests/widget_tests/test_dateinput.py b/tests/forms_tests/widget_tests/test_dateinput.py index 8fae6c672a..fa08b345c1 100644 --- a/tests/forms_tests/widget_tests/test_dateinput.py +++ b/tests/forms_tests/widget_tests/test_dateinput.py @@ -1,7 +1,6 @@ from datetime import date from django.forms import DateInput -from django.test import override_settings from django.utils import translation from .base import WidgetTest @@ -38,7 +37,6 @@ class DateInputTest(WidgetTest): widget = DateInput(format='%d/%m/%Y', attrs={'type': 'date'}) self.check_html(widget, 'date', d, html='<input type="date" name="date" value="17/09/2007">') - @override_settings(USE_L10N=True) @translation.override('de-at') def test_l10n(self): self.check_html( diff --git a/tests/forms_tests/widget_tests/test_datetimeinput.py b/tests/forms_tests/widget_tests/test_datetimeinput.py index 682ded3c84..0a2571f5b7 100644 --- a/tests/forms_tests/widget_tests/test_datetimeinput.py +++ b/tests/forms_tests/widget_tests/test_datetimeinput.py @@ -1,8 +1,9 @@ from datetime import datetime from django.forms import DateTimeInput -from django.test import override_settings +from django.test import ignore_warnings from django.utils import translation +from django.utils.deprecation import RemovedInDjango50Warning from .base import WidgetTest @@ -39,7 +40,6 @@ class DateTimeInputTest(WidgetTest): d = datetime(2007, 9, 17, 12, 51, 34, 482548) self.check_html(widget, 'date', d, html='<input type="datetime" name="date" value="17/09/2007 12:51">') - @override_settings(USE_L10N=True) @translation.override('de-at') def test_l10n(self): d = datetime(2007, 9, 17, 12, 51, 34, 482548) @@ -47,15 +47,22 @@ class DateTimeInputTest(WidgetTest): '<input type="text" name="date" value="17.09.2007 12:51:34">' )) - @override_settings(USE_L10N=True) @translation.override('de-at') def test_locale_aware(self): d = datetime(2007, 9, 17, 12, 51, 34, 482548) - with self.settings(USE_L10N=False): - self.check_html( - self.widget, 'date', d, - html='<input type="text" name="date" value="2007-09-17 12:51:34">', - ) + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The assertion should remain + # because format-related settings will take precedence over + # locale-dictated formats. + with ignore_warnings(category=RemovedInDjango50Warning): + with self.settings(USE_L10N=False): + with self.settings(DATETIME_INPUT_FORMATS=[ + '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f', '%Y-%m-%d %H:%M', + ]): + self.check_html( + self.widget, 'date', d, + html='<input type="text" name="date" value="2007-09-17 12:51:34">', + ) with translation.override('es'): self.check_html( self.widget, 'date', d, diff --git a/tests/forms_tests/widget_tests/test_nullbooleanselect.py b/tests/forms_tests/widget_tests/test_nullbooleanselect.py index a732e86da4..4e34020cdd 100644 --- a/tests/forms_tests/widget_tests/test_nullbooleanselect.py +++ b/tests/forms_tests/widget_tests/test_nullbooleanselect.py @@ -1,5 +1,4 @@ from django.forms import NullBooleanSelect -from django.test import override_settings from django.utils import translation from .base import WidgetTest @@ -89,7 +88,6 @@ class NullBooleanSelectTest(WidgetTest): </select>""" )) - @override_settings(USE_L10N=True) def test_l10n(self): """ The NullBooleanSelect widget's options are lazily localized (#17190). diff --git a/tests/forms_tests/widget_tests/test_numberinput.py b/tests/forms_tests/widget_tests/test_numberinput.py index 40bd94df6e..9fda30e156 100644 --- a/tests/forms_tests/widget_tests/test_numberinput.py +++ b/tests/forms_tests/widget_tests/test_numberinput.py @@ -6,7 +6,7 @@ from .base import WidgetTest class NumberInputTests(WidgetTest): - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_attrs_not_localized(self): widget = NumberInput(attrs={'max': 12345, 'min': 1234, 'step': 9999}) self.check_html( diff --git a/tests/forms_tests/widget_tests/test_radioselect.py b/tests/forms_tests/widget_tests/test_radioselect.py index 41f771e940..9622517144 100644 --- a/tests/forms_tests/widget_tests/test_radioselect.py +++ b/tests/forms_tests/widget_tests/test_radioselect.py @@ -101,7 +101,7 @@ class RadioSelectTest(WidgetTest): """ self.check_html(self.widget(choices=self.beatles), 'beatle', 'J', attrs={'class': 'bar'}, html=html) - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_doesnt_localize_input_value(self): choices = [ (1, 'One'), diff --git a/tests/forms_tests/widget_tests/test_select.py b/tests/forms_tests/widget_tests/test_select.py index 935f6f6b5e..dc2030e3ae 100644 --- a/tests/forms_tests/widget_tests/test_select.py +++ b/tests/forms_tests/widget_tests/test_select.py @@ -220,7 +220,7 @@ class SelectTest(WidgetTest): </select>""" )) - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_doesnt_localize_option_value(self): choices = [ (1, 'One'), diff --git a/tests/forms_tests/widget_tests/test_selectdatewidget.py b/tests/forms_tests/widget_tests/test_selectdatewidget.py index 661268a08d..6a922e4e71 100644 --- a/tests/forms_tests/widget_tests/test_selectdatewidget.py +++ b/tests/forms_tests/widget_tests/test_selectdatewidget.py @@ -1,9 +1,10 @@ from datetime import date from django.forms import DateField, Form, SelectDateWidget -from django.test import override_settings +from django.test import ignore_warnings, override_settings from django.utils import translation from django.utils.dates import MONTHS_AP +from django.utils.deprecation import RemovedInDjango50Warning from .base import WidgetTest @@ -387,7 +388,6 @@ class SelectDateWidgetTest(WidgetTest): with self.assertRaisesMessage(ValueError, 'empty_label list/tuple must have 3 elements.'): SelectDateWidget(years=('2014',), empty_label=('not enough', 'values')) - @override_settings(USE_L10N=True) @translation.override('nl') def test_l10n(self): w = SelectDateWidget( @@ -485,6 +485,11 @@ class SelectDateWidgetTest(WidgetTest): '13-08-0001', ) + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The test should remain because + # format-related settings will take precedence over locale-dictated + # formats. + @ignore_warnings(category=RemovedInDjango50Warning) @override_settings(USE_L10N=False, DATE_INPUT_FORMATS=['%d.%m.%Y']) def test_custom_input_format(self): w = SelectDateWidget(years=('0001', '1899', '2009', '2010')) @@ -551,7 +556,7 @@ class SelectDateWidgetTest(WidgetTest): data = {'field_day': '1', 'field_month': '12', 'field_year': '2000'} self.assertIs(self.widget.value_omitted_from_data(data, {}, 'field'), False) - @override_settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_years_rendered_without_separator(self): widget = SelectDateWidget(years=(2007,)) self.check_html(widget, 'mydate', '', html=( diff --git a/tests/forms_tests/widget_tests/test_splithiddendatetimewidget.py b/tests/forms_tests/widget_tests/test_splithiddendatetimewidget.py index dff28161a5..c574eb6f7b 100644 --- a/tests/forms_tests/widget_tests/test_splithiddendatetimewidget.py +++ b/tests/forms_tests/widget_tests/test_splithiddendatetimewidget.py @@ -1,7 +1,6 @@ from datetime import datetime from django.forms import SplitHiddenDateTimeWidget -from django.test import override_settings from django.utils import translation from .base import WidgetTest @@ -30,7 +29,6 @@ class SplitHiddenDateTimeWidgetTest(WidgetTest): '<input type="hidden" name="date_1" value="12:51:00">' )) - @override_settings(USE_L10N=True) @translation.override('de-at') def test_l10n(self): d = datetime(2007, 9, 17, 12, 51) diff --git a/tests/forms_tests/widget_tests/test_timeinput.py b/tests/forms_tests/widget_tests/test_timeinput.py index 1a511e4cab..6060168eb3 100644 --- a/tests/forms_tests/widget_tests/test_timeinput.py +++ b/tests/forms_tests/widget_tests/test_timeinput.py @@ -1,7 +1,6 @@ from datetime import time from django.forms import TimeInput -from django.test import override_settings from django.utils import translation from .base import WidgetTest @@ -41,7 +40,6 @@ class TimeInputTest(WidgetTest): widget = TimeInput(format='%H:%M', attrs={'type': 'time'}) self.check_html(widget, 'time', t, html='<input type="time" name="time" value="12:51">') - @override_settings(USE_L10N=True) @translation.override('de-at') def test_l10n(self): t = time(12, 51, 34, 482548) diff --git a/tests/gis_tests/test_geoforms.py b/tests/gis_tests/test_geoforms.py index 4768d9b39e..a2a3ccae7b 100644 --- a/tests/gis_tests/test_geoforms.py +++ b/tests/gis_tests/test_geoforms.py @@ -238,7 +238,7 @@ class SpecializedFieldTest(SimpleTestCase): self.assertIn(escape(ogr.json), rendered) # map_srid in openlayers.html template must not be localized. - @override_settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True) + @override_settings(USE_THOUSAND_SEPARATOR=True) def test_pointfield(self): class PointForm(forms.Form): p = forms.PointField() diff --git a/tests/humanize_tests/tests.py b/tests/humanize_tests/tests.py index a0d16bbfed..d710a99263 100644 --- a/tests/humanize_tests/tests.py +++ b/tests/humanize_tests/tests.py @@ -89,13 +89,13 @@ class HumanizeTests(SimpleTestCase): '100', '1,000', '10,123', '10,311', '1,000,000', '1,234,567.1234567', '1,234,567.1234567', None, ) - with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=False): + with self.settings(USE_THOUSAND_SEPARATOR=False): with translation.override('en'): self.humanize_tester(test_list, result_list, 'intcomma') def test_intcomma_without_number_grouping(self): # Regression for #17414 - with translation.override('ja'), self.settings(USE_L10N=True): + with translation.override('ja'): self.humanize_tester([100], ['100'], 'intcomma') def test_intword(self): @@ -126,7 +126,7 @@ class HumanizeTests(SimpleTestCase): '100', '1000', '10123', '10311', '1000000', None) result_list = ('100', '1.000', '10.123', '10.311', '1.000.000', '1.234.567,25', '100', '1.000', '10.123', '10.311', '1.000.000', None) - with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True): + with self.settings(USE_THOUSAND_SEPARATOR=True): with translation.override('de'): self.humanize_tester(test_list, result_list, 'intcomma') @@ -143,7 +143,7 @@ class HumanizeTests(SimpleTestCase): # Negative integers. test_list_negative = ('-' + test for test in test_list_positive) result_list_negative = ('-' + result for result in result_list_positive) - with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True): + with self.settings(USE_THOUSAND_SEPARATOR=True): with translation.override('de'): self.humanize_tester( (*test_list_positive, *test_list_negative), @@ -355,7 +355,7 @@ class HumanizeTests(SimpleTestCase): orig_humanize_datetime, humanize.datetime = humanize.datetime, MockDateTime try: # Choose a language with different naturaltime-past/naturaltime-future translations - with translation.override('cs'), self.settings(USE_L10N=True): + with translation.override('cs'): self.humanize_tester(test_list, result_list, 'naturaltime') finally: humanize.datetime = orig_humanize_datetime diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 104d986a2c..bb6ea15f85 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -19,9 +19,11 @@ from django.conf.locale import LANG_INFO from django.conf.urls.i18n import i18n_patterns from django.template import Context, Template from django.test import ( - RequestFactory, SimpleTestCase, TestCase, override_settings, + RequestFactory, SimpleTestCase, TestCase, ignore_warnings, + override_settings, ) from django.utils import translation +from django.utils.deprecation import RemovedInDjango50Warning from django.utils.formats import ( date_format, get_format, iter_format_modules, localize, localize_input, reset_format_cache, sanitize_separators, sanitize_strftime_format, @@ -422,7 +424,6 @@ class TranslationThreadSafetyTests(SimpleTestCase): self.assertLess(translation_count, len(trans_real._translations)) -@override_settings(USE_L10N=True) class FormattingTests(SimpleTestCase): def setUp(self): @@ -498,6 +499,7 @@ class FormattingTests(SimpleTestCase): self.assertEqual('31.12.2009 в 20:50', Template('{{ dt|date:"d.m.Y в H:i" }}').render(self.ctxt)) self.assertEqual('⌚ 10:15', Template('{{ t|time:"⌚ H:i" }}').render(self.ctxt)) + @ignore_warnings(category=RemovedInDjango50Warning) @override_settings(USE_L10N=False) def test_l10n_disabled(self): """ @@ -1135,8 +1137,9 @@ class FormattingTests(SimpleTestCase): self.assertEqual(sanitize_separators('77\xa0777,777'), '77777.777') self.assertEqual(sanitize_separators('12 345'), '12345') self.assertEqual(sanitize_separators('77 777,777'), '77777.777') - with self.settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=False): - self.assertEqual(sanitize_separators('12\xa0345'), '12\xa0345') + with translation.override(None): # RemovedInDjango50Warning + with self.settings(USE_THOUSAND_SEPARATOR=True, THOUSAND_SEPARATOR='.'): + self.assertEqual(sanitize_separators('12\xa0345'), '12\xa0345') with self.settings(USE_THOUSAND_SEPARATOR=True): with patch_formats(get_language(), THOUSAND_SEPARATOR='.', DECIMAL_SEPARATOR=','): @@ -1144,18 +1147,25 @@ class FormattingTests(SimpleTestCase): # Suspicion that user entered dot as decimal separator (#22171) self.assertEqual(sanitize_separators('10.10'), '10.10') - with self.settings(USE_L10N=False, DECIMAL_SEPARATOR=','): - self.assertEqual(sanitize_separators('1001,10'), '1001.10') - self.assertEqual(sanitize_separators('1001.10'), '1001.10') - - with self.settings( - USE_L10N=False, DECIMAL_SEPARATOR=',', USE_THOUSAND_SEPARATOR=True, - THOUSAND_SEPARATOR='.' - ): - self.assertEqual(sanitize_separators('1.001,10'), '1001.10') - self.assertEqual(sanitize_separators('1001,10'), '1001.10') - self.assertEqual(sanitize_separators('1001.10'), '1001.10') - self.assertEqual(sanitize_separators('1,001.10'), '1.001.10') # Invalid output + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The assertions should remain + # because format-related settings will take precedence over + # locale-dictated formats. + with ignore_warnings(category=RemovedInDjango50Warning): + with self.settings(USE_L10N=False): + with self.settings(DECIMAL_SEPARATOR=','): + self.assertEqual(sanitize_separators('1001,10'), '1001.10') + self.assertEqual(sanitize_separators('1001.10'), '1001.10') + with self.settings( + DECIMAL_SEPARATOR=',', + THOUSAND_SEPARATOR='.', + USE_THOUSAND_SEPARATOR=True, + ): + self.assertEqual(sanitize_separators('1.001,10'), '1001.10') + self.assertEqual(sanitize_separators('1001,10'), '1001.10') + self.assertEqual(sanitize_separators('1001.10'), '1001.10') + # Invalid output. + self.assertEqual(sanitize_separators('1,001.10'), '1.001.10') def test_iter_format_modules(self): """ @@ -1225,10 +1235,21 @@ class FormattingTests(SimpleTestCase): output3 = '; '.join([expected_localized, expected_unlocalized]) output4 = '; '.join([expected_unlocalized, expected_localized]) with translation.override('de', deactivate=True): - with self.settings(USE_L10N=False, USE_THOUSAND_SEPARATOR=True): - self.assertEqual(template1.render(context), output1) - self.assertEqual(template4.render(context), output4) - with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True): + # RemovedInDjango50Warning: When the deprecation ends, remove + # @ignore_warnings and USE_L10N=False. The assertions should remain + # because format-related settings will take precedence over + # locale-dictated formats. + with ignore_warnings(category=RemovedInDjango50Warning): + with self.settings( + USE_L10N=False, + DATE_FORMAT='N j, Y', + DECIMAL_SEPARATOR='.', + NUMBER_GROUPING=0, + USE_THOUSAND_SEPARATOR=True, + ): + self.assertEqual(template1.render(context), output1) + self.assertEqual(template4.render(context), output4) + with self.settings(USE_THOUSAND_SEPARATOR=True): self.assertEqual(template1.render(context), output1) self.assertEqual(template2.render(context), output2) self.assertEqual(template3.render(context), output3) @@ -1242,9 +1263,17 @@ class FormattingTests(SimpleTestCase): context = Context( {'int': 1455, 'float': 3.14, 'decimal': decimal.Decimal('24.1567')} ) - for use_l10n in [True, False]: - with self.subTest(use_l10n=use_l10n), self.settings( - USE_L10N=use_l10n, + with self.settings( + DECIMAL_SEPARATOR=',', + USE_THOUSAND_SEPARATOR=True, + THOUSAND_SEPARATOR='°', + NUMBER_GROUPING=2, + ): + self.assertEqual(template.render(context), '1455/3.14/24.1567') + # RemovedInDjango50Warning. + with ignore_warnings(category=RemovedInDjango50Warning): + with self.settings( + USE_L10N=False, DECIMAL_SEPARATOR=',', USE_THOUSAND_SEPARATOR=True, THOUSAND_SEPARATOR='°', diff --git a/tests/settings_tests/tests.py b/tests/settings_tests/tests.py index ba38fd87ba..899059764e 100644 --- a/tests/settings_tests/tests.py +++ b/tests/settings_tests/tests.py @@ -248,19 +248,19 @@ class SettingsTests(SimpleTestCase): Allow deletion of a setting in an overridden settings set (#18824) """ previous_i18n = settings.USE_I18N - previous_l10n = settings.USE_L10N + previous_tz = settings.USE_TZ with self.settings(USE_I18N=False): del settings.USE_I18N with self.assertRaises(AttributeError): getattr(settings, 'USE_I18N') # Should also work for a non-overridden setting - del settings.USE_L10N + del settings.USE_TZ with self.assertRaises(AttributeError): - getattr(settings, 'USE_L10N') + getattr(settings, 'USE_TZ') self.assertNotIn('USE_I18N', dir(settings)) - self.assertNotIn('USE_L10N', dir(settings)) + self.assertNotIn('USE_TZ', dir(settings)) self.assertEqual(settings.USE_I18N, previous_i18n) - self.assertEqual(settings.USE_L10N, previous_l10n) + self.assertEqual(settings.USE_TZ, previous_tz) def test_override_settings_nested(self): """ diff --git a/tests/sitemaps_tests/test_http.py b/tests/sitemaps_tests/test_http.py index 5dffe4017d..3a820e140f 100644 --- a/tests/sitemaps_tests/test_http.py +++ b/tests/sitemaps_tests/test_http.py @@ -176,7 +176,7 @@ class HTTPSitemapTests(SitemapTestsBase): response = self.client.get('/lastmod-sitemaps/descending.xml') self.assertEqual(response.headers['Last-Modified'], 'Sat, 20 Apr 2013 05:00:00 GMT') - @override_settings(USE_I18N=True, USE_L10N=True) + @override_settings(USE_I18N=True) def test_localized_priority(self): """The priority value should not be localized.""" with translation.override('fr'): diff --git a/tests/template_tests/filter_tests/test_date.py b/tests/template_tests/filter_tests/test_date.py index f973c229b9..b2bdfa2bbb 100644 --- a/tests/template_tests/filter_tests/test_date.py +++ b/tests/template_tests/filter_tests/test_date.py @@ -1,7 +1,7 @@ from datetime import datetime, time from django.template.defaultfilters import date -from django.test import SimpleTestCase, override_settings +from django.test import SimpleTestCase from django.utils import timezone, translation from ..utils import setup @@ -20,13 +20,9 @@ class DateTests(TimezoneTestCase): output = self.engine.render_to_string('date02', {'d': datetime(2008, 1, 1)}) self.assertEqual(output, 'Jan. 1, 2008') - @override_settings(USE_L10N=True) @setup({'date02_l10n': '{{ d|date }}'}) def test_date02_l10n(self): - """ - Without arg and when USE_L10N is True, the active language's DATE_FORMAT - is used. - """ + """Without arg, the active language's DATE_FORMAT is used.""" with translation.override('fr'): output = self.engine.render_to_string('date02_l10n', {'d': datetime(2008, 1, 1)}) self.assertEqual(output, '1 janvier 2008') diff --git a/tests/template_tests/filter_tests/test_filesizeformat.py b/tests/template_tests/filter_tests/test_filesizeformat.py index 1e5e2dee4f..3b3e02eadb 100644 --- a/tests/template_tests/filter_tests/test_filesizeformat.py +++ b/tests/template_tests/filter_tests/test_filesizeformat.py @@ -47,7 +47,7 @@ class FunctionTests(SimpleTestCase): ('', '0\xa0Bytes'), ('\N{GREEK SMALL LETTER ALPHA}', '0\xa0Bytes'), ] - with self.settings(USE_L10N=True), translation.override('de'): + with translation.override('de'): for value, expected in tests: with self.subTest(value=value): self.assertEqual(filesizeformat(value), expected) diff --git a/tests/template_tests/filter_tests/test_time.py b/tests/template_tests/filter_tests/test_time.py index 919417dc12..a848e74378 100644 --- a/tests/template_tests/filter_tests/test_time.py +++ b/tests/template_tests/filter_tests/test_time.py @@ -1,7 +1,7 @@ from datetime import time from django.template.defaultfilters import time as time_filter -from django.test import SimpleTestCase, override_settings +from django.test import SimpleTestCase from django.utils import timezone, translation from ..utils import setup @@ -18,7 +18,6 @@ class TimeTests(TimezoneTestCase): output = self.engine.render_to_string('time00', {'dt': time(16, 25)}) self.assertEqual(output, '4:25 p.m.') - @override_settings(USE_L10N=True) @setup({'time00_l10n': '{{ dt|time }}'}) def test_time00_l10n(self): with translation.override('fr'): diff --git a/tests/timezones/tests.py b/tests/timezones/tests.py index 7b54ec3bfc..98c5cdac33 100644 --- a/tests/timezones/tests.py +++ b/tests/timezones/tests.py @@ -24,12 +24,13 @@ from django.template import ( Context, RequestContext, Template, TemplateSyntaxError, context_processors, ) from django.test import ( - SimpleTestCase, TestCase, TransactionTestCase, override_settings, - skipIfDBFeature, skipUnlessDBFeature, + SimpleTestCase, TestCase, TransactionTestCase, ignore_warnings, + override_settings, skipIfDBFeature, skipUnlessDBFeature, ) from django.test.utils import requires_tz_support from django.urls import reverse from django.utils import timezone +from django.utils.deprecation import RemovedInDjango50Warning from django.utils.timezone import timedelta from .forms import ( @@ -812,8 +813,15 @@ class SerializationTests(SimpleTestCase): self.assertEqual(obj.dt, dt) +# RemovedInDjango50Warning: When the deprecation ends, remove setUpClass() and +# USE_L10N=False. The tests should remain because format-related settings will +# take precedence over locale-dictated formats. @override_settings(DATETIME_FORMAT='c', TIME_ZONE='Africa/Nairobi', USE_L10N=False, USE_TZ=True) class TemplateTests(SimpleTestCase): + @classmethod + def setUpClass(cls): + with ignore_warnings(category=RemovedInDjango50Warning): + super().setUpClass() @requires_tz_support def test_localtime_templatetag_and_filters(self): @@ -1072,8 +1080,15 @@ class TemplateTests(SimpleTestCase): self.assertEqual(tpl.render(Context({})), "+0700") +# RemovedInDjango50Warning: When the deprecation ends, remove setUpClass() and +# USE_L10N=False. The tests should remain because format-related settings will +# take precedence over locale-dictated formats. @override_settings(DATETIME_FORMAT='c', TIME_ZONE='Africa/Nairobi', USE_L10N=False, USE_TZ=False) class LegacyFormsTests(TestCase): + @classmethod + def setUpClass(cls): + with ignore_warnings(category=RemovedInDjango50Warning): + super().setUpClass() def test_form(self): form = EventForm({'dt': '2011-09-01 13:20:30'}) @@ -1109,8 +1124,15 @@ class LegacyFormsTests(TestCase): self.assertEqual(e.dt, datetime.datetime(2011, 9, 1, 13, 20, 30)) +# RemovedInDjango50Warning: When the deprecation ends, remove setUpClass() and +# USE_L10N=False. The tests should remain because format-related settings will +# take precedence over locale-dictated formats. @override_settings(DATETIME_FORMAT='c', TIME_ZONE='Africa/Nairobi', USE_L10N=False, USE_TZ=True) class NewFormsTests(TestCase): + @classmethod + def setUpClass(cls): + with ignore_warnings(category=RemovedInDjango50Warning): + super().setUpClass() @requires_tz_support def test_form(self): @@ -1183,6 +1205,10 @@ class NewFormsTests(TestCase): ROOT_URLCONF='timezones.urls', ) class AdminTests(TestCase): + @classmethod + def setUpClass(cls): + with ignore_warnings(category=RemovedInDjango50Warning): + super().setUpClass() @classmethod def setUpTestData(cls): diff --git a/tests/utils_tests/test_numberformat.py b/tests/utils_tests/test_numberformat.py index 201e2cfe87..2da0c9f300 100644 --- a/tests/utils_tests/test_numberformat.py +++ b/tests/utils_tests/test_numberformat.py @@ -15,9 +15,8 @@ class TestNumberFormat(SimpleTestCase): self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34') self.assertEqual(nformat(-1234.33, '.', decimal_pos=1), '-1234.3') # The use_l10n parameter can force thousand grouping behavior. - with self.settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=True): + with self.settings(USE_THOUSAND_SEPARATOR=True): self.assertEqual(nformat(1234, '.', grouping=3, thousand_sep=',', use_l10n=False), '1234') - with self.settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=False): self.assertEqual(nformat(1234, '.', grouping=3, thousand_sep=',', use_l10n=True), '1,234') def test_format_string(self): diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py index aa3cf4b839..5ceb7fc39e 100644 --- a/tests/view_tests/tests/test_debug.py +++ b/tests/view_tests/tests/test_debug.py @@ -195,7 +195,7 @@ class DebugViewTests(SimpleTestCase): """ Numeric IDs and fancy traceback context blocks line numbers shouldn't be localized. """ - with self.settings(DEBUG=True, USE_L10N=True): + with self.settings(DEBUG=True): with self.assertLogs('django.request', 'ERROR'): response = self.client.get('/raises500/') # We look for a HTML fragment of the form diff --git a/tests/view_tests/tests/test_i18n.py b/tests/view_tests/tests/test_i18n.py index 9276f61fea..63e9ef76c6 100644 --- a/tests/view_tests/tests/test_i18n.py +++ b/tests/view_tests/tests/test_i18n.py @@ -206,8 +206,8 @@ class I18NViewTests(SimpleTestCase): def test_get_formats(self): formats = get_formats() # Test 3 possible types in get_formats: integer, string, and list. - self.assertEqual(formats['FIRST_DAY_OF_WEEK'], 0) - self.assertEqual(formats['DECIMAL_SEPARATOR'], '.') + self.assertEqual(formats['FIRST_DAY_OF_WEEK'], 1) + self.assertEqual(formats['DECIMAL_SEPARATOR'], ',') self.assertEqual(formats['TIME_INPUT_FORMATS'], ['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']) def test_jsi18n(self): @@ -243,7 +243,7 @@ class I18NViewTests(SimpleTestCase): self.assertIn('catalog', data) self.assertIn('formats', data) self.assertEqual(data['formats']['TIME_INPUT_FORMATS'], ['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']) - self.assertEqual(data['formats']['FIRST_DAY_OF_WEEK'], 0) + self.assertEqual(data['formats']['FIRST_DAY_OF_WEEK'], 1) self.assertIn('plural', data) self.assertEqual(data['catalog']['month name\x04May'], 'Mai') self.assertIn('DATETIME_FORMAT', data['formats']) |