"""Every Protocol, with both of its implementations, checked by mypy. These functions have no assertions and cannot fail at runtime — the check happens under `mypy --strict`. If FakeProvisioner drifts from Provisioner (a renamed parameter, a changed return type), the type-check fails here rather than the fake quietly diverging from the real adapter and the worker's fast tests proving nothing about production. The test bodies exist so pytest runs the imports too: a Protocol satisfied statically but broken at import time is still broken. """ from __future__ import annotations from pathlib import Path from svcforge_core.adapters.clock import Clock, SystemClock from svcforge_core.adapters.helm import HelmProvisioner, Provisioner from svcforge_core.adapters.notify import LogNotifier, Notifier, WebhookNotifier from svcforge_core.adapters.redis import ( IdempotencyStore, IdempotencyStoreProto, InstanceCache, InstanceCacheProto, RateLimiter, RateLimiterProto, make_redis, ) from svcforge_core.settings import Settings from tests.fakes import ( FakeClock, FakeIdempotencyStore, FakeInstanceCache, FakeNotifier, FakeProvisioner, FakeRateLimiter, ) def take(p: Provisioner) -> None: """Accepts anything structurally a Provisioner. The whole assertion is the annotation.""" def take_clock(c: Clock) -> None: ... def take_notifier(n: Notifier) -> None: ... def test_provisioner_implementations_conform() -> None: take(HelmProvisioner(kubeconfig=Path("/dev/null"))) take(FakeProvisioner()) print("ok") def test_clock_implementations_conform() -> None: from datetime import UTC, datetime take_clock(SystemClock()) take_clock(FakeClock(start=datetime(2026, 1, 1, tzinfo=UTC))) print("ok") def test_notifier_implementations_conform() -> None: take_notifier(LogNotifier()) take_notifier(WebhookNotifier(url="https://example.invalid/hook")) take_notifier(FakeNotifier()) print("ok") def take_limiter(rl: RateLimiterProto) -> None: ... def take_idempotency(store: IdempotencyStoreProto) -> None: ... def take_cache(c: InstanceCacheProto) -> None: ... def test_redis_implementations_conform() -> None: """A client at a closed port is still a Redis. Nothing here connects — no commands billed. That is the module's thesis restated as a fixture, rather than a trick to keep the test fast. Every one of these classes has to be constructible and callable with Redis unreachable, because that is the state they are designed for. """ from datetime import UTC, datetime settings = Settings( # pydantic parses these strings into PostgresDsn/RedisDsn at runtime; the # annotation names the parsed type, so the ignores sit on the arguments. pg_dsn="postgresql://unused:unused@127.0.0.1:5432/unused", # type: ignore[arg-type] redis_dsn="redis://127.0.0.1:1/0", # type: ignore[arg-type] ) r = make_redis(settings) assert r is not None take_limiter(RateLimiter(r, limit=10, window_s=60)) take_limiter(FakeRateLimiter(10, 60, FakeClock(start=datetime(2026, 1, 1, tzinfo=UTC)))) take_idempotency(IdempotencyStore(r)) take_idempotency(FakeIdempotencyStore()) take_cache(InstanceCache(r)) take_cache(FakeInstanceCache()) # redis_dsn=None EXPLICITLY. Omitting it does not mean "unset": pydantic-settings # reads SVCFORGE_REDIS_DSN from the environment, so on any machine that has the real # DSN exported this assertion sees a live Upstash client and fails — a green test that # depends on your shell being empty is not a test. assert make_redis(Settings(pg_dsn=settings.pg_dsn, redis_dsn=None)) is None print("ok")