mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-12-14 12:15:23 +00:00
Respect PATHEXT when locating JS runtime on Windows (#15117)
Fixes #15043 Authored by: Grub4K
This commit is contained in:
@@ -1,21 +1,61 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import functools
|
import functools
|
||||||
import os.path
|
import os.path
|
||||||
|
import sys
|
||||||
|
|
||||||
from ._utils import _get_exe_version_output, detect_exe_version, int_or_none
|
from ._utils import _get_exe_version_output, detect_exe_version, int_or_none
|
||||||
|
|
||||||
|
|
||||||
# NOT public API
|
def _runtime_version_tuple(v):
|
||||||
def runtime_version_tuple(v):
|
|
||||||
# NB: will return (0,) if `v` is an invalid version string
|
# NB: will return (0,) if `v` is an invalid version string
|
||||||
return tuple(int_or_none(x, default=0) for x in v.split('.'))
|
return tuple(int_or_none(x, default=0) for x in v.split('.'))
|
||||||
|
|
||||||
|
|
||||||
|
_FALLBACK_PATHEXT = ('.COM', '.EXE', '.BAT', '.CMD')
|
||||||
|
|
||||||
|
|
||||||
|
def _find_exe(basename: str) -> str:
|
||||||
|
if os.name != 'nt':
|
||||||
|
return basename
|
||||||
|
|
||||||
|
paths: list[str] = []
|
||||||
|
|
||||||
|
# binary dir
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
paths.append(os.path.dirname(sys.executable))
|
||||||
|
# cwd
|
||||||
|
paths.append(os.getcwd())
|
||||||
|
# PATH items
|
||||||
|
if path := os.environ.get('PATH'):
|
||||||
|
paths.extend(filter(None, path.split(os.path.pathsep)))
|
||||||
|
|
||||||
|
pathext = os.environ.get('PATHEXT')
|
||||||
|
if pathext is None:
|
||||||
|
exts = _FALLBACK_PATHEXT
|
||||||
|
else:
|
||||||
|
exts = tuple(ext for ext in pathext.split(os.pathsep) if ext)
|
||||||
|
|
||||||
|
visited = []
|
||||||
|
for path in map(os.path.realpath, paths):
|
||||||
|
normed = os.path.normcase(path)
|
||||||
|
if normed in visited:
|
||||||
|
continue
|
||||||
|
visited.append(normed)
|
||||||
|
|
||||||
|
for ext in exts:
|
||||||
|
binary = os.path.join(path, f'{basename}{ext}')
|
||||||
|
if os.access(binary, os.F_OK | os.X_OK) and not os.path.isdir(binary):
|
||||||
|
return binary
|
||||||
|
|
||||||
|
return basename
|
||||||
|
|
||||||
|
|
||||||
def _determine_runtime_path(path, basename):
|
def _determine_runtime_path(path, basename):
|
||||||
if not path:
|
if not path:
|
||||||
return basename
|
return _find_exe(basename)
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
return os.path.join(path, basename)
|
return os.path.join(path, basename)
|
||||||
return path
|
return path
|
||||||
@@ -52,7 +92,7 @@ class DenoJsRuntime(JsRuntime):
|
|||||||
if not out:
|
if not out:
|
||||||
return None
|
return None
|
||||||
version = detect_exe_version(out, r'^deno (\S+)', 'unknown')
|
version = detect_exe_version(out, r'^deno (\S+)', 'unknown')
|
||||||
vt = runtime_version_tuple(version)
|
vt = _runtime_version_tuple(version)
|
||||||
return JsRuntimeInfo(
|
return JsRuntimeInfo(
|
||||||
name='deno', path=path, version=version, version_tuple=vt,
|
name='deno', path=path, version=version, version_tuple=vt,
|
||||||
supported=vt >= self.MIN_SUPPORTED_VERSION)
|
supported=vt >= self.MIN_SUPPORTED_VERSION)
|
||||||
@@ -67,7 +107,7 @@ class BunJsRuntime(JsRuntime):
|
|||||||
if not out:
|
if not out:
|
||||||
return None
|
return None
|
||||||
version = detect_exe_version(out, r'^(\S+)', 'unknown')
|
version = detect_exe_version(out, r'^(\S+)', 'unknown')
|
||||||
vt = runtime_version_tuple(version)
|
vt = _runtime_version_tuple(version)
|
||||||
return JsRuntimeInfo(
|
return JsRuntimeInfo(
|
||||||
name='bun', path=path, version=version, version_tuple=vt,
|
name='bun', path=path, version=version, version_tuple=vt,
|
||||||
supported=vt >= self.MIN_SUPPORTED_VERSION)
|
supported=vt >= self.MIN_SUPPORTED_VERSION)
|
||||||
@@ -82,7 +122,7 @@ class NodeJsRuntime(JsRuntime):
|
|||||||
if not out:
|
if not out:
|
||||||
return None
|
return None
|
||||||
version = detect_exe_version(out, r'^v(\S+)', 'unknown')
|
version = detect_exe_version(out, r'^v(\S+)', 'unknown')
|
||||||
vt = runtime_version_tuple(version)
|
vt = _runtime_version_tuple(version)
|
||||||
return JsRuntimeInfo(
|
return JsRuntimeInfo(
|
||||||
name='node', path=path, version=version, version_tuple=vt,
|
name='node', path=path, version=version, version_tuple=vt,
|
||||||
supported=vt >= self.MIN_SUPPORTED_VERSION)
|
supported=vt >= self.MIN_SUPPORTED_VERSION)
|
||||||
@@ -100,7 +140,7 @@ class QuickJsRuntime(JsRuntime):
|
|||||||
is_ng = 'QuickJS-ng' in out
|
is_ng = 'QuickJS-ng' in out
|
||||||
|
|
||||||
version = detect_exe_version(out, r'^QuickJS(?:-ng)?\s+version\s+(\S+)', 'unknown')
|
version = detect_exe_version(out, r'^QuickJS(?:-ng)?\s+version\s+(\S+)', 'unknown')
|
||||||
vt = runtime_version_tuple(version.replace('-', '.'))
|
vt = _runtime_version_tuple(version.replace('-', '.'))
|
||||||
if is_ng:
|
if is_ng:
|
||||||
return JsRuntimeInfo(
|
return JsRuntimeInfo(
|
||||||
name='quickjs-ng', path=path, version=version, version_tuple=vt,
|
name='quickjs-ng', path=path, version=version, version_tuple=vt,
|
||||||
|
|||||||
@@ -876,7 +876,13 @@ class Popen(subprocess.Popen):
|
|||||||
kwargs.setdefault('encoding', 'utf-8')
|
kwargs.setdefault('encoding', 'utf-8')
|
||||||
kwargs.setdefault('errors', 'replace')
|
kwargs.setdefault('errors', 'replace')
|
||||||
|
|
||||||
if shell and os.name == 'nt' and kwargs.get('executable') is None:
|
if os.name == 'nt' and kwargs.get('executable') is None:
|
||||||
|
# Must apply shell escaping if we are trying to run a batch file
|
||||||
|
# These conditions should be very specific to limit impact
|
||||||
|
if not shell and isinstance(args, list) and args and args[0].lower().endswith(('.bat', '.cmd')):
|
||||||
|
shell = True
|
||||||
|
|
||||||
|
if shell:
|
||||||
if not isinstance(args, str):
|
if not isinstance(args, str):
|
||||||
args = shell_quote(args, shell=True)
|
args = shell_quote(args, shell=True)
|
||||||
shell = False
|
shell = False
|
||||||
|
|||||||
Reference in New Issue
Block a user