Browse Source

Fixed #28663 -- Add a check for likely incorrectly migrated django.urls.path() routes.

Chris Lamb 7 years ago
parent
commit
998c9dd599

+ 10 - 1
django/urls/resolvers.py

@@ -255,7 +255,16 @@ class RoutePattern(CheckURLMixin):
         return None
 
     def check(self):
-        return self._check_pattern_startswith_slash()
+        warnings = self._check_pattern_startswith_slash()
+        route = self._route
+        if '(?P<' in route or route.startswith('^') or route.endswith('$'):
+            warnings.append(Warning(
+                "Your URL pattern {} has a route that contains '(?P<', begins "
+                "with a '^', or ends with a '$'. This was likely an oversight "
+                "when migrating to django.urls.path().".format(self.describe()),
+                id='2_0.W001',
+            ))
+        return warnings
 
     def _compile(self, route):
         return re.compile(_route_to_regex(route, self._is_endpoint)[0])

+ 3 - 1
docs/ref/checks.txt

@@ -98,7 +98,9 @@ Backwards compatibility
 Compatibility checks warn of potential problems that might occur after
 upgrading Django.
 
-Currently, there aren't any of these checks.
+* **2_0.W001**: Your URL pattern ``<pattern>`` has a ``route`` that contains
+  ``(?P<``, begins with a ``^``, or ends with a ``$``. This was likely an
+  oversight when migrating from ``url()`` to :func:`~django.urls.path`.
 
 Caches
 ------

+ 30 - 0
tests/check_framework/test_urls.py

@@ -135,6 +135,36 @@ class CheckUrlConfigTests(SimpleTestCase):
         self.assertEqual(result, [])
 
 
+class UpdatedToPathTests(SimpleTestCase):
+
+    @override_settings(ROOT_URLCONF='check_framework.urls.path_compatibility.contains_re_named_group')
+    def test_contains_re_named_group(self):
+        result = check_url_config(None)
+        self.assertEqual(len(result), 1)
+        warning = result[0]
+        self.assertEqual(warning.id, '2_0.W001')
+        expected_msg = "Your URL pattern '(?P<named-group>\\d+)' has a route"
+        self.assertIn(expected_msg, warning.msg)
+
+    @override_settings(ROOT_URLCONF='check_framework.urls.path_compatibility.beginning_with_caret')
+    def test_beginning_with_caret(self):
+        result = check_url_config(None)
+        self.assertEqual(len(result), 1)
+        warning = result[0]
+        self.assertEqual(warning.id, '2_0.W001')
+        expected_msg = "Your URL pattern '^beginning-with-caret' has a route"
+        self.assertIn(expected_msg, warning.msg)
+
+    @override_settings(ROOT_URLCONF='check_framework.urls.path_compatibility.ending_with_dollar')
+    def test_ending_with_dollar(self):
+        result = check_url_config(None)
+        self.assertEqual(len(result), 1)
+        warning = result[0]
+        self.assertEqual(warning.id, '2_0.W001')
+        expected_msg = "Your URL pattern 'ending-with-dollar$' has a route"
+        self.assertIn(expected_msg, warning.msg)
+
+
 class CheckURLSettingsTests(SimpleTestCase):
 
     @override_settings(STATIC_URL='a/', MEDIA_URL='b/')

+ 0 - 0
tests/check_framework/urls/path_compatibility/__init__.py


+ 5 - 0
tests/check_framework/urls/path_compatibility/beginning_with_caret.py

@@ -0,0 +1,5 @@
+from django.urls import path
+
+urlpatterns = [
+    path('^beginning-with-caret', lambda x: x),
+]

+ 5 - 0
tests/check_framework/urls/path_compatibility/contains_re_named_group.py

@@ -0,0 +1,5 @@
+from django.urls import path
+
+urlpatterns = [
+    path('(?P<named-group>\d+)', lambda x: x),
+]

+ 5 - 0
tests/check_framework/urls/path_compatibility/ending_with_dollar.py

@@ -0,0 +1,5 @@
+from django.urls import path
+
+urlpatterns = [
+    path('ending-with-dollar$', lambda x: x),
+]