Merge pull request #366 from davemorin/feat/324-reddit-json-fallback

feat(web): auto-enrich Reddit URLs from web search via JSON API
This commit is contained in:
Trevin Chow
2026-05-16 23:41:57 -07:00
committed by GitHub
2 changed files with 154 additions and 9 deletions
+83
View File
@@ -190,5 +190,88 @@ class WebSearchDispatchTests(unittest.TestCase):
grounding.web_search("test", ("2026-02-25", "2026-03-27"), {}, backend="google")
class RedditEnrichmentGateTests(unittest.TestCase):
"""EXCLUDE_SOURCES=reddit must suppress the web-search Reddit enrichment.
Otherwise a user who explicitly excluded Reddit would still get Reddit
content smuggled back in via web-search URLs that happen to point at
reddit.com threads.
"""
def test_reddit_excluded_via_exclude_sources_skips_enrichment(self):
config = {"BRAVE_API_KEY": "k", "EXCLUDE_SOURCES": "reddit"}
items = [{"url": "https://www.reddit.com/r/python/comments/abc/title/", "snippet": "original"}]
with patch("lib.grounding.brave_search", return_value=(items, {})), \
patch("lib.grounding._enrich_reddit_items") as enrich_mock:
grounding.web_search("test", ("2026-02-25", "2026-03-27"), config, backend="auto")
enrich_mock.assert_not_called()
def test_reddit_excluded_case_insensitive(self):
for value in ("REDDIT", "Reddit", " reddit ", "x,reddit,y"):
config = {"BRAVE_API_KEY": "k", "EXCLUDE_SOURCES": value}
self.assertTrue(
grounding._reddit_excluded(config),
msg=f"_reddit_excluded should be True for EXCLUDE_SOURCES={value!r}",
)
def test_reddit_not_excluded_when_other_sources_listed(self):
config = {"EXCLUDE_SOURCES": "tiktok,instagram"}
self.assertFalse(grounding._reddit_excluded(config))
def test_enrichment_runs_when_reddit_not_excluded(self):
config = {"BRAVE_API_KEY": "k"}
items = [{"url": "https://www.reddit.com/r/python/comments/abc/title/", "snippet": "original"}]
with patch("lib.grounding.brave_search", return_value=(items, {})), \
patch("lib.grounding._enrich_reddit_items", return_value=items) as enrich_mock:
grounding.web_search("test", ("2026-02-25", "2026-03-27"), config, backend="auto")
enrich_mock.assert_called_once()
class RedditEnrichItemsTests(unittest.TestCase):
"""Direct tests for `_enrich_reddit_items` covering the selftext key path
and the RedditRateLimitError early-exit behavior.
"""
def test_selftext_under_submission_populates_snippet(self):
from lib import reddit_enrich
item = {
"url": "https://www.reddit.com/r/python/comments/abc/title/",
"snippet": "original",
}
parsed = {
"submission": {"selftext": "thread body content"},
"comments": [],
}
with patch.object(reddit_enrich, "fetch_thread_data", return_value={"raw": True}), \
patch.object(reddit_enrich, "parse_thread_data", return_value=parsed):
result = grounding._enrich_reddit_items([item])
self.assertEqual("thread body content", result[0]["snippet"])
self.assertEqual("reddit_json_api", result[0]["enriched_via"])
def test_rate_limit_error_halts_iteration(self):
from lib import reddit_enrich
item1 = {"url": "https://www.reddit.com/r/python/comments/aaa/x/"}
item2 = {"url": "https://www.reddit.com/r/python/comments/bbb/y/"}
def fake_fetch(url, *args, **kwargs):
raise reddit_enrich.RedditRateLimitError(f"429 for {url}")
captured_stderr: list[str] = []
with patch.object(reddit_enrich, "fetch_thread_data", side_effect=fake_fetch) as fetch_mock, \
patch("lib.grounding.sys.stderr.write", side_effect=lambda s: captured_stderr.append(s)):
grounding._enrich_reddit_items([item1, item2])
# Only the first item should have triggered a fetch attempt
self.assertEqual(1, fetch_mock.call_count)
# A stderr message about the rate-limit halt should have been emitted
self.assertTrue(
any("rate-limited" in msg.lower() or "rate limited" in msg.lower() for msg in captured_stderr),
msg=f"Expected a rate-limit stderr message, got: {captured_stderr!r}",
)
if __name__ == "__main__":
unittest.main()