-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest_callback_protocols.py
More file actions
85 lines (65 loc) · 2.64 KB
/
Copy pathtest_callback_protocols.py
File metadata and controls
85 lines (65 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""Tests for NotifyCallback and OpsAlertFn protocol conformance."""
from __future__ import annotations
import os
import subprocess
import sys
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock
from paperscout.models import CycleResult, CycleStatus, IndexRefreshResult
from paperscout.monitor import DiffResult, PollResult, Scheduler
from paperscout.protocols import SOURCE_ISO_PROBE, SOURCE_WG21_INDEX, NotifyCallback, OpsAlertFn
from paperscout.sources import ISOProber, WG21Index
from paperscout.storage import ProbeState, UserWatchlist
from tests.conftest import make_test_settings
_REPO_ROOT = Path(__file__).resolve().parents[1]
_INVALID_CALLBACKS = _REPO_ROOT / "tests" / "typing" / "invalid_callbacks.py"
def test_notify_callback_protocol_isinstance() -> None:
def ok(result: PollResult) -> None:
del result
assert isinstance(ok, NotifyCallback)
def test_ops_alert_fn_protocol_isinstance() -> None:
def ok(message: str) -> None:
del message
assert isinstance(ok, OpsAlertFn)
async def test_scheduler_accepts_protocol_callbacks(fake_pool) -> None:
notified: list[PollResult] = []
alerts: list[str] = []
def on_notify(result: PollResult) -> None:
notified.append(result)
def on_ops_alert(message: str) -> None:
alerts.append(message)
wg21 = MagicMock(spec=WG21Index)
wg21.source_id = SOURCE_WG21_INDEX
wg21.fetch = AsyncMock(return_value=IndexRefreshResult({}, stale=False))
wg21.diff = MagicMock(return_value=DiffResult([], []))
iso = MagicMock(spec=ISOProber)
iso.source_id = SOURCE_ISO_PROBE
iso.fetch = AsyncMock(return_value=CycleResult(CycleStatus.EMPTY))
iso.diff = MagicMock(return_value=[])
iso.snapshot_stats = MagicMock(return_value={})
scheduler = Scheduler(
sources=[wg21, iso],
user_watchlist=MagicMock(spec=UserWatchlist),
state=ProbeState(fake_pool),
cfg=make_test_settings(),
notify_callback=on_notify,
ops_alert_fn=on_ops_alert,
)
assert isinstance(scheduler.notify_callback, NotifyCallback)
assert isinstance(scheduler.ops_alert_fn, OpsAlertFn)
wg21.papers = {}
await scheduler.poll_once()
assert notified == []
def test_mypy_rejects_invalid_callbacks() -> None:
env = {**os.environ, "MYPYPATH": str(_REPO_ROOT / "src")}
result = subprocess.run(
[sys.executable, "-m", "mypy", str(_INVALID_CALLBACKS)],
cwd=_REPO_ROOT,
capture_output=True,
text=True,
check=False,
env=env,
)
assert result.returncode != 0
combined = result.stdout + result.stderr
assert "Incompatible types" in combined