From 0d0e7f15038360c158b6d22c679b47b21557fa1f Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 20 Aug 2026 13:06:43 +0200 Subject: [PATCH 1/3] Refs #37293 -- Aliased RemovedInDjango70Warning to RemovedInDjango2028Warning. Updated references to RemovedInDjango70Warning to use the new warning, and adjusted references to "Django 7.0" to "Django 2028". RemovedInDjango70Warning remains importable as an alias of the same class, so existing warning filters and except clauses in third-party code keep working across the rename. --- django/conf/__init__.py | 61 ++--- django/conf/global_settings.py | 18 +- django/contrib/admin/checks.py | 2 +- django/contrib/admin/options.py | 47 ++-- django/contrib/postgres/aggregates/general.py | 24 +- django/contrib/postgres/aggregates/mixins.py | 8 +- django/core/mail/__init__.py | 61 ++--- django/core/mail/backends/base.py | 18 +- django/core/mail/backends/filebased.py | 2 +- django/core/mail/backends/locmem.py | 4 +- django/core/mail/backends/smtp.py | 8 +- django/core/mail/deprecation.py | 10 +- django/core/mail/handler.py | 10 +- django/core/mail/message.py | 57 ++--- django/core/paginator.py | 8 +- django/core/signing.py | 12 +- django/db/backends/base/creation.py | 6 +- django/db/models/fields/__init__.py | 10 +- django/db/models/fields/json.py | 10 +- django/db/models/query.py | 26 +-- django/db/models/sql/compiler.py | 6 +- django/db/models/sql/query.py | 12 +- django/db/models/utils.py | 4 +- django/db/transaction.py | 4 +- django/middleware/common.py | 2 +- django/template/base.py | 6 +- django/test/utils.py | 4 +- django/utils/crypto.py | 12 +- django/utils/deprecation.py | 11 +- django/utils/html.py | 10 +- django/utils/log.py | 8 +- docs/howto/mailers-migration.txt | 4 +- docs/internals/deprecation.txt | 6 +- docs/intro/tutorial02.txt | 2 +- docs/ref/models/instances.txt | 2 +- docs/ref/models/querysets.txt | 2 +- docs/ref/settings.txt | 34 +-- docs/ref/templates/builtins.txt | 4 +- docs/releases/5.2.15.txt | 2 +- docs/releases/6.0.6.txt | 2 +- docs/releases/6.0.txt | 2 +- docs/releases/6.1.txt | 6 +- docs/releases/6.2.txt | 11 + docs/topics/db/queries.txt | 4 +- docs/topics/email.txt | 16 +- tests/admin_views/admin.py | 4 +- tests/admin_views/models.py | 2 +- tests/admin_views/test_actions.py | 10 +- tests/aggregation_regress/tests.py | 6 +- tests/annotations/tests.py | 16 +- tests/backends/base/test_creation.py | 6 +- tests/basic/models.py | 4 +- tests/basic/tests.py | 12 +- tests/defer/tests.py | 8 +- ...test_signed_cookie_legacy_salt_fallback.py | 10 +- .../deprecation/test_use_blank_choice_dash.py | 10 +- tests/deprecation/tests.py | 14 ++ tests/expressions/test_queryset_values.py | 4 +- tests/forms_tests/tests/test_forms.py | 8 +- tests/gis_tests/relatedapp/tests.py | 6 +- tests/logging_tests/tests.py | 14 +- tests/lookup/tests.py | 22 +- tests/mail/__init__.py | 10 +- tests/mail/test_backends.py | 103 ++++----- tests/mail/test_deprecated.py | 48 ++-- tests/mail/test_handler.py | 6 +- tests/mail/tests.py | 216 +++++++++--------- tests/middleware/tests.py | 2 +- tests/model_fields/test_booleanfield.py | 8 +- tests/model_fields/test_jsonfield.py | 16 +- tests/model_fields/tests.py | 8 +- tests/model_inheritance_regress/tests.py | 6 +- tests/modeladmin/test_checks.py | 2 +- tests/modeladmin/tests.py | 16 +- tests/pagination/tests.py | 10 +- tests/postgres_tests/test_aggregates.py | 20 +- tests/postgres_tests/test_array.py | 8 +- tests/queries/test_sqlcompiler.py | 6 +- tests/queries/tests.py | 8 +- tests/select_related/tests.py | 10 +- tests/select_related_onetoone/tests.py | 6 +- tests/signed_cookies_tests/tests.py | 16 +- tests/signing/tests.py | 6 +- .../template_tests/syntax_tests/test_basic.py | 10 +- tests/test_utils/tests.py | 8 +- tests/transactions/tests.py | 4 +- tests/utils_tests/test_crypto.py | 8 +- tests/utils_tests/test_html.py | 10 +- tests/view_tests/tests/test_debug.py | 2 +- 89 files changed, 680 insertions(+), 627 deletions(-) diff --git a/django/conf/__init__.py b/django/conf/__init__.py index 7a9ed9418b1f..0edc7dcefe42 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -15,7 +15,7 @@ from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured from django.utils.deprecation import ( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, warn_about_external_use, ) from django.utils.functional import LazyObject, empty @@ -25,20 +25,20 @@ DEFAULT_STORAGE_ALIAS = "default" STATICFILES_STORAGE_ALIAS = "staticfiles" -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. SIGNED_COOKIE_LEGACY_SALT_DEPRECATED_MSG = ( "The SIGNED_COOKIE_LEGACY_SALT_FALLBACK transitional setting is " "deprecated. Remove it from your settings once legacy signed cookies " - "have expired. They will not be accepted in Django 7.0." + "have expired. They will not be accepted in Django 2028." ) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. USE_BLANK_CHOICE_DASH_DEPRECATED_MSG = ( "The USE_BLANK_CHOICE_DASH setting is deprecated. If you wish to define " "your own default blank choice label, override " "django.db.models.fields.BLANK_CHOICE_LABEL in your app's ready() method." ) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. DEPRECATED_EMAIL_SETTINGS = { "EMAIL_BACKEND", "EMAIL_FILE_PATH", @@ -53,11 +53,11 @@ "EMAIL_USE_TLS", } EMAIL_SETTING_DEPRECATED_MSG = ( - "The {name} setting is deprecated. Migrate to MAILERS before Django 7.0." + "The {name} setting is deprecated. Migrate to MAILERS before Django 2028." ) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # Must be called with the complete set of user-defined setting names (but no # default settings). def _check_email_settings_conflicts(explicit_settings): @@ -123,14 +123,15 @@ def __getattr__(self, name): _wrapped = self._wrapped val = getattr(_wrapped, name) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if name in DEPRECATED_EMAIL_SETTINGS: if hasattr(_wrapped, "MAILERS"): raise AttributeError( f"The {name} setting is not available when MAILERS is defined." ) _show_settings_deprecation_warning( - EMAIL_SETTING_DEPRECATED_MSG.format(name=name), RemovedInDjango70Warning + EMAIL_SETTING_DEPRECATED_MSG.format(name=name), + RemovedInDjango2028Warning, ) # Special case some settings which require further modification. @@ -154,18 +155,18 @@ def __setattr__(self, name, value): else: self.__dict__.pop(name, None) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if name == "SIGNED_COOKIE_LEGACY_SALT_FALLBACK": _show_settings_deprecation_warning( SIGNED_COOKIE_LEGACY_SALT_DEPRECATED_MSG, - RemovedInDjango70Warning, + RemovedInDjango2028Warning, ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if name == "USE_BLANK_CHOICE_DASH": _show_settings_deprecation_warning( - USE_BLANK_CHOICE_DASH_DEPRECATED_MSG, RemovedInDjango70Warning + USE_BLANK_CHOICE_DASH_DEPRECATED_MSG, RemovedInDjango2028Warning ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if name == "MAILERS": # When MAILERS is set, clear any cached values of # deprecated settings so that __getattr__() runs again for them. @@ -173,7 +174,8 @@ def __setattr__(self, name, value): self.__dict__.pop(setting, None) if name in DEPRECATED_EMAIL_SETTINGS: _show_settings_deprecation_warning( - EMAIL_SETTING_DEPRECATED_MSG.format(name=name), RemovedInDjango70Warning + EMAIL_SETTING_DEPRECATED_MSG.format(name=name), + RemovedInDjango2028Warning, ) super().__setattr__(name, value) @@ -183,7 +185,7 @@ def __delattr__(self, name): super().__delattr__(name) self.__dict__.pop(name, None) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def __dir__(self): attrs = super().__dir__() if hasattr(self._wrapped, "MAILERS"): @@ -206,7 +208,7 @@ def configure(self, default_settings=global_settings, **options): if self._wrapped is not empty: raise RuntimeError("Settings already configured.") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. _check_email_settings_conflicts(options.keys()) holder = UserSettingsHolder(default_settings) @@ -278,26 +280,26 @@ def __init__(self, settings_module): setattr(self, setting, setting_value) self._explicit_settings.add(setting) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if "SIGNED_COOKIE_LEGACY_SALT_FALLBACK" in self._explicit_settings: warnings.warn( SIGNED_COOKIE_LEGACY_SALT_DEPRECATED_MSG, - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if "USE_BLANK_CHOICE_DASH" in self._explicit_settings: warnings.warn( USE_BLANK_CHOICE_DASH_DEPRECATED_MSG, - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. _check_email_settings_conflicts(self._explicit_settings) for name in DEPRECATED_EMAIL_SETTINGS.intersection(self._explicit_settings): warnings.warn( EMAIL_SETTING_DEPRECATED_MSG.format(name=name), - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) @@ -343,21 +345,22 @@ def __getattr__(self, name): def __setattr__(self, name, value): self._deleted.discard(name) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if name == "SIGNED_COOKIE_LEGACY_SALT_FALLBACK": _show_settings_deprecation_warning( SIGNED_COOKIE_LEGACY_SALT_DEPRECATED_MSG, - RemovedInDjango70Warning, + RemovedInDjango2028Warning, ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if name == "USE_BLANK_CHOICE_DASH": _show_settings_deprecation_warning( - USE_BLANK_CHOICE_DASH_DEPRECATED_MSG, RemovedInDjango70Warning + USE_BLANK_CHOICE_DASH_DEPRECATED_MSG, RemovedInDjango2028Warning ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if name in DEPRECATED_EMAIL_SETTINGS: _show_settings_deprecation_warning( - EMAIL_SETTING_DEPRECATED_MSG.format(name=name), RemovedInDjango70Warning + EMAIL_SETTING_DEPRECATED_MSG.format(name=name), + RemovedInDjango2028Warning, ) super().__setattr__(name, value) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index a00c5c39220e..5799da577c82 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -188,28 +188,28 @@ def gettext_noop(s): DATABASE_ROUTERS = [] # Mailer configurations. No mailers are defined by default. -# RemovedInDjango70Warning: uncomment the next line. +# RemovedInDjango2028Warning: uncomment the next line. # MAILERS = {} -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # The email backend to use. For possible shortcuts see django.core.mail. # The default is to use the SMTP backend. # Third-party backends can be specified by providing a Python path # to a module that defines an EmailBackend class. EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # Host for sending email. EMAIL_HOST = "localhost" -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # Port for sending email. EMAIL_PORT = 25 # Whether to send SMTP 'Date' header in the local time zone or in UTC. EMAIL_USE_LOCALTIME = False -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # Optional SMTP authentication information for EMAIL_HOST. EMAIL_HOST_USER = "" EMAIL_HOST_PASSWORD = "" @@ -226,7 +226,7 @@ def gettext_noop(s): # Default form rendering class. FORM_RENDERER = "django.forms.renderers.DjangoTemplates" -# RemovedInDjango70Warning: This setting allows to revert back to the old +# RemovedInDjango2028Warning: This setting allows to revert back to the old # blank choice label in Django 6.1. USE_BLANK_CHOICE_DASH = False @@ -681,9 +681,9 @@ def gettext_noop(s): SECURE_CSP = {} SECURE_CSP_REPORT_ONLY = {} -# RemovedInDjango70Warning: A transitional setting helpful in early adoption of -# HTTPS as the default protocol in urlize and urlizetrunc when no protocol is -# provided. Set to True to assume HTTPS during the Django 6.x release cycle. +# RemovedInDjango2028Warning: A transitional setting helpful in early adoption +# of HTTPS as the default protocol in urlize and urlizetrunc when no protocol +# is provided. Set to True to assume HTTPS during the Django 6.x release cycle. URLIZE_ASSUME_HTTPS = False ######### diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py index 3cea98a0dcb0..82d7f9d2d35a 100644 --- a/django/contrib/admin/checks.py +++ b/django/contrib/admin/checks.py @@ -1101,7 +1101,7 @@ def _check_list_select_related(self, obj): if not isinstance(obj.list_select_related, (bool, list, tuple)): return must_be( - # RemovedInDjango70Warning: when the deprecation ends, replace: + # RemovedInDjango2028Warning: replace with: # "a tuple, list, or False", # and also update docs/ref/checks.txt. "a boolean, tuple or list", diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index d79361927960..818b816cf08d 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -63,7 +63,10 @@ from django.template.response import SimpleTemplateResponse, TemplateResponse from django.urls import reverse from django.utils.decorators import method_decorator -from django.utils.deprecation import RemovedInDjango70Warning, warn_about_implementation +from django.utils.deprecation import ( + RemovedInDjango2028Warning, + warn_about_implementation, +) from django.utils.html import format_html from django.utils.http import urlencode from django.utils.inspect import get_func_args @@ -107,25 +110,25 @@ class Action: plural_description: str locations: list - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def _as_tuple(self): return (self.func, self.name, self.description) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def __iter__(self): warnings.warn( "Unpacking an action tuple is deprecated. Use Action attributes instead.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) return iter(self._as_tuple()) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def __getitem__(self, index): warnings.warn( "Using indexes on an action tuple is deprecated. " "Use Action attributes instead.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) return self._as_tuple()[index] @@ -724,12 +727,12 @@ class ModelAdmin(BaseModelAdmin): def __init_subclass__(cls, **kwargs) -> None: super().__init_subclass__(**kwargs) if cls.__dict__.get("list_select_related") is True: - # RemovedInDjango70Warning: when the deprecation ends, raise a + # RemovedInDjango2028Warning: when the deprecation ends, raise a # ValueError. warnings.warn( "Setting ModelAdmin.list_select_related to True is deprecated. " "Use False or a list or tuple of fields to fetch instead.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) @@ -913,7 +916,7 @@ def get_changelist_instance(self, request): list_display = self.get_list_display(request) list_display_links = self.get_list_display_links(request, list_display) # Add the action checkboxes if any actions are available. - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # if self.get_actions( # request, action_location=ActionLocation.CHANGE_LIST # ): @@ -925,14 +928,14 @@ def get_changelist_instance(self, request): ChangeList = self.get_changelist(request) list_select_related = self.get_list_select_related(request) if list_select_related is True: - # RemovedInDjango70Warning: when the deprecation ends, remove the + # RemovedInDjango2028Warning: when the deprecation ends, remove the # below 'if' clause and raise a ValueError here. if self.list_select_related is not True: warn_about_implementation( "Returning True from ModelAdmin.get_list_select_related() is " "deprecated. Return False or a list or tuple of fields to " "fetch instead.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, self.get_list_select_related, ) return ChangeList( @@ -1126,7 +1129,7 @@ def _filter_actions_by_permissions(self, request, actions): filtered_actions.append(action) return filtered_actions - # RemovedInDjango70Warning: When the deprecation ends, remove. + # RemovedInDjango2028Warning: When the deprecation ends, remove. def _get_actions_with_action_location( self, request, action_location=ActionLocation.CHANGE_LIST ): @@ -1137,7 +1140,7 @@ def _get_actions_with_action_location( "Overriding get_actions() without the 'action_location' parameter is " "deprecated. Update the signature to get_actions(self, request, " "action_location=ActionLocation.CHANGE_LIST).", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, self.get_actions, ) if action_location == ActionLocation.CHANGE_FORM: @@ -1159,7 +1162,7 @@ def get_actions(self, request, action_location=ActionLocation.CHANGE_LIST): actions = self._filter_actions_by_permissions(request, base_actions) return {action.name: action for action in actions} - # RemovedInDjango70Warning: When the deprecation ends, remove. + # RemovedInDjango2028Warning: When the deprecation ends, remove. def _get_action_choices_with_action_location( self, request, @@ -1178,7 +1181,7 @@ def _get_action_choices_with_action_location( "parameter is deprecated. Update the signature to " "get_action_choices(self, request, default_choices=None, " "action_location=ActionLocation.CHANGE_LIST).", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, self.get_action_choices, ) return self.get_action_choices(request, default_choices=default_choices) @@ -1201,7 +1204,7 @@ def get_action_choices( if default_choices is None: default_choices = [("", get_blank_choice_label())] choices = [*default_choices] - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # actions = self.get_actions(request, action_location=action_location) actions = self._get_actions_with_action_location( request, action_location=action_location @@ -1858,7 +1861,7 @@ def response_action( else "" ) action_form = self.action_form(data, auto_id=None, prefix=prefix) - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # action_form.fields["action"].choices = self.get_action_choices( # request, action_location=action_location # ) @@ -1874,7 +1877,7 @@ def response_action( select_across = action_form.cleaned_data["select_across"] if action_location == ActionLocation.CHANGE_FORM: select_across = False - # RemovedInDjango70Warning: When the deprecation ends, replace: + # RemovedInDjango2028Warning: When the deprecation ends, replace: # actions = self.get_actions( # request, action_location=action_location # ) @@ -2090,7 +2093,7 @@ def _changeform_view(self, request, object_id, form_url, extra_context): ) action_form = None - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # actions = self.get_actions( # request, action_location=ActionLocation.CHANGE_FORM # ) @@ -2100,7 +2103,7 @@ def _changeform_view(self, request, object_id, form_url, extra_context): if actions and not add: action_location = ActionLocation.CHANGE_FORM action_form = self.action_form(auto_id=None, prefix=action_location.value) - # RemovedInDjango70Warning: When the deprecation ends, replace: + # RemovedInDjango2028Warning: When the deprecation ends, replace: # action_form.fields["action"].choices = self.get_action_choices( # request, action_location=action_location # ) @@ -2351,7 +2354,7 @@ def changelist_view(self, request, extra_context=None): action_failed = False selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME) - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # actions = self.get_actions( # request, action_location=ActionLocation.CHANGE_LIST # ) @@ -2439,7 +2442,7 @@ def changelist_view(self, request, extra_context=None): # Build the action form and populate it with available actions. if actions: action_form = self.action_form(auto_id=None) - # RemovedInDjango70Warning: When the deprecation ends, replace: + # RemovedInDjango2028Warning: When the deprecation ends, replace: # action_form.fields["action"].choices = self.get_action_choices( # request, action_location=ActionLocation.CHANGE_LIST # ) diff --git a/django/contrib/postgres/aggregates/general.py b/django/contrib/postgres/aggregates/general.py index be43e899be1e..978742fa7545 100644 --- a/django/contrib/postgres/aggregates/general.py +++ b/django/contrib/postgres/aggregates/general.py @@ -8,17 +8,17 @@ from django.db.models import BooleanField, JSONField from django.db.models import StringAgg as _StringAgg from django.db.models import Value -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning __all__ = [ "ArrayAgg", - "BitAnd", # RemovedInDjango70Warning - "BitOr", # RemovedInDjango70Warning - "BitXor", # RemovedInDjango70Warning + "BitAnd", # RemovedInDjango2028Warning + "BitOr", # RemovedInDjango2028Warning + "BitXor", # RemovedInDjango2028Warning "BoolAnd", "BoolOr", "JSONBAgg", - "StringAgg", # RemovedInDjango70Warning. + "StringAgg", # RemovedInDjango2028Warning. ] @@ -37,7 +37,7 @@ def __init__(self, expression, **extra): warnings.warn( "The PostgreSQL-specific BitAnd function is deprecated. Use " "django.db.models.aggregates.BitAnd instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, stacklevel=2, ) super().__init__(expression, **extra) @@ -48,7 +48,7 @@ def __init__(self, expression, **extra): warnings.warn( "The PostgreSQL-specific BitOr function is deprecated. Use " "django.db.models.aggregates.BitOr instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, stacklevel=2, ) super().__init__(expression, **extra) @@ -59,7 +59,7 @@ def __init__(self, expression, **extra): warnings.warn( "The PostgreSQL-specific BitXor function is deprecated. Use " "django.db.models.aggregates.BitXor instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, stacklevel=2, ) super().__init__(expression, **extra) @@ -82,16 +82,16 @@ class JSONBAgg(Aggregate): output_field = JSONField() -# RemovedInDjango70Warning: When the deprecation ends, remove completely. +# RemovedInDjango2028Warning: When the deprecation ends, remove completely. class StringAgg(_StringAgg): def __init__(self, expression, delimiter, **extra): if isinstance(delimiter, str): warnings.warn( "delimiter: str will be resolved as a field reference instead " - "of a string literal on Django 7.0. Pass " + "of a string literal on Django 2028. Pass " f"`delimiter=Value({delimiter!r})` to preserve the previous behavior.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, stacklevel=2, ) @@ -100,7 +100,7 @@ def __init__(self, expression, delimiter, **extra): warnings.warn( "The PostgreSQL specific StringAgg function is deprecated. Use " "django.db.models.aggregates.StringAgg instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, stacklevel=2, ) diff --git a/django/contrib/postgres/aggregates/mixins.py b/django/contrib/postgres/aggregates/mixins.py index 5cfe47d96c16..32bcdd592ea8 100644 --- a/django/contrib/postgres/aggregates/mixins.py +++ b/django/contrib/postgres/aggregates/mixins.py @@ -1,10 +1,10 @@ -# RemovedInDjango70Warning: When the deprecation ends, remove completely. +# RemovedInDjango2028Warning: When the deprecation ends, remove completely. import warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class OrderableAggMixin: allow_order_by = True @@ -12,7 +12,7 @@ def __init_subclass__(cls, /, *args, **kwargs): warnings.warn( "OrderableAggMixin is deprecated. Use Aggregate and allow_order_by " "instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, stacklevel=1, ) super().__init_subclass__(*args, **kwargs) diff --git a/django/core/mail/__init__.py b/django/core/mail/__init__.py index 4422f708b8bd..2bf57c6687c0 100644 --- a/django/core/mail/__init__.py +++ b/django/core/mail/__init__.py @@ -24,7 +24,7 @@ ) from django.core.mail.utils import DNS_NAME, CachedDnsName from django.utils.deprecation import ( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, deprecate_posargs, warn_about_external_use, ) @@ -56,7 +56,7 @@ "mail_managers", "EmailAlternative", "EmailAttachment", - # RemovedInDjango70Warning: When the deprecation ends, remove the last + # RemovedInDjango2028Warning: When the deprecation ends, remove the last # entries. "BadHeaderError", "SafeMIMEText", @@ -68,8 +68,8 @@ mailers = MailersHandler() -# RemovedInDjango70Warning. -@deprecate_posargs(RemovedInDjango70Warning, ["fail_silently"]) +# RemovedInDjango2028Warning. +@deprecate_posargs(RemovedInDjango2028Warning, ["fail_silently"]) def get_connection(backend=None, *, fail_silently=False, **kwds): """Load an email backend and return an instance of it. @@ -82,7 +82,7 @@ def get_connection(backend=None, *, fail_silently=False, **kwds): "get_connection() is deprecated. See 'Migrating email to mailers' " "in Django's documentation for recommended replacements." ) - warn_about_external_use(msg, RemovedInDjango70Warning, skip_frames=1) + warn_about_external_use(msg, RemovedInDjango2028Warning, skip_frames=1) warn_about_default_mailers_if_needed() if fail_silently: @@ -101,7 +101,7 @@ def get_connection(backend=None, *, fail_silently=False, **kwds): @deprecate_posargs( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, [ "fail_silently", "auth_user", @@ -132,7 +132,7 @@ def send_mail( Note: The API for this method is frozen. New code wanting to extend the functionality should use the EmailMessage class directly. """ - # RemovedInDjango70Warning: change entire implementation to: + # RemovedInDjango2028Warning: change entire implementation to: # email = EmailMultiAlternatives( # subject, message, from_email, recipient_list # ) @@ -141,15 +141,15 @@ def send_mail( # return email.send(using=using) if fail_silently: warn_about_external_use( - FAIL_SILENTLY_ARG_WARNING, RemovedInDjango70Warning, skip_frames=1 + FAIL_SILENTLY_ARG_WARNING, RemovedInDjango2028Warning, skip_frames=1 ) if auth_user is not None or auth_password is not None: warn_about_external_use( - AUTH_ARGS_WARNING, RemovedInDjango70Warning, skip_frames=1 + AUTH_ARGS_WARNING, RemovedInDjango2028Warning, skip_frames=1 ) if connection is not None: warn_about_external_use( - CONNECTION_ARG_WARNING, RemovedInDjango70Warning, skip_frames=1 + CONNECTION_ARG_WARNING, RemovedInDjango2028Warning, skip_frames=1 ) if using is not None: @@ -184,7 +184,7 @@ def send_mail( @deprecate_posargs( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, [ "fail_silently", "auth_user", @@ -210,21 +210,21 @@ def send_mass_mail( Note: The API for this method is frozen. New code wanting to extend the functionality should use the EmailMessage class directly. """ - # RemovedInDjango70Warning: change entire implementation to: + # RemovedInDjango2028Warning: change entire implementation to: # messages = [...] # mailer = mailers.default if using is None else mailers[using] # return mailer.send_messages(messages) if fail_silently: warn_about_external_use( - FAIL_SILENTLY_ARG_WARNING, RemovedInDjango70Warning, skip_frames=1 + FAIL_SILENTLY_ARG_WARNING, RemovedInDjango2028Warning, skip_frames=1 ) if auth_user is not None or auth_password is not None: warn_about_external_use( - AUTH_ARGS_WARNING, RemovedInDjango70Warning, skip_frames=1 + AUTH_ARGS_WARNING, RemovedInDjango2028Warning, skip_frames=1 ) if connection is not None: warn_about_external_use( - CONNECTION_ARG_WARNING, RemovedInDjango70Warning, skip_frames=1 + CONNECTION_ARG_WARNING, RemovedInDjango2028Warning, skip_frames=1 ) if using is not None: @@ -257,7 +257,7 @@ def send_mass_mail( return connection.send_messages(messages) -# RemovedInDjango70Warning: fail_silently and connection args. +# RemovedInDjango2028Warning: fail_silently and connection args. def _send_server_message( *, setting_name, @@ -268,15 +268,16 @@ def _send_server_message( connection=None, using=None, ): - # RemovedInDjango70Warning: everything before `recipients = getattr(...)`. - # skip_frames=2: this helper's caller + its @deprecate_posargs decorator. + # RemovedInDjango2028Warning: everything before `recipients = + # getattr(...)`. skip_frames=2: this helper's caller + its + # @deprecate_posargs decorator. if fail_silently: warn_about_external_use( - FAIL_SILENTLY_ARG_WARNING, RemovedInDjango70Warning, skip_frames=2 + FAIL_SILENTLY_ARG_WARNING, RemovedInDjango2028Warning, skip_frames=2 ) if connection is not None: warn_about_external_use( - CONNECTION_ARG_WARNING, RemovedInDjango70Warning, skip_frames=2 + CONNECTION_ARG_WARNING, RemovedInDjango2028Warning, skip_frames=2 ) if using is not None: @@ -286,18 +287,18 @@ def _send_server_message( "fail_silently cannot be used with a connection. " "Pass fail_silently to get_connection() instead." ) - # ... end of RemovedInDjango70Warning. + # ... end of RemovedInDjango2028Warning. recipients = getattr(settings, setting_name) if not recipients: return - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if all(isinstance(a, (list, tuple)) and len(a) == 2 for a in recipients): warnings.warn( f"Using (name, address) pairs in the {setting_name} setting is deprecated." " Replace with a list of email address strings.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, stacklevel=2, ) recipients = [a[1] for a in recipients] @@ -321,9 +322,9 @@ def _send_server_message( mail.send(using=using, fail_silently=fail_silently) -# RemovedInDjango70Warning: fail_silently and connection args. +# RemovedInDjango2028Warning: fail_silently and connection args. @deprecate_posargs( - RemovedInDjango70Warning, ["fail_silently", "connection", "html_message"] + RemovedInDjango2028Warning, ["fail_silently", "connection", "html_message"] ) def mail_admins( subject, @@ -346,9 +347,9 @@ def mail_admins( ) -# RemovedInDjango70Warning: fail_silently and connection args. +# RemovedInDjango2028Warning: fail_silently and connection args. @deprecate_posargs( - RemovedInDjango70Warning, ["fail_silently", "connection", "html_message"] + RemovedInDjango2028Warning, ["fail_silently", "connection", "html_message"] ) def mail_managers( subject, @@ -371,7 +372,7 @@ def mail_managers( ) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. _deprecate_on_import = { "BadHeaderError": "BadHeaderError is deprecated. Replace with ValueError.", "SafeMIMEText": ( @@ -385,7 +386,7 @@ def mail_managers( } -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. def __getattr__(name): try: msg = _deprecate_on_import[name] @@ -395,5 +396,5 @@ def __getattr__(name): # Issue deprecation warnings at time of import. from django.core.mail import message - warnings.warn(msg, category=RemovedInDjango70Warning) + warnings.warn(msg, category=RemovedInDjango2028Warning) return getattr(message, name) diff --git a/django/core/mail/backends/base.py b/django/core/mail/backends/base.py index 9061e9f65463..1d42c44a69fc 100644 --- a/django/core/mail/backends/base.py +++ b/django/core/mail/backends/base.py @@ -1,9 +1,9 @@ """Base email backend class.""" from django.core.mail import InvalidMailer -from django.utils.deprecation import RemovedInDjango70Warning, warn_about_external_use +from django.utils.deprecation import RemovedInDjango2028Warning, warn_about_external_use -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. _NOT_PROVIDED = object() @@ -24,7 +24,7 @@ class BaseEmailBackend: pass """ - # RemovedInDjango70Warning: fail_silently, _ignore_unknown_kwargs. + # RemovedInDjango2028Warning: fail_silently, _ignore_unknown_kwargs. def __init__( self, fail_silently=_NOT_PROVIDED, @@ -35,7 +35,7 @@ def __init__( ): self.alias = alias - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if fail_silently is _NOT_PROVIDED: self._fail_silently = False else: @@ -49,7 +49,7 @@ def __init__( if kwargs: kwarg_names = ", ".join(repr(key) for key in kwargs.keys()) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if alias is None: # Not being initialized from mail.mailers. Unknown kwargs are # ignored -- with a deprecation warning if they originated from @@ -60,23 +60,23 @@ def __init__( class_name = f"{type(self).__module__}.{type(self).__qualname__}" warn_about_external_use( f"{class_name}.__init__() does not support {kwarg_names}. " - "In Django 7.0, BaseEmailBackend will raise a TypeError " + "In Django 2028, BaseEmailBackend will raise a TypeError " "for unknown keyword arguments.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_name_prefixes="django.core.mail.backends", ) return raise InvalidMailer(f"Unknown options {kwarg_names}.", alias=alias) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def __getattr__(self, name): if name == "fail_silently": msg = ( "BaseEmailBackend.fail_silently is deprecated. A subclass " "that supports fail_silently must set its own attribute." ) - warn_about_external_use(msg, RemovedInDjango70Warning) + warn_about_external_use(msg, RemovedInDjango2028Warning) return self._fail_silently raise AttributeError( f"{type(self).__name__!r} object has no attribute {name!r}" diff --git a/django/core/mail/backends/filebased.py b/django/core/mail/backends/filebased.py index 67257738ac79..dabbe8368db8 100644 --- a/django/core/mail/backends/filebased.py +++ b/django/core/mail/backends/filebased.py @@ -17,7 +17,7 @@ def __init__(self, fail_silently=False, file_path=None, **kwargs): kwargs["stream"] = None super().__init__(fail_silently=fail_silently, **kwargs) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if self.alias is None: # Use deprecated settings when MAILERS not enabled. if file_path is not None: diff --git a/django/core/mail/backends/locmem.py b/django/core/mail/backends/locmem.py index 43a363ea737c..658d874b957d 100644 --- a/django/core/mail/backends/locmem.py +++ b/django/core/mail/backends/locmem.py @@ -18,8 +18,8 @@ class EmailBackend(BaseEmailBackend): The dummy outbox is accessible through the outbox instance attribute. """ - # RemovedInDjango70Warning: *args. (The only supported posarg will be - # removed from BaseEmailBackend in Django 7.0.) + # RemovedInDjango2028Warning: *args. (The only supported posarg will be + # removed from BaseEmailBackend in Django 2028.) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not hasattr(mail, "outbox"): diff --git a/django/core/mail/backends/smtp.py b/django/core/mail/backends/smtp.py index 5a45ee1dff36..8397d3f47d5a 100644 --- a/django/core/mail/backends/smtp.py +++ b/django/core/mail/backends/smtp.py @@ -10,7 +10,7 @@ from django.core.mail import InvalidMailer from django.core.mail.backends.base import BaseEmailBackend from django.core.mail.utils import DNS_NAME -from django.utils.deprecation import RemovedInDjango70Warning, warn_about_external_use +from django.utils.deprecation import RemovedInDjango2028Warning, warn_about_external_use from django.utils.encoding import force_str, punycode from django.utils.functional import cached_property @@ -34,13 +34,13 @@ def __init__( ssl_certfile=None, **kwargs, ): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if "alias" not in kwargs: msg = ( "Directly creating EmailBackend instances is deprecated. " "Use mail.mailers instead." ) - warn_about_external_use(msg, RemovedInDjango70Warning) + warn_about_external_use(msg, RemovedInDjango2028Warning) super().__init__(**kwargs) self.fail_silently = fail_silently @@ -48,7 +48,7 @@ def __init__( self._partial_connection = None self._lock = threading.RLock() - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if self.alias is None: # Use deprecated settings when MAILERS not enabled. self.host = host or settings.EMAIL_HOST diff --git a/django/core/mail/deprecation.py b/django/core/mail/deprecation.py index 71687ba3288e..1dbfc877f364 100644 --- a/django/core/mail/deprecation.py +++ b/django/core/mail/deprecation.py @@ -1,10 +1,10 @@ -# RemovedInDjango70Warning: this entire file. +# RemovedInDjango2028Warning: this entire file. # Mailers-related deprecation warnings and helpers used in multiple places. # (In a separate file to avoid circular import problems.) import warnings from django.conf import DEPRECATED_EMAIL_SETTINGS, settings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.warnings import django_file_prefixes FAIL_SILENTLY_ARG_WARNING = ( @@ -20,7 +20,7 @@ "with a MAILERS alias." ) NO_DEFAULT_MAILER_WARNING = ( - "Django 7.0 will not have a default mailer. Configure " + "Django 2028 will not have a default mailer. Configure " "settings.MAILERS to avoid errors when sending email." ) @@ -44,13 +44,13 @@ def warn_about_default_mailers_if_needed(): if not hasattr(settings, "MAILERS"): # If a warning about migrating to MAILERS was not already # issued on startup (for a deprecated email setting), warn defining - # MAILERS will be required for sending email in Django 7.0. + # MAILERS will be required for sending email in Django 2028. if not any( hasattr(settings, name) and settings.is_overridden(name) for name in DEPRECATED_EMAIL_SETTINGS ): warnings.warn( NO_DEFAULT_MAILER_WARNING, - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) diff --git a/django/core/mail/handler.py b/django/core/mail/handler.py index e13dc5891a3b..6dc3ccc9b9ec 100644 --- a/django/core/mail/handler.py +++ b/django/core/mail/handler.py @@ -30,19 +30,19 @@ def default(self): @property def settings(self): - # RemovedInDjango70Warning: change to: + # RemovedInDjango2028Warning: change to: # return settings.MAILERS return getattr(settings, "MAILERS", {}) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @property def _is_configured(self): """True if settings.py has opted into MAILERS support.""" return hasattr(settings, "MAILERS") - # RemovedInDjango70Warning: _deprecated_kwargs. + # RemovedInDjango2028Warning: _deprecated_kwargs. def create_connection(self, alias, /, *, _deprecated_kwargs=None): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if not self._is_configured and alias == DEFAULT_MAILER_ALIAS: # Create mailers.default from deprecated settings. from django.core.mail import get_connection @@ -59,7 +59,7 @@ def create_connection(self, alias, /, *, _deprecated_kwargs=None): if "alias" in options: raise InvalidMailer("OPTIONS must not define 'alias'.", alias=alias) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if _deprecated_kwargs: # Being called from get_connection() to create default mailer # instance with some overrides. _ignore_unknown_kwargs prevents diff --git a/django/core/mail/message.py b/django/core/mail/message.py index 2b396d870b43..105ce2af6ce1 100644 --- a/django/core/mail/message.py +++ b/django/core/mail/message.py @@ -20,7 +20,7 @@ from django.conf import settings from django.core.mail.utils import DNS_NAME from django.utils.deprecation import ( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, deprecate_posargs, warn_about_external_use, ) @@ -33,7 +33,7 @@ report_using_incompatibility, ) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from # some spam filters. utf8_charset = Charset.Charset("utf-8") @@ -45,17 +45,17 @@ # and cannot be guessed). DEFAULT_ATTACHMENT_MIME_TYPE = "application/octet-stream" -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. RFC5322_EMAIL_LINE_LENGTH_LIMIT = 998 -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # BadHeaderError must be ValueError (not subclass it), so that existing code # with `except BadHeaderError` will catch the ValueError that Python's modern # email API raises for headers containing CR or NL. BadHeaderError = ValueError -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. # Header names that contain structured address data (RFC 5322). ADDRESS_HEADERS = { "from", @@ -72,14 +72,14 @@ } -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. def forbid_multi_line_headers(name, val, encoding): """Forbid multi-line headers to prevent header injection.""" warnings.warn( "The internal API forbid_multi_line_headers() is deprecated." " Python's modern email API (with email.message.EmailMessage or" " email.policy.default) will reject multi-line headers.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, ) encoding = encoding or settings.DEFAULT_CHARSET @@ -103,7 +103,7 @@ def forbid_multi_line_headers(name, val, encoding): return name, val -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. def sanitize_address(addr, encoding): """ Format a pair of (name, address) or an email address string. @@ -114,7 +114,7 @@ def sanitize_address(addr, encoding): " email.policy.default) will handle most required validation and" " encoding. Use Python's email.headerregistry.Address to construct" " formatted addresses from component parts.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, ) address = None @@ -159,7 +159,7 @@ def sanitize_address(addr, encoding): return formataddr((nm, parsed_address.addr_spec)) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class MIMEMixin: def as_string(self, unixfrom=False, linesep="\n"): """Return the entire formatted message as a string. @@ -188,7 +188,7 @@ def as_bytes(self, unixfrom=False, linesep="\n"): return fp.getvalue() -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class SafeMIMEMessage(MIMEMixin, MIMEMessage): def __setitem__(self, name, val): # Per RFC 2046 Section 5.2.1, message/rfc822 attachment headers must be @@ -197,7 +197,7 @@ def __setitem__(self, name, val): MIMEMessage.__setitem__(self, name, val) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class SafeMIMEText(MIMEMixin, MIMEText): def __init__(self, _text, _subtype="plain", _charset=None): self.encoding = _charset @@ -220,7 +220,7 @@ def set_payload(self, payload, charset=None): MIMEText.set_payload(self, payload, charset=charset) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class SafeMIMEMultipart(MIMEMixin, MIMEMultipart): def __init__( self, _subtype="mixed", boundary=None, _subparts=None, encoding=None, **_params @@ -247,7 +247,7 @@ class EmailMessage: encoding = None @deprecate_posargs( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, [ "bcc", "connection", @@ -308,23 +308,23 @@ def __init__( if isinstance(attachment, email.message.MIMEPart): self.attach(attachment) elif isinstance(attachment, MIMEBase): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. self.attach(attachment) else: self.attach(*attachment) self.extra_headers = headers or {} - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if connection is not None: warn_about_external_use( - CONNECTION_ARG_WARNING, RemovedInDjango70Warning, skip_frames=1 + CONNECTION_ARG_WARNING, RemovedInDjango2028Warning, skip_frames=1 ) self._connection = connection - # RemovedInDjango70Warning: connection property. + # RemovedInDjango2028Warning: connection property. @property def connection(self): msg = "The EmailMessage.connection attribute is deprecated." - warn_about_external_use(msg, RemovedInDjango70Warning) + warn_about_external_use(msg, RemovedInDjango2028Warning) return self._connection @connection.setter @@ -333,7 +333,7 @@ def connection(self, value): "The EmailMessage.connection attribute is deprecated. Switch to " "EmailMessage.send(using=...) with a MAILERS alias." ) - warn_about_external_use(msg, RemovedInDjango70Warning) + warn_about_external_use(msg, RemovedInDjango2028Warning) self._connection = value def message(self, *, policy=email.policy.default): @@ -386,7 +386,8 @@ def send(self, fail_silently=False, *, using=None): # send to. return 0 - # RemovedInDjango70Warning: replace the remainder of this method with: + # RemovedInDjango2028Warning: replace the remainder of this method + # with: # from django.core.mail import mailers # mailer = mailers.default if using is None else mailers[using] # return mailer.send_messages([self]) @@ -394,7 +395,9 @@ def send(self, fail_silently=False, *, using=None): from django.core import mail if fail_silently: - warn_about_external_use(FAIL_SILENTLY_ARG_WARNING, RemovedInDjango70Warning) + warn_about_external_use( + FAIL_SILENTLY_ARG_WARNING, RemovedInDjango2028Warning + ) if hasattr(self, "get_connection"): raise AttributeError( "EmailMessage no longer supports the undocumented " @@ -439,7 +442,7 @@ def attach(self, filename=None, content=None, mimetype=None): warnings.warn( "MIMEBase attachments are deprecated." " Use an email.message.MIMEPart instead.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, ) if content is not None or mimetype is not None: raise ValueError( @@ -495,7 +498,7 @@ def _add_bodies(self, msg): def _add_attachments(self, msg): if self.attachments: if hasattr(self, "mixed_subtype"): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. raise AttributeError( "EmailMessage no longer supports the" " undocumented `mixed_subtype` attribute" @@ -505,7 +508,7 @@ def _add_attachments(self, msg): if isinstance(attachment, email.message.MIMEPart): msg.attach(attachment) elif isinstance(attachment, MIMEBase): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. msg.attach(attachment) else: self._add_attachment(msg, *attachment) @@ -605,7 +608,7 @@ class EmailMultiAlternatives(EmailMessage): """ @deprecate_posargs( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, [ "bcc", "connection", @@ -662,7 +665,7 @@ def _add_bodies(self, msg): super()._add_bodies(msg) if self.alternatives: if hasattr(self, "alternative_subtype"): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. raise AttributeError( "EmailMultiAlternatives no longer supports the" " undocumented `alternative_subtype` attribute" diff --git a/django/core/paginator.py b/django/core/paginator.py index 17a30a00f6ff..bb5f1987c9f1 100644 --- a/django/core/paginator.py +++ b/django/core/paginator.py @@ -5,7 +5,7 @@ from asgiref.sync import sync_to_async -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.functional import cached_property from django.utils.inspect import method_has_no_args from django.utils.translation import gettext_lazy as _ @@ -56,7 +56,7 @@ def __init__( else self.default_error_messages | error_messages ) if self.per_page <= self.orphans: - # RemovedInDjango70Warning: When the deprecation ends, replace + # RemovedInDjango2028Warning: When the deprecation ends, replace # with: # raise ValueError( # "The orphans argument cannot be larger than or equal to the " @@ -65,9 +65,9 @@ def __init__( msg = ( "Support for the orphans argument being larger than or equal to the " "per_page argument is deprecated. This will raise a ValueError in " - "Django 7.0." + "Django 2028." ) - warnings.warn(msg, category=RemovedInDjango70Warning, stacklevel=2) + warnings.warn(msg, category=RemovedInDjango2028Warning, stacklevel=2) def _check_object_list_is_ordered(self): """ diff --git a/django/core/signing.py b/django/core/signing.py index 174b7c34b8a7..6e284f4c841a 100644 --- a/django/core/signing.py +++ b/django/core/signing.py @@ -43,7 +43,7 @@ from django.conf import settings from django.utils.crypto import constant_time_compare, salted_hmac -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.encoding import force_bytes from django.utils.module_loading import import_string from django.utils.regex_helper import _lazy_re_compile @@ -99,14 +99,14 @@ def b64_decode(s): return base64.urlsafe_b64decode(s + pad) -# RemovedInDjango70Warning: algorithm="sha256" +# RemovedInDjango2028Warning: algorithm="sha256" def base64_hmac(salt, value, key, algorithm=None): if algorithm is None: warnings.warn( "The default argument for algorithm in base64_hmac() will change " - "from 'sha1' to 'sha256' in Django 7.0. Pass an explicit " + "from 'sha1' to 'sha256' in Django 2028. Pass an explicit " "algorithm to silence this warning.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) algorithm = "sha1" @@ -125,14 +125,14 @@ def _cookie_signer_salt(cookie_name, salt=""): return f"django.http.cookies.v2:{len(salt)}:{salt}{cookie_name}" -# RemovedInDjango70Warning: When the deprecation ends, remove. +# RemovedInDjango2028Warning: When the deprecation ends, remove. def _cookie_signer_legacy_salt(cookie_name, salt=""): return cookie_name + salt def _unsign_cookie(signed_value, *, cookie_name, salt="", max_age=None): try: - # RemovedInDjango70Warning: When the deprecation ends, replace the + # RemovedInDjango2028Warning: When the deprecation ends, replace the # whole function body with this single return statement. return get_cookie_signer(salt=_cookie_signer_salt(cookie_name, salt)).unsign( signed_value, max_age=max_age diff --git a/django/db/backends/base/creation.py b/django/db/backends/base/creation.py index 859fb07ff537..8aa4889f44ac 100644 --- a/django/db/backends/base/creation.py +++ b/django/db/backends/base/creation.py @@ -8,7 +8,7 @@ from django.core import serializers from django.db import router from django.db.transaction import atomic -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.module_loading import import_string # The prefix to put on the default database name when creating @@ -40,7 +40,7 @@ def _nodb_cursor(self): def log(self, msg): sys.stderr.write(msg + os.linesep) - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # def create_test_db(self, verbosity=1, autoclobber=False, keepdb=False): def create_test_db( self, verbosity=1, autoclobber=False, serialize=None, keepdb=False @@ -110,7 +110,7 @@ def create_test_db( "DatabaseCreation.serialize_test_db() once all test databases are set " "up instead if you need fixtures persistence between tests.", stacklevel=2, - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, ) if serialize: self.connection._test_serialized_contents = ( diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 0a12d3631cc1..0ad614a70036 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -32,7 +32,7 @@ parse_duration, parse_time, ) -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.duration import duration_string from django.utils.functional import Promise, cached_property from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH, clean_ipv6_address @@ -42,7 +42,7 @@ __all__ = [ "AutoField", - # RemovedInDjango70Warning + # RemovedInDjango2028Warning "BLANK_CHOICE_DASH", "BLANK_CHOICE_LABEL", "BigAutoField", @@ -86,7 +86,7 @@ class NOT_PROVIDED: pass -# RemovedInDjango70Warning: From Django 6.1, the values to use for "blank" +# RemovedInDjango2028Warning: From Django 6.1, the values to use for "blank" # in SelectFields will be defined by the below BLANK_CHOICE_LABEL constant. # Will be appended to the start of most "choices" lists. # BLANK_CHOICE_DASH is still available as a constant in Django 6.1. @@ -192,7 +192,7 @@ def _description(self): description = property(_description) def __init_subclass__(cls, **kwargs): - # RemovedInDjango70Warning: When the deprecation ends, remove + # RemovedInDjango2028Warning: When the deprecation ends, remove # completely. # Allow for both `get_placeholder` and `get_placeholder_sql` to # be declared to ease the deprecation process for third-party apps. @@ -203,7 +203,7 @@ def __init_subclass__(cls, **kwargs): "Field.get_placeholder is deprecated in favor of get_placeholder_sql. " f"Define {cls.__module__}.{cls.__qualname__}.get_placeholder_sql " "to return both SQL and parameters instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py index 2d5f51d4f320..509a905509ea 100644 --- a/django/db/models/fields/json.py +++ b/django/db/models/fields/json.py @@ -12,7 +12,7 @@ PostgresOperatorLookup, Transform, ) -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.translation import gettext_lazy as _ from django.utils.warnings import django_file_prefixes @@ -314,7 +314,7 @@ def process_rhs(self, compiler, connection): class JSONExact(lookups.Exact): - # RemovedInDjango70Warning: When the deprecation period is over, remove + # RemovedInDjango2028Warning: When the deprecation period is over, remove # the following line. can_use_none_as_rhs = True @@ -324,13 +324,13 @@ def process_rhs(self, compiler, connection): "Using None as the right-hand side of an exact lookup on JSONField to " "mean JSON scalar 'null' is deprecated. Use JSONNull() instead (or use " "the __isnull lookup if you meant SQL NULL).", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) rhs, rhs_params = super().process_rhs(compiler, connection) - # RemovedInDjango70Warning: When the deprecation period is over, remove + # RemovedInDjango2028Warning: When the deprecation ends, remove # The following if-block entirely. # Treat None lookup values as null. if rhs == "%s" and (*rhs_params,) == (None,): @@ -599,7 +599,7 @@ class KeyTransformIn(JSONIn): class KeyTransformExact(JSONExact): - # RemovedInDjango70Warning: When deprecation period ends, uncomment the + # RemovedInDjango2028Warning: When deprecation period ends, uncomment the # flag below. # can_use_none_as_rhs = True diff --git a/django/db/models/query.py b/django/db/models/query.py index ae000c3e8c65..2d3f520e27b8 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -47,8 +47,8 @@ ) from django.utils import timezone from django.utils.deprecation import ( - RemovedInDjango70Warning, RemovedInDjango71Warning, + RemovedInDjango2028Warning, warn_about_external_use, ) from django.utils.functional import cached_property @@ -64,7 +64,7 @@ DEFAULT_FETCH_MODE = FETCH_ONE -# RemovedInDjango70Warning: When the deprecation ends, remove this function +# RemovedInDjango2028Warning: When the deprecation ends, remove this function # and restore direct model_cls.from_db(..., fetch_mode=fetch_mode) calls at # its call sites. def _get_from_db(model_cls, fetch_mode): @@ -86,7 +86,7 @@ def _get_from_db(model_cls, fetch_mode): f"{model_cls.__qualname__}.from_db() must accept a fetch_mode keyword " "argument. Support for from_db() methods that do not accept it is " "deprecated.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) return from_db @@ -152,7 +152,7 @@ def __iter__(self): init_list = [ f[0].target.attname for f in select[model_fields_start:model_fields_end] ] - # RemovedInDjango70Warning: When the deprecation ends, remove this + # RemovedInDjango2028Warning: When the deprecation ends, remove this # assignment and call model_cls.from_db(..., fetch_mode=fetch_mode) # directly in the loop below. from_db = _get_from_db(model_cls, fetch_mode) @@ -245,7 +245,7 @@ def __iter__(self): query_iterator, cols ) fetch_mode = self.queryset._fetch_mode - # RemovedInDjango70Warning: When the deprecation ends, remove + # RemovedInDjango2028Warning: When the deprecation ends, remove # this assignment and call # model_cls.from_db(..., fetch_mode=fetch_mode) directly in the # loop below. @@ -1574,10 +1574,10 @@ def raw(self, raw_query, params=(), translations=None, using=None): def _values(self, *fields, **expressions): clone = self._chain() if expressions: - # RemovedInDjango70Warning: When the deprecation ends, deindent as: + # RemovedInDjango2028Warning: When the deprecation ends, deindent: # clone = clone.annotate(**expressions) with warnings.catch_warnings( - action="ignore", category=RemovedInDjango70Warning + action="ignore", category=RemovedInDjango2028Warning ): clone = clone.annotate(**expressions) clone._fields = fields @@ -1600,8 +1600,8 @@ def values_list(self, *fields, flat=False, named=False): "field." ) elif not fields: - # RemovedInDjango70Warning: When the deprecation ends, replace - # with: + # RemovedInDjango2028Warning: When the deprecation ends, + # replace with: # raise TypeError( # "'flat' is not valid when values_list is called with no " # "fields." @@ -1610,7 +1610,7 @@ def values_list(self, *fields, flat=False, named=False): "Calling values_list() with no field name and flat=True " "is deprecated. Pass an explicit field name instead, like " "'pk'.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, ) fields = [self.model._meta.concrete_fields[0].attname] @@ -1850,12 +1850,12 @@ def select_related(self, *fields): elif fields: obj.query.add_select_related(fields) else: - # RemovedInDjango70Warning: when the deprecation ends, raise a + # RemovedInDjango2028Warning: when the deprecation ends, raise a # TypeError instead. warn_about_external_use( "Calling select_related() with no arguments is deprecated. " "Specify the fields to fetch instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, skip_name_prefixes=("django.db.models",), ) obj.query.select_related = True @@ -3088,7 +3088,7 @@ def __init__(self, klass_info, select, db, fetch_mode): ) self.model_cls = klass_info["model"] - # RemovedInDjango70Warning: When the deprecation ends, remove this + # RemovedInDjango2028Warning: When the deprecation ends, remove this # assignment and call # self.model_cls.from_db(..., fetch_mode=fetch_mode) directly in # populate(). diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 1a22393cf91b..8109181855f4 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -24,7 +24,7 @@ ) from django.db.models.sql.query import Query, get_order_dir from django.db.transaction import TransactionManagementError -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.functional import cached_property from django.utils.hashable import make_hashable from django.utils.regex_helper import _lazy_re_compile @@ -578,14 +578,14 @@ def quote_name(self, name): self.quote_cache[name] = quoted return quoted - # RemovedInDjango70Warning: When the deprecation ends, remove. + # RemovedInDjango2028Warning: When the deprecation ends, remove. def quote_name_unless_alias(self, name): warnings.warn( ( "SQLCompiler.quote_name_unless_alias() is deprecated. " "Use .quote_name() instead." ), - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) return self.quote_name(name) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 204a8e3a52f9..d0acb43965b8 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -43,7 +43,7 @@ from django.db.models.sql.constants import INNER, LOUTER, ORDER_DIR, SINGLE from django.db.models.sql.datastructures import BaseTable, Empty, Join, MultiJoin from django.db.models.sql.where import AND, OR, ExtraWhere, NothingNode, WhereNode -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.functional import cached_property from django.utils.regex_helper import _lazy_re_compile from django.utils.tree import Node @@ -51,7 +51,7 @@ __all__ = ["Query", "RawQuery"] -# RemovedInDjango70Warning: When the deprecation ends, replace with: +# RemovedInDjango2028Warning: When the deprecation ends, replace with: # Quotation marks ('"`[]), whitespace characters, control characters, # semicolons, percent signs, hashes, or inline SQL comments are # forbidden in column aliases. @@ -1220,18 +1220,18 @@ def join_parent_model(self, opts, model, alias, seen): return alias or seen[None] def check_alias(self, alias): - # RemovedInDjango70Warning: When the deprecation ends, remove. + # RemovedInDjango2028Warning: When the deprecation ends, remove. if "%" in alias: warnings.warn( "Using percent signs in a column alias is deprecated.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) if FORBIDDEN_ALIAS_PATTERN.search(alias): raise ValueError( "Column aliases cannot contain whitespace characters, hashes, " - # RemovedInDjango70Warning: When the deprecation ends, replace - # with: + # RemovedInDjango2028Warning: When the deprecation ends, + # replace with: # "control characters, quotation marks, semicolons, percent " # "signs, or SQL comments." "control characters, quotation marks, semicolons, or SQL comments." diff --git a/django/db/models/utils.py b/django/db/models/utils.py index 7f38bd7afb41..b2e7c21841d8 100644 --- a/django/db/models/utils.py +++ b/django/db/models/utils.py @@ -69,8 +69,8 @@ def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) -# RemovedInDjango70Warning: At the end of the deprecation, remove this function -# and use .fields.BLANK_CHOICE_LABEL directly instead. +# RemovedInDjango2028Warning: At the end of the deprecation, remove this +# function and use .fields.BLANK_CHOICE_LABEL directly instead. def get_blank_choice_label(): from django.conf import settings diff --git a/django/db/transaction.py b/django/db/transaction.py index 94f381779c52..06189f7117ce 100644 --- a/django/db/transaction.py +++ b/django/db/transaction.py @@ -9,7 +9,7 @@ ProgrammingError, connections, ) -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.warnings import django_file_prefixes @@ -52,7 +52,7 @@ def rollback(using=None): def savepoint(using=None): warnings.warn( "savepoint() is deprecated. Use savepoint_create() instead.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) return savepoint_create(using=using) diff --git a/django/middleware/common.py b/django/middleware/common.py index 2046675e87f0..de6c94c1485d 100644 --- a/django/middleware/common.py +++ b/django/middleware/common.py @@ -147,7 +147,7 @@ def process_response(self, request, response): return response def send_mail(self, subject, message, *args, **kwargs): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if not mailers._is_configured: mail_managers(subject, message, *args, fail_silently=True, **kwargs) return diff --git a/django/template/base.py b/django/template/base.py index 2f4d447590bd..f475bb900c32 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -57,7 +57,7 @@ from enum import Enum from django.template.context import BaseContext -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.formats import localize from django.utils.html import conditional_escape from django.utils.inspect import getfullargspec, signature @@ -562,11 +562,11 @@ def parse(self, parse_until=None): "lookup of the empty string is deprecated.\n" f" Template: {self.origin.name}\n" f" Line: {token.lineno}", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) - # RemovedInDjango70Warning + # RemovedInDjango2028Warning # When deprecation ends elevate the warning to an error. # raise self.error( # token, diff --git a/django/test/utils.py b/django/test/utils.py index e69f3494825e..19088532ad8e 100644 --- a/django/test/utils.py +++ b/django/test/utils.py @@ -142,7 +142,7 @@ def setup_test_environment(debug=None): saved_data.debug = settings.DEBUG settings.DEBUG = debug - # RemovedInDjango70Warning: Override MAILERS unconditionally; + # RemovedInDjango2028Warning: Override MAILERS unconditionally; # remove EMAIL_BACKEND override. if hasattr(settings, "MAILERS"): saved_data.mailers = settings.MAILERS @@ -173,7 +173,7 @@ def teardown_test_environment(): settings.ALLOWED_HOSTS = saved_data.allowed_hosts settings.DEBUG = saved_data.debug - # RemovedInDjango70Warning: Restore MAILERS unconditionally; + # RemovedInDjango2028Warning: Restore MAILERS unconditionally; # remove EMAIL_BACKEND support. if hasattr(saved_data, "mailers"): settings.MAILERS = saved_data.mailers diff --git a/django/utils/crypto.py b/django/utils/crypto.py index 519eedc1152c..5c22b0038ac9 100644 --- a/django/utils/crypto.py +++ b/django/utils/crypto.py @@ -8,7 +8,7 @@ import warnings from django.conf import settings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.encoding import force_bytes from django.utils.warnings import django_file_prefixes @@ -19,24 +19,24 @@ class InvalidAlgorithm(ValueError): pass -# RemovedInDjango70Warning: algorithm="sha256" +# RemovedInDjango2028Warning: algorithm="sha256" def salted_hmac(key_salt, value, secret=None, *, algorithm=None): """ Return the HMAC of 'value', using a key generated from key_salt and a secret (which defaults to settings.SECRET_KEY). Default algorithm is SHA1, but any algorithm name supported by hashlib can be passed. - Removed in Django70Warning: The default algorithm will change to SHA256 - in Django 7.0, so provide an explicit algorithm to silence the warning. + RemovedInDjango2028Warning: The default algorithm will change to SHA256 + in Django 2028, so provide an explicit algorithm to silence the warning. A different key_salt should be passed in for every application of HMAC. """ if algorithm is None: warnings.warn( "The default argument for algorithm in salted_hmac() will change " - "from 'sha1' to 'sha256' in Django 7.0. Pass an explicit " + "from 'sha1' to 'sha256' in Django 2028. Pass an explicit " "algorithm to silence this warning.", - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) algorithm = "sha1" diff --git a/django/utils/deprecation.py b/django/utils/deprecation.py index 951967e99f8d..48e2a9cb8f46 100644 --- a/django/utils/deprecation.py +++ b/django/utils/deprecation.py @@ -10,7 +10,7 @@ from django.utils.warnings import django_file_prefixes -class RemovedInDjango70Warning(DeprecationWarning): +class RemovedInDjango2028Warning(DeprecationWarning): pass @@ -18,7 +18,7 @@ class RemovedInDjango71Warning(PendingDeprecationWarning): pass -RemovedInNextVersionWarning = RemovedInDjango70Warning +RemovedInNextVersionWarning = RemovedInDjango2028Warning RemovedAfterNextVersionWarning = RemovedInDjango71Warning @@ -31,6 +31,13 @@ def __getattr__(name): stacklevel=2, ) return _MiddlewareMixin + if name == "RemovedInDjango70Warning": + warnings.warn( + "RemovedInDjango2028Warning should be used instead of " + "RemovedInDjango70Warning.", + stacklevel=2, + ) + return RemovedInDjango2028Warning raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/django/utils/html.py b/django/utils/html.py index 63db147ff147..bb92cda2a5c9 100644 --- a/django/utils/html.py +++ b/django/utils/html.py @@ -13,7 +13,7 @@ from django.conf import settings from django.core.exceptions import SuspiciousOperation, ValidationError from django.core.validators import DomainNameValidator, EmailValidator -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.functional import Promise, cached_property, keep_lazy, keep_lazy_text from django.utils.http import MAX_URL_LENGTH, RFC3986_GENDELIMS, RFC3986_SUBDELIMS from django.utils.regex_helper import _lazy_re_compile @@ -360,8 +360,8 @@ def handle_word( url = smart_urlquote(html.unescape(middle)) elif len(middle) <= MAX_URL_LENGTH and self.simple_url_2_re.match(middle): unescaped_middle = html.unescape(middle) - # RemovedInDjango70Warning: When the deprecation ends, replace - # with: + # RemovedInDjango2028Warning: When the deprecation ends, + # replace with: # url = smart_urlquote(f"https://{unescaped_middle}") protocol = ( "https" @@ -371,10 +371,10 @@ def handle_word( if not settings.URLIZE_ASSUME_HTTPS: warnings.warn( "The default protocol will be changed from HTTP to " - "HTTPS in Django 7.0. Set the URLIZE_ASSUME_HTTPS " + "HTTPS in Django 2028. Set the URLIZE_ASSUME_HTTPS " "transitional setting to True to opt into using HTTPS as the " "new default protocol.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, stacklevel=2, ) url = smart_urlquote(f"{protocol}://{unescaped_middle}") diff --git a/django/utils/log.py b/django/utils/log.py index d37a9f530f8d..05a93762f843 100644 --- a/django/utils/log.py +++ b/django/utils/log.py @@ -7,7 +7,7 @@ from django.core import mail from django.core.exceptions import ImproperlyConfigured from django.core.management.color import color_style -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.module_loading import import_string from django.utils.warnings import django_file_prefixes @@ -91,7 +91,7 @@ def __init__( ): super().__init__() - # RemovedInDjango70Warning: email_backend arg and connection error. + # RemovedInDjango2028Warning: email_backend arg and connection error. if email_backend: if using: raise ImproperlyConfigured( @@ -104,7 +104,7 @@ def __init__( ) warnings.warn( "The 'email_backend' argument is deprecated. Use 'using' instead.", - RemovedInDjango70Warning, + RemovedInDjango2028Warning, skip_file_prefixes=django_file_prefixes(), ) if hasattr(self, "connection"): @@ -164,7 +164,7 @@ def emit(self, record): self.send_mail(subject, message, html_message=html_message) def send_mail(self, subject, message, *args, **kwargs): - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if not mail.mailers._is_configured: connection = mail.get_connection( backend=self.email_backend, fail_silently=True diff --git a/docs/howto/mailers-migration.txt b/docs/howto/mailers-migration.txt index c99d0de5cce2..30788f1592a8 100644 --- a/docs/howto/mailers-migration.txt +++ b/docs/howto/mailers-migration.txt @@ -1,4 +1,4 @@ -.. RemovedInDjango70Warning: Remove this file and references to it. +.. RemovedInDjango2028Warning: Remove this file and references to it. .. _migrating-to-mailers: @@ -50,7 +50,7 @@ use these specific features: .. deprecated:: 6.1 - The following settings and functions will be removed in Django 7.0: + The following settings and functions will be removed in Django 2028: * :setting:`EMAIL_BACKEND`, :setting:`EMAIL_FILE_PATH`, :setting:`EMAIL_HOST`, :setting:`EMAIL_HOST_PASSWORD`, diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index e7d68380926e..fc63c0dc35da 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -23,10 +23,10 @@ details on these changes. * Calling ``QuerySet.aiterator()`` after ``prefetch_related()`` without providing a ``chunk_size`` will raise :exc:`ValueError`. -.. _deprecation-removed-in-7.0: +.. _deprecation-removed-in-2028: -7.0 ---- +2028 +---- See the :ref:`Django 6.0 release notes ` for more details on these changes. diff --git a/docs/intro/tutorial02.txt b/docs/intro/tutorial02.txt index b93f5d8a38bf..f6929266b7bc 100644 --- a/docs/intro/tutorial02.txt +++ b/docs/intro/tutorial02.txt @@ -444,7 +444,7 @@ three-chevron prompt (>>>) indicates you are still in the shell, you need to exit first using ``exit()``). Run ``python manage.py shell`` again to reload the models. -.. RemovedInDjango70Warning: When Python 3.12 is no longer supported, +.. RemovedInDjango2028Warning: When Python 3.12 is no longer supported, ``exit()`` can be replaced with ``exit``. .. code-block:: pycon diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index 3b31d503cc79..8e4fabc4d0b5 100644 --- a/docs/ref/models/instances.txt +++ b/docs/ref/models/instances.txt @@ -153,7 +153,7 @@ is done. In this case it would be possible to use a ``super()`` call in the .. deprecated:: 6.1 Support for ``from_db()`` methods that do not accept the ``fetch_mode`` - keyword argument is deprecated and will be removed in Django 7.0. + keyword argument is deprecated and will be removed in Django 2028. .. _refreshing-objects: diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index e2d6e12319c8..44cb9ff497e5 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -1157,7 +1157,7 @@ underlying query more complex, and return more data, than is actually needed. .. deprecated:: 6.1 Calling ``select_related()`` with no arguments is deprecated, and support - for it will be removed in Django 7.0. Specify the fields to fetch instead. + for it will be removed in Django 2028. Specify the fields to fetch instead. ``prefetch_related()`` ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 587937cd6199..304bb75ca320 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1404,7 +1404,7 @@ The backend to use for sending emails. For the list of available backends see .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is :setting:`BACKEND ` in the :setting:`MAILERS` ``"default"`` configuration. See :ref:`migrating-to-mailers`. @@ -1421,7 +1421,7 @@ to store output files. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"file_path"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the file email backend. See :ref:`migrating-to-mailers`. @@ -1439,7 +1439,7 @@ See also :setting:`EMAIL_PORT`. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"host"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1460,7 +1460,7 @@ See also :setting:`EMAIL_HOST_USER`. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"password"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1479,7 +1479,7 @@ See also :setting:`EMAIL_HOST_PASSWORD`. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"username"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1495,7 +1495,7 @@ Port to use for the SMTP server defined in :setting:`EMAIL_HOST`. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"port"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1535,7 +1535,7 @@ experiencing hanging connections, see the implicit TLS setting .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"use_tls"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1557,7 +1557,7 @@ exclusive, so only set one of those settings to ``True``. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"use_ssl"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1590,7 +1590,7 @@ For more complex scenarios, the :ref:`SMTP EmailBackend .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"ssl_certfile"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1614,7 +1614,7 @@ for details on how the certificate chain file and private key file are handled. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"ssl_keyfile"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -1631,7 +1631,7 @@ attempt. .. deprecated:: 6.1 - This setting is deprecated and will be removed in Django 7.0. Its + This setting is deprecated and will be removed in Django 2028. Its replacement is ``"timeout"`` under :setting:`OPTIONS ` in a :setting:`MAILERS` definition that uses the SMTP email backend. See :ref:`migrating-to-mailers`. @@ -2170,7 +2170,7 @@ configuration process will be skipped. .. versionadded:: 6.1 -.. RemovedInDjango70Warning: Update the default value to be ``{}``. +.. RemovedInDjango2028Warning: Update the default value to be ``{}``. Default: Not defined @@ -2209,10 +2209,10 @@ See :ref:`topic-email-configuration` for more information. .. deprecated:: 6.1 - In Django 7.0, the default value will change from "Not defined" to ``{}``. + In Django 2028, the default value will change from "Not defined" to ``{}``. Until then, if ``MAILERS`` is not defined in the project's settings, Django will create a ``"default"`` mailer using the :setting:`EMAIL_BACKEND` - setting. Projects can opt into the Django 7.0 behavior at any time by + setting. Projects can opt into the Django 2028 behavior at any time by adding ``MAILERS`` and removing ``EMAIL_BACKEND`` from their settings. See :ref:`migrating-to-mailers-settings`. @@ -2866,8 +2866,8 @@ cookies signed with Django's current unambiguous signed-cookie salt derivation. .. deprecated:: 6.1 - This transitional setting will be removed in Django 7.0, when legacy signed - cookies will no longer be accepted. + This transitional setting will be removed in Django 2028, when legacy + signed cookies will no longer be accepted. .. setting:: SIGNING_BACKEND @@ -3238,7 +3238,7 @@ transitional setting to ``True`` to revert to the previous label. .. deprecated:: 6.1 - This setting will be removed in Django 7.0. To use a custom default blank + This setting will be removed in Django 2028. To use a custom default blank choice label, override ``django.db.models.fields.BLANK_CHOICE_LABEL`` in the app's ``ready()`` method. diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index a530d4e1d079..703ea814d300 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -3029,7 +3029,7 @@ If ``value`` is ``"Check out www.djangoproject.com"``, the output will be: .. deprecated:: 6.0 The default protocol when none is provided will change from HTTP to HTTPS - in Django 7.0. Hence, the output will become: + in Django 2028. Hence, the output will become: .. code-block:: html+django @@ -3080,7 +3080,7 @@ If ``value`` is ``"Check out www.djangoproject.com"``, the output would be: .. deprecated:: 6.0 The default protocol when none is provided will change from HTTP to HTTPS - in Django 7.0. Hence, the output will become: + in Django 2028. Hence, the output will become: .. code-block:: html+django diff --git a/docs/releases/5.2.15.txt b/docs/releases/5.2.15.txt index aed69baaafe0..6c54b26b7aba 100644 --- a/docs/releases/5.2.15.txt +++ b/docs/releases/5.2.15.txt @@ -16,7 +16,7 @@ in a context different from the one where they were signed. Cookies are now signed with an unambiguous salt derivation. For backwards compatibility, cookies signed by older Django versions are accepted until -Django 7.0. Projects affected by the above ambiguity should set +Django 2028. Projects affected by the above ambiguity should set :setting:`SIGNED_COOKIE_LEGACY_SALT_FALLBACK` to ``False`` to reject older cookies immediately. diff --git a/docs/releases/6.0.6.txt b/docs/releases/6.0.6.txt index e8d1e1629a53..bcaa9ada1416 100644 --- a/docs/releases/6.0.6.txt +++ b/docs/releases/6.0.6.txt @@ -17,7 +17,7 @@ in a context different from the one where they were signed. Cookies are now signed with an unambiguous salt derivation. For backwards compatibility, cookies signed by older Django versions are accepted until -Django 7.0. Projects affected by the above ambiguity should set +Django 2028. Projects affected by the above ambiguity should set :setting:`SIGNED_COOKIE_LEGACY_SALT_FALLBACK` to ``False`` to reject older cookies immediately. diff --git a/docs/releases/6.0.txt b/docs/releases/6.0.txt index 1697a095c9bf..255a6163461c 100644 --- a/docs/releases/6.0.txt +++ b/docs/releases/6.0.txt @@ -531,7 +531,7 @@ Miscellaneous :class:`~django.db.models.Aggregate` class. * The default protocol in :tfilter:`urlize` and :tfilter:`urlizetrunc` will - change from HTTP to HTTPS in Django 7.0. Set the transitional setting + change from HTTP to HTTPS in Django 2028. Set the transitional setting :setting:`URLIZE_ASSUME_HTTPS` to ``True`` to opt into assuming HTTPS during the Django 6.x release cycle. diff --git a/docs/releases/6.1.txt b/docs/releases/6.1.txt index d91ead22d9f8..78d4e320011b 100644 --- a/docs/releases/6.1.txt +++ b/docs/releases/6.1.txt @@ -118,7 +118,7 @@ replace :setting:`EMAIL_BACKEND` and related ``EMAIL_*`` settings in Django deprecation warnings: see the list of :ref:`email deprecations ` below. -You can opt into the new feature at any time before Django 7.0; see +You can opt into the new feature at any time before Django 2028; see :ref:`migrating-to-mailers`. To ease the transition, :data:`mail.mailers["default"] ` works with either :setting:`MAILERS` or the deprecated :setting:`EMAIL_BACKEND` setting @@ -644,7 +644,7 @@ Email unknown keyword arguments. Custom email backend subclasses should ensure they have consumed all supported ``**kwargs`` before forwarding the remainder to superclass init. The base class now issues a deprecation warning for unknown - arguments, and it will treat them as errors starting in Django 7.0. See + arguments, and it will treat them as errors starting in Django 2028. See :ref:`migrating-to-mailers-email-backends`. * Support for ``fail_silently`` in the ``BaseEmailBackend`` is deprecated. @@ -717,7 +717,7 @@ Miscellaneous * The default value of the ``algorithm`` argument for ``django.utils.crypto.salted_hmac()`` and ``django.core.signing.base64_hmac()`` is deprecated and will change from - ``"sha1"`` to ``"sha256"`` in Django 7.0. Pass an explicit ``algorithm`` + ``"sha1"`` to ``"sha256"`` in Django 2028. Pass an explicit ``algorithm`` to silence the deprecation warning. * Overriding ``ModelAdmin.get_actions()`` without the new ``action_location`` diff --git a/docs/releases/6.2.txt b/docs/releases/6.2.txt index 99609fce7fa5..e93d4f2602ec 100644 --- a/docs/releases/6.2.txt +++ b/docs/releases/6.2.txt @@ -31,6 +31,17 @@ only officially support the latest release of each series. What's new in Django 6.2 ======================== +Adopting calendar versioning +---------------------------- + +Following `DEP 20`_, the releases previously planned as Django 7.0 and 7.1 are +now Django 2028 and 2029. Accordingly, the deprecation warning classes are +renamed to match the calendar version in which the features they mark are +removed: ``RemovedInDjango70Warning`` becomes ``RemovedInDjango2028Warning``, +and ``RemovedInDjango71Warning`` becomes ``RemovedInDjango2029Warning``. + +.. _DEP 20: https://github.com/django/deps/blob/main/accepted/0020-annual-release-cycle.rst + Minor features -------------- diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt index 717dc388c598..7bed25a93606 100644 --- a/docs/topics/db/queries.txt +++ b/docs/topics/db/queries.txt @@ -1099,7 +1099,7 @@ while exact-matching ``JSONNull()`` is used to match JSON ``null``. >>> Dog.objects.create(name="Archie", data=JSONNull()) # JSON null. >>> Dog.objects.filter(data=None) - ...: RemovedInDjango70Warning: Using None as the right-hand side of an + ...: RemovedInDjango2028Warning: Using None as the right-hand side of an exact lookup on JSONField to mean JSON scalar 'null' is deprecated. Use JSONNull() instead (or use the __isnull lookup if you meant SQL NULL). ... @@ -1111,7 +1111,7 @@ while exact-matching ``JSONNull()`` is used to match JSON ``null``. >>> Dog.objects.filter(data__isnull=False) ]> -.. RemovedInDjango70Warning: Alter the example with the deprecation warning to: +.. RemovedInDjango2028Warning: Alter the example with the deprecation warning to: ]>. Unless you are sure you wish to work with SQL ``NULL`` values, consider setting diff --git a/docs/topics/email.txt b/docs/topics/email.txt index 6cb05f404984..f2bda1bda87c 100644 --- a/docs/topics/email.txt +++ b/docs/topics/email.txt @@ -111,11 +111,11 @@ approaches. .. deprecated:: 6.1 - Until Django 7.0, if the :setting:`MAILERS` setting is not defined then the - earlier behavior still applies: Django will default to using an SMTP server - on localhost (but will issue deprecation warnings). Starting in Django 7.0, - attempts to send email without :setting:`MAILERS` defined will result in a - ``MailerDoesNotExist`` error. + Until Django 2028, if the :setting:`MAILERS` setting is not defined then + the earlier behavior still applies: Django will default to using an SMTP + server on localhost (but will issue deprecation warnings). Starting in + Django 2028, attempts to send email without :setting:`MAILERS` defined will + result in a ``MailerDoesNotExist`` error. Existing projects can opt into the new behavior early by adding :setting:`MAILERS` to ``settings.py``. See :ref:`migrating-to-mailers`. @@ -1093,7 +1093,7 @@ Example:: respectively. (There is no setting equivalent to the ``"fail_silently"`` option.) -.. RemovedInDjango70Warning: class documentation for smtp.EmailBackend. +.. RemovedInDjango2028Warning: class documentation for smtp.EmailBackend. .. class:: backends.smtp.EmailBackend @@ -1113,7 +1113,7 @@ Example:: .. deprecated:: 6.1 Directly constructing an instance of an ``EmailBackend`` class will be - unsupported in Django 7.0. Undocumented use will result in different + unsupported in Django 2028. Undocumented use will result in different default argument handling compared to earlier releases. .. _topic-email-smtp-private-ca: @@ -1317,7 +1317,7 @@ backends. :setting:`EMAIL_BACKEND` and related settings. This supports backward compatibility with Django 6.0 and earlier. - This behavior (and those settings) will be removed in Django 7.0. + This behavior (and those settings) will be removed in Django 2028. .. function:: get_connection(backend=None, *, fail_silently=False, **kwargs) diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index 63ce3904c252..904912dd9529 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -1291,7 +1291,7 @@ class CourseAdmin(admin.ModelAdmin): ) -# RemovedInDjango70Warning: When the deprecation ends, remove. +# RemovedInDjango2028Warning: When the deprecation ends, remove. class OverriddenActionAdmin(admin.ModelAdmin): def get_actions(self, request): actions = super().get_actions(request) @@ -1383,7 +1383,7 @@ def test_action(self, request, selected): site.register(RelatedPrepopulated, search_fields=["name"]) site.register(RelatedWithUUIDPKModel) site.register(ReadOnlyRelatedField, ReadOnlyRelatedFieldAdmin) -# RemovedInDjango70Warning: When the deprecation ends, remove. +# RemovedInDjango2028Warning: When the deprecation ends, remove. site.register(ModelAction, OverriddenActionAdmin) # We intentionally register Promo and ChapterXtra1 but not Chapter nor diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py index 427317507732..bf86db864608 100644 --- a/tests/admin_views/models.py +++ b/tests/admin_views/models.py @@ -1209,6 +1209,6 @@ class CamelCaseRelatedModel(models.Model): ) -# RemovedInDjango70Warning: When the deprecation ends, remove. +# RemovedInDjango2028Warning: When the deprecation ends, remove. class ModelAction(models.Model): pass diff --git a/tests/admin_views/test_actions.py b/tests/admin_views/test_actions.py index f2fc4e3f3587..c76c7fda3e68 100644 --- a/tests/admin_views/test_actions.py +++ b/tests/admin_views/test_actions.py @@ -12,7 +12,7 @@ from django.test import TestCase, override_settings from django.test.utils import CaptureQueriesContext from django.urls import reverse -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .admin import SubscriberAdmin from .admin import __file__ as admin_filename @@ -867,7 +867,7 @@ def test_user_message_on_no_action(self): response = self.client.get(response.url) self.assertContains(response, "No action selected.") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_overridden_admin_action_methods(self): self.client.force_login(self.superuser) obj = ModelAction.objects.create() @@ -878,7 +878,7 @@ def test_overridden_admin_action_methods(self): "action_location=ActionLocation.CHANGE_LIST)." ) with self.assertWarnsMessage( - RemovedInDjango70Warning, get_actions_overridden_msg + RemovedInDjango2028Warning, get_actions_overridden_msg ) as warning: response = self.client.get(change_url) self.assertEqual(warning.filename, admin_filename) @@ -886,7 +886,7 @@ def test_overridden_admin_action_methods(self): changelist_url = reverse("admin:admin_views_modelaction_changelist") with warnings.catch_warnings(record=True) as warning_list: - warnings.simplefilter("always", RemovedInDjango70Warning) + warnings.simplefilter("always", RemovedInDjango2028Warning) response = self.client.get(changelist_url) message_warnings = [str(warning.message) for warning in warning_list] @@ -918,7 +918,7 @@ def test_overridden_admin_action_methods(self): "action_location=ActionLocation.CHANGE_LIST)." ) with self.assertWarnsMessage( - RemovedInDjango70Warning, get_actions_overridden_msg + RemovedInDjango2028Warning, get_actions_overridden_msg ) as warning: response = self.client.post( reverse("admin:admin_views_modelaction_changelist"), action_data diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py index ba1d8e77b231..e4b6e70aa252 100644 --- a/tests/aggregation_regress/tests.py +++ b/tests/aggregation_regress/tests.py @@ -27,7 +27,7 @@ from django.db.models.functions import Cast, Concat from django.test import TestCase, skipUnlessDBFeature from django.test.utils import Approximate, ignore_warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( Alfa, @@ -884,10 +884,10 @@ def test_order_by_group_by_join(self): def test_annotate_select_related(self): # Regression for #10127 - Empty select_related() works with annotate - # RemovedInDjango70Warning: when the deprecation ends, the below + # RemovedInDjango2028Warning: when the deprecation ends, the below # queryset and assertion can be removed. with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): qs = ( diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py index fd5f6716dcc7..c2ae7ee3c0aa 100644 --- a/tests/annotations/tests.py +++ b/tests/annotations/tests.py @@ -41,7 +41,7 @@ from django.db.models.sql.query import get_field_names_from_opts from django.test import TestCase, skipUnlessDBFeature from django.test.utils import register_lookup -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( Author, @@ -1186,7 +1186,7 @@ def test_annotation_aggregate_with_m2o(self): ) def test_alias_sql_injection(self): - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # msg = ( # "Column aliases cannot contain whitespace characters, hashes, " # "quotation marks, semicolons, percent signs, or SQL comments." @@ -1205,7 +1205,7 @@ def test_alias_sql_injection(self): Book.objects.annotate(**{crafted_alias: Value(1)}) def test_alias_filtered_relation_sql_injection(self): - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # msg = ( # "Column aliases cannot contain whitespace characters, hashes, " # "quotation marks, semicolons, percent signs, or SQL comments." @@ -1235,7 +1235,7 @@ def test_alias_forbidden_chars(self): "ali/*as", "alias*/", "alias;", - # RemovedInDjango70Warning: When the deprecation ends, add this: + # RemovedInDjango2028Warning: When the deprecation ends, add this: # "alias%", # [] and # are used by MSSQL. "alias[", @@ -1243,7 +1243,7 @@ def test_alias_forbidden_chars(self): "ali#as", "ali\0as", ] - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # msg = ( # "Column aliases cannot contain whitespace characters, hashes, " # "quotation marks, semicolons, percent signs, or SQL comments." @@ -1264,7 +1264,7 @@ def test_alias_forbidden_chars(self): def test_alias_containing_percent_sign_deprecation(self): msg = "Using percent signs in a column alias is deprecated." - with self.assertRaisesMessage(RemovedInDjango70Warning, msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, msg): Book.objects.annotate(**{"alias%": Value(1)}) @skipUnless(connection.vendor == "postgresql", "PostgreSQL tests") @@ -1559,7 +1559,7 @@ def test_alias_after_values(self): self.assertEqual(qs.get(pk=self.b1.pk), (self.b1.pk,)) def test_alias_sql_injection(self): - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # msg = ( # "Column aliases cannot contain whitespace characters, hashes, " # "quotation marks, semicolons, percent signs, or SQL comments." @@ -1578,7 +1578,7 @@ def test_alias_sql_injection(self): Book.objects.alias(**{crafted_alias: Value(1)}) def test_alias_filtered_relation_sql_injection(self): - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # msg = ( # "Column aliases cannot contain whitespace characters, hashes, " # "quotation marks, semicolons, percent signs, or SQL comments." diff --git a/tests/backends/base/test_creation.py b/tests/backends/base/test_creation.py index 8fd8f490b28f..fda9d00c93e8 100644 --- a/tests/backends/base/test_creation.py +++ b/tests/backends/base/test_creation.py @@ -8,7 +8,7 @@ from django.db.backends.base.creation import TEST_DATABASE_PREFIX, BaseDatabaseCreation from django.test import SimpleTestCase, TransactionTestCase from django.test.utils import override_settings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from ..models import ( CircularA, @@ -184,7 +184,7 @@ def test_serialize_deprecation(self, serialize_db_to_string, *mocked_objects): ) try: with ( - self.assertWarnsMessage(RemovedInDjango70Warning, msg) as ctx, + self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as ctx, mock.patch.object(creation, "_create_test_db"), ): creation.create_test_db(verbosity=0, serialize=True) @@ -197,7 +197,7 @@ def test_serialize_deprecation(self, serialize_db_to_string, *mocked_objects): serialize_db_to_string.reset_mock() try: with ( - self.assertWarnsMessage(RemovedInDjango70Warning, msg) as ctx, + self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as ctx, mock.patch.object(creation, "_create_test_db"), ): creation.create_test_db(verbosity=0, serialize=False) diff --git a/tests/basic/models.py b/tests/basic/models.py index 32dbff6f7095..4a4f19459125 100644 --- a/tests/basic/models.py +++ b/tests/basic/models.py @@ -63,7 +63,7 @@ class ChildPrimaryKeyWithDefault(PrimaryKeyWithDefault): pass -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class FromDbOldSignature(models.Model): name = models.CharField(max_length=20) @@ -74,7 +74,7 @@ def from_db(cls, db, field_names, values): return instance -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class FromDbOldSignatureRelated(models.Model): old = models.ForeignKey(FromDbOldSignature, models.CASCADE) diff --git a/tests/basic/tests.py b/tests/basic/tests.py index c407f371b08e..508e211b9e84 100644 --- a/tests/basic/tests.py +++ b/tests/basic/tests.py @@ -24,7 +24,7 @@ ) from django.test.utils import CaptureQueriesContext from django.utils.connection import ConnectionDoesNotExist -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.translation import gettext_lazy from .models import ( @@ -1131,7 +1131,7 @@ def test_refresh_ignores_fetch_mode_if_no_instance_plucked(self): class ModelFromDbTests(TestCase): - # RemovedInDjango70Warning: Remove the FromDbOldSignature tests when the + # RemovedInDjango2028Warning: Remove the FromDbOldSignature tests when the # deprecation ends. deprecation_msg = ( "FromDbOldSignature.from_db() must accept a fetch_mode keyword " @@ -1141,21 +1141,21 @@ class ModelFromDbTests(TestCase): def test_old_signature_iteration(self): obj = FromDbOldSignature.objects.create(name="test") - with self.assertWarnsMessage(RemovedInDjango70Warning, self.deprecation_msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, self.deprecation_msg): instances = list(FromDbOldSignature.objects.all()) self.assertEqual(instances, [obj]) self.assertEqual(instances[0]._loaded_values, {"id": obj.pk, "name": "test"}) def test_old_signature_get(self): obj = FromDbOldSignature.objects.create(name="test") - with self.assertWarnsMessage(RemovedInDjango70Warning, self.deprecation_msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, self.deprecation_msg): fetched = FromDbOldSignature.objects.get(pk=obj.pk) self.assertEqual(fetched._loaded_values, {"id": obj.pk, "name": "test"}) def test_old_signature_select_related(self): obj = FromDbOldSignature.objects.create(name="test") related = FromDbOldSignatureRelated.objects.create(old=obj) - with self.assertWarnsMessage(RemovedInDjango70Warning, self.deprecation_msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, self.deprecation_msg): fetched = FromDbOldSignatureRelated.objects.select_related("old").get( pk=related.pk ) @@ -1163,7 +1163,7 @@ def test_old_signature_select_related(self): def test_old_signature_raw(self): obj = FromDbOldSignature.objects.create(name="test") - with self.assertWarnsMessage(RemovedInDjango70Warning, self.deprecation_msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, self.deprecation_msg): instances = list( FromDbOldSignature.objects.raw("SELECT * FROM basic_fromdboldsignature") ) diff --git a/tests/defer/tests.py b/tests/defer/tests.py index 89c6f4903857..13d1aa1b4fad 100644 --- a/tests/defer/tests.py +++ b/tests/defer/tests.py @@ -2,7 +2,7 @@ from django.db.models import FETCH_PEERS, FETCH_RAISE from django.test import SimpleTestCase, TestCase from django.test.utils import ignore_warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( BigChild, @@ -148,12 +148,12 @@ def test_only_with_select_related(self): self.assertEqual(obj.related_id, self.s1.pk) self.assertEqual(obj.name, "p1") - # RemovedInDjango70Warning: when the deprecation ends, remove this test. + # RemovedInDjango2028Warning: when the deprecation ends, remove this test. def test_defer_foreign_keys_are_deferred_and_not_traversed(self): # select_related() overrides defer(). with self.assertNumQueries(1): with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): obj = Primary.objects.defer("related").select_related()[0] @@ -337,7 +337,7 @@ def test_defer_proxy(self): related = Secondary.objects.create(first="x1", second="x2") ChildProxy.objects.create(name="p1", value="xx", related=related) with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): children = ChildProxy.objects.select_related().only("id", "name") diff --git a/tests/deprecation/test_signed_cookie_legacy_salt_fallback.py b/tests/deprecation/test_signed_cookie_legacy_salt_fallback.py index 4b51707e45ef..7eaa928213f5 100644 --- a/tests/deprecation/test_signed_cookie_legacy_salt_fallback.py +++ b/tests/deprecation/test_signed_cookie_legacy_salt_fallback.py @@ -8,15 +8,15 @@ settings, ) from django.test import SimpleTestCase -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class SignedCookieLegacySaltFallbackDeprecationTests(SimpleTestCase): msg = SIGNED_COOKIE_LEGACY_SALT_DEPRECATED_MSG def test_override_settings_warning(self): - with self.assertRaisesMessage(RemovedInDjango70Warning, self.msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, self.msg): with self.settings(SIGNED_COOKIE_LEGACY_SALT_FALLBACK=True): pass @@ -26,14 +26,14 @@ def test_settings_init_warning(self): settings_module.SIGNED_COOKIE_LEGACY_SALT_FALLBACK = True sys.modules["fake_settings_module"] = settings_module try: - with self.assertRaisesMessage(RemovedInDjango70Warning, self.msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, self.msg): Settings("fake_settings_module") finally: del sys.modules["fake_settings_module"] def test_settings_assignment_warning(self): lazy_settings = LazySettings() - with self.assertRaisesMessage(RemovedInDjango70Warning, self.msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, self.msg): lazy_settings.SIGNED_COOKIE_LEGACY_SALT_FALLBACK = True def test_access(self): diff --git a/tests/deprecation/test_use_blank_choice_dash.py b/tests/deprecation/test_use_blank_choice_dash.py index 8867568535a4..a432208e63b3 100644 --- a/tests/deprecation/test_use_blank_choice_dash.py +++ b/tests/deprecation/test_use_blank_choice_dash.py @@ -8,15 +8,15 @@ settings, ) from django.test import SimpleTestCase -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class UseBlankChoiceDashDeprecationTests(SimpleTestCase): msg = USE_BLANK_CHOICE_DASH_DEPRECATED_MSG def test_override_settings_warning(self): - with self.assertRaisesMessage(RemovedInDjango70Warning, self.msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, self.msg): with self.settings(USE_BLANK_CHOICE_DASH=True): pass @@ -26,14 +26,14 @@ def test_settings_init_warning(self): settings_module.USE_BLANK_CHOICE_DASH = True sys.modules["fake_settings_module"] = settings_module try: - with self.assertRaisesMessage(RemovedInDjango70Warning, self.msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, self.msg): Settings("fake_settings_module") finally: del sys.modules["fake_settings_module"] def test_settings_assignment_warning(self): settings = LazySettings() - with self.assertRaisesMessage(RemovedInDjango70Warning, self.msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, self.msg): settings.USE_BLANK_CHOICE_DASH = True def test_access(self): diff --git a/tests/deprecation/tests.py b/tests/deprecation/tests.py index e3a2f872f0f2..af32818cbe04 100644 --- a/tests/deprecation/tests.py +++ b/tests/deprecation/tests.py @@ -3,6 +3,7 @@ from django.test import SimpleTestCase from django.utils.deprecation import ( RemovedAfterNextVersionWarning, + RemovedInDjango2028Warning, RenameMethodsBase, ) @@ -181,3 +182,16 @@ def test_removedafternextversionwarning_pending(self): self.assertTrue( issubclass(RemovedAfterNextVersionWarning, PendingDeprecationWarning) ) + + +# RemovedInDjango2028Warning. +class DeprecatedWarningsTests(SimpleTestCase): + def test_removed_in_django_70_warning_alias(self): + msg = ( + "RemovedInDjango2028Warning should be used instead of " + "RemovedInDjango70Warning." + ) + with self.assertWarnsMessage(UserWarning, msg): + from django.utils.deprecation import RemovedInDjango70Warning + + self.assertIs(RemovedInDjango70Warning, RemovedInDjango2028Warning) diff --git a/tests/expressions/test_queryset_values.py b/tests/expressions/test_queryset_values.py index 175aacd1115a..a3dd8215e5fe 100644 --- a/tests/expressions/test_queryset_values.py +++ b/tests/expressions/test_queryset_values.py @@ -2,7 +2,7 @@ from django.db.models import F, Sum from django.test import TestCase, skipUnlessDBFeature -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import Company, Employee, JSONFieldModel @@ -39,7 +39,7 @@ def test_values_expression(self): def test_values_expression_containing_percent_sign_deprecation_warns_once(self): msg = "Using percent signs in a column alias is deprecated." - with self.assertWarnsMessage(RemovedInDjango70Warning, msg) as cm: + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as cm: Company.objects.values(**{"alias%": F("id")}) self.assertEqual(len(cm.warnings), 1) diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index 2c1ec7865027..c2137f442d84 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -48,7 +48,7 @@ from django.test import SimpleTestCase, ignore_warnings from django.test.utils import override_settings from django.utils.datastructures import MultiValueDict -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.safestring import mark_safe from . import jinja2_tests @@ -801,8 +801,8 @@ class FrameworkForm(Form): """, ) - # RemovedInDjango70Warning - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning + @ignore_warnings(category=RemovedInDjango2028Warning) @override_settings(USE_BLANK_CHOICE_DASH=True) def test_blank_choice_dash(self): class SomeForm(Form): @@ -829,7 +829,7 @@ class SomeForm(Form): ) self.assertWarnsMessage( - RemovedInDjango70Warning, USE_BLANK_CHOICE_DASH_DEPRECATED_MSG + RemovedInDjango2028Warning, USE_BLANK_CHOICE_DASH_DEPRECATED_MSG ) def test_forms_with_radio(self): diff --git a/tests/gis_tests/relatedapp/tests.py b/tests/gis_tests/relatedapp/tests.py index 7ff7654b7549..a7d1ecac55ab 100644 --- a/tests/gis_tests/relatedapp/tests.py +++ b/tests/gis_tests/relatedapp/tests.py @@ -5,7 +5,7 @@ from django.test import TestCase, skipUnlessDBFeature from django.test.utils import ignore_warnings, override_settings from django.utils import timezone -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from ..utils import skipUnlessGISLookup from .models import Article, Author, Book, City, DirectoryEntry, Event, Location, Parcel @@ -17,10 +17,10 @@ class RelatedGeoModelTest(TestCase): def test02_select_related(self): "Testing `select_related` on geographic models (see #7126)." qs1 = City.objects.order_by("id") - # RemovedInDjango70Warning: when the deprecation ends, the below + # RemovedInDjango2028Warning: when the deprecation ends, the below # queryset can be removed. with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): qs2 = City.objects.order_by("id").select_related() diff --git a/tests/logging_tests/tests.py b/tests/logging_tests/tests.py index 2e4717426ecf..ec5b53d96700 100644 --- a/tests/logging_tests/tests.py +++ b/tests/logging_tests/tests.py @@ -24,7 +24,7 @@ from django.http.multipartparser import MultiPartParserError from django.test import RequestFactory, SimpleTestCase, override_settings from django.test.utils import LoggingCaptureMixin -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.log import ( DEFAULT_LOGGING, AdminEmailHandler, @@ -307,7 +307,7 @@ def make_log_record(self, url_path=None, *args, **kwargs): record.request = self.request_factory.get(url_path, *args, **kwargs) return record - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_deprecated_email_settings( ADMINS=["admin@example.com"], EMAIL_BACKEND="mail.custombackend.FailingEmailBackend", @@ -411,14 +411,14 @@ def test_subject_accepts_newlines(self): self.assertNotIn("\r", mail.outbox[0].subject) self.assertEqual(mail.outbox[0].subject, expected_subject) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(ADMINS=["admin@example.com"]) @ignore_no_default_mailer_warning() def test_uses_custom_email_backend(self): del settings.MAILERS self.addCleanup(OptionsCapturingBackend.reset) msg = "The 'email_backend' argument is deprecated. Use 'using' instead." - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): handler = AdminEmailHandler( email_backend="mail.custombackend.OptionsCapturingBackend" ) @@ -455,7 +455,7 @@ def test_using_arg(self): self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].sent_using, "custom") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_using_conflicts_with_email_backend(self): msg = "The 'email_backend' argument is not compatible with 'using'." with self.assertRaisesMessage(ImproperlyConfigured, msg): @@ -463,7 +463,7 @@ def test_using_conflicts_with_email_backend(self): email_backend="logging_tests.logconfig.MyEmailBackend", using="custom" ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(MAILERS={}) def test_email_backend_not_valid_when_mailers_defined(self): msg = ( @@ -473,7 +473,7 @@ def test_email_backend_not_valid_when_mailers_defined(self): with self.assertRaisesMessage(ImproperlyConfigured, msg): AdminEmailHandler(email_backend="logging_tests.logconfig.MyEmailBackend") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_error_when_subclass_defines_undocumented_connection_method(self): class CustomAdminEmailHandler(AdminEmailHandler): diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py index acdfbfabfc6f..9ab9b3f66542 100644 --- a/tests/lookup/tests.py +++ b/tests/lookup/tests.py @@ -32,7 +32,7 @@ ) from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.test.utils import ignore_warnings, isolate_apps, register_lookup -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( Article, @@ -590,18 +590,18 @@ def test_in_bulk_values_list_named_fields_alternative_field(self): self.assertEqual(arts1.slug, "a1") self.assertEqual(arts1.headline, "Article 1") - # RemovedInDjango70Warning: When the deprecation ends, remove this + # RemovedInDjango2028Warning: When the deprecation ends, remove this # test. def test_in_bulk_values_list_flat_empty(self): - with ignore_warnings(category=RemovedInDjango70Warning): + with ignore_warnings(category=RemovedInDjango2028Warning): arts = Article.objects.values_list(flat=True).in_bulk([]) self.assertEqual(arts, {}) - # RemovedInDjango70Warning: When the deprecation ends, remove this + # RemovedInDjango2028Warning: When the deprecation ends, remove this # test. def test_in_bulk_values_list_flat_all(self): Article.objects.exclude(pk__in=[self.a1.pk, self.a2.pk]).delete() - with ignore_warnings(category=RemovedInDjango70Warning): + with ignore_warnings(category=RemovedInDjango2028Warning): arts = Article.objects.values_list(flat=True).in_bulk() self.assertEqual( arts, @@ -611,10 +611,10 @@ def test_in_bulk_values_list_flat_all(self): }, ) - # RemovedInDjango70Warning: When the deprecation ends, remove this + # RemovedInDjango2028Warning: When the deprecation ends, remove this # test. def test_in_bulk_values_list_flat_pks(self): - with ignore_warnings(category=RemovedInDjango70Warning): + with ignore_warnings(category=RemovedInDjango2028Warning): arts = Article.objects.values_list(flat=True).in_bulk( [self.a1.pk, self.a2.pk] ) @@ -912,9 +912,9 @@ def test_values_list_filter_and_no_fields(self): ], ) - # RemovedInDjango70Warning: When the deprecation ends, remove this test. + # RemovedInDjango2028Warning: When the deprecation ends, remove this test. def test_values_list_flat_no_fields(self): - with ignore_warnings(category=RemovedInDjango70Warning): + with ignore_warnings(category=RemovedInDjango2028Warning): qs = Article.objects.values_list(flat=True) self.assertSequenceEqual( qs, @@ -1037,7 +1037,7 @@ def test_values_list_flat_more_than_one_field(self): with self.assertRaisesMessage(TypeError, msg): Article.objects.values_list("id", "headline", flat=True) - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # def test_values_list_flat_empty_error(self): # msg = ( # "'flat' is not valid when values_list is called with no fields." @@ -1050,7 +1050,7 @@ def test_values_list_flat_empty_warning(self): "is deprecated. Pass an explicit field name instead, like " "'pk'." ) - with self.assertRaisesMessage(RemovedInDjango70Warning, msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, msg): Article.objects.values_list(flat=True) def test_get_next_previous_by(self): diff --git a/tests/mail/__init__.py b/tests/mail/__init__.py index c6d8da261a04..ae17b79ca1c8 100644 --- a/tests/mail/__init__.py +++ b/tests/mail/__init__.py @@ -4,10 +4,10 @@ from django.conf import DEPRECATED_EMAIL_SETTINGS, EMAIL_SETTING_DEPRECATED_MSG from django.core.mail.deprecation import NO_DEFAULT_MAILER_WARNING from django.test import ignore_warnings, override_settings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class override_deprecated_email_settings(override_settings): """Override settings, ignoring warnings for deprecated email settings. @@ -32,7 +32,7 @@ def __init__(self, **kwargs): re.escape("{name}"), rf"(?:{deprecated_names_re})" ) self.ignore_warnings = ignore_warnings( - category=RemovedInDjango70Warning, message=message_re + category=RemovedInDjango2028Warning, message=message_re ) else: self.ignore_warnings = nullcontext() @@ -46,9 +46,9 @@ def disable(self): super().disable() -# RemovedInDjango70Warning: Remove this helper and all uses of it. +# RemovedInDjango2028Warning: Remove this helper and all uses of it. def ignore_no_default_mailer_warning(): return ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=re.escape(NO_DEFAULT_MAILER_WARNING), ) diff --git a/tests/mail/test_backends.py b/tests/mail/test_backends.py index eee501de7047..78d5bcfbf524 100644 --- a/tests/mail/test_backends.py +++ b/tests/mail/test_backends.py @@ -19,7 +19,7 @@ from django.core.mail.backends import console, dummy, filebased, locmem, smtp from django.core.mail.backends.base import BaseEmailBackend from django.test import SimpleTestCase, ignore_warnings, override_settings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .tests import MailTestsMixin, message_from_bytes @@ -36,15 +36,15 @@ def test_alias_arg_accepted(self): backend = BaseEmailBackend(alias="test_alias") self.assertEqual(backend.alias, "test_alias") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_fail_silently_arg_accepted(self): msg_init = "BaseEmailBackend.__init__() does not support 'fail_silently'." msg_use = "BaseEmailBackend.fail_silently is deprecated." for value in [True, False]: with self.subTest(fail_silently=value): - with self.assertWarnsMessage(RemovedInDjango70Warning, msg_init): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg_init): backend = BaseEmailBackend(fail_silently=value) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg_use): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg_use): self.assertIs(backend.fail_silently, value) def test_unknown_kwargs_error(self): @@ -52,16 +52,16 @@ def test_unknown_kwargs_error(self): with self.assertRaisesMessage(InvalidMailer, msg): BaseEmailBackend(alias="test_alias", oops_typo="foo", unknown="bar") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_unknown_kwargs_ignored(self): # In compatibility mode (without alias), unknown keyword args are # ignored with a deprecation warning. msg = ( "BaseEmailBackend.__init__() does not support 'oops_typo', " - "'unknown'. In Django 7.0, BaseEmailBackend will raise a " + "'unknown'. In Django 2028, BaseEmailBackend will raise a " "TypeError for unknown keyword arguments." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): backend = BaseEmailBackend(oops_typo="foo", unknown="foo") self.assertIsInstance(backend, BaseEmailBackend) self.assertFalse(hasattr(backend, "oops_typo")) @@ -113,7 +113,7 @@ def test_accepts_alias(self): backend = self.create_backend(alias="this-alias") self.assertEqual(backend.alias, "this-alias") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_alias_is_optional_during_transition_to_mailers(self): # alias=None tells create_backend() to _omit_ the `alias` arg. backend = self.create_backend(alias=None) @@ -192,9 +192,9 @@ def test_connection_can_be_used_as_contextmanager(self): backend.close.assert_called_once() - # RemovedInDjango70Warning. (But keep overrides in subclasses.) + # RemovedInDjango2028Warning. (But keep overrides in subclasses.) def test_fail_silently_arg_accepted(self): - # In Django 7.0, the fail_silently arg will *not* be accepted by + # In Django 2028, the fail_silently arg will *not* be accepted by # BaseEmailBackend. Backends that *do* support fail_silently must # handle that argument themselves. Tests for those backends should # override this test case to reflect continuing fail_silently support. @@ -206,9 +206,9 @@ def test_fail_silently_arg_accepted(self): msg_use = "EmailBackend.fail_silently is deprecated." for value in [True, False]: with self.subTest(fail_silently=value): - with self.assertWarnsMessage(RemovedInDjango70Warning, msg_init): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg_init): backend = self.create_backend(alias=None, fail_silently=value) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg_use): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg_use): self.assertIs(backend.fail_silently, value) with self.subTest("Updated configuration"): @@ -222,20 +222,20 @@ def test_unknown_kwargs_error(self): with self.assertRaisesMessage(InvalidMailer, msg): self.create_backend(oops_typo=True, unknown="foo") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_unknown_kwargs_ignored(self): # In compatibility mode (without alias), unknown keyword args are # ignored with a deprecation warning. backend_module = self.backend_class.__module__ msg = ( f"{backend_module}.EmailBackend.__init__() does not support " - "'unknown_kwarg'. In Django 7.0, BaseEmailBackend will raise a " + "'unknown_kwarg'. In Django 2028, BaseEmailBackend will raise a " "TypeError for unknown keyword arguments." ) with ( - self.assertWarnsMessage(RemovedInDjango70Warning, msg), + self.assertWarnsMessage(RemovedInDjango2028Warning, msg), ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=re.escape( "Directly creating EmailBackend instances is deprecated." ), @@ -319,7 +319,7 @@ def test_adds_sent_using_attribute(self): @ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"The EMAIL_FILE_PATH setting is deprecated\.", ) class FileBackendTests(SharedEmailBackendTests, SimpleTestCase): @@ -357,7 +357,7 @@ def get_mailbox_content(self): return messages def test_fail_silently_arg_accepted(self): - # RemovedInDjango70Warning: remove this comment (but keep the test). + # RemovedInDjango2028Warning: remove this comment (but keep the test). # The file backend continues to support fail_silently. Override the # SharedEmailBackendTests case that treats it as deprecated. for value in [True, False]: @@ -368,14 +368,14 @@ def test_fail_silently_arg_accepted(self): def test_create_from_mailers(self): super().test_create_from_mailers(required_options={"file_path": self.tmp_dir}) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_email_file_path_use_settings(self): file_path_settings = self.mkdtemp() with self.settings(EMAIL_FILE_PATH=file_path_settings): backend = filebased.EmailBackend() self.assertEqual(backend.file_path, str(file_path_settings)) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_email_file_path_override_settings(self): file_path_settings = self.mkdtemp() file_path_override = self.mkdtemp() @@ -385,7 +385,7 @@ def test_email_file_path_override_settings(self): backend = filebased.EmailBackend(file_path=file_path_override) self.assertEqual(backend.file_path, str(file_path_override)) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_error_if_email_file_path_setting_not_defined(self): msg = "The EMAIL_FILE_PATH setting must be set to use the file EmailBackend." with self.assertRaisesMessage(ImproperlyConfigured, msg): @@ -396,7 +396,7 @@ def test_file_path_option_required(self): with self.assertRaisesMessage(InvalidMailer, msg): filebased.EmailBackend(alias="test_alias") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_FILE_PATH="/this/path/does/not/exist") def test_ignores_settings_when_initialized_with_alias(self): backend = self.create_backend() @@ -412,7 +412,7 @@ def test_error_if_file_path_is_not_directory(self): with self.assertRaisesMessage(InvalidMailer, msg): self.create_backend(file_path=tmp_file) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. with self.subTest("Compatibility"): msg = ( "Path for saving email messages exists, but is not a " @@ -431,7 +431,7 @@ def test_error_if_file_path_cannot_be_created(self): with self.assertRaisesMessage(InvalidMailer, msg): self.create_backend(file_path="/dev/null/foo") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. with self.subTest("Compatibility"): msg = "Could not create directory for saving email messages: /dev/null/foo" with self.assertRaisesMessage(ImproperlyConfigured, msg): @@ -449,7 +449,7 @@ def test_error_if_file_path_is_not_writable(self): with self.assertRaisesMessage(InvalidMailer, msg): self.create_backend(file_path=self.tmp_dir) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. with self.subTest("Compatibility"): msg = f"Could not write to directory: {self.tmp_dir}" with self.assertRaisesMessage(ImproperlyConfigured, msg): @@ -544,7 +544,7 @@ def get_mailbox_content(self): return [message_from_bytes(m.encode()) for m in messages if m] def test_fail_silently_arg_accepted(self): - # RemovedInDjango70Warning: remove this comment (but keep the test). + # RemovedInDjango2028Warning: remove this comment (but keep the test). # The console backend continues to support fail_silently. Override the # SharedEmailBackendTests case that treats it as deprecated. for value in [True, False]: @@ -599,7 +599,8 @@ def flush_mailbox(self): @skipUnless(HAS_AIOSMTPD, "No aiosmtpd library detected.") @ignore_warnings( - category=RemovedInDjango70Warning, message=r"The EMAIL_\w+ setting is deprecated\." + category=RemovedInDjango2028Warning, + message=r"The EMAIL_\w+ setting is deprecated\.", ) class SMTPBackendTestsBase(SimpleTestCase): @classmethod @@ -625,7 +626,7 @@ def stop_smtp(cls): @skipUnless(HAS_AIOSMTPD, "No aiosmtpd library detected.") @ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=re.escape("Directly creating EmailBackend instances is deprecated."), ) class SMTPBackendTests(SharedEmailBackendTests, SMTPBackendTestsBase): @@ -651,7 +652,7 @@ def get_smtp_envelopes(self): return self.smtp_handler.smtp_envelopes def test_fail_silently_arg_accepted(self): - # RemovedInDjango70Warning: remove this comment (but keep the test). + # RemovedInDjango2028Warning: remove this comment (but keep the test). # The SMTP backend continues to support fail_silently. Override the # SharedEmailBackendTests case that treats it as deprecated. for value in [True, False]: @@ -662,7 +663,7 @@ def test_fail_silently_arg_accepted(self): def test_create_from_mailers(self): super().test_create_from_mailers(required_options={"host": "example.com"}) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings( EMAIL_HOST="mail.example.com", EMAIL_PORT=822, @@ -685,13 +686,13 @@ def test_ignores_settings_when_initialized_with_alias(self): self.assertIsNone(backend.ssl_certfile) self.assertIsNone(backend.ssl_keyfile) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_direct_construction_deprecated(self): msg = ( "Directly creating EmailBackend instances is deprecated. Use " "mail.mailers instead." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): backend = self.backend_class(use_tls=True) # Default values come from deprecated settings without special handling # for port. @@ -716,14 +717,14 @@ def test_port_default_adapts_to_security(self): ) self.assertEqual(backend.port, expected_port) - # RemovedInDjango70Warning: Until Django 7.0, the dynamic port default - # applies only when initialized through mail.mailers. + # RemovedInDjango2028Warning: Until Django 2028, the dynamic port + # default applies only when initialized through mail.mailers. for case, kwargs, _ in cases: with self.subTest(f"compatibility {case}"): backend = self.backend_class(host="mail.example.com", **kwargs) self.assertEqual(backend.port, 25) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings( EMAIL_HOST="mail.example.com", EMAIL_PORT=822, @@ -733,7 +734,7 @@ def test_email_host_use_settings(self): self.assertEqual(backend.host, "mail.example.com") self.assertEqual(backend.port, 822) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings( EMAIL_HOST="mail.example.com", EMAIL_PORT=822, @@ -757,7 +758,7 @@ def test_smtp_connection_uses_host_and_port(self): "mail.example.com", 5322, local_hostname=mock.ANY ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings( EMAIL_HOST_USER="not empty username", EMAIL_HOST_PASSWORD="not empty password", @@ -767,7 +768,7 @@ def test_email_authentication_use_settings(self): self.assertEqual(backend.username, "not empty username") self.assertEqual(backend.password, "not empty password") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings( EMAIL_HOST_USER="not empty username", EMAIL_HOST_PASSWORD="not empty password", @@ -777,7 +778,7 @@ def test_email_authentication_override_settings(self): self.assertEqual(backend.username, "username") self.assertEqual(backend.password, "password") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings( EMAIL_HOST_USER="not empty username", EMAIL_HOST_PASSWORD="not empty password", @@ -842,13 +843,13 @@ def test_reopen_replaces_partial_connection(self): self.assertIsNone(partial_conn.sock) self.assertIsNotNone(backend._partial_connection.sock) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_USE_TLS=True) def test_email_tls_use_settings(self): backend = smtp.EmailBackend() self.assertIs(backend.use_tls, True) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_USE_TLS=True) def test_email_tls_override_settings(self): backend = smtp.EmailBackend(use_tls=False) @@ -866,7 +867,7 @@ def test_ssl_tls_mutually_exclusive(self): with self.assertRaisesMessage(InvalidMailer, msg): self.create_backend(use_ssl=True, use_tls=True) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_ssl_tls_settings_mutually_exclusive(self): msg = ( "EMAIL_USE_TLS/EMAIL_USE_SSL are mutually exclusive, so only set " @@ -878,13 +879,13 @@ def test_ssl_tls_settings_mutually_exclusive(self): ): smtp.EmailBackend() - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_USE_SSL=True) def test_email_ssl_use_settings(self): backend = smtp.EmailBackend() self.assertIs(backend.use_ssl, True) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_USE_SSL=True) def test_email_ssl_override_settings(self): backend = smtp.EmailBackend(use_ssl=False) @@ -894,13 +895,13 @@ def test_email_ssl_default_disabled(self): backend = self.create_backend() self.assertIs(backend.use_ssl, False) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_SSL_CERTFILE="foo") def test_email_ssl_certfile_use_settings(self): backend = smtp.EmailBackend() self.assertEqual(backend.ssl_certfile, "foo") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_SSL_CERTFILE="foo") def test_email_ssl_certfile_override_settings(self): backend = smtp.EmailBackend(ssl_certfile="bar") @@ -910,13 +911,13 @@ def test_email_ssl_certfile_default_disabled(self): backend = self.create_backend() self.assertIsNone(backend.ssl_certfile) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_SSL_KEYFILE="foo") def test_email_ssl_keyfile_use_settings(self): backend = smtp.EmailBackend() self.assertEqual(backend.ssl_keyfile, "foo") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_SSL_KEYFILE="foo") def test_email_ssl_keyfile_override_settings(self): backend = smtp.EmailBackend(ssl_keyfile="bar") @@ -973,13 +974,13 @@ def __init__(self, *args, **kwargs): self.assertEqual(myemailbackend.timeout, 42) self.assertEqual(myemailbackend.connection.timeout, 42) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_TIMEOUT=10) def test_email_timeout_use_settings(self): backend = smtp.EmailBackend() self.assertEqual(backend.timeout, 10) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(EMAIL_TIMEOUT=10) def test_email_timeout_override_settings(self): backend = smtp.EmailBackend(timeout=15) @@ -1155,7 +1156,7 @@ class SMTPBackendStoppedServerTests(SMTPBackendTestsBase): @classmethod def setUpClass(cls): super().setUpClass() - # RemovedInDjango70Warning: alias argument can be removed (needed + # RemovedInDjango2028Warning: alias argument can be removed (needed # during mail.mailers transition to prevent compatibility mode). cls.backend = smtp.EmailBackend( alias="test_alias", diff --git a/tests/mail/test_deprecated.py b/tests/mail/test_deprecated.py index 2617750a8033..d2ae1a479bde 100644 --- a/tests/mail/test_deprecated.py +++ b/tests/mail/test_deprecated.py @@ -1,4 +1,4 @@ -# RemovedInDjango70Warning: This entire file. +# RemovedInDjango2028Warning: This entire file. import re import types import warnings @@ -21,7 +21,7 @@ from django.core.mail.deprecation import NO_DEFAULT_MAILER_WARNING from django.core.mail.message import forbid_multi_line_headers, sanitize_address from django.test import SimpleTestCase, ignore_warnings, override_settings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from . import override_deprecated_email_settings from .tests import MailTestsMixin @@ -53,7 +53,7 @@ def test_deprecated_on_import(self): ] for name, msg in cases: with self.subTest(name=name): - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): __import__("django.core.mail", fromlist=[name]) def test_sanitize_address_deprecated(self): @@ -64,7 +64,7 @@ def test_sanitize_address_deprecated(self): " encoding. Use Python's email.headerregistry.Address to construct" " formatted addresses from component parts." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): sanitize_address("to@example.com", "ascii") def test_forbid_multi_line_headers_deprecated(self): @@ -73,7 +73,7 @@ def test_forbid_multi_line_headers_deprecated(self): " Python's modern email API (with email.message.EmailMessage or" " email.policy.default) will reject multi-line headers." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): forbid_multi_line_headers("To", "to@example.com", "ascii") @@ -131,7 +131,7 @@ def get_connection(self, fail_silently=False): email.send() -@ignore_warnings(category=RemovedInDjango70Warning) +@ignore_warnings(category=RemovedInDjango2028Warning) class DeprecatedCompatibilityTests(SimpleTestCase): def test_bad_header_error(self): """ @@ -228,24 +228,24 @@ def test_warn_when_defining_deprecated_settings(self): for name in self.deprecated_settings: msg = ( f"The {name} setting is deprecated. Migrate to " - "MAILERS before Django 7.0." + "MAILERS before Django 2028." ) settings = {name: "foo"} with self.subTest(name=name): with ( self.subTest("settings module"), self.mock_settings_module(**settings), - self.assertWarnsMessage(RemovedInDjango70Warning, msg), + self.assertWarnsMessage(RemovedInDjango2028Warning, msg), ): self.init_simulated_settings() with ( self.subTest("settings.configure()"), - self.assertWarnsMessage(RemovedInDjango70Warning, msg), + self.assertWarnsMessage(RemovedInDjango2028Warning, msg), ): LazySettings().configure(**settings) with ( self.subTest("override_settings()"), - self.assertWarnsMessage(RemovedInDjango70Warning, msg), + self.assertWarnsMessage(RemovedInDjango2028Warning, msg), ): with override_settings(**settings): pass @@ -256,18 +256,18 @@ def test_multiple_deprecated_settings_are_all_reported(self): expected_warning_count = len(settings) with self.subTest("settings module"), self.mock_settings_module(**settings): - with self.assertWarnsRegex(RemovedInDjango70Warning, msg_re) as cm: + with self.assertWarnsRegex(RemovedInDjango2028Warning, msg_re) as cm: self.init_simulated_settings() self.assertEqual(len(cm.warnings), expected_warning_count) with self.subTest("settings.configure()"): - with self.assertWarnsRegex(RemovedInDjango70Warning, msg_re) as cm: + with self.assertWarnsRegex(RemovedInDjango2028Warning, msg_re) as cm: LazySettings().configure(**settings) self.assertEqual(len(cm.warnings), expected_warning_count) with self.subTest("override_settings()"): with ( - self.assertWarnsRegex(RemovedInDjango70Warning, msg_re) as cm, + self.assertWarnsRegex(RemovedInDjango2028Warning, msg_re) as cm, override_settings(**settings), ): pass @@ -285,22 +285,22 @@ def test_warn_about_no_default_mailer(self): msg = NO_DEFAULT_MAILER_WARNING with ( self.subTest("get_connection()"), - self.assertWarnsMessage(RemovedInDjango70Warning, msg), + self.assertWarnsMessage(RemovedInDjango2028Warning, msg), ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=re.escape("get_connection() is deprecated."), ), ): get_connection() with ( self.subTest("mailers.default"), - self.assertWarnsMessage(RemovedInDjango70Warning, msg), + self.assertWarnsMessage(RemovedInDjango2028Warning, msg), ): _ = mailers.default # The warning is not issued on startup, to avoid creating noise for # projects that don't send email at all. - with self.assertNotWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertNotWarnsMessage(RemovedInDjango2028Warning, msg): settings = self.init_simulated_settings() self.assertHasOnlyDefaultEmailSettings(settings, msg="invalid test") @@ -317,7 +317,7 @@ def test_no_default_mailer_warning_if_any_email_setting_defined(self): with ( self.subTest(name=name), override_deprecated_email_settings(**{name: value}), - self.assertNotWarnsMessage(RemovedInDjango70Warning, msg), + self.assertNotWarnsMessage(RemovedInDjango2028Warning, msg), ): _ = mailers.default with ( @@ -329,7 +329,7 @@ def test_no_default_mailer_warning_if_any_email_setting_defined(self): } } ), - self.assertNotWarnsMessage(RemovedInDjango70Warning, msg), + self.assertNotWarnsMessage(RemovedInDjango2028Warning, msg), ): _ = mailers.default @@ -359,12 +359,12 @@ def test_warn_when_using_deprecated_settings(self): for name in self.deprecated_settings: msg = ( f"The {name} setting is deprecated. Migrate to " - "MAILERS before Django 7.0." + "MAILERS before Django 2028." ) with ( self.subTest(name=name), override_deprecated_email_settings(**{name: "foo"}), - self.assertWarnsMessage(RemovedInDjango70Warning, msg), + self.assertWarnsMessage(RemovedInDjango2028Warning, msg), ): getattr(django.conf.settings, name) @@ -399,7 +399,7 @@ def test_error_when_using_deprecated_settings_with_mailers_defined(self): with self.assertRaisesMessage(AttributeError, msg): getattr(django.conf.settings, name) - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) def test_direct_settings_manipulation(self): settings = self.init_simulated_settings() @@ -445,7 +445,7 @@ def test_error_when_using_conflicting_setting_via_override_settings(self): del django.conf.settings.EMAIL_HOST self.assertNotIn("EMAIL_HOST", dir(django.conf.settings)) - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) def test_deprecated_settings_defaults_unchanged(self): # Django's test runner overrides EMAIL_BACKEND in django.conf.settings, # so construct a fresh settings object for this test. @@ -460,7 +460,7 @@ def test_deprecated_settings_defaults_unchanged(self): else: self.assertEqual(actual, expected) - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) def test_email_backend_override_during_tests(self): self.assertEqual( django.conf.settings.EMAIL_BACKEND, diff --git a/tests/mail/test_handler.py b/tests/mail/test_handler.py index 227b7088ff7e..7dc929b8cedb 100644 --- a/tests/mail/test_handler.py +++ b/tests/mail/test_handler.py @@ -89,8 +89,8 @@ def test_default_mailer_property(self): backend = mailers.default self.assertEqual(backend.alias, "default") - # RemovedInDjango70Warning: remove override_settings (but keep the test). - # (MAILERS={} becomes the default in Django 7.0.) + # RemovedInDjango2028Warning: remove override_settings (but keep the test). + # (MAILERS={} becomes the default in Django 2028.) @override_settings(MAILERS={}) def test_default_mailers(self): msg = "The mailer 'default' is not configured." @@ -204,7 +204,7 @@ def test_does_not_exist_is_limited_purpose(self): MailerDoesNotExist("Some other configuration problem") -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class MailersCompatibilityTests(SimpleTestCase): """mailers.default is usable even when MAILERS is not defined.""" diff --git a/tests/mail/tests.py b/tests/mail/tests.py index 01a37284c10f..b41864391514 100644 --- a/tests/mail/tests.py +++ b/tests/mail/tests.py @@ -40,7 +40,7 @@ ) from django.test import SimpleTestCase, override_settings from django.test.utils import ignore_warnings, requires_tz_support -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.translation import gettext_lazy from . import ( @@ -247,7 +247,7 @@ def get_message_structure(self, message, level=0): structure.append(self.get_message_structure(subpart, level + 1)) return "".join(structure) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def use_email_backend(self, backend): if hasattr(settings, "MAILERS"): return self.settings(MAILERS={"default": {"BACKEND": backend}}) @@ -1126,7 +1126,7 @@ def test_attach_8bit_rfc822_message_non_ascii(self): self.assertEqual(attached_message["Content-Transfer-Encoding"], "8bit") self.assertEqual(attached_message.get_content_type(), "text/plain") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_attach_mime_image(self): """ EmailMessage.attach() docs: "You can pass it @@ -1141,7 +1141,7 @@ def test_attach_mime_image(self): image = MIMEImage(b"GIF89a...", "gif") image["Content-Disposition"] = "inline" image["Content-ID"] = "" - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): email.attach(image) attachments = self.get_raw_attachments(email) @@ -1179,7 +1179,7 @@ def test_attach_mime_part(self): self.assertEqual(image_att.get_content(), b"GIF89a...") self.assertIsNone(image_att.get_filename()) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_attach_mime_image_in_constructor(self): msg = ( "MIMEBase attachments are deprecated." @@ -1187,7 +1187,7 @@ def test_attach_mime_image_in_constructor(self): ) image = MIMEImage(b"\x89PNG...", "png") image["Content-Disposition"] = "attachment; filename=test.png" - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): email = EmailMessage(attachments=[image]) attachments = self.get_raw_attachments(email) @@ -1673,8 +1673,8 @@ def test_all_params_optional(self): email = EmailMultiAlternatives() self.assertIsInstance(email.message(), PyMessage) # force serialization. - # RemovedInDjango70Warning: connection argument. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning: connection argument. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_positional_arguments_order(self): """ EmailMessage class docs: "… is initialized with the following @@ -1714,8 +1714,8 @@ def test_positional_arguments_order(self): ) self.assertIs(email.connection, connection) - # RemovedInDjango70Warning: connection argument and attribute. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning: connection argument and attribute. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_all_params_can_be_set_before_send(self): """ EmailMessage class docs: "All parameters … can be set at any time @@ -1846,8 +1846,8 @@ def test_message_policy_compat32(self): message.as_string(policy=policy.compat32), ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_send_fail_silently_conflict(self): email = EmailMessage( "Subject", @@ -1868,22 +1868,24 @@ def test_send(self): email.send() self.assertEqual(mail.outbox[0].to, ["to@example.com"]) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if not mailers._is_configured: self.assertIsNone(mail.outbox[0].sent_using) return self.assertEqual(mail.outbox[0].sent_using, "default") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_connection_arg_deprecated(self): connection = object() - with self.assertWarnsMessage(RemovedInDjango70Warning, CONNECTION_ARG_WARNING): + with self.assertWarnsMessage( + RemovedInDjango2028Warning, CONNECTION_ARG_WARNING + ): email = EmailMessage(connection=connection) - with ignore_warnings(category=RemovedInDjango70Warning): + with ignore_warnings(category=RemovedInDjango2028Warning): self.assertIs(email.connection, connection) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_connection_attr_deprecated(self): email = EmailMessage() connection = object() @@ -1892,22 +1894,22 @@ def test_connection_attr_deprecated(self): "EmailMessage.send(using=...) with a MAILERS alias." ) msg_get = "The EmailMessage.connection attribute is deprecated." - with self.assertWarnsMessage(RemovedInDjango70Warning, msg_set): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg_set): email.connection = connection - with self.assertWarnsMessage(RemovedInDjango70Warning, msg_get): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg_get): self.assertIs(email.connection, connection) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_fail_silently_deprecated(self): email = EmailMessage(to=["to@example.com"]) with self.assertWarnsMessage( - RemovedInDjango70Warning, FAIL_SILENTLY_ARG_WARNING + RemovedInDjango2028Warning, FAIL_SILENTLY_ARG_WARNING ): email.send(fail_silently=True) -# RemovedInDjango70Warning: Move override_settings and additional test cases to -# EmailMessageTests and remove this class. +# RemovedInDjango2028Warning: Move override_settings and additional test cases +# to EmailMessageTests and remove this class. @override_settings( MAILERS={ "default": {"BACKEND": "django.core.mail.backends.locmem.EmailBackend"}, @@ -1926,8 +1928,8 @@ def test_send_using(self): self.assertEqual(mail.outbox[1].sent_using, "custom") self.assertEqual(mail.outbox[2].sent_using, "default") - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_send_using_conflicts_with_connection(self): msg = "'connection' is not compatible with 'using'." with self.subTest("in constructor"): @@ -1941,8 +1943,8 @@ def test_send_using_conflicts_with_connection(self): with self.assertRaisesMessage(TypeError, msg): email.send(using="test") - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_send_using_conflicts_with_fail_silently(self): msg = "'fail_silently' is not compatible with 'using'." email = EmailMessage(to=["to@example.com"]) @@ -1957,7 +1959,7 @@ class SendMailTests(SimpleTestCase, MailTestsMixin): def test_sends_using_default_mailer(self): send_mail("subject", "body", "from@example.com", ["to@example.com"]) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if not mailers._is_configured: self.assertIsNone(mail.outbox[0].sent_using) return @@ -2031,11 +2033,13 @@ def test_lazy_addresses(self): self.assertEqual(message.get("from"), "tester") self.assertEqual(message.get("to"), "django") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_connection_arg(self): # Send using non-default connection. connection = custombackend.EmailBackend() - with self.assertWarnsMessage(RemovedInDjango70Warning, CONNECTION_ARG_WARNING): + with self.assertWarnsMessage( + RemovedInDjango2028Warning, CONNECTION_ARG_WARNING + ): send_mail( "Subject", "Content", @@ -2047,12 +2051,12 @@ def test_connection_arg(self): self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, "Subject") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_auth_passed_to_backend_init(self): self.addCleanup(OptionsCapturingBackend.reset) with ( self.use_email_backend("mail.custombackend.OptionsCapturingBackend"), - self.assertWarnsMessage(RemovedInDjango70Warning, AUTH_ARGS_WARNING), + self.assertWarnsMessage(RemovedInDjango2028Warning, AUTH_ARGS_WARNING), ): send_mail( "Subject", @@ -2067,13 +2071,13 @@ def test_auth_passed_to_backend_init(self): self.assertEqual(init_kwargs["username"], "user") self.assertEqual(init_kwargs["password"], "password") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_fail_silently_passed_to_backend_init(self): self.addCleanup(OptionsCapturingBackend.reset) with ( self.use_email_backend("mail.custombackend.OptionsCapturingBackend"), self.assertWarnsMessage( - RemovedInDjango70Warning, FAIL_SILENTLY_ARG_WARNING + RemovedInDjango2028Warning, FAIL_SILENTLY_ARG_WARNING ), ): send_mail( @@ -2086,8 +2090,8 @@ def test_fail_silently_passed_to_backend_init(self): init_kwargs = OptionsCapturingBackend.init_kwargs[0] self.assertIs(init_kwargs["fail_silently"], True) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_fail_silently_conflict(self): msg = ( "fail_silently cannot be used with a connection. " @@ -2103,8 +2107,8 @@ def test_fail_silently_conflict(self): connection=mail.get_connection(), ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_auth_conflict(self): msg = ( "auth_user and auth_password cannot be used with a connection. " @@ -2124,8 +2128,8 @@ def test_auth_conflict(self): connection=mail.get_connection(), ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_using_connection_conflict(self): msg = "'connection' is not compatible with 'using'." with self.assertRaisesMessage(TypeError, msg): @@ -2138,8 +2142,8 @@ def test_using_connection_conflict(self): using="default", ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_using_fail_silently_conflict(self): msg = "'fail_silently' is not compatible with 'using'." with self.assertRaisesMessage(TypeError, msg): @@ -2152,8 +2156,8 @@ def test_using_fail_silently_conflict(self): using="default", ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_using_auth_conflict(self): msg = ( "'auth_user' and 'auth_password' are not compatible with 'using'. " @@ -2174,8 +2178,8 @@ def test_using_auth_conflict(self): ) -# RemovedInDjango70Warning: Move override_settings and additional test cases to -# SendMailTests and remove this class. +# RemovedInDjango2028Warning: Move override_settings and additional test cases +# to SendMailTests and remove this class. @override_settings( MAILERS={ "default": {"BACKEND": "django.core.mail.backends.locmem.EmailBackend"}, @@ -2229,18 +2233,20 @@ def test_sends_using_default_mailer(self): [("Subject1", "Content1", "from1@example.com", ["to1@example.com"])] ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if not mailers._is_configured: self.assertIsNone(mail.outbox[0].sent_using) return self.assertEqual(mail.outbox[0].sent_using, "default") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_connection_arg(self): # Send using non-default connection. connection = custombackend.EmailBackend() - with self.assertWarnsMessage(RemovedInDjango70Warning, CONNECTION_ARG_WARNING): + with self.assertWarnsMessage( + RemovedInDjango2028Warning, CONNECTION_ARG_WARNING + ): send_mass_mail( [ ("Subject1", "Content1", "from1@example.com", ["to1@example.com"]), @@ -2254,18 +2260,18 @@ def test_connection_arg(self): self.assertEqual(connection.test_outbox[1].subject, "Subject2") # Connection is provided to EmailMessage objects (#17811). with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message="The EmailMessage.connection attribute is deprecated.", ): self.assertIs(connection.test_outbox[0].connection, connection) self.assertIs(connection.test_outbox[1].connection, connection) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_auth_passed_to_backend_init(self): self.addCleanup(OptionsCapturingBackend.reset) with ( self.use_email_backend("mail.custombackend.OptionsCapturingBackend"), - self.assertWarnsMessage(RemovedInDjango70Warning, AUTH_ARGS_WARNING), + self.assertWarnsMessage(RemovedInDjango2028Warning, AUTH_ARGS_WARNING), ): send_mass_mail( [("Subject1", "Content1", "from1@example.com", ["to1@example.com"])], @@ -2277,13 +2283,13 @@ def test_auth_passed_to_backend_init(self): self.assertEqual(init_kwargs["username"], "user") self.assertEqual(init_kwargs["password"], "password") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_fail_silently_passed_to_backend_init(self): self.addCleanup(OptionsCapturingBackend.reset) with ( self.use_email_backend("mail.custombackend.OptionsCapturingBackend"), self.assertWarnsMessage( - RemovedInDjango70Warning, FAIL_SILENTLY_ARG_WARNING + RemovedInDjango2028Warning, FAIL_SILENTLY_ARG_WARNING ), ): send_mass_mail( @@ -2293,8 +2299,8 @@ def test_fail_silently_passed_to_backend_init(self): init_kwargs = OptionsCapturingBackend.init_kwargs[0] self.assertIs(init_kwargs["fail_silently"], True) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_send_fail_silently_conflict(self): datatuple = (("Subject", "Message", "from@example.com", ["to@example.com"]),) msg = ( @@ -2306,8 +2312,8 @@ def test_send_fail_silently_conflict(self): datatuple, fail_silently=True, connection=mail.get_connection() ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_send_auth_conflict(self): datatuple = (("Subject", "Message", "from@example.com", ["to@example.com"]),) msg = ( @@ -2323,8 +2329,8 @@ def test_send_auth_conflict(self): datatuple, **{param: "value"}, connection=mail.get_connection() ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_using_connection_conflict(self): msg = "'connection' is not compatible with 'using'." with self.assertRaisesMessage(TypeError, msg): @@ -2334,8 +2340,8 @@ def test_using_connection_conflict(self): using="default", ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_using_fail_silently_conflict(self): msg = "'fail_silently' is not compatible with 'using'." with self.assertRaisesMessage(TypeError, msg): @@ -2346,8 +2352,8 @@ def test_using_fail_silently_conflict(self): ) -# RemovedInDjango70Warning: Move override_settings and additional test cases to -# SendMassMailTests and remove this class. +# RemovedInDjango2028Warning: Move override_settings and additional test cases +# to SendMassMailTests and remove this class. @override_settings( MAILERS={ "default": {"BACKEND": "django.core.mail.backends.locmem.EmailBackend"}, @@ -2458,14 +2464,14 @@ def test_sends_using_default_mailer(self): with self.subTest(mail_func.__name__): mail_func("Subject", "Content") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. if not mailers._is_configured: self.assertIsNone(mail.outbox[0].sent_using) continue self.assertEqual(mail.outbox[0].sent_using, "default") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_deprecated_admins_managers_tuples(self): tests = ( [("nobody", "nobody@example.com"), ("other", "other@example.com")], @@ -2485,7 +2491,7 @@ def test_deprecated_admins_managers_tuples(self): self.subTest(setting=setting, value=value), self.settings(**{setting: value}), ): - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): mail_func("subject", "content") message = self.get_outbox_message() expected_to = ", ".join([str(address) for _, address in value]) @@ -2495,8 +2501,8 @@ def test_wrong_admins_managers(self): tests = ( "test@example.com", gettext_lazy("test@example.com"), - # RemovedInDjango70Warning: uncomment these cases when support for - # deprecated (name, address) tuples is removed. + # RemovedInDjango2028Warning: uncomment these cases when support + # for deprecated (name, address) tuples is removed. # [ # ("nobody", "nobody@example.com"), # ("other", "other@example.com") @@ -2523,43 +2529,47 @@ def test_wrong_admins_managers(self): with self.assertRaisesMessage(ImproperlyConfigured, msg): mail_func("subject", "content") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(ADMINS=["nobody@example.com"]) def test_connection_arg_mail_admins(self): # Send using non-default connection. connection = custombackend.EmailBackend() - with self.assertWarnsMessage(RemovedInDjango70Warning, CONNECTION_ARG_WARNING): + with self.assertWarnsMessage( + RemovedInDjango2028Warning, CONNECTION_ARG_WARNING + ): mail_admins("Admin message", "Content", connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, "[Django] Admin message") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(MANAGERS=["nobody@example.com"]) - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) def test_connection_arg_mail_managers(self): # Send using non-default connection. connection = custombackend.EmailBackend() - with self.assertWarnsMessage(RemovedInDjango70Warning, CONNECTION_ARG_WARNING): + with self.assertWarnsMessage( + RemovedInDjango2028Warning, CONNECTION_ARG_WARNING + ): mail_managers("Manager message", "Content", connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, "[Django] Manager message") - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(ADMINS=["admin@example.com"], MANAGERS=["manager@example.com"]) def test_fail_silently_deprecated(self): for mail_func in [mail_managers, mail_admins]: with ( self.subTest(mail_func=mail_func), self.assertWarnsMessage( - RemovedInDjango70Warning, FAIL_SILENTLY_ARG_WARNING + RemovedInDjango2028Warning, FAIL_SILENTLY_ARG_WARNING ), ): mail_func("Subject", "Content", fail_silently=True) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_mail_admins_fail_silently_conflict(self): msg = ( "fail_silently cannot be used with a connection. " @@ -2573,8 +2583,8 @@ def test_mail_admins_fail_silently_conflict(self): connection=mail.get_connection(), ) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_mail_managers_fail_silently_conflict(self): msg = ( "fail_silently cannot be used with a connection. " @@ -2589,8 +2599,8 @@ def test_mail_managers_fail_silently_conflict(self): ) -# RemovedInDjango70Warning: Move override_settings and additional test cases to -# MailAdminsAndManagersTests and remove this class. +# RemovedInDjango2028Warning: Move override_settings and additional test cases +# to MailAdminsAndManagersTests and remove this class. @override_settings( MAILERS={ "default": {"BACKEND": "django.core.mail.backends.locmem.EmailBackend"}, @@ -2608,8 +2618,8 @@ def test_using_arg(self): self.assertEqual(mail.outbox[0].sent_using, "custom") -# RemovedInDjango70Warning. -@ignore_warnings(category=RemovedInDjango70Warning) +# RemovedInDjango2028Warning. +@ignore_warnings(category=RemovedInDjango2028Warning) class GetConnectionTests(SimpleTestCase): """Tests for django.core.mail.get_connection().""" @@ -2618,7 +2628,7 @@ def test_deprecated(self): "get_connection() is deprecated. See 'Migrating email to mailers' " "in Django's documentation for recommended replacements." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): mail.get_connection() @override_settings(EMAIL_BACKEND="django.core.mail.backends.console.EmailBackend") @@ -2751,9 +2761,9 @@ def test_mailers_compatibility_no_default_mailer(self): mail.get_connection() -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class DeprecatedInternalsTests(SimpleTestCase): - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) @mock.patch("django.core.mail.message.MIMEText.set_payload") def test_nonascii_as_string_with_ascii_charset(self, mock_set_payload): """Line length check should encode the payload supporting @@ -2790,7 +2800,7 @@ def simplified_set_payload(instance, payload, charset): mock_set_payload.assert_called_once() self.assertEqual(message.get_payload(decode=True), text) - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) def test_sanitize_address(self): """Email addresses are properly sanitized.""" # Tests the internal sanitize_address() function. Many of these cases @@ -2885,7 +2895,7 @@ def test_sanitize_address(self): sanitize_address(email_address, encoding), expected_result ) - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) def test_sanitize_address_invalid(self): # Tests the internal sanitize_address() function. Note that Django's # EmailMessage.message() will not catch these cases, as it only calls @@ -2910,7 +2920,7 @@ def test_sanitize_address_invalid(self): with self.assertRaisesMessage(ValueError, "Invalid address"): sanitize_address(email_address, encoding="utf-8") - @ignore_warnings(category=RemovedInDjango70Warning) + @ignore_warnings(category=RemovedInDjango2028Warning) def test_sanitize_address_header_injection(self): # Tests the internal sanitize_address() function. These cases are # duplicated in test_address_header_handling(), which verifies headers @@ -2930,27 +2940,27 @@ def test_sanitize_address_header_injection(self): sanitize_address(email_address, encoding="utf-8") -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class MailDeprecatedPositionalArgsTests(SimpleTestCase): def get_connection(self, *args, **kwargs): with ( ignore_no_default_mailer_warning(), ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=re.escape("get_connection() is deprecated."), ), ): return mail.get_connection(*args, **kwargs) - def assertDeprecatedIn70(self, params, name): + def assertDeprecatedIn2028(self, params, name): return self.assertWarnsMessage( - RemovedInDjango70Warning, + RemovedInDjango2028Warning, f"Passing positional argument(s) {params} to {name}() is deprecated.", ) def test_get_connection(self): - with self.assertDeprecatedIn70("'fail_silently'", "get_connection"): + with self.assertDeprecatedIn2028("'fail_silently'", "get_connection"): self.get_connection( "django.core.mail.backends.dummy.EmailBackend", # Deprecated positional arg: @@ -2958,7 +2968,7 @@ def test_get_connection(self): ) def test_send_mail(self): - with self.assertDeprecatedIn70( + with self.assertDeprecatedIn2028( "'fail_silently', 'auth_user', 'auth_password', 'connection', " "'html_message'", "send_mail", @@ -2977,7 +2987,7 @@ def test_send_mail(self): ) def test_send_mass_mail(self): - with self.assertDeprecatedIn70( + with self.assertDeprecatedIn2028( "'fail_silently', 'auth_user', 'auth_password', 'connection'", "send_mass_mail", ): @@ -2991,7 +3001,7 @@ def test_send_mass_mail(self): ) def test_mail_admins(self): - with self.assertDeprecatedIn70( + with self.assertDeprecatedIn2028( "'fail_silently', 'connection', 'html_message'", "mail_admins" ): mail_admins( @@ -3004,7 +3014,7 @@ def test_mail_admins(self): ) def test_mail_managers(self): - with self.assertDeprecatedIn70( + with self.assertDeprecatedIn2028( "'fail_silently', 'connection', 'html_message'", "mail_managers" ): mail_managers( @@ -3017,7 +3027,7 @@ def test_mail_managers(self): ) def test_email_message_init(self): - with self.assertDeprecatedIn70( + with self.assertDeprecatedIn2028( "'bcc', 'connection', 'attachments', 'headers', 'cc', 'reply_to'", "EmailMessage", ): @@ -3036,7 +3046,7 @@ def test_email_message_init(self): ) def test_email_multi_alternatives_init(self): - with self.assertDeprecatedIn70( + with self.assertDeprecatedIn2028( "'bcc', 'connection', 'attachments', 'headers', 'alternatives', 'cc', " "'reply_to'", "EmailMultiAlternatives", @@ -3057,7 +3067,7 @@ def test_email_multi_alternatives_init(self): ) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. class PythonGlobalState(SimpleTestCase): """ Tests for #12422 -- Django smarts (#2472/#11212) with charset of utf-8 text @@ -3115,7 +3125,7 @@ def test_no_legacy_apis_imported(self): django_path = django_core_mail_path.parent.parent.parent for abs_path in django_core_mail_path.glob("**/*.py"): allowed_exceptions = self.allowed_exceptions.copy() - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. # The following will be removed after the deprecation period. if abs_path.name == "message.py": allowed_exceptions.update( diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py index 4996e339355c..f2092e10f1c7 100644 --- a/tests/middleware/tests.py +++ b/tests/middleware/tests.py @@ -503,7 +503,7 @@ def test_referer_equal_to_requested_url_without_trailing_slash_with_no_append_sl BrokenLinkEmailsMiddleware(self.get_response)(self.req) self.assertEqual(len(mail.outbox), 1) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_deprecated_email_settings( EMAIL_BACKEND="mail.custombackend.FailingEmailBackend" ) diff --git a/tests/model_fields/test_booleanfield.py b/tests/model_fields/test_booleanfield.py index 7b656b417687..33ffa4e72754 100644 --- a/tests/model_fields/test_booleanfield.py +++ b/tests/model_fields/test_booleanfield.py @@ -4,7 +4,7 @@ from django.db.models.utils import get_blank_choice_label from django.test import SimpleTestCase, TestCase from django.test.utils import ignore_warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import BooleanModel, FksToBooleans, NullBooleanModel @@ -93,10 +93,10 @@ def test_select_related(self): self.assertIs(ma.nbf.nbfield, True) # select_related() - # RemovedInDjango70Warning: when the deprecation ends, remove this part - # of the test. + # RemovedInDjango2028Warning: when the deprecation ends, remove this + # part of the test. with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): mb = FksToBooleans.objects.select_related().get(pk=m1.id) diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index 21365109efa8..163f01356c77 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -49,7 +49,7 @@ skipUnlessDBFeature, ) from django.test.utils import CaptureQueriesContext -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( CustomJSONDecoder, @@ -236,8 +236,8 @@ def test_null(self): self.assertIsNone(obj.value) @skipUnlessDBFeature("supports_primitives_in_json_field") - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_json_null_different_from_sql_null(self): json_null = NullableJSONModel.objects.create(value=Value(None, JSONField())) NullableJSONModel.objects.update(value=Value(None, JSONField())) @@ -251,7 +251,7 @@ def test_json_null_different_from_sql_null(self): ) self.assertSequenceEqual( NullableJSONModel.objects.filter(value=None), - # RemovedInDjango70Warning: When the deprecation ends, replace + # RemovedInDjango2028Warning: When the deprecation ends, replace # with: # [sql_null], [json_null], @@ -1475,7 +1475,7 @@ def test_custom_jsonnull_encoder(self): self.assertEqual(obj.value["array"], [1, None]) -# RemovedInDjango70Warning. +# RemovedInDjango2028Warning. @skipUnlessDBFeature("supports_primitives_in_json_field") class JSONExactNoneDeprecationTests(TestCase): @classmethod @@ -1488,7 +1488,7 @@ def setUpTestData(cls): cls.obj = NullableJSONModel.objects.create(value=JSONNull()) def test_filter(self): - with self.assertWarnsMessage(RemovedInDjango70Warning, self.msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, self.msg): self.assertSequenceEqual( NullableJSONModel.objects.filter(value=None), [self.obj] ) @@ -1497,12 +1497,12 @@ def test_annotation_q_filter(self): qs = NullableJSONModel.objects.annotate( has_empty_data=Q(value__isnull=True) | Q(value=None) ).filter(has_empty_data=True) - with self.assertWarnsMessage(RemovedInDjango70Warning, self.msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, self.msg): self.assertSequenceEqual(qs, [self.obj]) def test_case_when(self): qs = NullableJSONModel.objects.annotate( has_json_null=Case(When(value=None, then=Value(True)), default=Value(False)) ).filter(has_json_null=True) - with self.assertWarnsMessage(RemovedInDjango70Warning, self.msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, self.msg): self.assertSequenceEqual(qs, [self.obj]) diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py index fa7436343a11..097d4c9a34e1 100644 --- a/tests/model_fields/tests.py +++ b/tests/model_fields/tests.py @@ -6,7 +6,7 @@ from django.db import connection, models from django.test import SimpleTestCase, TestCase from django.utils.choices import CallableChoiceIterator -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.functional import lazy from .models import ( @@ -150,7 +150,7 @@ class MyModel(models.Model): self.assertEqual(field_hash, hash(field)) def test_get_placeholder_deprecation(self): - # RemovedInDjango70Warning: When the deprecation ends, remove + # RemovedInDjango2028Warning: When the deprecation ends, remove # completely. msg = ( "Field.get_placeholder is deprecated in favor of get_placeholder_sql. " @@ -158,14 +158,14 @@ def test_get_placeholder_deprecation(self): "test_get_placeholder_deprecation..SomeField.get_placeholder_sql " "to return both SQL and parameters instead." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): class SomeField(models.Field): def get_placeholder(self, value, compiler, connection): return "%s" def test_get_placeholder_sql_shim(self): - # RemovedInDjango70Warning: When the deprecation ends, remove + # RemovedInDjango2028Warning: When the deprecation ends, remove # completely. with warnings.catch_warnings(record=True): warnings.simplefilter("always") diff --git a/tests/model_inheritance_regress/tests.py b/tests/model_inheritance_regress/tests.py index ab4edea0acc7..056f3cdc3b01 100644 --- a/tests/model_inheritance_regress/tests.py +++ b/tests/model_inheritance_regress/tests.py @@ -10,7 +10,7 @@ from django.db.models import FETCH_PEERS from django.test import TestCase from django.test.utils import ignore_warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( ArticleWithAuthor, @@ -254,10 +254,10 @@ def test_issue_11764(self): """ Regression test for #11764 """ - # RemovedInDjango70Warning: when the deprecation ends, this test can + # RemovedInDjango2028Warning: when the deprecation ends, this test can # be removed. with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): wholesalers = list(Wholesaler.objects.select_related()) diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py index 40777d14589d..4e80e84923d0 100644 --- a/tests/modeladmin/test_checks.py +++ b/tests/modeladmin/test_checks.py @@ -1249,7 +1249,7 @@ class TestModelAdmin(ModelAdmin): self.assertIsInvalid( TestModelAdmin, ValidationTestModel, - # RemovedInDjango70Warning: when the deprecation ends, replace: + # RemovedInDjango2028Warning: when the deprecation ends, replace: # ... must be a tuple, list, or False.", "The value of 'list_select_related' must be a boolean, tuple or list.", "admin.E117", diff --git a/tests/modeladmin/tests.py b/tests/modeladmin/tests.py index 2b608954432b..27d02e9c26c2 100644 --- a/tests/modeladmin/tests.py +++ b/tests/modeladmin/tests.py @@ -22,7 +22,7 @@ from django.forms.widgets import Select from django.test import RequestFactory, SimpleTestCase, TestCase from django.test.utils import ignore_warnings, isolate_apps -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import Band, Concert, Song @@ -1033,19 +1033,19 @@ def test_list_select_related_true_deprecated(self): r"Setting ModelAdmin.list_select_related to True is deprecated. " r"Use False or a list or tuple of fields to fetch instead." ) - # RemovedInDjango70Warning: + # RemovedInDjango2028Warning: # with self.assertRaisesMessage(ValueError, msg) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg) as warning: + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as warning: class TestModelAdmin(ModelAdmin): list_select_related = True self.assertEqual(warning.filename, __file__) - # RemovedInDjango70Warning: when the deprecation ends, remove. + # RemovedInDjango2028Warning: when the deprecation ends, remove. def test_list_select_related_true_deprecated_subclass(self): with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Setting ModelAdmin.list_select_related to True is deprecated\.", ): @@ -1056,7 +1056,7 @@ class BaseTestModelAdmin(ModelAdmin): class TestModelAdmin(BaseTestModelAdmin): pass - # RemovedInDjango70Warning: when the deprecation ends, rename. + # RemovedInDjango2028Warning: when the deprecation ends, rename. def test_get_list_select_related_returns_true_deprecated(self): msg = ( "Returning True from ModelAdmin.get_list_select_related() is " @@ -1073,9 +1073,9 @@ def get_list_select_related(self, request): username="bob", email="bob@test.com", password="test" ) - # RemovedInDjango70Warning: + # RemovedInDjango2028Warning: # with self.assertRaisesMessage(ValueError, msg) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg) as warning: + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as warning: TestModelAdmin(Band, self.site).get_changelist_instance(request) self.assertEqual(warning.filename, __file__) diff --git a/tests/pagination/tests.py b/tests/pagination/tests.py index 267e1a5d84bd..4a35495ef771 100644 --- a/tests/pagination/tests.py +++ b/tests/pagination/tests.py @@ -15,7 +15,7 @@ UnorderedObjectListWarning, ) from django.test import SimpleTestCase, TestCase -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .custom import AsyncValidAdjacentNumsPaginator, ValidAdjacentNumsPaginator from .models import Article @@ -157,7 +157,7 @@ async def test_invalid_apage_number_async(self): await paginator.apage(3) def test_orphans_value_larger_than_per_page_value(self): - # RemovedInDjango70Warning: When the deprecation ends, replace with: + # RemovedInDjango2028Warning: When the deprecation ends, replace with: # msg = ( # "The orphans argument cannot be larger than or equal to the " # "per_page argument." @@ -165,15 +165,15 @@ def test_orphans_value_larger_than_per_page_value(self): msg = ( "Support for the orphans argument being larger than or equal to the " "per_page argument is deprecated. This will raise a ValueError in " - "Django 7.0." + "Django 2028." ) for paginator_class in [Paginator, AsyncPaginator]: for orphans in [2, 3]: with self.subTest(paginator_class=paginator_class, msg=msg): - # RemovedInDjango70Warning: When the deprecation ends, + # RemovedInDjango2028Warning: When the deprecation ends, # replace with: # with self.assertRaisesMessage(ValueError, msg): - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): paginator_class([1, 2, 3], 2, orphans) def test_error_messages(self): diff --git a/tests/postgres_tests/test_aggregates.py b/tests/postgres_tests/test_aggregates.py index bd57b8e3383c..b1cfbfcc185d 100644 --- a/tests/postgres_tests/test_aggregates.py +++ b/tests/postgres_tests/test_aggregates.py @@ -15,17 +15,17 @@ from django.db.models.functions import Cast, Concat, LPad, Substr from django.test.utils import Approximate from django.utils import timezone -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from . import PostgreSQLTestCase from .models import AggregateTestModel, HotelReservation, Room, StatTestModel try: - from django.contrib.postgres.aggregates import BitAnd # RemovedInDjango70Warning - from django.contrib.postgres.aggregates import BitOr # RemovedInDjango70Warning - from django.contrib.postgres.aggregates import BitXor # RemovedInDjango70Warning + from django.contrib.postgres.aggregates import BitAnd # RemovedInDjango2028Warning + from django.contrib.postgres.aggregates import BitOr # RemovedInDjango2028Warning + from django.contrib.postgres.aggregates import BitXor # RemovedInDjango2028Warning from django.contrib.postgres.aggregates import ( - StringAgg, # RemovedInDjango70Warning. + StringAgg, # RemovedInDjango2028Warning. ) from django.contrib.postgres.aggregates import ( ArrayAgg, @@ -566,11 +566,11 @@ def test_values_list(self): def test_string_agg_delimiter_deprecation(self): msg = ( "delimiter: str will be resolved as a field reference instead " - 'of a string literal on Django 7.0. Pass `delimiter=Value("\'")` to ' - "preserve the previous behavior." + 'of a string literal on Django 2028. Pass `delimiter=Value("\'")` ' + "to preserve the previous behavior." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg) as ctx: + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as ctx: values = AggregateTestModel.objects.aggregate( stringagg=StringAgg("char_field", delimiter="'") ) @@ -583,7 +583,7 @@ def test_string_agg_deprecation(self): "django.db.models.aggregates.StringAgg instead." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg) as ctx: + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as ctx: values = AggregateTestModel.objects.aggregate( stringagg=StringAgg("char_field", delimiter=Value("'")) ) @@ -599,7 +599,7 @@ def test_bit_agg_deprecation(self): ) with ( self.subTest(BitAggregate.__name__), - self.assertWarnsMessage(RemovedInDjango70Warning, msg) as ctx, + self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as ctx, ): AggregateTestModel.objects.aggregate( bitagg=BitAggregate("integer_field") diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py index b46166b53516..8d5b2d3bc406 100644 --- a/tests/postgres_tests/test_array.py +++ b/tests/postgres_tests/test_array.py @@ -16,7 +16,7 @@ from django.test import TransactionTestCase, override_settings, skipUnlessDBFeature from django.test.utils import isolate_apps from django.utils import timezone -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from . import PostgreSQLSimpleTestCase, PostgreSQLTestCase, PostgreSQLWidgetTestCase from .models import ( @@ -1586,14 +1586,14 @@ def test_saving_and_querying_for_sql_null(self): self.assertSequenceEqual( OtherTypesArrayModel.objects.filter(json__1__isnull=True), [obj] ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. msg = ( "Using None as the right-hand side of an exact lookup on JSONField to mean " "JSON scalar 'null' is deprecated. Use JSONNull() instead (or use the " "__isnull lookup if you meant SQL NULL)." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): - # RemovedInDjango70Warning: deindent, and replace [] with [obj]. + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): + # RemovedInDjango2028Warning: deindent, and replace [] with [obj]. self.assertSequenceEqual( OtherTypesArrayModel.objects.filter(json__1=None), [] ) diff --git a/tests/queries/test_sqlcompiler.py b/tests/queries/test_sqlcompiler.py index 5a456811a12f..2cbb7e86a8bc 100644 --- a/tests/queries/test_sqlcompiler.py +++ b/tests/queries/test_sqlcompiler.py @@ -4,7 +4,7 @@ from django.db.models.sql import Query from django.db.models.sql.compiler import SQLCompiler from django.test import TestCase -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import Item @@ -41,7 +41,7 @@ def test_execute_sql_suppresses_cursor_closing_failure_on_exception(self): self.assertIsNone(exc.__cause__) self.assertTrue(exc.__suppress_context__) - # RemovedInDjango70Warning: When the deprecation ends, remove this + # RemovedInDjango2028Warning: When the deprecation ends, remove this # test. def test_quote_name_unless_alias_deprecation(self): query = Query(Item) @@ -50,7 +50,7 @@ def test_quote_name_unless_alias_deprecation(self): "SQLCompiler.quote_name_unless_alias() is deprecated. " "Use .quote_name() instead." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg) as ctx: + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg) as ctx: self.assertEqual( compiler.quote_name_unless_alias("name"), compiler.quote_name("name"), diff --git a/tests/queries/tests.py b/tests/queries/tests.py index c987649fac25..b73275c51807 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -14,7 +14,7 @@ from django.db.models.sql.where import AND, OR, NothingNode, WhereNode from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature from django.test.utils import CaptureQueriesContext, ignore_warnings, register_lookup -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( FK1, @@ -2014,10 +2014,10 @@ def test_tickets_3045_3288(self): # infinitely if you forgot to specify "depth". Now we set an arbitrary # default upper bound. self.assertSequenceEqual(X.objects.all(), []) - # RemovedInDjango70Warning: when the deprecation ends, remove this test - # case. + # RemovedInDjango2028Warning: when the deprecation ends, remove this + # test case. with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): self.assertSequenceEqual(X.objects.select_related(), []) diff --git a/tests/select_related/tests.py b/tests/select_related/tests.py index 06faff4f4b40..47baaaa6642e 100644 --- a/tests/select_related/tests.py +++ b/tests/select_related/tests.py @@ -4,7 +4,7 @@ from django.db.models import FETCH_PEERS from django.test import SimpleTestCase, TestCase from django.test.utils import garbage_collect, ignore_warnings, requires_gil -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( Bookmark, @@ -111,12 +111,12 @@ def test_list_without_select_related(self): ], ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_list_with_select_related(self): """select_related() applies to entire lists, not just items.""" with self.assertNumQueries(1): with ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ): world = Species.objects.select_related() @@ -131,13 +131,13 @@ def test_list_with_select_related(self): ], ) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. def test_select_related_no_arguments_deprecated(self): msg = ( "Calling select_related() with no arguments is deprecated. " "Specify the fields to fetch instead." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): Species.objects.select_related() def test_list_with_depth(self): diff --git a/tests/select_related_onetoone/tests.py b/tests/select_related_onetoone/tests.py index 00025fcdca55..6ef414eaa2e5 100644 --- a/tests/select_related_onetoone/tests.py +++ b/tests/select_related_onetoone/tests.py @@ -2,7 +2,7 @@ from django.db.models import FilteredRelation from django.test import SimpleTestCase, TestCase from django.test.utils import ignore_warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import ( AdvancedUserStat, @@ -88,12 +88,12 @@ def test_back_and_forward(self): self.assertEqual(u.userstat.user.username, "test") def test_not_followed_by_default(self): - # RemovedInDjango70Warning: when the deprecation ends, remove this + # RemovedInDjango2028Warning: when the deprecation ends, remove this # test. with ( self.assertNumQueries(2), ignore_warnings( - category=RemovedInDjango70Warning, + category=RemovedInDjango2028Warning, message=r"Calling select_related\(\) with no arguments is deprecated\.", ), ): diff --git a/tests/signed_cookies_tests/tests.py b/tests/signed_cookies_tests/tests.py index 279da5ea59c3..c0caf9c8fdf9 100644 --- a/tests/signed_cookies_tests/tests.py +++ b/tests/signed_cookies_tests/tests.py @@ -4,7 +4,7 @@ from django.http import HttpRequest, HttpResponse from django.test import SimpleTestCase, override_settings from django.test.utils import freeze_time, ignore_warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning class SignedCookieTest(SimpleTestCase): @@ -36,8 +36,8 @@ def test_salt_namespace_is_unambiguous(self): with self.assertRaises(signing.BadSignature): request.get_signed_cookie("ab", salt="c") - # RemovedInDjango70Warning: When the deprecation ends, remove this test. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning: When the deprecation ends, remove this test. + @ignore_warnings(category=RemovedInDjango2028Warning) @override_settings(SIGNED_COOKIE_LEGACY_SALT_FALLBACK=True) def test_expired_legacy_cookie_raises_signature_expired(self): with freeze_time(123456789): @@ -49,8 +49,8 @@ def test_expired_legacy_cookie_raises_signature_expired(self): with self.assertRaises(signing.SignatureExpired): request.get_signed_cookie("a", salt="bc", max_age=10) - # RemovedInDjango70Warning: When the deprecation ends, remove this test. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning: When the deprecation ends, remove this test. + @ignore_warnings(category=RemovedInDjango2028Warning) @override_settings(SIGNED_COOKIE_LEGACY_SALT_FALLBACK=True) def test_legacy_salt_namespace_is_accepted(self): request = HttpRequest() @@ -62,7 +62,7 @@ def test_legacy_salt_namespace_is_accepted(self): # No protection since SIGNED_COOKIE_LEGACY_SALT_FALLBACK=True. self.assertEqual(request.get_signed_cookie("ab", salt="c"), "hello") - # RemovedInDjango70Warning: When the deprecation ends, remove this test. + # RemovedInDjango2028Warning: When the deprecation ends, remove this test. def test_legacy_salt_namespace_not_accepted(self): request = HttpRequest() request.COOKIES["a"] = signing.get_cookie_signer( @@ -71,8 +71,8 @@ def test_legacy_salt_namespace_not_accepted(self): with self.assertRaises(signing.BadSignature): request.get_signed_cookie("a", salt="bc") - # RemovedInDjango70Warning: When the deprecation ends, remove this test. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning: When the deprecation ends, remove this test. + @ignore_warnings(category=RemovedInDjango2028Warning) @override_settings(SIGNED_COOKIE_LEGACY_SALT_FALLBACK=True) def test_expired_new_style_cookie_does_not_fallback_to_legacy_salt(self): with freeze_time(123456789): diff --git a/tests/signing/tests.py b/tests/signing/tests.py index 963e8db52b57..28519c0c2a96 100644 --- a/tests/signing/tests.py +++ b/tests/signing/tests.py @@ -4,7 +4,7 @@ from django.test import SimpleTestCase, override_settings from django.test.utils import freeze_time from django.utils.crypto import InvalidAlgorithm -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning class TestSigner(SimpleTestCase): @@ -47,10 +47,10 @@ def test_signature_with_salt(self): def test_base64_hmac_default_algorithm_deprecation(self): msg = ( "The default argument for algorithm in base64_hmac() will change " - "from 'sha1' to 'sha256' in Django 7.0. Pass an explicit " + "from 'sha1' to 'sha256' in Django 2028. Pass an explicit " "algorithm to silence this warning." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): signing.base64_hmac("salt", "value", "key") def test_custom_algorithm(self): diff --git a/tests/template_tests/syntax_tests/test_basic.py b/tests/template_tests/syntax_tests/test_basic.py index fe43e907f330..6f0ce2eaccad 100644 --- a/tests/template_tests/syntax_tests/test_basic.py +++ b/tests/template_tests/syntax_tests/test_basic.py @@ -3,7 +3,7 @@ from django.template.context import Context from django.template.loader_tags import BlockContext, BlockNode from django.test import SimpleTestCase, ignore_warnings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.views.debug import ExceptionReporter from ..utils import SilentAttrClass, SilentGetItemClass, SomeClass, setup @@ -416,12 +416,12 @@ def test_double_dot_lookup(self): for debug in [True, False]: with self.subTest(debug=debug): engine = Engine(loaders=loaders, debug=debug) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): engine.render_to_string("template", {}) # Cached loader results in warning only on first access. engine.render_to_string("template", {}) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. # Replace the above test with the following. # @setup({"template": "{{ doubledot..lookup }}"}) # def test_double_dot_lookup(self): @@ -483,8 +483,8 @@ def test_unknown_source_template(self): self.assertEqual(str(e), self.template_error_msg) -# RemovedInDjango70Warning -@ignore_warnings(category=RemovedInDjango70Warning) +# RemovedInDjango2028Warning +@ignore_warnings(category=RemovedInDjango2028Warning) class DeprecatedTests(SimpleTestCase): @setup({"template": "{{ doubledot..lookup }}"}) def test_double_dot_lookup(self): diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py index 3a388cc74018..3f392b308823 100644 --- a/tests/test_utils/tests.py +++ b/tests/test_utils/tests.py @@ -53,7 +53,7 @@ teardown_test_environment, ) from django.urls import NoReverseMatch, path, reverse, reverse_lazy -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.html import VOID_ELEMENTS from .models import Car, Person, PossessedCar @@ -1844,8 +1844,8 @@ def test_allowed_hosts(self): setup_test_environment() self.assertEqual(settings.ALLOWED_HOSTS, ["*", "testserver"]) - # RemovedInDjango70Warning. - @ignore_warnings(category=RemovedInDjango70Warning) + # RemovedInDjango2028Warning. + @ignore_warnings(category=RemovedInDjango2028Warning) def test_email_backend_override(self): with ( self.mock_test_state(), @@ -1892,7 +1892,7 @@ def test_mailers_override(self): ) # setup_test_environment() shouldn't mutate original setting value. self.assertEqual(settings_value, expected_value) - # RemovedInDjango70Warning: Remove both EMAIL_BACKEND assertions. + # RemovedInDjango2028Warning: Remove both EMAIL_BACKEND assertions. self.assertFalse(hasattr(settings, "EMAIL_BACKEND")) teardown_test_environment() diff --git a/tests/transactions/tests.py b/tests/transactions/tests.py index 0baeca29e605..0438a798bd1e 100644 --- a/tests/transactions/tests.py +++ b/tests/transactions/tests.py @@ -18,7 +18,7 @@ skipIfDBFeature, skipUnlessDBFeature, ) -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from .models import Reporter @@ -596,5 +596,5 @@ class DurableTests(DurableTestsBase, TestCase): class SavepointTests(SimpleTestCase): def test_deprecation_warning(self): msg = "savepoint() is deprecated. Use savepoint_create() instead." - with self.assertRaisesMessage(RemovedInDjango70Warning, msg): + with self.assertRaisesMessage(RemovedInDjango2028Warning, msg): transaction.savepoint() diff --git a/tests/utils_tests/test_crypto.py b/tests/utils_tests/test_crypto.py index 61d9bb047896..1d7a1959a13f 100644 --- a/tests/utils_tests/test_crypto.py +++ b/tests/utils_tests/test_crypto.py @@ -8,7 +8,7 @@ pbkdf2, salted_hmac, ) -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning class TestUtilsCryptoMisc(SimpleTestCase): @@ -47,7 +47,7 @@ def test_salted_hmac(self): ), ( ("salt", "value"), - # RemovedInDjango70Warning: Remove the explicit algorithm to + # RemovedInDjango2028Warning: Remove the explicit algorithm to # test the new default value. {"algorithm": "sha256"}, "ee0bf789e4e009371a5372c90f73fcf17695a8439c9108b0480f14e347b3f9ec", @@ -70,10 +70,10 @@ def test_salted_hmac(self): def test_salted_hmac_default_algorithm_deprecation(self): msg = ( "The default argument for algorithm in salted_hmac() will change " - "from 'sha1' to 'sha256' in Django 7.0. Pass an explicit " + "from 'sha1' to 'sha256' in Django 2028. Pass an explicit " "algorithm to silence this warning." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): salted_hmac("salt", "value") def test_invalid_algorithm(self): diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py index ee115aaf1cf2..24d27586d7bc 100644 --- a/tests/utils_tests/test_html.py +++ b/tests/utils_tests/test_html.py @@ -7,7 +7,7 @@ from django.core.serializers.json import DjangoJSONEncoder from django.test import SimpleTestCase from django.test.utils import override_settings -from django.utils.deprecation import RemovedInDjango70Warning +from django.utils.deprecation import RemovedInDjango2028Warning from django.utils.functional import lazystr from django.utils.html import ( conditional_escape, @@ -485,11 +485,11 @@ def test_urlize(self): @override_settings(URLIZE_ASSUME_HTTPS=False) def test_urlize_http_default_warning(self): msg = ( - "The default protocol will be changed from HTTP to HTTPS in Django 7.0. " - "Set the URLIZE_ASSUME_HTTPS transitional setting to True to opt into " - "using HTTPS as the new default protocol." + "The default protocol will be changed from HTTP to HTTPS in " + "Django 2028. Set the URLIZE_ASSUME_HTTPS transitional setting to " + "True to opt into using HTTPS as the new default protocol." ) - with self.assertWarnsMessage(RemovedInDjango70Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2028Warning, msg): self.assertEqual( urlize("Visit example.com"), 'Visit example.com', diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py index 2b6477613769..39214abcfb18 100644 --- a/tests/view_tests/tests/test_debug.py +++ b/tests/view_tests/tests/test_debug.py @@ -498,7 +498,7 @@ def test_template_override_exception_reporter(self): response = self.client.get("/raises500/", headers={"accept": "text/plain"}) self.assertContains(response, "Oh dear, an error occurred!", status_code=500) - # RemovedInDjango70Warning. + # RemovedInDjango2028Warning. @override_settings(MAILERS={}) def test_works_with_mailers_defined(self): with self.assertLogs("django.request", "ERROR"): From 52abe52bec23df6523aff492364f4f1b049c9572 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 20 Aug 2026 13:13:59 +0200 Subject: [PATCH 2/3] Fixed #37293 -- Renamed RemovedInDjango71Warning to RemovedInDjango2029Warning. Per DEP 20, Django's version numbers are calendar-based from 2028, so deprecation warning classes are now named after the calendar version that removes the feature they mark, and the deprecation timeline is headed by the same calendar version. Updated references to RemovedInDjango71Warning to use the new warning, and adjusted references to "Django 7.1" to "Django 2029". --- django/db/models/query.py | 10 +++++----- django/http/response.py | 10 +++++----- django/utils/deprecation.py | 6 +++--- docs/internals/deprecation.txt | 6 +++--- docs/releases/6.2.txt | 2 +- tests/async/test_async_queryset.py | 6 +++--- tests/deprecation/test_middleware_mixin.py | 4 ++-- tests/httpwrappers/tests.py | 6 +++--- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/django/db/models/query.py b/django/db/models/query.py index 2d3f520e27b8..bc881fced9e2 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -47,8 +47,8 @@ ) from django.utils import timezone from django.utils.deprecation import ( - RemovedInDjango71Warning, RemovedInDjango2028Warning, + RemovedInDjango2029Warning, warn_about_external_use, ) from django.utils.functional import cached_property @@ -632,7 +632,7 @@ async def aiterator(self, chunk_size=None): """ if chunk_size is None: if self._prefetch_related_lookups: - # RemovedInDjango71Warning: Replace the warning with: + # RemovedInDjango2029Warning: Replace the warning with: # raise ValueError( # "chunk_size must be provided when using " # "QuerySet.aiterator() after prefetch_related()." @@ -640,11 +640,11 @@ async def aiterator(self, chunk_size=None): warnings.warn( "Using QuerySet.aiterator() after prefetch_related() without " "providing a chunk_size is deprecated and will raise a " - "ValueError in Django 7.1.", - category=RemovedInDjango71Warning, + "ValueError in Django 2029.", + category=RemovedInDjango2029Warning, skip_file_prefixes=django_file_prefixes(), ) - # RemovedInDjango71Warning: When the deprecation ends, remove. + # RemovedInDjango2029Warning: Remove when the deprecation ends. chunk_size = 2000 elif chunk_size <= 0: raise ValueError("Chunk size must be strictly positive.") diff --git a/django/http/response.py b/django/http/response.py index c4ed51206089..b1d70b4047b4 100644 --- a/django/http/response.py +++ b/django/http/response.py @@ -20,7 +20,7 @@ from django.http.cookie import SimpleCookie from django.utils import timezone from django.utils.datastructures import CaseInsensitiveMapping -from django.utils.deprecation import RemovedInDjango71Warning +from django.utils.deprecation import RemovedInDjango2029Warning from django.utils.encoding import iri_to_uri from django.utils.functional import cached_property from django.utils.http import ( @@ -757,22 +757,22 @@ def __init__( self, data, encoder=DjangoJSONEncoder, - # RemovedInDjango71Warning: Remove the safe parameter from here and + # RemovedInDjango2029Warning: Remove the safe parameter from here and # the docstring. safe=None, json_dumps_params=None, **kwargs, ): - # RemovedInDjango71Warning. + # RemovedInDjango2029Warning. if safe is None: safe = False else: warnings.warn( "The safe parameter is deprecated.", - category=RemovedInDjango71Warning, + category=RemovedInDjango2029Warning, skip_file_prefixes=django_file_prefixes(), ) - # RemovedInDjango71Warning. + # RemovedInDjango2029Warning. if safe and not isinstance(data, dict): raise TypeError( "In order to allow non-dict objects to be serialized set the " diff --git a/django/utils/deprecation.py b/django/utils/deprecation.py index 48e2a9cb8f46..63fbe5088b72 100644 --- a/django/utils/deprecation.py +++ b/django/utils/deprecation.py @@ -14,12 +14,12 @@ class RemovedInDjango2028Warning(DeprecationWarning): pass -class RemovedInDjango71Warning(PendingDeprecationWarning): +class RemovedInDjango2029Warning(PendingDeprecationWarning): pass RemovedInNextVersionWarning = RemovedInDjango2028Warning -RemovedAfterNextVersionWarning = RemovedInDjango71Warning +RemovedAfterNextVersionWarning = RemovedInDjango2029Warning def __getattr__(name): @@ -27,7 +27,7 @@ def __getattr__(name): warnings.warn( "Importing MiddlewareMixin from django.utils.deprecation is deprecated. " "Import from django.middleware.MiddlewareMixin instead.", - RemovedInDjango71Warning, + RemovedInDjango2029Warning, stacklevel=2, ) return _MiddlewareMixin diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index fc63c0dc35da..12e45ba9bd98 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -7,10 +7,10 @@ in a backward incompatible way, following their deprecation, as per the :ref:`deprecation policy `. More details about each item can often be found in the release notes of two versions prior. -.. _deprecation-removed-in-7.1: +.. _deprecation-removed-in-2029: -7.1 ---- +2029 +---- See the :ref:`Django 6.2 release notes ` for more details on these changes. diff --git a/docs/releases/6.2.txt b/docs/releases/6.2.txt index e93d4f2602ec..f366db6e3cda 100644 --- a/docs/releases/6.2.txt +++ b/docs/releases/6.2.txt @@ -353,4 +353,4 @@ Miscellaneous * Calling :meth:`.QuerySet.aiterator` after ``prefetch_related()`` without providing a ``chunk_size`` is deprecated. It currently falls back to a ``chunk_size`` of 2000, but a ``ValueError`` will be raised in - Django 7.1. + Django 2029. diff --git a/tests/async/test_async_queryset.py b/tests/async/test_async_queryset.py index f04127470155..69a606112f74 100644 --- a/tests/async/test_async_queryset.py +++ b/tests/async/test_async_queryset.py @@ -7,7 +7,7 @@ from django.db import NotSupportedError, connection from django.db.models import Prefetch, Sum from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature -from django.utils.deprecation import RemovedInDjango71Warning +from django.utils.deprecation import RemovedInDjango2029Warning from .models import RelatedModel, SimpleModel @@ -66,7 +66,7 @@ async def test_aiterator_prefetch_related_chunk_size_none(self): ) qs = SimpleModel.objects.prefetch_related("relatedmodel_set").aiterator() - # RemovedInDjango71Warning: When the deprecation ends, replace with: + # RemovedInDjango2029Warning: When the deprecation ends, replace with: # with self.assertRaisesMessage( # ValueError, # "chunk_size must be provided when using QuerySet.aiterator() " @@ -75,7 +75,7 @@ async def test_aiterator_prefetch_related_chunk_size_none(self): # async for _ in qs: # pass results = [] - with self.assertWarnsMessage(RemovedInDjango71Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2029Warning, msg): async for s in qs: results.append(s) self.assertCountEqual(results, [self.s1, self.s2, self.s3]) diff --git a/tests/deprecation/test_middleware_mixin.py b/tests/deprecation/test_middleware_mixin.py index c18b58e08bad..1dfaedc49b58 100644 --- a/tests/deprecation/test_middleware_mixin.py +++ b/tests/deprecation/test_middleware_mixin.py @@ -30,7 +30,7 @@ from django.middleware.locale import LocaleMiddleware from django.middleware.security import SecurityMiddleware from django.test import SimpleTestCase -from django.utils.deprecation import RemovedInDjango71Warning +from django.utils.deprecation import RemovedInDjango2029Warning class MiddlewareMixinTests(SimpleTestCase): @@ -61,7 +61,7 @@ def test_deprecation_import_compatibility(self): "Importing MiddlewareMixin from django.utils.deprecation is deprecated. " "Import from django.middleware.MiddlewareMixin instead." ) - with self.assertWarnsMessage(RemovedInDjango71Warning, msg): + with self.assertWarnsMessage(RemovedInDjango2029Warning, msg): from django.utils.deprecation import ( MiddlewareMixin as DeprecatedMiddlewareMixin, ) diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py index e2eb9af30f8c..5e57d372a03b 100644 --- a/tests/httpwrappers/tests.py +++ b/tests/httpwrappers/tests.py @@ -24,7 +24,7 @@ parse_cookie, ) from django.test import SimpleTestCase -from django.utils.deprecation import RemovedInDjango71Warning +from django.utils.deprecation import RemovedInDjango2029Warning from django.utils.encoding import iri_to_uri from django.utils.functional import lazystr from django.utils.http import MAX_URL_REDIRECT_LENGTH @@ -704,7 +704,7 @@ def test_json_response_non_ascii(self): response = JsonResponse(data) self.assertEqual(json.loads(response.text), data) - # RemovedInDjango71Warning: When the deprecation ends, remove this test. + # RemovedInDjango2029Warning: When the deprecation ends, remove this test. def test_json_response_raises_type_error_with_safe_arg(self): with ( self.assertRaisesMessage( @@ -713,7 +713,7 @@ def test_json_response_raises_type_error_with_safe_arg(self): "safe parameter to False", ), self.assertWarnsMessage( - RemovedInDjango71Warning, "The safe parameter is deprecated." + RemovedInDjango2029Warning, "The safe parameter is deprecated." ), ): JsonResponse([1, 2, 3], safe=True) From 026b005f3dc43a98557ce5a546b5e4938d06fed1 Mon Sep 17 00:00:00 2001 From: Natalia <124304+nessita@users.noreply.github.com> Date: Wed, 2 Sep 2026 23:10:47 -0300 Subject: [PATCH 3/3] Refs #37293 -- Updated deprecation docs for calendar-based warning names. --- django/utils/deprecation.py | 8 +++--- .../writing-code/submitting-patches.txt | 26 +++++++++---------- tests/deprecation/test_deprecate_posargs.py | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/django/utils/deprecation.py b/django/utils/deprecation.py index 63fbe5088b72..17bad6fe6b9b 100644 --- a/django/utils/deprecation.py +++ b/django/utils/deprecation.py @@ -246,7 +246,7 @@ def deprecate_posargs(deprecation_warning, remappable_names, /): The decorated function will map any positional arguments after the ``*`` to the corresponding keyword arguments and issue a deprecation warning. - The decorator takes two arguments: a RemovedInDjangoXXWarning warning + The decorator takes two arguments: a RemovedInDjangoXXXXWarning warning category and a list of parameter names that have been changed from positional-or-keyword to keyword-only, in their original positional order. @@ -261,7 +261,7 @@ def some_func(request, option1, option2=True): to:: - @deprecate_posargs(RemovedInDjangoXXWarning, ["option1", "option2"]) + @deprecate_posargs(RemovedInDjangoXXXXWarning, ["option1", "option2"]) def some_func(request, *, option1, option2=True): ... @@ -274,7 +274,7 @@ def some_func(request, *, option1, option2=True): parameters or change the remaining ones. For example, this attempt to add a new param would break code using the deprecated posargs:: - @deprecate_posargs(RemovedInDjangoXXWarning, ["option1", "option2"]) + @deprecate_posargs(RemovedInDjangoXXXXWarning, ["option1", "option2"]) def some_func(request, wrong_new_param=None, *, option1, option2=True): # Broken: existing code may pass a value intended as option1 in the # wrong_new_param position. @@ -285,7 +285,7 @@ def some_func(request, wrong_new_param=None, *, option1, option2=True): @deprecate_posargs is kept in the original posargs order. This change will work without breaking existing code:: - @deprecate_posargs(RemovedInDjangoXXWarning, ["option1", "option2"]) + @deprecate_posargs(RemovedInDjangoXXXXWarning, ["option1", "option2"]) def some_func(request, *, new_param=None, option2=True, option1): ... diff --git a/docs/internals/contributing/writing-code/submitting-patches.txt b/docs/internals/contributing/writing-code/submitting-patches.txt index 9bf9c534ff92..f3c128716aa4 100644 --- a/docs/internals/contributing/writing-code/submitting-patches.txt +++ b/docs/internals/contributing/writing-code/submitting-patches.txt @@ -300,11 +300,11 @@ There are a couple of reasons that code in Django might be deprecated: As the :ref:`deprecation policy` describes, the first release of Django that deprecates a feature (``A.B``) -should raise a ``RemovedInDjangoXXWarning`` (where XX is the Django version +should raise a ``RemovedInDjangoXXXXWarning`` (where XXXX is the Django version where the feature will be removed) when the deprecated feature is invoked. Assuming we have good test coverage, these warnings are converted to errors when :ref:`running the test suite ` with warnings enabled: -``python -Wa runtests.py``. Thus, when adding a ``RemovedInDjangoXXWarning`` +``python -Wa runtests.py``. Thus, when adding a ``RemovedInDjangoXXXXWarning`` you need to eliminate or silence any warnings generated when running the tests. The first step is to remove any use of the deprecated behavior by Django @@ -315,45 +315,45 @@ test or class level: #) In a particular test:: from django.test import ignore_warnings - from django.utils.deprecation import RemovedInDjangoXXWarning + from django.utils.deprecation import RemovedInDjangoXXXXWarning - @ignore_warnings(category=RemovedInDjangoXXWarning) + @ignore_warnings(category=RemovedInDjangoXXXXWarning) def test_foo(self): ... #) For an entire test case:: from django.test import ignore_warnings - from django.utils.deprecation import RemovedInDjangoXXWarning + from django.utils.deprecation import RemovedInDjangoXXXXWarning - @ignore_warnings(category=RemovedInDjangoXXWarning) + @ignore_warnings(category=RemovedInDjangoXXXXWarning) class MyDeprecatedTests(unittest.TestCase): ... You should also add a test for the deprecation warning:: - from django.utils.deprecation import RemovedInDjangoXXWarning + from django.utils.deprecation import RemovedInDjangoXXXXWarning def test_foo_deprecation_warning(self): msg = "Expected deprecation message" - with self.assertWarnsMessage(RemovedInDjangoXXWarning, msg) as ctx: + with self.assertWarnsMessage(RemovedInDjangoXXXXWarning, msg) as ctx: # invoke deprecated behavior ... self.assertEqual(ctx.filename, __file__) -It's important to include a ``RemovedInDjangoXXWarning`` comment above code +It's important to include a ``RemovedInDjangoXXXXWarning`` comment above code which has no warning reference, but will need to be changed or removed when the deprecation ends. This could include hooks which have been added to keep the previous behavior, or standalone items that are unnecessary or unused when the deprecation ends. For example:: import warnings - from django.utils.deprecation import RemovedInDjangoXXWarning + from django.utils.deprecation import RemovedInDjangoXXXXWarning from django.utils.warnings import django_file_prefixes - # RemovedInDjangoXXWarning. + # RemovedInDjangoXXXXWarning. def old_private_helper(): # Helper function that is only used in foo(). pass @@ -362,7 +362,7 @@ deprecation ends. For example:: def foo(): warnings.warn( "foo() is deprecated.", - category=RemovedInDjangoXXWarning, + category=RemovedInDjangoXXXXWarning, skip_file_prefixes=django_file_prefixes(), ) old_private_helper() @@ -384,7 +384,7 @@ Finally, there are a couple of updates to Django's documentation to make: Once you have completed these steps, you are finished with the deprecation. In each :term:`feature release `, all -``RemovedInDjangoXXWarning``\s matching the new version are removed. +``RemovedInDjangoXXXXWarning``\s matching the new version are removed. The ``django.utils.deprecation`` module provides some helpful deprecation utilities, such as a ``@deprecate_posargs`` decorator to assist with converting diff --git a/tests/deprecation/test_deprecate_posargs.py b/tests/deprecation/test_deprecate_posargs.py index 8c70d5d20587..a6e2b61eb4e4 100644 --- a/tests/deprecation/test_deprecate_posargs.py +++ b/tests/deprecation/test_deprecate_posargs.py @@ -13,7 +13,7 @@ class DeprecatePosargsTests(SimpleTestCase): # Note: these tests use the generic RemovedAfterNextVersionWarning so they # don't need to be updated each release. In actual use, you must substitute - # a specific RemovedInDjangoXXWarning. + # a specific RemovedInDjangoXXXXWarning. def assertDeprecated(self, params, name): msg = (