Skip to content

Typed callback protocols for notify_callback and ops_alert_fn#66

Merged
wpak-ai merged 4 commits into
developfrom
feat/callback-protocols
Jun 17, 2026
Merged

Typed callback protocols for notify_callback and ops_alert_fn#66
wpak-ai merged 4 commits into
developfrom
feat/callback-protocols

Conversation

@henry0816191

@henry0816191 henry0816191 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replace bare / partially-typed callback parameters in Scheduler with explicit typing.Protocol classes. A caller that passes a function with the wrong signature is now caught by the type checker at author time rather than at runtime.

Changes

  • protocols.py: Add @runtime_checkable NotifyCallback ((PollResult) -> None) and OpsAlertFn ((str) -> None); PollResult imported under TYPE_CHECKING to avoid circular import.
  • monitor.py: notify_callback and ops_alert_fn params and instance attributes annotated with the new Protocol types; unused Callable import removed.
  • __main__.py: _on_poll_result closure gains explicit result: PollResult annotation; structurally satisfies NotifyCallback.
  • pyproject.toml: Per-module strict = true override for paperscout.protocols and paperscout.monitor; typing/ added to pytest norecursedirs.
  • .pre-commit-config.yaml: Local uv run mypy hook for protocols.py + monitor.py (uses project's own uv.lock mypy, avoids version drift).
  • Tests: New tests/test_callback_protocols.py — isinstance conformance, scheduler wiring, and subprocess mypy negative test; tests/typing/invalid_callbacks.py holds deliberate type errors verified by that test.

Acceptance criteria

Criterion Status
NotifyCallback and OpsAlertFn Protocol classes defined Done
All callback params in monitor.py annotated Done
mypy --strict passes on protocols.py + monitor.py Done (0 errors)
Test confirms mis-typed callback flagged by mypy Done (test_mypy_rejects_invalid_callbacks)
Existing test suite passes without regressions Done (369 passed, 2 skipped)

Test plan

  • uv run pytest tests/ — 369 passed, 2 skipped
  • uv run mypy src/paperscout/protocols.py src/paperscout/monitor.py — clean (strict)
  • uv run mypy tests/typing/invalid_callbacks.py — 2 [assignment] errors as expected
  • uv run pre-commit run --all-files — all hooks passed

Related

Summary by CodeRabbit

  • New Features
    • Added structural typing contracts for notification and ops alert callbacks for safer callback integration.
  • Refactor / Type Safety
    • Updated scheduler and entrypoint wiring to use the new callback protocols with stronger type annotations.
    • Tightened static typing for monitoring/protocol modules while keeping broader settings unchanged.
  • Tests
    • Added runtime and mypy coverage to verify valid callbacks are accepted and invalid ones are rejected, including scheduler behavior.
  • Chores
    • Added a targeted pre-commit mypy hook and improved pytest directory traversal exclusions.

@henry0816191 henry0816191 self-assigned this Jun 17, 2026
@henry0816191 henry0816191 requested a review from wpak-ai as a code owner June 17, 2026 15:19
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dceed7d8-75b2-4a4b-b1fc-619b8160b452

📥 Commits

Reviewing files that changed from the base of the PR and between a76111a and 9dcd853.

📒 Files selected for processing (1)
  • src/paperscout/__main__.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/paperscout/main.py

📝 Walkthrough

Walkthrough

Two new @runtime_checkable Protocol types — NotifyCallback and OpsAlertFn — are added to protocols.py with explicit __call__ signatures. These replace the untyped/bare-Callable callback parameters in Scheduler.__init__ in monitor.py and throughout __main__.py, including the _on_poll_result callback and several helper functions. Protocol conformance tests and a mypy-rejection fixture are added, and tooling is updated with strict mypy overrides and a pre-commit hook covering the affected modules.

Changes

Callback Protocol Typing

Layer / File(s) Summary
Protocol definitions: NotifyCallback and OpsAlertFn
src/paperscout/protocols.py
Adds TYPE_CHECKING-guarded PollResult import and two new @runtime_checkable Protocol classes with explicit __call__ signatures: NotifyCallback(result: PollResult) -> None and OpsAlertFn(message: str) -> None. Updates module docstring to describe "structural typing contracts".
Scheduler and __main__ type annotations
src/paperscout/monitor.py, src/paperscout/__main__.py
Removes Callable from collections.abc imports in monitor.py; imports NotifyCallback and OpsAlertFn from .protocols; annotates Scheduler.__init__ parameters and instance attributes with those protocol types. In __main__.py, imports PollResult and cast; annotates _on_poll_result with result: PollResult -> None; strengthens type signatures on helper functions (_mq_health_fields, _merge_extra_health_fields, _pool_status, _extra_health_fields) using dict[str, Any]; annotates sources as list[DataSource]; refactors _register_shutdown_signals with typed handler factory functions; passes ops_alert_fn via explicit cast(OpsAlertFn, _ops_alert).
Protocol conformance tests and invalid-callback fixture
tests/test_callback_protocols.py, tests/typing/invalid_callbacks.py
Adds isinstance conformance tests for both protocols, an async Scheduler integration test asserting correct attribute types and empty initial poll_once, and a subprocess mypy test that invokes the invalid-callbacks fixture and asserts a non-zero exit and "Incompatible types" in output. The fixture defines bad_notify(x: str) and bad_ops_alert(n: int) bound to protocol-typed variables to force mypy errors.
Mypy strict overrides, norecursedirs, and pre-commit hook
pyproject.toml, .pre-commit-config.yaml
Adds [[tool.mypy.overrides]] with strict = true for paperscout.protocols and paperscout.monitor; extends norecursedirs to exclude tests/typing. Adds a local pre-commit hook running uv run mypy against protocols.py, monitor.py, and __main__.py with pass_filenames: false.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hop hop, no more bare Callable in sight,
Two Protocols typed with signatures just right.
NotifyCallback carries a PollResult along,
OpsAlertFn keeps ops alerts strong.
mypy now catches mismatched args mid-flight —
The type checker's happy, and so is the rabbit tonight! 🌙

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding typed callback protocols for the two key callback parameters in the system.
Description check ✅ Passed The PR description comprehensively covers all changes, includes a detailed test plan with results, and maps to the acceptance criteria. All required sections are present and complete.
Linked Issues check ✅ Passed The PR successfully addresses all five coding requirements from issue #63: protocols are defined as @runtime_checkable with explicit signatures, all callback parameters are annotated, mypy --strict passes with zero errors, mis-typed callbacks are tested and flagged, and the existing test suite passes without regressions.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #63 requirements: protocol definitions, callback parameter annotations, type-checking configuration, pre-commit hooks, and comprehensive tests. No unrelated changes are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/callback-protocols

Comment @coderabbitai help to get the list of available commands and usage tips.

@henry0816191

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.pre-commit-config.yaml (1)

25-26: ⚡ Quick win

Include src/paperscout/__main__.py in the mypy hook target list.

The callback is wired at the Scheduler(...) call site in src/paperscout/__main__.py; excluding it means pre-commit won’t catch signature drift there.

Suggested diff
-        args: [src/paperscout/protocols.py, src/paperscout/monitor.py]
+        args: [src/paperscout/protocols.py, src/paperscout/monitor.py, src/paperscout/__main__.py]
🤖 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 @.pre-commit-config.yaml around lines 25 - 26, The mypy hook configuration in
the pre-commit args list is missing the __main__ module from its target files.
Currently the args array only includes the protocols and monitor modules. Add
the __main__ module to the args list in the mypy hook configuration so that mypy
will validate the Scheduler call site and catch any signature drift there.
🤖 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 @.pre-commit-config.yaml:
- Around line 25-26: The mypy hook configuration in the pre-commit args list is
missing the __main__ module from its target files. Currently the args array only
includes the protocols and monitor modules. Add the __main__ module to the args
list in the mypy hook configuration so that mypy will validate the Scheduler
call site and catch any signature drift there.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fbb276a0-cf21-40f1-800d-6dd44250ce45

📥 Commits

Reviewing files that changed from the base of the PR and between 8f831b4 and 00fddf5.

📒 Files selected for processing (7)
  • .pre-commit-config.yaml
  • pyproject.toml
  • src/paperscout/__main__.py
  • src/paperscout/monitor.py
  • src/paperscout/protocols.py
  • tests/test_callback_protocols.py
  • tests/typing/invalid_callbacks.py

@wpak-ai wpak-ai merged commit 24423d1 into develop Jun 17, 2026
16 of 17 checks passed
@wpak-ai wpak-ai deleted the feat/callback-protocols branch June 17, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Protocol types for notify_callback and ops_alert_fn

2 participants