Commit ae720d9b by Tom Christie Committed by GitHub

Fix issue with generating categories for schema endpoints (#4394)

parent 7466b61e
...@@ -39,6 +39,10 @@ class SchemaGenerator(object): ...@@ -39,6 +39,10 @@ class SchemaGenerator(object):
'patch': 'partial_update', 'patch': 'partial_update',
'delete': 'destroy', 'delete': 'destroy',
} }
known_actions = (
'create', 'read', 'retrieve', 'list',
'update', 'partial_update', 'destroy'
)
def __init__(self, title=None, url=None, patterns=None, urlconf=None): def __init__(self, title=None, url=None, patterns=None, urlconf=None):
assert coreapi, '`coreapi` must be installed for schema support.' assert coreapi, '`coreapi` must be installed for schema support.'
...@@ -118,7 +122,8 @@ class SchemaGenerator(object): ...@@ -118,7 +122,8 @@ class SchemaGenerator(object):
if self.should_include_endpoint(path, callback): if self.should_include_endpoint(path, callback):
for method in self.get_allowed_methods(callback): for method in self.get_allowed_methods(callback):
action = self.get_action(path, method, callback) action = self.get_action(path, method, callback)
endpoint = (path, method, action, callback) category = self.get_category(path, method, callback, action)
endpoint = (path, method, category, action, callback)
api_endpoints.append(endpoint) api_endpoints.append(endpoint)
elif isinstance(pattern, RegexURLResolver): elif isinstance(pattern, RegexURLResolver):
...@@ -128,21 +133,7 @@ class SchemaGenerator(object): ...@@ -128,21 +133,7 @@ class SchemaGenerator(object):
) )
api_endpoints.extend(nested_endpoints) api_endpoints.extend(nested_endpoints)
return self.add_categories(api_endpoints) return api_endpoints
def add_categories(self, api_endpoints):
"""
(path, method, action, callback) -> (path, method, category, action, callback)
"""
# Determine the top level categories for the schema content,
# based on the URLs of the endpoints. Eg `set(['users', 'organisations'])`
paths = [endpoint[0] for endpoint in api_endpoints]
categories = self.get_categories(paths)
return [
(path, method, self.get_category(categories, path), action, callback)
for (path, method, action, callback) in api_endpoints
]
def get_path(self, path_regex): def get_path(self, path_regex):
""" """
...@@ -181,36 +172,41 @@ class SchemaGenerator(object): ...@@ -181,36 +172,41 @@ class SchemaGenerator(object):
def get_action(self, path, method, callback): def get_action(self, path, method, callback):
""" """
Return a description action string for the endpoint, eg. 'list'. Return a descriptive action string for the endpoint, eg. 'list'.
""" """
actions = getattr(callback, 'actions', self.default_mapping) actions = getattr(callback, 'actions', self.default_mapping)
return actions[method.lower()] return actions[method.lower()]
def get_categories(self, paths): def get_category(self, path, method, callback, action):
categories = set() """
split_paths = set([ Return a descriptive category string for the endpoint, eg. 'users'.
tuple(path.split("{")[0].strip('/').split('/'))
for path in paths Examples of category/action pairs that should be generated for various
]) endpoints:
while split_paths: /users/ [users][list], [users][create]
for split_path in list(split_paths): /users/{pk}/ [users][read], [users][update], [users][destroy]
if len(split_path) == 0: /users/enabled/ [users][enabled] (custom action)
split_paths.remove(split_path) /users/{pk}/star/ [users][star] (custom action)
elif len(split_path) == 1: /users/{pk}/groups/ [groups][list], [groups][create]
categories.add(split_path[0]) /users/{pk}/groups/{pk}/ [groups][read], [groups][update], [groups][destroy]
split_paths.remove(split_path) """
elif split_path[0] in categories: path_components = path.strip('/').split('/')
split_paths.remove(split_path) path_components = [
component for component in path_components
return categories if '{' not in component
]
def get_category(self, categories, path): if action in self.known_actions:
path_components = path.split("{")[0].strip('/').split('/') # Default action, eg "/users/", "/users/{pk}/"
for path_component in path_components: idx = -1
if path_component in categories: else:
return path_component # Custom action, eg "/users/{pk}/activate/", "/users/active/"
return None idx = -2
try:
return path_components[idx]
except IndexError:
return None
# Methods for generating each individual `Link` instance... # Methods for generating each individual `Link` instance...
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment