summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Johnson <me@adamj.eu>2024-02-24 19:14:22 +0000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2024-03-02 19:54:21 +0100
commit5dfcf343cd414d3f7a33dabb763b4478fa081d72 (patch)
tree05bca08a653181fb795a8ae4b6c6564e758a666a
parent595738296faec582ce90f1cffef90fbb9b18384b (diff)
Refs #35250 -- Avoided double conversion in RoutePattern.
-rw-r--r--django/urls/resolvers.py58
1 files changed, 36 insertions, 22 deletions
diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py
index 5f9941dd65..e335fc0a58 100644
--- a/django/urls/resolvers.py
+++ b/django/urls/resolvers.py
@@ -128,9 +128,6 @@ def get_ns_resolver(ns_pattern, resolver, converters):
class LocaleRegexDescriptor:
- def __init__(self, attr):
- self.attr = attr
-
def __get__(self, instance, cls=None):
"""
Return a compiled regular expression based on the active language.
@@ -140,15 +137,23 @@ class LocaleRegexDescriptor:
# As a performance optimization, if the given regex string is a regular
# string (not a lazily-translated string proxy), compile it once and
# avoid per-language compilation.
- pattern = getattr(instance, self.attr)
+ pattern = instance._regex
if isinstance(pattern, str):
- instance.__dict__["regex"] = instance._compile(pattern)
+ instance.__dict__["regex"] = self._compile(pattern)
return instance.__dict__["regex"]
language_code = get_language()
if language_code not in instance._regex_dict:
- instance._regex_dict[language_code] = instance._compile(str(pattern))
+ instance._regex_dict[language_code] = self._compile(str(pattern))
return instance._regex_dict[language_code]
+ def _compile(self, regex):
+ try:
+ return re.compile(regex)
+ except re.error as e:
+ raise ImproperlyConfigured(
+ f'"{regex}" is not a valid regular expression: {e}'
+ ) from e
+
class CheckURLMixin:
def describe(self):
@@ -186,7 +191,7 @@ class CheckURLMixin:
class RegexPattern(CheckURLMixin):
- regex = LocaleRegexDescriptor("_regex")
+ regex = LocaleRegexDescriptor()
def __init__(self, regex, name=None, is_endpoint=False):
self._regex = regex
@@ -232,15 +237,6 @@ class RegexPattern(CheckURLMixin):
else:
return []
- def _compile(self, regex):
- """Compile and return the given regular expression."""
- try:
- return re.compile(regex)
- except re.error as e:
- raise ImproperlyConfigured(
- '"%s" is not a valid regular expression: %s' % (regex, e)
- ) from e
-
def __str__(self):
return str(self._regex)
@@ -250,7 +246,7 @@ _PATH_PARAMETER_COMPONENT_RE = _lazy_re_compile(
)
-def _route_to_regex(route, is_endpoint=False):
+def _route_to_regex(route, is_endpoint):
"""
Convert a path pattern into a regular expression. Return the regular
expression and a dictionary mapping the capture names to the converters.
@@ -296,15 +292,36 @@ def _route_to_regex(route, is_endpoint=False):
return "".join(parts), converters
+class LocaleRegexRouteDescriptor:
+ def __get__(self, instance, cls=None):
+ """
+ Return a compiled regular expression based on the active language.
+ """
+ if instance is None:
+ return self
+ # As a performance optimization, if the given route is a regular string
+ # (not a lazily-translated string proxy), compile it once and avoid
+ # per-language compilation.
+ if isinstance(instance._route, str):
+ instance.__dict__["regex"] = re.compile(instance._regex)
+ return instance.__dict__["regex"]
+ language_code = get_language()
+ if language_code not in instance._regex_dict:
+ instance._regex_dict[language_code] = re.compile(
+ _route_to_regex(str(instance._route), instance._is_endpoint)[0]
+ )
+ return instance._regex_dict[language_code]
+
+
class RoutePattern(CheckURLMixin):
- regex = LocaleRegexDescriptor("_route")
+ regex = LocaleRegexRouteDescriptor()
def __init__(self, route, name=None, is_endpoint=False):
self._route = route
+ self._regex, self.converters = _route_to_regex(str(route), is_endpoint)
self._regex_dict = {}
self._is_endpoint = is_endpoint
self.name = name
- self.converters = _route_to_regex(str(route), is_endpoint)[1]
def match(self, path):
match = self.regex.search(path)
@@ -356,9 +373,6 @@ class RoutePattern(CheckURLMixin):
warnings.append(Warning(msg % (self.describe(), "<"), id="urls.W010"))
return warnings
- def _compile(self, route):
- return re.compile(_route_to_regex(route, self._is_endpoint)[0])
-
def __str__(self):
return str(self._route)