addressed review-library tool's results#5
Conversation
📝 WalkthroughWalkthroughThis PR removes the APScheduler dependency, refactors type safety by introducing a Tier enum to replace string tier values, converts the ProbeState.discovered property to a get_all_discovered() method, and adds exponential backoff retry logic to the probe mechanism. ChangesAPScheduler Removal
Type Safety & API Refactoring
Sequence Diagram(s)No sequence diagrams generated. The changes are primarily type safety improvements, API refactoring, and resilience enhancements rather than new control flow or multi-component interactions. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Review rate limit: 4/5 reviews remaining, refill in 12 minutes. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/paperscout/sources.py (2)
518-519: 💤 Low valueConsider logging malformed Last-Modified headers.
The static analyzer flags the
try-except-passpattern (S110). While verbose logging of every malformed header may not be desired, a debug-level log could help diagnose issues with specific servers.♻️ Optional: Add debug logging
try: last_modified = parsedate_to_datetime(lm_str) threshold = timedelta(hours=self.cfg.alert_modified_hours) is_recent = ( datetime.now(timezone.utc) - last_modified ) <= threshold - except Exception: - pass + except Exception as exc: + log.debug("Failed to parse Last-Modified '%s' for %s: %s", lm_str, url, exc)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/paperscout/sources.py` around lines 518 - 519, The silent except block swallowing errors when parsing Last-Modified headers should be replaced with a debug-level log so malformed headers can be diagnosed; locate the try/except around Last-Modified parsing (the except Exception: pass) in src/paperscout/sources.py and change it to log the header value and error (e.g., logger.debug with the header content and exception info or use exc_info=True) instead of passing, keeping behavior non-failure but recording details for troubleshooting.
487-553: 💤 Low valueUnreachable code after retry loop.
The
elseclause on line 499-500 andreturn Noneon line 553 are unreachable. The for-loop either exits viabreak(line 491) orreturn None(line 498), so theelseblock never executes. Similarly, line 553 is outside theasync with sem:block but can never be reached.♻️ Proposed cleanup
async with sem: _max_retries = 3 for _attempt in range(_max_retries): try: resp = await client.head(url) break except httpx.HTTPError as exc: if _attempt < _max_retries - 1: await asyncio.sleep(0.5 * (2 ** _attempt)) continue log.debug("ERR %s %s (after %d attempts)", url, exc, _max_retries) self._stats["error"] += 1 return None - else: - return None if resp.status_code != 200: # ... rest of the logic ... return ProbeHit(...) - return None🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/paperscout/sources.py` around lines 487 - 553, The for-loop's else and the trailing return None are unreachable; remove the for ... else block and the final return None, and instead after the retry loop (after the for _attempt in range(_max_retries): ... break/except) add a simple presence check for resp (e.g. if resp is None or "resp" not in locals(): return None) so the subsequent code that inspects resp.status_code, parses last-modified and eventually returns ProbeHit (and calls _fetch_front_text) only runs when resp is valid; reference symbols: _max_retries, resp, for _attempt, ProbeHit, _fetch_front_text.src/paperscout/scout.py (1)
416-418: 💤 Low valueRedundant local import.
datetimeandtimezoneare already imported at the top of the file (line 7). The local import with aliases_dtand_tzis unnecessary.♻️ Remove redundant import
def _handle_status(state: ProbeState, paper_count_fn, say, reply_opts: dict) -> None: - from datetime import datetime as _dt, timezone as _tz last = state.last_poll - last_str = _dt.fromtimestamp(last, tz=_tz.utc).strftime("%Y-%m-%d %H:%M:%S UTC") if last else "never" + last_str = datetime.fromtimestamp(last, tz=timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC") if last else "never"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/paperscout/scout.py` around lines 416 - 418, Remove the redundant local import "from datetime import datetime as _dt, timezone as _tz" and change the usage to the module-level imports already present at the top of the file; specifically update the expression that builds last_str (which reads state.last_poll into last and formats it) to call datetime.fromtimestamp(last, tz=timezone.utc). Ensure you keep the same conditional ("if last else 'never'") and the same strftime format while referencing datetime and timezone (not _dt/_tz) so the duplicate import and aliased names are eliminated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/paperscout/scout.py`:
- Around line 416-418: Remove the redundant local import "from datetime import
datetime as _dt, timezone as _tz" and change the usage to the module-level
imports already present at the top of the file; specifically update the
expression that builds last_str (which reads state.last_poll into last and
formats it) to call datetime.fromtimestamp(last, tz=timezone.utc). Ensure you
keep the same conditional ("if last else 'never'") and the same strftime format
while referencing datetime and timezone (not _dt/_tz) so the duplicate import
and aliased names are eliminated.
In `@src/paperscout/sources.py`:
- Around line 518-519: The silent except block swallowing errors when parsing
Last-Modified headers should be replaced with a debug-level log so malformed
headers can be diagnosed; locate the try/except around Last-Modified parsing
(the except Exception: pass) in src/paperscout/sources.py and change it to log
the header value and error (e.g., logger.debug with the header content and
exception info or use exc_info=True) instead of passing, keeping behavior
non-failure but recording details for troubleshooting.
- Around line 487-553: The for-loop's else and the trailing return None are
unreachable; remove the for ... else block and the final return None, and
instead after the retry loop (after the for _attempt in range(_max_retries): ...
break/except) add a simple presence check for resp (e.g. if resp is None or
"resp" not in locals(): return None) so the subsequent code that inspects
resp.status_code, parses last-modified and eventually returns ProbeHit (and
calls _fetch_front_text) only runs when resp is valid; reference symbols:
_max_retries, resp, for _attempt, ProbeHit, _fetch_front_text.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d1bdd593-cbe6-4172-b875-d896895b2344
📒 Files selected for processing (10)
README.mdpyproject.tomlsrc/paperscout/__main__.pysrc/paperscout/health.pysrc/paperscout/monitor.pysrc/paperscout/scout.pysrc/paperscout/sources.pysrc/paperscout/storage.pytests/test_health.pytests/test_storage.py
💤 Files with no reviewable changes (2)
- README.md
- pyproject.toml
Summary by CodeRabbit
New Features
Refactor