mirror of
https://github.com/vinefeeder/TwinVine.git
synced 2026-07-15 18:10:04 +02:00
config/batch rejig
This commit is contained in:
@@ -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,28 +239,27 @@ 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):
|
||||
|
||||
@@ -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:
|
||||
@@ -11,13 +19,26 @@ def _batchloader():
|
||||
if line:
|
||||
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 didn’t 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))
|
||||
Reference in New Issue
Block a user