Fixed #35090 -- Deprecated registering URL converters with the same name.

This commit is contained in:
Salvo Polizzi 2024-02-22 12:04:03 +01:00 committed by Mariusz Felisiak
parent 50e95ad536
commit 6e1ece7ed5
6 changed files with 61 additions and 2 deletions

View File

@ -1,5 +1,8 @@
import functools
import uuid
import warnings
from django.utils.deprecation import RemovedInDjango60Warning
class IntConverter:
@ -53,6 +56,15 @@ REGISTERED_CONVERTERS = {}
def register_converter(converter, type_name):
if type_name in REGISTERED_CONVERTERS or type_name in DEFAULT_CONVERTERS:
# RemovedInDjango60Warning: when the deprecation ends, replace with
# raise ValueError(f"Converter {type_name} is already registered.")
warnings.warn(
f"Converter {type_name!r} is already registered. Support for overriding "
"registered converters is deprecated and will be removed in Django 6.0.",
RemovedInDjango60Warning,
stacklevel=2,
)
REGISTERED_CONVERTERS[type_name] = converter()
get_converters.cache_clear()

View File

@ -74,6 +74,9 @@ details on these changes.
* The setter for ``django.contrib.gis.gdal.OGRGeometry.coord_dim`` will be
removed.
* ``django.urls.register_converter()`` will no longer allow overriding existing
converters.
.. _deprecation-removed-in-5.1:
5.1

View File

@ -120,6 +120,10 @@ The ``converter`` argument is a converter class, and ``type_name`` is the
converter name to use in path patterns. See
:ref:`registering-custom-path-converters` for an example.
.. deprecated:: 5.1
Overriding existing converters is deprecated.
==================================================
``django.conf.urls`` functions for use in URLconfs
==================================================

View File

@ -419,6 +419,9 @@ Miscellaneous
* Setting ``django.contrib.gis.gdal.OGRGeometry.coord_dim`` is deprecated. Use
:meth:`~django.contrib.gis.gdal.OGRGeometry.set_3d` instead.
* Overriding existing converters with ``django.urls.register_converter()`` is
deprecated.
Features removed in 5.1
=======================

View File

@ -183,6 +183,11 @@ Register custom converter classes in your URLconf using
...,
]
.. deprecated:: 5.1
Overriding existing converters with ``django.urls.register_converter()`` is
deprecated.
Using regular expressions
=========================

View File

@ -4,10 +4,20 @@ import uuid
from django.core.exceptions import ImproperlyConfigured
from django.test import SimpleTestCase
from django.test.utils import override_settings
from django.urls import NoReverseMatch, Resolver404, path, re_path, resolve, reverse
from django.urls import (
NoReverseMatch,
Resolver404,
path,
re_path,
register_converter,
resolve,
reverse,
)
from django.urls.converters import IntConverter
from django.utils.deprecation import RemovedInDjango60Warning
from django.views import View
from .converters import DynamicConverter
from .converters import Base64Converter, DynamicConverter
from .views import empty_view
included_kwargs = {"base": b"hello", "value": b"world"}
@ -193,6 +203,28 @@ class SimplifiedURLTests(SimpleTestCase):
with self.assertRaisesMessage(ImproperlyConfigured, msg):
path("foo/<nonexistent:var>/", empty_view)
def test_warning_override_default_converter(self):
# RemovedInDjango60Warning: when the deprecation ends, replace with
# msg = "Converter 'int' is already registered."
# with self.assertRaisesMessage(ValueError, msg):
msg = (
"Converter 'int' is already registered. Support for overriding registered "
"converters is deprecated and will be removed in Django 6.0."
)
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
register_converter(IntConverter, "int")
def test_warning_override_converter(self):
# RemovedInDjango60Warning: when the deprecation ends, replace with
# msg = "Converter 'base64' is already registered."
# with self.assertRaisesMessage(ValueError, msg):
msg = (
"Converter 'base64' is already registered. Support for overriding "
"registered converters is deprecated and will be removed in Django 6.0."
)
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
register_converter(Base64Converter, "base64")
def test_invalid_view(self):
msg = "view must be a callable or a list/tuple in the case of include()."
with self.assertRaisesMessage(TypeError, msg):