Code

Ticket #20757: patch_commit_44e7837a1706.patch

File patch_commit_44e7837a1706.patch, 6.9 KB (added by fcurella, 9 months ago)
  • django/core/urlresolvers.py

    diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
    index b7017e47b91115db23f2406d0b4a825ca55a272a..f599cf83ddf2ec19e5ea4b8a8b19bce2adba595a 100644
    a b from threading import local 
    1313 
    1414from django.http import Http404 
    1515from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist 
    16 from django.utils.datastructures import MultiValueDict 
     16from django.utils.datastructures import MultiValueDict, NameIndexedIterable 
    1717from django.utils.encoding import force_str, force_text, iri_to_uri 
    1818from django.utils.functional import memoize, lazy 
    1919from django.utils.http import urlquote 
    class RegexURLPattern(LocaleRegexProvider): 
    229229        self._callback = get_callable(self._callback_str) 
    230230        return self._callback 
    231231 
     232 
     233class URLEntry(NameIndexedIterable): 
     234    state_class = tuple 
     235    keys = ('urlbits', 'p_pattern', 'pattern.default') 
     236 
     237    def __repr__(self): 
     238        return "<URLEntry: %s>" % self.state.__repr__() 
     239 
     240 
     241class URLBit(NameIndexedIterable): 
     242    state_class = tuple 
     243    keys = ('format', 'argument_names') 
     244 
     245    def __repr__(self): 
     246        return "<URLBit: %s>" % self.state.__repr__() 
     247 
     248 
    232249class RegexURLResolver(LocaleRegexProvider): 
    233250    def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None): 
    234251        LocaleRegexProvider.__init__(self, regex) 
    class RegexURLResolver(LocaleRegexProvider): 
    269286                    if pattern.app_name: 
    270287                        apps.setdefault(pattern.app_name, []).append(pattern.namespace) 
    271288                else: 
    272                     parent = normalize(pattern.regex.pattern) 
     289                    parent = [URLBit(*p) for p in normalize(pattern.regex.pattern)] 
    273290                    for name in pattern.reverse_dict: 
    274291                        for matches, pat, defaults in pattern.reverse_dict.getlist(name): 
    275292                            new_matches = [] 
    276293                            for piece, p_args in parent: 
    277                                 new_matches.extend([(piece + suffix, p_args + args) for (suffix, args) in matches]) 
    278                             lookups.appendlist(name, (new_matches, p_pattern + pat, dict(defaults, **pattern.default_kwargs))) 
     294                                new_matches.extend([URLBit(piece + suffix, p_args + args) for (suffix, args) in matches]) 
     295                            lookups.appendlist(name, URLEntry(new_matches, p_pattern + pat, dict(defaults, **pattern.default_kwargs))) 
    279296                    for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items(): 
    280297                        namespaces[namespace] = (p_pattern + prefix, sub_pattern) 
    281298                    for app_name, namespace_list in pattern.app_dict.items(): 
    282299                        apps.setdefault(app_name, []).extend(namespace_list) 
    283300            else: 
    284                 bits = normalize(p_pattern) 
    285                 lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args)) 
     301                bits = [URLBit(*p) for p in normalize(p_pattern)] 
     302                lookups.appendlist(pattern.callback, URLEntry(bits, p_pattern, pattern.default_args)) 
    286303                if pattern.name is not None: 
    287                     lookups.appendlist(pattern.name, (bits, p_pattern, pattern.default_args)) 
     304                    lookups.appendlist(pattern.name, URLEntry(bits, p_pattern, pattern.default_args)) 
    288305        self._reverse_dict[language_code] = lookups 
    289306        self._namespace_dict[language_code] = namespaces 
    290307        self._app_dict[language_code] = apps 
    def is_valid_path(path, urlconf=None): 
    574591        return True 
    575592    except Resolver404: 
    576593        return False 
     594 
     595def get_urlformat(urlname): 
     596    """ 
     597    Given a URL name, returns the URL as a string suitable for string.format. 
     598 
     599    Example:: 
     600 
     601    urlpatterns = patterns('', 
     602        url(r'^extra/(?P<extra>\w+)/$', empty_view, name="named-url2"), 
     603    ) 
     604 
     605    >>> get_urlformat('named-url2') 
     606    '/extra/%(extra)s/' 
     607    """ 
     608    urlconf = get_urlconf() 
     609    resolver = get_resolver(urlconf) 
     610    urlbit = resolver.reverse_dict[urlname].urlbits[0] 
     611    return "%s%s" % (get_script_prefix(), urlbit.format) 
  • django/utils/datastructures.py

    diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
    index 3b1638392c08bf5fed640cdea67d5559a971a584..dbd7f0a3c242c0ed057a06438ef86e659958fa40 100644
    a b class DictWrapper(dict): 
    496496        if use_func: 
    497497            return self.func(value) 
    498498        return value 
     499 
     500 
     501class NameIndexedIterable(object): 
     502    """ 
     503    An Iterable (most likely a list or tuple), whose indexes can be referred 
     504    by name. 
     505    """ 
     506    state_class = list 
     507    keys = list() 
     508 
     509    def __init__(self, *args, **kwargs): 
     510        updated_args = list(args) 
     511        for i, keyword in enumerate(self.keys): 
     512            if keyword in kwargs: 
     513                updated_args[i] = kwargs[keyword] 
     514            else: 
     515                break 
     516        self.state = self.state_class(updated_args) 
     517        super(NameIndexedIterable, self).__init__() 
     518 
     519    def __getitem__(self, index): 
     520        return self.state[index] 
     521 
     522    def __setitem__(self, index, value): 
     523        self.state[index] = value 
     524 
     525    def __getattr__(self, attr): 
     526        if attr in self.keys: 
     527            return self.state[self.keys.index(attr)] 
     528        return super(NameIndexedIterable, self).__getattr__(attr) 
     529 
     530    def __setattr__(self, attr, value): 
     531        if attr in self.keys: 
     532            self.state[self.keys.index(attr)] = value 
     533        return super(NameIndexedIterable, self).__setattr__(attr, value) 
     534 
     535    def __repr__(self): 
     536        return self.state.__repr__() 
  • tests/urlpatterns_reverse/tests.py

    diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py
    index 222ebe053b1362afca1c9962cc2b4e3fbc908b55..e265e7659e26bc305cd93a23f7491a3721a72965 100644
    a b from django.conf import settings 
    99from django.contrib.auth.models import User 
    1010from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist 
    1111from django.core.urlresolvers import (reverse, resolve, get_callable, 
    12     get_resolver, NoReverseMatch, Resolver404, ResolverMatch, RegexURLResolver, 
    13     RegexURLPattern) 
     12    get_resolver, get_urlformat, NoReverseMatch, Resolver404, ResolverMatch, 
     13    RegexURLResolver, RegexURLPattern) 
    1414from django.http import HttpRequest, HttpResponseRedirect, HttpResponsePermanentRedirect 
    1515from django.shortcuts import redirect 
    1616from django.test import TestCase 
    class ViewLoadingTests(TestCase): 
    644644        self.assertRaises(AttributeError, get_callable, 
    645645            'urlpatterns_reverse.views_broken.i_am_broken') 
    646646 
     647 
     648class URLObjects(TestCase): 
     649    urls = 'urlpatterns_reverse.named_urls' 
     650 
     651    def test_URL_objects(self): 
     652        format = get_urlformat('named-url2') 
     653        self.assertEqual(format, '/extra/%(extra)s/')