Add separate logs per run and remove retry functionality that was making things more expensive

This commit is contained in:
dazedanon 2025-10-26 11:44:08 -05:00
parent 7bcc1b4e7b
commit 7ef200c13a
5 changed files with 123 additions and 25 deletions

View file

@ -179,7 +179,6 @@ if errorlevel 1 (
echo.
echo GUI closed successfully.
pause
:: End of main flow - prevent falling through into subroutines below
goto :eof

View file

@ -73,7 +73,12 @@ class LogViewer(QWidget):
self._tail_timer.timeout.connect(self._poll_tail)
self._tail_interval = 300 # ms
self._tail_f = None
self._tail_path = Path("log/translationHistory.txt")
# Default: prefer the most recent file in log/history, else legacy path
try:
latest = self._latest_history_file()
except Exception:
latest = None
self._tail_path = latest or Path("log/translationHistory.txt")
def toggle_auto_refresh(self, enabled):
"""Toggle auto-refresh functionality."""
@ -124,8 +129,9 @@ class LogViewer(QWidget):
def start_tail(self, file_path: str | Path = None, interval_ms: int = None):
"""Start tailing the given log file and append new lines as they arrive.
By default tails `log/translationHistory.txt`. Seeks to the end so
only new lines after this call are shown.
By default tails the most recent file in `log/history/` (if present),
otherwise falls back to `log/translationHistory.txt`.
Seeks to the end so only new lines after this call are shown.
"""
if file_path:
self._tail_path = Path(file_path)
@ -213,3 +219,16 @@ class LogViewer(QWidget):
"""Handle widget hide event - pause refresh to save resources."""
super().hideEvent(event)
# No-op for simplified viewer
def _latest_history_file(self):
"""Return the most recent file in log/history or None if not found."""
try:
hist_dir = Path("log") / "history"
# Ensure history directory exists so callers can rely on it
hist_dir.mkdir(parents=True, exist_ok=True)
files = [p for p in hist_dir.iterdir() if p.is_file()]
if not files:
return None
return max(files, key=lambda p: p.stat().st_mtime)
except Exception:
return None

View file

@ -6,6 +6,7 @@ Simple file management and translation execution with console log display.
"""
import os
import datetime
import subprocess
import threading
import sys
@ -1549,13 +1550,53 @@ class TranslationTab(QWidget):
self.translation_worker.progress_signal.connect(self.update_file_progress)
self.translation_worker.item_progress_signal.connect(self.update_item_progress)
self.translation_worker.finished_signal.connect(self.on_translation_finished)
# Clear and start tailing the translation history so only new
# lines are shown in the right-hand log panel.
# Prepare a per-run log file in log/history and start tailing it so
# the right-hand log panel shows only this run's new lines.
try:
history_dir = self.project_root / 'log' / 'history'
history_dir.mkdir(parents=True, exist_ok=True)
# Use timestamp (safe filename) for sorting
fname = datetime.datetime.now().strftime('translationHistory_%Y%m%d_%H%M%S.txt')
run_log_path = history_dir / fname
# Create/touch the file so tailer can open and seek to end
run_log_path.touch(exist_ok=True)
# Export env var so subprocess workers inherit the path
try:
os.environ['TRANSLATION_RUN_LOG'] = str(run_log_path)
except Exception:
pass
# Try to create a hard link at legacy location so modules that
# still write to log/translationHistory.txt end up in this file.
legacy = self.project_root / 'log' / 'translationHistory.txt'
try:
# Remove any existing legacy file and create hard link
if legacy.exists():
try:
legacy.unlink()
except Exception:
pass
os.link(str(run_log_path), str(legacy))
except Exception:
# If hard link fails (Windows permissions or cross-device),
# fallback to ensuring the legacy file exists but do not fail.
try:
legacy.parent.mkdir(parents=True, exist_ok=True)
legacy.touch(exist_ok=True)
except Exception:
pass
# Clear UI log and start tailing the per-run file
self.translation_log_viewer.clear_log()
self.translation_log_viewer.start_tail(self.project_root / 'log' / 'translationHistory.txt')
self.translation_log_viewer.start_tail(run_log_path)
except Exception:
pass
# Fallback to legacy file if anything goes wrong
try:
self.translation_log_viewer.clear_log()
self.translation_log_viewer.start_tail(self.project_root / 'log' / 'translationHistory.txt')
except Exception:
pass
# Start the worker
self.translation_worker.start()

View file

@ -1,6 +1,8 @@
import sys
import os
import traceback
import datetime
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
from colorama import Fore
from tqdm import tqdm
@ -132,6 +134,37 @@ files to translate are in the /files folder and that you picked the right game e
setSpeakerParseMode(True)
# Open File (Threads) - recursively walk 'files' and preserve directory structure
# Prepare per-run log file so CLI runs also write to a run-specific history file
try:
hist_dir = Path("log") / "history"
hist_dir.mkdir(parents=True, exist_ok=True)
fname = datetime.datetime.now().strftime("translationHistory_%Y%m%d_%H%M%S.txt")
run_log_path = hist_dir / fname
run_log_path.touch(exist_ok=True)
# Export env var so other modules/util functions pick it up
try:
os.environ['TRANSLATION_RUN_LOG'] = str(run_log_path)
except Exception:
pass
# Try to create a hard link from legacy path to this run file for compatibility
legacy = Path("log") / "translationHistory.txt"
try:
if legacy.exists():
try:
legacy.unlink()
except Exception:
pass
os.link(str(run_log_path), str(legacy))
except Exception:
# Fallback: ensure legacy file exists so modules writing to it won't fail
try:
legacy.parent.mkdir(parents=True, exist_ok=True)
legacy.touch(exist_ok=True)
except Exception:
pass
except Exception:
pass
with ThreadPoolExecutor(max_workers=THREADS) as executor:
futures = []
files_root = "files"

View file

@ -611,7 +611,23 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
"""
if not text:
return [text, [0, 0]]
# If a per-run log file is specified via environment variable, prefer it.
run_log = os.getenv("TRANSLATION_RUN_LOG")
if run_log:
# Make sure parent dir exists
try:
Path(run_log).parent.mkdir(parents=True, exist_ok=True)
except Exception:
pass
config.logFilePath = run_log
# Ensure log directory exists for the configured path
try:
Path(config.logFilePath).parent.mkdir(parents=True, exist_ok=True)
except Exception:
pass
with open(config.logFilePath, "a+", encoding="utf-8") as logFile:
totalTokens = [0, 0]
@ -693,27 +709,17 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
if cleaned_text:
if isinstance(tItem, list):
extracted = extractTranslation(cleaned_text, True, pbar)
# Check 1: Mismatch in length
# Check 1: Mismatch in length -> still a hard failure
if extracted is None or len(tItem) != len(extracted):
is_valid = False
# Check 2: Untranslated content
else:
# Set translations first (line count matches)
# Set translations (line count matches)
final_translations = extracted
# Then check for untranslated content as a warning, not a blocker
for line in extracted:
if re.search(config.langRegex, str(line)):
is_valid = False
break
else:
# Check for untranslated content in single string
if re.search(config.langRegex, cleaned_text):
is_valid = False
else:
final_translations = cleaned_text.replace("Placeholder Text", "")
# Single string: accept output even if it contains characters
# matching langRegex (allow names or untranslated tokens).
final_translations = cleaned_text.replace("Placeholder Text", "")
else:
is_valid = False
if pbar: pbar.write(f"AI Refused: {tItem}\n")