Skip to content

Commit 9e2028a

Browse files
committed
Remove caching, remove configuration of rate limit, minor bug fixes
1 parent dc6bad1 commit 9e2028a

21 files changed

Lines changed: 281 additions & 358 deletions

‎docs/configuration.html‎

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ <h1>Configuration</h1>
7171
base_url="https://www.ratemyprofessors.com/graphql",
7272
timeout_seconds=10.0,
7373
max_retries=3,
74-
rate_limit_per_minute=60,
7574
)
7675
with RMPClient(config) as client:
7776
...</code></pre>
@@ -104,12 +103,6 @@ <h2 id="available-options">
104103
<td><code>3</code></td>
105104
<td>Number of retry attempts for failed requests</td>
106105
</tr>
107-
<tr>
108-
<td><code>rate_limit_per_minute</code></td>
109-
<td><code>int</code></td>
110-
<td><code>60</code></td>
111-
<td>Max requests per minute (token bucket)</td>
112-
</tr>
113106
<tr>
114107
<td><code>user_agent</code></td>
115108
<td><code>str</code></td>
@@ -128,19 +121,46 @@ <h2 id="rate-limiting">
128121
Rate Limiting <a href="#rate-limiting" class="anchor">#</a>
129122
</h2>
130123
<p>
131-
The client uses a token-bucket algorithm. Tokens replenish continuously.
132-
Each request consumes one token. If no tokens are available, the request
133-
blocks until one becomes available.
124+
The client uses a token-bucket algorithm fixed at <strong>60 requests per
125+
minute</strong>. Tokens replenish continuously at 1 per second. Each
126+
request consumes one token; if none are available the request blocks
127+
until one becomes available. This limit is not configurable.
134128
</p>
135-
<pre><code class="language-python">config = RMPClientConfig(rate_limit_per_minute=30)</code></pre>
136129

137130
<h2 id="retries">Retries <a href="#retries" class="anchor">#</a></h2>
138131
<p>
139132
On 5xx errors or network failures, the client retries up to
140133
<code>max_retries</code> times. 4xx errors are
141134
<strong>not</strong> retried. After exhausting retries, a
142-
<code>RetryError</code> is raised.
135+
<code>RetryError</code> is raised. Each retry attempt consumes a token
136+
from the rate limiter before firing.
143137
</p>
138+
<table>
139+
<tr>
140+
<th>Situation</th>
141+
<th>Retried?</th>
142+
</tr>
143+
<tr>
144+
<td>Network error (timeout, connection reset)</td>
145+
<td>Yes</td>
146+
</tr>
147+
<tr>
148+
<td>5xx server error</td>
149+
<td>Yes</td>
150+
</tr>
151+
<tr>
152+
<td>4xx client error (400, 401, 403, 404)</td>
153+
<td>No &mdash; raises <code>HttpError</code> immediately</td>
154+
</tr>
155+
<tr>
156+
<td>429 Too Many Requests</td>
157+
<td>Yes &mdash; exponential back-off, up to <code>max_retries</code> times</td>
158+
</tr>
159+
<tr>
160+
<td>GraphQL <code>errors</code> in a 200 response</td>
161+
<td>No &mdash; raises <code>RMPAPIError</code> immediately</td>
162+
</tr>
163+
</table>
144164
<pre><code class="language-python">config = RMPClientConfig(max_retries=5)</code></pre>
145165

146166
<h2 id="timeouts">Timeouts <a href="#timeouts" class="anchor">#</a></h2>

‎docs/index.html‎

Lines changed: 138 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,121 @@
1-
<!DOCTYPE html>
1+
<!doctype html>
22
<html lang="en">
3-
<head>
4-
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6-
<title>RateMyProfessors API Client (Python)</title>
7-
<link rel="icon" href="favicon.svg" type="image/svg+xml" />
8-
<link rel="stylesheet" href="style.css" />
9-
<link id="hljs-theme" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css" />
10-
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
11-
<script>
12-
(function(){var t=localStorage.getItem('rmp-docs-theme');var d=t==='dark'||(!t&&window.matchMedia('(prefers-color-scheme:dark)').matches);if(d)document.documentElement.classList.add('dark')})();
13-
</script>
14-
</head>
15-
<body>
16-
<header class="topbar">
17-
<div class="topbar-right">
18-
<a href="https://github.com/amaanjaved1/Rate-My-Professors-API-Client" class="topbar-btn" target="_blank" rel="noopener" aria-label="GitHub">
19-
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z"/></svg>
20-
</a>
21-
<button class="topbar-btn" id="theme-toggle" aria-label="Toggle theme"></button>
22-
</div>
23-
</header>
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>RateMyProfessors API Client (Python)</title>
7+
<link rel="icon" href="favicon.svg" type="image/svg+xml" />
8+
<link rel="stylesheet" href="style.css" />
9+
<link
10+
id="hljs-theme"
11+
rel="stylesheet"
12+
href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css"
13+
/>
14+
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
15+
<script>
16+
(function () {
17+
var t = localStorage.getItem("rmp-docs-theme");
18+
var d =
19+
t === "dark" ||
20+
(!t && window.matchMedia("(prefers-color-scheme:dark)").matches);
21+
if (d) document.documentElement.classList.add("dark");
22+
})();
23+
</script>
24+
</head>
25+
<body>
26+
<header class="topbar">
27+
<div class="topbar-right">
28+
<a
29+
href="https://github.com/amaanjaved1/Rate-My-Professors-API-Client"
30+
class="topbar-btn"
31+
target="_blank"
32+
rel="noopener"
33+
aria-label="GitHub"
34+
>
35+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
36+
<path
37+
d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z"
38+
/>
39+
</svg>
40+
</a>
41+
<button
42+
class="topbar-btn"
43+
id="theme-toggle"
44+
aria-label="Toggle theme"
45+
></button>
46+
</div>
47+
</header>
2448

25-
<aside class="sidebar">
26-
<div class="sidebar-brand">RMP API Docs</div>
27-
<nav><ul>
28-
<li><a href="index.html" class="active">Home</a></li>
29-
<li><a href="usage.html">Usage</a></li>
30-
<li><a href="reference.html">API Reference</a></li>
31-
<li><a href="configuration.html">Configuration</a></li>
32-
<li><a href="extras.html">Extras</a></li>
33-
</ul></nav>
34-
</aside>
49+
<aside class="sidebar">
50+
<div class="sidebar-brand">RMP API Docs</div>
51+
<nav>
52+
<ul>
53+
<li><a href="index.html" class="active">Home</a></li>
54+
<li><a href="usage.html">Usage</a></li>
55+
<li><a href="reference.html">API Reference</a></li>
56+
<li><a href="configuration.html">Configuration</a></li>
57+
<li><a href="extras.html">Extras</a></li>
58+
</ul>
59+
</nav>
60+
</aside>
3561

36-
<main class="content">
37-
<h1>RateMyProfessors API Client</h1>
38-
<div class="badges">
39-
<a href="https://pypi.org/project/ratemyprofessors-client/"><img src="https://img.shields.io/pypi/v/ratemyprofessors-client?color=10b981&cacheSeconds=300" alt="PyPI" /></a>
40-
<a href="https://pypi.org/project/ratemyprofessors-client/"><img src="https://img.shields.io/pepy/dt/ratemyprofessors-client?cacheSeconds=300" alt="downloads" /></a>
41-
</div>
42-
<p>
43-
An unofficial, typed Python client for <a href="https://www.ratemyprofessors.com">RateMyProfessors</a>.
44-
All data is fetched via RMP's GraphQL API &mdash; no HTML scraping or browser automation required.
45-
</p>
62+
<main class="content">
63+
<h1>RateMyProfessors API Client</h1>
64+
<div class="badges">
65+
<a href="https://pypi.org/project/ratemyprofessors-client/"
66+
><img
67+
src="https://img.shields.io/pypi/v/ratemyprofessors-client?color=10b981&cacheSeconds=300"
68+
alt="PyPI"
69+
/></a>
70+
<a href="https://pypi.org/project/ratemyprofessors-client/"
71+
><img
72+
src="https://img.shields.io/pepy/dt/ratemyprofessors-client?cacheSeconds=300"
73+
alt="downloads"
74+
/></a>
75+
</div>
76+
<p>
77+
An unofficial, typed Python client for
78+
<a href="https://www.ratemyprofessors.com">RateMyProfessors</a>. All
79+
data is fetched via RMP's GraphQL API &mdash; no HTML scraping or
80+
browser automation required.
81+
</p>
4682

47-
<div class="callout">
48-
<strong>Disclaimer:</strong> This library is unofficial and may break if RMP changes their internal API. Use responsibly and respect rate limits.
49-
</div>
83+
<div class="callout">
84+
<strong>Disclaimer:</strong> This library is unofficial and may break if
85+
RMP changes their internal API. Use responsibly and respect rate limits.
86+
</div>
5087

51-
<h2 id="features">Features <a href="#features" class="anchor">#</a></h2>
52-
<ul>
53-
<li>Strong typing via Pydantic models</li>
54-
<li>Automatic retries with configurable max attempts</li>
55-
<li>Token-bucket rate limiting (default 60 req/min)</li>
56-
<li>In-memory caching for ratings pages</li>
57-
<li>Cursor-based pagination for all list/search endpoints</li>
58-
<li>Clear error hierarchy for precise exception handling</li>
59-
<li>Built-in helpers for ingestion workflows (sentiment, comment validation, course codes)</li>
60-
</ul>
88+
<h2 id="features">Features <a href="#features" class="anchor">#</a></h2>
89+
<ul>
90+
<li>Strong typing via Pydantic models</li>
91+
<li>Automatic retries with configurable max attempts</li>
92+
<li>Token-bucket rate limiting (default 60 req/min)</li>
93+
<li>In-memory caching for ratings pages</li>
94+
<li>Cursor-based pagination for all list/search endpoints</li>
95+
<li>Clear error hierarchy for precise exception handling</li>
96+
<li>
97+
Built-in helpers for ingestion workflows (sentiment, comment
98+
validation, course codes)
99+
</li>
100+
</ul>
61101

62-
<h2 id="requirements">Requirements <a href="#requirements" class="anchor">#</a></h2>
63-
<ul>
64-
<li><strong>Python 3.10</strong> or later</li>
65-
<li>Works with type checkers (Pydantic models, fully typed API)</li>
66-
</ul>
102+
<h2 id="requirements">
103+
Requirements <a href="#requirements" class="anchor">#</a>
104+
</h2>
105+
<ul>
106+
<li><strong>Python 3.10</strong> or later</li>
107+
<li>Works with type checkers (Pydantic models, fully typed API)</li>
108+
</ul>
67109

68-
<h2 id="installation">Installation <a href="#installation" class="anchor">#</a></h2>
69-
<pre><code class="language-bash">pip install ratemyprofessors-client</code></pre>
110+
<h2 id="installation">
111+
Installation <a href="#installation" class="anchor">#</a>
112+
</h2>
113+
<pre><code class="language-bash">pip install ratemyprofessors-client</code></pre>
70114

71-
<h2 id="quick-start">Quick Start <a href="#quick-start" class="anchor">#</a></h2>
72-
<pre><code class="language-python">from rmp_client import RMPClient
115+
<h2 id="quick-start">
116+
Quick Start <a href="#quick-start" class="anchor">#</a>
117+
</h2>
118+
<pre><code class="language-python">from rmp_client import RMPClient
73119

74120
with RMPClient() as client:
75121
prof = client.get_professor("2823076")
@@ -78,16 +124,33 @@ <h2 id="quick-start">Quick Start <a href="#quick-start" class="anchor">#</a></h2
78124
for rating in client.iter_professor_ratings(prof.id):
79125
print(rating.date, rating.quality, rating.comment)</code></pre>
80126

81-
<h2 id="documentation">Documentation <a href="#documentation" class="anchor">#</a></h2>
82-
<ul>
83-
<li><a href="usage.html">Usage</a> &mdash; Quickstart examples for every endpoint</li>
84-
<li><a href="configuration.html">Configuration</a> &mdash; Tuning retries, rate limits, timeouts, and headers</li>
85-
<li><a href="reference.html">API Reference</a> &mdash; Full method and type reference</li>
86-
<li><a href="extras.html">Extras</a> &mdash; Ingestion helpers (sentiment, comment validation, course mapping)</li>
87-
</ul>
88-
</main>
127+
<h2 id="documentation">
128+
Documentation <a href="#documentation" class="anchor">#</a>
129+
</h2>
130+
<ul>
131+
<li>
132+
<a href="usage.html">Usage</a> &mdash; Quickstart examples for every
133+
endpoint
134+
</li>
135+
<li>
136+
<a href="configuration.html">Configuration</a> &mdash; Tuning retries,
137+
rate limits, timeouts, and headers
138+
</li>
139+
<li>
140+
<a href="reference.html">API Reference</a> &mdash; Full method and
141+
type reference
142+
</li>
143+
<li>
144+
<a href="extras.html">Extras</a> &mdash; Ingestion helpers (sentiment,
145+
comment validation, course mapping)
146+
</li>
147+
</ul>
148+
</main>
89149

90-
<aside class="toc"><div class="toc-title">On this page</div><ul id="toc-list"></ul></aside>
91-
<script src="script.js"></script>
92-
</body>
150+
<aside class="toc">
151+
<div class="toc-title">On this page</div>
152+
<ul id="toc-list"></ul>
153+
</aside>
154+
<script src="script.js"></script>
155+
</body>
93156
</html>

‎docs/reference.html‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ <h2 id="school-methods">School Methods <a href="#school-methods" class="anchor">
4747
<tr><td><code>search_schools(query, *, page_size=20, cursor=None)</code></td><td><code>SchoolSearchResult</code></td><td>Search schools by name</td></tr>
4848
<tr><td><code>get_school(school_id)</code></td><td><code>School</code></td><td>Fetch a single school with category ratings</td></tr>
4949
<tr><td><code>get_compare_schools(school_id_1, school_id_2)</code></td><td><code>CompareSchoolsResult</code></td><td>Fetch two schools side by side</td></tr>
50-
<tr><td><code>get_school_ratings_page(school_id, *, cursor=None, page_size=20)</code></td><td><code>SchoolRatingsPage</code></td><td>Get one page of school ratings (cached)</td></tr>
50+
<tr><td><code>get_school_ratings_page(school_id, *, cursor=None, page_size=20)</code></td><td><code>SchoolRatingsPage</code></td><td>Get one page of school ratings</td></tr>
5151
<tr><td><code>iter_school_ratings(school_id, *, page_size=20, since=None)</code></td><td><code>Iterator[SchoolRating]</code></td><td>Iterate all school ratings</td></tr>
5252
</table>
5353

@@ -58,7 +58,7 @@ <h2 id="professor-methods">Professor Methods <a href="#professor-methods" class=
5858
<tr><td><code>list_professors_for_school(school_id, *, query=None, page_size=20, cursor=None)</code></td><td><code>ProfessorSearchResult</code></td><td>List professors at a school</td></tr>
5959
<tr><td><code>iter_professors_for_school(school_id, *, query=None, page_size=20)</code></td><td><code>Iterator[Professor]</code></td><td>Iterate all professors at a school</td></tr>
6060
<tr><td><code>get_professor(professor_id)</code></td><td><code>Professor</code></td><td>Fetch a single professor</td></tr>
61-
<tr><td><code>get_professor_ratings_page(professor_id, *, cursor=None, page_size=20, course_filter=None)</code></td><td><code>ProfessorRatingsPage</code></td><td>Get one page of professor ratings (cached)</td></tr>
61+
<tr><td><code>get_professor_ratings_page(professor_id, *, cursor=None, page_size=20, course_filter=None)</code></td><td><code>ProfessorRatingsPage</code></td><td>Get one page of professor ratings</td></tr>
6262
<tr><td><code>iter_professor_ratings(professor_id, *, page_size=20, since=None, course_filter=None)</code></td><td><code>Iterator[Rating]</code></td><td>Iterate all professor ratings</td></tr>
6363
</table>
6464

@@ -78,7 +78,7 @@ <h3 id="School">School</h3>
7878
<p><code>id</code>, <code>name</code>, <code>location</code>, <code>overall_quality</code>, <code>num_ratings</code>, <code>reputation</code>, <code>safety</code>, <code>happiness</code>, <code>facilities</code>, <code>social</code>, <code>location_rating</code>, <code>clubs</code>, <code>opportunities</code>, <code>internet</code>, <code>food</code></p>
7979

8080
<h3 id="Professor">Professor</h3>
81-
<p><code>id</code>, <code>name</code>, <code>department</code>, <code>school</code> (School), <code>url</code>, <code>overall_rating</code>, <code>num_ratings</code>, <code>percent_take_again</code>, <code>level_of_difficulty</code>, <code>tags</code>, <code>rating_distribution</code></p>
81+
<p><code>id</code>, <code>name</code>, <code>department</code>, <code>school</code> (School), <code>overall_rating</code>, <code>num_ratings</code>, <code>percent_take_again</code>, <code>level_of_difficulty</code>, <code>tags</code>, <code>rating_distribution</code></p>
8282

8383
<h3 id="Rating">Rating</h3>
8484
<p><code>date</code>, <code>comment</code>, <code>quality</code>, <code>difficulty</code>, <code>tags</code>, <code>course_raw</code>, <code>details</code>, <code>thumbs_up</code>, <code>thumbs_down</code></p>
@@ -103,7 +103,6 @@ <h2 id="errors">Errors <a href="#errors" class="anchor">#</a></h2>
103103
<tr><th>Error</th><th>Description</th></tr>
104104
<tr><td><code>HttpError</code></td><td>Non-2xx HTTP response. Has <code>status_code</code>, <code>url</code>, <code>body</code>.</td></tr>
105105
<tr><td><code>ParsingError</code></td><td>Could not parse the GraphQL response.</td></tr>
106-
<tr><td><code>RateLimitError</code></td><td>Local rate limiter blocked the request.</td></tr>
107106
<tr><td><code>RetryError</code></td><td>All retry attempts exhausted.</td></tr>
108107
<tr><td><code>RMPAPIError</code></td><td>GraphQL API returned an <code>errors</code> array.</td></tr>
109108
<tr><td><code>ConfigurationError</code></td><td>Invalid client configuration.</td></tr>

‎src/rmp_client/__init__.py‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
ConfigurationError,
77
HttpError,
88
ParsingError,
9-
RateLimitError,
109
RetryError,
1110
RMPAPIError,
1211
RMPError,
@@ -30,7 +29,6 @@
3029
"ConfigurationError",
3130
"HttpError",
3231
"ParsingError",
33-
"RateLimitError",
3432
"RetryError",
3533
"RMPAPIError",
3634
"TokenBucket",

0 commit comments

Comments
 (0)