summaryrefslogtreecommitdiff
path: root/django/utils
diff options
context:
space:
mode:
authorHasan Ramezani <hasan.r67@gmail.com>2019-10-26 16:42:32 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-10-29 09:22:26 +0100
commite3d0b4d5501c6d0bc39f035e4345e5bdfde12e41 (patch)
treea8ddbafdf4a38a87df6f65fc4d02dba08c725096 /django/utils
parent39a34d4bf94bc8325119bc23b64f3a041a85dd2d (diff)
Fixed #30899 -- Lazily compiled import time regular expressions.
Diffstat (limited to 'django/utils')
-rw-r--r--django/utils/cache.py4
-rw-r--r--django/utils/dateformat.py6
-rw-r--r--django/utils/dateparse.py14
-rw-r--r--django/utils/datetime_safe.py5
-rw-r--r--django/utils/html.py12
-rw-r--r--django/utils/http.py11
-rw-r--r--django/utils/text.py15
-rw-r--r--django/utils/translation/__init__.py4
-rw-r--r--django/utils/translation/template.py16
-rw-r--r--django/utils/translation/trans_real.py7
10 files changed, 51 insertions, 43 deletions
diff --git a/django/utils/cache.py b/django/utils/cache.py
index 14e8256b94..df9c4c755a 100644
--- a/django/utils/cache.py
+++ b/django/utils/cache.py
@@ -17,7 +17,6 @@ An example: i18n middleware would need to distinguish caches by the
"Accept-language" header.
"""
import hashlib
-import re
import time
from collections import defaultdict
@@ -29,10 +28,11 @@ from django.utils.http import (
http_date, parse_etags, parse_http_date_safe, quote_etag,
)
from django.utils.log import log_response
+from django.utils.regex_helper import _lazy_re_compile
from django.utils.timezone import get_current_timezone_name
from django.utils.translation import get_language
-cc_delim_re = re.compile(r'\s*,\s*')
+cc_delim_re = _lazy_re_compile(r'\s*,\s*')
def patch_cache_control(response, **kwargs):
diff --git a/django/utils/dateformat.py b/django/utils/dateformat.py
index d3f586aacf..836b40a70a 100644
--- a/django/utils/dateformat.py
+++ b/django/utils/dateformat.py
@@ -12,17 +12,17 @@ Usage:
"""
import calendar
import datetime
-import re
import time
from django.utils.dates import (
MONTHS, MONTHS_3, MONTHS_ALT, MONTHS_AP, WEEKDAYS, WEEKDAYS_ABBR,
)
+from django.utils.regex_helper import _lazy_re_compile
from django.utils.timezone import get_default_timezone, is_aware, is_naive
from django.utils.translation import gettext as _
-re_formatchars = re.compile(r'(?<!\\)([aAbBcdDeEfFgGhHiIjlLmMnNoOPrsStTUuwWyYzZ])')
-re_escaped = re.compile(r'\\(.)')
+re_formatchars = _lazy_re_compile(r'(?<!\\)([aAbBcdDeEfFgGhHiIjlLmMnNoOPrsStTUuwWyYzZ])')
+re_escaped = _lazy_re_compile(r'\\(.)')
class Formatter:
diff --git a/django/utils/dateparse.py b/django/utils/dateparse.py
index f90d952581..d142e161b6 100644
--- a/django/utils/dateparse.py
+++ b/django/utils/dateparse.py
@@ -6,27 +6,27 @@
# - The date/datetime/time constructors produce friendlier error messages.
import datetime
-import re
+from django.utils.regex_helper import _lazy_re_compile
from django.utils.timezone import get_fixed_timezone, utc
-date_re = re.compile(
+date_re = _lazy_re_compile(
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})$'
)
-time_re = re.compile(
+time_re = _lazy_re_compile(
r'(?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
)
-datetime_re = re.compile(
+datetime_re = _lazy_re_compile(
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})'
r'[T ](?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
r'(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$'
)
-standard_duration_re = re.compile(
+standard_duration_re = _lazy_re_compile(
r'^'
r'(?:(?P<days>-?\d+) (days?, )?)?'
r'(?P<sign>-?)'
@@ -39,7 +39,7 @@ standard_duration_re = re.compile(
# Support the sections of ISO 8601 date representation that are accepted by
# timedelta
-iso8601_duration_re = re.compile(
+iso8601_duration_re = _lazy_re_compile(
r'^(?P<sign>[-+]?)'
r'P'
r'(?:(?P<days>\d+(.\d+)?)D)?'
@@ -54,7 +54,7 @@ iso8601_duration_re = re.compile(
# Support PostgreSQL's day-time interval format, e.g. "3 days 04:05:06". The
# year-month and mixed intervals cannot be converted to a timedelta and thus
# aren't accepted.
-postgres_interval_re = re.compile(
+postgres_interval_re = _lazy_re_compile(
r'^'
r'(?:(?P<days>-?\d+) (days? ?))?'
r'(?:(?P<sign>[-+])?'
diff --git a/django/utils/datetime_safe.py b/django/utils/datetime_safe.py
index 7eaa5c21ce..ade2dca610 100644
--- a/django/utils/datetime_safe.py
+++ b/django/utils/datetime_safe.py
@@ -7,12 +7,13 @@
# >>> datetime_safe.date(10, 8, 2).strftime("%Y/%m/%d was a %A")
# '0010/08/02 was a Monday'
-import re
import time as ttime
from datetime import (
date as real_date, datetime as real_datetime, time as real_time,
)
+from django.utils.regex_helper import _lazy_re_compile
+
class date(real_date):
def strftime(self, fmt):
@@ -54,7 +55,7 @@ def new_datetime(d):
# This library does not support strftime's "%s" or "%y" format strings.
# Allowed if there's an even number of "%"s because they are escaped.
-_illegal_formatting = re.compile(r"((^|[^%])(%%)*%[sy])")
+_illegal_formatting = _lazy_re_compile(r"((^|[^%])(%%)*%[sy])")
def _findall(text, substr):
diff --git a/django/utils/html.py b/django/utils/html.py
index 94aa0ff35e..2b8f2a8c89 100644
--- a/django/utils/html.py
+++ b/django/utils/html.py
@@ -11,6 +11,7 @@ from urllib.parse import (
from django.utils.encoding import punycode
from django.utils.functional import Promise, keep_lazy, keep_lazy_text
from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS
+from django.utils.regex_helper import _lazy_re_compile
from django.utils.safestring import SafeData, SafeString, mark_safe
from django.utils.text import normalize_newlines
@@ -21,10 +22,13 @@ WRAPPING_PUNCTUATION = [('(', ')'), ('[', ']')]
# List of possible strings used for bullets in bulleted lists.
DOTS = ['&middot;', '*', '\u2022', '&#149;', '&bull;', '&#8226;']
-unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)')
-word_split_re = re.compile(r'''([\s<>"']+)''')
-simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE)
-simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$', re.IGNORECASE)
+unencoded_ampersands_re = _lazy_re_compile(r'&(?!(\w+|#\d+);)')
+word_split_re = _lazy_re_compile(r'''([\s<>"']+)''')
+simple_url_re = _lazy_re_compile(r'^https?://\[?\w', re.IGNORECASE)
+simple_url_2_re = _lazy_re_compile(
+ r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$',
+ re.IGNORECASE
+)
@keep_lazy(str, SafeString)
diff --git a/django/utils/http.py b/django/utils/http.py
index ff2f08ac1e..709ce60e1f 100644
--- a/django/utils/http.py
+++ b/django/utils/http.py
@@ -16,9 +16,10 @@ from django.core.exceptions import TooManyFieldsSent
from django.utils.datastructures import MultiValueDict
from django.utils.deprecation import RemovedInDjango40Warning
from django.utils.functional import keep_lazy_text
+from django.utils.regex_helper import _lazy_re_compile
# based on RFC 7232, Appendix C
-ETAG_MATCH = re.compile(r'''
+ETAG_MATCH = _lazy_re_compile(r'''
\A( # start of string and capture group
(?:W/)? # optional weak indicator
" # opening quote
@@ -34,14 +35,14 @@ __M = r'(?P<mon>\w{3})'
__Y = r'(?P<year>\d{4})'
__Y2 = r'(?P<year>\d{2})'
__T = r'(?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\d{2})'
-RFC1123_DATE = re.compile(r'^\w{3}, %s %s %s %s GMT$' % (__D, __M, __Y, __T))
-RFC850_DATE = re.compile(r'^\w{6,9}, %s-%s-%s %s GMT$' % (__D, __M, __Y2, __T))
-ASCTIME_DATE = re.compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y))
+RFC1123_DATE = _lazy_re_compile(r'^\w{3}, %s %s %s %s GMT$' % (__D, __M, __Y, __T))
+RFC850_DATE = _lazy_re_compile(r'^\w{6,9}, %s-%s-%s %s GMT$' % (__D, __M, __Y2, __T))
+ASCTIME_DATE = _lazy_re_compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y))
RFC3986_GENDELIMS = ":/?#[]@"
RFC3986_SUBDELIMS = "!$&'()*+,;="
-FIELDS_MATCH = re.compile('[&;]')
+FIELDS_MATCH = _lazy_re_compile('[&;]')
@keep_lazy_text
diff --git a/django/utils/text.py b/django/utils/text.py
index 03e2d05177..5e1409116e 100644
--- a/django/utils/text.py
+++ b/django/utils/text.py
@@ -7,6 +7,7 @@ from io import BytesIO
from django.utils.deprecation import RemovedInDjango40Warning
from django.utils.functional import SimpleLazyObject, keep_lazy_text, lazy
+from django.utils.regex_helper import _lazy_re_compile
from django.utils.translation import gettext as _, gettext_lazy, pgettext
@@ -17,11 +18,11 @@ def capfirst(x):
# Set up regular expressions
-re_words = re.compile(r'<[^>]+?>|([^<>\s]+)', re.S)
-re_chars = re.compile(r'<[^>]+?>|(.)', re.S)
-re_tag = re.compile(r'<(/)?(\S+?)(?:(\s*/)|\s.*?)?>', re.S)
-re_newlines = re.compile(r'\r\n|\r') # Used in normalize_newlines
-re_camel_case = re.compile(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))')
+re_words = _lazy_re_compile(r'<[^>]+?>|([^<>\s]+)', re.S)
+re_chars = _lazy_re_compile(r'<[^>]+?>|(.)', re.S)
+re_tag = _lazy_re_compile(r'<(/)?(\S+?)(?:(\s*/)|\s.*?)?>', re.S)
+re_newlines = _lazy_re_compile(r'\r\n|\r') # Used in normalize_newlines
+re_camel_case = _lazy_re_compile(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))')
@keep_lazy_text
@@ -306,7 +307,7 @@ def compress_sequence(sequence):
# Expression to match some_token and some_token="with spaces" (and similarly
# for single-quoted strings).
-smart_split_re = re.compile(r"""
+smart_split_re = _lazy_re_compile(r"""
((?:
[^\s'"]*
(?:
@@ -355,7 +356,7 @@ def _replace_entity(match):
return match.group(0)
-_entity_re = re.compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));")
+_entity_re = _lazy_re_compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));")
@keep_lazy_text
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index e48c7d245d..728286c78e 100644
--- a/django/utils/translation/__init__.py
+++ b/django/utils/translation/__init__.py
@@ -1,7 +1,6 @@
"""
Internationalization support.
"""
-import re
import warnings
from contextlib import ContextDecorator
from decimal import ROUND_UP, Decimal
@@ -9,6 +8,7 @@ from decimal import ROUND_UP, Decimal
from django.utils.autoreload import autoreload_started, file_changed
from django.utils.deprecation import RemovedInDjango40Warning
from django.utils.functional import lazy
+from django.utils.regex_helper import _lazy_re_compile
__all__ = [
'activate', 'deactivate', 'override', 'deactivate_all',
@@ -328,7 +328,7 @@ def get_language_info(lang_code):
return info
-trim_whitespace_re = re.compile(r'\s*\n\s*')
+trim_whitespace_re = _lazy_re_compile(r'\s*\n\s*')
def trim_whitespace(s):
diff --git a/django/utils/translation/template.py b/django/utils/translation/template.py
index aa849b0937..979ae1ade6 100644
--- a/django/utils/translation/template.py
+++ b/django/utils/translation/template.py
@@ -1,12 +1,12 @@
-import re
import warnings
from io import StringIO
from django.template.base import TRANSLATOR_COMMENT_MARK, Lexer, TokenType
+from django.utils.regex_helper import _lazy_re_compile
from . import TranslatorCommentWarning, trim_whitespace
-dot_re = re.compile(r'\S')
+dot_re = _lazy_re_compile(r'\S')
def blankout(src, char):
@@ -17,8 +17,8 @@ def blankout(src, char):
return dot_re.sub(char, src)
-context_re = re.compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""")
-inline_re = re.compile(
+context_re = _lazy_re_compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""")
+inline_re = _lazy_re_compile(
# Match the trans 'some text' part
r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))"""
# Match and ignore optional filters
@@ -26,10 +26,10 @@ inline_re = re.compile(
# Match the optional context part
r"""(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?\s*"""
)
-block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""")
-endblock_re = re.compile(r"""^\s*endblocktrans$""")
-plural_re = re.compile(r"""^\s*plural$""")
-constant_re = re.compile(r"""_\(((?:".*?")|(?:'.*?'))\)""")
+block_re = _lazy_re_compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""")
+endblock_re = _lazy_re_compile(r"""^\s*endblocktrans$""")
+plural_re = _lazy_re_compile(r"""^\s*plural$""")
+constant_re = _lazy_re_compile(r"""_\(((?:".*?")|(?:'.*?'))\)""")
def templatize(src, origin=None):
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index e089597ccb..d852675360 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -14,6 +14,7 @@ from django.conf.locale import LANG_INFO
from django.core.exceptions import AppRegistryNotReady
from django.core.signals import setting_changed
from django.dispatch import receiver
+from django.utils.regex_helper import _lazy_re_compile
from django.utils.safestring import SafeData, mark_safe
from . import to_language, to_locale
@@ -31,18 +32,18 @@ CONTEXT_SEPARATOR = "\x04"
# Format of Accept-Language header values. From RFC 2616, section 14.4 and 3.9
# and RFC 3066, section 2.1
-accept_language_re = re.compile(r'''
+accept_language_re = _lazy_re_compile(r'''
([A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8})*|\*) # "en", "en-au", "x-y-z", "es-419", "*"
(?:\s*;\s*q=(0(?:\.\d{,3})?|1(?:\.0{,3})?))? # Optional "q=1.00", "q=0.8"
(?:\s*,\s*|$) # Multiple accepts per header.
''', re.VERBOSE)
-language_code_re = re.compile(
+language_code_re = _lazy_re_compile(
r'^[a-z]{1,8}(?:-[a-z0-9]{1,8})*(?:@[a-z0-9]{1,20})?$',
re.IGNORECASE
)
-language_code_prefix_re = re.compile(r'^/(\w+([@-]\w+)?)(/|$)')
+language_code_prefix_re = _lazy_re_compile(r'^/(\w+([@-]\w+)?)(/|$)')
@receiver(setting_changed)