Skip to content

Commit

Permalink
merge with current develop
Browse files Browse the repository at this point in the history
  • Loading branch information
napster125 committed Mar 1, 2014
1 parent dea2f7b commit e45a97c
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 52 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ Many thanks to Tom Christie & all the contributors who have developed [Django RE
* David Wolever (@wolever)
* Brian Moe (@bmoe)
* Ian Martin (@aztechian)
* @pzrq
* @jfelectron
* Warnar Boekkooi (@boekkooi)
* Darren Thompson (@WhiteDawn)
* Lukasz Balcerzak (@lukaszb)
* David Newgas (@davidn)


### Django REST Framework Docs contributors:
Expand All @@ -126,6 +132,12 @@ Many thanks to Tom Christie & all the contributors who have developed [Django RE

## Release Notes:

### v0.1.12 (Feb 24, 2014)
* Improved resource grouping
* Alphabetical sorting of resources
* Fixed CSRF headers
* Misc bug fixes & improvements

### v0.1.11 (Dec 1, 2013)
* Added proper unicode support for Python 2
* Compatibility fixes for Python 3
Expand Down
3 changes: 1 addition & 2 deletions rest_framework_swagger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
'api_key': '',
'enabled_methods': ['get', 'post', 'put', 'patch', 'delete'],
'is_authenticated': False,
'is_superuser': False,
'resource_url_prefix': None
'is_superuser': False
}

try:
Expand Down
20 changes: 17 additions & 3 deletions rest_framework_swagger/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def test_flatten_url_tree_with_filter(self):
urlparser = UrlParser()
apis = urlparser.get_apis(self.url_patterns, filter_path="a-view")

self.assertEqual(1, len(apis))
self.assertEqual(3, len(apis))

def test_flatten_url_tree_excluded_namesapce(self):
urls = patterns('',
Expand Down Expand Up @@ -135,9 +135,9 @@ def test_get_api_callback_not_rest_view(self):

def test_get_top_level_api(self):
urlparser = UrlParser()
apis = urlparser.get_top_level_apis(urlparser.get_apis(self.url_patterns), None)
apis = urlparser.get_top_level_apis(urlparser.get_apis(self.url_patterns))

self.assertEqual(4, len(apis))
self.assertEqual(2, len(apis))

def test_assemble_endpoint_data(self):
"""
Expand Down Expand Up @@ -175,6 +175,20 @@ class MyViewSet(ModelViewSet):

self.assertEqual(4, urls_created - len(apis))

def test_get_base_path_for_common_endpoints(self):
parser = UrlParser()
paths = ['api/endpoint1', 'api/endpoint2']
base_path = parser.__get_base_path__(paths)

self.assertEqual('api/', base_path)

def test_get_base_path_for_root_level_endpoints(self):
parser = UrlParser()
paths = ['endpoint1', 'endpoint2', 'endpoint3']
base_path = parser.__get_base_path__(paths)

self.assertEqual('', base_path)


class NestedUrlParserTest(TestCase):
def setUp(self):
Expand Down
67 changes: 38 additions & 29 deletions rest_framework_swagger/urlparser.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import unipath
import os

from django.conf import settings
from django.utils.importlib import import_module
from django.core.urlresolvers import RegexURLResolver, RegexURLPattern
from django.contrib.admindocs.views import simplify_regex

from rest_framework.views import APIView

from rest_framework_swagger.apidocview import APIDocView
from .apidocview import APIDocView


class UrlParser(object):

def get_apis(self, patterns=None, filter_path=None, exclude_namespaces=[], resource_url_prefix=None):
def get_apis(self, patterns=None, filter_path=None, exclude_namespaces=[]):
"""
Returns all the DRF APIViews found in the project URLs
Expand All @@ -22,40 +23,26 @@ def get_apis(self, patterns=None, filter_path=None, exclude_namespaces=[], resou
urls = import_module(settings.ROOT_URLCONF)
patterns = urls.urlpatterns

if filter_path is not None:
return self.get_filtered_apis(patterns, filter_path, resource_url_prefix)

patterns = self.__flatten_patterns_tree__(
apis = self.__flatten_patterns_tree__(
patterns,
filter_path=filter_path,
exclude_namespaces=exclude_namespaces,
)
if filter_path is not None:
return self.get_filtered_apis(apis, filter_path)

return patterns
return apis

def get_filtered_apis(self, patterns, filter_path, resource_url_prefix):
def get_filtered_apis(self, apis, filter_path):
filtered_list = []

all_apis = self.get_apis(patterns, exclude_namespaces=[])
top_level_apis = self.get_top_level_apis(all_apis, resource_url_prefix)
top_level_apis.discard(filter_path)

for top in list(top_level_apis):
if top in filter_path: #and len(filter_path) > len(top):
top_level_apis.remove(top)

for api in all_apis:
remove = False
for top in top_level_apis:
if top + '/' in api['path'].lstrip("/"):
remove = True

if filter_path in api['path'].strip("/") and not remove:
for api in apis:
if filter_path in api['path'].strip('/'):
filtered_list.append(api)

return filtered_list

def get_top_level_apis(self, apis, resource_url_prefix):
def get_top_level_apis(self, apis):
"""
Returns the 'top level' APIs (ie. swagger 'resources')
Expand All @@ -68,14 +55,36 @@ def get_top_level_apis(self, apis, resource_url_prefix):
# If a URLs /resource/ and /resource/{pk} exist, use the base
# as the resource. If there is no base resource URL, then include
path_base = path.split('/{')[0]
if resource_url_prefix is not None:
path_base = path_base.replace(resource_url_prefix, '', 1)
path_base = path_base.split('/')[0]
if '{' in path and path_base in api_paths:
continue
root_paths.add(path_base)

return root_paths
top_level_apis = self.__filter_top_level_apis__(root_paths)

return sorted(top_level_apis, key=self.__get_last_element__)

def __filter_top_level_apis__(self, root_paths):
"""
Returns top level APIs
"""
filtered_paths = set()
base_path = self.__get_base_path__(root_paths)
for path in root_paths:
resource = path.lstrip(base_path).split('/')[0]
filtered_paths.add(base_path + resource)

return list(filtered_paths)

def __get_base_path__(self, root_paths):
base_path = os.path.commonprefix(root_paths)
slash_index = base_path.rfind('/') + 1
base_path = base_path[:slash_index]

return base_path

def __get_last_element__(self, paths):
split_paths = paths.split('/')
return split_paths[len(split_paths) - 1]

def __assemble_endpoint_data__(self, pattern, prefix='', filter_path=None):
"""
Expand Down
19 changes: 3 additions & 16 deletions rest_framework_swagger/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,11 @@ def get(self, request):

def get_resources(self):
urlparser = UrlParser()
apis = urlparser.get_apis(
exclude_namespaces=SWAGGER_SETTINGS.get('exclude_namespaces')
)
resources = urlparser.get_top_level_apis(
apis,
resource_url_prefix=SWAGGER_SETTINGS.get('resource_url_prefix')
)
resources = sorted(resources, key=self.get_child)
apis = urlparser.get_apis(exclude_namespaces=SWAGGER_SETTINGS.get('exclude_namespaces'))
resources = urlparser.get_top_level_apis(apis)

return resources

def get_child(self, path):
split_path = path.split('/')
return split_path[len(split_path) - 1]


class SwaggerApiView(APIDocView):

Expand All @@ -101,7 +91,4 @@ def get(self, request, path):

def get_api_for_resource(self, filter_path):
urlparser = UrlParser()
return urlparser.get_apis(
filter_path=filter_path,
resource_url_prefix=SWAGGER_SETTINGS.get('resource_url_prefix')
)
return urlparser.get_apis(filter_path=filter_path)
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from setuptools import setup
from rest_framework_swagger import VERSION

#README = open(os.path.join(os.path.dirname(__file__), 'README.md')).read()

README = """
Django REST Swagger
Expand Down Expand Up @@ -50,4 +50,3 @@
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)

0 comments on commit e45a97c

Please sign in to comment.