From 79a713898cc8da2157a96d2238c297903e924927 Mon Sep 17 00:00:00 2001
From: Philipp Reitter
Date: Mon, 4 Jul 2016 11:18:48 +0200
Subject: [PATCH 1/4] all parent patterns are kept as a list
---
rest_framework_docs/api_docs.py | 14 ++++++++------
rest_framework_docs/api_endpoint.py | 21 ++++++++-------------
2 files changed, 16 insertions(+), 19 deletions(-)
diff --git a/rest_framework_docs/api_docs.py b/rest_framework_docs/api_docs.py
index d22dd4c..8e8517e 100644
--- a/rest_framework_docs/api_docs.py
+++ b/rest_framework_docs/api_docs.py
@@ -7,7 +7,6 @@
class ApiDocumentation(object):
-
def __init__(self, drf_router=None):
self.endpoints = []
self.drf_router = drf_router
@@ -21,13 +20,16 @@ def __init__(self, drf_router=None):
else:
self.get_all_view_names(root_urlconf.urlpatterns)
- def get_all_view_names(self, urlpatterns, parent_pattern=None):
+ def get_all_view_names(self, urlpatterns, previous_parent_patterns=None):
for pattern in urlpatterns:
+ parent_patterns = list(previous_parent_patterns or [])
if isinstance(pattern, RegexURLResolver):
- parent_pattern = None if pattern._regex == "^" else pattern
- self.get_all_view_names(urlpatterns=pattern.url_patterns, parent_pattern=parent_pattern)
- elif isinstance(pattern, RegexURLPattern) and self._is_drf_view(pattern) and not self._is_format_endpoint(pattern):
- api_endpoint = ApiEndpoint(pattern, parent_pattern, self.drf_router)
+ if not pattern._regex == "^":
+ parent_patterns.append(pattern)
+ self.get_all_view_names(urlpatterns=pattern.url_patterns, previous_parent_patterns=parent_patterns)
+ elif isinstance(pattern, RegexURLPattern) and self._is_drf_view(pattern) \
+ and not self._is_format_endpoint(pattern):
+ api_endpoint = ApiEndpoint(pattern, parent_patterns)
self.endpoints.append(api_endpoint)
def _is_drf_view(self, pattern):
diff --git a/rest_framework_docs/api_endpoint.py b/rest_framework_docs/api_endpoint.py
index 89a33f8..193498a 100644
--- a/rest_framework_docs/api_endpoint.py
+++ b/rest_framework_docs/api_endpoint.py
@@ -6,28 +6,23 @@
class ApiEndpoint(object):
-
- def __init__(self, pattern, parent_pattern=None, drf_router=None):
- self.drf_router = drf_router
+ def __init__(self, pattern, parent_patterns=None):
self.pattern = pattern
self.callback = pattern.callback
# self.name = pattern.name
self.docstring = self.__get_docstring__()
- self.name_parent = simplify_regex(parent_pattern.regex.pattern).strip('/') if parent_pattern else None
- self.path = self.__get_path__(parent_pattern)
+ self.name_parent = '/'.join(
+ simplify_regex(pattern.regex.pattern).strip('/') for pattern in (parent_patterns or []))
+ self.path = self.__get_path__(parent_patterns)
self.allowed_methods = self.__get_allowed_methods__()
# self.view_name = pattern.callback.__name__
self.errors = None
- self.serializer_class = self.__get_serializer_class__()
- if self.serializer_class:
- self.serializer = self.__get_serializer__()
- self.fields = self.__get_serializer_fields__(self.serializer)
- self.fields_json = self.__get_serializer_fields_json__()
-
+ self.fields = self.__get_serializer_fields__()
+ self.fields_json = self.__get_serializer_fields_json__()
self.permissions = self.__get_permissions_class__()
- def __get_path__(self, parent_pattern):
- if parent_pattern:
+ def __get_path__(self, parent_patterns):
+ if parent_patterns:
return "/{0}{1}".format(self.name_parent, simplify_regex(self.pattern.regex.pattern))
return simplify_regex(self.pattern.regex.pattern)
From 46c64bb7934312d9188b56e3b972833877e49ff0 Mon Sep 17 00:00:00 2001
From: Philipp Reitter
Date: Mon, 4 Jul 2016 11:38:39 +0200
Subject: [PATCH 2/4] fixed drf_router missing
---
rest_framework_docs/api_docs.py | 2 +-
rest_framework_docs/api_endpoint.py | 15 ++++++++++-----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/rest_framework_docs/api_docs.py b/rest_framework_docs/api_docs.py
index 8e8517e..1364041 100644
--- a/rest_framework_docs/api_docs.py
+++ b/rest_framework_docs/api_docs.py
@@ -29,7 +29,7 @@ def get_all_view_names(self, urlpatterns, previous_parent_patterns=None):
self.get_all_view_names(urlpatterns=pattern.url_patterns, previous_parent_patterns=parent_patterns)
elif isinstance(pattern, RegexURLPattern) and self._is_drf_view(pattern) \
and not self._is_format_endpoint(pattern):
- api_endpoint = ApiEndpoint(pattern, parent_patterns)
+ api_endpoint = ApiEndpoint(pattern, parent_patterns, self.drf_router)
self.endpoints.append(api_endpoint)
def _is_drf_view(self, pattern):
diff --git a/rest_framework_docs/api_endpoint.py b/rest_framework_docs/api_endpoint.py
index 193498a..df84379 100644
--- a/rest_framework_docs/api_endpoint.py
+++ b/rest_framework_docs/api_endpoint.py
@@ -6,19 +6,24 @@
class ApiEndpoint(object):
- def __init__(self, pattern, parent_patterns=None):
+
+ def __init__(self, pattern, parent_patterns=None, drf_router=None):
+ self.drf_router = drf_router
self.pattern = pattern
self.callback = pattern.callback
# self.name = pattern.name
self.docstring = self.__get_docstring__()
- self.name_parent = '/'.join(
- simplify_regex(pattern.regex.pattern).strip('/') for pattern in (parent_patterns or []))
+ self.name_parent = '/'.join(simplify_regex(pattern.regex.pattern).strip('/') for pattern in (parent_patterns or []))
self.path = self.__get_path__(parent_patterns)
self.allowed_methods = self.__get_allowed_methods__()
# self.view_name = pattern.callback.__name__
self.errors = None
- self.fields = self.__get_serializer_fields__()
- self.fields_json = self.__get_serializer_fields_json__()
+ self.serializer_class = self.__get_serializer_class__()
+ if self.serializer_class:
+ self.serializer = self.__get_serializer__()
+ self.fields = self.__get_serializer_fields__(self.serializer)
+ self.fields_json = self.__get_serializer_fields_json__()
+
self.permissions = self.__get_permissions_class__()
def __get_path__(self, parent_patterns):
From a61fb6ce7df701e9fc63d112d30f10da168688aa Mon Sep 17 00:00:00 2001
From: Philipp Reitter
Date: Mon, 4 Jul 2016 23:41:04 +0200
Subject: [PATCH 3/4] fixed a bug with starting/trailing slashes
---
rest_framework_docs/api_endpoint.py | 6 ++++--
tests/tests.py | 24 +++++++++++++++++-------
tests/urls.py | 12 ++++++++++++
tests/views.py | 4 ++++
4 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/rest_framework_docs/api_endpoint.py b/rest_framework_docs/api_endpoint.py
index df84379..0b477a3 100644
--- a/rest_framework_docs/api_endpoint.py
+++ b/rest_framework_docs/api_endpoint.py
@@ -13,7 +13,9 @@ def __init__(self, pattern, parent_patterns=None, drf_router=None):
self.callback = pattern.callback
# self.name = pattern.name
self.docstring = self.__get_docstring__()
- self.name_parent = '/'.join(simplify_regex(pattern.regex.pattern).strip('/') for pattern in (parent_patterns or []))
+ self.name_parent = ''.join([pattern.regex.pattern for pattern in (parent_patterns or [])])
+ self.name_parent_suffix = '/' if self.name_parent.endswith('/') else ''
+ self.name_parent = simplify_regex(self.name_parent).strip('/')
self.path = self.__get_path__(parent_patterns)
self.allowed_methods = self.__get_allowed_methods__()
# self.view_name = pattern.callback.__name__
@@ -28,7 +30,7 @@ def __init__(self, pattern, parent_patterns=None, drf_router=None):
def __get_path__(self, parent_patterns):
if parent_patterns:
- return "/{0}{1}".format(self.name_parent, simplify_regex(self.pattern.regex.pattern))
+ return simplify_regex("{}{}{}".format(self.name_parent, self.name_parent_suffix, self.pattern.regex.pattern))
return simplify_regex(self.pattern.regex.pattern)
def __get_allowed_methods__(self):
diff --git a/tests/tests.py b/tests/tests.py
index 998faee..4f4903c 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -27,7 +27,7 @@ def test_index_view_with_endpoints(self):
response = self.client.get(reverse('drfdocs'))
self.assertEqual(response.status_code, 200)
- self.assertEqual(len(response.context["endpoints"]), 15)
+ self.assertEqual(len(response.context["endpoints"]), 17)
# Test the login view
self.assertEqual(response.context["endpoints"][0].name_parent, "accounts")
@@ -49,6 +49,16 @@ def test_index_view_with_endpoints(self):
# The view "OrganisationErroredView" (organisations/(?P[\w-]+)/errored/) should contain an error.
self.assertEqual(str(response.context["endpoints"][9].errors), "'test_value'")
+ def test_deep_recurrence(self):
+ response = self.client.get("%s?search=inherited" % reverse("drfdocs"))
+
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(response.context["endpoints"]), 2)
+
+ endpoints = response.context["endpoints"]
+ self.assertEqual(endpoints[0].path, '/organisations/inherited/view/')
+ self.assertEqual(endpoints[1].path, '/organisations/inherited2no-slash/')
+
def test_index_search_with_endpoints(self):
response = self.client.get("%s?search=reset-password" % reverse("drfdocs"))
@@ -75,9 +85,9 @@ def test_model_viewset(self):
self.assertEqual(response.context["endpoints"][10].path, '/organisations//')
self.assertEqual(response.context['endpoints'][6].fields[2]['to_many_relation'], True)
- self.assertEqual(response.context["endpoints"][11].path, '/organisation-model-viewsets/')
- self.assertEqual(response.context["endpoints"][12].path, '/organisation-model-viewsets//')
- self.assertEqual(response.context["endpoints"][11].allowed_methods, ['GET', 'POST', 'OPTIONS'])
- self.assertEqual(response.context["endpoints"][12].allowed_methods, ['GET', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'])
- self.assertEqual(response.context["endpoints"][13].allowed_methods, ['POST', 'OPTIONS'])
- self.assertEqual(response.context["endpoints"][13].docstring, 'This is a test.')
+ self.assertEqual(response.context["endpoints"][13].path, '/organisation-model-viewsets/')
+ self.assertEqual(response.context["endpoints"][14].path, '/organisation-model-viewsets//')
+ self.assertEqual(response.context["endpoints"][13].allowed_methods, ['GET', 'POST', 'OPTIONS'])
+ self.assertEqual(response.context["endpoints"][14].allowed_methods, ['GET', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'])
+ self.assertEqual(response.context["endpoints"][15].allowed_methods, ['POST', 'OPTIONS'])
+ self.assertEqual(response.context["endpoints"][15].docstring, 'This is a test.')
diff --git a/tests/urls.py b/tests/urls.py
index abdf71b..52109e5 100644
--- a/tests/urls.py
+++ b/tests/urls.py
@@ -6,6 +6,14 @@
from rest_framework_docs.views import DRFDocsView
from tests import views
+inherited_urls = [
+ url(r'^view/$', views.InheritedView.as_view(), name="inherited"),
+]
+
+inherited_no_slash_urls = [
+ url(r'^no-slash/$', views.InheritedView.as_view(), name="inherited-no-slash"),
+]
+
accounts_urls = [
url(r'^login/$', views.LoginView.as_view(), name="login"),
url(r'^login2/$', views.LoginWithSerilaizerClassView.as_view(), name="login2"),
@@ -18,12 +26,16 @@
url(r'^test/$', views.TestView.as_view(), name="test-view"),
]
+
organisations_urls = [
url(r'^create/$', view=views.CreateOrganisationView.as_view(), name="create"),
url(r'^(?P[\w-]+)/members/$', view=views.OrganisationMembersView.as_view(), name="members"),
url(r'^(?P[\w-]+)/leave/$', view=views.LeaveOrganisationView.as_view(), name="leave"),
url(r'^(?P[\w-]+)/errored/$', view=views.OrganisationErroredView.as_view(), name="errored"),
url(r'^(?P[\w-]+)/$', view=views.RetrieveOrganisationView.as_view(), name="organisation"),
+
+ url(r'^inherited/', include(inherited_urls)),
+ url(r'^inherited2', include(inherited_no_slash_urls))
]
router = SimpleRouter()
diff --git a/tests/views.py b/tests/views.py
index fcf319d..a7dfc26 100644
--- a/tests/views.py
+++ b/tests/views.py
@@ -149,3 +149,7 @@ def test_route(self, request):
class RetrieveOrganisationView(generics.RetrieveAPIView):
serializer_class = serializers.RetrieveOrganisationSerializer
+
+
+class InheritedView(generics.CreateAPIView):
+ serializer_class = serializers.CreateOrganisationSerializer
From 8dc5bff2857c4857f53a1c4113311b9a49b1eba6 Mon Sep 17 00:00:00 2001
From: Philipp Reitter
Date: Mon, 4 Jul 2016 23:44:47 +0200
Subject: [PATCH 4/4] fixed flake8 test case
---
rest_framework_docs/api_endpoint.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rest_framework_docs/api_endpoint.py b/rest_framework_docs/api_endpoint.py
index 0b477a3..8ef2080 100644
--- a/rest_framework_docs/api_endpoint.py
+++ b/rest_framework_docs/api_endpoint.py
@@ -13,7 +13,7 @@ def __init__(self, pattern, parent_patterns=None, drf_router=None):
self.callback = pattern.callback
# self.name = pattern.name
self.docstring = self.__get_docstring__()
- self.name_parent = ''.join([pattern.regex.pattern for pattern in (parent_patterns or [])])
+ self.name_parent = ''.join([parent_pattern.regex.pattern for parent_pattern in (parent_patterns or [])])
self.name_parent_suffix = '/' if self.name_parent.endswith('/') else ''
self.name_parent = simplify_regex(self.name_parent).strip('/')
self.path = self.__get_path__(parent_patterns)