config/batch rejig

This commit is contained in:
VineFeeder
2025-08-28 12:45:18 +01:00
parent 4232af387c
commit d1428eea9b
5 changed files with 129 additions and 64 deletions
+17 -47
View File
@@ -17,32 +17,16 @@ from rich.console import Console
from .parsing_utils import prettify
import click
import subprocess
from .batchloader import batchload
#from .batchloader import batchload
import pkgutil
#import inspect
from .pretty import catppuccin_mocha
from .config_loader import load_config_with_fallback, get_bool, project_config_path, save_project_config
PAGE_SIZE = 8 # size of beaupy pagination
console = Console()
catppuccin_mocha = {
# Colors based on "CatppuccinMocha" from Gogh themes
"bg": "rgb(30,30,46)",
"text": "rgb(205,214,244)",
"text2": "rgb(162,169,193)", # slightly darker
"black": "rgb(69,71,90)",
"bright_black": "rgb(88,91,112)",
"red": "rgb(243,139,168)",
"green": "rgb(166,227,161)",
"yellow": "rgb(249,226,175)",
"blue": "rgb(137,180,250)",
"pink": "rgb(245,194,231)",
"cyan": "rgb(148,226,213)",
"gray": "rgb(166,173,200)",
"bright_gray": "rgb(186,194,222)",
"dark_gray": "rgb(54,54,84)",
}
"""
@@ -73,18 +57,11 @@ Example usage:
_PKG_NAME = "vinefeeder"
_CFG_NAME = "config.yaml"
def _user_config_dir() -> Path:
# XDG on Linux; AppData\Roaming on Windows; ~/.config on others
if os.name == "nt":
base = os.environ.get("APPDATA") or (Path.home() / "AppData" / "Roaming")
return Path(base) / "VineFeeder"
xdg = os.environ.get("XDG_CONFIG_HOME")
return (Path(xdg) if xdg else Path.home() / ".config") / "vinefeeder"
def _user_config_path() -> Path:
return _user_config_dir() / _CFG_NAME
def load_config_with_fallback() -> tuple[dict, Path | None]:
'''def load_config_with_fallback() -> tuple[dict, Path | None]:
"""
Returns (config_dict, user_path_if_used_or_None).
Prefers user config; falls back to package-bundled default.
@@ -97,15 +74,9 @@ def load_config_with_fallback() -> tuple[dict, Path | None]:
# packaged default
with resources.files(_PKG_NAME).joinpath(_CFG_NAME).open("rb") as f:
data = yaml.safe_load(f) or {}
return data, None
return data, None'''
def save_user_config(cfg: dict) -> Path:
"""Writes config to the user path, creating the directory as needed."""
p = _user_config_path()
p.parent.mkdir(parents=True, exist_ok=True)
with p.open("w", encoding="utf-8") as f:
yaml.safe_dump(cfg, f, default_flow_style=False)
return p
def derive_loader_class_name(service_modname: str) -> str:
"""
@@ -233,7 +204,7 @@ class VineFeeder(QWidget):
# Run Batch Button
self.run_batch_button = QPushButton("Run Batch")
self.run_batch_button.clicked.connect(batchload)
self.run_batch_button.clicked.connect(self._run_batch_button_handler)
self.run_batch_button.setEnabled(False) # Initially disabled
self.style_batch_button(self.run_batch_button)
self.sechighlighted_layout.addWidget(self.run_batch_button)
@@ -268,30 +239,29 @@ class VineFeeder(QWidget):
self.update_batch_file_indicator()
def _run_batch_button_handler(self):
from .batchloader import batchload
batchload()
def toggle_batch_mode(self):
state = self.batch_slider.value() == 1
def toggle_batch_mode(self, value=None):
state = (value == 1) if value is not None else (self.batch_slider.value() == 1)
if state:
self.batch_label.setStyleSheet("color: lightgreen; padding-left: 5px; border: none;")
self.batch_label.setStyleSheet("color: lightgreen; padding-left: 5px; border: none")
else:
self.toggle_dark_mode()
self.run_batch_button.setEnabled(state)
self.update_batch_file_indicator()
# Update config (write to the *user* config location)
# Persist to config
try:
cfg, _ = load_config_with_fallback()
cfg["BATCH_DOWNLOAD"] = state
save_user_config(cfg)
save_project_config(cfg)
except Exception as e:
console.print(f"[{catppuccin_mocha['text2']}][warning] Could not update config.yaml: {e}[/]")
def style_batch_button(self, button):
button.setStyleSheet("""
color: white;
@@ -4,14 +4,12 @@ from beaupy import select, select_multiple
from rich.console import Console
from abc import abstractmethod
import os
import platform
import sys
import time
from .pretty import create_clean_panel
from .pretty import catppuccin_mocha
import yaml
import subprocess
from .__main__ import load_config_with_fallback, save_user_config
from .config_loader import load_config_with_fallback, get_bool
console = Console()
@@ -38,16 +36,15 @@ class BaseLoader:
self.browse_video_list = []
self.category = None
myconfig, _ = load_config_with_fallback()
self.BATCH_DOWNLOAD = myconfig['BATCH_DOWNLOAD']
self.TERMINAL_RESET = myconfig['TERMINAL_RESET']
cfg, _ = load_config_with_fallback()
self.BATCH_DOWNLOAD = bool(cfg.get("BATCH_DOWNLOAD", False))
self.TERMINAL_RESET = bool(cfg.get("TERMINAL_RESET", False))
def reset_terminal(self):
if not self.BATCH_DOWNLOAD:
if self.TERMINAL_RESET:
if os.name == 'nt': # Windows
os.system('cls')
# Optionally, reinitialize ANSI or console buffer here if needed
else: # Unix/Linux/macOS
try:
subprocess.run(['reset'], check=True)
@@ -406,7 +403,7 @@ class BaseLoader:
# clear for next use
time.sleep(1)
if self.TERMINAL_RESET:
if self.TERMINAL_RESET and not self.BATCH_DOWNLOAD:
console.print(f"[{catppuccin_mocha['text2']}]Preparing to reset Terminal[/]")
time.sleep(5)
self.reset_terminal()
@@ -1,9 +1,17 @@
import subprocess
import os
import threading
from rich.console import Console
from .pretty import catppuccin_mocha
import time
from .config_loader import load_config_with_fallback, get_bool
console = Console()
def _batchloader():
cfg, _ = load_config_with_fallback()
TERMINAL_RESET = bool(cfg.get("TERMINAL_RESET", False))
try:
with open('./batch.txt', 'r') as file:
for line in file:
@@ -12,12 +20,25 @@ def _batchloader():
print(line)
subprocess.run(line, shell=True)
print("Batch processing complete.")
yesno = input("delete batch file? (y/n) ")
if yesno.lower() == 'y':
os.remove("./batch.txt")
print("batch.txt deleted.\n\nReady.")
console.print(f"batch.txt deleted.\n\n[{catppuccin_mocha['pink']}]Ready.")
if TERMINAL_RESET:
console.print(f"[{catppuccin_mocha['text2']}]Preparing to reset Terminal[/]")
time.sleep(5)
if os.name == 'nt': # Windows
os.system('cls')
else: # Unix/Linux/macOS
try:
subprocess.run(['reset'], check=True)
console.print(f"[{catppuccin_mocha['pink']}]Ready![/]")
except Exception:
os.system('clear') # fallback if 'reset' is not available
except FileNotFoundError:
@@ -31,5 +52,6 @@ def batchload():
thread.start()
if __name__ == "__main__":
batchload()
@@ -1,5 +1,2 @@
BATCH_DOWNLOAD: False
# Set to True if up/down cursor arrows stop working in the
# Terminal window after envied has downloaded.
TERMINAL_RESET: False
BATCH_DOWNLOAD: true
TERMINAL_RESET: true
@@ -0,0 +1,79 @@
from __future__ import annotations
from pathlib import Path
import os
import yaml
from importlib import resources
from typing import Tuple, Optional, Dict, Any
# Optional: allow a one-line override without changing code.
# If VINEFEEDER_CONFIG is set, we'll use that file.
ENV_VAR = "VINEFEEDER_CONFIG"
PKG_NAME = "vinefeeder"
CFG_NAME = "config.yaml"
def project_config_path() -> Path:
"""
Resolve the config file path with this priority:
1) $VINEFEEDER_CONFIG if set
2) <package_dir>/config.yaml (the repo copy beside the code)
3) importlib.resources fallback (works when installed as a wheel)
"""
# 1) explicit override via env
env_path = os.environ.get(ENV_VAR)
if env_path:
p = Path(env_path).expanduser().resolve()
if p.exists():
return p
# 2) the config.yaml living next to this file (repo/dev layout)
here = Path(__file__).resolve().parent
local_cfg = here / CFG_NAME
if local_cfg.exists():
return local_cfg
# 3) installed package data (site-packages / wheel)
try:
# resources.files returns a Traversable
f = resources.files(PKG_NAME).joinpath(CFG_NAME)
with resources.as_file(f) as p:
if p.exists():
return p
except Exception:
pass
# If we get here, we didnt find it. Return where it *should* be in dev.
return local_cfg
def load_config_with_fallback() -> Tuple[Dict[str, Any], Optional[Path]]:
"""
Load YAML config from the resolved project path.
Returns (config_dict, path_used).
"""
cfg_path = project_config_path()
try:
data = yaml.safe_load(cfg_path.read_text(encoding="utf-8")) or {}
return data, cfg_path
except FileNotFoundError:
# Consistent shape even if missing
return {}, None
def save_project_config(cfg: Dict[str, Any]) -> Path:
"""
Save back to the *project* config path (beside the code).
Useful during development; may fail if running from a read-only install.
"""
p = project_config_path()
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(yaml.safe_dump(cfg, default_flow_style=False), encoding="utf-8")
return p
# Convenience helpers if you want one-liners elsewhere:
def get_bool(key: str, default: bool = False) -> bool:
cfg, _ = load_config_with_fallback()
return bool(cfg.get(key, default))