|
11 | 11 |
|
12 | 12 | import logging |
13 | 13 | import os |
| 14 | +import time |
14 | 15 |
|
15 | 16 | import requests |
16 | 17 | from dataclasses import dataclass |
@@ -80,28 +81,69 @@ def api_endpoint(self): |
80 | 81 | ) |
81 | 82 | return url |
82 | 83 |
|
| 84 | + def handle_rate_limit(self, response): |
| 85 | + """ |
| 86 | + Handle rate limiting by waiting until the rate limit resets. |
| 87 | +
|
| 88 | + Parameters |
| 89 | + ---------- |
| 90 | + response : requests.Response |
| 91 | + The response object from the API request. |
| 92 | +
|
| 93 | + Notes |
| 94 | + ----- |
| 95 | + This method checks the remaining rate limit in the response headers. |
| 96 | + If the remaining requests are exhausted, it calculates the time |
| 97 | + until the rate limit resets and sleeps accordingly. |
| 98 | + """ |
| 99 | + |
| 100 | + if "X-RateLimit-Remaining" in response.headers: |
| 101 | + remaining_requests = int(response.headers["X-RateLimit-Remaining"]) |
| 102 | + if remaining_requests <= 0: |
| 103 | + reset_time = int(response.headers["X-RateLimit-Reset"]) |
| 104 | + sleep_time = max(reset_time - time.time(), 0) + 1 |
| 105 | + time.sleep(sleep_time) |
| 106 | + |
83 | 107 | def return_response(self) -> list[dict[str, object]]: |
84 | 108 | """ |
85 | 109 | Make a GET request to the Github API endpoint |
86 | 110 | Deserialize json response to list of dicts. |
87 | 111 |
|
| 112 | + Handles pagination as github has a REST api 100 request max. |
| 113 | +
|
88 | 114 | Returns |
89 | 115 | ------- |
90 | 116 | list |
91 | 117 | List of dict items each containing a review issue |
92 | 118 | """ |
93 | 119 |
|
| 120 | + results = [] |
| 121 | + # This is computed as a property. Reassign here to support pagination |
| 122 | + # and new urls for each page |
| 123 | + api_endpoint_url = self.api_endpoint |
94 | 124 | try: |
95 | | - response = requests.get( |
96 | | - self.api_endpoint, |
97 | | - headers={"Authorization": f"token {self.get_token()}"}, |
98 | | - ) |
99 | | - response.raise_for_status() |
| 125 | + while True: |
| 126 | + response = requests.get( |
| 127 | + api_endpoint_url, |
| 128 | + headers={"Authorization": f"token {self.get_token()}"}, |
| 129 | + ) |
| 130 | + response.raise_for_status() |
| 131 | + results.extend(response.json()) |
| 132 | + |
| 133 | + # Check if there are more pages to fetch |
| 134 | + if "next" in response.links: |
| 135 | + next_url = response.links["next"]["url"] |
| 136 | + api_endpoint_url = next_url |
| 137 | + else: |
| 138 | + break |
| 139 | + |
| 140 | + # Handle rate limiting |
| 141 | + self.handle_rate_limit(response) |
100 | 142 |
|
101 | 143 | except requests.HTTPError as exception: |
102 | 144 | raise exception |
103 | 145 |
|
104 | | - return response.json() |
| 146 | + return results |
105 | 147 |
|
106 | 148 | def get_repo_meta(self, url: str) -> dict[str, Any] | None: |
107 | 149 | """ |
|
0 commit comments