From 7ff344bf8b4943c0bb2309a4aa01be146f21bc29 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 16 Oct 2017 09:58:25 +0200 Subject: [PATCH 1/4] Update remaing `include` calls Missed as part of #5481 cleanup. --- tests/test_routers.py | 2 +- tests/test_versioning.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_routers.py b/tests/test_routers.py index 46d54ed9f3..39c5317d6d 100644 --- a/tests/test_routers.py +++ b/tests/test_routers.py @@ -97,7 +97,7 @@ def regex_url_path_detail(self, request, *args, **kwargs): urlpatterns = [ url(r'^non-namespaced/', include(namespaced_router.urls)), - url(r'^namespaced/', include(namespaced_router.urls, namespace='example', app_name='example')), + url(r'^namespaced/', include((namespaced_router.urls, 'example'), namespace='example')), url(r'^example/', include(notes_router.urls)), url(r'^example2/', include(kwarged_notes_router.urls)), diff --git a/tests/test_versioning.py b/tests/test_versioning.py index ab64dfab7f..e73059c7d7 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -170,7 +170,7 @@ class TestURLReversing(URLPatternsTestCase): ] urlpatterns = [ - url(r'^v1/', include(included, namespace='v1', app_name='v1')), + url(r'^v1/', include((included, 'v1'), namespace='v1')), url(r'^another/$', dummy_view, name='another'), url(r'^(?P[v1|v2]+)/another/$', dummy_view, name='another'), ] @@ -335,8 +335,8 @@ class TestHyperlinkedRelatedField(URLPatternsTestCase): ] urlpatterns = [ - url(r'^v1/', include(included, namespace='v1', app_name='v1')), - url(r'^v2/', include(included, namespace='v2', app_name='v2')) + url(r'^v1/', include((included, 'v1'), namespace='v1')), + url(r'^v2/', include((included, 'v2'), namespace='v2')) ] def setUp(self): @@ -367,12 +367,12 @@ class TestNamespaceVersioningHyperlinkedRelatedFieldScheme(URLPatternsTestCase): ] included = [ url(r'^namespaced/(?P\d+)/$', dummy_pk_view, name='namespaced'), - url(r'^nested/', include(nested, namespace='nested-namespace', app_name='nested-namespace')) + url(r'^nested/', include((nested, 'nested-namespace'), namespace='nested-namespace')) ] urlpatterns = [ - url(r'^v1/', include(included, namespace='v1', app_name='restframeworkv1')), - url(r'^v2/', include(included, namespace='v2', app_name='restframeworkv2')), + url(r'^v1/', include((included, 'restframeworkv1'), namespace='v1')), + url(r'^v2/', include((included, 'restframeworkv2'), namespace='v2')), url(r'^non-api/(?P\d+)/$', dummy_pk_view, name='non-api-view') ] From d1e69ad33474d728a0e7e32ea5d72ac496d02ec3 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 16 Oct 2017 10:14:25 +0200 Subject: [PATCH 2/4] Provide app_name in include_docs_urls --- rest_framework/documentation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/documentation.py b/rest_framework/documentation.py index 9f9c828bc0..8aee5c932c 100644 --- a/rest_framework/documentation.py +++ b/rest_framework/documentation.py @@ -76,4 +76,4 @@ def include_docs_urls( url(r'^$', docs_view, name='docs-index'), url(r'^schema.js$', schema_js_view, name='schema-js') ] - return include(urls, namespace='api-docs') + return include((urls, 'api-docs'), namespace='api-docs') From 0e9fcd19ea5f7e8ea47bc1b943f94e988547ffb4 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 16 Oct 2017 10:25:16 +0200 Subject: [PATCH 3/4] Update remaining get_regex_pattern usages --- tests/test_routers.py | 11 ++++++----- tests/test_schemas.py | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/test_routers.py b/tests/test_routers.py index 39c5317d6d..07a57fe55b 100644 --- a/tests/test_routers.py +++ b/tests/test_routers.py @@ -9,6 +9,7 @@ from django.test import TestCase, override_settings from rest_framework import permissions, serializers, viewsets +from rest_framework.compat import get_regex_pattern from rest_framework.decorators import detail_route, list_route from rest_framework.response import Response from rest_framework.routers import DefaultRouter, SimpleRouter @@ -176,7 +177,7 @@ def setUp(self): def test_custom_lookup_field_route(self): detail_route = notes_router.urls[-1] - detail_url_pattern = detail_route.regex.pattern + detail_url_pattern = get_regex_pattern(detail_route) assert '' in detail_url_pattern def test_retrieve_lookup_field_list_view(self): @@ -213,7 +214,7 @@ class NoteViewSet(viewsets.ModelViewSet): def test_urls_limited_by_lookup_value_regex(self): expected = ['^notes/$', '^notes/(?P[0-9a-f]{32})/$'] for idx in range(len(expected)): - assert expected[idx] == self.urls[idx].regex.pattern + assert expected[idx] == get_regex_pattern(self.urls[idx]) @override_settings(ROOT_URLCONF='tests.test_routers') @@ -228,7 +229,7 @@ def setUp(self): def test_custom_lookup_url_kwarg_route(self): detail_route = kwarged_notes_router.urls[-1] - detail_url_pattern = detail_route.regex.pattern + detail_url_pattern = get_regex_pattern(detail_route) assert '^notes/(?P' in detail_url_pattern def test_retrieve_lookup_url_kwarg_detail_view(self): @@ -252,7 +253,7 @@ class NoteViewSet(viewsets.ModelViewSet): def test_urls_have_trailing_slash_by_default(self): expected = ['^notes/$', '^notes/(?P[^/.]+)/$'] for idx in range(len(expected)): - assert expected[idx] == self.urls[idx].regex.pattern + assert expected[idx] == get_regex_pattern(self.urls[idx]) class TestTrailingSlashRemoved(TestCase): @@ -267,7 +268,7 @@ class NoteViewSet(viewsets.ModelViewSet): def test_urls_can_have_trailing_slash_removed(self): expected = ['^notes$', '^notes/(?P[^/.]+)$'] for idx in range(len(expected)): - assert expected[idx] == self.urls[idx].regex.pattern + assert expected[idx] == get_regex_pattern(self.urls[idx]) class TestNameableRoot(TestCase): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 901f4c6c56..d07e77fb31 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -9,7 +9,7 @@ from rest_framework import ( filters, generics, pagination, permissions, serializers ) -from rest_framework.compat import coreapi, coreschema +from rest_framework.compat import coreapi, coreschema, get_regex_pattern from rest_framework.decorators import ( api_view, detail_route, list_route, schema ) @@ -689,7 +689,7 @@ def test_should_include_endpoint_excludes_correctly(self): inspector = EndpointEnumerator(self.patterns) # Not pretty. Mimics internals of EndpointEnumerator to put should_include_endpoint under test - pairs = [(inspector.get_path_from_regex(pattern.regex.pattern), pattern.callback) + pairs = [(inspector.get_path_from_regex(get_regex_pattern(pattern)), pattern.callback) for pattern in self.patterns] should_include = [ From 7166c35a8788a77675fc694414ee06b54db6f8dc Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 16 Oct 2017 11:16:13 +0200 Subject: [PATCH 4/4] Allow functools.partial in is_simple_callable check --- rest_framework/fields.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index adb0026898..43fed9aeef 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -4,6 +4,7 @@ import copy import datetime import decimal +import functools import inspect import re import uuid @@ -54,7 +55,7 @@ def is_simple_callable(obj): """ True if the object is a callable that takes no arguments. """ - if not (inspect.isfunction(obj) or inspect.ismethod(obj)): + if not (inspect.isfunction(obj) or inspect.ismethod(obj) or isinstance(obj, functools.partial)): return False sig = inspect.signature(obj)