def _populate(self): lookups = MultiValueDict() namespaces = {} apps = {} language_code = get_language() for pattern in reversed(self.url_patterns): p_pattern = pattern.regex.pattern if p_pattern.startswith('^'): p_pattern = p_pattern[1:] if isinstance(pattern, RegexURLResolver): if pattern.namespace: namespaces[pattern.namespace] = (p_pattern, pattern) if pattern.app_name: apps.setdefault(pattern.app_name, []).append(pattern.namespace) else: parent = normalize(pattern.regex.pattern) for name in pattern.reverse_dict: for matches, pat, defaults in pattern.reverse_dict.getlist(name): new_matches = [] for piece, p_args in parent: new_matches.extend([(piece + suffix, p_args + args) for (suffix, args) in matches]) lookups.appendlist(name, (new_matches, p_pattern + pat, dict(defaults, **pattern.default_kwargs))) for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items(): namespaces[namespace] = (p_pattern + prefix, sub_pattern) for app_name, namespace_list in pattern.app_dict.items(): apps.setdefault(app_name, []).extend(namespace_list) else: bits = normalize(p_pattern) lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args)) if pattern.name is not None: lookups.appendlist(pattern.name, (bits, p_pattern, pattern.default_args)) self._reverse_dict[language_code] = lookups self._namespace_dict[language_code] = namespaces self._app_dict[language_code] = apps
def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs): if args and kwargs: raise ValueError("Don't mix *args and **kwargs in call to reverse()!") try: lookup_view = get_callable(lookup_view, True) except (ImportError, AttributeError) as e: raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e)) possibilities = self.reverse_dict.getlist(lookup_view) prefix_norm, prefix_args = normalize(_prefix)[0] for possibility, pattern, defaults in possibilities: for result, params in possibility: if args: if len(args) != len(params) + len(prefix_args): continue unicode_args = [force_text(val) for val in args] candidate = (prefix_norm + result) % dict(zip(prefix_args + params, unicode_args)) else: if set(kwargs.keys()) | set(defaults.keys()) != set(params) | set(defaults.keys()) | set(prefix_args): continue matches = True for k, v in defaults.items(): if kwargs.get(k, v) != v: matches = False break if not matches: continue unicode_kwargs = dict([(k, force_text(v)) for (k, v) in kwargs.items()]) candidate = (prefix_norm + result) % unicode_kwargs if re.search('^%s%s' % (_prefix, pattern), candidate, re.UNICODE): return candidate # lookup_view can be URL label, or dotted path, or callable, Any of # these can be passed in at the top, but callables are not friendly in # error messages. m = getattr(lookup_view, '__module__', None) n = getattr(lookup_view, '__name__', None) if m is not None and n is not None: lookup_view_s = "%s.%s" % (m, n) else: lookup_view_s = lookup_view raise NoReverseMatch("Reverse for '%s' with arguments '%s' and keyword " "arguments '%s' not found." % (lookup_view_s, args, kwargs))
def test_group_backreference(self): pattern = r"(?P<first_group_name>.*)-(?P=first_group_name)" expected = [('%(first_group_name)s-%(first_group_name)s', ['first_group_name'])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected)
def test_empty(self): pattern = r"" expected = [('', [])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected)
def test_group_named(self): pattern = r"(?P<first_group_name>.*)-(?P<second_group_name>.*)" expected = [('%(first_group_name)s-%(second_group_name)s', ['first_group_name', 'second_group_name'])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected)
def test_group_noncapturing(self): pattern = r"(?:non-capturing)" expected = [('non-capturing', [])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected)
def test_group_ignored(self): pattern = r"(?i)(?L)(?m)(?s)(?u)(?#)" expected = [('', [])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected)
def test_group_positional(self): pattern = r"(.*)-(.+)" expected = [('%(_0)s-%(_1)s', ['_0', '_1'])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected)
def test_escape(self): pattern = r"\\\^\$\.\|\?\*\+\(\)\[" expected = [('\\^$.|?*+()[', [])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected)