diff options
Diffstat (limited to 'app/backends/common.py')
| -rw-r--r-- | app/backends/common.py | 68 |
1 files changed, 43 insertions, 25 deletions
diff --git a/app/backends/common.py b/app/backends/common.py index 10b4ccf..9b6232a 100644 --- a/app/backends/common.py +++ b/app/backends/common.py @@ -102,12 +102,19 @@ def resolve_wav_dir_arg(value: str) -> Path: def find_wav_files(input_dir: Path) -> List[Path]: - """Return the .wav files in INPUT_DIR, sorted alphabetically by name.""" - return sorted( - (path for path in input_dir.iterdir() - if path.is_file() and path.suffix.lower() == ".wav"), - key=lambda path: path.name.lower(), - ) + """Return the .wav files in INPUT_DIR, sorted alphabetically by name. + + A missing or unreadable directory yields [] so callers can treat it + like an empty directory (matching ``count_wavs``). + """ + try: + return sorted( + (path for path in input_dir.iterdir() + if path.is_file() and path.suffix.lower() == ".wav"), + key=lambda path: path.name.lower(), + ) + except OSError: + return [] def count_wavs(directory: Path) -> int: @@ -248,29 +255,38 @@ def server_running(url: str, timeout: float = 0.3) -> bool: return False -def update_config_value(key: str, value: str, +def update_config_value(key: str, value, config_path: Optional[Path] = None) -> bool: - """Rewrite a ``KEY = "value"`` line in app/converter/config.py. - - Only the quoted literal is replaced; surrounding lines and the trailing - comment are preserved. Returns True when the file was changed. Used by - the qwen and faster wizards to keep their API URL / voice / speaker - settings in sync with the converter. + """Set ``KEY`` to VALUE in app/converter/config.py and in memory. + + Only the value of the named assignment changes: indentation and any + trailing comment are preserved. Strings render double-quoted; other + literals (ints, booleans) render bare. After a successful write (or + when the file already holds VALUE) the new value is mirrored onto the + imported ``converter.config`` module, so a wizard's change takes + effect immediately instead of only after the next process start. + Returns True when the file now holds VALUE, False when it could not + be read or written (or KEY has no line in it). """ path = Path(config_path) if config_path is not None else CONFIG_PATH + rendered = f'"{value}"' if isinstance(value, str) else str(value) try: text = path.read_text(encoding="utf-8") + match = re.search( + rf'(?m)^(\s*{re.escape(key)}\s*=\s*)("[^"]*"|\S+)(\s*(?:#.*)?)$', + text) + if match is None: + return False + if match.group(2) != rendered: + text = text[:match.start(2)] + rendered + text[match.end(2):] + path.write_text(text, encoding="utf-8") except OSError: return False - match = re.search(r'(?m)^(\s*' + re.escape(key) + r'\s*=\s*")([^"]*)(")', - text) - if not match or match.group(2) == value: - return False - text = text[:match.start(2)] + value + text[match.end(2):] - try: - path.write_text(text, encoding="utf-8") - except OSError: - return False + # Local import: this module must stay importable before the venv + # exists (backends.envs bootstraps from it), and converter.config is + # stdlib-only constants, safe to load whenever a wizard runs. + from converter import config as _config + setattr(_config, key, value) return True @@ -458,16 +474,18 @@ def git_clone(url: str, target: Path, *, emit=None, cancel=None) -> int: emit=emit, cancel=cancel) -def pip_install(packages: List[str]) -> int: +def pip_install(packages: List[str], *, emit=None, cancel=None) -> int: """pip install PACKAGES into the managed venv (``envs/tts``). Returns exit code. Delegates to ``backends.envs.pip_install`` so backend TTS packages are installed alongside the app requirements in the tool-managed environment rather than into whatever interpreter happens to be running the wizard. - The import is local to avoid a circular import (envs imports this module). + With EMIT given (the in-TUI task view) pip runs with its output streamed + into EMIT; CANCEL aborts it. The import is local to avoid a circular + import (envs imports this module). """ from backends import envs - return envs.pip_install(packages) + return envs.pip_install(packages, emit=emit, cancel=cancel) def pip_uninstall(packages: List[str], *, emit=None) -> int: |
