diff --git a/pagure/api/issue.py b/pagure/api/issue.py index 577ccef..2386f71 100644 --- a/pagure/api/issue.py +++ b/pagure/api/issue.py @@ -345,6 +345,11 @@ def api_view_issues(repo, username=None, namespace=None): | | | | provided as an unix date| | | | | or in the format Y-M-D | +---------------+---------+--------------+---------------------------+ + | ``order`` | string | Optional | | Set the ordering of the | + | | | | issues. This can be | + | | | | ``asc`` or ``desc``. | + | | | | Default: ``desc`` | + +---------------+---------+--------------+---------------------------+ Sample response ^^^^^^^^^^^^^^^ @@ -357,6 +362,7 @@ def api_view_issues(repo, username=None, namespace=None): "author": null, 'milestones': [], 'no_stones': null, + 'order': null, 'priority': null, "since": null, "status": "Closed", @@ -404,6 +410,7 @@ def api_view_issues(repo, username=None, namespace=None): no_stones = False priority = flask.request.args.get('priority', None) since = flask.request.args.get('since', None) + order = flask.request.args.get('order', None) status = flask.request.args.get('status', None) tags = flask.request.args.getlist('tags') tags = [tag.strip() for tag in tags if tag.strip()] @@ -443,6 +450,7 @@ def api_view_issues(repo, username=None, namespace=None): 'private': private, 'milestones': milestone, 'priority': priority_key, + 'order': order, 'no_milestones': no_stones, } @@ -484,6 +492,7 @@ def api_view_issues(repo, username=None, namespace=None): 'author': author, 'milestones': milestone, 'no_stones': no_stones, + 'order': order, 'priority': priority, 'since': since, 'status': status, diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index 93b7e3b..db46b11 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -2055,7 +2055,7 @@ def search_issues( closed=False, tags=None, assignee=None, author=None, private=None, priority=None, milestones=None, count=False, offset=None, limit=None, search_pattern=None, custom_search=None, - updated_after=None, no_milestones=None): + updated_after=None, no_milestones=None, order='desc'): ''' Retrieve one or more issues associated to a project with the given criterias. @@ -2112,6 +2112,8 @@ def search_issues( :type updated_after: str or None :kwarg no_milestones: Request issues that do not have a milestone set yet :type None, True, or False + :kwarg order: Order issues in 'asc' or 'desc' order. + :type order: None, str :return: A single Issue object if issueid is specified, a list of Project objects otherwise. @@ -2328,9 +2330,14 @@ def search_issues( model.Issue.title.ilike('%' + str(search_pattern) + '%') ) - query = query.order_by( - model.Issue.date_created.desc() - ) + if order == 'asc': + query = query.order_by( + model.Issue.date_created.asc() + ) + else: + query = query.order_by( + model.Issue.date_created.desc() + ) if issueid is not None or issueuid is not None: output = query.first() diff --git a/tests/test_pagure_flask_api_issue.py b/tests/test_pagure_flask_api_issue.py index c7f525a..7750c3a 100644 --- a/tests/test_pagure_flask_api_issue.py +++ b/tests/test_pagure_flask_api_issue.py @@ -286,6 +286,9 @@ LCL_ISSUES = [ class PagureFlaskApiIssuetests(tests.Modeltests): """ Tests for the flask API of pagure for issue """ + + maxDiff = None + def setUp(self): """ Set up the environnment, ran before every tests. """ super(PagureFlaskApiIssuetests, self).setUp() @@ -827,6 +830,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -868,6 +872,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -910,6 +915,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -938,6 +944,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -980,6 +987,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1007,6 +1015,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1031,6 +1040,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, "milestones": [], "no_stones": None, + 'order': None, "priority": None, "since": None, "status": "Closed", @@ -1053,6 +1063,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": "Invalid", @@ -1078,6 +1089,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": "All", @@ -1088,6 +1100,39 @@ class PagureFlaskApiIssuetests(tests.Modeltests): } ) + def test_api_view_issues_reversed(self): + """ Test the api_view_issues method of the flask api. in reversed + order. + + """ + self.test_api_new_issue() + + headers = {'Authorization': 'token aaabbbcccddd'} + + # List issues in reverse order + output = self.app.get('/api/0/test/issues?order=asc', headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + for idx in range(len(data['issues'])): + data['issues'][idx]['last_updated'] = '1431414800' + data['issues'][idx]['date_created'] = '1431414800' + expected = { + "args": { + "assignee": None, + "author": None, + 'milestones': [], + 'no_stones': None, + 'order': 'asc', + 'priority': None, + "since": None, + "status": None, + "tags": [] + }, + "issues": FULL_ISSUE_LIST[1:][::-1], + "total_issues": 8 + } + self.assertDictEqual(data, expected) + def test_api_view_issues_milestone(self): """ Test the api_view_issues method of the flask api when filtering for a milestone. @@ -1144,6 +1189,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1169,6 +1215,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': ['v1.0'], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1240,6 +1287,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1265,6 +1313,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': 'high', "since": None, "status": None, @@ -1289,6 +1338,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': '1', "since": None, "status": None, @@ -1377,6 +1427,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1402,6 +1453,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': True, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1427,6 +1479,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': False, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1521,6 +1574,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": None, "status": None, @@ -1549,6 +1603,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": start, "status": None, @@ -1574,6 +1629,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": middle, "status": None, @@ -1599,6 +1655,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": final, "status": None, @@ -1627,6 +1684,7 @@ class PagureFlaskApiIssuetests(tests.Modeltests): "author": None, 'milestones': [], 'no_stones': None, + 'order': None, 'priority': None, "since": final, "status": None, diff --git a/tests/test_pagure_flask_api_ui_private_repo.py b/tests/test_pagure_flask_api_ui_private_repo.py index c218435..f1eaf59 100644 --- a/tests/test_pagure_flask_api_ui_private_repo.py +++ b/tests/test_pagure_flask_api_ui_private_repo.py @@ -2088,7 +2088,7 @@ class PagurePrivateRepotest(tests.Modeltests): } ) - def test_api_priavte_repo_view_issues(self): + def test_api_private_repo_view_issues(self): """ Test the api_view_issues method of the flask api. """ self.test_api_private_repo_new_issue() @@ -2120,6 +2120,7 @@ class PagurePrivateRepotest(tests.Modeltests): "author": None, "milestones": [], "no_stones": None, + "order": None, "priority": None, "since": None, "status": None, @@ -2188,6 +2189,7 @@ class PagurePrivateRepotest(tests.Modeltests): "author": None, "milestones": [], "no_stones": None, + "order": None, "priority": None, "status": None, "since": None, @@ -2269,6 +2271,7 @@ class PagurePrivateRepotest(tests.Modeltests): "author": None, "milestones": [], "no_stones": None, + "order": None, "priority": None, "status": None, "since": None, @@ -2340,6 +2343,7 @@ class PagurePrivateRepotest(tests.Modeltests): "author": None, "milestones": [], "no_stones": None, + "order": None, "priority": None, "status": "Closed", "since": None, @@ -2363,6 +2367,7 @@ class PagurePrivateRepotest(tests.Modeltests): "author": None, "milestones": [], "no_stones": None, + "order": None, "priority": None, "status": "Invalid", "since": None, @@ -2390,6 +2395,7 @@ class PagurePrivateRepotest(tests.Modeltests): "author": None, "milestones": [], "no_stones": None, + "order": None, "priority": None, "since": None, "status": "All",