Exemplo n.º 1
0
 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
Exemplo n.º 2
0
 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
Exemplo n.º 3
0
 def _populate(self):
     # Short-circuit if called recursively in this thread to prevent
     # infinite recursion. Concurrent threads may call this at the same
     # time and will need to continue, so set 'populating' on a
     # thread-local variable.
     if getattr(self._local, 'populating', False):
         return
     try:
         self._local.populating = True
         lookups = MultiValueDict()
         namespaces = {}
         apps = {}
         language_code = get_language()
         for url_pattern in reversed(self.url_patterns):
             p_pattern = url_pattern.pattern.regex.pattern
             if p_pattern.startswith('^'):
                 p_pattern = p_pattern[1:]
             if isinstance(url_pattern, URLPattern):
                 self._callback_strs.add(url_pattern.lookup_str)
                 bits = normalize(url_pattern.pattern.regex.pattern)
                 lookups.appendlist(
                     url_pattern.callback,
                     (bits, p_pattern, url_pattern.default_args, url_pattern.pattern.converters)
                 )
                 if url_pattern.name is not None:
                     lookups.appendlist(
                         url_pattern.name,
                         (bits, p_pattern, url_pattern.default_args, url_pattern.pattern.converters)
                     )
             else:  # url_pattern is a URLResolver.
                 url_pattern._populate()
                 if url_pattern.app_name:
                     apps.setdefault(url_pattern.app_name, []).append(url_pattern.namespace)
                     namespaces[url_pattern.namespace] = (p_pattern, url_pattern)
                 else:
                     for name in url_pattern.reverse_dict:
                         for matches, pat, defaults, converters in url_pattern.reverse_dict.getlist(name):
                             new_matches = normalize(p_pattern + pat)
                             lookups.appendlist(
                                 name,
                                 (
                                     new_matches,
                                     p_pattern + pat,
                                     {**defaults, **url_pattern.default_kwargs},
                                     {**self.pattern.converters, **url_pattern.pattern.converters, **converters}
                                 )
                             )
                     for namespace, (prefix, sub_pattern) in url_pattern.namespace_dict.items():
                         current_converters = url_pattern.pattern.converters
                         sub_pattern.pattern.converters.update(current_converters)
                         namespaces[namespace] = (p_pattern + prefix, sub_pattern)
                     for app_name, namespace_list in url_pattern.app_dict.items():
                         apps.setdefault(app_name, []).extend(namespace_list)
                 self._callback_strs.update(url_pattern._callback_strs)
         self._namespace_dict[language_code] = namespaces
         self._app_dict[language_code] = apps
         self._reverse_dict[language_code] = lookups
         self._populated = True
     finally:
         self._local.populating = False
Exemplo n.º 4
0
 def _populate(self):
     # Short-circuit if called recursively in this thread to prevent
     # infinite recursion. Concurrent threads may call this at the same
     # time and will need to continue, so set 'populating' on a
     # thread-local variable.
     if getattr(self._local, 'populating', False):
         return
     try:
         self._local.populating = True
         lookups = MultiValueDict()
         namespaces = {}
         apps = {}
         language_code = get_language()
         for url_pattern in reversed(self.url_patterns):
             p_pattern = url_pattern.pattern.regex.pattern
             if p_pattern.startswith('^'):
                 p_pattern = p_pattern[1:]
             if isinstance(url_pattern, URLPattern):
                 self._callback_strs.add(url_pattern.lookup_str)
                 bits = normalize(url_pattern.pattern.regex.pattern)
                 lookups.appendlist(
                     url_pattern.callback,
                     (bits, p_pattern, url_pattern.default_args, url_pattern.pattern.converters)
                 )
                 if url_pattern.name is not None:
                     lookups.appendlist(
                         url_pattern.name,
                         (bits, p_pattern, url_pattern.default_args, url_pattern.pattern.converters)
                     )
             else:  # url_pattern is a URLResolver.
                 url_pattern._populate()
                 if url_pattern.app_name:
                     apps.setdefault(url_pattern.app_name, []).append(url_pattern.namespace)
                     namespaces[url_pattern.namespace] = (p_pattern, url_pattern)
                 else:
                     for name in url_pattern.reverse_dict:
                         for matches, pat, defaults, converters in url_pattern.reverse_dict.getlist(name):
                             new_matches = normalize(p_pattern + pat)
                             lookups.appendlist(
                                 name,
                                 (
                                     new_matches,
                                     p_pattern + pat,
                                     {**defaults, **url_pattern.default_kwargs},
                                     {**self.pattern.converters, **url_pattern.pattern.converters, **converters}
                                 )
                             )
                     for namespace, (prefix, sub_pattern) in url_pattern.namespace_dict.items():
                         current_converters = url_pattern.pattern.converters
                         sub_pattern.pattern.converters.update(current_converters)
                         namespaces[namespace] = (p_pattern + prefix, sub_pattern)
                     for app_name, namespace_list in url_pattern.app_dict.items():
                         apps.setdefault(app_name, []).extend(namespace_list)
                 self._callback_strs.update(url_pattern._callback_strs)
         self._namespace_dict[language_code] = namespaces
         self._app_dict[language_code] = apps
         self._reverse_dict[language_code] = lookups
         self._populated = True
     finally:
         self._local.populating = False
Exemplo n.º 5
0
 def _get_reverse_dict(self):
     if not self._reverse_dict and hasattr(self.urlconf_module,
                                           'urlpatterns'):
         lookups = MultiValueDict()
         for pattern in reversed(self.urlconf_module.urlpatterns):
             p_pattern = pattern.regex.pattern
             if p_pattern.startswith('^'):
                 p_pattern = p_pattern[1:]
             if isinstance(pattern, RegexURLResolver):
                 parent = normalize(pattern.regex.pattern)
                 for name in pattern.reverse_dict:
                     for matches, pat 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))
             else:
                 bits = normalize(p_pattern)
                 lookups.appendlist(pattern.callback, (bits, p_pattern))
                 lookups.appendlist(pattern.name, (bits, p_pattern))
         self._reverse_dict = lookups
     return self._reverse_dict
Exemplo n.º 6
0
    def _populate(self):
        lookups = MultiValueDict()
        namespaces = {}
        apps = {}
        language_code = get_language()
        for pattern in reversed(self.url_patterns):
            if hasattr(pattern, '_callback_str'):
                self._callback_strs.add(pattern._callback_str)
            elif hasattr(pattern, '_callback'):
                callback = pattern._callback
                if isinstance(callback, functools.partial):
                    callback = callback.func

                if not hasattr(callback, '__name__'):
                    lookup_str = callback.__module__ + "." + callback.__class__.__name__
                else:
                    lookup_str = callback.__module__ + "." + callback.__name__
                self._callback_strs.add(lookup_str)
            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_pat = pattern.regex.pattern
                    for name in pattern.reverse_dict:
                        for matches, pat, defaults in pattern.reverse_dict.getlist(
                                name):
                            new_matches = normalize(parent_pat + pat)
                            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)
                    self._callback_strs.update(pattern._callback_strs)
            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
        self._populated = True
Exemplo n.º 7
0
 def _populate(self):
     if self._populating:
         return
     self._populating = True
     lookups = MultiValueDict()
     namespaces = {}
     apps = {}
     language_code = get_language()
     for pattern in reversed(self.url_patterns):
         if isinstance(pattern, RegexURLPattern):
             self._callback_strs.add(pattern.lookup_str)
         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_pat = pattern.regex.pattern
                 for name in pattern.reverse_dict:
                     for matches, pat, defaults in pattern.reverse_dict.getlist(
                             name):
                         new_matches = normalize(parent_pat + pat)
                         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)
             if not pattern._populating:
                 pattern._populate()
             self._callback_strs.update(pattern._callback_strs)
         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
     self._populated = True
     self._populating = False
Exemplo n.º 8
0
    def _populate(self):
        lookups = MultiValueDict()
        namespaces = {}
        apps = {}
        language_code = get_language()
        for pattern in reversed(self.url_patterns):
            if hasattr(pattern, '_callback_str'):
                self._callback_strs.add(pattern._callback_str)
            elif hasattr(pattern, '_callback'):
                callback = pattern._callback
                if isinstance(callback, functools.partial):
                    callback = callback.func

                if not hasattr(callback, '__name__'):
                    lookup_str = callback.__module__ + "." + callback.__class__.__name__
                else:
                    lookup_str = callback.__module__ + "." + callback.__name__
                self._callback_strs.add(lookup_str)
            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_pat = pattern.regex.pattern
                    for name in pattern.reverse_dict:
                        for matches, pat, defaults in pattern.reverse_dict.getlist(name):
                            new_matches = normalize(parent_pat + pat)
                            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)
                    self._callback_strs.update(pattern._callback_strs)
            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
        self._populated = True
Exemplo n.º 9
0
 def _populate(self):
     if self._populating:
         return
     self._populating = True
     lookups = MultiValueDict()
     namespaces = {}
     apps = {}
     language_code = get_language()
     for pattern in reversed(self.url_patterns):
         if isinstance(pattern, RegexURLPattern):
             self._callback_strs.add(pattern.lookup_str)
         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_pat = pattern.regex.pattern
                 for name in pattern.reverse_dict:
                     for matches, pat, defaults in pattern.reverse_dict.getlist(name):
                         new_matches = normalize(parent_pat + pat)
                         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)
             if not pattern._populating:
                 pattern._populate()
             self._callback_strs.update(pattern._callback_strs)
         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
     self._populated = True
     self._populating = False
Exemplo n.º 10
0
 def _populate(self):
     # Short-circuit if called recursively in this thread to prevent
     # infinite recursion. Concurrent threads may call this at the same
     # time and will need to continue, so set 'populating' on a
     # thread-local variable.
     if getattr(self._local, "populating", False):
         return
     self._local.populating = True
     lookups = MultiValueDict()
     namespaces = {}
     apps = {}
     language_code = get_language()
     for pattern in reversed(self.url_patterns):
         if isinstance(pattern, RegexURLPattern):
             self._callback_strs.add(pattern.lookup_str)
         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_pat = pattern.regex.pattern
                 for name in pattern.reverse_dict:
                     for matches, pat, defaults in pattern.reverse_dict.getlist(name):
                         new_matches = normalize(parent_pat + pat)
                         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)
             if not getattr(pattern._local, "populating", False):
                 pattern._populate()
             self._callback_strs.update(pattern._callback_strs)
         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
     self._populated = True
     self._local.populating = False
Exemplo n.º 11
0
    def _get_named_urls(resolver, ns="",pattern="",parts=None):
        if resolver.namespace:
            if not include_admin \
                    and ns=="" \
                    and resolver.namespace=='admin':return []
            if not ns=='':
                ns += "__"
            ns += resolver.namespace

        if not parts:
            parts = []

        norml = normalize(resolver.regex.pattern)
        if len(norml)>1: raise Exception('jsurls currently can only deal with a single path')
        norml = norml[0]

        _pattern,_parts = norml
        pattern += _pattern 

        parts.extend(_parts)

        rslts=[]    
        for r in resolver.url_patterns:
            if r.__class__==RegexURLResolver:
                rslts.extend(_get_named_urls(r,ns=ns,pattern=pattern,parts=parts))

        for p in resolver.url_patterns:
            if p.__class__==RegexURLPattern and p.name and p.name!="":
                name = ns and ns or ""
                if not name=="":
                    name += '__'
                name += p.name

                norml = normalize(p.regex.pattern)
                if len(norml)>1: raise Exception('jsurls currently can only deal with a single path')
                norml = norml[0]

                _pattern,_parts = norml

                _pat = pattern + _pattern 

                _par = []
                _par.extend(parts)
                _par.extend(_parts)

                rslts.append(JSUrl(name,_pat,_par))

        return rslts
Exemplo n.º 12
0
 def walk_urlpatterns(obj, parents):
     if isinstance(obj, list):
         for item in obj:
             walk_urlpatterns(item, parents)
     elif isinstance(obj, RegexURLResolver):
         if obj.namespace is None:
             parents += (obj, )
             walk_urlpatterns(obj.url_patterns, parents)
     elif isinstance(obj, RegexURLPattern):
         for name in names:
             if name == obj.name:
                 pattern = '^/'
                 for parent in parents:
                     pattern += parent.regex.pattern.lstrip('^')
                 pattern += obj.regex.pattern.lstrip('^')
                 [(replace_pattern, kwargs)] = normalize(pattern)
                 test_pattern = pattern
                 for kwarg in kwargs:
                     test_pattern = test_pattern.replace(
                         '?P<{}>'.format(kwarg), '')
                 test_pattern = test_pattern.replace('\\', '\\\\')
                 data[name] = {
                     'replace_pattern': replace_pattern,
                     'test_pattern': test_pattern,
                     'kwargs': kwargs,
                 }
Exemplo n.º 13
0
    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()!")
        text_args = [force_text(v) for v in args]
        text_kwargs = dict((k, force_text(v)) for (k, v) in kwargs.items())

        if not self._populated:
            self._populate()

        try:
            if lookup_view in self._callback_strs:
                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(urlquote(_prefix))[0]
        for possibility, pattern, defaults in possibilities:
            for result, params in possibility:
                if args:
                    if len(args) != len(params) + len(prefix_args):
                        continue
                    candidate_subs = dict(zip(prefix_args + params, text_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
                    candidate_subs = text_kwargs
                # WSGI provides decoded URLs, without %xx escapes, and the URL
                # resolver operates on such URLs. First substitute arguments
                # without quoting to build a decoded URL and look for a match.
                # Then, if we have a match, redo the substitution with quoted
                # arguments in order to return a properly encoded URL.
                candidate_pat = prefix_norm.replace("%", "%%") + result
                if re.search("^%s%s" % (prefix_norm, pattern), candidate_pat % candidate_subs, re.UNICODE):
                    candidate_subs = dict((k, urlquote(v)) for (k, v) in candidate_subs.items())
                    return candidate_pat % candidate_subs
        # 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

        patterns = [pattern for (possibility, pattern, defaults) in possibilities]
        raise NoReverseMatch(
            "Reverse for '%s' with arguments '%s' and keyword "
            "arguments '%s' not found. %d pattern(s) tried: %s" % (lookup_view_s, args, kwargs, len(patterns), patterns)
        )
Exemplo n.º 14
0
def subscriber_url(channel):
    push_server = getattr(settings, 'PUSH_SERVER', {})
    subscriber_host = push_server.get('subscriber_host', {})
    subscriber_host_location = subscriber_host.get('location', current_host)
    subscriber_host_secure = subscriber_host.get('secure', False)
    subscriber_pattern = None
    for location in push_server.get('locations', ()):
        if location.get('type') == 'subscriber':
            subscriber_pattern = location.get('url')
            # TODO: Currently we support only the first subscriber URL
            break
    if not subscriber_host_location or not subscriber_pattern:
        raise ValueError("Missing required settings")
    subscriber = regex_helper.normalize(subscriber_pattern)
    if len(subscriber) != 1 or len(subscriber[0][1]) != 1:
        raise ValueError("Non-reversible reg-exp: '%s'" % (subscriber_pattern,))
    subscriber, (arg,) = subscriber[0]
    subscriber = subscriber % {
        arg: channel,
    }
    return 'http{0}://{1}{2}'.format(
        ('s' if subscriber_host_secure else ''),
        subscriber_host_location,
        subscriber,
    )
    def generate(self, **kwargs):
        for pattern in self.patterns:
            normalized_patterns = normalize(pattern.pattern)
            for normalized_pattern in normalized_patterns:
                args = kwargs.copy()
                if args.has_key('month'):
                    args['week_or_month_selector'] = 'm'
                    args['week_or_month'] = args['month']
                    del args['month']
                if args.has_key('week'):
                    if args.has_key('day'):
                        raise TypeError
                    args['week_or_month_selector'] = 'w'
                    args['week_or_month'] = args['week']
                    del args['week']

                keys = args.keys()
                keys.sort()

                allowed_keys = normalized_pattern[1]
                allowed_keys.sort()

                if keys == allowed_keys:
                    self.selector = normalized_pattern[0] % args
                    if self.is_valid():
                        self.populate()
                        return self.selector

        raise TypeError
Exemplo n.º 16
0
def reverse_subdomain(name, args=(), kwargs=None):
    if args and kwargs:
        raise ValueError("Don't mix *args and **kwargs in call to reverse()!")

    if kwargs is None:
        kwargs = {}

    try:
        subdomain = settings.SUBDOMAINS[name]
    except KeyError:
        raise NoReverseMatch("No subdomain called %s exists" % name)

    unicode_args = [force_unicode(x) for x in args]
    unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()])

    for result, params in normalize(subdomain['regex']):
        if args:
            if len(args) != len(params):
                continue
            candidate = result % dict(zip(params, unicode_args))
        else:
            if set(kwargs.keys()) != set(params):
                continue
            candidate = result % unicode_kwargs

        if re.match(subdomain['regex'], candidate, re.UNICODE):
            return candidate

    raise NoReverseMatch(
        "Reverse subdomain for '%s' with arguments '%s' and keyword arguments "
        "'%s' not found." % (name, args, kwargs))
Exemplo n.º 17
0
def reverse_host(name, args=None, kwargs=None):
    if args and kwargs:
        raise ValueError("Don't mix *args and **kwargs in call to reverse()!")

    if args is None:
        args = ()
    if kwargs is None:
        kwargs = {}

    unicode_args = [force_unicode(x) for x in args]
    unicode_kwargs = dict(((k, force_unicode(v)) for (k, v) in kwargs.iteritems()))

    host = get_host(name)
    for result, params in normalize(host.regex):
        if args:
            if len(args) != len(params):
                continue
            candidate = result % dict(zip(params, unicode_args))
        else:
            if set(kwargs.keys()) != set(params):
                continue
            candidate = result % unicode_kwargs

        if re.match(host.regex, candidate, re.UNICODE):
            return candidate

    raise NoReverseMatch("Reverse host for '%s' with arguments '%s' and "
                         "keyword arguments '%s' not found."
                         % (name, args, kwargs))
Exemplo n.º 18
0
def reverse_subdomain(name, args=(), kwargs=None):
    if args and kwargs:
        raise ValueError("Don't mix *args and **kwargs in call to reverse()!")

    if kwargs is None:
        kwargs = {}

    try:
        subdomain = settings.SUBDOMAINS[name]
    except KeyError:
        raise NoReverseMatch("No subdomain called %s exists" % name)

    unicode_args = [force_unicode(x) for x in args]
    unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()])

    for result, params in normalize(subdomain['regex']):
        if args:
            if len(args) != len(params):
                continue
            candidate = result % dict(zip(params, unicode_args))
        else:
            if set(kwargs.keys()) != set(params):
                continue
            candidate = result % unicode_kwargs

        if re.match(subdomain['regex'], candidate, re.UNICODE):
            return candidate

    raise NoReverseMatch(
        "Reverse subdomain for '%s' with arguments '%s' and keyword arguments "
        "'%s' not found." % (name, args, kwargs)
    )
Exemplo n.º 19
0
    def _populate_subresolver(self, resolver, lookups, namespaces, apps):
        # XXX emulate part of _populate :/

        if hasattr(resolver, '_callback_str'):
            self._callback_strs.add(resolver._callback_str)
        elif hasattr(resolver, '_callback'):
            callback = resolver._callback
            if isinstance(callback, functools.partial):
                callback = callback.func

            if not hasattr(callback, '__name__'):
                lookup_str = callback.__module__ + "." + callback.__class__.__name__
            else:
                lookup_str = callback.__module__ + "." + callback.__name__
            self._callback_strs.add(lookup_str)
        p_pattern = resolver.regex.pattern
        if p_pattern.startswith('^'):
            p_pattern = p_pattern[1:]
        if isinstance(resolver, RegexURLResolver):
            if resolver.namespace:
                namespaces[resolver.namespace] = (p_pattern, resolver)
                if resolver.app_name:
                    apps.setdefault(resolver.app_name,
                                    []).append(resolver.namespace)
            else:
                parent_pat = resolver.regex.pattern
                for name in resolver.reverse_dict:
                    for matches, pat, defaults in resolver.reverse_dict.getlist(
                            name):
                        new_matches = normalize(parent_pat + pat)
                        lookups.appendlist(
                            name, (new_matches, p_pattern + pat,
                                   dict(defaults, **resolver.default_kwargs)))
                for namespace, (
                        prefix,
                        sub_pattern) in resolver.namespace_dict.items():
                    namespaces[namespace] = (p_pattern + prefix, sub_pattern)
                for app_name, namespace_list in resolver.app_dict.items():
                    apps.setdefault(app_name, []).extend(namespace_list)
                self._callback_strs.update(resolver._callback_strs)
        else:
            bits = normalize(p_pattern)
            lookups.appendlist(resolver.callback,
                               (bits, p_pattern, resolver.default_args))
            if resolver.name is not None:
                lookups.appendlist(resolver.name,
                                   (bits, p_pattern, resolver.default_args))
Exemplo n.º 20
0
 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)
Exemplo n.º 21
0
    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()!")

        if not self._populated:
            self._populate()

        try:
            if lookup_view in self._callback_strs:
                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(urlquote(_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.replace('%', '%%') +
                                 result) % unicode_kwargs
                if re.search('^%s%s' % (prefix_norm, pattern), candidate,
                             re.UNICODE):
                    if candidate.startswith('//'):
                        candidate = '/%%2F%s' % candidate[2:]
                    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))
Exemplo n.º 22
0
 def test_group_ignored(self):
     pattern = r"(?i)(?L)(?m)(?s)(?u)(?#)"
     expected = [('', [])]
     with warnings.catch_warnings(record=True) as warns:
         warnings.simplefilter('always')
         result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
     for i, char in enumerate('iLmsu#'):
         self.assertEqual(str(warns[i].message), 'Using (?%s) in url() patterns is deprecated.' % char)
Exemplo n.º 23
0
    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()!")
        text_args = [force_text(v) for v in args]
        text_kwargs = dict((k, force_text(v)) for (k, v) in kwargs.items())

        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(urlquote(_prefix))[0]
        for possibility, pattern, defaults in possibilities:
            for result, params in possibility:
                if args:
                    if len(args) != len(params) + len(prefix_args):
                        continue
                    candidate_subs = dict(zip(prefix_args + params, text_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
                    candidate_subs = text_kwargs
                # WSGI provides decoded URLs, without %xx escapes, and the URL
                # resolver operates on such URLs. First substitute arguments
                # without quoting to build a decoded URL and look for a match.
                # Then, if we have a match, redo the substitution with quoted
                # arguments in order to return a properly encoded URL.
                candidate_pat = prefix_norm.replace('%', '%%') + result
                if re.search('^%s%s' % (prefix_norm, pattern),
                             candidate_pat % candidate_subs, re.UNICODE):
                    candidate_subs = dict(
                        (k, urlquote(v)) for (k, v) in candidate_subs.items())
                    return candidate_pat % candidate_subs
        # 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))
Exemplo n.º 24
0
 def _get_reverse_dict(self):
     if not self._reverse_dict:
         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):
                 parent = normalize(pattern.regex.pattern)
                 for name in pattern.reverse_dict:
                     for matches, pat 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])
                         self._reverse_dict.appendlist(name, (new_matches, p_pattern + pat))
             else:
                 bits = normalize(p_pattern)
                 self._reverse_dict.appendlist(pattern.callback, (bits, p_pattern))
                 self._reverse_dict.appendlist(pattern.name, (bits, p_pattern))
     return self._reverse_dict
Exemplo n.º 25
0
 def _get_reverse_dict(self):
     if not self._reverse_dict and hasattr(self.urlconf_module, 'urlpatterns'):
         for pattern in reversed(self.urlconf_module.urlpatterns):
             p_pattern = pattern.regex.pattern
             if p_pattern.startswith('^'):
                 p_pattern = p_pattern[1:]
             if isinstance(pattern, RegexURLResolver):
                 parent = normalize(pattern.regex.pattern)
                 for name, (matches, pat) in pattern.reverse_dict.items():
                     new_matches = []
                     for piece, p_args in parent:
                         new_matches.extend([(piece + suffix, p_args + args)
                                 for (suffix, args) in matches])
                     self._reverse_dict[name] = new_matches, p_pattern + pat
             else:
                 bits = normalize(p_pattern)
                 self._reverse_dict[pattern.callback] = bits, p_pattern
                 self._reverse_dict[pattern.name] = bits, p_pattern
     return self._reverse_dict
Exemplo n.º 26
0
 def _get_reverse_dict(self):
     if not self._reverse_dict and hasattr(self.urlconf_module, 'urlpatterns'):
         for pattern in reversed(self.urlconf_module.urlpatterns):
             p_pattern = pattern.regex.pattern
             if p_pattern.startswith('^'):
                 p_pattern = p_pattern[1:]
             if isinstance(pattern, RegexURLResolver):
                 parent = normalize(pattern.regex.pattern)
                 for name, (matches, pat) in pattern.reverse_dict.iteritems():
                     new_matches = []
                     for piece, p_args in parent:
                         new_matches.extend([(piece + suffix, p_args + args)
                                 for (suffix, args) in matches])
                     self._reverse_dict[name] = new_matches, p_pattern + pat
             else:
                 bits = normalize(p_pattern)
                 self._reverse_dict[pattern.callback] = bits, p_pattern
                 self._reverse_dict[pattern.name] = bits, p_pattern
     return self._reverse_dict
Exemplo n.º 27
0
def reverse_host(host, args=None, kwargs=None):
    """
    Given the host name and the appropriate parameters,
    reverses the host, e.g.::

        >>> from django.conf import settings
        >>> settings.ROOT_HOSTCONF = 'mysite.hosts'
        >>> settings.PARENT_HOST = 'example.com'
        >>> from django_hosts.resolvers import reverse_host
        >>> reverse_host('with_username', args=('jezdez',))
        'jezdez.example.com'

    :param name: the name of the host as specified in the hostconf
    :param args: the host arguments to use to find a matching entry in the
                 hostconf
    :param kwargs: similar to args but key value arguments
    :raises django.core.urlresolvers.NoReverseMatch: if no host matches
    :rtype: reversed hostname
    """
    if args and kwargs:
        raise ValueError("Don't mix *args and **kwargs in call to reverse()!")

    args = args or ()
    kwargs = kwargs or {}

    if not isinstance(host, host_cls):
        host = get_host(host)

    unicode_args = [force_text(x) for x in args]
    unicode_kwargs = dict(((k, force_text(v))
                          for (k, v) in six.iteritems(kwargs)))

    for result, params in normalize(host.regex):
        if args:
            if len(args) != len(params):
                continue
            candidate = result % dict(zip(params, unicode_args))
        else:
            if set(kwargs.keys()) != set(params):
                continue
            candidate = result % unicode_kwargs

        if re.match(host.regex, candidate, re.UNICODE):  # pragma: no cover
            parent_host = getattr(settings, 'PARENT_HOST', '').lstrip('.')
            if parent_host:
                # only add the parent host when needed (aka www-less domain)
                if candidate and candidate != parent_host:
                    candidate = '%s.%s' % (candidate, parent_host)
                else:
                    candidate = parent_host
            return candidate

    raise NoReverseMatch("Reverse host for '%s' with arguments '%s' "
                         "and keyword arguments '%s' not found." %
                         (host.name, args, kwargs))
Exemplo n.º 28
0
def reverse_host(host, args=None, kwargs=None):
    """
    Given the host name and the appropriate parameters,
    reverses the host, e.g.::

        >>> from django.conf import settings
        >>> settings.ROOT_HOSTCONF = 'mysite.hosts'
        >>> settings.PARENT_HOST = 'example.com'
        >>> from django_hosts.resolvers import reverse_host
        >>> reverse_host('with_username', args=('jezdez',))
        'jezdez.example.com'

    :param name: the name of the host as specified in the hostconf
    :param args: the host arguments to use to find a matching entry in the
                 hostconf
    :param kwargs: similar to args but key value arguments
    :raises django.core.urlresolvers.NoReverseMatch: if no host matches
    :rtype: reversed hostname
    """
    if args and kwargs:
        raise ValueError("Don't mix *args and **kwargs in call to reverse()!")

    args = args or ()
    kwargs = kwargs or {}

    if not isinstance(host, host_cls):
        host = get_host(host)

    unicode_args = [force_text(x) for x in args]
    unicode_kwargs = dict(
        ((k, force_text(v)) for (k, v) in dict.items(kwargs)))

    for result, params in normalize(host.regex):
        if args:
            if len(args) != len(params):
                continue
            candidate = result % dict(zip(params, unicode_args))
        else:
            if set(kwargs.keys()) != set(params):
                continue
            candidate = result % unicode_kwargs

        if re.match(host.regex, candidate, re.UNICODE):  # pragma: no cover
            parent_host = getattr(settings, 'PARENT_HOST', '').lstrip('.')
            if parent_host:
                # only add the parent host when needed (aka www-less domain)
                if candidate and candidate != parent_host:
                    candidate = '%s.%s' % (candidate, parent_host)
                else:
                    candidate = parent_host
            return candidate

    raise NoReverseMatch("Reverse host for '%s' with arguments '%s' "
                         "and keyword arguments '%s' not found." %
                         (host.name, args, kwargs))
Exemplo n.º 29
0
 def _build_reverse_dict_for_lang(self, lang):
     reverse_dict = MultiValueDict()
     namespaces = {}
     apps = {}
     for pattern in reversed(self.url_patterns):
         if hasattr(pattern, 'get_regex'):
             p_pattern = pattern.get_regex(lang).pattern
         else:
             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:
                 if hasattr(pattern, 'get_regex'):
                     parent = normalize(pattern.get_regex(lang).pattern)
                 else:
                     parent = normalize(pattern.regex.pattern)
                 if hasattr(pattern, 'get_reverse_dict'):
                     sub_reverse_dict = pattern.get_reverse_dict(lang)
                 else:
                     sub_reverse_dict = pattern.reverse_dict
                 for name in sub_reverse_dict:
                     for matches, pat in sub_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])
                         reverse_dict.appendlist(name, (new_matches, p_pattern + pat))
                 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)
             reverse_dict.appendlist(pattern.callback, (bits, p_pattern))
             reverse_dict.appendlist(pattern.name, (bits, p_pattern))
     self._namespace_dict = namespaces
     self._app_dict = apps
     return reverse_dict
Exemplo n.º 30
0
 def _build_reverse_dict_for_lang(self, lang):
     reverse_dict = MultiValueDict()
     namespaces = {}
     apps = {}
     for pattern in reversed(self.url_patterns):
         if hasattr(pattern, 'get_regex'):
             p_pattern = pattern.get_regex(lang).pattern
         else:
             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:
                 if hasattr(pattern, 'get_regex'):
                     parent = normalize(pattern.get_regex(lang).pattern)
                 else:
                     parent = normalize(pattern.regex.pattern)
                 if hasattr(pattern, 'get_reverse_dict'):
                     sub_reverse_dict = pattern.get_reverse_dict(lang)
                 else:
                     sub_reverse_dict = pattern.reverse_dict
                 for name in sub_reverse_dict:
                     for matches, pat in sub_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])
                         reverse_dict.appendlist(name, (new_matches, p_pattern + pat))
                 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)
             reverse_dict.appendlist(pattern.callback, (bits, p_pattern))
             reverse_dict.appendlist(pattern.name, (bits, p_pattern))
     self._namespace_dict = namespaces
     self._app_dict = apps
     return reverse_dict
Exemplo n.º 31
0
 def get_context_data(self, **kwargs):
     context = super(ScriptUrls, self).get_context_data(**kwargs)
     url_dict = {}
     from django.core.urlresolvers import reverse
     from django.utils.regex_helper import normalize
     from feedreader_api.api0 import urls as api_urls
     for url in api_urls.urlpatterns:
         url_dict[url.name] = normalize(url.regex.pattern)[0][0]
     context['urls'] = url_dict
     #context['latest_articles'] = Article.objects.all()[:5]
     return context
Exemplo n.º 32
0
 def test_group_ignored(self):
     pattern = r"(?i)(?L)(?m)(?s)(?u)(?#)"
     expected = [('', [])]
     with warnings.catch_warnings(record=True) as warns:
         warnings.simplefilter('always')
         result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
     for i, char in enumerate('iLmsu#'):
         self.assertEqual(
             str(warns[i].message),
             'Using (?%s) in url() patterns is deprecated.' % char)
Exemplo n.º 33
0
    def _populate_subresolver(self, resolver, lookups, namespaces, apps):
        # XXX emulate part of _populate :/

        if hasattr(resolver, '_callback_str'):
            self._callback_strs.add(resolver._callback_str)
        elif hasattr(resolver, '_callback'):
            callback = resolver._callback
            if isinstance(callback, functools.partial):
                callback = callback.func

            if not hasattr(callback, '__name__'):
                lookup_str = callback.__module__ + "." + callback.__class__.__name__
            else:
                lookup_str = callback.__module__ + "." + callback.__name__
            self._callback_strs.add(lookup_str)
        p_pattern = resolver.regex.pattern
        if p_pattern.startswith('^'):
            p_pattern = p_pattern[1:]
        if isinstance(resolver, RegexURLResolver):
            if resolver.namespace:
                namespaces[resolver.namespace] = (p_pattern, resolver)
                if resolver.app_name:
                    apps.setdefault(resolver.app_name, []).append(resolver.namespace)
            else:
                parent_pat = resolver.regex.pattern
                for name in resolver.reverse_dict:
                    for matches, pat, defaults in resolver.reverse_dict.getlist(name):
                        new_matches = normalize(parent_pat + pat)
                        lookups.appendlist(name,
                            (new_matches, p_pattern + pat, dict(defaults, **resolver.default_kwargs)))
                for namespace, (prefix, sub_pattern) in resolver.namespace_dict.items():
                    namespaces[namespace] = (p_pattern + prefix, sub_pattern)
                for app_name, namespace_list in resolver.app_dict.items():
                    apps.setdefault(app_name, []).extend(namespace_list)
                self._callback_strs.update(resolver._callback_strs)
        else:
            bits = normalize(p_pattern)
            lookups.appendlist(resolver.callback, (bits, p_pattern, resolver.default_args))
            if resolver.name is not None:
                lookups.appendlist(resolver.name, (bits, p_pattern, resolver.default_args))
Exemplo n.º 34
0
def endpoint_string_pattern(viewname, with_host=False, pattern_subdomain='www', force_secure=False):
    urlconf = get_urlconf()
    resolver = get_resolver(urlconf)
    args = resolver.reverse_dict[viewname][0][0][1][:]
    pattern = resolver.reverse_dict[viewname][0][0][0]
    prefix = get_script_prefix()
    prefix_norm, prefix_args = normalize(urlquote(prefix))[0]
    candidate_pat = prefix_norm.replace('%', '%%') + pattern
    pattern_args = {arg: '{%s}' % arg for arg in args}
    path = candidate_pat % pattern_args
    if with_host:
        return '%s//%s.%s%s' % (('https:' if force_secure else ''), pattern_subdomain, settings.TOP_DOMAIN, path)

    return path
Exemplo n.º 35
0
    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()!")

        if not self._populated:
            self._populate()

        try:
            if lookup_view in self._callback_strs:
                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(urlquote(_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.replace('%', '%%') + result) % unicode_kwargs
                if re.search('^%s%s' % (prefix_norm, pattern), candidate, re.UNICODE):
                    if candidate.startswith('//'):
                        candidate = '/%%2F%s' % candidate[2:]
                    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))
Exemplo n.º 36
0
    def normalize_url_pattern(url_pattern):
        normalized = normalize(url_pattern)

        try:
            [(url_as_str, url_params)] = normalized
        except ValueError:
            try:
                [(url_as_str_without_param, _),
                 (url_as_str, url_params)] = normalized
            except ValueError:
                raise UrlStructureNotSupported

        if 'format' in url_params and url_as_str.endswith('.%(format)s'):
            # remove optional parameter provided by DRF ViewSet
            # eg. /items is provided as /items.%(format)s (/items.json)
            url_params.remove('format')
            url_as_str = url_as_str[:-len('.%(format)s')]

        return url_as_str, url_params
Exemplo n.º 37
0
def reverse_route(route_name, args=None, kwargs=None):
    args = args or []
    kwargs = kwargs or {}
    prefix = get_script_prefix()

    try:
        route = Route.objects.filter(name=route_name).get()
    except Route.DoesNotExist:
        msg = ("Reverse for '%s' not found." % (route_name))
        raise NoReverseMatch(msg)

    converters = _route_to_regex(route.path)[1]

    for result, params in normalize(_route_to_regex(route.path)[0]):
        if args:
            if len(args) != len(params):
                continue
            candidate_subs = dict(zip(params, args))
        else:
            if set(kwargs).symmetric_difference(params):
                continue
            candidate_subs = kwargs

        text_candidate_subs = {}
        for k, v in candidate_subs.items():
            if k in converters:
                text_candidate_subs[k] = converters[k].to_url(v)
            else:
                text_candidate_subs[k] = str(v)

        candidate_pat = prefix.replace('%', '%%') + result
        url = urllib.parse.quote(candidate_pat % text_candidate_subs,
                                 safe=RFC3986_SUBDELIMS + '/~:@')
        return escape_leading_slashes(url)

    if args:
        arg_msg = "arguments '%s'" % (args, )
    elif kwargs:
        arg_msg = "keyword arguments '%s'" % (kwargs, )
    else:
        arg_msg = "no arguments"
    msg = ("Reverse for '%s' with %s not matched." % (route_name, arg_msg))
    raise NoReverseMatch(msg)
Exemplo n.º 38
0
def inspect_pattern(pattern, prefix=None):
    prefix = prefix or ''
    view, decorators = extract_view(pattern.callback)
    module = inspect.getmodule(view)

    if inspect.isfunction(view):
        argspec = inspect.getargspec(view)
    else:
        argspec = None

    annotations = {}
    group_names = {}
    normalized_pattern, groups = regex_helper.normalize(prefix + pattern.regex.pattern)[0]
    for group in groups:
        try:
            group_number = int(group.strip('_'))
        except ValueError:
            group_number = None
        if argspec is not None and group_number is not None:
            try:
                group_name = argspec[0][group_number + 1]
            except IndexError:
                group_name = group
        else:
            group_name = group
        annotations[group] = '<span class="capturegroup">&lt;%s&gt;</span>' % group_name
        group_names[group] = group_name

    return {
        'view_module': module.__name__,
        'view_name': view.__name__,
        'prefix': prefix,
        'regex': pattern.regex.pattern,
        'name': pattern.name,
        'default_args': pattern.default_args,
        'annotated_pattern': normalized_pattern % annotations,
        'normalized_pattern': normalized_pattern % group_names,
        'raw_pattern': prefix + pattern.regex.pattern,
    }
Exemplo n.º 39
0
def subscriber_url(channel):
    push_server = getattr(settings, 'PUSH_SERVER', {})
    port = push_server.get('port', 80)
    subscriber_pattern = None
    for location in push_server.get('locations', ()):
        if location.get('type') == 'subscriber':
            subscriber_pattern = location.get('url')
            # TODO: Currently we support only the first subscriber URL
            break
    if port == 80:
        port = ''
    else:
        port = ':%s' % (port,)
    address = push_server.get('address')
    if not (address and subscriber_pattern):
        raise ValueError("Missing required settings")
    subscriber = regex_helper.normalize(subscriber_pattern)
    if len(subscriber) != 1 or len(subscriber[0][1]) != 1:
        raise ValueError("Non-reversible reg-exp: '%s'" % (subscriber_pattern,))
    subscriber, (arg,) = subscriber[0]
    subscriber = subscriber % {
        arg: channel,
    }
    return 'http://%s%s%s' % (address, port, subscriber)
Exemplo n.º 40
0
 def test_group_positional(self):
     pattern = r"(.*)-(.+)"
     expected = [('%(_0)s-%(_1)s', ['_0', '_1'])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 41
0
def build_url_template(viewname, kwargs=[], urlconf=None, prefix=None, current_app=None):
    resolver = get_resolver(urlconf)

    if prefix is None:
        prefix = get_script_prefix()

    kwargs = list(kwargs)

    parts = viewname.split(':')
    parts.reverse()
    view = parts[0]
    path = parts[1:]

    resolved_path = []
    ns_pattern = ''
    while path:
        ns = path.pop()

        # Lookup the name to see if it could be an app identifier
        try:
            app_list = resolver.app_dict[ns]
            # Yes! Path part matches an app in the current Resolver
            if current_app and current_app in app_list:
                # If we are reversing for a particular app,
                # use that namespace
                ns = current_app
            elif ns not in app_list:
                # The name isn't shared by one of the instances
                # (i.e., the default) so just pick the first instance
                # as the default.
                ns = app_list[0]
        except KeyError:
            pass

        try:
            extra, resolver = resolver.namespace_dict[ns]
            resolved_path.append(ns)
            ns_pattern = ns_pattern + extra
        except KeyError as key:
            if resolved_path:
                raise NoReverseMatch(
                    "%s is not a registered namespace inside '%s'" %
                    (key, ':'.join(resolved_path)))
            else:
                raise NoReverseMatch("%s is not a registered namespace" %
                                     key)
    if ns_pattern:
        resolver = get_ns_resolver(ns_pattern, resolver)

    possibilities = resolver.reverse_dict.getlist(view)
    prefix_norm, prefix_args = normalize(prefix)[0]
    for entry in possibilities:
        if len(entry) == 3:
            possibility, pattern, defaults = entry
        else:
            possibility, pattern = entry
            defaults = {}

        for result, params in possibility:
            if set(kwargs + list(defaults)) != set(params + list(defaults) + prefix_args):
                continue

            unicode_kwargs = dict([(k, '%(' + force_text(k) + ')s') for k in kwargs])
            unicode_kwargs.update(defaults)
            return (prefix_norm + result) % unicode_kwargs

    raise NoReverseMatch("Reverse for '%s' with keyword arguments '%s' not "
            "found." % (viewname, kwargs))
Exemplo n.º 42
0
 def test_group_noncapturing(self):
     pattern = r"(?:non-capturing)"
     expected = [('non-capturing', [])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 43
0
 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)
Exemplo n.º 44
0
 def test_empty(self):
     pattern = r""
     expected = [('', [])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 45
0
 def test_group_positional(self):
     pattern = r"(.*)-(.+)"
     expected = [("%(_0)s-%(_1)s", ["_0", "_1"])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 46
0
 def _populate(self):
     # Short-circuit if called recursively in this thread to prevent
     # infinite recursion. Concurrent threads may call this at the same
     # time and will need to continue, so set 'populating' on a
     # thread-local variable.
     #pylint:disable=protected-access,too-many-locals
     if getattr(self._local, 'populating', False):
         return
     try:
         self._local.populating = True
         lookups = MultiValueDict()
         namespaces = {}
         apps = {}
         path_prefix = self._get_path_prefix()
         for url_pattern in reversed(self.url_patterns):
             if isinstance(url_pattern, DjangoRegexURLPattern):
                 self._callback_strs.add(url_pattern.lookup_str)
             # could be RegexURLPattern.regex or RegexURLResolver.regex here.
             p_pattern = url_pattern.regex.pattern
             if p_pattern.startswith('^'):
                 p_pattern = p_pattern[1:]
             if isinstance(url_pattern, DjangoRegexURLResolver):
                 if url_pattern.namespace:
                     namespaces[url_pattern.namespace] = (p_pattern,
                                                          url_pattern)
                     if url_pattern.app_name:
                         apps.setdefault(url_pattern.app_name,
                                         []).append(url_pattern.namespace)
                 else:
                     parent_pat = url_pattern.regex.pattern
                     for name in url_pattern.reverse_dict:
                         for _, pat, defaults \
                             in url_pattern.reverse_dict.getlist(name):
                             new_matches = normalize(parent_pat + pat)
                             lookups.appendlist(name, (
                                 new_matches,
                                 p_pattern + pat,
                                 dict(defaults, **
                                      url_pattern.default_kwargs),
                             ))
                     for namespace, (prefix, sub_pattern) \
                         in url_pattern.namespace_dict.items():
                         namespaces[namespace] = (p_pattern + prefix,
                                                  sub_pattern)
                     for app_name, namespace_list in \
                             url_pattern.app_dict.items():
                         apps.setdefault(app_name,
                                         []).extend(namespace_list)
                 if not getattr(url_pattern._local, 'populating', False):
                     url_pattern._populate()
                 self._callback_strs.update(url_pattern._callback_strs)
             else:
                 bits = normalize(p_pattern)
                 lookups.appendlist(
                     url_pattern.callback,
                     (bits, p_pattern, url_pattern.default_args))
                 if url_pattern.name is not None:
                     lookups.appendlist(
                         url_pattern.name,
                         (bits, p_pattern, url_pattern.default_args))
         self._reverse_dict[path_prefix] = lookups
         self._namespace_dict[path_prefix] = namespaces
         self._app_dict[path_prefix] = apps
         self._populated = True
     finally:
         self._local.populating = False
Exemplo n.º 47
0
    def test_openapi_arguments(self) -> None:
        """This end-to-end API documentation test compares the arguments
        defined in the actual code using @has_request_variables and
        REQ(), with the arguments declared in our API documentation
        for every API endpoint in Zulip.

        First, we import the fancy-Django version of zproject/urls.py
        by doing this, each has_request_variables wrapper around each
        imported view function gets called to generate the wrapped
        view function and thus filling the global arguments_map variable.
        Basically, we're exploiting code execution during import.

            Then we need to import some view modules not already imported in
        urls.py. We use this different syntax because of the linters complaining
        of an unused import (which is correct, but we do this for triggering the
        has_request_variables decorator).

            At the end, we perform a reverse mapping test that verifies that
        every URL pattern defined in the OpenAPI documentation actually exists
        in code.
        """

        from zproject import urls as urlconf

        # We loop through all the API patterns, looking in particular
        # for those using the rest_dispatch decorator; we then parse
        # its mapping of (HTTP_METHOD -> FUNCTION).
        for p in urlconf.v1_api_and_json_patterns + urlconf.v1_api_mobile_patterns:
            if p.callback is not rest_dispatch:
                # Endpoints not using rest_dispatch don't have extra data.
                methods_endpoints: Dict[str, Any] = dict(GET=p.callback, )
            else:
                methods_endpoints = assert_is_not_none(p.default_args)

            # since the module was already imported and is now residing in
            # memory, we won't actually face any performance penalties here.
            for method, value in methods_endpoints.items():
                if callable(value):
                    function: Callable[..., HttpResponse] = value
                    tags: Set[str] = set()
                else:
                    function, tags = value

                if function is get_events:
                    # Work around the fact that the registered
                    # get_events view function isn't where we do
                    # @has_request_variables.
                    #
                    # TODO: Make this configurable via an optional argument
                    # to has_request_variables, e.g.
                    # @has_request_variables(view_func_name="zerver.tornado.views.get_events")
                    function = get_events_backend

                function_name = f"{function.__module__}.{function.__name__}"

                # Our accounting logic in the `has_request_variables()`
                # code means we have the list of all arguments
                # accepted by every view function in arguments_map.
                accepted_arguments = set(arguments_map[function_name])

                regex_pattern = p.pattern.regex.pattern
                for url_format, url_params in regex_helper.normalize(
                        regex_pattern):
                    url_pattern = "/" + url_format % {
                        param: f"{{{param}}}"
                        for param in url_params
                    }

                    if "intentionally_undocumented" in tags:
                        self.ensure_no_documentation_if_intentionally_undocumented(
                            url_pattern, method)
                        continue

                    if url_pattern in self.pending_endpoints:
                        # HACK: After all pending_endpoints have been resolved, we should remove
                        # this segment and the "msg" part of the `ensure_no_...` method.
                        msg = f"""
We found some OpenAPI documentation for {method} {url_pattern},
so maybe we shouldn't include it in pending_endpoints.
"""
                        self.ensure_no_documentation_if_intentionally_undocumented(
                            url_pattern, method, msg)
                        continue

                    try:
                        # Don't include OpenAPI parameters that live in
                        # the path; these are not extracted by REQ.
                        openapi_parameters = get_openapi_parameters(
                            url_pattern, method, include_url_parameters=False)
                    except Exception:  # nocoverage
                        raise AssertionError(
                            f"Could not find OpenAPI docs for {method} {url_pattern}"
                        )

                    # We now have everything we need to understand the
                    # function as defined in our urls.py:
                    #
                    # * method is the HTTP method, e.g. GET, POST, or PATCH
                    #
                    # * p.pattern.regex.pattern is the URL pattern; might require
                    #   some processing to match with OpenAPI rules
                    #
                    # * accepted_arguments is the full set of arguments
                    #   this method accepts (from the REQ declarations in
                    #   code).
                    #
                    # * The documented parameters for the endpoint as recorded in our
                    #   OpenAPI data in zerver/openapi/zulip.yaml.
                    #
                    # We now compare these to confirm that the documented
                    # argument list matches what actually appears in the
                    # codebase.

                    openapi_parameter_names = {
                        parameter["name"]
                        for parameter in openapi_parameters
                    }

                    if len(accepted_arguments -
                           openapi_parameter_names) > 0:  # nocoverage
                        print("Undocumented parameters for", url_pattern,
                              method, function_name)
                        print(" +", openapi_parameter_names)
                        print(" -", accepted_arguments)
                        assert url_pattern in self.buggy_documentation_endpoints
                    elif len(openapi_parameter_names -
                             accepted_arguments) > 0:  # nocoverage
                        print("Documented invalid parameters for", url_pattern,
                              method, function_name)
                        print(" -", openapi_parameter_names)
                        print(" +", accepted_arguments)
                        assert url_pattern in self.buggy_documentation_endpoints
                    else:
                        self.assertEqual(openapi_parameter_names,
                                         accepted_arguments)
                        self.check_argument_types(function, openapi_parameters)
                        self.checked_endpoints.add(url_pattern)

        self.check_for_non_existant_openapi_endpoints()
Exemplo n.º 48
0
                pass

            try:
                extra, resolver = resolver.namespace_dict[ns]
                resolved_path.append(ns)
                prefix = prefix + extra
            except KeyError, key:
                if resolved_path:
                    raise NoReverseMatch("%s is not a registered namespace inside '%s'" % (key, ':'.join(resolved_path)))
                else:
                    raise NoReverseMatch("%s is not a registered namespace" % key)

    # This is a hack to get namespaced URLs to reverse when the base
    # has named parameters (may work for positional, but not tested at all).
    pattern = prefix
    possibility = normalize(pattern) # The magical regex reverse function!
    # Below copied from _populate above and slightly altered
    for result, params in possibility:
        copy_args = [v for v in args]
        copy_kwargs = kwargs.copy()
        if args:
            if len(args) < len(params):
                continue
            # Pop arguments to ensure the right number are passed on to the
            # resolver.
            unicode_args = [force_unicode(copy_args.pop(0)) for v in params]
            candidate =  result % dict(zip(params, unicode_args))
        else:
            if not set(params).issubset(set(kwargs.keys())):
                continue
            # Pop arguments to ensure the right number are passed on to the
Exemplo n.º 49
0
            extra, resolver = resolver.namespace_dict[ns]
            resolved_path.append(ns)
            ns_pattern = ns_pattern + extra
        except KeyError, key:
            if resolved_path:
                raise NoReverseMatch(
                    "%s is not a registered namespace inside '%s'" %
                    (key, ':'.join(resolved_path)))
            else:
                raise NoReverseMatch("%s is not a registered namespace" %
                                     key)
    if ns_pattern:
        resolver = get_ns_resolver(ns_pattern, resolver)

    possibilities = resolver.reverse_dict.getlist(view)
    prefix_norm, prefix_args = normalize(prefix)[0]
    for entry in possibilities:
        if len(entry) == 3:
            possibility, pattern, defaults = entry
        else:
            possibility, pattern = entry
            defaults = {}

        for result, params in possibility:
            if set(kwargs + defaults.keys()) != set(params + defaults.keys() + prefix_args):
                continue

            unicode_kwargs = dict([(k, u'#{' + force_unicode(k) + u'}') for k in kwargs])
            unicode_kwargs.update(defaults)
            return (prefix_norm + result) % unicode_kwargs
Exemplo n.º 50
0
 def test_group_noncapturing(self):
     pattern = r"(?:non-capturing)"
     expected = [('non-capturing', [])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 51
0
 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)
Exemplo n.º 52
0
 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)
Exemplo n.º 53
0
 def test_escape(self):
     pattern = r"\\\^\$\.\|\?\*\+\(\)\["
     expected = [('\\^$.|?*+()[', [])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 54
0
 def test_empty(self):
     pattern = r""
     expected = [('', [])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 55
0
 def test_group_ignored(self):
     pattern = r"(?i)(?L)(?m)(?s)(?u)(?#)"
     expected = [(u'', [])]
     result = regex_helper.normalize(pattern)
     self.assertEqual(result, expected)
Exemplo n.º 56
0
 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)
Exemplo n.º 57
0
    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()!")
        text_args = [force_text(v) for v in args]
        text_kwargs = {k: force_text(v) for (k, v) in kwargs.items()}

        if not self._populated:
            self._populate()

        original_lookup = lookup_view
        try:
            if self._is_callback(lookup_view):
                lookup_view = get_callable(lookup_view, True)
        except (ImportError, AttributeError) as e:
            raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e))
        else:
            if not callable(original_lookup) and callable(lookup_view):
                warnings.warn(
                    'Reversing by dotted path is deprecated (%s).' % original_lookup,
                    RemovedInDjango20Warning, stacklevel=3
                )
        possibilities = self.reverse_dict.getlist(lookup_view)

        prefix_norm, prefix_args = normalize(urlquote(_prefix))[0]
        for possibility, pattern, defaults in possibilities:
            for result, params in possibility:
                if args:
                    if len(args) != len(params) + len(prefix_args):
                        continue
                    candidate_subs = dict(zip(prefix_args + params, text_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
                    candidate_subs = text_kwargs
                # WSGI provides decoded URLs, without %xx escapes, and the URL
                # resolver operates on such URLs. First substitute arguments
                # without quoting to build a decoded URL and look for a match.
                # Then, if we have a match, redo the substitution with quoted
                # arguments in order to return a properly encoded URL.
                candidate_pat = prefix_norm.replace('%', '%%') + result
                if re.search('^%s%s' % (prefix_norm, pattern), candidate_pat % candidate_subs, re.UNICODE):
                    # safe characters from `pchar` definition of RFC 3986
                    candidate_subs = dict((k, urlquote(v, safe=RFC3986_SUBDELIMS + str('/~:@')))
                                          for (k, v) in candidate_subs.items())
                    url = candidate_pat % candidate_subs
                    # Don't allow construction of scheme relative urls.
                    if url.startswith('//'):
                        url = '/%%2F%s' % url[2:]
                    return url
        # 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

        patterns = [pattern for (possibility, pattern, defaults) in possibilities]
        raise NoReverseMatch("Reverse for '%s' with arguments '%s' and keyword "
                "arguments '%s' not found. %d pattern(s) tried: %s" %
                             (lookup_view_s, args, kwargs, len(patterns), patterns))
Exemplo n.º 58
0
def build_url_template(viewname,
                       kwargs=[],
                       urlconf=None,
                       prefix=None,
                       current_app=None):
    resolver = get_resolver(urlconf)

    if prefix is None:
        prefix = get_script_prefix()

    kwargs = list(kwargs)

    parts = viewname.split(':')
    parts.reverse()
    view = parts[0]
    path = parts[1:]

    resolved_path = []
    ns_pattern = ''
    while path:
        ns = path.pop()

        # Lookup the name to see if it could be an app identifier
        try:
            app_list = resolver.app_dict[ns]
            # Yes! Path part matches an app in the current Resolver
            if current_app and current_app in app_list:
                # If we are reversing for a particular app,
                # use that namespace
                ns = current_app
            elif ns not in app_list:
                # The name isn't shared by one of the instances
                # (i.e., the default) so just pick the first instance
                # as the default.
                ns = app_list[0]
        except KeyError:
            pass

        try:
            extra, resolver = resolver.namespace_dict[ns]
            resolved_path.append(ns)
            ns_pattern = ns_pattern + extra
        except KeyError as key:
            if resolved_path:
                raise NoReverseMatch(
                    "%s is not a registered namespace inside '%s'" %
                    (key, ':'.join(resolved_path)))
            else:
                raise NoReverseMatch("%s is not a registered namespace" % key)
    if ns_pattern:
        resolver = get_ns_resolver(ns_pattern, resolver)

    possibilities = resolver.reverse_dict.getlist(view)
    prefix_norm, prefix_args = normalize(prefix)[0]
    for entry in possibilities:
        if len(entry) == 3:
            possibility, pattern, defaults = entry
        else:
            possibility, pattern = entry
            defaults = {}

        for result, params in possibility:
            if set(kwargs + list(defaults)) != set(params + list(defaults) +
                                                   prefix_args):
                continue

            unicode_kwargs = dict([(k, '%(' + force_text(k) + ')s')
                                   for k in kwargs])
            unicode_kwargs.update(defaults)
            return (prefix_norm + result) % unicode_kwargs

    raise NoReverseMatch(
        "Reverse for '%s' with keyword arguments '%s' not found." %
        (viewname, kwargs))
Exemplo n.º 59
0
    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()!")
        text_args = [force_text(v) for v in args]
        text_kwargs = {k: force_text(v) for (k, v) in kwargs.items()}

        if not self._populated:
            self._populate()

        original_lookup = lookup_view
        try:
            if self._is_callback(lookup_view):
                lookup_view = get_callable(lookup_view, True)
        except (ImportError, AttributeError) as e:
            raise NoReverseMatch("Error importing '%s': %s." %
                                 (lookup_view, e))
        else:
            if not callable(original_lookup) and callable(lookup_view):
                warnings.warn('Reversing by dotted path is deprecated (%s).' %
                              original_lookup,
                              RemovedInDjango110Warning,
                              stacklevel=3)
        possibilities = self.reverse_dict.getlist(lookup_view)

        prefix_norm, prefix_args = normalize(urlquote(_prefix))[0]
        for possibility, pattern, defaults in possibilities:
            for result, params in possibility:
                if args:
                    if len(args) != len(params) + len(prefix_args):
                        continue
                    candidate_subs = dict(zip(prefix_args + params, text_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
                    candidate_subs = text_kwargs
                # WSGI provides decoded URLs, without %xx escapes, and the URL
                # resolver operates on such URLs. First substitute arguments
                # without quoting to build a decoded URL and look for a match.
                # Then, if we have a match, redo the substitution with quoted
                # arguments in order to return a properly encoded URL.
                candidate_pat = prefix_norm.replace('%', '%%') + result
                if re.search('^%s%s' % (prefix_norm, pattern),
                             candidate_pat % candidate_subs, re.UNICODE):
                    # safe characters from `pchar` definition of RFC 3986
                    candidate_subs = dict(
                        (k, urlquote(v, safe=RFC3986_SUBDELIMS + str('/~:@')))
                        for (k, v) in candidate_subs.items())
                    url = candidate_pat % candidate_subs
                    # Don't allow construction of scheme relative urls.
                    if url.startswith('//'):
                        url = '/%%2F%s' % url[2:]
                    return url
        # 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

        patterns = [
            pattern for (possibility, pattern, defaults) in possibilities
        ]
        raise NoReverseMatch(
            "Reverse for '%s' with arguments '%s' and keyword "
            "arguments '%s' not found. %d pattern(s) tried: %s" %
            (lookup_view_s, args, kwargs, len(patterns), patterns))
Exemplo n.º 60
0
    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()!")

        if not self._populated:
            self._populate()

        try:
            if lookup_view in self._callback_strs:
                lookup_view = get_callable(lookup_view, True)
        except (ImportError, AttributeError), 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_unicode(val) for val in args]
                    candidate = (prefix_norm + result) % dict(
                        zip(prefix_args + params, unicode_args))
                else:
                    if set(kwargs.keys() +
                           defaults.keys()) != set(params + defaults.keys() +
                                                   prefix_args):
                        continue
                    matches = True
                    for k, v in defaults.items():