From 018bf8c5ad1f1bbeb144e80e81a7319e039ada6e Mon Sep 17 00:00:00 2001 From: Jake Moshenko Date: Tue, 26 Jan 2016 16:27:36 -0500 Subject: [PATCH] Refactor how parsed_args are passed to methods --- endpoints/api/__init__.py | 81 +++++++++++++++++++------------------ endpoints/api/build.py | 8 ++-- endpoints/api/discovery.py | 6 +-- endpoints/api/logs.py | 62 ++++++++++++++-------------- endpoints/api/repository.py | 22 +++++----- endpoints/api/robot.py | 12 +++--- endpoints/api/search.py | 18 ++++----- endpoints/api/secscan.py | 6 +-- endpoints/api/superuser.py | 18 ++++----- endpoints/api/tag.py | 18 ++++----- endpoints/api/team.py | 6 +-- endpoints/api/trigger.py | 6 +-- endpoints/api/user.py | 16 ++++---- 13 files changed, 142 insertions(+), 137 deletions(-) diff --git a/endpoints/api/__init__.py b/endpoints/api/__init__.py index 78100f4a7..7a3e4ea99 100644 --- a/endpoints/api/__init__.py +++ b/endpoints/api/__init__.py @@ -212,52 +212,55 @@ def query_param(name, help_str, type=reqparse.text_type, default=None, return func return add_param +def page_support(page_token_kwarg='page_token', parsed_args_kwarg='parsed_args'): + def inner(func): + """ Adds pagination support to an API endpoint. The decorated API will have an + added query parameter named 'next_page'. Works in tandem with the + modelutil paginate method. + """ + @wraps(func) + @query_param('next_page', 'The page token for the next page', type=str) + def wrapper(self, *args, **kwargs): + page_token = None -def page_support(func): - """ Adds pagination support to an API endpoint. The decorated API will have an - added query parameter named 'next_page'. Works in tandem with the - modelutil paginate method. - """ - @wraps(func) - @query_param('next_page', 'The page token for the next page', type=str) - def wrapper(self, query_args, *args, **kwargs): - page_token = None + if kwargs[parsed_args_kwarg]['next_page']: + # Decrypt the page token. + unencrypted = decrypt_string(kwargs[parsed_args_kwarg]['next_page'], + app.config['PAGE_TOKEN_KEY'], + ttl=_PAGE_TOKEN_TTL) + if unencrypted is not None: + try: + page_token = json.loads(unencrypted) + except ValueError: + pass - if query_args['next_page']: - # Decrypt the page token. - unencrypted = decrypt_string(query_args['next_page'], app.config['PAGE_TOKEN_KEY'], - ttl=_PAGE_TOKEN_TTL) - if unencrypted is not None: - try: - page_token = json.loads(unencrypted) - except ValueError: - pass + # Note: if page_token is None, we'll receive the first page of results back. + kwargs[page_token_kwarg] = page_token + (result, next_page_token) = func(self, *args, **kwargs) + if next_page_token is not None: + result['next_page'] = encrypt_string(json.dumps(next_page_token), + app.config['PAGE_TOKEN_KEY']) - # Note: if page_token is None, we'll receive the first page of results back. - (result, next_page_token) = func(self, query_args, page_token=page_token, *args, **kwargs) - if next_page_token is not None: - result['next_page'] = encrypt_string(json.dumps(next_page_token), - app.config['PAGE_TOKEN_KEY']) + return result - return result + return wrapper + return inner - return wrapper +def parse_args(kwarg_name='parsed_args'): + def inner(func): + @wraps(func) + def wrapper(self, *args, **kwargs): + if '__api_query_params' not in dir(func): + abort(500) + parser = reqparse.RequestParser() + for arg_spec in func.__api_query_params: + parser.add_argument(**arg_spec) + kwargs[kwarg_name] = parser.parse_args() -def parse_args(func): - @wraps(func) - def wrapper(self, *args, **kwargs): - if '__api_query_params' not in dir(func): - abort(500) - - parser = reqparse.RequestParser() - for arg_spec in func.__api_query_params: - parser.add_argument(**arg_spec) - parsed_args = parser.parse_args() - - return func(self, parsed_args, *args, **kwargs) - return wrapper - + return func(self, *args, **kwargs) + return wrapper + return inner def parse_repository_name(func): @wraps(func) diff --git a/endpoints/api/build.py b/endpoints/api/build.py index 97857638f..e206a905c 100644 --- a/endpoints/api/build.py +++ b/endpoints/api/build.py @@ -185,14 +185,14 @@ class RepositoryBuildList(RepositoryParamResource): } @require_repo_read - @parse_args + @parse_args() @query_param('limit', 'The maximum number of builds to return', type=int, default=5) @query_param('since', 'Returns all builds since the given unix timecode', type=int, default=None) @nickname('getRepoBuilds') - def get(self, args, namespace, repository): + def get(self, namespace, repository, parsed_args): """ Get the list of repository builds. """ - limit = args.get('limit', 5) - since = args.get('since', None) + limit = parsed_args.get('limit', 5) + since = parsed_args.get('since', None) if since is not None: since = datetime.datetime.utcfromtimestamp(since) diff --git a/endpoints/api/discovery.py b/endpoints/api/discovery.py index fd1a09f08..c024fde6f 100644 --- a/endpoints/api/discovery.py +++ b/endpoints/api/discovery.py @@ -272,9 +272,9 @@ def swagger_route_data(include_internal=False, compact=False): @resource('/v1/discovery') class DiscoveryResource(ApiResource): """Ability to inspect the API for usage information and documentation.""" - @parse_args + @parse_args() @query_param('internal', 'Whether to include internal APIs.', type=truthy_bool, default=False) @nickname('discovery') - def get(self, args): + def get(self, parsed_args): """ List all of the API endpoints available in the swagger API format.""" - return swagger_route_data(args['internal']) + return swagger_route_data(parsed_args['internal']) diff --git a/endpoints/api/logs.py b/endpoints/api/logs.py index d2c144c1f..e47939c60 100644 --- a/endpoints/api/logs.py +++ b/endpoints/api/logs.py @@ -113,19 +113,19 @@ class RepositoryLogs(RepositoryParamResource): """ Resource for fetching logs for the specific repository. """ @require_repo_admin @nickname('listRepoLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs (%m/%d/%Y %Z)', type=str) @query_param('page', 'The page number for the logs', type=int, default=1) - @page_support - def get(self, args, namespace, repository, page_token): + @page_support() + def get(self, namespace, repository, page_token, parsed_args): """ List the logs for the specified repository. """ repo = model.repository.get_repository(namespace, repository) if not repo: raise NotFound() - start_time = args['starttime'] - end_time = args['endtime'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] return get_logs(start_time, end_time, repository=repo, page_token=page_token) @@ -135,16 +135,16 @@ class UserLogs(ApiResource): """ Resource for fetching logs for the current user. """ @require_user_admin @nickname('listUserLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('performer', 'Username for which to filter logs.', type=str) - @page_support - def get(self, args, page_token): + @page_support() + def get(self, parsed_args, page_token): """ List the logs for the current user. """ - performer_name = args['performer'] - start_time = args['starttime'] - end_time = args['endtime'] + performer_name = parsed_args['performer'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] user = get_authenticated_user() return get_logs(start_time, end_time, performer_name=performer_name, namespace=user.username, @@ -157,20 +157,20 @@ class UserLogs(ApiResource): class OrgLogs(ApiResource): """ Resource for fetching logs for the entire organization. """ @nickname('listOrgLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('performer', 'Username for which to filter logs.', type=str) @query_param('page', 'The page number for the logs', type=int, default=1) - @page_support + @page_support() @require_scope(scopes.ORG_ADMIN) - def get(self, args, orgname, page_token): + def get(self, orgname, page_token, parsed_args): """ List the logs for the specified organization. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): - performer_name = args['performer'] - start_time = args['starttime'] - end_time = args['endtime'] + performer_name = parsed_args['performer'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] return get_logs(start_time, end_time, namespace=orgname, performer_name=performer_name, page_token=page_token) @@ -184,17 +184,17 @@ class RepositoryAggregateLogs(RepositoryParamResource): """ Resource for fetching aggregated logs for the specific repository. """ @require_repo_admin @nickname('getAggregateRepoLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs (%m/%d/%Y %Z)', type=str) - def get(self, args, namespace, repository): + def get(self, namespace, repository, parsed_args): """ Returns the aggregated logs for the specified repository. """ repo = model.repository.get_repository(namespace, repository) if not repo: raise NotFound() - start_time = args['starttime'] - end_time = args['endtime'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] return get_aggregate_logs(start_time, end_time, repository=repo) @@ -204,15 +204,15 @@ class UserAggregateLogs(ApiResource): """ Resource for fetching aggregated logs for the current user. """ @require_user_admin @nickname('getAggregateUserLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('performer', 'Username for which to filter logs.', type=str) - def get(self, args): + def get(self, parsed_args): """ Returns the aggregated logs for the current user. """ - performer_name = args['performer'] - start_time = args['starttime'] - end_time = args['endtime'] + performer_name = parsed_args['performer'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] user = get_authenticated_user() return get_aggregate_logs(start_time, end_time, performer_name=performer_name, @@ -225,18 +225,18 @@ class UserAggregateLogs(ApiResource): class OrgAggregateLogs(ApiResource): """ Resource for fetching aggregate logs for the entire organization. """ @nickname('getAggregateOrgLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('performer', 'Username for which to filter logs.', type=str) @require_scope(scopes.ORG_ADMIN) - def get(self, args, orgname): + def get(self, orgname, parsed_args): """ Gets the aggregated logs for the specified organization. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): - performer_name = args['performer'] - start_time = args['starttime'] - end_time = args['endtime'] + performer_name = parsed_args['performer'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] return get_aggregate_logs(start_time, end_time, namespace=orgname, performer_name=performer_name) diff --git a/endpoints/api/repository.py b/endpoints/api/repository.py index 18f4fc432..cecfbfa7c 100644 --- a/endpoints/api/repository.py +++ b/endpoints/api/repository.py @@ -167,7 +167,7 @@ class RepositoryList(ApiResource): @require_scope(scopes.READ_REPO) @nickname('listRepos') - @parse_args + @parse_args() @query_param('page', 'Offset page number. (int)', type=int) @query_param('limit', 'Limit on the number of results (int)', type=int) @query_param('namespace', 'Filters the repositories returned to this namespace', type=str) @@ -179,24 +179,26 @@ class RepositoryList(ApiResource): type=truthy_bool, default=False) @query_param('popularity', 'Whether to include the repository\'s popularity metric.', type=truthy_bool, default=False) - def get(self, args): + def get(self, parsed_args): """ Fetch the list of repositories visible to the current user under a variety of situations. """ - if not args['namespace'] and not args['starred'] and not args['public']: + if not parsed_args['namespace'] and not parsed_args['starred'] and not parsed_args['public']: raise InvalidRequest('namespace, starred or public are required for this API call') - repositories, star_lookup = self._load_repositories(args['namespace'], args['public'], - args['starred'], args['limit'], - args['page']) + repositories, star_lookup = self._load_repositories(parsed_args['namespace'], + parsed_args['public'], + parsed_args['starred'], + parsed_args['limit'], + parsed_args['page']) # Collect the IDs of the repositories found for subequent lookup of popularity # and/or last modified. repository_ids = [repo.id for repo in repositories] - if args['last_modified']: + if parsed_args['last_modified']: last_modified_map = model.repository.get_when_last_modified(repository_ids) - if args['popularity']: + if parsed_args['popularity']: action_count_map = model.repository.get_action_counts(repository_ids) def repo_view(repo_obj): @@ -209,10 +211,10 @@ class RepositoryList(ApiResource): repo_id = repo_obj.id - if args['last_modified']: + if parsed_args['last_modified']: repo['last_modified'] = last_modified_map.get(repo_id) - if args['popularity']: + if parsed_args['popularity']: repo['popularity'] = action_count_map.get(repo_id, 0) if get_authenticated_user(): diff --git a/endpoints/api/robot.py b/endpoints/api/robot.py index ed64f87cc..b1914bb34 100644 --- a/endpoints/api/robot.py +++ b/endpoints/api/robot.py @@ -75,14 +75,14 @@ class UserRobotList(ApiResource): """ Resource for listing user robots. """ @require_user_admin @nickname('getUserRobots') - @parse_args + @parse_args() @query_param('permissions', 'Whether to include repostories and teams in which the robots have permission.', type=truthy_bool, default=False) - def get(self, args): + def get(self, parsed_args): """ List the available robots for the user. """ user = get_authenticated_user() - return robots_list(user.username, include_permissions=args.get('permissions', False)) + return robots_list(user.username, include_permissions=parsed_args.get('permissions', False)) @resource('/v1/user/robots/') @@ -124,15 +124,15 @@ class OrgRobotList(ApiResource): """ Resource for listing an organization's robots. """ @require_scope(scopes.ORG_ADMIN) @nickname('getOrgRobots') - @parse_args + @parse_args() @query_param('permissions', 'Whether to include repostories and teams in which the robots have permission.', type=truthy_bool, default=False) - def get(self, args, orgname): + def get(self, orgname, parsed_args): """ List the organization's robots. """ permission = OrganizationMemberPermission(orgname) if permission.can(): - return robots_list(orgname, include_permissions=args.get('permissions', False)) + return robots_list(orgname, include_permissions=parsed_args.get('permissions', False)) raise Unauthorized() diff --git a/endpoints/api/search.py b/endpoints/api/search.py index ba961080f..143edc52f 100644 --- a/endpoints/api/search.py +++ b/endpoints/api/search.py @@ -19,18 +19,18 @@ import math class EntitySearch(ApiResource): """ Resource for searching entities. """ @path_param('prefix', 'The prefix of the entities being looked up') - @parse_args + @parse_args() @query_param('namespace', 'Namespace to use when querying for org entities.', type=str, default='') @query_param('includeTeams', 'Whether to include team names.', type=truthy_bool, default=False) @query_param('includeOrgs', 'Whether to include orgs names.', type=truthy_bool, default=False) @nickname('getMatchingEntities') - def get(self, args, prefix): + def get(self, prefix, parsed_args): """ Get a list of entities that match the specified prefix. """ teams = [] org_data = [] - namespace_name = args['namespace'] + namespace_name = parsed_args['namespace'] robot_namespace = None organization = None @@ -42,11 +42,11 @@ class EntitySearch(ApiResource): if permission.can(): robot_namespace = namespace_name - if args['includeTeams']: + if parsed_args['includeTeams']: teams = model.team.get_matching_teams(prefix, organization) - if args['includeOrgs'] and AdministerOrganizationPermission(namespace_name) \ - and namespace_name.startswith(prefix): + if (parsed_args['includeOrgs'] and AdministerOrganizationPermission(namespace_name) and + namespace_name.startswith(prefix)): org_data = [{ 'name': namespace_name, 'kind': 'org', @@ -217,13 +217,13 @@ def conduct_robot_search(username, query, results): @resource('/v1/find/all') class ConductSearch(ApiResource): """ Resource for finding users, repositories, teams, etc. """ - @parse_args + @parse_args() @query_param('query', 'The search query.', type=str, default='') @require_scope(scopes.READ_REPO) @nickname('conductSearch') - def get(self, args): + def get(self, parsed_args): """ Get a list of entities and resources that match the specified query. """ - query = args['query'] + query = parsed_args['query'] if not query: return {'results': []} diff --git a/endpoints/api/secscan.py b/endpoints/api/secscan.py index 272437bc4..91a5ee891 100644 --- a/endpoints/api/secscan.py +++ b/endpoints/api/secscan.py @@ -62,10 +62,10 @@ class RepositoryImageVulnerabilities(RepositoryParamResource): @require_repo_read @nickname('getRepoImageVulnerabilities') - @parse_args + @parse_args() @query_param('minimumPriority', 'Minimum vulnerability priority', type=str, default='Low') - def get(self, args, namespace, repository, imageid): + def get(self, namespace, repository, imageid, parsed_args): """ Fetches the vulnerabilities (if any) for a repository tag. """ repo_image = model.image.get_repo_image(namespace, repository, imageid) if repo_image is None: @@ -80,7 +80,7 @@ class RepositoryImageVulnerabilities(RepositoryParamResource): layer_id = '%s.%s' % (repo_image.docker_image_id, repo_image.storage.uuid) data = _call_security_api('layers/%s/vulnerabilities', layer_id, - minimumPriority=args.minimumPriority) + minimumPriority=parsed_args.minimumPriority) return { 'status': _get_status(repo_image), diff --git a/endpoints/api/superuser.py b/endpoints/api/superuser.py index 71b154910..3279c9e9f 100644 --- a/endpoints/api/superuser.py +++ b/endpoints/api/superuser.py @@ -91,14 +91,14 @@ class SuperUserAggregateLogs(ApiResource): @require_fresh_login @verify_not_prod @nickname('listAllAggregateLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs. (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs. (%m/%d/%Y %Z)', type=str) - def get(self, args): + def get(self, parsed_args): """ Returns the aggregated logs for the current system. """ if SuperUserPermission().can(): - start_time = args['starttime'] - end_time = args['endtime'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] return get_aggregate_logs(start_time, end_time) @@ -113,17 +113,17 @@ class SuperUserLogs(ApiResource): @require_fresh_login @verify_not_prod @nickname('listAllLogs') - @parse_args + @parse_args() @query_param('starttime', 'Earliest time from which to get logs (%m/%d/%Y %Z)', type=str) @query_param('endtime', 'Latest time to which to get logs (%m/%d/%Y %Z)', type=str) @query_param('page', 'The page number for the logs', type=int, default=1) - @page_support + @page_support() @require_scope(scopes.SUPERUSER) - def get(self, args, page_token): + def get(self, parsed_args, page_token): """ List the usage logs for the current system. """ if SuperUserPermission().can(): - start_time = args['starttime'] - end_time = args['endtime'] + start_time = parsed_args['starttime'] + end_time = parsed_args['endtime'] return get_logs(start_time, end_time, page_token=page_token) diff --git a/endpoints/api/tag.py b/endpoints/api/tag.py index 2de6b90ee..fc34c0b8c 100644 --- a/endpoints/api/tag.py +++ b/endpoints/api/tag.py @@ -17,12 +17,12 @@ class ListRepositoryTags(RepositoryParamResource): """ Resource for listing full repository tag history, alive *and dead*. """ @require_repo_read - @parse_args + @parse_args() @query_param('specificTag', 'Filters the tags to the specific tag.', type=str, default='') @query_param('limit', 'Limit to the number of results to return per page. Max 100.', type=int, default=50) @query_param('page', 'Page index for the results. Default 1.', type=int, default=1) @nickname('listRepoTags') - def get(self, args, namespace, repository): + def get(self, namespace, repository, parsed_args): repo = model.repository.get_repository(namespace, repository) if not repo: raise NotFound() @@ -42,10 +42,10 @@ class ListRepositoryTags(RepositoryParamResource): return tag_info - specific_tag = args.get('specificTag') or None + specific_tag = parsed_args.get('specificTag') or None - page = max(1, args.get('page', 1)) - limit = min(100, max(1, args.get('limit', 50))) + page = max(1, parsed_args.get('page', 1)) + limit = min(100, max(1, parsed_args.get('limit', 50))) # Note: We ask for limit+1 here, so we can check to see if there are # additional pages of results. @@ -135,10 +135,10 @@ class RepositoryTagImages(RepositoryParamResource): """ Resource for listing the images in a specific repository tag. """ @require_repo_read @nickname('listTagImages') - @parse_args + @parse_args() @query_param('owned', 'If specified, only images wholely owned by this tag are returned.', type=truthy_bool, default=False) - def get(self, args, namespace, repository, tag): + def get(self, namespace, repository, tag, parsed_args): """ List the images for the specified repository tag. """ try: tag_image = model.tag.get_tag_image(namespace, repository, tag) @@ -158,7 +158,7 @@ class RepositoryTagImages(RepositoryParamResource): # Filter the images returned to those not found in the ancestry of any of the other tags in # the repository. - if args['owned']: + if parsed_args['owned']: all_tags = model.tag.list_repository_tags(namespace, repository) for current_tag in all_tags: if current_tag.name == tag: @@ -174,7 +174,7 @@ class RepositoryTagImages(RepositoryParamResource): return { 'images': [image_view(image, image_map_all) for image in all_images - if not args['owned'] or (str(image.id) in image_map)] + if not parsed_args['owned'] or (str(image.id) in image_map)] } diff --git a/endpoints/api/team.py b/endpoints/api/team.py index 87965fdb7..3cff62660 100644 --- a/endpoints/api/team.py +++ b/endpoints/api/team.py @@ -175,11 +175,11 @@ class OrganizationTeam(ApiResource): class TeamMemberList(ApiResource): """ Resource for managing the list of members for a team. """ @require_scope(scopes.ORG_ADMIN) - @parse_args + @parse_args() @query_param('includePending', 'Whether to include pending members', type=truthy_bool, default=False) @nickname('getOrganizationTeamMembers') - def get(self, args, orgname, teamname): + def get(self, orgname, teamname, parsed_args): """ Retrieve the list of members for the specified team. """ view_permission = ViewTeamPermission(orgname, teamname) edit_permission = AdministerOrganizationPermission(orgname) @@ -194,7 +194,7 @@ class TeamMemberList(ApiResource): members = model.organization.get_organization_team_members(team.id) invites = [] - if args['includePending'] and edit_permission.can(): + if parsed_args['includePending'] and edit_permission.can(): invites = model.team.get_organization_team_member_invites(team.id) data = { diff --git a/endpoints/api/trigger.py b/endpoints/api/trigger.py index 66ca30a76..b986c591b 100644 --- a/endpoints/api/trigger.py +++ b/endpoints/api/trigger.py @@ -450,12 +450,12 @@ class ActivateBuildTrigger(RepositoryParamResource): class TriggerBuildList(RepositoryParamResource): """ Resource to represent builds that were activated from the specified trigger. """ @require_repo_admin - @parse_args + @parse_args() @query_param('limit', 'The maximum number of builds to return', type=int, default=5) @nickname('listTriggerRecentBuilds') - def get(self, args, namespace, repository, trigger_uuid): + def get(self, namespace, repository, trigger_uuid, parsed_args): """ List the builds started by the specified trigger. """ - limit = args['limit'] + limit = parsed_args['limit'] builds = model.build.list_trigger_builds(namespace, repository, trigger_uuid, limit) return { 'builds': [build_status_view(bld) for bld in builds] diff --git a/endpoints/api/user.py b/endpoints/api/user.py index 0c4868b39..eb9e0f663 100644 --- a/endpoints/api/user.py +++ b/endpoints/api/user.py @@ -691,13 +691,13 @@ class Recovery(ApiResource): @internal_only class UserNotificationList(ApiResource): @require_user_admin - @parse_args + @parse_args() @query_param('page', 'Offset page number. (int)', type=int, default=0) @query_param('limit', 'Limit on the number of results (int)', type=int, default=5) @nickname('listUserNotifications') - def get(self, args): - page = args['page'] - limit = args['limit'] + def get(self, parsed_args): + page = parsed_args['page'] + limit = parsed_args['limit'] notifications = list(model.notification.list_notifications(get_authenticated_user(), page=page, limit=limit + 1)) @@ -832,14 +832,14 @@ class StarredRepositoryList(ApiResource): } @nickname('listStarredRepos') - @parse_args + @parse_args() @query_param('page', 'Offset page number. (int)', type=int) @query_param('limit', 'Limit on the number of results (int)', type=int) @require_user_admin - def get(self, args): + def get(self, parsed_args): """ List all starred repositories. """ - page = args['page'] - limit = args['limit'] + page = parsed_args['page'] + limit = parsed_args['limit'] starred_repos = model.repository.get_user_starred_repositories(get_authenticated_user(), page=page, limit=limit) def repo_view(repo_obj):