Files
AV-Watch/avwatch/sources/__init__.py
T

82 lines
3.0 KiB
Python
Raw Normal View History

"""Source registry and dispatch."""
from __future__ import annotations
import logging
from ..models import Item, VersionCheck
from .base import Context, error
from .blackmagic import BlackmagicSource
from .generic import HtmlSource, JsonSource, ManualSource, RssSource
from .github_releases import GithubSource
from .websearch import WebSearchSource
log = logging.getLogger(__name__)
_SOURCES = {
s.kind: s()
for s in (
BlackmagicSource,
GithubSource,
HtmlSource,
JsonSource,
RssSource,
WebSearchSource,
ManualSource,
)
}
KINDS = sorted(_SOURCES)
def check_item(item: Item, ctx: Context) -> VersionCheck:
"""Resolve the latest available version for one item. Never raises --
an adapter blowing up must not abort a 90-item scan."""
# An unconfirmed placeholder must not be searched on. A query built from
# a guessed vendor returns a real, correct-looking version for the WRONG
# product, and the team then acts on it. Silence is the safe answer until
# somebody names the actual model.
if not item.is_confirmed:
return VersionCheck(
item_id=item.id,
status="unconfigured",
detail=("Make/model not confirmed, so no version lookup is "
"attempted -- a guessed vendor would return the wrong "
"product's version. Set status: confirmed once you have "
"filled in the real make and model."),
)
kind = item.source_kind
# Nothing to decide, so nothing worth looking up.
if item.update_class == "do_not_touch":
return VersionCheck(
item_id=item.id,
status="unconfigured",
detail=("Marked do_not_touch, so no version is looked up -- this "
"is a licensed contractor's to update, never ours. "
"Tracked for visibility only."),
)
# Vendor-pushed items update on someone else's schedule. A paid lookup
# buys a version number nobody can act on, so skip it -- but keep free
# sources (GitHub, the Blackmagic feed), which cost nothing and do at
# least tell us a change landed.
if item.update_class == "vendor_pushed" and kind == "websearch":
return VersionCheck(
item_id=item.id,
status="unconfigured",
detail=("Marked vendor_pushed, so the paid version lookup is "
"skipped -- it updates on the supplier's schedule and "
"there is no install decision to inform. Watch for "
"breaking-change notices instead."),
)
source = _SOURCES.get(kind)
if source is None:
return error(item, f"unknown source kind {kind!r}; known: {', '.join(KINDS)}")
try:
return source.check(item, ctx)
except Exception as exc: # noqa: BLE001 - deliberate isolation boundary
log.exception("source %s failed for %s", kind, item.id)
return error(item, f"{type(exc).__name__}: {exc}")