From 56685268c664d3fae615e2753cd0e0c1f40c480c Mon Sep 17 00:00:00 2001
From: Karsten Hopp <karsten@redhat.com>
Date: Aug 17 2018 09:52:11 +0000
Subject: [PATCH 1/2] paginate /api/0/<repo>/pull-requests


Fixes part of https://pagure.io/pagure/issue/3403

Signed-off-by: Karsten Hopp <karsten@redhat.com>

---

diff --git a/pagure/api/fork.py b/pagure/api/fork.py
index ad28e5a..42b8678 100644
--- a/pagure/api/fork.py
+++ b/pagure/api/fork.py
@@ -22,7 +22,8 @@ import pagure.exceptions
 import pagure.lib
 import pagure.lib.tasks
 from pagure.api import (API, api_method, api_login_required, APIERROR,
-                        get_authorized_api_project, get_request_data)
+                        get_authorized_api_project, get_request_data,
+                        get_page, get_per_page)
 from pagure.config import config as pagure_config
 from pagure.utils import authenticated, is_repo_committer, is_true, \
     api_authenticated
@@ -175,18 +176,33 @@ def api_pull_request_views(repo, username=None, namespace=None):
             author=author,
             status=status)
 
-    jsonout = flask.jsonify({
+    page = get_page()
+    per_page = get_per_page()
+
+    pagination_metadata = pagure.lib.get_pagination_metadata(
+        flask.request, page, per_page, len(requests))
+    start = (page - 1) * per_page
+    if start + per_page > len(requests):
+        requests_page = requests[start:]
+    else:
+        requests_page = requests[start:(start + per_page)]
+
+    jsonout = {
         'total_requests': len(requests),
         'requests': [
             request.to_json(public=True, api=True)
-            for request in requests],
+            for request in requests_page],
         'args': {
             'status': status,
             'assignee': assignee,
             'author': author,
         }
-    })
-    return jsonout
+    }
+    if pagination_metadata:
+        jsonout['args']['page'] = page
+        jsonout['args']['per_page'] = per_page
+        jsonout['pagination'] = pagination_metadata
+    return flask.jsonify(jsonout)
 
 
 @API.route('/<repo>/pull-request/<int:requestid>')
diff --git a/tests/test_pagure_flask_api_fork.py b/tests/test_pagure_flask_api_fork.py
index ac1f827..1ac0be6 100644
--- a/tests/test_pagure_flask_api_fork.py
+++ b/tests/test_pagure_flask_api_fork.py
@@ -116,10 +116,28 @@ class PagureFlaskApiForktests(tests.Modeltests):
         output = self.app.get('/api/0/test/pull-requests?status=closed')
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.get_data(as_text=True))
+        for k in ['first', 'last']:
+            self.assertIsNotNone(data['pagination'][k])
+            data['pagination'][k] = 'http://localhost...'
         self.assertDictEqual(
             data,
             {
-                u'args': {u'assignee': None, u'author': None, u'status': u'closed'},
+                u'args': {
+                    u'assignee': None,
+                    u'author': None,
+                    u'page': 1,
+                    u'per_page': 20,
+                    u'status': u'closed'
+                },
+                u'pagination': {
+                    u'first': u'http://localhost...',
+                    u'last': u'http://localhost...',
+                    u'next': None,
+                    u'page': 1,
+                    u'pages': 0,
+                    u'per_page': 20,
+                    u'prev': None
+                },
                 u'requests': [],
                 u'total_requests': 0
             }
@@ -134,10 +152,16 @@ class PagureFlaskApiForktests(tests.Modeltests):
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.get_data(as_text=True))
         self.assertEqual(
-            sorted(data.keys()), ['args', 'requests', 'total_requests'])
+            sorted(data.keys()), ['args', 'pagination', 'requests', 'total_requests'])
         self.assertDictEqual(
             data['args'],
-            {u'assignee': None, u'author': None, u'status': u'closed'}
+            {
+                u'assignee': None,
+                u'author': None,
+                u'page': 1,
+                u'per_page': 20,
+                u'status': u'closed'
+            }
         )
         self.assertEqual(data['total_requests'], 1)
 
@@ -172,10 +196,16 @@ class PagureFlaskApiForktests(tests.Modeltests):
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.get_data(as_text=True))
         self.assertEqual(
-            sorted(data.keys()), ['args', 'requests', 'total_requests'])
+            sorted(data.keys()), ['args', 'pagination', 'requests', 'total_requests'])
         self.assertDictEqual(
             data['args'],
-            {u'assignee': None, u'author': None, u'status': u'all'}
+            {
+                u'assignee': None,
+                u'author': None,
+                u'page': 1,
+                u'per_page': 20,
+                u'status': u'all'
+            }
         )
         self.assertEqual(data['total_requests'], 1)
 
@@ -188,10 +218,16 @@ class PagureFlaskApiForktests(tests.Modeltests):
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.get_data(as_text=True))
         self.assertEqual(
-            sorted(data.keys()), ['args', 'requests', 'total_requests'])
+            sorted(data.keys()), ['args', 'pagination', 'requests', 'total_requests'])
         self.assertDictEqual(
             data['args'],
-            {u'assignee': None, u'author': None, u'status': u'all'}
+            {
+                u'assignee': None,
+                u'author': None,
+                u'page': 1,
+                u'per_page': 20,
+                u'status': u'all'
+            }
         )
         self.assertEqual(data['total_requests'], 1)
 
@@ -246,12 +282,26 @@ class PagureFlaskApiForktests(tests.Modeltests):
         data['requests'][0]['repo_from']['date_modified'] = '1431414800'
         data['requests'][0]['uid'] = '1431414800'
         data['requests'][0]['last_updated'] = '1431414800'
+        for k in ['first', 'last']:
+            self.assertIsNotNone(data['pagination'][k])
+            data['pagination'][k] = 'http://localhost...'
         expected_data = {
             "args": {
                 "assignee": None,
                 "author": None,
+                "page": 1,
+                "per_page": 20,
                 "status": True
             },
+            'pagination': {
+              "first": 'http://localhost...',
+              "last": 'http://localhost...',
+              "next": None,
+              "page": 1,
+              "pages": 1,
+              "per_page": 20,
+              "prev": None
+            },
             "requests": [{
                 "assignee": None,
                 "branch": "master",
diff --git a/tests/test_pagure_flask_api_ui_private_repo.py b/tests/test_pagure_flask_api_ui_private_repo.py
index 3486d7e..8e84ebb 100644
--- a/tests/test_pagure_flask_api_ui_private_repo.py
+++ b/tests/test_pagure_flask_api_ui_private_repo.py
@@ -1377,14 +1377,28 @@ class PagurePrivateRepotest(tests.Modeltests):
             data['requests'][0]['repo_from']['date_modified'] = '1431414800'
             data['requests'][0]['uid'] = '1431414800'
             data['requests'][0]['last_updated'] = '1431414800'
+            for k in ['first', 'last']:
+                self.assertIsNotNone(data['pagination'][k])
+                data['pagination'][k] = 'http://localhost...'
             self.assertDictEqual(
                 data,
                 {
                     "args": {
                         "assignee": None,
                         "author": None,
+                        "page": 1,
+                        "per_page": 20,
                         "status": True
                     },
+                    "pagination": {
+                        "first": 'http://localhost...',
+                        "last": 'http://localhost...',
+                        "next": None,
+                        "page": 1,
+                        "pages": 1,
+                        "per_page": 20,
+                        "prev": None
+                    },
                     "requests": [
                         {
                             "assignee": None,

From dd03b171f7c3c151e40bea159eac92bf04fb815f Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Aug 17 2018 14:46:37 +0000
Subject: [PATCH 2/2] Fix the unit-tests


Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>

---

diff --git a/tests/test_pagure_flask_api_fork.py b/tests/test_pagure_flask_api_fork.py
index 1ac0be6..524b6b5 100644
--- a/tests/test_pagure_flask_api_fork.py
+++ b/tests/test_pagure_flask_api_fork.py
@@ -152,7 +152,8 @@ class PagureFlaskApiForktests(tests.Modeltests):
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.get_data(as_text=True))
         self.assertEqual(
-            sorted(data.keys()), ['args', 'pagination', 'requests', 'total_requests'])
+            sorted(data.keys()),
+            ['args', 'pagination', 'requests', 'total_requests'])
         self.assertDictEqual(
             data['args'],
             {
@@ -196,7 +197,8 @@ class PagureFlaskApiForktests(tests.Modeltests):
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.get_data(as_text=True))
         self.assertEqual(
-            sorted(data.keys()), ['args', 'pagination', 'requests', 'total_requests'])
+            sorted(data.keys()),
+            ['args', 'pagination', 'requests', 'total_requests'])
         self.assertDictEqual(
             data['args'],
             {
@@ -218,7 +220,8 @@ class PagureFlaskApiForktests(tests.Modeltests):
         self.assertEqual(output.status_code, 200)
         data = json.loads(output.get_data(as_text=True))
         self.assertEqual(
-            sorted(data.keys()), ['args', 'pagination', 'requests', 'total_requests'])
+            sorted(data.keys()),
+            ['args', 'pagination', 'requests', 'total_requests'])
         self.assertDictEqual(
             data['args'],
             {
@@ -415,6 +418,9 @@ class PagureFlaskApiForktests(tests.Modeltests):
         data2['requests'][0]['repo_from']['date_modified'] = '1431414800'
         data2['requests'][0]['uid'] = '1431414800'
         data2['requests'][0]['last_updated'] = '1431414800'
+        for k in ['first', 'last']:
+            self.assertIsNotNone(data['pagination'][k])
+            data2['pagination'][k] = 'http://localhost...'
         self.assertDictEqual(data, data2)
 
     @patch('pagure.lib.notify.send_email')
diff --git a/tests/test_pagure_flask_api_ui_private_repo.py b/tests/test_pagure_flask_api_ui_private_repo.py
index 8e84ebb..18d513d 100644
--- a/tests/test_pagure_flask_api_ui_private_repo.py
+++ b/tests/test_pagure_flask_api_ui_private_repo.py
@@ -1509,6 +1509,10 @@ class PagurePrivateRepotest(tests.Modeltests):
             data2['requests'][0]['repo_from']['date_modified'] = '1431414800'
             data2['requests'][0]['uid'] = '1431414800'
             data2['requests'][0]['last_updated'] = '1431414800'
+            for k in ['first', 'last']:
+                self.assertIsNotNone(data['pagination'][k])
+                data2['pagination'][k] = 'http://localhost...'
+
             self.assertDictEqual(data, data2)
 
             # For single PR
@@ -1613,7 +1617,7 @@ class PagurePrivateRepotest(tests.Modeltests):
                     "user": {
                         "fullname": "PY C",
                         "name": "pingou"
-                    }
+                    },
                 }
 
             )

