Skip to content

Commit 5ec0cac

Browse files
johntrandallclaude
andcommitted
Fix get_subreddit_info crash when redditwarp raises KeyError
When Reddit removes fields from their API response (e.g. active_user_count), redditwarp's Subreddit model construction raises KeyError. This adds a fallback that catches KeyError and uses a raw API call to return basic subreddit info. Fixes #6 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fb0816a commit 5ec0cac

File tree

3 files changed

+106
-1
lines changed

3 files changed

+106
-1
lines changed

src/mcp_server_reddit/server.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,25 @@ def get_frontpage_posts(self, limit: int = 10) -> list[Post]:
115115

116116
def get_subreddit_info(self, subreddit_name: str) -> SubredditInfo:
117117
"""Get information about a subreddit"""
118-
subr = self.client.p.subreddit.fetch_by_name(subreddit_name)
118+
try:
119+
subr = self.client.p.subreddit.fetch_by_name(subreddit_name)
120+
except KeyError as exc:
121+
# redditwarp's Subreddit model uses bracket access on fields that
122+
# Reddit may have removed from the API (e.g. active_user_count).
123+
# Fall back to a raw API call to get basic subreddit info.
124+
import logging
125+
logging.getLogger(__name__).warning(
126+
"redditwarp model construction failed for r/%s: %s. "
127+
"Using fallback.",
128+
subreddit_name, exc,
129+
)
130+
root = self.client.request('GET', f'/r/{subreddit_name}/about')
131+
data = root['data']
132+
return SubredditInfo(
133+
name=data.get('display_name', subreddit_name),
134+
subscriber_count=data.get('subscribers', -1),
135+
description=data.get('public_description'),
136+
)
119137
return SubredditInfo(
120138
name=subr.name,
121139
subscriber_count=subr.subscriber_count,

tests/__init__.py

Whitespace-only changes.

tests/test_server.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""Tests for mcp-server-reddit server logic."""
2+
3+
from unittest.mock import MagicMock, patch, PropertyMock
4+
5+
import pytest
6+
7+
from mcp_server_reddit.server import RedditServer, SubredditInfo
8+
9+
10+
class TestGetSubredditInfo:
11+
"""Test get_subreddit_info with normal and fallback paths."""
12+
13+
def _make_server_with_mock_client(self):
14+
"""Create a RedditServer with a mocked redditwarp client."""
15+
with patch.object(RedditServer, '__init__', lambda self: None):
16+
server = RedditServer()
17+
server.client = MagicMock()
18+
return server
19+
20+
def test_normal_path(self):
21+
"""Returns SubredditInfo when redditwarp model construction succeeds."""
22+
server = self._make_server_with_mock_client()
23+
24+
mock_subr = MagicMock()
25+
mock_subr.name = 'python'
26+
mock_subr.subscriber_count = 1200000
27+
mock_subr.public_description = 'News about Python'
28+
server.client.p.subreddit.fetch_by_name.return_value = mock_subr
29+
30+
result = server.get_subreddit_info('python')
31+
32+
assert isinstance(result, SubredditInfo)
33+
assert result.name == 'python'
34+
assert result.subscriber_count == 1200000
35+
assert result.description == 'News about Python'
36+
37+
def test_fallback_on_keyerror(self):
38+
"""Falls back to raw API when redditwarp raises KeyError.
39+
40+
This happens when Reddit removes fields from the API response
41+
that redditwarp expects (e.g. active_user_count).
42+
"""
43+
server = self._make_server_with_mock_client()
44+
45+
# Simulate redditwarp KeyError during model construction
46+
server.client.p.subreddit.fetch_by_name.side_effect = KeyError('active_user_count')
47+
48+
# Mock the raw API fallback
49+
server.client.request.return_value = {
50+
'data': {
51+
'display_name': 'python',
52+
'subscribers': 1200000,
53+
'public_description': 'News about Python',
54+
}
55+
}
56+
57+
result = server.get_subreddit_info('python')
58+
59+
assert isinstance(result, SubredditInfo)
60+
assert result.name == 'python'
61+
assert result.subscriber_count == 1200000
62+
assert result.description == 'News about Python'
63+
server.client.request.assert_called_once_with('GET', '/r/python/about')
64+
65+
def test_fallback_with_missing_fields(self):
66+
"""Fallback handles missing fields gracefully with defaults."""
67+
server = self._make_server_with_mock_client()
68+
server.client.p.subreddit.fetch_by_name.side_effect = KeyError('active_user_count')
69+
70+
# Minimal API response — missing optional fields
71+
server.client.request.return_value = {
72+
'data': {}
73+
}
74+
75+
result = server.get_subreddit_info('test_sub')
76+
77+
assert result.name == 'test_sub' # falls back to argument
78+
assert result.subscriber_count == -1 # default
79+
assert result.description is None
80+
81+
def test_non_keyerror_exceptions_propagate(self):
82+
"""Non-KeyError exceptions are not caught by the fallback."""
83+
server = self._make_server_with_mock_client()
84+
server.client.p.subreddit.fetch_by_name.side_effect = ConnectionError('network down')
85+
86+
with pytest.raises(ConnectionError):
87+
server.get_subreddit_info('python')

0 commit comments

Comments
 (0)