~ubuntu-branches/ubuntu/precise/horizon/precise-updates

« back to all changes in this revision

Viewing changes to horizon/horizon/utils/reverse_bugfix.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-03-02 12:11:59 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20120302121159-65b88lcl4slve26i
Tags: 2012.1~e4-0ubuntu1
* New upstream version.
* debian/rules: Update due to upstream build changes.
* debian/control: Update standards-version.
* debian/patches/openstack-config-settings.patch: Dropped
* debian/patches/fix-dashboard-django-wsgi.patch: Refreshed
* debian/patches/fix-dashboard-manage.patch: Refreshed
* debian/openstack-dashboard.install: Update due to upstream build changes.
* debian/dashboard: Update to upstream build changes.
* debian/pydist-overrides: Dont try to install python-django-nose-selenium.
* debian/openstack-dashboard.install: Add missing config files.
* debian/rules: Fix broken settings.py
* debian/patches/pkg-setup.patch: Copy missing templates, shameously
  taken from debian
* debian/patches/fix-broken-tarbll.patch: Add missing files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""
2
 
Bugfix for issue #15900: https://code.djangoproject.com/ticket/15900.
3
 
 
4
 
This code is largely reproduced from
5
 
https://code.djangoproject.com/browser/django/trunk/django/core/urlresolvers.py
6
 
and is the work of Django's authors:
7
 
https://code.djangoproject.com/browser/django/trunk/AUTHORS
8
 
 
9
 
It is licensed under Django's BSD license, available here:
10
 
https://code.djangoproject.com/browser/django/trunk/LICENSE
11
 
 
12
 
To use, simply import this code in your project's root URLconf file before
13
 
defining any URL patterns.
14
 
"""
15
 
 
16
 
from django.core import urlresolvers
17
 
 
18
 
if not hasattr(urlresolvers.RegexURLResolver, "_reverse_with_prefix"):
19
 
    import re
20
 
 
21
 
    from django.conf import urls
22
 
    from django.utils.datastructures import MultiValueDict
23
 
    from django.utils.encoding import iri_to_uri, force_unicode
24
 
    from django.utils.regex_helper import normalize
25
 
 
26
 
    def _populate(self):
27
 
        lookups = MultiValueDict()
28
 
        namespaces = {}
29
 
        apps = {}
30
 
        for pattern in reversed(self.url_patterns):
31
 
            p_pattern = pattern.regex.pattern
32
 
            if p_pattern.startswith('^'):
33
 
                p_pattern = p_pattern[1:]
34
 
            if isinstance(pattern, urlresolvers.RegexURLResolver):
35
 
                if pattern.namespace:
36
 
                    namespaces[pattern.namespace] = (p_pattern, pattern)
37
 
                    if pattern.app_name:
38
 
                        apps.setdefault(pattern.app_name, []) \
39
 
                            .append(pattern.namespace)
40
 
                else:
41
 
                    parent = normalize(pattern.regex.pattern)
42
 
                    for name in pattern.reverse_dict:
43
 
                        for matches, pat, defaults in \
44
 
                                pattern.reverse_dict.getlist(name):
45
 
                            new_matches = []
46
 
                            for piece, p_args in parent:
47
 
                                vals = [(piece + suffix, p_args + args) for \
48
 
                                        (suffix, args) in matches]
49
 
                                new_matches.extend(vals)
50
 
                            lookup_list = (new_matches, p_pattern + pat,
51
 
                                           dict(defaults,
52
 
                                                **pattern.default_kwargs))
53
 
                            lookups.appendlist(name, lookup_list)
54
 
                    for namespace, (prefix, sub_pattern) in \
55
 
                            pattern.namespace_dict.items():
56
 
                        namespace_vals = (p_pattern + prefix, sub_pattern)
57
 
                        namespaces[namespace] = namespace_vals
58
 
                    for app_name, namespace_list in pattern.app_dict.items():
59
 
                        apps.setdefault(app_name, []).extend(namespace_list)
60
 
            else:
61
 
                bits = normalize(p_pattern)
62
 
                lookup_list = (bits, p_pattern, pattern.default_args)
63
 
                lookups.appendlist(pattern.callback, lookup_list)
64
 
                if pattern.name is not None:
65
 
                    lookup_list = (bits, p_pattern, pattern.default_args)
66
 
                    lookups.appendlist(pattern.name, lookup_list)
67
 
        self._reverse_dict = lookups
68
 
        self._namespace_dict = namespaces
69
 
        self._app_dict = apps
70
 
 
71
 
    def resolver_reverse(self, lookup_view, *args, **kwargs):
72
 
        return self._reverse_with_prefix(lookup_view, '', *args, **kwargs)
73
 
 
74
 
    def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
75
 
        if args and kwargs:
76
 
            raise ValueError("Don't mix *args and **kwargs in call to "
77
 
                             "reverse()!")
78
 
        try:
79
 
            lookup_view = urlresolvers.get_callable(lookup_view, True)
80
 
        except (ImportError, AttributeError), e:
81
 
            raise urlresolvers.NoReverseMatch("Error importing '%s': %s."
82
 
                                              % (lookup_view, e))
83
 
        possibilities = self.reverse_dict.getlist(lookup_view)
84
 
        prefix_norm, prefix_args = normalize(_prefix)[0]
85
 
        for possibility, pattern, defaults in possibilities:
86
 
            for result, params in possibility:
87
 
                if args:
88
 
                    if len(args) != len(params) + len(prefix_args):
89
 
                        continue
90
 
                    unicode_args = [force_unicode(val) for val in args]
91
 
                    candidate = (prefix_norm + result) \
92
 
                            % dict(zip(prefix_args + params, unicode_args))
93
 
                else:
94
 
                    if set(kwargs.keys() + defaults.keys()) != \
95
 
                            set(params + defaults.keys() + prefix_args):
96
 
                        continue
97
 
                    matches = True
98
 
                    for k, v in defaults.items():
99
 
                        if kwargs.get(k, v) != v:
100
 
                            matches = False
101
 
                            break
102
 
                    if not matches:
103
 
                        continue
104
 
                    unicode_kwargs = dict([(k, force_unicode(v)) for \
105
 
                            (k, v) in kwargs.items()])
106
 
                    candidate = (prefix_norm + result) % unicode_kwargs
107
 
                if re.search(u'^%s%s' % (_prefix, pattern),
108
 
                             candidate, re.UNICODE):
109
 
                    return candidate
110
 
        # lookup_view can be URL label, or dotted path, or callable, Any of
111
 
        # these can be passed in at the top, but callables are not friendly in
112
 
        # error messages.
113
 
        m = getattr(lookup_view, '__module__', None)
114
 
        n = getattr(lookup_view, '__name__', None)
115
 
        if m is not None and n is not None:
116
 
            lookup_view_s = "%s.%s" % (m, n)
117
 
        else:
118
 
            lookup_view_s = lookup_view
119
 
        raise urlresolvers.NoReverseMatch("Reverse for '%s' with "
120
 
                                          "arguments '%s' and keyword "
121
 
                                          "arguments '%s' not found."
122
 
                                          % (lookup_view_s, args, kwargs))
123
 
 
124
 
    def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None,
125
 
                current_app=None):
126
 
        if urlconf is None:
127
 
            urlconf = urlresolvers.get_urlconf()
128
 
        resolver = urlresolvers.get_resolver(urlconf)
129
 
        args = args or []
130
 
        kwargs = kwargs or {}
131
 
 
132
 
        if prefix is None:
133
 
            prefix = urlresolvers.get_script_prefix()
134
 
 
135
 
        if not isinstance(viewname, basestring):
136
 
            view = viewname
137
 
        else:
138
 
            parts = viewname.split(':')
139
 
            parts.reverse()
140
 
            view = parts[0]
141
 
            path = parts[1:]
142
 
 
143
 
            resolved_path = []
144
 
            while path:
145
 
                ns = path.pop()
146
 
 
147
 
                # Lookup the name to see if it could be an app identifier
148
 
                try:
149
 
                    app_list = resolver.app_dict[ns]
150
 
                    # Yes! Path part matches an app in the current Resolver
151
 
                    if current_app and current_app in app_list:
152
 
                        # If we are reversing for a particular app,
153
 
                        # use that namespace
154
 
                        ns = current_app
155
 
                    elif ns not in app_list:
156
 
                        # The name isn't shared by one of the instances
157
 
                        # (i.e., the default) so just pick the first instance
158
 
                        # as the default.
159
 
                        ns = app_list[0]
160
 
                except KeyError:
161
 
                    pass
162
 
 
163
 
                try:
164
 
                    extra, resolver = resolver.namespace_dict[ns]
165
 
                    resolved_path.append(ns)
166
 
                    prefix = prefix + extra
167
 
                except KeyError, key:
168
 
                    if resolved_path:
169
 
                        raise urlresolvers.NoReverseMatch("%s is not a "
170
 
                                "registered namespace inside %s'"
171
 
                                % (key, ':'.join(resolved_path)))
172
 
                    else:
173
 
                        raise urlresolvers.NoReverseMatch("%s is not a "
174
 
                                                          "registered "
175
 
                                                          "namespace" % key)
176
 
 
177
 
        return iri_to_uri(resolver._reverse_with_prefix(view, prefix,
178
 
                                                        *args, **kwargs))
179
 
 
180
 
    urlresolvers.RegexURLResolver._populate = _populate
181
 
    urlresolvers.RegexURLResolver.reverse = resolver_reverse
182
 
    urlresolvers.RegexURLResolver._reverse_with_prefix = _reverse_with_prefix
183
 
    urlresolvers.reverse = reverse