forked from yt-dlp/yt-dlp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_jsruntime.py
More file actions
145 lines (112 loc) · 4.22 KB
/
_jsruntime.py
File metadata and controls
145 lines (112 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
from __future__ import annotations
import abc
import dataclasses
import functools
import os.path
import sys
from ._utils import _get_exe_version_output, detect_exe_version, version_tuple
_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):
if not path:
return _find_exe(basename)
if os.path.isdir(path):
return os.path.join(path, basename)
return path
@dataclasses.dataclass(frozen=True)
class JsRuntimeInfo:
name: str
path: str
version: str
version_tuple: tuple[int, ...]
supported: bool = True
class JsRuntime(abc.ABC):
def __init__(self, path=None):
self._path = path
@functools.cached_property
def info(self) -> JsRuntimeInfo | None:
return self._info()
@abc.abstractmethod
def _info(self) -> JsRuntimeInfo | None:
raise NotImplementedError
class DenoJsRuntime(JsRuntime):
MIN_SUPPORTED_VERSION = (2, 0, 0)
def _info(self):
path = _determine_runtime_path(self._path, 'deno')
out = _get_exe_version_output(path, ['--version'])
if not out:
return None
version = detect_exe_version(out, r'^deno (\S+)', 'unknown')
vt = version_tuple(version, lenient=True)
return JsRuntimeInfo(
name='deno', path=path, version=version, version_tuple=vt,
supported=vt >= self.MIN_SUPPORTED_VERSION)
class BunJsRuntime(JsRuntime):
MIN_SUPPORTED_VERSION = (1, 0, 31)
def _info(self):
path = _determine_runtime_path(self._path, 'bun')
out = _get_exe_version_output(path, ['--version'])
if not out:
return None
version = detect_exe_version(out, r'^(\S+)', 'unknown')
vt = version_tuple(version, lenient=True)
return JsRuntimeInfo(
name='bun', path=path, version=version, version_tuple=vt,
supported=vt >= self.MIN_SUPPORTED_VERSION)
class NodeJsRuntime(JsRuntime):
MIN_SUPPORTED_VERSION = (20, 0, 0)
def _info(self):
path = _determine_runtime_path(self._path, 'node')
out = _get_exe_version_output(path, ['--version'])
if not out:
return None
version = detect_exe_version(out, r'^v(\S+)', 'unknown')
vt = version_tuple(version, lenient=True)
return JsRuntimeInfo(
name='node', path=path, version=version, version_tuple=vt,
supported=vt >= self.MIN_SUPPORTED_VERSION)
class QuickJsRuntime(JsRuntime):
MIN_SUPPORTED_VERSION = (2023, 12, 9)
def _info(self):
path = _determine_runtime_path(self._path, 'qjs')
# quickjs does not have --version and --help returns a status code of 1
out = _get_exe_version_output(path, ['--help'], ignore_return_code=True)
if not out:
return None
is_ng = 'QuickJS-ng' in out
version = detect_exe_version(out, r'^QuickJS(?:-ng)?\s+version\s+(\S+)', 'unknown')
vt = version_tuple(version, lenient=True)
if is_ng:
return JsRuntimeInfo(
name='quickjs-ng', path=path, version=version, version_tuple=vt,
supported=vt > (0,))
return JsRuntimeInfo(
name='quickjs', path=path, version=version, version_tuple=vt,
supported=vt >= self.MIN_SUPPORTED_VERSION)