1
0
mirror of https://github.com/django/django.git synced 2025-05-07 23:46:30 +00:00

Fixed #30899 -- Lazily compiled import time regular expressions.

This commit is contained in:
Hasan Ramezani 2019-10-26 16:42:32 +02:00 committed by Mariusz Felisiak
parent 39a34d4bf9
commit e3d0b4d550
34 changed files with 114 additions and 95 deletions

View File

@ -1,6 +1,5 @@
import datetime import datetime
import decimal import decimal
import re
from collections import defaultdict from collections import defaultdict
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
@ -11,12 +10,13 @@ from django.forms.utils import pretty_name
from django.urls import NoReverseMatch, reverse from django.urls import NoReverseMatch, reverse
from django.utils import formats, timezone from django.utils import formats, timezone
from django.utils.html import format_html from django.utils.html import format_html
from django.utils.regex_helper import _lazy_re_compile
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import ngettext, override as translation_override from django.utils.translation import ngettext, override as translation_override
QUOTE_MAP = {i: '_%02X' % i for i in b'":/_#?;@&=+$,"[]<>%\n\\'} QUOTE_MAP = {i: '_%02X' % i for i in b'":/_#?;@&=+$,"[]<>%\n\\'}
UNQUOTE_MAP = {v: chr(k) for k, v in QUOTE_MAP.items()} UNQUOTE_MAP = {v: chr(k) for k, v in QUOTE_MAP.items()}
UNQUOTE_RE = re.compile('_(?:%s)' % '|'.join([x[1:] for x in UNQUOTE_MAP])) UNQUOTE_RE = _lazy_re_compile('_(?:%s)' % '|'.join([x[1:] for x in UNQUOTE_MAP]))
class FieldIsAForeignKeyColumnName(Exception): class FieldIsAForeignKeyColumnName(Exception):

View File

@ -5,6 +5,7 @@ from email.errors import HeaderParseError
from email.parser import HeaderParser from email.parser import HeaderParser
from django.urls import reverse from django.urls import reverse
from django.utils.regex_helper import _lazy_re_compile
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
try: try:
@ -146,8 +147,8 @@ if docutils_is_available:
create_reference_role(name, urlbase) create_reference_role(name, urlbase)
# Match the beginning of a named or unnamed group. # Match the beginning of a named or unnamed group.
named_group_matcher = re.compile(r'\(\?P(<\w+>)') named_group_matcher = _lazy_re_compile(r'\(\?P(<\w+>)')
unnamed_group_matcher = re.compile(r'\(') unnamed_group_matcher = _lazy_re_compile(r'\(')
def replace_named_groups(pattern): def replace_named_groups(pattern):

View File

@ -1,11 +1,10 @@
import re
from django.contrib.gis.db.models.fields import BaseSpatialField from django.contrib.gis.db.models.fields import BaseSpatialField
from django.contrib.gis.measure import Distance from django.contrib.gis.measure import Distance
from django.db import NotSupportedError from django.db import NotSupportedError
from django.db.models.expressions import Expression from django.db.models.expressions import Expression
from django.db.models.lookups import Lookup, Transform from django.db.models.lookups import Lookup, Transform
from django.db.models.sql.query import Query from django.db.models.sql.query import Query
from django.utils.regex_helper import _lazy_re_compile
class RasterBandTransform(Transform): class RasterBandTransform(Transform):
@ -253,7 +252,7 @@ class OverlapsLookup(GISLookup):
class RelateLookup(GISLookup): class RelateLookup(GISLookup):
lookup_name = 'relate' lookup_name = 'relate'
sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)' sql_template = '%(func)s(%(lhs)s, %(rhs)s, %%s)'
pattern_regex = re.compile(r'^[012TF\*]{9}$') pattern_regex = _lazy_re_compile(r'^[012TF\*]{9}$')
def process_rhs(self, compiler, connection): def process_rhs(self, compiler, connection):
# Check the pattern argument # Check the pattern argument

View File

@ -1,11 +1,11 @@
import logging import logging
import os import os
import re
from ctypes import CDLL, CFUNCTYPE, c_char_p, c_int from ctypes import CDLL, CFUNCTYPE, c_char_p, c_int
from ctypes.util import find_library from ctypes.util import find_library
from django.contrib.gis.gdal.error import GDALException from django.contrib.gis.gdal.error import GDALException
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.utils.regex_helper import _lazy_re_compile
logger = logging.getLogger('django.contrib.gis') logger = logging.getLogger('django.contrib.gis')
@ -83,7 +83,7 @@ def gdal_full_version():
return _version_info('') return _version_info('')
version_regex = re.compile(r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<subminor>\d+))?') version_regex = _lazy_re_compile(r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<subminor>\d+))?')
def gdal_version_info(): def gdal_version_info():

View File

@ -1,13 +1,17 @@
import re import re
from django.utils.regex_helper import _lazy_re_compile
# Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure # Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure
# to prevent potentially malicious input from reaching the underlying C # to prevent potentially malicious input from reaching the underlying C
# library. Not a substitute for good Web security programming practices. # library. Not a substitute for good Web security programming practices.
hex_regex = re.compile(r'^[0-9A-F]+$', re.I) hex_regex = _lazy_re_compile(r'^[0-9A-F]+$', re.I)
wkt_regex = re.compile(r'^(SRID=(?P<srid>\-?\d+);)?' wkt_regex = _lazy_re_compile(
r'(?P<wkt>' r'^(SRID=(?P<srid>\-?\d+);)?'
r'(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|' r'(?P<wkt>'
r'MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)' r'(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|'
r'[ACEGIMLONPSRUTYZ\d,\.\-\+\(\) ]+)$', r'MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)'
re.I) r'[ACEGIMLONPSRUTYZ\d,\.\-\+\(\) ]+)$',
json_regex = re.compile(r'^(\s+)?\{.*}(\s+)?$', re.DOTALL) re.I
)
json_regex = _lazy_re_compile(r'^(\s+)?\{.*}(\s+)?$', re.DOTALL)

View File

@ -1,4 +1,3 @@
import re
from io import BytesIO from io import BytesIO
from django.conf import settings from django.conf import settings
@ -8,8 +7,9 @@ from django.http import HttpRequest, QueryDict, parse_cookie
from django.urls import set_script_prefix from django.urls import set_script_prefix
from django.utils.encoding import repercent_broken_unicode from django.utils.encoding import repercent_broken_unicode
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.regex_helper import _lazy_re_compile
_slashes_re = re.compile(br'/+') _slashes_re = _lazy_re_compile(br'/+')
class LimitedStream: class LimitedStream:

View File

@ -16,10 +16,11 @@ from django.core.management.utils import (
from django.utils.encoding import DEFAULT_LOCALE_ENCODING from django.utils.encoding import DEFAULT_LOCALE_ENCODING
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.jslex import prepare_js_for_gettext from django.utils.jslex import prepare_js_for_gettext
from django.utils.regex_helper import _lazy_re_compile
from django.utils.text import get_text_list from django.utils.text import get_text_list
from django.utils.translation import templatize from django.utils.translation import templatize
plural_forms_re = re.compile(r'^(?P<value>"Plural-Forms.+?\\n")\s*$', re.MULTILINE | re.DOTALL) plural_forms_re = _lazy_re_compile(r'^(?P<value>"Plural-Forms.+?\\n")\s*$', re.MULTILINE | re.DOTALL)
STATUS_OK = 0 STATUS_OK = 0
NO_LOCALE_DIR = object() NO_LOCALE_DIR = object()

View File

@ -11,8 +11,9 @@ from django.core.servers.basehttp import (
WSGIServer, get_internal_wsgi_application, run, WSGIServer, get_internal_wsgi_application, run,
) )
from django.utils import autoreload from django.utils import autoreload
from django.utils.regex_helper import _lazy_re_compile
naiveip_re = re.compile(r"""^(?: naiveip_re = _lazy_re_compile(r"""^(?:
(?P<addr> (?P<addr>
(?P<ipv4>\d{1,3}(?:\.\d{1,3}){3}) | # IPv4 address (?P<ipv4>\d{1,3}(?:\.\d{1,3}){3}) | # IPv4 address
(?P<ipv6>\[[a-fA-F0-9:]+\]) | # IPv6 address (?P<ipv6>\[[a-fA-F0-9:]+\]) | # IPv6 address

View File

@ -36,7 +36,6 @@ These functions make use of all of them.
import base64 import base64
import datetime import datetime
import json import json
import re
import time import time
import zlib import zlib
@ -45,8 +44,9 @@ from django.utils import baseconv
from django.utils.crypto import constant_time_compare, salted_hmac from django.utils.crypto import constant_time_compare, salted_hmac
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.module_loading import import_string from django.utils.module_loading import import_string
from django.utils.regex_helper import _lazy_re_compile
_SEP_UNSAFE = re.compile(r'^[A-z0-9-_=]*$') _SEP_UNSAFE = _lazy_re_compile(r'^[A-z0-9-_=]*$')
class BadSignature(Exception): class BadSignature(Exception):

View File

@ -3,14 +3,13 @@ MySQL database backend for Django.
Requires mysqlclient: https://pypi.org/project/mysqlclient/ Requires mysqlclient: https://pypi.org/project/mysqlclient/
""" """
import re
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import utils from django.db import utils
from django.db.backends import utils as backend_utils from django.db.backends import utils as backend_utils
from django.db.backends.base.base import BaseDatabaseWrapper from django.db.backends.base.base import BaseDatabaseWrapper
from django.utils.asyncio import async_unsafe from django.utils.asyncio import async_unsafe
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.regex_helper import _lazy_re_compile
try: try:
import MySQLdb as Database import MySQLdb as Database
@ -47,7 +46,7 @@ django_conversions = {
# This should match the numerical portion of the version numbers (we can treat # This should match the numerical portion of the version numbers (we can treat
# versions like 5.0.24 and 5.0.24a as the same). # versions like 5.0.24 and 5.0.24a as the same).
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})') server_version_re = _lazy_re_compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
class CursorWrapper: class CursorWrapper:

View File

@ -1,5 +1,4 @@
import datetime import datetime
import re
import uuid import uuid
from functools import lru_cache from functools import lru_cache
@ -12,6 +11,7 @@ from django.db.utils import DatabaseError
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import force_bytes, force_str from django.utils.encoding import force_bytes, force_str
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.regex_helper import _lazy_re_compile
from .base import Database from .base import Database
from .utils import BulkInsertMapper, InsertVar, Oracle_datetime from .utils import BulkInsertMapper, InsertVar, Oracle_datetime
@ -102,7 +102,7 @@ END;
# if the time zone name is passed in parameter. Use interpolation instead. # if the time zone name is passed in parameter. Use interpolation instead.
# https://groups.google.com/forum/#!msg/django-developers/zwQju7hbG78/9l934yelwfsJ # https://groups.google.com/forum/#!msg/django-developers/zwQju7hbG78/9l934yelwfsJ
# This regexp matches all time zone names from the zoneinfo database. # This regexp matches all time zone names from the zoneinfo database.
_tzname_re = re.compile(r'^[\w/:+-]+$') _tzname_re = _lazy_re_compile(r'^[\w/:+-]+$')
def _prepare_tzname_delta(self, tzname): def _prepare_tzname_delta(self, tzname):
if '+' in tzname: if '+' in tzname:

View File

@ -23,6 +23,7 @@ from django.utils import timezone
from django.utils.asyncio import async_unsafe from django.utils.asyncio import async_unsafe
from django.utils.dateparse import parse_datetime, parse_time from django.utils.dateparse import parse_datetime, parse_time
from django.utils.duration import duration_microseconds from django.utils.duration import duration_microseconds
from django.utils.regex_helper import _lazy_re_compile
from .client import DatabaseClient # isort:skip from .client import DatabaseClient # isort:skip
from .creation import DatabaseCreation # isort:skip from .creation import DatabaseCreation # isort:skip
@ -380,7 +381,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
return self.creation.is_in_memory_db(self.settings_dict['NAME']) return self.creation.is_in_memory_db(self.settings_dict['NAME'])
FORMAT_QMARK_REGEX = re.compile(r'(?<!%)%s') FORMAT_QMARK_REGEX = _lazy_re_compile(r'(?<!%)%s')
class SQLiteCursorWrapper(Database.Cursor): class SQLiteCursorWrapper(Database.Cursor):

View File

@ -7,10 +7,11 @@ from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo, BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo,
) )
from django.db.models.indexes import Index from django.db.models.indexes import Index
from django.utils.regex_helper import _lazy_re_compile
FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('pk',)) FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('pk',))
field_size_re = re.compile(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$') field_size_re = _lazy_re_compile(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$')
def get_field_size(name): def get_field_size(name):

View File

@ -2,7 +2,7 @@
Constants specific to the SQL storage portion of the ORM. Constants specific to the SQL storage portion of the ORM.
""" """
import re from django.utils.regex_helper import _lazy_re_compile
# Size of each "chunk" for get_iterator calls. # Size of each "chunk" for get_iterator calls.
# Larger values are slightly faster at the expense of more storage space. # Larger values are slightly faster at the expense of more storage space.
@ -16,7 +16,7 @@ SINGLE = 'single'
CURSOR = 'cursor' CURSOR = 'cursor'
NO_RESULTS = 'no results' NO_RESULTS = 'no results'
ORDER_PATTERN = re.compile(r'\?|[-+]?[.\w]+$') ORDER_PATTERN = _lazy_re_compile(r'\?|[-+]?[.\w]+$')
ORDER_DIR = { ORDER_DIR = {
'ASC': ('ASC', 'DESC'), 'ASC': ('ASC', 'DESC'),
'DESC': ('DESC', 'ASC'), 'DESC': ('DESC', 'ASC'),

View File

@ -28,6 +28,7 @@ from django.utils import formats
from django.utils.dateparse import parse_duration from django.utils.dateparse import parse_duration
from django.utils.duration import duration_string from django.utils.duration import duration_string
from django.utils.ipv6 import clean_ipv6_address from django.utils.ipv6 import clean_ipv6_address
from django.utils.regex_helper import _lazy_re_compile
from django.utils.translation import gettext_lazy as _, ngettext_lazy from django.utils.translation import gettext_lazy as _, ngettext_lazy
__all__ = ( __all__ = (
@ -243,7 +244,7 @@ class IntegerField(Field):
default_error_messages = { default_error_messages = {
'invalid': _('Enter a whole number.'), 'invalid': _('Enter a whole number.'),
} }
re_decimal = re.compile(r'\.0*\s*$') re_decimal = _lazy_re_compile(r'\.0*\s*$')
def __init__(self, *, max_value=None, min_value=None, **kwargs): def __init__(self, *, max_value=None, min_value=None, **kwargs):
self.max_value, self.min_value = max_value, min_value self.max_value, self.min_value = max_value, min_value

View File

@ -4,7 +4,6 @@ HTML Widget classes
import copy import copy
import datetime import datetime
import re
import warnings import warnings
from collections import defaultdict from collections import defaultdict
from itertools import chain from itertools import chain
@ -17,6 +16,7 @@ from django.utils.datastructures import OrderedSet
from django.utils.dates import MONTHS from django.utils.dates import MONTHS
from django.utils.formats import get_format from django.utils.formats import get_format
from django.utils.html import format_html, html_safe from django.utils.html import format_html, html_safe
from django.utils.regex_helper import _lazy_re_compile
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.topological_sort import ( from django.utils.topological_sort import (
CyclicDependencyError, stable_topological_sort, CyclicDependencyError, stable_topological_sort,
@ -935,7 +935,7 @@ class SelectDateWidget(Widget):
template_name = 'django/forms/widgets/select_date.html' template_name = 'django/forms/widgets/select_date.html'
input_type = 'select' input_type = 'select'
select_widget = Select select_widget = Select
date_re = re.compile(r'(\d{4}|0)-(\d\d?)-(\d\d?)$') date_re = _lazy_re_compile(r'(\d{4}|0)-(\d\d?)-(\d\d?)$')
def __init__(self, attrs=None, years=None, months=None, empty_label=None): def __init__(self, attrs=None, years=None, months=None, empty_label=None):
self.attrs = attrs or {} self.attrs = attrs or {}

View File

@ -1,7 +1,6 @@
import cgi import cgi
import codecs import codecs
import copy import copy
import re
from io import BytesIO from io import BytesIO
from itertools import chain from itertools import chain
from urllib.parse import quote, urlencode, urljoin, urlsplit from urllib.parse import quote, urlencode, urljoin, urlsplit
@ -19,9 +18,10 @@ from django.utils.datastructures import (
from django.utils.encoding import escape_uri_path, iri_to_uri from django.utils.encoding import escape_uri_path, iri_to_uri
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.http import is_same_domain, limited_parse_qsl from django.utils.http import is_same_domain, limited_parse_qsl
from django.utils.regex_helper import _lazy_re_compile
RAISE_ERROR = object() RAISE_ERROR = object()
host_validation_re = re.compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9\.:]+\])(:\d+)?$") host_validation_re = _lazy_re_compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9\.:]+\])(:\d+)?$")
class UnreadablePostError(OSError): class UnreadablePostError(OSError):

View File

@ -17,8 +17,9 @@ from django.http.cookie import SimpleCookie
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import iri_to_uri from django.utils.encoding import iri_to_uri
from django.utils.http import http_date from django.utils.http import http_date
from django.utils.regex_helper import _lazy_re_compile
_charset_from_content_type_re = re.compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I) _charset_from_content_type_re = _lazy_re_compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)
class BadHeaderError(ValueError): class BadHeaderError(ValueError):

View File

@ -1,10 +1,9 @@
import re
from django.utils.cache import patch_vary_headers from django.utils.cache import patch_vary_headers
from django.utils.deprecation import MiddlewareMixin from django.utils.deprecation import MiddlewareMixin
from django.utils.regex_helper import _lazy_re_compile
from django.utils.text import compress_sequence, compress_string from django.utils.text import compress_sequence, compress_string
re_accepts_gzip = re.compile(r'\bgzip\b') re_accepts_gzip = _lazy_re_compile(r'\bgzip\b')
class GZipMiddleware(MiddlewareMixin): class GZipMiddleware(MiddlewareMixin):

View File

@ -58,6 +58,7 @@ from inspect import getcallargs, getfullargspec, unwrap
from django.template.context import BaseContext from django.template.context import BaseContext
from django.utils.formats import localize from django.utils.formats import localize
from django.utils.html import conditional_escape, escape from django.utils.html import conditional_escape, escape
from django.utils.regex_helper import _lazy_re_compile
from django.utils.safestring import SafeData, mark_safe from django.utils.safestring import SafeData, mark_safe
from django.utils.text import ( from django.utils.text import (
get_text_list, smart_split, unescape_string_literal, get_text_list, smart_split, unescape_string_literal,
@ -87,7 +88,7 @@ UNKNOWN_SOURCE = '<unknown source>'
# match a variable or block tag and capture the entire tag, including start/end # match a variable or block tag and capture the entire tag, including start/end
# delimiters # delimiters
tag_re = (re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % tag_re = (_lazy_re_compile('(%s.*?%s|%s.*?%s|%s.*?%s)' %
(re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END), (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END), re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END)))) re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END))))
@ -603,7 +604,7 @@ filter_raw_string = r"""
'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR), 'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR),
} }
filter_re = re.compile(filter_raw_string, re.VERBOSE) filter_re = _lazy_re_compile(filter_raw_string, re.VERBOSE)
class FilterExpression: class FilterExpression:
@ -993,7 +994,7 @@ class VariableNode(Node):
# Regex for token keyword arguments # Regex for token keyword arguments
kwarg_re = re.compile(r"(?:(\w+)=)?(.+)") kwarg_re = _lazy_re_compile(r"(?:(\w+)=)?(.+)")
def token_kwargs(bits, parser, support_legacy=False): def token_kwargs(bits, parser, support_legacy=False):

View File

@ -1,7 +1,6 @@
import json import json
import mimetypes import mimetypes
import os import os
import re
import sys import sys
from copy import copy from copy import copy
from functools import partial from functools import partial
@ -26,15 +25,16 @@ from django.utils.encoding import force_bytes
from django.utils.functional import SimpleLazyObject from django.utils.functional import SimpleLazyObject
from django.utils.http import urlencode from django.utils.http import urlencode
from django.utils.itercompat import is_iterable from django.utils.itercompat import is_iterable
from django.utils.regex_helper import _lazy_re_compile
__all__ = ('Client', 'RedirectCycleError', 'RequestFactory', 'encode_file', 'encode_multipart') __all__ = ('Client', 'RedirectCycleError', 'RequestFactory', 'encode_file', 'encode_multipart')
BOUNDARY = 'BoUnDaRyStRiNg' BOUNDARY = 'BoUnDaRyStRiNg'
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
CONTENT_TYPE_RE = re.compile(r'.*; charset=([\w\d-]+);?') CONTENT_TYPE_RE = _lazy_re_compile(r'.*; charset=([\w\d-]+);?')
# Structured suffix spec: https://tools.ietf.org/html/rfc6838#section-4.2.8 # Structured suffix spec: https://tools.ietf.org/html/rfc6838#section-4.2.8
JSON_CONTENT_TYPE_RE = re.compile(r'^application\/(.+\+)?json') JSON_CONTENT_TYPE_RE = _lazy_re_compile(r'^application\/(.+\+)?json')
class RedirectCycleError(Exception): class RedirectCycleError(Exception):

View File

@ -1,12 +1,13 @@
"""Compare two HTML documents.""" """Compare two HTML documents."""
import re
from html.parser import HTMLParser from html.parser import HTMLParser
from django.utils.regex_helper import _lazy_re_compile
# ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 # ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020
# SPACE. # SPACE.
# https://infra.spec.whatwg.org/#ascii-whitespace # https://infra.spec.whatwg.org/#ascii-whitespace
ASCII_WHITESPACE = re.compile(r'[\t\n\f\r ]+') ASCII_WHITESPACE = _lazy_re_compile(r'[\t\n\f\r ]+')
def normalize_whitespace(string): def normalize_whitespace(string):

View File

@ -21,7 +21,7 @@ from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.http import RFC3986_SUBDELIMS, escape_leading_slashes from django.utils.http import RFC3986_SUBDELIMS, escape_leading_slashes
from django.utils.regex_helper import normalize from django.utils.regex_helper import _lazy_re_compile, normalize
from django.utils.translation import get_language from django.utils.translation import get_language
from .converters import get_converter from .converters import get_converter
@ -195,7 +195,7 @@ class RegexPattern(CheckURLMixin):
return str(self._regex) return str(self._regex)
_PATH_PARAMETER_COMPONENT_RE = re.compile( _PATH_PARAMETER_COMPONENT_RE = _lazy_re_compile(
r'<(?:(?P<converter>[^>:]+):)?(?P<parameter>\w+)>' r'<(?:(?P<converter>[^>:]+):)?(?P<parameter>\w+)>'
) )

View File

@ -17,7 +17,6 @@ An example: i18n middleware would need to distinguish caches by the
"Accept-language" header. "Accept-language" header.
""" """
import hashlib import hashlib
import re
import time import time
from collections import defaultdict from collections import defaultdict
@ -29,10 +28,11 @@ from django.utils.http import (
http_date, parse_etags, parse_http_date_safe, quote_etag, http_date, parse_etags, parse_http_date_safe, quote_etag,
) )
from django.utils.log import log_response 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.timezone import get_current_timezone_name
from django.utils.translation import get_language 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): def patch_cache_control(response, **kwargs):

View File

@ -12,17 +12,17 @@ Usage:
""" """
import calendar import calendar
import datetime import datetime
import re
import time import time
from django.utils.dates import ( from django.utils.dates import (
MONTHS, MONTHS_3, MONTHS_ALT, MONTHS_AP, WEEKDAYS, WEEKDAYS_ABBR, 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.timezone import get_default_timezone, is_aware, is_naive
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
re_formatchars = re.compile(r'(?<!\\)([aAbBcdDeEfFgGhHiIjlLmMnNoOPrsStTUuwWyYzZ])') re_formatchars = _lazy_re_compile(r'(?<!\\)([aAbBcdDeEfFgGhHiIjlLmMnNoOPrsStTUuwWyYzZ])')
re_escaped = re.compile(r'\\(.)') re_escaped = _lazy_re_compile(r'\\(.)')
class Formatter: class Formatter:

View File

@ -6,27 +6,27 @@
# - The date/datetime/time constructors produce friendlier error messages. # - The date/datetime/time constructors produce friendlier error messages.
import datetime import datetime
import re
from django.utils.regex_helper import _lazy_re_compile
from django.utils.timezone import get_fixed_timezone, utc 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})$' 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<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<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'(?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'[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<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
r'(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$' r'(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$'
) )
standard_duration_re = re.compile( standard_duration_re = _lazy_re_compile(
r'^' r'^'
r'(?:(?P<days>-?\d+) (days?, )?)?' r'(?:(?P<days>-?\d+) (days?, )?)?'
r'(?P<sign>-?)' r'(?P<sign>-?)'
@ -39,7 +39,7 @@ standard_duration_re = re.compile(
# Support the sections of ISO 8601 date representation that are accepted by # Support the sections of ISO 8601 date representation that are accepted by
# timedelta # timedelta
iso8601_duration_re = re.compile( iso8601_duration_re = _lazy_re_compile(
r'^(?P<sign>[-+]?)' r'^(?P<sign>[-+]?)'
r'P' r'P'
r'(?:(?P<days>\d+(.\d+)?)D)?' 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 # 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 # year-month and mixed intervals cannot be converted to a timedelta and thus
# aren't accepted. # aren't accepted.
postgres_interval_re = re.compile( postgres_interval_re = _lazy_re_compile(
r'^' r'^'
r'(?:(?P<days>-?\d+) (days? ?))?' r'(?:(?P<days>-?\d+) (days? ?))?'
r'(?:(?P<sign>[-+])?' r'(?:(?P<sign>[-+])?'

View File

@ -7,12 +7,13 @@
# >>> datetime_safe.date(10, 8, 2).strftime("%Y/%m/%d was a %A") # >>> datetime_safe.date(10, 8, 2).strftime("%Y/%m/%d was a %A")
# '0010/08/02 was a Monday' # '0010/08/02 was a Monday'
import re
import time as ttime import time as ttime
from datetime import ( from datetime import (
date as real_date, datetime as real_datetime, time as real_time, 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): class date(real_date):
def strftime(self, fmt): def strftime(self, fmt):
@ -54,7 +55,7 @@ def new_datetime(d):
# This library does not support strftime's "%s" or "%y" format strings. # 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. # 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): def _findall(text, substr):

View File

@ -11,6 +11,7 @@ from urllib.parse import (
from django.utils.encoding import punycode from django.utils.encoding import punycode
from django.utils.functional import Promise, keep_lazy, keep_lazy_text from django.utils.functional import Promise, keep_lazy, keep_lazy_text
from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS 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.safestring import SafeData, SafeString, mark_safe
from django.utils.text import normalize_newlines from django.utils.text import normalize_newlines
@ -21,10 +22,13 @@ WRAPPING_PUNCTUATION = [('(', ')'), ('[', ']')]
# List of possible strings used for bullets in bulleted lists. # List of possible strings used for bullets in bulleted lists.
DOTS = ['&middot;', '*', '\u2022', '&#149;', '&bull;', '&#8226;'] DOTS = ['&middot;', '*', '\u2022', '&#149;', '&bull;', '&#8226;']
unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)') unencoded_ampersands_re = _lazy_re_compile(r'&(?!(\w+|#\d+);)')
word_split_re = re.compile(r'''([\s<>"']+)''') word_split_re = _lazy_re_compile(r'''([\s<>"']+)''')
simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE) simple_url_re = _lazy_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) simple_url_2_re = _lazy_re_compile(
r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$',
re.IGNORECASE
)
@keep_lazy(str, SafeString) @keep_lazy(str, SafeString)

View File

@ -16,9 +16,10 @@ from django.core.exceptions import TooManyFieldsSent
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from django.utils.deprecation import RemovedInDjango40Warning from django.utils.deprecation import RemovedInDjango40Warning
from django.utils.functional import keep_lazy_text from django.utils.functional import keep_lazy_text
from django.utils.regex_helper import _lazy_re_compile
# based on RFC 7232, Appendix C # based on RFC 7232, Appendix C
ETAG_MATCH = re.compile(r''' ETAG_MATCH = _lazy_re_compile(r'''
\A( # start of string and capture group \A( # start of string and capture group
(?:W/)? # optional weak indicator (?:W/)? # optional weak indicator
" # opening quote " # opening quote
@ -34,14 +35,14 @@ __M = r'(?P<mon>\w{3})'
__Y = r'(?P<year>\d{4})' __Y = r'(?P<year>\d{4})'
__Y2 = r'(?P<year>\d{2})' __Y2 = r'(?P<year>\d{2})'
__T = r'(?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\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)) RFC1123_DATE = _lazy_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)) RFC850_DATE = _lazy_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)) ASCTIME_DATE = _lazy_re_compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y))
RFC3986_GENDELIMS = ":/?#[]@" RFC3986_GENDELIMS = ":/?#[]@"
RFC3986_SUBDELIMS = "!$&'()*+,;=" RFC3986_SUBDELIMS = "!$&'()*+,;="
FIELDS_MATCH = re.compile('[&;]') FIELDS_MATCH = _lazy_re_compile('[&;]')
@keep_lazy_text @keep_lazy_text

View File

@ -7,6 +7,7 @@ from io import BytesIO
from django.utils.deprecation import RemovedInDjango40Warning from django.utils.deprecation import RemovedInDjango40Warning
from django.utils.functional import SimpleLazyObject, keep_lazy_text, lazy 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 from django.utils.translation import gettext as _, gettext_lazy, pgettext
@ -17,11 +18,11 @@ def capfirst(x):
# Set up regular expressions # Set up regular expressions
re_words = re.compile(r'<[^>]+?>|([^<>\s]+)', re.S) re_words = _lazy_re_compile(r'<[^>]+?>|([^<>\s]+)', re.S)
re_chars = re.compile(r'<[^>]+?>|(.)', re.S) re_chars = _lazy_re_compile(r'<[^>]+?>|(.)', re.S)
re_tag = re.compile(r'<(/)?(\S+?)(?:(\s*/)|\s.*?)?>', re.S) re_tag = _lazy_re_compile(r'<(/)?(\S+?)(?:(\s*/)|\s.*?)?>', re.S)
re_newlines = re.compile(r'\r\n|\r') # Used in normalize_newlines re_newlines = _lazy_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_camel_case = _lazy_re_compile(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))')
@keep_lazy_text @keep_lazy_text
@ -306,7 +307,7 @@ def compress_sequence(sequence):
# Expression to match some_token and some_token="with spaces" (and similarly # Expression to match some_token and some_token="with spaces" (and similarly
# for single-quoted strings). # for single-quoted strings).
smart_split_re = re.compile(r""" smart_split_re = _lazy_re_compile(r"""
((?: ((?:
[^\s'"]* [^\s'"]*
(?: (?:
@ -355,7 +356,7 @@ def _replace_entity(match):
return match.group(0) 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 @keep_lazy_text

View File

@ -1,7 +1,6 @@
""" """
Internationalization support. Internationalization support.
""" """
import re
import warnings import warnings
from contextlib import ContextDecorator from contextlib import ContextDecorator
from decimal import ROUND_UP, Decimal 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.autoreload import autoreload_started, file_changed
from django.utils.deprecation import RemovedInDjango40Warning from django.utils.deprecation import RemovedInDjango40Warning
from django.utils.functional import lazy from django.utils.functional import lazy
from django.utils.regex_helper import _lazy_re_compile
__all__ = [ __all__ = [
'activate', 'deactivate', 'override', 'deactivate_all', 'activate', 'deactivate', 'override', 'deactivate_all',
@ -328,7 +328,7 @@ def get_language_info(lang_code):
return info 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): def trim_whitespace(s):

View File

@ -1,12 +1,12 @@
import re
import warnings import warnings
from io import StringIO from io import StringIO
from django.template.base import TRANSLATOR_COMMENT_MARK, Lexer, TokenType from django.template.base import TRANSLATOR_COMMENT_MARK, Lexer, TokenType
from django.utils.regex_helper import _lazy_re_compile
from . import TranslatorCommentWarning, trim_whitespace from . import TranslatorCommentWarning, trim_whitespace
dot_re = re.compile(r'\S') dot_re = _lazy_re_compile(r'\S')
def blankout(src, char): def blankout(src, char):
@ -17,8 +17,8 @@ def blankout(src, char):
return dot_re.sub(char, src) return dot_re.sub(char, src)
context_re = re.compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""") context_re = _lazy_re_compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""")
inline_re = re.compile( inline_re = _lazy_re_compile(
# Match the trans 'some text' part # Match the trans 'some text' part
r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))""" r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))"""
# Match and ignore optional filters # Match and ignore optional filters
@ -26,10 +26,10 @@ inline_re = re.compile(
# Match the optional context part # Match the optional context part
r"""(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?\s*""" r"""(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?\s*"""
) )
block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""") block_re = _lazy_re_compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""")
endblock_re = re.compile(r"""^\s*endblocktrans$""") endblock_re = _lazy_re_compile(r"""^\s*endblocktrans$""")
plural_re = re.compile(r"""^\s*plural$""") plural_re = _lazy_re_compile(r"""^\s*plural$""")
constant_re = re.compile(r"""_\(((?:".*?")|(?:'.*?'))\)""") constant_re = _lazy_re_compile(r"""_\(((?:".*?")|(?:'.*?'))\)""")
def templatize(src, origin=None): def templatize(src, origin=None):

View File

@ -14,6 +14,7 @@ from django.conf.locale import LANG_INFO
from django.core.exceptions import AppRegistryNotReady from django.core.exceptions import AppRegistryNotReady
from django.core.signals import setting_changed from django.core.signals import setting_changed
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.regex_helper import _lazy_re_compile
from django.utils.safestring import SafeData, mark_safe from django.utils.safestring import SafeData, mark_safe
from . import to_language, to_locale 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 # Format of Accept-Language header values. From RFC 2616, section 14.4 and 3.9
# and RFC 3066, section 2.1 # 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", "*" ([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*q=(0(?:\.\d{,3})?|1(?:\.0{,3})?))? # Optional "q=1.00", "q=0.8"
(?:\s*,\s*|$) # Multiple accepts per header. (?:\s*,\s*|$) # Multiple accepts per header.
''', re.VERBOSE) ''', 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})?$', r'^[a-z]{1,8}(?:-[a-z0-9]{1,8})*(?:@[a-z0-9]{1,20})?$',
re.IGNORECASE re.IGNORECASE
) )
language_code_prefix_re = re.compile(r'^/(\w+([@-]\w+)?)(/|$)') language_code_prefix_re = _lazy_re_compile(r'^/(\w+([@-]\w+)?)(/|$)')
@receiver(setting_changed) @receiver(setting_changed)

View File

@ -13,6 +13,7 @@ from django.utils import timezone
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.module_loading import import_string from django.utils.module_loading import import_string
from django.utils.regex_helper import _lazy_re_compile
from django.utils.version import get_docs_version from django.utils.version import get_docs_version
# Minimal Django templates engine to render the error templates # Minimal Django templates engine to render the error templates
@ -24,7 +25,7 @@ DEBUG_ENGINE = Engine(
libraries={'i18n': 'django.templatetags.i18n'}, libraries={'i18n': 'django.templatetags.i18n'},
) )
HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE', flags=re.IGNORECASE) HIDDEN_SETTINGS = _lazy_re_compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE', flags=re.IGNORECASE)
CLEANSED_SUBSTITUTE = '********************' CLEANSED_SUBSTITUTE = '********************'