0
# Pagination
1
2
Pagination module providing utilities for handling paginated GitHub API responses and parsing pagination headers efficiently.
3
4
## Capabilities
5
6
### Paginated Operations
7
8
Convert GitHub API operations into iterators for handling large result sets.
9
10
```python { .api }
11
def paged(oper, *args, per_page=30, max_pages=9999, **kwargs):
12
"""
13
Convert API operation into an iterator for pagination.
14
15
Parameters:
16
- oper: callable, GitHub API operation function
17
- *args: positional arguments for the operation
18
- per_page: int, number of items per page (default 30)
19
- max_pages: int, maximum pages to fetch (default 9999)
20
- **kwargs: keyword arguments for the operation
21
22
Yields:
23
API response objects for each page
24
"""
25
26
```
27
28
### Link Header Parsing
29
30
Parse RFC 5988 link headers from GitHub API responses.
31
32
```python { .api }
33
def parse_link_hdr(header):
34
"""
35
Parse RFC 5988 link header from GitHub API response.
36
37
Parameters:
38
- header: str, link header value
39
40
Returns:
41
list: List of tuples containing (url, attributes_dict)
42
"""
43
44
def pages(oper, n_pages, *args, n_workers=None, per_page=100, **kwargs):
45
"""
46
Get multiple pages from an operation in parallel.
47
48
Parameters:
49
- oper: callable, GitHub API operation function
50
- n_pages: int, number of pages to retrieve
51
- *args: positional arguments for the operation
52
- n_workers: int, number of parallel workers (defaults to n_pages)
53
- per_page: int, items per page
54
- **kwargs: keyword arguments for the operation
55
56
Returns:
57
list: List of page results retrieved in parallel
58
"""
59
```
60
61
## Usage Examples
62
63
### Basic Pagination
64
65
```python
66
from ghapi.all import GhApi, paged
67
68
api = GhApi(token='your_token')
69
70
# Paginate through all issues in a repository
71
for page in paged(api.issues.list_for_repo, owner='user', repo='repo', per_page=50):
72
for issue in page:
73
print(f"#{issue.number}: {issue.title}")
74
75
# Limit to first 5 pages
76
for page in paged(api.repos.list_for_user, username='user', per_page=100, max_pages=5):
77
for repo in page:
78
print(f"{repo.full_name}: {repo.stargazers_count} stars")
79
```
80
81
### Repository Pagination
82
83
```python
84
from ghapi.all import GhApi, paged
85
86
api = GhApi(token='your_token')
87
88
# Get all repositories for an organization
89
all_repos = []
90
for page in paged(api.repos.list_for_org, org='organization', per_page=100):
91
all_repos.extend(page)
92
93
print(f"Total repositories: {len(all_repos)}")
94
95
# Process repositories in batches
96
for page in paged(api.repos.list_for_org, org='org', per_page=25):
97
print(f"Processing batch of {len(page)} repositories:")
98
for repo in page:
99
print(f" - {repo.name} ({repo.language})")
100
101
# Get multiple pages in parallel
102
from ghapi.all import pages
103
page_results = pages(api.repos.list_for_org, 5, org='organization', per_page=20)
104
total_repos = sum(len(page) for page in page_results)
105
print(f"Retrieved {total_repos} repositories across 5 pages in parallel")
106
```
107
108
### Issue and Pull Request Pagination
109
110
```python
111
from ghapi.all import GhApi, paged
112
113
api = GhApi(token='your_token', owner='user', repo='repo')
114
115
# Get all open issues
116
open_issues = []
117
for page in paged(api.issues.list_for_repo, state='open', per_page=100):
118
open_issues.extend(page)
119
120
print(f"Open issues: {len(open_issues)}")
121
122
# Get all pull requests with specific label
123
for page in paged(api.pulls.list, state='all', per_page=50):
124
for pr in page:
125
if any(label.name == 'enhancement' for label in pr.labels):
126
print(f"Enhancement PR: #{pr.number} - {pr.title}")
127
128
# Get issue comments across all issues
129
for page in paged(api.issues.list_comments_for_repo, per_page=100):
130
for comment in page:
131
print(f"Comment by {comment.user.login}: {comment.body[:50]}...")
132
```
133
134
### Commit and Event Pagination
135
136
```python
137
from ghapi.all import GhApi, paged
138
139
api = GhApi(token='your_token')
140
141
# Get all commits in repository
142
commit_count = 0
143
for page in paged(api.repos.list_commits, owner='user', repo='repo', per_page=100):
144
commit_count += len(page)
145
for commit in page:
146
print(f"{commit.sha[:8]}: {commit.commit.message.split('\\n')[0]}")
147
148
print(f"Total commits: {commit_count}")
149
150
# Get repository events
151
for page in paged(api.activity.list_repo_events, owner='user', repo='repo', per_page=50):
152
for event in page:
153
print(f"{event.type}: {event.actor.login} at {event.created_at}")
154
```
155
156
### User and Organization Data
157
158
```python
159
from ghapi.all import GhApi, paged
160
161
api = GhApi(token='your_token')
162
163
# Get all followers for a user
164
followers = []
165
for page in paged(api.users.list_followers_for_user, username='user', per_page=100):
166
followers.extend(page)
167
168
print(f"Total followers: {len(followers)}")
169
170
# Get organization members
171
for page in paged(api.orgs.list_members, org='organization', per_page=50):
172
for member in page:
173
print(f"Member: {member.login}")
174
175
# Get user's starred repositories
176
starred_repos = []
177
for page in paged(api.activity.list_repos_starred_by_user, username='user', per_page=100):
178
starred_repos.extend(page)
179
180
print(f"Starred repositories: {len(starred_repos)}")
181
```
182
183
### Advanced Pagination with Filtering
184
185
```python
186
from ghapi.all import GhApi, paged
187
from datetime import datetime, timedelta
188
189
api = GhApi(token='your_token')
190
191
# Get recent issues (last 30 days)
192
thirty_days_ago = datetime.now() - timedelta(days=30)
193
recent_issues = []
194
195
for page in paged(api.issues.list_for_repo,
196
owner='user', repo='repo',
197
state='all',
198
since=thirty_days_ago.isoformat(),
199
per_page=100):
200
recent_issues.extend(page)
201
202
print(f"Issues in last 30 days: {len(recent_issues)}")
203
204
# Get pull requests by author
205
author_prs = []
206
for page in paged(api.pulls.list, owner='user', repo='repo', state='all', per_page=100):
207
for pr in page:
208
if pr.user.login == 'specific_author':
209
author_prs.append(pr)
210
211
print(f"PRs by author: {len(author_prs)}")
212
```
213
214
### Link Header Parsing
215
216
```python
217
from ghapi.all import parse_link_hdr
218
219
# Example link header from GitHub API
220
link_header = '<https://api.github.com/repos/user/repo/issues?page=2>; rel="next", <https://api.github.com/repos/user/repo/issues?page=5>; rel="last"'
221
222
# Parse the header
223
links = parse_link_hdr(link_header)
224
for url, attrs in links:
225
print(f"URL: {url}")
226
for key, value in attrs.items():
227
print(f" {key}: {value}")
228
229
# Extract specific relation types
230
next_url = None
231
last_url = None
232
for url, attrs in links:
233
if attrs.get('rel') == 'next':
234
next_url = url
235
elif attrs.get('rel') == 'last':
236
last_url = url
237
238
if next_url:
239
print(f"Next page: {next_url}")
240
if last_url:
241
print(f"Last page: {last_url}")
242
```
243
244
### Custom Pagination Logic
245
246
```python
247
from ghapi.all import GhApi, paged
248
249
api = GhApi(token='your_token')
250
251
def collect_all_data(operation_func, *args, **kwargs):
252
"""Collect all paginated data into a single list."""
253
all_data = []
254
for page in paged(operation_func, *args, per_page=100, **kwargs):
255
all_data.extend(page)
256
print(f"Collected {len(all_data)} items so far...")
257
return all_data
258
259
# Use custom collector
260
all_issues = collect_all_data(
261
api.issues.list_for_repo,
262
owner='user',
263
repo='repo',
264
state='all'
265
)
266
267
print(f"Total issues collected: {len(all_issues)}")
268
269
def process_in_chunks(operation_func, chunk_processor, *args, **kwargs):
270
"""Process paginated data in chunks."""
271
for page_num, page in enumerate(paged(operation_func, *args, per_page=50, **kwargs)):
272
print(f"Processing page {page_num + 1}...")
273
chunk_processor(page)
274
275
def process_repo_chunk(repos):
276
"""Process a chunk of repositories."""
277
for repo in repos:
278
if repo.stargazers_count > 100:
279
print(f"Popular repo: {repo.full_name} ({repo.stargazers_count} stars)")
280
281
# Process repositories in chunks
282
process_in_chunks(
283
api.repos.list_for_org,
284
process_repo_chunk,
285
org='organization'
286
)
287
```
288
289
### Error Handling with Pagination
290
291
```python
292
from ghapi.all import GhApi, paged
293
import time
294
295
api = GhApi(token='your_token')
296
297
def safe_paginate(operation_func, *args, retry_count=3, **kwargs):
298
"""Paginate with error handling and retries."""
299
page_num = 0
300
for page in paged(operation_func, *args, per_page=100, **kwargs):
301
page_num += 1
302
retries = 0
303
304
while retries < retry_count:
305
try:
306
# Process the page
307
yield page
308
break
309
except Exception as e:
310
retries += 1
311
print(f"Error processing page {page_num}, retry {retries}: {e}")
312
if retries < retry_count:
313
time.sleep(2 ** retries) # Exponential backoff
314
else:
315
print(f"Failed to process page {page_num} after {retry_count} retries")
316
raise
317
318
# Use safe pagination
319
try:
320
for page in safe_paginate(api.repos.list_for_org, org='large_org'):
321
for repo in page:
322
print(f"Processing: {repo.name}")
323
except Exception as e:
324
print(f"Pagination failed: {e}")
325
```