53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
"""Source protocol shared by every version adapter."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Protocol
|
|
|
|
from ..http import HttpClient
|
|
from ..models import Item, VersionCheck
|
|
|
|
|
|
@dataclass
|
|
class Context:
|
|
"""Passed to every source. ``scratch`` lets an adapter fetch one shared
|
|
payload (a vendor-wide downloads feed, say) and reuse it across the dozens
|
|
of items that resolve from it."""
|
|
|
|
http: HttpClient
|
|
scratch: dict[str, Any] = field(default_factory=dict)
|
|
|
|
def memo(self, key: str, factory):
|
|
if key not in self.scratch:
|
|
self.scratch[key] = factory()
|
|
return self.scratch[key]
|
|
|
|
|
|
class Source(Protocol):
|
|
kind: str
|
|
|
|
def check(self, item: Item, ctx: Context) -> VersionCheck:
|
|
...
|
|
|
|
|
|
def error(item: Item, detail: str) -> VersionCheck:
|
|
return VersionCheck(item_id=item.id, status="error", detail=detail)
|
|
|
|
|
|
def manual(item: Item, detail: str = "No machine-readable feed; check by hand.") -> VersionCheck:
|
|
return VersionCheck(item_id=item.id, status="manual", detail=detail)
|
|
|
|
|
|
def unconfigured(item: Item, detail: str) -> VersionCheck:
|
|
"""AVWatch knows how to track this item, but the capability it needs is
|
|
not switched on.
|
|
|
|
Kept distinct from ``manual`` on purpose. "There is no firmware for this
|
|
passive splitter" and "your API key is missing so 60 items could not be
|
|
looked up" are completely different problems, and collapsing them into one
|
|
'check by hand' list makes a configuration gap look like the gear was
|
|
never tracked at all.
|
|
"""
|
|
return VersionCheck(item_id=item.id, status="unconfigured", detail=detail)
|