HTTP: prefer pip-system-certs/certifi_win32 bundle; use init-time verify in retries; add tests

This commit is contained in:
2026-01-05 13:09:24 -08:00
parent 1f765cffda
commit ac1d1d634f
12 changed files with 19424 additions and 2371 deletions

View File

@@ -5,7 +5,7 @@ starting point for implementing a full Vimm (vimm.net) provider.
It prefers server-rendered HTML parsing via lxml and uses the repo's
`HTTPClient` helper for robust HTTP calls (timeouts/retries).
Selectors in `search()` are intentionally permissive heuristics; update the
XPaths to match the real site HTML when you have an actual fixture.
"""
@@ -78,6 +78,11 @@ class Vimm(Provider):
resp = client.get(url)
content = resp.content
except Exception as exc:
# Log and return empty results on failure. The HTTP client will
# already attempt a certifi-based retry in common certificate
# verification failure cases; if you still see cert errors, install
# the `certifi` package or configure SSL_CERT_FILE to point at a
# valid CA bundle.
log(f"[vimm] HTTP fetch failed: {exc}", file=sys.stderr)
return []
@@ -183,3 +188,104 @@ class Vimm(Provider):
continue
return results[: max(0, int(limit))]
# Bridge into the ResultTable provider registry so vimm results can be rendered
# with the new provider/table/select API.
try:
from SYS.result_table_adapters import register_provider
from SYS.result_table_api import ResultModel
from SYS.result_table_api import title_column, ext_column, metadata_column
def _convert_search_result_to_model(sr):
try:
if hasattr(sr, "to_dict"):
d = sr.to_dict()
elif isinstance(sr, dict):
d = sr
else:
d = {
"title": getattr(sr, "title", str(sr)),
"path": getattr(sr, "path", None),
"size_bytes": getattr(sr, "size_bytes", None),
"columns": getattr(sr, "columns", None),
"full_metadata": getattr(sr, "full_metadata", None),
}
except Exception:
d = {"title": getattr(sr, "title", str(sr))}
title = d.get("title") or ""
path = d.get("path") or None
size = d.get("size_bytes") or None
ext = None
try:
if path:
from pathlib import Path
suf = Path(str(path)).suffix
if suf:
ext = suf.lstrip(".")
except Exception:
ext = None
metadata = d.get("full_metadata") or d.get("metadata") or {}
return ResultModel(
title=str(title),
path=str(path) if path is not None else None,
ext=str(ext) if ext is not None else None,
size_bytes=int(size) if size is not None else None,
metadata=metadata or {},
source="vimm",
)
def _adapter(items):
for it in items:
yield _convert_search_result_to_model(it)
def _columns_factory(rows):
cols = [title_column()]
if any(getattr(r, "ext", None) for r in rows):
cols.append(ext_column())
if any(getattr(r, "size_bytes", None) for r in rows):
cols.append(metadata_column("size", "Size"))
# Add up to 2 discovered metadata keys from rows
seen = []
for r in rows:
for k in (r.metadata or {}).keys():
if k in ("name", "title", "path"):
continue
if k not in seen:
seen.append(k)
if len(seen) >= 2:
break
if len(seen) >= 2:
break
for k in seen:
cols.append(metadata_column(k))
return cols
def _selection_fn(row):
if getattr(row, "path", None):
return ["-path", row.path]
return ["-title", row.title or ""]
SAMPLE_ITEMS = [
{"title": "Room of Awe", "path": "sample/Room of Awe", "ext": "zip", "size_bytes": 1024 * 1024 * 12, "full_metadata": {"platform": "PC"}},
{"title": "Song of Joy", "path": "sample/Song of Joy.mp3", "ext": "mp3", "size_bytes": 5120000, "full_metadata": {"platform": "PC"}},
{"title": "Cover Image", "path": "sample/Cover.jpg", "ext": "jpg", "size_bytes": 20480, "full_metadata": {}},
]
try:
register_provider(
"vimm",
_adapter,
columns=_columns_factory,
selection_fn=_selection_fn,
metadata={"description": "Vimm provider bridge (ProviderCore -> ResultTable API)"},
)
except Exception:
# Non-fatal: registration is best-effort
pass
except Exception:
pass