fix: complete rate limiter integration and report command structure

- Add RequestRateLimiter class to providers/base.py with wait() method
- Integrate rate limiter through enrichment pipeline (enrich_identities_data → _enrich_record_with_fresh_providers → _build_providers → TMDBProvider)
- Add _cmd wrapper functions to commands/report.py for CLI imports
- Fix SeriesIdentity import in reports.py
- Add sidecar file tracking to planner review_context for move operations
- Update tests to match new rate limiter signature

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
windyboy
2026-09-25 14:03:01 +08:00
co-authored by Claude Sonnet 4.5
parent dfa18ed405
commit 0f0636bf19
6 changed files with 85 additions and 11 deletions
+8 -9
View File
@@ -7,7 +7,7 @@ import pytest
from vlm.config import Config
from vlm.enrichment import _build_display_title, _build_providers, enrich_identities_data
from vlm.providers.base import ProviderResult
from vlm.providers.base import ProviderResult, RequestRateLimiter
from vlm.providers.tmdb import TMDBAuthError
@@ -188,7 +188,7 @@ def test_build_providers_rejects_unknown_provider(tmp_path):
)
with pytest.raises(ValueError, match="Unsupported enrichment providers"):
_build_providers(config, request_timeout=3, retries=1)
_build_providers(config, request_timeout=3, retries=1, rate_limiter=RequestRateLimiter(0.25))
def test_refresh_all_clears_stale_enrichment_fields(tmp_path, monkeypatch):
@@ -387,15 +387,14 @@ def test_enrich_respects_max_concurrency_for_uncached_records(tmp_path, monkeypa
thread_ids: set[int] = set()
lock = threading.Lock()
seen_limiters: dict[str, object] = {}
def _fake_enrich(record, media_type, config_obj, request_timeout, retries, rate_limiters=None):
seen_limiters: list[object] = []
def _fake_enrich(record, media_type, config_obj, request_timeout, retries, rate_limiter=None):
with lock:
if rate_limiters is not None and "tmdb" in rate_limiters:
limiter = rate_limiters["tmdb"]
if "limiter" not in seen_limiters:
seen_limiters["limiter"] = limiter
if rate_limiter is not None:
if not seen_limiters:
seen_limiters.append(rate_limiter)
else:
assert limiter is seen_limiters["limiter"]
assert rate_limiter is seen_limiters[0]
time.sleep(0.01)
with lock:
thread_ids.add(threading.get_ident())