refactor: phase 1 - testability improvements

- Add Config dataclass with get_config()/set_config() for injection
- Add Config.from_args() for CLI argument parsing (testable)
- Add platform font path detection (Darwin/Linux)
- Bound translate cache with @lru_cache(maxsize=500)
- Add fixtures for external dependencies (network, feeds, config)
- Add 15 tests for Config class, from_args, and platform detection

This enables testability by:
- Allowing config injection instead of global mutable state
- Supporting custom argv in from_args() for testing
- Providing reusable fixtures for mocking network/filesystem
- Preventing unbounded memory growth in translation cache

Fixes: _arg_value/_arg_int not accepting custom argv
This commit is contained in:
2026-03-15 15:44:39 -07:00
committed by Gene Johnson
parent a27c09f58e
commit b1280dc193
4 changed files with 529 additions and 22 deletions

View File

@@ -7,26 +7,16 @@ import json
import re
import urllib.parse
import urllib.request
from functools import lru_cache
from engine.sources import LOCATION_LANGS
_TRANSLATE_CACHE = {}
TRANSLATE_CACHE_SIZE = 500
def detect_location_language(title):
"""Detect if headline mentions a location, return target language."""
title_lower = title.lower()
for pattern, lang in LOCATION_LANGS.items():
if re.search(pattern, title_lower):
return lang
return None
def translate_headline(title, target_lang):
"""Translate headline via Google Translate API (zero dependencies)."""
key = (title, target_lang)
if key in _TRANSLATE_CACHE:
return _TRANSLATE_CACHE[key]
@lru_cache(maxsize=TRANSLATE_CACHE_SIZE)
def _translate_cached(title: str, target_lang: str) -> str:
"""Cached translation implementation."""
try:
q = urllib.parse.quote(title)
url = (
@@ -39,5 +29,18 @@ def translate_headline(title, target_lang):
result = "".join(p[0] for p in data[0] if p[0]) or title
except Exception:
result = title
_TRANSLATE_CACHE[key] = result
return result
def detect_location_language(title):
"""Detect if headline mentions a location, return target language."""
title_lower = title.lower()
for pattern, lang in LOCATION_LANGS.items():
if re.search(pattern, title_lower):
return lang
return None
def translate_headline(title: str, target_lang: str) -> str:
"""Translate headline via Google Translate API (zero dependencies)."""
return _translate_cached(title, target_lang)