@chikhamx/voidx 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/postinstall.js +122 -90
- package/bin/voidx.js +48 -58
- package/package.json +1 -1
package/bin/postinstall.js
CHANGED
|
@@ -2,19 +2,14 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
4
|
// Post-install: download a standalone Python, create venv, pip install voidx.
|
|
5
|
-
//
|
|
5
|
+
// Uses only the bundled Python — never falls back to the system Python.
|
|
6
6
|
|
|
7
|
-
const { createWriteStream, existsSync, mkdirSync, readFileSync, writeFileSync } = require("fs");
|
|
7
|
+
const { createWriteStream, existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, rmSync } = require("fs");
|
|
8
8
|
const { spawnSync } = require("child_process");
|
|
9
|
-
const { get, request } = require("https");
|
|
10
|
-
const { createGunzip } = require("zlib");
|
|
11
|
-
const { pipeline } = require("stream/promises");
|
|
12
|
-
const { createUnzip } = require("zlib");
|
|
13
9
|
const { join, dirname } = require("path");
|
|
14
10
|
const os = require("os");
|
|
15
11
|
const fs = require("fs");
|
|
16
12
|
const path = require("path");
|
|
17
|
-
const { execSync } = require("child_process");
|
|
18
13
|
|
|
19
14
|
const pkg = require("../package.json");
|
|
20
15
|
|
|
@@ -92,7 +87,32 @@ function resolveBundledPython(pythonDir, platform) {
|
|
|
92
87
|
return path.join(installDir, "bin", "python3");
|
|
93
88
|
}
|
|
94
89
|
|
|
95
|
-
// ── Download
|
|
90
|
+
// ── Download with retry ────────────────────────────────────────────────────
|
|
91
|
+
const MAX_DOWNLOAD_RETRIES = 3;
|
|
92
|
+
|
|
93
|
+
function sleep(ms) {
|
|
94
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function downloadFileWithRetry(url, dest, retries = MAX_DOWNLOAD_RETRIES) {
|
|
98
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
99
|
+
try {
|
|
100
|
+
return await downloadFile(url, dest);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
// Clean up partial download
|
|
103
|
+
try { unlinkSync(dest); } catch {}
|
|
104
|
+
if (attempt < retries) {
|
|
105
|
+
const delay = Math.pow(2, attempt) * 1000;
|
|
106
|
+
console.error(` Download attempt ${attempt}/${retries} failed: ${err.message}`);
|
|
107
|
+
console.error(` Retrying in ${delay / 1000}s…`);
|
|
108
|
+
await sleep(delay);
|
|
109
|
+
} else {
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
96
116
|
function downloadFile(url, dest) {
|
|
97
117
|
return new Promise((resolve, reject) => {
|
|
98
118
|
const doRequest = (currentUrl, redirects = 0) => {
|
|
@@ -100,7 +120,7 @@ function downloadFile(url, dest) {
|
|
|
100
120
|
return reject(new Error(`Too many redirects downloading ${url}`));
|
|
101
121
|
}
|
|
102
122
|
const mod = currentUrl.startsWith("https") ? require("https") : require("http");
|
|
103
|
-
mod.get(currentUrl, { timeout:
|
|
123
|
+
mod.get(currentUrl, { timeout: 30000 }, (res) => {
|
|
104
124
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
105
125
|
return doRequest(res.headers.location, redirects + 1);
|
|
106
126
|
}
|
|
@@ -163,14 +183,45 @@ function writeMarker(markerPath, content) {
|
|
|
163
183
|
|
|
164
184
|
// ── pip install ────────────────────────────────────────────────────────────
|
|
165
185
|
function pipInstall(venvPython, packageSpec, env) {
|
|
186
|
+
// Upgrade pip first to avoid resolver bugs in old versions
|
|
187
|
+
const pipUpgradeEnv = Object.assign({}, env, {
|
|
188
|
+
PIP_NO_INPUT: "1",
|
|
189
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1",
|
|
190
|
+
PYTHON_KEYRING_BACKEND: "keyring.backends.null.Keyring",
|
|
191
|
+
});
|
|
192
|
+
const pipUpgradeResult = spawnSync(
|
|
193
|
+
venvPython,
|
|
194
|
+
["-m", "pip", "install", "--upgrade", "pip", "--no-cache-dir"],
|
|
195
|
+
{ encoding: "utf8", stdio: "inherit", windowsHide: true, env: pipUpgradeEnv }
|
|
196
|
+
);
|
|
197
|
+
if (pipUpgradeResult.error || pipUpgradeResult.status !== 0) {
|
|
198
|
+
console.error(" ⚠️ Failed to upgrade pip, continuing with current version…");
|
|
199
|
+
}
|
|
200
|
+
|
|
166
201
|
const pipEnv = Object.assign({}, env, {
|
|
167
202
|
PIP_NO_INPUT: "1",
|
|
168
203
|
PIP_DISABLE_PIP_VERSION_CHECK: "1",
|
|
169
204
|
PYTHON_KEYRING_BACKEND: "keyring.backends.null.Keyring",
|
|
170
205
|
});
|
|
206
|
+
|
|
207
|
+
const pipArgs = ["-m", "pip", "install", "--upgrade", "--no-cache-dir", "--progress-bar", "on"];
|
|
208
|
+
|
|
209
|
+
// Support custom PyPI index for users behind firewalls or in regions with slow PyPI access
|
|
210
|
+
const pipIndex = env.VOIDX_NPM_PIP_INDEX;
|
|
211
|
+
if (pipIndex) {
|
|
212
|
+
pipArgs.push("-i", pipIndex);
|
|
213
|
+
// Extract host for --trusted-host when using a custom index
|
|
214
|
+
try {
|
|
215
|
+
const indexUrl = new URL(pipIndex);
|
|
216
|
+
pipArgs.push("--trusted-host", indexUrl.hostname);
|
|
217
|
+
} catch {}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
pipArgs.push(packageSpec);
|
|
221
|
+
|
|
171
222
|
const result = spawnSync(
|
|
172
223
|
venvPython,
|
|
173
|
-
|
|
224
|
+
pipArgs,
|
|
174
225
|
{ encoding: "utf8", stdio: "inherit", windowsHide: true, env: pipEnv }
|
|
175
226
|
);
|
|
176
227
|
if (result.error) {
|
|
@@ -181,37 +232,6 @@ function pipInstall(venvPython, packageSpec, env) {
|
|
|
181
232
|
}
|
|
182
233
|
}
|
|
183
234
|
|
|
184
|
-
// ── System Python fallback ─────────────────────────────────────────────────
|
|
185
|
-
function probeSystemPython() {
|
|
186
|
-
const candidates = [
|
|
187
|
-
{ command: "python3", args: [] },
|
|
188
|
-
{ command: "python", args: [] },
|
|
189
|
-
{ command: "python3.12", args: [] },
|
|
190
|
-
{ command: "python3.11", args: [] },
|
|
191
|
-
];
|
|
192
|
-
if (process.platform === "win32") {
|
|
193
|
-
candidates.push({ command: "py", args: ["-3"] });
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
for (const candidate of candidates) {
|
|
197
|
-
const result = spawnSync(
|
|
198
|
-
candidate.command,
|
|
199
|
-
[...candidate.args, "-c", "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"],
|
|
200
|
-
{ encoding: "utf8", windowsHide: true }
|
|
201
|
-
);
|
|
202
|
-
if (result.error || result.status !== 0) continue;
|
|
203
|
-
const ver = (result.stdout || "").trim();
|
|
204
|
-
const match = /^(\d+)\.(\d+)/.exec(ver);
|
|
205
|
-
if (!match) continue;
|
|
206
|
-
const major = parseInt(match[1], 10);
|
|
207
|
-
const minor = parseInt(match[2], 10);
|
|
208
|
-
if (major > 3 || (major === 3 && minor >= 11)) {
|
|
209
|
-
return { command: candidate.command, args: candidate.args };
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
235
|
// ── Main ───────────────────────────────────────────────────────────────────
|
|
216
236
|
async function main() {
|
|
217
237
|
const env = process.env;
|
|
@@ -228,70 +248,71 @@ async function main() {
|
|
|
228
248
|
return;
|
|
229
249
|
}
|
|
230
250
|
|
|
231
|
-
// Step 1:
|
|
232
|
-
let pythonForVenv;
|
|
251
|
+
// Step 1: Download bundled Python (required — no system Python fallback)
|
|
233
252
|
const platformInfo = getPlatformInfo();
|
|
253
|
+
if (!platformInfo) {
|
|
254
|
+
console.error(`\n ❌ Unsupported platform: ${os.platform()}-${os.arch()}\n`);
|
|
255
|
+
console.error(" voidx npm package supports: macOS (x64/arm64), Linux (x64/arm64), Windows (x64/arm64)\n");
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
234
258
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
console.error(" [1/3] Downloading Python runtime…");
|
|
238
|
-
|
|
239
|
-
const pythonDir = resolvePythonDir(env);
|
|
240
|
-
const pbsFilename = getPbsFilename(platformInfo.target);
|
|
241
|
-
const pbsUrl = `${PBS_RELEASE_BASE}/${pbsFilename}`;
|
|
242
|
-
const archivePath = path.join(pythonDir, pbsFilename);
|
|
243
|
-
const bundledPython = resolveBundledPython(pythonDir, platformInfo.platform);
|
|
244
|
-
|
|
245
|
-
if (!existsSync(bundledPython)) {
|
|
246
|
-
try {
|
|
247
|
-
mkdirSync(pythonDir, { recursive: true });
|
|
259
|
+
console.error(`\n🐍 Setting up voidx ${pkg.version}…\n`);
|
|
260
|
+
console.error(" [1/3] Downloading Python runtime…");
|
|
248
261
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
262
|
+
const pythonDir = resolvePythonDir(env);
|
|
263
|
+
const pbsFilename = getPbsFilename(platformInfo.target);
|
|
264
|
+
const pbsUrlBase = env.VOIDX_NPM_PYTHON_MIRROR || PBS_RELEASE_BASE;
|
|
265
|
+
const pbsUrl = `${pbsUrlBase}/${PBS_TAG}/${pbsFilename}`;
|
|
266
|
+
const archivePath = path.join(pythonDir, pbsFilename);
|
|
267
|
+
const bundledPython = resolveBundledPython(pythonDir, platformInfo.platform);
|
|
254
268
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
269
|
+
if (!existsSync(bundledPython)) {
|
|
270
|
+
try {
|
|
271
|
+
mkdirSync(pythonDir, { recursive: true });
|
|
258
272
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
console.error(
|
|
263
|
-
console.error(" Falling back to system Python…\n");
|
|
273
|
+
if (!existsSync(archivePath)) {
|
|
274
|
+
console.error(` Downloading ${pbsFilename}…`);
|
|
275
|
+
await downloadFileWithRetry(pbsUrl, archivePath);
|
|
276
|
+
console.error(" Download complete.");
|
|
264
277
|
}
|
|
265
|
-
} else {
|
|
266
|
-
console.error(" Using cached Python runtime.");
|
|
267
|
-
}
|
|
268
278
|
|
|
269
|
-
|
|
270
|
-
|
|
279
|
+
console.error(" Extracting Python runtime…");
|
|
280
|
+
extractTarGz(archivePath, pythonDir);
|
|
281
|
+
console.error(" Extraction complete.");
|
|
282
|
+
|
|
283
|
+
// Clean up archive to save disk
|
|
284
|
+
try { fs.unlinkSync(archivePath); } catch {}
|
|
285
|
+
} catch (err) {
|
|
286
|
+
// Clean up partial archive on failure
|
|
287
|
+
try { unlinkSync(archivePath); } catch {}
|
|
288
|
+
console.error(`\n ❌ Failed to download Python runtime: ${err.message}\n`);
|
|
289
|
+
console.error(" This is usually a network issue. Try:");
|
|
290
|
+
console.error(" 1. Use a mirror: VOIDX_NPM_PYTHON_MIRROR=https://npmmirror.com/mirrors/python-standalone");
|
|
291
|
+
console.error(" 2. Retry: npm install -g @chikhamx/voidx");
|
|
292
|
+
console.error(" 3. Debug: VOIDX_NPM_DEBUG=1 npm install -g @chikhamx/voidx\n");
|
|
293
|
+
process.exit(1);
|
|
271
294
|
}
|
|
295
|
+
} else {
|
|
296
|
+
console.error(" Using cached Python runtime.");
|
|
272
297
|
}
|
|
273
298
|
|
|
274
|
-
//
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
console.error(
|
|
284
|
-
console.error(" Windows: https://python.org/downloads\n");
|
|
285
|
-
process.exit(1);
|
|
299
|
+
// Step 2: Create venv (rebuild if corrupted)
|
|
300
|
+
console.error(" [2/3] Creating virtual environment…");
|
|
301
|
+
|
|
302
|
+
// If venv exists but is corrupted (python binary missing), nuke and rebuild
|
|
303
|
+
if (existsSync(venvDir) && !existsSync(venvPython)) {
|
|
304
|
+
console.error(" Existing venv is corrupted, rebuilding…");
|
|
305
|
+
try {
|
|
306
|
+
rmSync(venvDir, { recursive: true, force: true });
|
|
307
|
+
} catch (err) {
|
|
308
|
+
console.error(` Failed to remove corrupted venv: ${err.message}`);
|
|
286
309
|
}
|
|
287
310
|
}
|
|
288
311
|
|
|
289
|
-
// Step 2: Create venv
|
|
290
|
-
console.error(" [2/3] Creating virtual environment…");
|
|
291
312
|
if (!existsSync(venvPython)) {
|
|
292
313
|
const venvResult = spawnSync(
|
|
293
|
-
|
|
294
|
-
[
|
|
314
|
+
bundledPython,
|
|
315
|
+
["-m", "venv", venvDir],
|
|
295
316
|
{ encoding: "utf8", stdio: "inherit", windowsHide: true }
|
|
296
317
|
);
|
|
297
318
|
if (venvResult.error) {
|
|
@@ -313,7 +334,18 @@ async function main() {
|
|
|
313
334
|
console.error(`\n✅ voidx ${pkg.version} installed! Run: voidx\n`);
|
|
314
335
|
}
|
|
315
336
|
|
|
337
|
+
// ── URL builder (for mirror support) ──────────────────────────────────────
|
|
338
|
+
|
|
339
|
+
function buildPythonDownloadUrl(mirrorBase, tag, filename) {
|
|
340
|
+
return `${mirrorBase}/${tag}/${filename}`;
|
|
341
|
+
}
|
|
342
|
+
|
|
316
343
|
main().catch((err) => {
|
|
317
344
|
console.error(`\n❌ Setup failed: ${err.message}\n`);
|
|
318
345
|
process.exit(1);
|
|
319
346
|
});
|
|
347
|
+
|
|
348
|
+
module.exports = {
|
|
349
|
+
buildPythonDownloadUrl,
|
|
350
|
+
downloadFileWithRetry,
|
|
351
|
+
};
|
package/bin/voidx.js
CHANGED
|
@@ -40,7 +40,7 @@ function main(argv = process.argv.slice(2), env = process.env) {
|
|
|
40
40
|
// ── Python selection ───────────────────────────────────────────────────────
|
|
41
41
|
|
|
42
42
|
function selectPython(env) {
|
|
43
|
-
// 1. Explicit override
|
|
43
|
+
// 1. Explicit override (for advanced users / debugging)
|
|
44
44
|
const explicit = env.VOIDX_PYTHON;
|
|
45
45
|
if (explicit) {
|
|
46
46
|
const candidate = { command: explicit, args: [], label: explicit };
|
|
@@ -56,7 +56,7 @@ function selectPython(env) {
|
|
|
56
56
|
return candidate;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// 2. Bundled Python (
|
|
59
|
+
// 2. Bundled Python (the only normal path)
|
|
60
60
|
const bundledBin = resolveBundledPythonBin(env);
|
|
61
61
|
if (bundledBin && fs.existsSync(bundledBin)) {
|
|
62
62
|
const candidate = { command: bundledBin, args: [], label: "bundled" };
|
|
@@ -66,38 +66,11 @@ function selectPython(env) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
//
|
|
70
|
-
const candidates = [
|
|
71
|
-
{ command: "python3", args: [], label: "python3" },
|
|
72
|
-
{ command: "python", args: [], label: "python" },
|
|
73
|
-
{ command: "python3.13", args: [], label: "python3.13" },
|
|
74
|
-
{ command: "python3.12", args: [], label: "python3.12" },
|
|
75
|
-
{ command: "python3.11", args: [], label: "python3.11" },
|
|
76
|
-
];
|
|
77
|
-
if (process.platform === "win32") {
|
|
78
|
-
candidates.push({ command: "py", args: ["-3"], label: "py -3" });
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const oldVersions = [];
|
|
82
|
-
for (const candidate of candidates) {
|
|
83
|
-
const probe = probePython(candidate);
|
|
84
|
-
if (!probe.ok) {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (isCompatible(probe.version)) {
|
|
88
|
-
return candidate;
|
|
89
|
-
}
|
|
90
|
-
oldVersions.push(`${probe.versionText} at ${candidate.label}`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const hint = pythonHint();
|
|
94
|
-
if (oldVersions.length > 0) {
|
|
95
|
-
throw new Error(
|
|
96
|
-
`voidx requires Python 3.11+. Found ${oldVersions.join(", ")}.\n${hint}`
|
|
97
|
-
);
|
|
98
|
-
}
|
|
69
|
+
// No system Python fallback — bundled Python is required
|
|
99
70
|
throw new Error(
|
|
100
|
-
|
|
71
|
+
"voidx bundled Python not found.\n" +
|
|
72
|
+
"Reinstall the npm package to set it up:\n" +
|
|
73
|
+
" npm install -g @chikhamx/voidx"
|
|
101
74
|
);
|
|
102
75
|
}
|
|
103
76
|
|
|
@@ -136,22 +109,6 @@ function isCompatible(version) {
|
|
|
136
109
|
return version[0] > 3 || (version[0] === 3 && version[1] >= 11);
|
|
137
110
|
}
|
|
138
111
|
|
|
139
|
-
function pythonHint() {
|
|
140
|
-
if (process.platform === "darwin") {
|
|
141
|
-
return "Install Python 3.11+ via: brew install python@3.12\n" +
|
|
142
|
-
"Or reinstall voidx to get the bundled Python.";
|
|
143
|
-
}
|
|
144
|
-
if (process.platform === "linux") {
|
|
145
|
-
return "Install Python 3.11+ via your package manager (apt/dnf).\n" +
|
|
146
|
-
"Or reinstall voidx to get the bundled Python.";
|
|
147
|
-
}
|
|
148
|
-
if (process.platform === "win32") {
|
|
149
|
-
return "Install Python 3.11+ from https://python.org/downloads\n" +
|
|
150
|
-
"Or reinstall voidx to get the bundled Python.";
|
|
151
|
-
}
|
|
152
|
-
return "Install Python 3.11+ or reinstall voidx.";
|
|
153
|
-
}
|
|
154
|
-
|
|
155
112
|
// ── Paths ──────────────────────────────────────────────────────────────────
|
|
156
113
|
|
|
157
114
|
function resolveDataHome(env) {
|
|
@@ -220,6 +177,16 @@ function ensureVenv(python, venvDir, env) {
|
|
|
220
177
|
fs.mkdirSync(path.dirname(venvDir), { recursive: true });
|
|
221
178
|
const venvPython = resolveVenvPython(venvDir);
|
|
222
179
|
|
|
180
|
+
// If venv exists but is corrupted (python binary missing), nuke and rebuild
|
|
181
|
+
if (fs.existsSync(venvDir) && !fs.existsSync(venvPython)) {
|
|
182
|
+
console.error(" Existing venv is corrupted, rebuilding…");
|
|
183
|
+
try {
|
|
184
|
+
fs.rmSync(venvDir, { recursive: true, force: true });
|
|
185
|
+
} catch (err) {
|
|
186
|
+
console.error(` Failed to remove corrupted venv: ${err.message}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
223
190
|
const isFresh = !fs.existsSync(venvPython);
|
|
224
191
|
if (isFresh) {
|
|
225
192
|
console.error(
|
|
@@ -247,22 +214,45 @@ function ensureVenv(python, venvDir, env) {
|
|
|
247
214
|
`\n📦 Downloading ${packageSpec} and dependencies… ` +
|
|
248
215
|
"(1–2 minutes on first run)\n"
|
|
249
216
|
);
|
|
217
|
+
|
|
218
|
+
// Upgrade pip first to avoid resolver bugs
|
|
219
|
+
const pipUpgradeEnv = Object.assign({}, env, {
|
|
220
|
+
PIP_NO_INPUT: "1",
|
|
221
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1",
|
|
222
|
+
PYTHON_KEYRING_BACKEND: "keyring.backends.null.Keyring",
|
|
223
|
+
});
|
|
224
|
+
const pipUpgradeResult = spawnSync(
|
|
225
|
+
venvPython,
|
|
226
|
+
["-m", "pip", "install", "--upgrade", "pip", "--no-cache-dir"],
|
|
227
|
+
{ encoding: "utf8", stdio: "inherit", windowsHide: true, env: pipUpgradeEnv }
|
|
228
|
+
);
|
|
229
|
+
if (pipUpgradeResult.error || pipUpgradeResult.status !== 0) {
|
|
230
|
+
console.error(" ⚠️ Failed to upgrade pip, continuing with current version…");
|
|
231
|
+
}
|
|
232
|
+
|
|
250
233
|
const pipEnv = Object.assign({}, env, {
|
|
251
234
|
PIP_NO_INPUT: "1",
|
|
252
235
|
PIP_DISABLE_PIP_VERSION_CHECK: "1",
|
|
253
236
|
PYTHON_KEYRING_BACKEND: "keyring.backends.null.Keyring",
|
|
254
237
|
});
|
|
238
|
+
|
|
239
|
+
const pipArgs = ["-m", "pip", "install", "--upgrade", "--no-cache-dir", "--progress-bar", "on"];
|
|
240
|
+
|
|
241
|
+
// Support custom PyPI index
|
|
242
|
+
const pipIndex = env.VOIDX_NPM_PIP_INDEX;
|
|
243
|
+
if (pipIndex) {
|
|
244
|
+
pipArgs.push("-i", pipIndex);
|
|
245
|
+
try {
|
|
246
|
+
const indexUrl = new URL(pipIndex);
|
|
247
|
+
pipArgs.push("--trusted-host", indexUrl.hostname);
|
|
248
|
+
} catch {}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
pipArgs.push(packageSpec);
|
|
252
|
+
|
|
255
253
|
const result = spawnSync(
|
|
256
254
|
venvPython,
|
|
257
|
-
|
|
258
|
-
"-m",
|
|
259
|
-
"pip",
|
|
260
|
-
"install",
|
|
261
|
-
"--upgrade",
|
|
262
|
-
"--progress-bar",
|
|
263
|
-
"on",
|
|
264
|
-
packageSpec,
|
|
265
|
-
],
|
|
255
|
+
pipArgs,
|
|
266
256
|
{ encoding: "utf8", stdio: "inherit", windowsHide: true, env: pipEnv }
|
|
267
257
|
);
|
|
268
258
|
if (result.error) {
|