Skip to content

Commit 79ee432

Browse files
authored
Merge pull request #4 from amaanjaved1/feature/final-cleanup
Feature/final cleanup
2 parents 1d7c555 + fda5f61 commit 79ee432

18 files changed

Lines changed: 1291 additions & 373 deletions

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# RateMyProfessors API Client (Python)
22

3+
[![PyPI](https://img.shields.io/pypi/v/ratemyprofessors-client?color=10b981)](https://pypi.org/project/ratemyprofessors-client/) [![downloads](https://img.shields.io/pepy/dt/ratemyprofessors-client)](https://pypi.org/project/ratemyprofessors-client/) [![docs](https://img.shields.io/badge/docs-website-10b981)](https://amaanjaved1.github.io/Rate-My-Professors-API-Client/)
4+
35
A typed, retrying, rate-limited **unofficial** client for [RateMyProfessors](https://www.ratemyprofessors.com).
46

5-
> **Disclaimer:** This library is unofficial and may break if RMP changes their internal API. Use responsibly and respect rate limits.
7+
> **Looking for TypeScript?** Check out the [TypeScript version](https://github.com/amaanjaved1/rate-my-professors-client-ts).
68
79
## Requirements
810

@@ -114,8 +116,8 @@ from rmp_client import (
114116
)
115117
```
116118

117-
- `normalize_comment(text)` — Normalize text for deduplication (lowercase, collapse whitespace)
118-
- `is_valid_comment(text, min_len=10)`Check if a comment is non-empty and meets a minimum length
119+
- `normalize_comment(text, *, strip_html=True, strip_punctuation=False)` — Normalize text for deduplication (trim, strip HTML, lowercase, collapse whitespace; optionally strip punctuation)
120+
- `is_valid_comment(text, *, min_len=10)`Validate a comment and return a `ValidationResult` with diagnostics (empty, too short, all caps, excessive repeats, no alpha)
119121
- `clean_course_label(raw)` — Clean scraped course labels (remove counts, normalize whitespace)
120122
- `build_course_mapping(scraped, valid)` — Map scraped labels to known course codes
121123
- `analyze_sentiment(text)` — Compute sentiment label from text (uses TextBlob)

docs/configuration.html

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Configuration &mdash; RMP Client</title>
7+
<link rel="stylesheet" href="style.css" />
8+
<link id="hljs-theme" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css" />
9+
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
10+
<script>
11+
(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')})();
12+
</script>
13+
</head>
14+
<body>
15+
<header class="topbar">
16+
<div class="topbar-right">
17+
<a href="https://github.com/amaanjaved1/Rate-My-Professors-API-Client" class="topbar-btn" target="_blank" rel="noopener" aria-label="GitHub">
18+
<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>
19+
</a>
20+
<button class="topbar-btn" id="theme-toggle" aria-label="Toggle theme"></button>
21+
</div>
22+
</header>
23+
24+
<aside class="sidebar">
25+
<div class="sidebar-brand">RMP API Docs</div>
26+
<nav><ul>
27+
<li><a href="index.html">Home</a></li>
28+
<li><a href="usage.html">Usage</a></li>
29+
<li><a href="reference.html">API Reference</a></li>
30+
<li><a href="configuration.html" class="active">Configuration</a></li>
31+
<li><a href="extras.html">Extras</a></li>
32+
</ul></nav>
33+
</aside>
34+
35+
<main class="content">
36+
<h1>Configuration</h1>
37+
<p>The client is configured via <code>RMPClientConfig</code>. All fields have sensible defaults.</p>
38+
<pre><code class="language-python">from rmp_client import RMPClientConfig, RMPClient
39+
40+
config = RMPClientConfig(
41+
base_url="https://www.ratemyprofessors.com/graphql",
42+
timeout_seconds=10.0,
43+
max_retries=3,
44+
rate_limit_per_minute=60,
45+
)
46+
with RMPClient(config) as client:
47+
...</code></pre>
48+
49+
<h2 id="available-options">Available Options <a href="#available-options" class="anchor">#</a></h2>
50+
<table>
51+
<tr><th>Option</th><th>Type</th><th>Default</th><th>Description</th></tr>
52+
<tr><td><code>base_url</code></td><td><code>str</code></td><td><code>https://...graphql</code></td><td>GraphQL endpoint URL</td></tr>
53+
<tr><td><code>timeout_seconds</code></td><td><code>float</code></td><td><code>10.0</code></td><td>HTTP request timeout</td></tr>
54+
<tr><td><code>max_retries</code></td><td><code>int</code></td><td><code>3</code></td><td>Number of retry attempts for failed requests</td></tr>
55+
<tr><td><code>rate_limit_per_minute</code></td><td><code>int</code></td><td><code>60</code></td><td>Max requests per minute (token bucket)</td></tr>
56+
<tr><td><code>user_agent</code></td><td><code>str</code></td><td>Firefox UA</td><td>User-Agent header</td></tr>
57+
<tr><td><code>default_headers</code></td><td><code>Mapping[str, str]</code></td><td>UA + Accept-Language</td><td>Default headers for all requests</td></tr>
58+
</table>
59+
60+
<h2 id="rate-limiting">Rate Limiting <a href="#rate-limiting" class="anchor">#</a></h2>
61+
<p>The client uses a token-bucket algorithm. Tokens replenish continuously. Each request consumes one token. If no tokens are available, the request blocks until one becomes available.</p>
62+
<pre><code class="language-python">config = RMPClientConfig(rate_limit_per_minute=30)</code></pre>
63+
64+
<h2 id="retries">Retries <a href="#retries" class="anchor">#</a></h2>
65+
<p>On 5xx errors or network failures, the client retries up to <code>max_retries</code> times. 4xx errors are <strong>not</strong> retried. After exhausting retries, a <code>RetryError</code> is raised.</p>
66+
<pre><code class="language-python">config = RMPClientConfig(max_retries=5)</code></pre>
67+
68+
<h2 id="timeouts">Timeouts <a href="#timeouts" class="anchor">#</a></h2>
69+
<p>The <code>timeout_seconds</code> value applies to each individual HTTP request (connect + read).</p>
70+
<pre><code class="language-python">config = RMPClientConfig(timeout_seconds=30.0)</code></pre>
71+
</main>
72+
73+
<aside class="toc"><div class="toc-title">On this page</div><ul id="toc-list"></ul></aside>
74+
<script src="script.js"></script>
75+
</body>
76+
</html>

docs/configuration.md

Lines changed: 0 additions & 52 deletions
This file was deleted.

docs/extras.html

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Extras &mdash; RMP Client</title>
7+
<link rel="stylesheet" href="style.css" />
8+
<link id="hljs-theme" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css" />
9+
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
10+
<script>
11+
(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')})();
12+
</script>
13+
</head>
14+
<body>
15+
<header class="topbar">
16+
<div class="topbar-right">
17+
<a href="https://github.com/amaanjaved1/Rate-My-Professors-API-Client" class="topbar-btn" target="_blank" rel="noopener" aria-label="GitHub">
18+
<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>
19+
</a>
20+
<button class="topbar-btn" id="theme-toggle" aria-label="Toggle theme"></button>
21+
</div>
22+
</header>
23+
24+
<aside class="sidebar">
25+
<div class="sidebar-brand">RMP API Docs</div>
26+
<nav><ul>
27+
<li><a href="index.html">Home</a></li>
28+
<li><a href="usage.html">Usage</a></li>
29+
<li><a href="reference.html">API Reference</a></li>
30+
<li><a href="configuration.html">Configuration</a></li>
31+
<li><a href="extras.html" class="active">Extras</a></li>
32+
</ul></nav>
33+
</aside>
34+
35+
<main class="content">
36+
<h1>Extras</h1>
37+
<p>Helpers for ingestion pipelines. Import them from <code>rmp_client</code>:</p>
38+
<pre><code class="language-python">from rmp_client import (
39+
analyze_sentiment, normalize_comment,
40+
is_valid_comment, build_course_mapping,
41+
clean_course_label,
42+
)</code></pre>
43+
44+
<h2 id="sentiment">Sentiment <a href="#sentiment" class="anchor">#</a></h2>
45+
<p>Compute a sentiment score and label from comment text (uses TextBlob internally).</p>
46+
<pre><code class="language-python">result = analyze_sentiment("Great prof, explains concepts clearly.")
47+
print(result.score, result.label) # e.g. 0.65 "positive"</code></pre>
48+
49+
<h2 id="helpers">Helpers <a href="#helpers" class="anchor">#</a></h2>
50+
51+
<h3 id="normalize_comment">normalize_comment</h3>
52+
<div class="method-sig">normalize_comment(text: str, *, strip_html: bool = True, strip_punctuation: bool = False) -&gt; str</div>
53+
<p>Normalizes a comment for comparison or deduplication. Trims whitespace, strips HTML tags (opt-out), lowercases, and collapses runs of whitespace. Optionally strips punctuation for looser matching.</p>
54+
<table>
55+
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
56+
<tr><td><code>text</code></td><td><code>str</code></td><td>&mdash;</td><td>Comment text</td></tr>
57+
<tr><td><code>strip_html</code></td><td><code>bool</code></td><td><code>True</code></td><td>Remove HTML tags</td></tr>
58+
<tr><td><code>strip_punctuation</code></td><td><code>bool</code></td><td><code>False</code></td><td>Remove all punctuation</td></tr>
59+
</table>
60+
<pre><code class="language-python">a = normalize_comment(" Great Professor! ")
61+
b = normalize_comment("great professor!")
62+
assert a == b # True
63+
64+
normalize_comment("&lt;b&gt;Loved&lt;/b&gt; this class") # "loved this class"
65+
normalize_comment("Hello, world!", strip_punctuation=True) # "hello world"</code></pre>
66+
67+
<h3 id="is_valid_comment">is_valid_comment</h3>
68+
<div class="method-sig">is_valid_comment(text: str, *, min_len: int = 10) -&gt; ValidationResult</div>
69+
<p>Validates a comment and returns detailed diagnostics. Checks for empty text, insufficient length, all-caps, excessive repeated characters, and absence of alphabetic characters.</p>
70+
<table>
71+
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
72+
<tr><td><code>text</code></td><td><code>str</code></td><td>&mdash;</td><td>Comment text</td></tr>
73+
<tr><td><code>min_len</code></td><td><code>int</code></td><td><code>10</code></td><td>Minimum character length</td></tr>
74+
</table>
75+
<p><strong>Returns:</strong> <code>ValidationResult</code> with <code>valid</code> (bool) and <code>issues</code> (list of <code>CommentIssue</code>).</p>
76+
<p>Each issue has a <code>code</code> (<code>"empty"</code>, <code>"too_short"</code>, <code>"all_caps"</code>, <code>"excessive_repeats"</code>, <code>"no_alpha"</code>) and a human-readable <code>message</code>.</p>
77+
<pre><code class="language-python">result = is_valid_comment("Good")
78+
# ValidationResult(valid=False, issues=[CommentIssue(code="too_short", ...)])
79+
80+
result = is_valid_comment("Great class, learned a lot")
81+
# ValidationResult(valid=True, issues=[])
82+
83+
result = is_valid_comment("WORST PROF EVER!!!")
84+
# ValidationResult(valid=False, issues=[CommentIssue(code="all_caps", ...)])</code></pre>
85+
86+
<h2 id="course-code-helpers">Course Code Helpers <a href="#course-code-helpers" class="anchor">#</a></h2>
87+
<p>Map scraped RMP course labels to your course catalog.</p>
88+
<pre><code class="language-python">scraped = ["ANAT 215 (12)", "phys115"]
89+
valid = ["ANAT 215", "PHYS 115"]
90+
91+
mapping = build_course_mapping(scraped, valid)
92+
# {"ANAT 215 (12)": "ANAT 215", "phys115": "PHYS 115"}
93+
94+
cleaned = clean_course_label("MATH 101 (5)")
95+
# "MATH 101"</code></pre>
96+
</main>
97+
98+
<aside class="toc"><div class="toc-title">On this page</div><ul id="toc-list"></ul></aside>
99+
<script src="script.js"></script>
100+
</body>
101+
</html>

docs/extras.md

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)