lksjalk
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled

This commit is contained in:
nose
2025-12-24 05:10:07 -08:00
parent 8e3cf7594e
commit 892fe1cb0a
3 changed files with 55 additions and 70 deletions

View File

@@ -1,8 +1,5 @@
from __future__ import annotations from __future__ import annotations
import json
import shutil
import subprocess
import sys import sys
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
@@ -11,7 +8,7 @@ from SYS.logger import log
class YouTube(Provider): class YouTube(Provider):
"""Search provider for YouTube using yt-dlp.""" """Search provider for YouTube using the yt_dlp Python package."""
def search( def search(
self, self,
@@ -20,75 +17,56 @@ class YouTube(Provider):
filters: Optional[Dict[str, Any]] = None, filters: Optional[Dict[str, Any]] = None,
**kwargs: Any, **kwargs: Any,
) -> List[SearchResult]: ) -> List[SearchResult]:
ytdlp_path = shutil.which("yt-dlp") # Use the yt_dlp Python module (installed via requirements.txt).
if not ytdlp_path:
log("[youtube] yt-dlp not found in PATH", file=sys.stderr)
return []
search_query = f"ytsearch{limit}:{query}"
cmd = [ytdlp_path, "--dump-json", "--flat-playlist", "--no-warnings", search_query]
try: try:
process = subprocess.run( import yt_dlp # type: ignore
cmd, ydl_opts: Dict[str, Any] = {"quiet": True, "skip_download": True, "extract_flat": True}
capture_output=True, with yt_dlp.YoutubeDL(ydl_opts) as ydl: # type: ignore[arg-type]
text=True, search_query = f"ytsearch{limit}:{query}"
encoding="utf-8", info = ydl.extract_info(search_query, download=False)
errors="replace", entries = info.get("entries") or []
) results: List[SearchResult] = []
for video_data in entries[:limit]:
title = video_data.get("title", "Unknown")
video_id = video_data.get("id", "")
url = video_data.get("url") or f"https://youtube.com/watch?v={video_id}"
uploader = video_data.get("uploader", "Unknown")
duration = video_data.get("duration", 0)
view_count = video_data.get("view_count", 0)
if process.returncode != 0: duration_str = f"{int(duration // 60)}:{int(duration % 60):02d}" if duration else ""
log(f"[youtube] yt-dlp failed: {process.stderr}", file=sys.stderr) views_str = f"{view_count:,}" if view_count else ""
return []
results: List[SearchResult] = [] results.append(
for line in process.stdout.splitlines(): SearchResult(
if not line.strip(): table="youtube",
continue title=title,
path=url,
try: detail=f"By: {uploader}",
video_data = json.loads(line) annotations=[duration_str, f"{views_str} views"],
except json.JSONDecodeError: media_kind="video",
continue columns=[
("Title", title),
title = video_data.get("title", "Unknown") ("Uploader", uploader),
video_id = video_data.get("id", "") ("Duration", duration_str),
url = video_data.get("url") or f"https://youtube.com/watch?v={video_id}" ("Views", views_str),
uploader = video_data.get("uploader", "Unknown") ],
duration = video_data.get("duration", 0) full_metadata={
view_count = video_data.get("view_count", 0) "video_id": video_id,
"uploader": uploader,
duration_str = f"{int(duration // 60)}:{int(duration % 60):02d}" if duration else "" "duration": duration,
views_str = f"{view_count:,}" if view_count else "" "view_count": view_count,
},
results.append( )
SearchResult(
table="youtube",
title=title,
path=url,
detail=f"By: {uploader}",
annotations=[duration_str, f"{views_str} views"],
media_kind="video",
columns=[
("Title", title),
("Uploader", uploader),
("Duration", duration_str),
("Views", views_str),
],
full_metadata={
"video_id": video_id,
"uploader": uploader,
"duration": duration,
"view_count": view_count,
},
) )
) return results
except Exception:
return results log("[youtube] yt_dlp import failed", file=sys.stderr)
except Exception as exc:
log(f"[youtube] Error: {exc}", file=sys.stderr)
return [] return []
def validate(self) -> bool: def validate(self) -> bool:
return shutil.which("yt-dlp") is not None try:
import yt_dlp # type: ignore
return True
except Exception:
return False

View File

@@ -501,6 +501,8 @@ fi
# At this point REPO may still be wrong if mm was invoked outside any project; keep the embedded path as a last resort. # At this point REPO may still be wrong if mm was invoked outside any project; keep the embedded path as a last resort.
VENV="$REPO/.venv" VENV="$REPO/.venv"
# Ensure tools installed into the venv are discoverable to subprocess-based providers
export PATH="$VENV/bin:$PATH"
# Debug mode: set MM_DEBUG=1 to print repository, venv, and import diagnostics # Debug mode: set MM_DEBUG=1 to print repository, venv, and import diagnostics
if [ -n "${MM_DEBUG:-}" ]; then if [ -n "${MM_DEBUG:-}" ]; then

View File

@@ -303,6 +303,8 @@ set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO="$SCRIPT_DIR" REPO="$SCRIPT_DIR"
VENV="$REPO/.venv" VENV="$REPO/.venv"
# Make tools installed into the local venv available in PATH for provider discovery
export PATH="$VENV/bin:$PATH"
PY="$VENV/bin/python" PY="$VENV/bin/python"
if [ -x "$PY" ]; then if [ -x "$PY" ]; then
exec "$PY" -m medeia_macina.cli_entry "$@" exec "$PY" -m medeia_macina.cli_entry "$@"
@@ -320,6 +322,9 @@ fi
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repo = $scriptDir $repo = $scriptDir
$venv = Join-Path $repo '.venv' $venv = Join-Path $repo '.venv'
# Ensure venv Scripts dir is on PATH for provider discovery
$venvScripts = Join-Path $venv 'Scripts'
if (Test-Path $venvScripts) { $env:PATH = $venvScripts + ';' + $env:PATH }
$py = Join-Path $venv 'Scripts\python.exe' $py = Join-Path $venv 'Scripts\python.exe'
$cli = Join-Path $repo 'CLI.py' $cli = Join-Path $repo 'CLI.py'
if (Test-Path $py) { & $py -m medeia_macina.cli_entry @args; exit $LASTEXITCODE } if (Test-Path $py) { & $py -m medeia_macina.cli_entry @args; exit $LASTEXITCODE }
@@ -335,10 +340,10 @@ python -m medeia_macina.cli_entry @args
bat_text = ( bat_text = (
"@echo off\r\n" "@echo off\r\n"
"set SCRIPT_DIR=%~dp0\r\n" "set SCRIPT_DIR=%~dp0\r\n"
"set PATH=%SCRIPT_DIR%\.venv\Scripts;%PATH%\r\n"
"if exist \"%SCRIPT_DIR%\\.venv\\Scripts\\python.exe\" \"%SCRIPT_DIR%\\.venv\\Scripts\\python.exe\" -m medeia_macina.cli_entry %*\r\n" "if exist \"%SCRIPT_DIR%\\.venv\\Scripts\\python.exe\" \"%SCRIPT_DIR%\\.venv\\Scripts\\python.exe\" -m medeia_macina.cli_entry %*\r\n"
"if exist \"%SCRIPT_DIR%\\CLI.py\" python \"%SCRIPT_DIR%\\CLI.py\" %*\r\n" "if exist \"%SCRIPT_DIR%\\CLI.py\" python \"%SCRIPT_DIR%\\CLI.py\" %*\r\n"
"python -m medeia_macina.cli_entry %*\r\n" "python -m medeia_macina.cli_entry %*\r\n"
"python -m medeia_macina.cli_entry %*\r\n"
) )
try: try:
bat.write_text(bat_text, encoding="utf-8") bat.write_text(bat_text, encoding="utf-8")