update refactoring and add new features

This commit is contained in:
2026-07-24 20:55:58 -07:00
parent 7f12bc7f40
commit 03fbbbcf28
69 changed files with 16332 additions and 17600 deletions
+51 -35
View File
@@ -1,5 +1,6 @@
# pyright: reportUnusedFunction=false
from typing import Any, Dict, Sequence, List, Optional
import atexit
import os
import sys
import json
@@ -21,6 +22,8 @@ from SYS.config import get_hydrus_access_key, get_hydrus_url, resolve_cookies_pa
_NOTES_PREFETCH_INFLIGHT: set[str] = set()
_NOTES_PREFETCH_LOCK = threading.Lock()
_PREFETCH_THREADS: set[threading.Thread] = set()
_PREFETCH_THREADS_LOCK = threading.Lock()
_PLAYLIST_STORE_CACHE: Optional[Dict[str, Any]] = None
_PLAYLIST_STORE_MTIME_NS: Optional[int] = None
_SHA256_RE = re.compile(r"[0-9a-f]{64}")
@@ -347,21 +350,20 @@ def _get_latest_mpv_run_marker(log_db_path: str) -> Optional[tuple[str, str]]:
try:
import sqlite3
conn = sqlite3.connect(log_db_path, timeout=5.0)
cur = conn.cursor()
cur.execute(
(
"SELECT timestamp, message FROM logs "
"WHERE module = 'mpv' AND ("
"message LIKE '[helper] version=% started ipc=%' "
"OR message LIKE 'medeia lua loaded version=%'"
") "
"ORDER BY timestamp DESC LIMIT 1"
with sqlite3.connect(log_db_path, timeout=5.0) as conn:
cur = conn.cursor()
cur.execute(
(
"SELECT timestamp, message FROM logs "
"WHERE module = 'mpv' AND ("
"message LIKE '[helper] version=% started ipc=%' "
"OR message LIKE 'medeia lua loaded version=%'"
") "
"ORDER BY timestamp DESC LIMIT 1"
)
)
)
row = cur.fetchone()
cur.close()
conn.close()
row = cur.fetchone()
cur.close()
if row and row[0]:
return str(row[0]), str(row[1] or "")
except Exception:
@@ -381,26 +383,25 @@ def _get_mpv_logs_for_latest_run(
try:
import sqlite3
conn = sqlite3.connect(log_db_path, timeout=5.0)
cur = conn.cursor()
query = "SELECT timestamp, level, module, message FROM logs WHERE module = 'mpv'"
params: List[str] = []
if marker_ts:
query += " AND timestamp >= ?"
params.append(marker_ts)
else:
cutoff = (datetime.utcnow() - timedelta(hours=6)).strftime("%Y-%m-%d %H:%M:%S")
query += " AND timestamp >= ?"
params.append(cutoff)
if log_filter_text:
query += " AND LOWER(message) LIKE ?"
params.append(f"%{log_filter_text.lower()}%")
query += " ORDER BY timestamp DESC LIMIT ?"
params.append(str(max(1, int(limit))))
cur.execute(query, tuple(params))
rows = cur.fetchall()
cur.close()
conn.close()
with sqlite3.connect(log_db_path, timeout=5.0) as conn:
cur = conn.cursor()
query = "SELECT timestamp, level, module, message FROM logs WHERE module = 'mpv'"
params: List[str] = []
if marker_ts:
query += " AND timestamp >= ?"
params.append(marker_ts)
else:
cutoff = (datetime.utcnow() - timedelta(hours=6)).strftime("%Y-%m-%d %H:%M:%S")
query += " AND timestamp >= ?"
params.append(cutoff)
if log_filter_text:
query += " AND LOWER(message) LIKE ?"
params.append(f"%{log_filter_text.lower()}%")
query += " ORDER BY timestamp DESC LIMIT ?"
params.append(str(max(1, int(limit))))
cur.execute(query, tuple(params))
rows = cur.fetchall()
cur.close()
rows.reverse()
return marker_ts, marker_msg, rows
except Exception:
@@ -849,11 +850,26 @@ def _prefetch_notes_async(
thread = threading.Thread(
target=_worker,
name=f"mpv-notes-prefetch-{file_hash[:8]}",
daemon=True,
)
with _PREFETCH_THREADS_LOCK:
_PREFETCH_THREADS.add(thread)
thread.start()
def _shutdown_prefetch_threads() -> None:
with _PREFETCH_THREADS_LOCK:
threads = list(_PREFETCH_THREADS)
_PREFETCH_THREADS.clear()
for t in threads:
try:
t.join(timeout=1.0)
except Exception:
pass
atexit.register(_shutdown_prefetch_threads)
def _schedule_notes_prefetch(items: Sequence[Any], config: Optional[Dict[str, Any]]) -> None:
limit = _get_lyric_prefetch_limit(config)
if limit <= 0:
+12 -8
View File
@@ -14,11 +14,6 @@ def _repo_root() -> Path:
return package_dir.parent
REPO_ROOT = _repo_root()
if str(REPO_ROOT) not in sys.path:
sys.path.insert(0, str(REPO_ROOT))
def main(argv: list[str] | None = None) -> int:
args = list(sys.argv[1:] if argv is None else argv)
if not args:
@@ -35,10 +30,19 @@ def main(argv: list[str] | None = None) -> int:
url = str(args[0] or "").strip()
captured_stdout = io.StringIO()
captured_stderr = io.StringIO()
with contextlib.redirect_stdout(captured_stdout), contextlib.redirect_stderr(captured_stderr):
from plugins.mpv.pipeline_helper import _run_op
payload = _run_op("ytdlp-formats", {"url": url})
_root_str = str(_repo_root())
_path_added = _root_str not in sys.path
if _path_added:
sys.path.insert(0, _root_str)
try:
with contextlib.redirect_stdout(captured_stdout), contextlib.redirect_stderr(captured_stderr):
from plugins.mpv.pipeline_helper import _run_op
payload = _run_op("ytdlp-formats", {"url": url})
finally:
if _path_added:
sys.path.remove(_root_str)
noisy_stdout = captured_stdout.getvalue().strip()
noisy_stderr = captured_stderr.getvalue().strip()
+2 -4
View File
@@ -7,6 +7,7 @@ This is the central hub for all Python-mpv IPC communication. The Lua script
should use the Python CLI, which uses this module to manage mpv connections.
"""
import atexit
import ctypes
import json
import os
@@ -901,6 +902,7 @@ class MPVIPCClient:
self.is_windows = platform.system() == "Windows"
self.silent = bool(silent)
self._recv_buffer: bytes = b""
atexit.register(self.disconnect)
def _write_payload(self, payload: str) -> None:
if not self.sock:
@@ -1229,10 +1231,6 @@ class MPVIPCClient:
self.sock = None
self._recv_buffer = b""
def __del__(self) -> None:
"""Cleanup on object destruction."""
self.disconnect()
def __enter__(self):
"""Context manager entry."""
self.connect()
+16 -11
View File
@@ -61,17 +61,22 @@ def _runtime_config_root() -> Path:
# Make repo-local packages importable even when mpv starts us from another cwd.
_ROOT = str(_repo_root())
if _ROOT not in sys.path:
sys.path.insert(0, _ROOT)
from plugins.mpv.mpv_ipc import MPVIPCClient, _windows_kill_pids, _windows_hidden_subprocess_kwargs, _windows_list_mpv_pids # noqa: E402
from SYS.config import load_config, reload_config # noqa: E402
from SYS.logger import set_debug, debug, set_thread_stream # noqa: E402
from SYS.repl_queue import enqueue_repl_command, repl_state_is_alive # noqa: E402
from SYS.utils import format_bytes # noqa: E402
from PluginCore.registry import get_plugin, get_plugin_class # noqa: E402
from plugins.ytdlp.tooling import get_display_format_id, get_selection_format_id # noqa: E402
_root_str = str(_repo_root())
_path_added = _root_str not in sys.path
if _path_added:
sys.path.insert(0, _root_str)
try:
from plugins.mpv.mpv_ipc import MPVIPCClient, _windows_kill_pids, _windows_hidden_subprocess_kwargs, _windows_list_mpv_pids # noqa: E402
from SYS.config import load_config, reload_config # noqa: E402
from SYS.logger import set_debug, debug, set_thread_stream # noqa: E402
from SYS.repl_queue import enqueue_repl_command, repl_state_is_alive # noqa: E402
from SYS.utils import format_bytes # noqa: E402
from PluginCore.registry import get_plugin, get_plugin_class # noqa: E402
from plugins.ytdlp.tooling import get_display_format_id, get_selection_format_id # noqa: E402
finally:
if _path_added:
sys.path.remove(_root_str)
del _root_str, _path_added
REQUEST_PROP = "user-data/medeia-pipeline-request"
RESPONSE_PROP = "user-data/medeia-pipeline-response"