| 190 | |
| 191 | |
| 192 | class RegexPattern(CheckURLMixin): |
| 193 | regex = LocaleRegexDescriptor() |
| 194 | |
| 195 | def __init__(self, regex, name=None, is_endpoint=False): |
| 196 | self._regex = regex |
| 197 | self._regex_dict = {} |
| 198 | self._is_endpoint = is_endpoint |
| 199 | self.name = name |
| 200 | self.converters = {} |
| 201 | |
| 202 | def match(self, path): |
| 203 | match = ( |
| 204 | self.regex.fullmatch(path) |
| 205 | if self._is_endpoint and self.regex.pattern.endswith("$") |
| 206 | else self.regex.search(path) |
| 207 | ) |
| 208 | if match: |
| 209 | # If there are any named groups, use those as kwargs, ignoring |
| 210 | # non-named groups. Otherwise, pass all non-named arguments as |
| 211 | # positional arguments. |
| 212 | kwargs = match.groupdict() |
| 213 | args = () if kwargs else match.groups() |
| 214 | kwargs = {k: v for k, v in kwargs.items() if v is not None} |
| 215 | return path[match.end() :], args, kwargs |
| 216 | return None |
| 217 | |
| 218 | def check(self): |
| 219 | warnings = [] |
| 220 | warnings.extend(self._check_pattern_startswith_slash()) |
| 221 | if not self._is_endpoint: |
| 222 | warnings.extend(self._check_include_trailing_dollar()) |
| 223 | return warnings |
| 224 | |
| 225 | def _check_include_trailing_dollar(self): |
| 226 | if self._regex.endswith("$") and not self._regex.endswith(r"\$"): |
| 227 | return [ |
| 228 | Warning( |
| 229 | "Your URL pattern {} uses include with a route ending with a '$'. " |
| 230 | "Remove the dollar from the route to avoid problems including " |
| 231 | "URLs.".format(self.describe()), |
| 232 | id="urls.W001", |
| 233 | ) |
| 234 | ] |
| 235 | else: |
| 236 | return [] |
| 237 | |
| 238 | def __str__(self): |
| 239 | return str(self._regex) |
| 240 | |
| 241 | |
| 242 | _PATH_PARAMETER_COMPONENT_RE = _lazy_re_compile( |
searching dependent graphs…