Read/write config files as UTF-8 on Windows (#4)
Path.read_text()/write_text() default to the platform encoding (cp1252 on Windows), which mangles or crashes on UTF-8 files. yt-dlp's video.info.json is UTF-8 and routinely contains non-ASCII bytes, so on Windows the parse raised UnicodeDecodeError, was swallowed by a bare except, and the /watch report came back missing Title/Uploader. - download.py: read video.info.json as UTF-8; log parse failures to stderr instead of swallowing them silently. - whisper.py, setup.py: same UTF-8 fix on .env reads and writes for symmetry across platforms. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -98,14 +98,15 @@ def download_url(url: str, out_dir: Path) -> dict:
|
|||||||
info: dict = {}
|
info: dict = {}
|
||||||
if info_path.exists():
|
if info_path.exists():
|
||||||
try:
|
try:
|
||||||
raw = json.loads(info_path.read_text())
|
raw = json.loads(info_path.read_text(encoding="utf-8"))
|
||||||
info = {
|
info = {
|
||||||
"title": raw.get("title"),
|
"title": raw.get("title"),
|
||||||
"uploader": raw.get("uploader") or raw.get("channel"),
|
"uploader": raw.get("uploader") or raw.get("channel"),
|
||||||
"duration": raw.get("duration"),
|
"duration": raw.get("duration"),
|
||||||
"url": raw.get("webpage_url") or url,
|
"url": raw.get("webpage_url") or url,
|
||||||
}
|
}
|
||||||
except Exception:
|
except Exception as exc:
|
||||||
|
print(f"[watch] info.json parse failed: {exc}", file=sys.stderr)
|
||||||
info = {"url": url}
|
info = {"url": url}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+5
-5
@@ -79,7 +79,7 @@ def _read_env_key(name: str) -> str | None:
|
|||||||
return None
|
return None
|
||||||
_check_file_permissions(CONFIG_FILE)
|
_check_file_permissions(CONFIG_FILE)
|
||||||
try:
|
try:
|
||||||
for line in CONFIG_FILE.read_text().splitlines():
|
for line in CONFIG_FILE.read_text(encoding="utf-8").splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line or line.startswith("#") or "=" not in line:
|
if not line or line.startswith("#") or "=" not in line:
|
||||||
continue
|
continue
|
||||||
@@ -113,7 +113,7 @@ def _scaffold_env() -> bool:
|
|||||||
if CONFIG_FILE.exists():
|
if CONFIG_FILE.exists():
|
||||||
return False
|
return False
|
||||||
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
CONFIG_FILE.write_text(ENV_TEMPLATE)
|
CONFIG_FILE.write_text(ENV_TEMPLATE, encoding="utf-8")
|
||||||
try:
|
try:
|
||||||
CONFIG_FILE.chmod(0o600)
|
CONFIG_FILE.chmod(0o600)
|
||||||
except OSError:
|
except OSError:
|
||||||
@@ -130,15 +130,15 @@ def _write_setup_complete() -> None:
|
|||||||
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
existing = ""
|
existing = ""
|
||||||
if CONFIG_FILE.exists():
|
if CONFIG_FILE.exists():
|
||||||
existing = CONFIG_FILE.read_text()
|
existing = CONFIG_FILE.read_text(encoding="utf-8")
|
||||||
for line in existing.splitlines():
|
for line in existing.splitlines():
|
||||||
if line.strip().startswith("SETUP_COMPLETE="):
|
if line.strip().startswith("SETUP_COMPLETE="):
|
||||||
return
|
return
|
||||||
if existing and not existing.endswith("\n"):
|
if existing and not existing.endswith("\n"):
|
||||||
existing += "\n"
|
existing += "\n"
|
||||||
CONFIG_FILE.write_text(existing + "SETUP_COMPLETE=true\n")
|
CONFIG_FILE.write_text(existing + "SETUP_COMPLETE=true\n", encoding="utf-8")
|
||||||
else:
|
else:
|
||||||
CONFIG_FILE.write_text(ENV_TEMPLATE + "\nSETUP_COMPLETE=true\n")
|
CONFIG_FILE.write_text(ENV_TEMPLATE + "\nSETUP_COMPLETE=true\n", encoding="utf-8")
|
||||||
try:
|
try:
|
||||||
CONFIG_FILE.chmod(0o600)
|
CONFIG_FILE.chmod(0o600)
|
||||||
except OSError:
|
except OSError:
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ def load_api_key(preferred: str | None = None) -> tuple[str, str] | tuple[None,
|
|||||||
if not path.exists():
|
if not path.exists():
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
for line in path.read_text().splitlines():
|
for line in path.read_text(encoding="utf-8").splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line or line.startswith("#") or "=" not in line:
|
if not line or line.startswith("#") or "=" not in line:
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user