Fixed #34691 -- Added system check for unmatched angle brackets in path().

This commit is contained in:
Amir Karimi 2023-07-04 17:09:09 +03:30 committed by Mariusz Felisiak
parent 2ddfa3e2b6
commit d1855c4847
6 changed files with 89 additions and 1 deletions

View File

@ -62,6 +62,7 @@ answer newbie questions, and generally made Django that much better:
Aljaž Košir <aljazkosir5@gmail.com>
Aljosa Mohorovic <aljosa.mohorovic@gmail.com>
Alokik Vijay <alokik.roe@gmail.com>
Amir Karimi <amk9978@gmail.com>
Amit Chakradeo <https://amit.chakradeo.net/>
Amit Ramon <amit.ramon@gmail.com>
Amit Upadhyay <http://www.amitu.com/blog/>

View File

@ -318,7 +318,10 @@ class RoutePattern(CheckURLMixin):
return None
def check(self):
warnings = self._check_pattern_startswith_slash()
warnings = [
*self._check_pattern_startswith_slash(),
*self._check_pattern_unmatched_angle_brackets(),
]
route = self._route
if "(?P<" in route or route.startswith("^") or route.endswith("$"):
warnings.append(
@ -331,6 +334,34 @@ class RoutePattern(CheckURLMixin):
)
return warnings
def _check_pattern_unmatched_angle_brackets(self):
warnings = []
segments = self._route.split("/")
for segment in segments:
open_bracket_counter = 0
unmatched_angle_bracket = None
for char in segment:
if char == "<":
open_bracket_counter += 1
elif char == ">":
open_bracket_counter -= 1
if open_bracket_counter < 0:
unmatched_angle_bracket = ">"
break
else:
if open_bracket_counter > 0:
unmatched_angle_bracket = "<"
if unmatched_angle_bracket is not None:
warnings.append(
Warning(
"Your URL pattern %s has an unmatched '%s' bracket."
% (self.describe(), unmatched_angle_bracket),
id="urls.W010",
)
)
return warnings
def _compile(self, route):
return re.compile(_route_to_regex(route, self._is_endpoint)[0])

View File

@ -609,6 +609,8 @@ The following checks are performed on your URL configuration:
imported.
* **urls.E009**: Your URL pattern ``<pattern>`` has an invalid view, pass
``<view>.as_view()`` instead of ``<view>``.
* **urls.W010**: Your URL pattern ``<pattern>` has an unmatched
``<angle bracket>``.
``contrib`` app checks
======================

View File

@ -161,6 +161,47 @@ class CheckUrlConfigTests(SimpleTestCase):
],
)
@override_settings(
ROOT_URLCONF="check_framework.urls.path_compatibility.matched_angle_brackets"
)
def test_no_warnings_matched_angle_brackets(self):
self.assertEqual(check_url_config(None), [])
@override_settings(
ROOT_URLCONF="check_framework.urls.path_compatibility.unmatched_angle_brackets"
)
def test_warning_unmatched_angle_brackets(self):
self.assertEqual(
check_url_config(None),
[
Warning(
"Your URL pattern 'beginning-with/<angle_bracket' has an unmatched "
"'<' bracket.",
id="urls.W010",
),
Warning(
"Your URL pattern 'ending-with/angle_bracket>' has an unmatched "
"'>' bracket.",
id="urls.W010",
),
Warning(
"Your URL pattern 'closed_angle>/x/<opened_angle' has an unmatched "
"'>' bracket.",
id="urls.W010",
),
Warning(
"Your URL pattern 'closed_angle>/x/<opened_angle' has an unmatched "
"'<' bracket.",
id="urls.W010",
),
Warning(
"Your URL pattern '<mixed>angle_bracket>' has an unmatched '>' "
"bracket.",
id="urls.W010",
),
],
)
class UpdatedToPathTests(SimpleTestCase):
@override_settings(

View File

@ -0,0 +1,5 @@
from django.urls import path
urlpatterns = [
path("<int:angle_bracket>", lambda x: x),
]

View File

@ -0,0 +1,8 @@
from django.urls import path
urlpatterns = [
path("beginning-with/<angle_bracket", lambda x: x),
path("ending-with/angle_bracket>", lambda x: x),
path("closed_angle>/x/<opened_angle", lambda x: x),
path("<mixed>angle_bracket>", lambda x: x),
]