Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7e85510
URL dispatcher API -- initial commit.
knbk Jun 10, 2015
152896c
Added basic URL object.
knbk Jun 11, 2015
2372282
Extended URL with several useful methods.
knbk Jun 15, 2015
07af4d6
URL pre-nuke.
knbk Jun 15, 2015
2d8b720
URL post-nuke.
knbk Jun 15, 2015
40588eb
A few more tests for URL.
knbk Jun 15, 2015
d549fae
Added Constraint, RegexPattern.
knbk Jun 15, 2015
0b0e21c
Added BaseResolver, Resolver and ResolverEndpoint.
knbk Jun 16, 2015
2b737aa
Basic namespace handling.
knbk Jun 16, 2015
440c5bc
Added support for passing a module/string reference to Resolver or a …
knbk Jun 18, 2015
2271424
Lazy compilation for the regex in RegexPattern. Fixed args/kwargs
knbk Jun 18, 2015
0af4fb2
Renamed urls to urls_tests.
knbk Jun 18, 2015
06c120c
Lots of changes.
knbk Jun 18, 2015
60f70d4
I should commit more often.
knbk Jun 20, 2015
ef17a24
Added repr to resolvers, fixed some tests.
knbk Jun 22, 2015
285a349
Renamed url argument to path.
knbk Jun 25, 2015
7839136
Resolved remaining test failures.
knbk Jun 25, 2015
7c87c7d
Fixed test failures after rebase.
knbk Jun 25, 2015
c8b028f
Fixed some test failures on Python 2.
knbk Jun 25, 2015
56cbdef
Moved resolve_error_handler outside the Resolver. Changed some of the
knbk Jun 27, 2015
cccaba1
Miscellaneous changes.
knbk Jun 27, 2015
c8fdec2
Flake8, isort, and moving some code.
knbk Jun 27, 2015
c6bf237
Deprecated django.core.urlresolvers in favour of django.core.urls.
knbk Jun 27, 2015
d702485
Removed django.core.urlresolvers references in the test suite.
knbk Jun 28, 2015
1c8d49c
Moved URL to django.core.urls.utils.
knbk Jun 29, 2015
7ec5094
Additional tests; flake8.
knbk Jul 6, 2015
e2ff966
Doc layout.
knbk Jul 9, 2015
cf2af51
Added request parameter to calls to resolve(). Added request parameter
knbk Jul 21, 2015
0a35b16
Moved django.core.urls to django.urls.
knbk Jul 22, 2015
c0189bb
Fixed test failures on py2.
knbk Jul 23, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions django/conf/urls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
from importlib import import_module

from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import (
LocaleRegexURLResolver, RegexURLPattern, RegexURLResolver,
from django.urls import (
BaseResolver, LocalePrefix, LocalizedRegexPattern, RegexPattern, Resolver,
ResolverEndpoint,
)
from django.utils import six
from django.utils.deprecation import (
RemovedInDjango20Warning, RemovedInDjango110Warning,
)
from django.utils.functional import Promise

__all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'patterns', 'url']

Expand Down Expand Up @@ -66,10 +68,10 @@ def include(arg, namespace=None, app_name=None):
# Make sure we can iterate through the patterns (without this, some
# testcases will break).
if isinstance(patterns, (list, tuple)):
for url_pattern in patterns:
for name, resolver in patterns:
# Test if the LocaleRegexURLResolver is used within the include;
# this should throw an error since this is not allowed!
if isinstance(url_pattern, LocaleRegexURLResolver):
if any(isinstance(constraint, LocalePrefix) for constraint in resolver.constraints):
raise ImproperlyConfigured(
'Using i18n_patterns in an included URLconf is not allowed.')

Expand All @@ -86,28 +88,35 @@ def patterns(prefix, *args):
pattern_list = []
for t in args:
if isinstance(t, (list, tuple)):
t = url(prefix=prefix, *t)
elif isinstance(t, RegexURLPattern):
t.add_prefix(prefix)
if len(t) != 2 or not isinstance(t[1], BaseResolver):
t = url(prefix=prefix, *t)
elif len(t) == 2 and isinstance(t[1], ResolverEndpoint):
t[1].add_prefix(prefix)
pattern_list.append(t)
return pattern_list


def url(regex, view, kwargs=None, name=None, prefix=''):
def url(constraints, view, kwargs=None, name=None, prefix='', decorators=None):
if isinstance(constraints, six.string_types):
constraints = RegexPattern(constraints)
elif isinstance(constraints, Promise):
constraints = LocalizedRegexPattern(constraints)
if not isinstance(constraints, (list, tuple)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous if/elif converts constraints into either a RegexPattern or LocalizedRegexPattern but then immediately has to re-convert it into a list containing one of said objects. Would it make sense to have lines 100 & 103 both be wrapped into []?

constraints = [constraints]

if isinstance(view, (list, tuple)):
# For include(...) processing.
urlconf_module, app_name, namespace = view
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
resolvers, app_name, namespace = view
return namespace, Resolver(resolvers, app_name, constraints=constraints, kwargs=kwargs, decorators=decorators)
else:
if isinstance(view, six.string_types):
warnings.warn(
'Support for string view arguments to url() is deprecated and '
'will be removed in Django 1.10 (got %s). Pass the callable '
'will be removed in Django 2.0 (got %s). Pass the callable '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad merge conflict resolution? 1.10->2.0

'instead.' % view,
RemovedInDjango110Warning, stacklevel=2
)
if not view:
raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % regex)
raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % constraints)
if prefix:
view = prefix + '.' + view
return RegexURLPattern(regex, view, kwargs, name)
return None, ResolverEndpoint(view, name, constraints=constraints, kwargs=kwargs, decorators=decorators)
4 changes: 2 additions & 2 deletions django/conf/urls/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django.conf import settings
from django.conf.urls import patterns, url
from django.core.urlresolvers import LocaleRegexURLResolver
from django.urls import LocalePrefix, Resolver
from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning
from django.views.i18n import set_language
Expand All @@ -27,7 +27,7 @@ def i18n_patterns(prefix, *args):
pattern_list = [prefix] + list(args)
if not settings.USE_I18N:
return pattern_list
return [LocaleRegexURLResolver(pattern_list)]
return [(None, Resolver(pattern_list, constraints=[LocalePrefix()]))]


urlpatterns = [
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from django.conf import settings
from django.contrib.admin.utils import quote
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import NoReverseMatch, reverse
from django.db import models
from django.urls import NoReverseMatch, reverse
from django.utils.encoding import python_2_unicode_compatible, smart_text
from django.utils.translation import ugettext, ugettext_lazy as _

Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
FieldDoesNotExist, FieldError, PermissionDenied, ValidationError,
)
from django.core.paginator import Paginator
from django.core.urlresolvers import reverse
from django.db import models, router, transaction
from django.db.models.constants import LOOKUP_SEP
from django.db.models.fields import BLANK_CHOICE_DASH
Expand All @@ -35,6 +34,7 @@
from django.http import Http404, HttpResponseRedirect
from django.http.response import HttpResponseBase
from django.template.response import SimpleTemplateResponse, TemplateResponse
from django.urls import reverse
from django.utils import six
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text, python_2_unicode_compatible
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
from django.contrib.admin import ModelAdmin, actions
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.core.urlresolvers import NoReverseMatch, reverse
from django.db.models.base import ModelBase
from django.http import Http404, HttpResponseRedirect
from django.template.engine import Engine
from django.template.response import TemplateResponse
from django.urls import NoReverseMatch, reverse
from django.utils import six
from django.utils.text import capfirst
from django.utils.translation import ugettext as _, ugettext_lazy
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/templatetags/admin_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
ALL_VAR, ORDER_VAR, PAGE_VAR, SEARCH_VAR,
)
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import NoReverseMatch
from django.db import models
from django.template import Library
from django.template.loader import get_template
from django.urls import NoReverseMatch
from django.utils import formats
from django.utils.encoding import force_text
from django.utils.html import escapejs, format_html
Expand Down
9 changes: 7 additions & 2 deletions django/contrib/admin/templatetags/admin_urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django import template
from django.contrib.admin.utils import quote
from django.core.urlresolvers import Resolver404, get_script_prefix, resolve
from django.urls import Resolver404, get_script_prefix, resolve
from django.utils.http import urlencode
from django.utils.six.moves.urllib.parse import parse_qsl, urlparse, urlunparse

Expand All @@ -22,6 +22,11 @@ def add_preserved_filters(context, url, popup=False, to_field=None):
opts = context.get('opts')
preserved_filters = context.get('preserved_filters')

try:
request = context.request
except AttributeError:
request = None

parsed_url = list(urlparse(url))
parsed_qs = dict(parse_qsl(parsed_url[4]))
merged_qs = dict()
Expand All @@ -31,7 +36,7 @@ def add_preserved_filters(context, url, popup=False, to_field=None):

match_url = '/%s' % url.partition(get_script_prefix())[2]
try:
match = resolve(match_url)
match = resolve(match_url, request=request)
except Resolver404:
pass
else:
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

from django.contrib.auth import get_permission_codename
from django.core.exceptions import FieldDoesNotExist
from django.core.urlresolvers import NoReverseMatch, reverse
from django.db import models
from django.db.models.constants import LOOKUP_SEP
from django.db.models.deletion import Collector
from django.db.models.sql.constants import QUERY_TERMS
from django.forms.forms import pretty_name
from django.urls import NoReverseMatch, reverse
from django.utils import formats, six, timezone
from django.utils.encoding import force_str, force_text, smart_text
from django.utils.html import format_html
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/views/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
FieldDoesNotExist, ImproperlyConfigured, SuspiciousOperation,
)
from django.core.paginator import InvalidPage
from django.core.urlresolvers import reverse
from django.db import models
from django.urls import reverse
from django.utils import six
from django.utils.encoding import force_text
from django.utils.http import urlencode
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

from django import forms
from django.contrib.admin.templatetags.admin_static import static
from django.core.urlresolvers import reverse
from django.db.models.deletion import CASCADE
from django.forms.utils import flatatt
from django.forms.widgets import RadioFieldRenderer
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils import six
from django.utils.encoding import force_text
from django.utils.html import (
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admindocs/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from email.errors import HeaderParseError
from email.parser import HeaderParser

from django.core.urlresolvers import reverse
from django.urls import reverse
from django.utils.encoding import force_bytes
from django.utils.safestring import mark_safe

Expand Down
31 changes: 16 additions & 15 deletions django/contrib/admindocs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
import re
from importlib import import_module

from django import urls
from django.apps import apps
from django.conf import settings
from django.contrib import admin
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.admindocs import utils
from django.core import urlresolvers
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.db import models
from django.http import Http404
from django.template.engine import Engine
from django.urls.utils import get_mod_func
from django.utils.decorators import method_decorator
from django.utils.inspect import func_has_no_args
from django.utils.translation import ugettext as _
Expand All @@ -35,7 +36,7 @@ def dispatch(self, request, *args, **kwargs):
return super(BaseAdminDocsView, self).dispatch(request, *args, **kwargs)

def get_context_data(self, **kwargs):
kwargs.update({'root_path': urlresolvers.reverse('admin:index')})
kwargs.update({'root_path': urls.reverse('admin:index')})
kwargs.update(admin.site.each_context(self.request))
return super(BaseAdminDocsView, self).get_context_data(**kwargs)

Expand Down Expand Up @@ -144,9 +145,9 @@ class ViewDetailView(BaseAdminDocsView):

def get_context_data(self, **kwargs):
view = self.kwargs['view']
urlconf = urlresolvers.get_urlconf()
if urlresolvers.get_resolver(urlconf)._is_callback(view):
mod, func = urlresolvers.get_mod_func(view)
urlconf = urls.get_urlconf()
if urls.get_resolver(urlconf)._is_callback(view):
mod, func = get_mod_func(view)
view_func = getattr(import_module(mod), func)
else:
raise Http404
Expand Down Expand Up @@ -344,25 +345,25 @@ def extract_views_from_urlpatterns(urlpatterns, base='', namespace=None):
Each object in the returned list is a two-tuple: (view_func, regex)
"""
views = []
for p in urlpatterns:
if hasattr(p, 'url_patterns'):
for name, resolver in urlpatterns:
if hasattr(resolver, 'resolvers'):
try:
patterns = p.url_patterns
sub_resolvers = resolver.resolvers
except ImportError:
continue
views.extend(extract_views_from_urlpatterns(
patterns,
base + p.regex.pattern,
(namespace or []) + (p.namespace and [p.namespace] or [])
sub_resolvers,
base + ''.join(c.describe() for c in resolver.constraints),
(namespace or []) + (name and [name] or [])
))
elif hasattr(p, 'callback'):
elif hasattr(resolver, 'func'):
try:
views.append((p.callback, base + p.regex.pattern,
namespace, p.name))
views.append((resolver.func, base + ''.join(c.describe() for c in resolver.constraints),
namespace, resolver.url_name))
except ViewDoesNotExist:
continue
else:
raise TypeError(_("%s does not appear to be a urlpattern object") % p)
raise TypeError(_("%s does not appear to be a resolver object") % resolver)
return views

named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)')
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/auth/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
)
from django.contrib.auth.models import Group, User
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.db import transaction
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text
from django.utils.html import escape
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
)
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, QueryDict
from django.shortcuts import resolve_url
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.deprecation import (
RemovedInDjango20Warning, RemovedInDjango110Warning,
)
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/flatpages/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import unicode_literals

from django.contrib.sites.models import Site
from django.core.urlresolvers import get_script_prefix
from django.db import models
from django.urls import get_script_prefix
from django.utils.encoding import iri_to_uri, python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _

Expand Down
14 changes: 7 additions & 7 deletions django/contrib/gis/sitemaps/kml.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django import urls
from django.apps import apps
from django.contrib.gis.db.models.fields import GeometryField
from django.contrib.sitemaps import Sitemap
from django.core import urlresolvers
from django.db import models


Expand Down Expand Up @@ -56,12 +56,12 @@ def items(self):
return self.locations

def location(self, obj):
return urlresolvers.reverse('django.contrib.gis.sitemaps.views.%s' % self.geo_format,
kwargs={'label': obj[0],
'model': obj[1],
'field_name': obj[2],
}
)
return urls.reverse('django.contrib.gis.sitemaps.views.%s' % self.geo_format,
kwargs={'label': obj[0],
'model': obj[1],
'field_name': obj[2],
}
)


class KMZSitemap(KMLSitemap):
Expand Down
13 changes: 7 additions & 6 deletions django/contrib/sitemaps/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django import urls
from django.apps import apps as django_apps
from django.conf import settings
from django.core import paginator, urlresolvers
from django.core import paginator
from django.core.exceptions import ImproperlyConfigured
from django.utils import translation
from django.utils.six.moves.urllib.parse import urlencode
Expand All @@ -18,17 +19,17 @@ def ping_google(sitemap_url=None, ping_url=PING_URL):
Alerts Google that the sitemap for the current site has been updated.
If sitemap_url is provided, it should be an absolute path to the sitemap
for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this
function will attempt to deduce it by using urlresolvers.reverse().
function will attempt to deduce it by using urls.reverse().
"""
if sitemap_url is None:
try:
# First, try to get the "index" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.index')
except urlresolvers.NoReverseMatch:
sitemap_url = urls.reverse('django.contrib.sitemaps.views.index')
except urls.NoReverseMatch:
try:
# Next, try for the "global" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap')
except urlresolvers.NoReverseMatch:
sitemap_url = urls.reverse('django.contrib.sitemaps.views.sitemap')
except urls.NoReverseMatch:
pass

if sitemap_url is None:
Expand Down
Loading