We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
KeyError while trying to fetch an unbounded PaginatedList's count 
Accessing the `totalCount` attribute on a `PaginatedList` returned from the `get_repos` method throws a KeyError

Trace
```py
repos = github_client.get_repos()

repos.totalCount
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-42-68d28c2d7948> in <module>
----> 1 repos.totalCount

e:\software\python36\lib\site-packages\github\PaginatedList.py in totalCount(self)
    164                 links = self.__parseLinkHeader(headers)
    165                 lastUrl = links.get("last")
--> 166                 self.__totalCount = int(parse_qs(lastUrl)["page"][0])
    167         return self.__totalCount
    168 

KeyError: 'page'
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `github/PaginatedList.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 ############################ Copyrights and license ############################
4 #                                                                              #
5 # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net>                 #
6 # Copyright 2012 Zearin <zearin@gonk.net>                                      #
7 # Copyright 2013 AKFish <akfish@gmail.com>                                     #
8 # Copyright 2013 Bill Mill <bill.mill@gmail.com>                               #
9 # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net>                 #
10 # Copyright 2013 davidbrai <davidbrai@gmail.com>                               #
11 # Copyright 2014 Thialfihar <thi@thialfihar.org>                               #
12 # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net>                 #
13 # Copyright 2015 Dan Vanderkam <danvdk@gmail.com>                              #
14 # Copyright 2015 Eliot Walker <eliot@lyft.com>                                 #
15 # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com>          #
16 # Copyright 2017 Jannis Gebauer <ja.geb@me.com>                                #
17 # Copyright 2018 Gilad Shefer <gshefer@redhat.com>                             #
18 # Copyright 2018 Joel Koglin <JoelKoglin@gmail.com>                            #
19 # Copyright 2018 Wan Liuyang <tsfdye@gmail.com>                                #
20 # Copyright 2018 sfdye <tsfdye@gmail.com>                                      #
21 #                                                                              #
22 # This file is part of PyGithub.                                               #
23 # http://pygithub.readthedocs.io/                                              #
24 #                                                                              #
25 # PyGithub is free software: you can redistribute it and/or modify it under    #
26 # the terms of the GNU Lesser General Public License as published by the Free  #
27 # Software Foundation, either version 3 of the License, or (at your option)    #
28 # any later version.                                                           #
29 #                                                                              #
30 # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #
31 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #
32 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
33 # details.                                                                     #
34 #                                                                              #
35 # You should have received a copy of the GNU Lesser General Public License     #
36 # along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #
37 #                                                                              #
38 ################################################################################
39 
40 from urllib.parse import parse_qs
41 
42 
43 class PaginatedListBase:
44     def __init__(self):
45         self.__elements = list()
46 
47     def __getitem__(self, index):
48         assert isinstance(index, (int, slice))
49         if isinstance(index, int):
50             self.__fetchToIndex(index)
51             return self.__elements[index]
52         else:
53             return self._Slice(self, index)
54 
55     def __iter__(self):
56         for element in self.__elements:
57             yield element
58         while self._couldGrow():
59             newElements = self._grow()
60             for element in newElements:
61                 yield element
62 
63     def _isBiggerThan(self, index):
64         return len(self.__elements) > index or self._couldGrow()
65 
66     def __fetchToIndex(self, index):
67         while len(self.__elements) <= index and self._couldGrow():
68             self._grow()
69 
70     def _grow(self):
71         newElements = self._fetchNextPage()
72         self.__elements += newElements
73         return newElements
74 
75     class _Slice:
76         def __init__(self, theList, theSlice):
77             self.__list = theList
78             self.__start = theSlice.start or 0
79             self.__stop = theSlice.stop
80             self.__step = theSlice.step or 1
81 
82         def __iter__(self):
83             index = self.__start
84             while not self.__finished(index):
85                 if self.__list._isBiggerThan(index):
86                     yield self.__list[index]
87                     index += self.__step
88                 else:
89                     return
90 
91         def __finished(self, index):
92             return self.__stop is not None and index >= self.__stop
93 
94 
95 class PaginatedList(PaginatedListBase):
96     """
97     This class abstracts the `pagination of the API <http://developer.github.com/v3/#pagination>`_.
98 
99     You can simply enumerate through instances of this class::
100 
101         for repo in user.get_repos():
102             print(repo.name)
103 
104     If you want to know the total number of items in the list::
105 
106         print(user.get_repos().totalCount)
107 
108     You can also index them or take slices::
109 
110         second_repo = user.get_repos()[1]
111         first_repos = user.get_repos()[:10]
112 
113     If you want to iterate in reversed order, just do::
114 
115         for repo in user.get_repos().reversed:
116             print(repo.name)
117 
118     And if you really need it, you can explicitly access a specific page::
119 
120         some_repos = user.get_repos().get_page(0)
121         some_other_repos = user.get_repos().get_page(3)
122     """
123 
124     def __init__(
125         self,
126         contentClass,
127         requester,
128         firstUrl,
129         firstParams,
130         headers=None,
131         list_item="items",
132     ):
133         super().__init__()
134         self.__requester = requester
135         self.__contentClass = contentClass
136         self.__firstUrl = firstUrl
137         self.__firstParams = firstParams or ()
138         self.__nextUrl = firstUrl
139         self.__nextParams = firstParams or {}
140         self.__headers = headers
141         self.__list_item = list_item
142         if self.__requester.per_page != 30:
143             self.__nextParams["per_page"] = self.__requester.per_page
144         self._reversed = False
145         self.__totalCount = None
146 
147     @property
148     def totalCount(self):
149         if not self.__totalCount:
150             params = {} if self.__nextParams is None else self.__nextParams.copy()
151             # set per_page = 1 so the totalCount is just the number of pages
152             params.update({"per_page": 1})
153             headers, data = self.__requester.requestJsonAndCheck(
154                 "GET", self.__firstUrl, parameters=params, headers=self.__headers
155             )
156             if "link" not in headers:
157                 if data and "total_count" in data:
158                     self.__totalCount = data["total_count"]
159                 elif data:
160                     self.__totalCount = len(data)
161                 else:
162                     self.__totalCount = 0
163             else:
164                 links = self.__parseLinkHeader(headers)
165                 lastUrl = links.get("last")
166                 self.__totalCount = int(parse_qs(lastUrl)["page"][0])
167         return self.__totalCount
168 
169     def _getLastPageUrl(self):
170         headers, data = self.__requester.requestJsonAndCheck(
171             "GET", self.__firstUrl, parameters=self.__nextParams, headers=self.__headers
172         )
173         links = self.__parseLinkHeader(headers)
174         lastUrl = links.get("last")
175         return lastUrl
176 
177     @property
178     def reversed(self):
179         r = PaginatedList(
180             self.__contentClass,
181             self.__requester,
182             self.__firstUrl,
183             self.__firstParams,
184             self.__headers,
185             self.__list_item,
186         )
187         r.__reverse()
188         return r
189 
190     def __reverse(self):
191         self._reversed = True
192         lastUrl = self._getLastPageUrl()
193         if lastUrl:
194             self.__nextUrl = lastUrl
195 
196     def _couldGrow(self):
197         return self.__nextUrl is not None
198 
199     def _fetchNextPage(self):
200         headers, data = self.__requester.requestJsonAndCheck(
201             "GET", self.__nextUrl, parameters=self.__nextParams, headers=self.__headers
202         )
203         data = data if data else []
204 
205         self.__nextUrl = None
206         if len(data) > 0:
207             links = self.__parseLinkHeader(headers)
208             if self._reversed:
209                 if "prev" in links:
210                     self.__nextUrl = links["prev"]
211             elif "next" in links:
212                 self.__nextUrl = links["next"]
213         self.__nextParams = None
214 
215         if self.__list_item in data:
216             self.__totalCount = data.get("total_count")
217             data = data[self.__list_item]
218 
219         content = [
220             self.__contentClass(self.__requester, headers, element, completed=False)
221             for element in data
222             if element is not None
223         ]
224         if self._reversed:
225             return content[::-1]
226         return content
227 
228     def __parseLinkHeader(self, headers):
229         links = {}
230         if "link" in headers:
231             linkHeaders = headers["link"].split(", ")
232             for linkHeader in linkHeaders:
233                 url, rel, *rest = linkHeader.split("; ")
234                 url = url[1:-1]
235                 rel = rel[5:-1]
236                 links[rel] = url
237         return links
238 
239     def get_page(self, page):
240         params = dict(self.__firstParams)
241         if page != 0:
242             params["page"] = page + 1
243         if self.__requester.per_page != 30:
244             params["per_page"] = self.__requester.per_page
245         headers, data = self.__requester.requestJsonAndCheck(
246             "GET", self.__firstUrl, parameters=params, headers=self.__headers
247         )
248 
249         if self.__list_item in data:
250             self.__totalCount = data.get("total_count")
251             data = data[self.__list_item]
252 
253         return [
254             self.__contentClass(self.__requester, headers, element, completed=False)
255             for element in data
256         ]
257
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/github/PaginatedList.py b/github/PaginatedList.py
--- a/github/PaginatedList.py
+++ b/github/PaginatedList.py
@@ -163,7 +163,10 @@
             else:
                 links = self.__parseLinkHeader(headers)
                 lastUrl = links.get("last")
-                self.__totalCount = int(parse_qs(lastUrl)["page"][0])
+                if lastUrl:
+                    self.__totalCount = int(parse_qs(lastUrl)["page"][0])
+                else:
+                    self.__totalCount = 0
         return self.__totalCount
 
     def _getLastPageUrl(self):

{"golden_diff": "diff --git a/github/PaginatedList.py b/github/PaginatedList.py\n--- a/github/PaginatedList.py\n+++ b/github/PaginatedList.py\n@@ -163,7 +163,10 @@\n             else:\n                 links = self.__parseLinkHeader(headers)\n                 lastUrl = links.get(\"last\")\n-                self.__totalCount = int(parse_qs(lastUrl)[\"page\"][0])\n+                if lastUrl:\n+                    self.__totalCount = int(parse_qs(lastUrl)[\"page\"][0])\n+                else:\n+                    self.__totalCount = 0\n         return self.__totalCount\n \n     def _getLastPageUrl(self):\n", "issue": "KeyError while trying to fetch an unbounded PaginatedList's count \nAccessing the `totalCount` attribute on a `PaginatedList` returned from the `get_repos` method throws a KeyError\r\n\r\nTrace\r\n```py\r\nrepos = github_client.get_repos()\r\n\r\nrepos.totalCount\r\n---------------------------------------------------------------------------\r\nKeyError                                  Traceback (most recent call last)\r\n<ipython-input-42-68d28c2d7948> in <module>\r\n----> 1 repos.totalCount\r\n\r\ne:\\software\\python36\\lib\\site-packages\\github\\PaginatedList.py in totalCount(self)\r\n    164                 links = self.__parseLinkHeader(headers)\r\n    165                 lastUrl = links.get(\"last\")\r\n--> 166                 self.__totalCount = int(parse_qs(lastUrl)[\"page\"][0])\r\n    167         return self.__totalCount\r\n    168 \r\n\r\nKeyError: 'page'\r\n```\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n############################ Copyrights and license ############################\n#                                                                              #\n# Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net>                 #\n# Copyright 2012 Zearin <zearin@gonk.net>                                      #\n# Copyright 2013 AKFish <akfish@gmail.com>                                     #\n# Copyright 2013 Bill Mill <bill.mill@gmail.com>                               #\n# Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net>                 #\n# Copyright 2013 davidbrai <davidbrai@gmail.com>                               #\n# Copyright 2014 Thialfihar <thi@thialfihar.org>                               #\n# Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net>                 #\n# Copyright 2015 Dan Vanderkam <danvdk@gmail.com>                              #\n# Copyright 2015 Eliot Walker <eliot@lyft.com>                                 #\n# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com>          #\n# Copyright 2017 Jannis Gebauer <ja.geb@me.com>                                #\n# Copyright 2018 Gilad Shefer <gshefer@redhat.com>                             #\n# Copyright 2018 Joel Koglin <JoelKoglin@gmail.com>                            #\n# Copyright 2018 Wan Liuyang <tsfdye@gmail.com>                                #\n# Copyright 2018 sfdye <tsfdye@gmail.com>                                      #\n#                                                                              #\n# This file is part of PyGithub.                                               #\n# http://pygithub.readthedocs.io/                                              #\n#                                                                              #\n# PyGithub is free software: you can redistribute it and/or modify it under    #\n# the terms of the GNU Lesser General Public License as published by the Free  #\n# Software Foundation, either version 3 of the License, or (at your option)    #\n# any later version.                                                           #\n#                                                                              #\n# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #\n# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #\n# details.                                                                     #\n#                                                                              #\n# You should have received a copy of the GNU Lesser General Public License     #\n# along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #\n#                                                                              #\n################################################################################\n\nfrom urllib.parse import parse_qs\n\n\nclass PaginatedListBase:\n    def __init__(self):\n        self.__elements = list()\n\n    def __getitem__(self, index):\n        assert isinstance(index, (int, slice))\n        if isinstance(index, int):\n            self.__fetchToIndex(index)\n            return self.__elements[index]\n        else:\n            return self._Slice(self, index)\n\n    def __iter__(self):\n        for element in self.__elements:\n            yield element\n        while self._couldGrow():\n            newElements = self._grow()\n            for element in newElements:\n                yield element\n\n    def _isBiggerThan(self, index):\n        return len(self.__elements) > index or self._couldGrow()\n\n    def __fetchToIndex(self, index):\n        while len(self.__elements) <= index and self._couldGrow():\n            self._grow()\n\n    def _grow(self):\n        newElements = self._fetchNextPage()\n        self.__elements += newElements\n        return newElements\n\n    class _Slice:\n        def __init__(self, theList, theSlice):\n            self.__list = theList\n            self.__start = theSlice.start or 0\n            self.__stop = theSlice.stop\n            self.__step = theSlice.step or 1\n\n        def __iter__(self):\n            index = self.__start\n            while not self.__finished(index):\n                if self.__list._isBiggerThan(index):\n                    yield self.__list[index]\n                    index += self.__step\n                else:\n                    return\n\n        def __finished(self, index):\n            return self.__stop is not None and index >= self.__stop\n\n\nclass PaginatedList(PaginatedListBase):\n    \"\"\"\n    This class abstracts the `pagination of the API <http://developer.github.com/v3/#pagination>`_.\n\n    You can simply enumerate through instances of this class::\n\n        for repo in user.get_repos():\n            print(repo.name)\n\n    If you want to know the total number of items in the list::\n\n        print(user.get_repos().totalCount)\n\n    You can also index them or take slices::\n\n        second_repo = user.get_repos()[1]\n        first_repos = user.get_repos()[:10]\n\n    If you want to iterate in reversed order, just do::\n\n        for repo in user.get_repos().reversed:\n            print(repo.name)\n\n    And if you really need it, you can explicitly access a specific page::\n\n        some_repos = user.get_repos().get_page(0)\n        some_other_repos = user.get_repos().get_page(3)\n    \"\"\"\n\n    def __init__(\n        self,\n        contentClass,\n        requester,\n        firstUrl,\n        firstParams,\n        headers=None,\n        list_item=\"items\",\n    ):\n        super().__init__()\n        self.__requester = requester\n        self.__contentClass = contentClass\n        self.__firstUrl = firstUrl\n        self.__firstParams = firstParams or ()\n        self.__nextUrl = firstUrl\n        self.__nextParams = firstParams or {}\n        self.__headers = headers\n        self.__list_item = list_item\n        if self.__requester.per_page != 30:\n            self.__nextParams[\"per_page\"] = self.__requester.per_page\n        self._reversed = False\n        self.__totalCount = None\n\n    @property\n    def totalCount(self):\n        if not self.__totalCount:\n            params = {} if self.__nextParams is None else self.__nextParams.copy()\n            # set per_page = 1 so the totalCount is just the number of pages\n            params.update({\"per_page\": 1})\n            headers, data = self.__requester.requestJsonAndCheck(\n                \"GET\", self.__firstUrl, parameters=params, headers=self.__headers\n            )\n            if \"link\" not in headers:\n                if data and \"total_count\" in data:\n                    self.__totalCount = data[\"total_count\"]\n                elif data:\n                    self.__totalCount = len(data)\n                else:\n                    self.__totalCount = 0\n            else:\n                links = self.__parseLinkHeader(headers)\n                lastUrl = links.get(\"last\")\n                self.__totalCount = int(parse_qs(lastUrl)[\"page\"][0])\n        return self.__totalCount\n\n    def _getLastPageUrl(self):\n        headers, data = self.__requester.requestJsonAndCheck(\n            \"GET\", self.__firstUrl, parameters=self.__nextParams, headers=self.__headers\n        )\n        links = self.__parseLinkHeader(headers)\n        lastUrl = links.get(\"last\")\n        return lastUrl\n\n    @property\n    def reversed(self):\n        r = PaginatedList(\n            self.__contentClass,\n            self.__requester,\n            self.__firstUrl,\n            self.__firstParams,\n            self.__headers,\n            self.__list_item,\n        )\n        r.__reverse()\n        return r\n\n    def __reverse(self):\n        self._reversed = True\n        lastUrl = self._getLastPageUrl()\n        if lastUrl:\n            self.__nextUrl = lastUrl\n\n    def _couldGrow(self):\n        return self.__nextUrl is not None\n\n    def _fetchNextPage(self):\n        headers, data = self.__requester.requestJsonAndCheck(\n            \"GET\", self.__nextUrl, parameters=self.__nextParams, headers=self.__headers\n        )\n        data = data if data else []\n\n        self.__nextUrl = None\n        if len(data) > 0:\n            links = self.__parseLinkHeader(headers)\n            if self._reversed:\n                if \"prev\" in links:\n                    self.__nextUrl = links[\"prev\"]\n            elif \"next\" in links:\n                self.__nextUrl = links[\"next\"]\n        self.__nextParams = None\n\n        if self.__list_item in data:\n            self.__totalCount = data.get(\"total_count\")\n            data = data[self.__list_item]\n\n        content = [\n            self.__contentClass(self.__requester, headers, element, completed=False)\n            for element in data\n            if element is not None\n        ]\n        if self._reversed:\n            return content[::-1]\n        return content\n\n    def __parseLinkHeader(self, headers):\n        links = {}\n        if \"link\" in headers:\n            linkHeaders = headers[\"link\"].split(\", \")\n            for linkHeader in linkHeaders:\n                url, rel, *rest = linkHeader.split(\"; \")\n                url = url[1:-1]\n                rel = rel[5:-1]\n                links[rel] = url\n        return links\n\n    def get_page(self, page):\n        params = dict(self.__firstParams)\n        if page != 0:\n            params[\"page\"] = page + 1\n        if self.__requester.per_page != 30:\n            params[\"per_page\"] = self.__requester.per_page\n        headers, data = self.__requester.requestJsonAndCheck(\n            \"GET\", self.__firstUrl, parameters=params, headers=self.__headers\n        )\n\n        if self.__list_item in data:\n            self.__totalCount = data.get(\"total_count\")\n            data = data[self.__list_item]\n\n        return [\n            self.__contentClass(self.__requester, headers, element, completed=False)\n            for element in data\n        ]\n", "path": "github/PaginatedList.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n############################ Copyrights and license ############################\n#                                                                              #\n# Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net>                 #\n# Copyright 2012 Zearin <zearin@gonk.net>                                      #\n# Copyright 2013 AKFish <akfish@gmail.com>                                     #\n# Copyright 2013 Bill Mill <bill.mill@gmail.com>                               #\n# Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net>                 #\n# Copyright 2013 davidbrai <davidbrai@gmail.com>                               #\n# Copyright 2014 Thialfihar <thi@thialfihar.org>                               #\n# Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net>                 #\n# Copyright 2015 Dan Vanderkam <danvdk@gmail.com>                              #\n# Copyright 2015 Eliot Walker <eliot@lyft.com>                                 #\n# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com>          #\n# Copyright 2017 Jannis Gebauer <ja.geb@me.com>                                #\n# Copyright 2018 Gilad Shefer <gshefer@redhat.com>                             #\n# Copyright 2018 Joel Koglin <JoelKoglin@gmail.com>                            #\n# Copyright 2018 Wan Liuyang <tsfdye@gmail.com>                                #\n# Copyright 2018 sfdye <tsfdye@gmail.com>                                      #\n#                                                                              #\n# This file is part of PyGithub.                                               #\n# http://pygithub.readthedocs.io/                                              #\n#                                                                              #\n# PyGithub is free software: you can redistribute it and/or modify it under    #\n# the terms of the GNU Lesser General Public License as published by the Free  #\n# Software Foundation, either version 3 of the License, or (at your option)    #\n# any later version.                                                           #\n#                                                                              #\n# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #\n# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #\n# details.                                                                     #\n#                                                                              #\n# You should have received a copy of the GNU Lesser General Public License     #\n# along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #\n#                                                                              #\n################################################################################\n\nfrom urllib.parse import parse_qs\n\n\nclass PaginatedListBase:\n    def __init__(self):\n        self.__elements = list()\n\n    def __getitem__(self, index):\n        assert isinstance(index, (int, slice))\n        if isinstance(index, int):\n            self.__fetchToIndex(index)\n            return self.__elements[index]\n        else:\n            return self._Slice(self, index)\n\n    def __iter__(self):\n        for element in self.__elements:\n            yield element\n        while self._couldGrow():\n            newElements = self._grow()\n            for element in newElements:\n                yield element\n\n    def _isBiggerThan(self, index):\n        return len(self.__elements) > index or self._couldGrow()\n\n    def __fetchToIndex(self, index):\n        while len(self.__elements) <= index and self._couldGrow():\n            self._grow()\n\n    def _grow(self):\n        newElements = self._fetchNextPage()\n        self.__elements += newElements\n        return newElements\n\n    class _Slice:\n        def __init__(self, theList, theSlice):\n            self.__list = theList\n            self.__start = theSlice.start or 0\n            self.__stop = theSlice.stop\n            self.__step = theSlice.step or 1\n\n        def __iter__(self):\n            index = self.__start\n            while not self.__finished(index):\n                if self.__list._isBiggerThan(index):\n                    yield self.__list[index]\n                    index += self.__step\n                else:\n                    return\n\n        def __finished(self, index):\n            return self.__stop is not None and index >= self.__stop\n\n\nclass PaginatedList(PaginatedListBase):\n    \"\"\"\n    This class abstracts the `pagination of the API <http://developer.github.com/v3/#pagination>`_.\n\n    You can simply enumerate through instances of this class::\n\n        for repo in user.get_repos():\n            print(repo.name)\n\n    If you want to know the total number of items in the list::\n\n        print(user.get_repos().totalCount)\n\n    You can also index them or take slices::\n\n        second_repo = user.get_repos()[1]\n        first_repos = user.get_repos()[:10]\n\n    If you want to iterate in reversed order, just do::\n\n        for repo in user.get_repos().reversed:\n            print(repo.name)\n\n    And if you really need it, you can explicitly access a specific page::\n\n        some_repos = user.get_repos().get_page(0)\n        some_other_repos = user.get_repos().get_page(3)\n    \"\"\"\n\n    def __init__(\n        self,\n        contentClass,\n        requester,\n        firstUrl,\n        firstParams,\n        headers=None,\n        list_item=\"items\",\n    ):\n        super().__init__()\n        self.__requester = requester\n        self.__contentClass = contentClass\n        self.__firstUrl = firstUrl\n        self.__firstParams = firstParams or ()\n        self.__nextUrl = firstUrl\n        self.__nextParams = firstParams or {}\n        self.__headers = headers\n        self.__list_item = list_item\n        if self.__requester.per_page != 30:\n            self.__nextParams[\"per_page\"] = self.__requester.per_page\n        self._reversed = False\n        self.__totalCount = None\n\n    @property\n    def totalCount(self):\n        if not self.__totalCount:\n            params = {} if self.__nextParams is None else self.__nextParams.copy()\n            # set per_page = 1 so the totalCount is just the number of pages\n            params.update({\"per_page\": 1})\n            headers, data = self.__requester.requestJsonAndCheck(\n                \"GET\", self.__firstUrl, parameters=params, headers=self.__headers\n            )\n            if \"link\" not in headers:\n                if data and \"total_count\" in data:\n                    self.__totalCount = data[\"total_count\"]\n                elif data:\n                    self.__totalCount = len(data)\n                else:\n                    self.__totalCount = 0\n            else:\n                links = self.__parseLinkHeader(headers)\n                lastUrl = links.get(\"last\")\n                if lastUrl:\n                    self.__totalCount = int(parse_qs(lastUrl)[\"page\"][0])\n                else:\n                    self.__totalCount = 0\n        return self.__totalCount\n\n    def _getLastPageUrl(self):\n        headers, data = self.__requester.requestJsonAndCheck(\n            \"GET\", self.__firstUrl, parameters=self.__nextParams, headers=self.__headers\n        )\n        links = self.__parseLinkHeader(headers)\n        lastUrl = links.get(\"last\")\n        return lastUrl\n\n    @property\n    def reversed(self):\n        r = PaginatedList(\n            self.__contentClass,\n            self.__requester,\n            self.__firstUrl,\n            self.__firstParams,\n            self.__headers,\n            self.__list_item,\n        )\n        r.__reverse()\n        return r\n\n    def __reverse(self):\n        self._reversed = True\n        lastUrl = self._getLastPageUrl()\n        if lastUrl:\n            self.__nextUrl = lastUrl\n\n    def _couldGrow(self):\n        return self.__nextUrl is not None\n\n    def _fetchNextPage(self):\n        headers, data = self.__requester.requestJsonAndCheck(\n            \"GET\", self.__nextUrl, parameters=self.__nextParams, headers=self.__headers\n        )\n        data = data if data else []\n\n        self.__nextUrl = None\n        if len(data) > 0:\n            links = self.__parseLinkHeader(headers)\n            if self._reversed:\n                if \"prev\" in links:\n                    self.__nextUrl = links[\"prev\"]\n            elif \"next\" in links:\n                self.__nextUrl = links[\"next\"]\n        self.__nextParams = None\n\n        if self.__list_item in data:\n            self.__totalCount = data.get(\"total_count\")\n            data = data[self.__list_item]\n\n        content = [\n            self.__contentClass(self.__requester, headers, element, completed=False)\n            for element in data\n            if element is not None\n        ]\n        if self._reversed:\n            return content[::-1]\n        return content\n\n    def __parseLinkHeader(self, headers):\n        links = {}\n        if \"link\" in headers:\n            linkHeaders = headers[\"link\"].split(\", \")\n            for linkHeader in linkHeaders:\n                url, rel, *rest = linkHeader.split(\"; \")\n                url = url[1:-1]\n                rel = rel[5:-1]\n                links[rel] = url\n        return links\n\n    def get_page(self, page):\n        params = dict(self.__firstParams)\n        if page != 0:\n            params[\"page\"] = page + 1\n        if self.__requester.per_page != 30:\n            params[\"per_page\"] = self.__requester.per_page\n        headers, data = self.__requester.requestJsonAndCheck(\n            \"GET\", self.__firstUrl, parameters=params, headers=self.__headers\n        )\n\n        if self.__list_item in data:\n            self.__totalCount = data.get(\"total_count\")\n            data = data[self.__list_item]\n\n        return [\n            self.__contentClass(self.__requester, headers, element, completed=False)\n            for element in data\n        ]\n", "path": "github/PaginatedList.py"}]}