From 220649e57958a2f3e4f56f94807a84734ab230bb Mon Sep 17 00:00:00 2001 From: jakedt Date: Tue, 11 Mar 2014 15:20:03 -0400 Subject: [PATCH] Use doc strings for resource and method docs. Tweak some docs. Switch to 100 length lines. --- endpoints/api/__init__.py | 12 +++---- endpoints/api/discovery.py | 20 ++++++------ endpoints/api/repository.py | 62 +++++++++++++++++-------------------- 3 files changed, 43 insertions(+), 51 deletions(-) diff --git a/endpoints/api/__init__.py b/endpoints/api/__init__.py index 16e6dcdb9..5bbceb959 100644 --- a/endpoints/api/__init__.py +++ b/endpoints/api/__init__.py @@ -56,10 +56,9 @@ def method_metadata(func, name): nickname = partial(add_method_metadata, 'nickname') -def query_parameter(name, help_str, type=reqparse.text_type, - default=None, choices=(), required=False): +def query_param(name, help_str, type=reqparse.text_type, default=None, + choices=(), required=False): def add_param(func): - logger.debug('%s', func) if '__api_query_params' not in dir(func): func.__api_query_params = [] func.__api_query_params.append({ @@ -78,8 +77,6 @@ def parse_args(func): @wraps(func) def wrapper(self, *args, **kwargs): if '__api_query_params' not in dir(func): - logger.debug('No query params defined.') - logger.debug('%s', func) abort(400) parser = reqparse.RequestParser() @@ -139,9 +136,8 @@ def validate_json_request(schema_name): def log_action(kind, user_or_orgname, metadata={}, repo=None): performer = current_user.db_user() - model.log_action(kind, user_or_orgname, performer=performer, - ip=request.remote_addr, metadata=metadata, repository=repo) - + model.log_action(kind, user_or_orgname, performer=performer, ip=request.remote_addr, + metadata=metadata, repository=repo) import endpoints.api.legacy diff --git a/endpoints/api/discovery.py b/endpoints/api/discovery.py index 081dc05c0..7ec4c1ae6 100644 --- a/endpoints/api/discovery.py +++ b/endpoints/api/discovery.py @@ -29,11 +29,12 @@ def swagger_route_data(): endpoint_method = app.view_functions[rule.endpoint] if 'view_class' in dir(endpoint_method): + view_class = endpoint_method.view_class operations = [] method_names = list(rule.methods.difference(['HEAD', 'OPTIONS'])) for method_name in method_names: - method = getattr(endpoint_method.view_class, method_name.lower(), None) + method = getattr(view_class, method_name.lower(), None) parameters = [] for param in rule.arguments: @@ -49,16 +50,15 @@ def swagger_route_data(): if req_schema_name: parameters.append({ 'paramType': 'body', - 'name': 'request_body', + 'name': 'body', 'description': 'Request body contents.', 'dataType': req_schema_name, 'required': True, }) - schema = endpoint_method.view_class.schemas[req_schema_name] + schema = view_class.schemas[req_schema_name] models[req_schema_name] = schema - logger.debug('method dir: %s', dir(method)) if '__api_query_params' in dir(method): for param_spec in method.__api_query_params: new_param = { @@ -79,13 +79,14 @@ def swagger_route_data(): 'method': method_name, 'nickname': method_metadata(method, 'nickname'), 'type': 'void', + 'summary': method.__doc__ if method.__doc__ else '', 'parameters': parameters, }) swagger_path = PARAM_REGEX.sub(r'{\2}', rule.rule) apis.append({ 'path': swagger_path, - 'description': 'Resource description.', + 'description': view_class.__doc__ if view_class.__doc__ else "", 'operations': operations, }) @@ -96,10 +97,9 @@ def swagger_route_data(): 'resourcePath': '/', 'info': { 'title': 'Quay.io API', - 'description': ('This API allows you to perform many of the operations ' - 'required to work with Quay.io repositories, users, and ' - 'organizations. You can find out more at ' - 'Quay.io.'), + 'description': ('This API allows you to perform many of the operations required to work ' + 'with Quay.io repositories, users, and organizations. You can find out more ' + 'at Quay.io.'), 'termsOfServiceUrl': 'https://quay.io/tos', 'contact': 'support@quay.io', }, @@ -110,6 +110,8 @@ def swagger_route_data(): @resource('/v1/discovery') class DiscoveryResource(Resource): + """Ability to inspect the API for usage information and documentation.""" @nickname('discovery') def get(self): + """ List all of the API endpoints available in the swagger API format.""" return swagger_route_data() diff --git a/endpoints/api/repository.py b/endpoints/api/repository.py index 8bda3a115..48081809a 100644 --- a/endpoints/api/repository.py +++ b/endpoints/api/repository.py @@ -5,12 +5,10 @@ from flask.ext.restful import Resource, reqparse, abort from flask.ext.login import current_user from data import model -from endpoints.api import (truthy_bool, format_date, nickname, log_action, - validate_json_request, require_repo_read, - RepositoryParamResource, resource, query_parameter, +from endpoints.api import (truthy_bool, format_date, nickname, log_action, validate_json_request, + require_repo_read, RepositoryParamResource, resource, query_param, parse_args) -from auth.permissions import (ReadRepositoryPermission, - ModifyRepositoryPermission, +from auth.permissions import (ReadRepositoryPermission, ModifyRepositoryPermission, AdministerRepositoryPermission) @@ -19,11 +17,12 @@ logger = logging.getLogger(__name__) @resource('/v1/repository') class RepositoryList(Resource): + """Operations for creating and listing repositories.""" schemas = { 'NewRepo': { 'id': 'NewRepo', 'type': 'object', - 'description': 'Description of a new repository.', + 'description': 'Description of a new repository', 'required': [ 'repository', 'visibility', @@ -31,11 +30,11 @@ class RepositoryList(Resource): 'properties': { 'repository': { 'type': 'string', - 'description': 'Repository name.', + 'description': 'Repository name', }, 'visibility': { 'type': 'string', - 'description': 'Visibility which the repository will start with.', + 'description': 'Visibility which the repository will start with', 'enum': [ 'public', 'private', @@ -43,13 +42,12 @@ class RepositoryList(Resource): }, 'namespace': { 'type': 'string', - 'description': ('Namespace in which the repository should be ' - 'created. If omitted, the username of the caller is' - 'used.'), + 'description': ('Namespace in which the repository should be created. If omitted, the ' + 'username of the caller is used'), }, 'description': { 'type': 'string', - 'description': 'Markdown encoded description for the repository.', + 'description': 'Markdown encoded description for the repository', }, } } @@ -58,6 +56,7 @@ class RepositoryList(Resource): @nickname('createRepo') @validate_json_request('NewRepo') def post(self): + """Create a new repository.""" owner = current_user.db_user() req = request.get_json() namespace_name = req['namespace'] if 'namespace' in req else owner.username @@ -78,9 +77,8 @@ class RepositoryList(Resource): repo.description = req['description'] repo.save() - log_action('create_repo', namespace_name, - {'repo': repository_name, 'namespace': namespace_name}, - repo=repo) + log_action('create_repo', namespace_name, {'repo': repository_name, + 'namespace': namespace_name}, repo=repo) return jsonify({ 'namespace': namespace_name, 'name': repository_name @@ -90,20 +88,17 @@ class RepositoryList(Resource): @nickname('listRepos') @parse_args - @query_parameter('page', 'Offset page number. (int)', type=int) - @query_parameter('limit', 'Limit on the number of results (int)', type=int) - @query_parameter('namespace', ('Namespace to use when querying for org ' - 'repositories.'), type=str) - @query_parameter('public', 'Whether to include public repositories.', - type=truthy_bool, default=True) - @query_parameter('private', 'Whether to inlcude private repositories.', - type=truthy_bool, default=True) - @query_parameter('sort', 'Whether to sort the results.', type=truthy_bool, - default=False) - @query_parameter('count', ('Whether to include a count of the total number ' - 'of results available.'), type=truthy_bool, - default=False) + @query_param('page', 'Offset page number. (int)', type=int) + @query_param('limit', 'Limit on the number of results (int)', type=int) + @query_param('namespace', 'Namespace to use when querying for org repositories.', type=str) + @query_param('public', 'Whether to include public repositories.', type=truthy_bool, default=True) + @query_param('private', 'Whether to inlcude private repositories.', type=truthy_bool, + default=True) + @query_param('sort', 'Whether to sort the results.', type=truthy_bool, default=False) + @query_param('count', 'Whether to include a count of the total number of results available.', + type=truthy_bool, default=False) def get(self, args): + """Fetch the list of repositories under a variety of situations.""" def repo_view(repo_obj): return { 'namespace': repo_obj.namespace, @@ -120,15 +115,12 @@ class RepositoryList(Resource): repo_count = None if args['count']: - repo_count = model.get_visible_repository_count(username, - include_public=args['public'], + repo_count = model.get_visible_repository_count(username, include_public=args['public'], namespace=args['namespace']) response['count'] = repo_count - repo_query = model.get_visible_repositories(username, limit=args['limit'], - page=args['page'], - include_public=args['public'], - sort=args['sort'], + repo_query = model.get_visible_repositories(username, limit=args['limit'], page=args['page'], + include_public=args['public'], sort=args['sort'], namespace=args['namespace']) response['repositories'] = [repo_view(repo) for repo in repo_query] @@ -153,9 +145,11 @@ def image_view(image): @resource('/v1/repository/') class Repository(RepositoryParamResource): + """Operations for managing a specific repository.""" @require_repo_read @nickname('getRepo') def get(self, namespace, repository): + """Fetch the specified repository.""" logger.debug('Get repo: %s/%s' % (namespace, repository)) def tag_view(tag):