Add Deno version detection and caching support

Introduces functions to detect Deno version directly and with caching in ytsage_deno.py and ytsage_utils.py. Updates the About dialog to display Deno status, version, and path if available. Also extends version cache refresh logic to include Deno.
This commit is contained in:
oop7
2025-11-14 18:19:02 +02:00
parent 38a8d9d29f
commit 894f999017
3 changed files with 121 additions and 2 deletions
+44
View File
@@ -462,6 +462,50 @@ def get_deno_path() -> Path:
return "deno" # type: ignore[return-value] return "deno" # type: ignore[return-value]
def get_deno_version_direct(deno_path=None) -> str:
"""
Get Deno version directly without caching.
Args:
deno_path: Optional path to Deno binary. If None, uses get_deno_path()
Returns:
str: Version string or error message
"""
try:
if deno_path is None:
deno_path = get_deno_path()
if not deno_path or deno_path == "deno":
return "Not found"
result = subprocess.run(
[str(deno_path), "--version"],
capture_output=True,
text=True,
timeout=10,
creationflags=SUBPROCESS_CREATIONFLAGS
)
if result.returncode == 0:
# Deno outputs: "deno 1.38.0 (release, x86_64-pc-windows-msvc)"
# Extract version from first line
lines = result.stdout.strip().split("\n")
if lines:
first_line = lines[0]
# Extract version number (e.g., "1.38.0" from "deno 1.38.0 ...")
parts = first_line.split()
if len(parts) >= 2 and parts[0] == "deno":
return parts[1]
return first_line.strip()
return "Unknown version"
else:
return "Error getting version"
except Exception as e:
logger.exception(f"Error getting Deno version: {e}")
return "Error getting version"
def setup_deno(parent_widget=None): def setup_deno(parent_widget=None):
""" """
Show the Deno setup dialog and handle the result. Show the Deno setup dialog and handle the result.
+39 -1
View File
@@ -45,6 +45,7 @@ except ImportError:
_version_cache = { _version_cache = {
"ytdlp": {"version": None, "path": None, "last_check": 0, "path_mtime": 0}, "ytdlp": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},
"ffmpeg": {"version": None, "path": None, "last_check": 0, "path_mtime": 0}, "ffmpeg": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},
"deno": {"version": None, "path": None, "last_check": 0, "path_mtime": 0},
} }
# Cache expiry time in seconds (5 minutes) # Cache expiry time in seconds (5 minutes)
@@ -173,8 +174,34 @@ def get_ffmpeg_version_cached() -> str:
return "Error getting version" return "Error getting version"
def get_deno_version_cached() -> str:
"""Get Deno version with caching support."""
try:
from src.core.ytsage_deno import get_deno_path
current_path = get_deno_path()
# Check if we need to refresh cache
if not should_refresh_cache("deno", current_path):
cached_version = _version_cache["deno"].get("version")
if cached_version:
return cached_version
# Get fresh version info
from src.core.ytsage_deno import get_deno_version_direct
version_info = get_deno_version_direct(current_path)
# Update cache
update_version_cache("deno", version_info, current_path)
return version_info
except Exception as e:
logger.exception(f"Error getting cached Deno version: {e}")
return "Error getting version"
def refresh_version_cache(force=False) -> bool: def refresh_version_cache(force=False) -> bool:
"""Manually refresh version cache for both tools.""" """Manually refresh version cache for all tools."""
try: try:
# Refresh yt-dlp # Refresh yt-dlp
current_path = get_yt_dlp_path() current_path = get_yt_dlp_path()
@@ -185,6 +212,12 @@ def refresh_version_cache(force=False) -> bool:
version_info = get_ffmpeg_version_direct() version_info = get_ffmpeg_version_direct()
update_version_cache("ffmpeg", version_info, "ffmpeg", force_save=True) update_version_cache("ffmpeg", version_info, "ffmpeg", force_save=True)
# Refresh Deno
from src.core.ytsage_deno import get_deno_path, get_deno_version_direct
deno_path = get_deno_path()
version_info = get_deno_version_direct(deno_path)
update_version_cache("deno", version_info, deno_path, force_save=True)
return True return True
except Exception as e: except Exception as e:
logger.exception(f"Error refreshing version cache: {e}") logger.exception(f"Error refreshing version cache: {e}")
@@ -201,6 +234,11 @@ def get_ffmpeg_version() -> str:
return get_ffmpeg_version_cached() return get_ffmpeg_version_cached()
def get_deno_version() -> str:
"""Get the version of Deno (uses cached version for performance)."""
return get_deno_version_cached()
def get_ytdlp_version_direct(yt_dlp_path=None) -> str: def get_ytdlp_version_direct(yt_dlp_path=None) -> str:
"""Get yt-dlp version directly without caching.""" """Get yt-dlp version directly without caching."""
try: try:
@@ -23,8 +23,9 @@ from src import __version__ as APP_VERSION
from src.utils.ytsage_localization import _ from src.utils.ytsage_localization import _
from src.core.ytsage_ffmpeg import get_ffmpeg_path from src.core.ytsage_ffmpeg import get_ffmpeg_path
from src.core.ytsage_utils import _version_cache, check_ffmpeg, get_ffmpeg_version, get_ytdlp_version, refresh_version_cache from src.core.ytsage_utils import _version_cache, check_ffmpeg, get_ffmpeg_version, get_ytdlp_version, get_deno_version, refresh_version_cache
from src.core.ytsage_yt_dlp import check_ytdlp_installed, get_yt_dlp_path from src.core.ytsage_yt_dlp import check_ytdlp_installed, get_yt_dlp_path
from src.core.ytsage_deno import check_deno_installed, get_deno_path
class LogWindow(QDialog): class LogWindow(QDialog):
@@ -442,6 +443,42 @@ class AboutDialog(QDialog):
) )
self.status_container.addWidget(ffmpeg_item) self.status_container.addWidget(ffmpeg_item)
# Deno Status - compact version with path (only show path if in app bin directory)
deno_found = check_deno_installed()
deno_status_text = (
f"<span style='color: #4CAF50;'>{_('about.detected')}</span>" if deno_found else f"<span style='color: #F44336;'>{_('about.missing')}</span>"
)
deno_version = get_deno_version() if deno_found else _('about.not_available')
# Get Deno path - only show if in app bin directory
deno_path_text = None
if deno_found:
deno_path = get_deno_path()
# Only show path if it's not the fallback "deno" and the file exists
if deno_path and deno_path != "deno":
from pathlib import Path
from src.utils.ytsage_constants import DENO_APP_BIN_PATH
# Check if the path is our managed binary
if Path(deno_path).resolve() == DENO_APP_BIN_PATH.resolve():
deno_path_text = deno_path
# Simplified cache status for Deno
deno_cache = _version_cache.get("deno", {})
last_check = deno_cache.get("last_check", 0)
cache_status = ""
if last_check > 0 and deno_found:
cache_time = datetime.fromtimestamp(last_check).strftime("%H:%M")
cache_status = f" <span style='color: #888; font-size: 10px;'>({cache_time})</span>"
deno_item = self._create_status_item(
"🦕",
"Deno",
deno_status_text,
deno_version + cache_status,
deno_path_text,
)
self.status_container.addWidget(deno_item)
def refresh_version_info(self) -> None: def refresh_version_info(self) -> None:
"""Refresh version information manually.""" """Refresh version information manually."""
self.refresh_btn.setText(_('about.refreshing')) self.refresh_btn.setText(_('about.refreshing'))