Ticket #6934: support-for-more-flexible-url-regex-patterns.patch

File support-for-more-flexible-url-regex-patterns.patch, 2.6 KB (added by sebastian_noack, 7 years ago)
  • django/core/urlresolvers.py

     
    8484
    8585    Raises NoReverseMatch if the args/kwargs aren't valid for the regex.
    8686    """
    87     # TODO: Handle nested parenthesis in the following regex.
    88     result = re.sub(r'\(([^)]+)\)', MatchChecker(args, kwargs), regex.pattern)
    89     return result.replace('^', '').replace('$', '')
     87    url = grouped = ''
     88    level = 0
     89    match_checker = MatchChecker(args, kwargs)
    9090
     91    for c in regex.pattern:
     92        if c == '(':
     93            level += 1
     94            if level == 1:
     95                continue
     96        elif c == ')':
     97            level -= 1
     98            if level == 0:
     99                url += match_checker(grouped)
     100                grouped = ''
     101                continue
     102       
     103        if level == 0:
     104            url += c
     105        else:
     106            grouped += c
     107
     108    return url.replace('^', '').replace('$', '')
     109
    91110class MatchChecker(object):
    92111    "Class used in reverse RegexURLPattern lookup."
    93112    def __init__(self, args, kwargs):
    94113        self.args, self.kwargs = args, kwargs
    95114        self.current_arg = 0
    96115
    97     def __call__(self, match_obj):
    98         # match_obj.group(1) is the contents of the parenthesis.
     116    def __call__(self, grouped):
     117        # grouped is the contents of the outer parenthesis.
    99118        # First we need to figure out whether it's a named or unnamed group.
    100119        #
    101         grouped = match_obj.group(1)
    102120        m = re.search(r'^\?P<(\w+)>(.*?)$', grouped, re.UNICODE)
    103121        if m: # If this was a named group...
    104122            # m.group(1) is the name of the group
     
    115133                    # The arg wasn't passed in.
    116134                    raise NoReverseMatch('Not enough positional arguments passed in')
    117135            test_regex = m.group(2)
    118         else: # Otherwise, this was a positional (unnamed) group.
     136        elif not re.match(r'^\?', grouped, re.UNICODE): # If this was a positional (unnamed) group.
    119137            try:
    120138                value = self.args[self.current_arg]
    121139                self.current_arg += 1
     
    123141                # The arg wasn't passed in.
    124142                raise NoReverseMatch('Not enough positional arguments passed in')
    125143            test_regex = grouped
     144        else: # Otherwise, it was a not-matching, look-ahead, or -behind group.
     145            return u''
    126146        # Note we're using re.match here on purpose because the start of
    127147        # to string needs to match.
    128148        if not re.match(test_regex + '$', force_unicode(value), re.UNICODE):
Back to Top