@vercel/python 6.1.1 → 6.1.3
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/dist/index.js +645 -504
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var require_windows = __commonJS({
|
|
|
48
48
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports, module2) {
|
|
49
49
|
module2.exports = isexe;
|
|
50
50
|
isexe.sync = sync;
|
|
51
|
-
var
|
|
51
|
+
var fs5 = require("fs");
|
|
52
52
|
function checkPathExt(path, options) {
|
|
53
53
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
54
54
|
if (!pathext) {
|
|
@@ -73,12 +73,12 @@ var require_windows = __commonJS({
|
|
|
73
73
|
return checkPathExt(path, options);
|
|
74
74
|
}
|
|
75
75
|
function isexe(path, options, cb) {
|
|
76
|
-
|
|
76
|
+
fs5.stat(path, function(er, stat) {
|
|
77
77
|
cb(er, er ? false : checkStat(stat, path, options));
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
function sync(path, options) {
|
|
81
|
-
return checkStat(
|
|
81
|
+
return checkStat(fs5.statSync(path), path, options);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
});
|
|
@@ -88,14 +88,14 @@ var require_mode = __commonJS({
|
|
|
88
88
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports, module2) {
|
|
89
89
|
module2.exports = isexe;
|
|
90
90
|
isexe.sync = sync;
|
|
91
|
-
var
|
|
91
|
+
var fs5 = require("fs");
|
|
92
92
|
function isexe(path, options, cb) {
|
|
93
|
-
|
|
93
|
+
fs5.stat(path, function(er, stat) {
|
|
94
94
|
cb(er, er ? false : checkStat(stat, options));
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
function sync(path, options) {
|
|
98
|
-
return checkStat(
|
|
98
|
+
return checkStat(fs5.statSync(path), options);
|
|
99
99
|
}
|
|
100
100
|
function checkStat(stat, options) {
|
|
101
101
|
return stat.isFile() && checkMode(stat, options);
|
|
@@ -119,7 +119,7 @@ var require_mode = __commonJS({
|
|
|
119
119
|
// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
|
|
120
120
|
var require_isexe = __commonJS({
|
|
121
121
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module2) {
|
|
122
|
-
var
|
|
122
|
+
var fs5 = require("fs");
|
|
123
123
|
var core;
|
|
124
124
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
125
125
|
core = require_windows();
|
|
@@ -395,7 +395,7 @@ var require_shebang_command = __commonJS({
|
|
|
395
395
|
var require_readShebang = __commonJS({
|
|
396
396
|
"../../node_modules/.pnpm/cross-spawn@6.0.5/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module2) {
|
|
397
397
|
"use strict";
|
|
398
|
-
var
|
|
398
|
+
var fs5 = require("fs");
|
|
399
399
|
var shebangCommand = require_shebang_command();
|
|
400
400
|
function readShebang(command) {
|
|
401
401
|
const size = 150;
|
|
@@ -408,9 +408,9 @@ var require_readShebang = __commonJS({
|
|
|
408
408
|
}
|
|
409
409
|
let fd;
|
|
410
410
|
try {
|
|
411
|
-
fd =
|
|
412
|
-
|
|
413
|
-
|
|
411
|
+
fd = fs5.openSync(command, "r");
|
|
412
|
+
fs5.readSync(fd, buffer, 0, size, 0);
|
|
413
|
+
fs5.closeSync(fd);
|
|
414
414
|
} catch (e) {
|
|
415
415
|
}
|
|
416
416
|
return shebangCommand(buffer.toString());
|
|
@@ -1498,7 +1498,7 @@ var require_parse = __commonJS({
|
|
|
1498
1498
|
var escape = require_escape();
|
|
1499
1499
|
var readShebang = require_readShebang();
|
|
1500
1500
|
var semver = require_semver();
|
|
1501
|
-
var
|
|
1501
|
+
var isWin3 = process.platform === "win32";
|
|
1502
1502
|
var isExecutableRegExp = /\.(?:com|exe)$/i;
|
|
1503
1503
|
var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
|
1504
1504
|
var supportsShellOption = niceTry(() => semver.satisfies(process.version, "^4.8.0 || ^5.7.0 || >= 6.0.0", true)) || false;
|
|
@@ -1513,7 +1513,7 @@ var require_parse = __commonJS({
|
|
|
1513
1513
|
return parsed.file;
|
|
1514
1514
|
}
|
|
1515
1515
|
function parseNonShell(parsed) {
|
|
1516
|
-
if (!
|
|
1516
|
+
if (!isWin3) {
|
|
1517
1517
|
return parsed;
|
|
1518
1518
|
}
|
|
1519
1519
|
const commandFile = detectShebang(parsed);
|
|
@@ -1535,7 +1535,7 @@ var require_parse = __commonJS({
|
|
|
1535
1535
|
return parsed;
|
|
1536
1536
|
}
|
|
1537
1537
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
1538
|
-
if (
|
|
1538
|
+
if (isWin3) {
|
|
1539
1539
|
parsed.command = typeof parsed.options.shell === "string" ? parsed.options.shell : process.env.comspec || "cmd.exe";
|
|
1540
1540
|
parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
|
|
1541
1541
|
parsed.options.windowsVerbatimArguments = true;
|
|
@@ -1578,7 +1578,7 @@ var require_parse = __commonJS({
|
|
|
1578
1578
|
var require_enoent = __commonJS({
|
|
1579
1579
|
"../../node_modules/.pnpm/cross-spawn@6.0.5/node_modules/cross-spawn/lib/enoent.js"(exports, module2) {
|
|
1580
1580
|
"use strict";
|
|
1581
|
-
var
|
|
1581
|
+
var isWin3 = process.platform === "win32";
|
|
1582
1582
|
function notFoundError(original, syscall) {
|
|
1583
1583
|
return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
|
|
1584
1584
|
code: "ENOENT",
|
|
@@ -1589,7 +1589,7 @@ var require_enoent = __commonJS({
|
|
|
1589
1589
|
});
|
|
1590
1590
|
}
|
|
1591
1591
|
function hookChildProcess(cp, parsed) {
|
|
1592
|
-
if (!
|
|
1592
|
+
if (!isWin3) {
|
|
1593
1593
|
return;
|
|
1594
1594
|
}
|
|
1595
1595
|
const originalEmit = cp.emit;
|
|
@@ -1604,13 +1604,13 @@ var require_enoent = __commonJS({
|
|
|
1604
1604
|
};
|
|
1605
1605
|
}
|
|
1606
1606
|
function verifyENOENT(status, parsed) {
|
|
1607
|
-
if (
|
|
1607
|
+
if (isWin3 && status === 1 && !parsed.file) {
|
|
1608
1608
|
return notFoundError(parsed.original, "spawn");
|
|
1609
1609
|
}
|
|
1610
1610
|
return null;
|
|
1611
1611
|
}
|
|
1612
1612
|
function verifyENOENTSync(status, parsed) {
|
|
1613
|
-
if (
|
|
1613
|
+
if (isWin3 && status === 1 && !parsed.file) {
|
|
1614
1614
|
return notFoundError(parsed.original, "spawnSync");
|
|
1615
1615
|
}
|
|
1616
1616
|
return null;
|
|
@@ -1895,9 +1895,9 @@ var require_pump = __commonJS({
|
|
|
1895
1895
|
"../../node_modules/.pnpm/pump@3.0.2/node_modules/pump/index.js"(exports, module2) {
|
|
1896
1896
|
var once = require_once();
|
|
1897
1897
|
var eos = require_end_of_stream();
|
|
1898
|
-
var
|
|
1898
|
+
var fs5;
|
|
1899
1899
|
try {
|
|
1900
|
-
|
|
1900
|
+
fs5 = require("fs");
|
|
1901
1901
|
} catch (e) {
|
|
1902
1902
|
}
|
|
1903
1903
|
var noop = function() {
|
|
@@ -1909,9 +1909,9 @@ var require_pump = __commonJS({
|
|
|
1909
1909
|
var isFS = function(stream) {
|
|
1910
1910
|
if (!ancient)
|
|
1911
1911
|
return false;
|
|
1912
|
-
if (!
|
|
1912
|
+
if (!fs5)
|
|
1913
1913
|
return false;
|
|
1914
|
-
return (stream instanceof (
|
|
1914
|
+
return (stream instanceof (fs5.ReadStream || noop) || stream instanceof (fs5.WriteStream || noop)) && isFn(stream.close);
|
|
1915
1915
|
};
|
|
1916
1916
|
var isRequest = function(stream) {
|
|
1917
1917
|
return stream.setHeader && isFn(stream.abort);
|
|
@@ -2143,7 +2143,7 @@ var require_signal_exit = __commonJS({
|
|
|
2143
2143
|
} else {
|
|
2144
2144
|
assert = require("assert");
|
|
2145
2145
|
signals = require_signals();
|
|
2146
|
-
|
|
2146
|
+
isWin3 = /^win/i.test(process2.platform);
|
|
2147
2147
|
EE = require("events");
|
|
2148
2148
|
if (typeof EE !== "function") {
|
|
2149
2149
|
EE = EE.EventEmitter;
|
|
@@ -2215,7 +2215,7 @@ var require_signal_exit = __commonJS({
|
|
|
2215
2215
|
unload();
|
|
2216
2216
|
emit("exit", null, sig);
|
|
2217
2217
|
emit("afterexit", null, sig);
|
|
2218
|
-
if (
|
|
2218
|
+
if (isWin3 && sig === "SIGHUP") {
|
|
2219
2219
|
sig = "SIGINT";
|
|
2220
2220
|
}
|
|
2221
2221
|
process2.kill(process2.pid, sig);
|
|
@@ -2272,7 +2272,7 @@ var require_signal_exit = __commonJS({
|
|
|
2272
2272
|
}
|
|
2273
2273
|
var assert;
|
|
2274
2274
|
var signals;
|
|
2275
|
-
var
|
|
2275
|
+
var isWin3;
|
|
2276
2276
|
var EE;
|
|
2277
2277
|
var emitter;
|
|
2278
2278
|
var unload;
|
|
@@ -2651,7 +2651,7 @@ ${stderr}${stdout}`;
|
|
|
2651
2651
|
var require_lib = __commonJS({
|
|
2652
2652
|
"../../node_modules/.pnpm/which@3.0.0/node_modules/which/lib/index.js"(exports, module2) {
|
|
2653
2653
|
var isexe = require_isexe();
|
|
2654
|
-
var { join:
|
|
2654
|
+
var { join: join6, delimiter, sep, posix } = require("path");
|
|
2655
2655
|
var isWindows = process.platform === "win32";
|
|
2656
2656
|
var rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? "" : sep}]`.replace(/(\\)/g, "\\$1"));
|
|
2657
2657
|
var rRel = new RegExp(`^\\.${rSlash.source}`);
|
|
@@ -2680,7 +2680,7 @@ var require_lib = __commonJS({
|
|
|
2680
2680
|
var getPathPart = (raw, cmd) => {
|
|
2681
2681
|
const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
|
|
2682
2682
|
const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
|
|
2683
|
-
return prefix +
|
|
2683
|
+
return prefix + join6(pathPart, cmd);
|
|
2684
2684
|
};
|
|
2685
2685
|
var which3 = async (cmd, opt = {}) => {
|
|
2686
2686
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
@@ -2748,20 +2748,147 @@ __export(src_exports, {
|
|
|
2748
2748
|
version: () => version
|
|
2749
2749
|
});
|
|
2750
2750
|
module.exports = __toCommonJS(src_exports);
|
|
2751
|
-
var
|
|
2751
|
+
var import_fs5 = __toESM(require("fs"));
|
|
2752
2752
|
var import_util = require("util");
|
|
2753
|
-
var
|
|
2754
|
-
var
|
|
2753
|
+
var import_path5 = require("path");
|
|
2754
|
+
var import_build_utils7 = require("@vercel/build-utils");
|
|
2755
2755
|
|
|
2756
2756
|
// src/install.ts
|
|
2757
2757
|
var import_execa = __toESM(require_execa());
|
|
2758
|
-
var
|
|
2758
|
+
var import_fs2 = __toESM(require("fs"));
|
|
2759
2759
|
var import_os = __toESM(require("os"));
|
|
2760
|
-
var
|
|
2760
|
+
var import_path2 = require("path");
|
|
2761
2761
|
var import_which = __toESM(require_lib());
|
|
2762
|
+
var import_build_utils2 = require("@vercel/build-utils");
|
|
2763
|
+
|
|
2764
|
+
// src/utils.ts
|
|
2765
|
+
var import_fs = __toESM(require("fs"));
|
|
2766
|
+
var import_path = require("path");
|
|
2762
2767
|
var import_build_utils = require("@vercel/build-utils");
|
|
2768
|
+
var execa = require_execa();
|
|
2763
2769
|
var isWin = process.platform === "win32";
|
|
2764
|
-
var
|
|
2770
|
+
var isInVirtualEnv = () => {
|
|
2771
|
+
return process.env.VIRTUAL_ENV;
|
|
2772
|
+
};
|
|
2773
|
+
function getVenvBinDir(venvPath) {
|
|
2774
|
+
return (0, import_path.join)(venvPath, isWin ? "Scripts" : "bin");
|
|
2775
|
+
}
|
|
2776
|
+
function useVirtualEnv(workPath, env, systemPython) {
|
|
2777
|
+
const venvDirs = [".venv", "venv"];
|
|
2778
|
+
let pythonCmd = systemPython;
|
|
2779
|
+
for (const venv of venvDirs) {
|
|
2780
|
+
const venvRoot = (0, import_path.join)(workPath, venv);
|
|
2781
|
+
const binDir = process.platform === "win32" ? (0, import_path.join)(venvRoot, "Scripts") : (0, import_path.join)(venvRoot, "bin");
|
|
2782
|
+
const candidates = process.platform === "win32" ? [(0, import_path.join)(binDir, "python.exe"), (0, import_path.join)(binDir, "python")] : [(0, import_path.join)(binDir, "python3"), (0, import_path.join)(binDir, "python")];
|
|
2783
|
+
const found = candidates.find((p) => import_fs.default.existsSync(p));
|
|
2784
|
+
if (found) {
|
|
2785
|
+
pythonCmd = found;
|
|
2786
|
+
env.VIRTUAL_ENV = venvRoot;
|
|
2787
|
+
env.PATH = `${binDir}${import_path.delimiter}${env.PATH || ""}`;
|
|
2788
|
+
return { pythonCmd, venvRoot };
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
return { pythonCmd };
|
|
2792
|
+
}
|
|
2793
|
+
function createVenvEnv(venvPath, baseEnv = process.env) {
|
|
2794
|
+
const env = { ...baseEnv, VIRTUAL_ENV: venvPath };
|
|
2795
|
+
const binDir = getVenvBinDir(venvPath);
|
|
2796
|
+
const existingPath = env.PATH || process.env.PATH || "";
|
|
2797
|
+
env.PATH = existingPath ? `${binDir}${import_path.delimiter}${existingPath}` : binDir;
|
|
2798
|
+
return env;
|
|
2799
|
+
}
|
|
2800
|
+
async function ensureVenv({
|
|
2801
|
+
pythonPath,
|
|
2802
|
+
venvPath
|
|
2803
|
+
}) {
|
|
2804
|
+
const marker = (0, import_path.join)(venvPath, "pyvenv.cfg");
|
|
2805
|
+
try {
|
|
2806
|
+
await import_fs.default.promises.access(marker);
|
|
2807
|
+
return;
|
|
2808
|
+
} catch {
|
|
2809
|
+
}
|
|
2810
|
+
await import_fs.default.promises.mkdir(venvPath, { recursive: true });
|
|
2811
|
+
console.log(`Creating virtual environment at "${venvPath}"...`);
|
|
2812
|
+
await execa(pythonPath, ["-m", "venv", venvPath]);
|
|
2813
|
+
}
|
|
2814
|
+
function getVenvPythonBin(venvPath) {
|
|
2815
|
+
return (0, import_path.join)(getVenvBinDir(venvPath), isWin ? "python.exe" : "python");
|
|
2816
|
+
}
|
|
2817
|
+
async function runPyprojectScript(workPath, scriptNames, env) {
|
|
2818
|
+
const pyprojectPath = (0, import_path.join)(workPath, "pyproject.toml");
|
|
2819
|
+
if (!import_fs.default.existsSync(pyprojectPath))
|
|
2820
|
+
return false;
|
|
2821
|
+
let pyproject = null;
|
|
2822
|
+
try {
|
|
2823
|
+
pyproject = await (0, import_build_utils.readConfigFile)(pyprojectPath);
|
|
2824
|
+
} catch {
|
|
2825
|
+
console.error("Failed to parse pyproject.toml");
|
|
2826
|
+
return false;
|
|
2827
|
+
}
|
|
2828
|
+
const scripts = pyproject?.tool?.vercel?.scripts || {};
|
|
2829
|
+
const candidates = typeof scriptNames === "string" ? [scriptNames] : Array.from(scriptNames);
|
|
2830
|
+
const scriptToRun = candidates.find((name) => Boolean(scripts[name]));
|
|
2831
|
+
if (!scriptToRun)
|
|
2832
|
+
return false;
|
|
2833
|
+
const systemPython = process.platform === "win32" ? "python" : "python3";
|
|
2834
|
+
const finalEnv = { ...process.env, ...env };
|
|
2835
|
+
useVirtualEnv(workPath, finalEnv, systemPython);
|
|
2836
|
+
const scriptCommand = scripts[scriptToRun];
|
|
2837
|
+
if (typeof scriptCommand === "string" && scriptCommand.trim()) {
|
|
2838
|
+
console.log(`Executing: ${scriptCommand}`);
|
|
2839
|
+
await (0, import_build_utils.execCommand)(scriptCommand, {
|
|
2840
|
+
cwd: workPath,
|
|
2841
|
+
env: finalEnv
|
|
2842
|
+
});
|
|
2843
|
+
return true;
|
|
2844
|
+
}
|
|
2845
|
+
return false;
|
|
2846
|
+
}
|
|
2847
|
+
async function runUvCommand(options) {
|
|
2848
|
+
const { uvPath, args, cwd, venvPath } = options;
|
|
2849
|
+
const pretty = `uv ${args.join(" ")}`;
|
|
2850
|
+
(0, import_build_utils.debug)(`Running "${pretty}"...`);
|
|
2851
|
+
if (!uvPath) {
|
|
2852
|
+
throw new Error(`uv is required to run "${pretty}" but is not available`);
|
|
2853
|
+
}
|
|
2854
|
+
try {
|
|
2855
|
+
await execa(uvPath, args, {
|
|
2856
|
+
cwd,
|
|
2857
|
+
env: createVenvEnv(venvPath)
|
|
2858
|
+
});
|
|
2859
|
+
return true;
|
|
2860
|
+
} catch (err) {
|
|
2861
|
+
const error = new Error(
|
|
2862
|
+
`Failed to run "${pretty}": ${err instanceof Error ? err.message : String(err)}`
|
|
2863
|
+
);
|
|
2864
|
+
if (err && typeof err === "object") {
|
|
2865
|
+
if ("code" in err) {
|
|
2866
|
+
error.code = err.code;
|
|
2867
|
+
} else if ("signal" in err) {
|
|
2868
|
+
error.code = err.signal;
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
throw error;
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
function findDir({
|
|
2875
|
+
file,
|
|
2876
|
+
entryDirectory,
|
|
2877
|
+
workPath,
|
|
2878
|
+
fsFiles
|
|
2879
|
+
}) {
|
|
2880
|
+
if (fsFiles[(0, import_path.join)(entryDirectory, file)]) {
|
|
2881
|
+
return (0, import_path.join)(workPath, entryDirectory);
|
|
2882
|
+
}
|
|
2883
|
+
if (fsFiles[file]) {
|
|
2884
|
+
return workPath;
|
|
2885
|
+
}
|
|
2886
|
+
return null;
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
// src/install.ts
|
|
2890
|
+
var isWin2 = process.platform === "win32";
|
|
2891
|
+
var uvExec = isWin2 ? "uv.exe" : "uv";
|
|
2765
2892
|
var makeDependencyCheckCode = (dependency) => `
|
|
2766
2893
|
from importlib import util
|
|
2767
2894
|
dep = '${dependency}'.replace('-', '_')
|
|
@@ -2776,7 +2903,7 @@ async function isInstalled(pythonPath, dependency, cwd) {
|
|
|
2776
2903
|
{
|
|
2777
2904
|
stdio: "pipe",
|
|
2778
2905
|
cwd,
|
|
2779
|
-
env: { ...process.env, PYTHONPATH: (0,
|
|
2906
|
+
env: { ...process.env, PYTHONPATH: (0, import_path2.join)(cwd, resolveVendorDir()) }
|
|
2780
2907
|
}
|
|
2781
2908
|
);
|
|
2782
2909
|
return stdout.startsWith(cwd);
|
|
@@ -2799,7 +2926,7 @@ async function areRequirementsInstalled(pythonPath, requirementsPath, cwd) {
|
|
|
2799
2926
|
{
|
|
2800
2927
|
stdio: "pipe",
|
|
2801
2928
|
cwd,
|
|
2802
|
-
env: { ...process.env, PYTHONPATH: (0,
|
|
2929
|
+
env: { ...process.env, PYTHONPATH: (0, import_path2.join)(cwd, resolveVendorDir()) }
|
|
2803
2930
|
}
|
|
2804
2931
|
);
|
|
2805
2932
|
return true;
|
|
@@ -2807,10 +2934,334 @@ async function areRequirementsInstalled(pythonPath, requirementsPath, cwd) {
|
|
|
2807
2934
|
return false;
|
|
2808
2935
|
}
|
|
2809
2936
|
}
|
|
2937
|
+
async function runUvSync({
|
|
2938
|
+
uvPath,
|
|
2939
|
+
venvPath,
|
|
2940
|
+
projectDir,
|
|
2941
|
+
locked
|
|
2942
|
+
}) {
|
|
2943
|
+
const args = ["sync", "--active", "--no-dev"];
|
|
2944
|
+
if (locked) {
|
|
2945
|
+
args.push("--locked");
|
|
2946
|
+
}
|
|
2947
|
+
args.push("--no-editable");
|
|
2948
|
+
await runUvCommand({
|
|
2949
|
+
uvPath,
|
|
2950
|
+
args,
|
|
2951
|
+
cwd: projectDir,
|
|
2952
|
+
venvPath
|
|
2953
|
+
});
|
|
2954
|
+
}
|
|
2955
|
+
async function getSitePackagesDirs(pythonBin) {
|
|
2956
|
+
const code = `
|
|
2957
|
+
import json
|
|
2958
|
+
import sysconfig
|
|
2959
|
+
paths = []
|
|
2960
|
+
for key in ("purelib", "platlib"):
|
|
2961
|
+
candidate = sysconfig.get_path(key)
|
|
2962
|
+
if candidate and candidate not in paths:
|
|
2963
|
+
paths.append(candidate)
|
|
2964
|
+
print(json.dumps(paths))
|
|
2965
|
+
`.trim();
|
|
2966
|
+
const { stdout } = await (0, import_execa.default)(pythonBin, ["-c", code]);
|
|
2967
|
+
try {
|
|
2968
|
+
const parsed = JSON.parse(stdout);
|
|
2969
|
+
if (Array.isArray(parsed)) {
|
|
2970
|
+
return parsed.filter((p) => typeof p === "string");
|
|
2971
|
+
}
|
|
2972
|
+
} catch (err) {
|
|
2973
|
+
(0, import_build_utils2.debug)("Failed to parse site-packages output", err);
|
|
2974
|
+
}
|
|
2975
|
+
return [];
|
|
2976
|
+
}
|
|
2977
|
+
async function getVenvSitePackagesDirs(venvPath) {
|
|
2978
|
+
const pythonBin = getVenvPythonBin(venvPath);
|
|
2979
|
+
return getSitePackagesDirs(pythonBin);
|
|
2980
|
+
}
|
|
2810
2981
|
function resolveVendorDir() {
|
|
2811
2982
|
const vendorDir = process.env.VERCEL_PYTHON_VENDOR_DIR || "_vendor";
|
|
2812
2983
|
return vendorDir;
|
|
2813
2984
|
}
|
|
2985
|
+
async function detectInstallSource({
|
|
2986
|
+
workPath,
|
|
2987
|
+
entryDirectory,
|
|
2988
|
+
fsFiles
|
|
2989
|
+
}) {
|
|
2990
|
+
const uvLockDir = findDir({
|
|
2991
|
+
file: "uv.lock",
|
|
2992
|
+
entryDirectory,
|
|
2993
|
+
workPath,
|
|
2994
|
+
fsFiles
|
|
2995
|
+
});
|
|
2996
|
+
const pyprojectDir = findDir({
|
|
2997
|
+
file: "pyproject.toml",
|
|
2998
|
+
entryDirectory,
|
|
2999
|
+
workPath,
|
|
3000
|
+
fsFiles
|
|
3001
|
+
});
|
|
3002
|
+
const pipfileLockDir = findDir({
|
|
3003
|
+
file: "Pipfile.lock",
|
|
3004
|
+
entryDirectory,
|
|
3005
|
+
workPath,
|
|
3006
|
+
fsFiles
|
|
3007
|
+
});
|
|
3008
|
+
const pipfileDir = findDir({
|
|
3009
|
+
file: "Pipfile",
|
|
3010
|
+
entryDirectory,
|
|
3011
|
+
workPath,
|
|
3012
|
+
fsFiles
|
|
3013
|
+
});
|
|
3014
|
+
const requirementsDir = findDir({
|
|
3015
|
+
file: "requirements.txt",
|
|
3016
|
+
entryDirectory,
|
|
3017
|
+
workPath,
|
|
3018
|
+
fsFiles
|
|
3019
|
+
});
|
|
3020
|
+
let manifestPath = null;
|
|
3021
|
+
let manifestType = null;
|
|
3022
|
+
if (uvLockDir && pyprojectDir) {
|
|
3023
|
+
manifestType = "uv.lock";
|
|
3024
|
+
manifestPath = (0, import_path2.join)(uvLockDir, "uv.lock");
|
|
3025
|
+
} else if (pyprojectDir) {
|
|
3026
|
+
manifestType = "pyproject.toml";
|
|
3027
|
+
manifestPath = (0, import_path2.join)(pyprojectDir, "pyproject.toml");
|
|
3028
|
+
} else if (pipfileLockDir) {
|
|
3029
|
+
manifestType = "Pipfile.lock";
|
|
3030
|
+
manifestPath = (0, import_path2.join)(pipfileLockDir, "Pipfile.lock");
|
|
3031
|
+
} else if (pipfileDir) {
|
|
3032
|
+
manifestType = "Pipfile";
|
|
3033
|
+
manifestPath = (0, import_path2.join)(pipfileDir, "Pipfile");
|
|
3034
|
+
} else if (requirementsDir) {
|
|
3035
|
+
manifestType = "requirements.txt";
|
|
3036
|
+
manifestPath = (0, import_path2.join)(requirementsDir, "requirements.txt");
|
|
3037
|
+
}
|
|
3038
|
+
let manifestContent;
|
|
3039
|
+
if (manifestPath) {
|
|
3040
|
+
try {
|
|
3041
|
+
manifestContent = await import_fs2.default.promises.readFile(manifestPath, "utf8");
|
|
3042
|
+
} catch (err) {
|
|
3043
|
+
(0, import_build_utils2.debug)("Failed to read install manifest contents", err);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
return { manifestPath, manifestType, manifestContent };
|
|
3047
|
+
}
|
|
3048
|
+
async function createPyprojectToml({
|
|
3049
|
+
projectName,
|
|
3050
|
+
pyprojectPath,
|
|
3051
|
+
dependencies
|
|
3052
|
+
}) {
|
|
3053
|
+
const requiresPython = ">=3.12";
|
|
3054
|
+
const depsToml = dependencies.length > 0 ? [
|
|
3055
|
+
"dependencies = [",
|
|
3056
|
+
...dependencies.map((dep) => ` "${dep}",`),
|
|
3057
|
+
"]"
|
|
3058
|
+
].join("\n") : "dependencies = []";
|
|
3059
|
+
const content = [
|
|
3060
|
+
"[project]",
|
|
3061
|
+
`name = "${projectName}"`,
|
|
3062
|
+
'version = "0.1.0"',
|
|
3063
|
+
`requires-python = "${requiresPython}"`,
|
|
3064
|
+
"classifiers = [",
|
|
3065
|
+
' "Private :: Do Not Upload",',
|
|
3066
|
+
"]",
|
|
3067
|
+
depsToml,
|
|
3068
|
+
""
|
|
3069
|
+
].join("\n");
|
|
3070
|
+
await import_fs2.default.promises.writeFile(pyprojectPath, content);
|
|
3071
|
+
}
|
|
3072
|
+
async function uvLock({
|
|
3073
|
+
projectDir,
|
|
3074
|
+
uvPath
|
|
3075
|
+
}) {
|
|
3076
|
+
const args = ["lock"];
|
|
3077
|
+
const pretty = `${uvPath} ${args.join(" ")}`;
|
|
3078
|
+
(0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
|
|
3079
|
+
try {
|
|
3080
|
+
await (0, import_execa.default)(uvPath, args, { cwd: projectDir });
|
|
3081
|
+
} catch (err) {
|
|
3082
|
+
throw new Error(
|
|
3083
|
+
`Failed to run "${pretty}": ${err instanceof Error ? err.message : String(err)}`
|
|
3084
|
+
);
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
async function uvAddDependencies({
|
|
3088
|
+
projectDir,
|
|
3089
|
+
uvPath,
|
|
3090
|
+
venvPath,
|
|
3091
|
+
dependencies
|
|
3092
|
+
}) {
|
|
3093
|
+
const toAdd = dependencies.filter(Boolean);
|
|
3094
|
+
if (!toAdd.length)
|
|
3095
|
+
return;
|
|
3096
|
+
const args = ["add", "--active", ...toAdd];
|
|
3097
|
+
const pretty = `${uvPath} ${args.join(" ")}`;
|
|
3098
|
+
(0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
|
|
3099
|
+
await runUvCommand({ uvPath, args, cwd: projectDir, venvPath });
|
|
3100
|
+
}
|
|
3101
|
+
async function uvAddFromFile({
|
|
3102
|
+
projectDir,
|
|
3103
|
+
uvPath,
|
|
3104
|
+
venvPath,
|
|
3105
|
+
requirementsPath
|
|
3106
|
+
}) {
|
|
3107
|
+
const args = ["add", "--active", "-r", requirementsPath];
|
|
3108
|
+
const pretty = `${uvPath} ${args.join(" ")}`;
|
|
3109
|
+
(0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
|
|
3110
|
+
await runUvCommand({ uvPath, args, cwd: projectDir, venvPath });
|
|
3111
|
+
}
|
|
3112
|
+
function getDependencyName(spec) {
|
|
3113
|
+
const match = spec.match(/^[A-Za-z0-9_.-]+/);
|
|
3114
|
+
return match ? match[0].toLowerCase() : spec.toLowerCase();
|
|
3115
|
+
}
|
|
3116
|
+
async function filterMissingRuntimeDependencies({
|
|
3117
|
+
pyprojectPath,
|
|
3118
|
+
runtimeDependencies
|
|
3119
|
+
}) {
|
|
3120
|
+
let declared = [];
|
|
3121
|
+
try {
|
|
3122
|
+
const config = await (0, import_build_utils2.readConfigFile)(pyprojectPath);
|
|
3123
|
+
declared = config?.project?.dependencies || [];
|
|
3124
|
+
} catch (err) {
|
|
3125
|
+
(0, import_build_utils2.debug)("Failed to parse pyproject.toml when filtering runtime deps", err);
|
|
3126
|
+
}
|
|
3127
|
+
const declaredNames = new Set(declared.map(getDependencyName));
|
|
3128
|
+
return runtimeDependencies.filter((spec) => {
|
|
3129
|
+
const name = getDependencyName(spec);
|
|
3130
|
+
return !declaredNames.has(name);
|
|
3131
|
+
});
|
|
3132
|
+
}
|
|
3133
|
+
async function ensureUvProject({
|
|
3134
|
+
workPath,
|
|
3135
|
+
entryDirectory,
|
|
3136
|
+
fsFiles,
|
|
3137
|
+
pythonPath,
|
|
3138
|
+
pipPath,
|
|
3139
|
+
uvPath,
|
|
3140
|
+
venvPath,
|
|
3141
|
+
meta,
|
|
3142
|
+
runtimeDependencies
|
|
3143
|
+
}) {
|
|
3144
|
+
const installInfo = await detectInstallSource({
|
|
3145
|
+
workPath,
|
|
3146
|
+
entryDirectory,
|
|
3147
|
+
fsFiles
|
|
3148
|
+
});
|
|
3149
|
+
const { manifestType, manifestPath } = installInfo;
|
|
3150
|
+
let projectDir;
|
|
3151
|
+
let pyprojectPath;
|
|
3152
|
+
if (manifestType === "uv.lock") {
|
|
3153
|
+
if (!manifestPath) {
|
|
3154
|
+
throw new Error("Expected uv.lock path to be resolved, but it was null");
|
|
3155
|
+
}
|
|
3156
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3157
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3158
|
+
if (!import_fs2.default.existsSync(pyprojectPath)) {
|
|
3159
|
+
throw new Error(
|
|
3160
|
+
`Expected "pyproject.toml" next to "uv.lock" in "${projectDir}"`
|
|
3161
|
+
);
|
|
3162
|
+
}
|
|
3163
|
+
console.log("Installing required dependencies from uv.lock...");
|
|
3164
|
+
} else if (manifestType === "pyproject.toml") {
|
|
3165
|
+
if (!manifestPath) {
|
|
3166
|
+
throw new Error(
|
|
3167
|
+
"Expected pyproject.toml path to be resolved, but it was null"
|
|
3168
|
+
);
|
|
3169
|
+
}
|
|
3170
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3171
|
+
pyprojectPath = manifestPath;
|
|
3172
|
+
console.log("Installing required dependencies from pyproject.toml...");
|
|
3173
|
+
const lockPath2 = (0, import_path2.join)(projectDir, "uv.lock");
|
|
3174
|
+
if (!import_fs2.default.existsSync(lockPath2)) {
|
|
3175
|
+
await uvLock({ projectDir, uvPath });
|
|
3176
|
+
}
|
|
3177
|
+
} else if (manifestType === "Pipfile.lock" || manifestType === "Pipfile") {
|
|
3178
|
+
if (!manifestPath) {
|
|
3179
|
+
throw new Error(
|
|
3180
|
+
"Expected Pipfile/Pipfile.lock path to be resolved, but it was null"
|
|
3181
|
+
);
|
|
3182
|
+
}
|
|
3183
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3184
|
+
console.log(`Installing required dependencies from ${manifestType}...`);
|
|
3185
|
+
const exportedReq = await exportRequirementsFromPipfile({
|
|
3186
|
+
pythonPath,
|
|
3187
|
+
pipPath,
|
|
3188
|
+
uvPath,
|
|
3189
|
+
projectDir,
|
|
3190
|
+
meta
|
|
3191
|
+
});
|
|
3192
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3193
|
+
if (!import_fs2.default.existsSync(pyprojectPath)) {
|
|
3194
|
+
await createPyprojectToml({
|
|
3195
|
+
projectName: "app",
|
|
3196
|
+
pyprojectPath,
|
|
3197
|
+
dependencies: []
|
|
3198
|
+
});
|
|
3199
|
+
}
|
|
3200
|
+
await uvAddFromFile({
|
|
3201
|
+
projectDir,
|
|
3202
|
+
uvPath,
|
|
3203
|
+
venvPath,
|
|
3204
|
+
requirementsPath: exportedReq
|
|
3205
|
+
});
|
|
3206
|
+
} else if (manifestType === "requirements.txt") {
|
|
3207
|
+
if (!manifestPath) {
|
|
3208
|
+
throw new Error(
|
|
3209
|
+
"Expected requirements.txt path to be resolved, but it was null"
|
|
3210
|
+
);
|
|
3211
|
+
}
|
|
3212
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3213
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3214
|
+
console.log(
|
|
3215
|
+
"Installing required dependencies from requirements.txt with uv..."
|
|
3216
|
+
);
|
|
3217
|
+
if (!import_fs2.default.existsSync(pyprojectPath)) {
|
|
3218
|
+
await createPyprojectToml({
|
|
3219
|
+
projectName: "app",
|
|
3220
|
+
pyprojectPath,
|
|
3221
|
+
dependencies: []
|
|
3222
|
+
});
|
|
3223
|
+
}
|
|
3224
|
+
await uvAddFromFile({
|
|
3225
|
+
projectDir,
|
|
3226
|
+
uvPath,
|
|
3227
|
+
venvPath,
|
|
3228
|
+
requirementsPath: manifestPath
|
|
3229
|
+
});
|
|
3230
|
+
} else {
|
|
3231
|
+
projectDir = workPath;
|
|
3232
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3233
|
+
console.log(
|
|
3234
|
+
"No Python manifest found; creating an empty pyproject.toml and uv.lock..."
|
|
3235
|
+
);
|
|
3236
|
+
await createPyprojectToml({
|
|
3237
|
+
projectName: "app",
|
|
3238
|
+
pyprojectPath,
|
|
3239
|
+
dependencies: []
|
|
3240
|
+
});
|
|
3241
|
+
await uvLock({ projectDir, uvPath });
|
|
3242
|
+
}
|
|
3243
|
+
if (runtimeDependencies.length) {
|
|
3244
|
+
const missingRuntimeDeps = await filterMissingRuntimeDependencies({
|
|
3245
|
+
pyprojectPath,
|
|
3246
|
+
runtimeDependencies
|
|
3247
|
+
});
|
|
3248
|
+
if (missingRuntimeDeps.length) {
|
|
3249
|
+
await uvAddDependencies({
|
|
3250
|
+
projectDir,
|
|
3251
|
+
uvPath,
|
|
3252
|
+
venvPath,
|
|
3253
|
+
dependencies: missingRuntimeDeps
|
|
3254
|
+
});
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
const lockPath = (0, import_path2.join)(projectDir, "uv.lock");
|
|
3258
|
+
if (!import_fs2.default.existsSync(lockPath)) {
|
|
3259
|
+
throw new Error(
|
|
3260
|
+
`Expected "uv.lock" to exist in "${projectDir}" after preparing uv project`
|
|
3261
|
+
);
|
|
3262
|
+
}
|
|
3263
|
+
return { projectDir, pyprojectPath, lockPath };
|
|
3264
|
+
}
|
|
2814
3265
|
async function getGlobalScriptsDir(pythonPath) {
|
|
2815
3266
|
const code = `import sysconfig; print(sysconfig.get_path('scripts'))`;
|
|
2816
3267
|
try {
|
|
@@ -2818,7 +3269,7 @@ async function getGlobalScriptsDir(pythonPath) {
|
|
|
2818
3269
|
const out = stdout.trim();
|
|
2819
3270
|
return out || null;
|
|
2820
3271
|
} catch (err) {
|
|
2821
|
-
(0,
|
|
3272
|
+
(0, import_build_utils2.debug)("Failed to resolve Python global scripts directory", err);
|
|
2822
3273
|
return null;
|
|
2823
3274
|
}
|
|
2824
3275
|
}
|
|
@@ -2832,12 +3283,12 @@ async function getUserScriptsDir(pythonPath) {
|
|
|
2832
3283
|
const out = stdout.trim();
|
|
2833
3284
|
return out || null;
|
|
2834
3285
|
} catch (err) {
|
|
2835
|
-
(0,
|
|
3286
|
+
(0, import_build_utils2.debug)("Failed to resolve Python user scripts directory", err);
|
|
2836
3287
|
return null;
|
|
2837
3288
|
}
|
|
2838
3289
|
}
|
|
2839
3290
|
async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
|
|
2840
|
-
const target = targetDir ? (0,
|
|
3291
|
+
const target = targetDir ? (0, import_path2.join)(targetDir, resolveVendorDir()) : resolveVendorDir();
|
|
2841
3292
|
process.env.PIP_USER = "0";
|
|
2842
3293
|
if (uvPath) {
|
|
2843
3294
|
const uvArgs = [
|
|
@@ -2847,10 +3298,10 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
|
|
|
2847
3298
|
"--no-cache-dir",
|
|
2848
3299
|
"--target",
|
|
2849
3300
|
target,
|
|
2850
|
-
...args
|
|
3301
|
+
...filterUnsafeUvPipArgs(args)
|
|
2851
3302
|
];
|
|
2852
3303
|
const prettyUv = `${uvPath} ${uvArgs.join(" ")}`;
|
|
2853
|
-
(0,
|
|
3304
|
+
(0, import_build_utils2.debug)(`Running "${prettyUv}"...`);
|
|
2854
3305
|
try {
|
|
2855
3306
|
await (0, import_execa.default)(uvPath, uvArgs, {
|
|
2856
3307
|
cwd: workPath
|
|
@@ -2858,7 +3309,7 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
|
|
|
2858
3309
|
return;
|
|
2859
3310
|
} catch (err) {
|
|
2860
3311
|
console.log(`Failed to run "${prettyUv}", falling back to pip`);
|
|
2861
|
-
(0,
|
|
3312
|
+
(0, import_build_utils2.debug)(`error: ${err}`);
|
|
2862
3313
|
}
|
|
2863
3314
|
}
|
|
2864
3315
|
const cmdArgs = [
|
|
@@ -2871,14 +3322,14 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
|
|
|
2871
3322
|
...args
|
|
2872
3323
|
];
|
|
2873
3324
|
const pretty = `${pipPath} ${cmdArgs.join(" ")}`;
|
|
2874
|
-
(0,
|
|
3325
|
+
(0, import_build_utils2.debug)(`Running "${pretty}"...`);
|
|
2875
3326
|
try {
|
|
2876
3327
|
await (0, import_execa.default)(pipPath, cmdArgs, {
|
|
2877
3328
|
cwd: workPath
|
|
2878
3329
|
});
|
|
2879
3330
|
} catch (err) {
|
|
2880
3331
|
console.log(`Failed to run "${pretty}"`);
|
|
2881
|
-
(0,
|
|
3332
|
+
(0, import_build_utils2.debug)(`error: ${err}`);
|
|
2882
3333
|
throw err;
|
|
2883
3334
|
}
|
|
2884
3335
|
}
|
|
@@ -2889,38 +3340,38 @@ async function maybeFindUvBin(pythonPath) {
|
|
|
2889
3340
|
try {
|
|
2890
3341
|
const globalScriptsDir = await getGlobalScriptsDir(pythonPath);
|
|
2891
3342
|
if (globalScriptsDir) {
|
|
2892
|
-
const uvPath = (0,
|
|
2893
|
-
if (
|
|
3343
|
+
const uvPath = (0, import_path2.join)(globalScriptsDir, uvExec);
|
|
3344
|
+
if (import_fs2.default.existsSync(uvPath))
|
|
2894
3345
|
return uvPath;
|
|
2895
3346
|
}
|
|
2896
3347
|
} catch (err) {
|
|
2897
|
-
(0,
|
|
3348
|
+
(0, import_build_utils2.debug)("Failed to resolve Python global scripts directory", err);
|
|
2898
3349
|
}
|
|
2899
3350
|
try {
|
|
2900
3351
|
const userScriptsDir = await getUserScriptsDir(pythonPath);
|
|
2901
3352
|
if (userScriptsDir) {
|
|
2902
|
-
const uvPath = (0,
|
|
2903
|
-
if (
|
|
3353
|
+
const uvPath = (0, import_path2.join)(userScriptsDir, uvExec);
|
|
3354
|
+
if (import_fs2.default.existsSync(uvPath))
|
|
2904
3355
|
return uvPath;
|
|
2905
3356
|
}
|
|
2906
3357
|
} catch (err) {
|
|
2907
|
-
(0,
|
|
3358
|
+
(0, import_build_utils2.debug)("Failed to resolve Python user scripts directory", err);
|
|
2908
3359
|
}
|
|
2909
3360
|
try {
|
|
2910
3361
|
const candidates = [];
|
|
2911
|
-
if (!
|
|
2912
|
-
candidates.push((0,
|
|
3362
|
+
if (!isWin2) {
|
|
3363
|
+
candidates.push((0, import_path2.join)(import_os.default.homedir(), ".local", "bin", "uv"));
|
|
2913
3364
|
candidates.push("/usr/local/bin/uv");
|
|
2914
3365
|
candidates.push("/opt/homebrew/bin/uv");
|
|
2915
3366
|
} else {
|
|
2916
3367
|
candidates.push("C:\\Users\\Public\\uv\\uv.exe");
|
|
2917
3368
|
}
|
|
2918
3369
|
for (const p of candidates) {
|
|
2919
|
-
if (
|
|
3370
|
+
if (import_fs2.default.existsSync(p))
|
|
2920
3371
|
return p;
|
|
2921
3372
|
}
|
|
2922
3373
|
} catch (err) {
|
|
2923
|
-
(0,
|
|
3374
|
+
(0, import_build_utils2.debug)("Failed to resolve uv fallback paths", err);
|
|
2924
3375
|
}
|
|
2925
3376
|
return null;
|
|
2926
3377
|
}
|
|
@@ -2968,7 +3419,7 @@ async function installRequirement({
|
|
|
2968
3419
|
}) {
|
|
2969
3420
|
const actualTargetDir = targetDir || workPath;
|
|
2970
3421
|
if (meta.isDev && await isInstalled(pythonPath, dependency, actualTargetDir)) {
|
|
2971
|
-
(0,
|
|
3422
|
+
(0, import_build_utils2.debug)(
|
|
2972
3423
|
`Skipping ${dependency} dependency installation, already installed in ${actualTargetDir}`
|
|
2973
3424
|
);
|
|
2974
3425
|
return;
|
|
@@ -2988,7 +3439,7 @@ async function installRequirementsFile({
|
|
|
2988
3439
|
}) {
|
|
2989
3440
|
const actualTargetDir = targetDir || workPath;
|
|
2990
3441
|
if (meta.isDev && await areRequirementsInstalled(pythonPath, filePath, actualTargetDir)) {
|
|
2991
|
-
(0,
|
|
3442
|
+
(0, import_build_utils2.debug)(`Skipping requirements file installation, already installed`);
|
|
2992
3443
|
return;
|
|
2993
3444
|
}
|
|
2994
3445
|
await pipInstall(
|
|
@@ -2999,35 +3450,8 @@ async function installRequirementsFile({
|
|
|
2999
3450
|
targetDir
|
|
3000
3451
|
);
|
|
3001
3452
|
}
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
if (!uvPath) {
|
|
3005
|
-
throw new Error("uv is not available to export requirements");
|
|
3006
|
-
}
|
|
3007
|
-
const args = [
|
|
3008
|
-
"export",
|
|
3009
|
-
"--no-default-groups",
|
|
3010
|
-
"--no-emit-workspace",
|
|
3011
|
-
"--no-editable"
|
|
3012
|
-
];
|
|
3013
|
-
if (locked) {
|
|
3014
|
-
args.push("--frozen");
|
|
3015
|
-
}
|
|
3016
|
-
(0, import_build_utils.debug)(`Running "${uvPath} ${args.join(" ")}" in ${projectDir}...`);
|
|
3017
|
-
let stdout;
|
|
3018
|
-
try {
|
|
3019
|
-
const { stdout: out } = await (0, import_execa.default)(uvPath, args, { cwd: projectDir });
|
|
3020
|
-
stdout = out;
|
|
3021
|
-
} catch (err) {
|
|
3022
|
-
throw new Error(
|
|
3023
|
-
`Failed to run "${uvPath} ${args.join(" ")}": ${err instanceof Error ? err.message : String(err)}`
|
|
3024
|
-
);
|
|
3025
|
-
}
|
|
3026
|
-
const tmpDir = await import_fs.default.promises.mkdtemp((0, import_path.join)(import_os.default.tmpdir(), "vercel-uv-"));
|
|
3027
|
-
const outPath = (0, import_path.join)(tmpDir, "requirements.uv.txt");
|
|
3028
|
-
await import_fs.default.promises.writeFile(outPath, stdout);
|
|
3029
|
-
(0, import_build_utils.debug)(`Exported requirements to ${outPath}`);
|
|
3030
|
-
return outPath;
|
|
3453
|
+
function filterUnsafeUvPipArgs(args) {
|
|
3454
|
+
return args.filter((arg) => arg !== "--no-warn-script-location");
|
|
3031
3455
|
}
|
|
3032
3456
|
async function exportRequirementsFromPipfile({
|
|
3033
3457
|
pythonPath,
|
|
@@ -3036,8 +3460,8 @@ async function exportRequirementsFromPipfile({
|
|
|
3036
3460
|
projectDir,
|
|
3037
3461
|
meta
|
|
3038
3462
|
}) {
|
|
3039
|
-
const tempDir = await
|
|
3040
|
-
(0,
|
|
3463
|
+
const tempDir = await import_fs2.default.promises.mkdtemp(
|
|
3464
|
+
(0, import_path2.join)(import_os.default.tmpdir(), "vercel-pipenv-")
|
|
3041
3465
|
);
|
|
3042
3466
|
await installRequirement({
|
|
3043
3467
|
pythonPath,
|
|
@@ -3049,9 +3473,9 @@ async function exportRequirementsFromPipfile({
|
|
|
3049
3473
|
args: ["--no-warn-script-location"],
|
|
3050
3474
|
uvPath
|
|
3051
3475
|
});
|
|
3052
|
-
const tempVendorDir = (0,
|
|
3053
|
-
const convertCmd =
|
|
3054
|
-
(0,
|
|
3476
|
+
const tempVendorDir = (0, import_path2.join)(tempDir, resolveVendorDir());
|
|
3477
|
+
const convertCmd = isWin2 ? (0, import_path2.join)(tempVendorDir, "Scripts", "pipfile2req.exe") : (0, import_path2.join)(tempVendorDir, "bin", "pipfile2req");
|
|
3478
|
+
(0, import_build_utils2.debug)(`Running "${convertCmd}" in ${projectDir}...`);
|
|
3055
3479
|
let stdout;
|
|
3056
3480
|
try {
|
|
3057
3481
|
const { stdout: out } = await (0, import_execa.default)(convertCmd, [], {
|
|
@@ -3064,17 +3488,46 @@ async function exportRequirementsFromPipfile({
|
|
|
3064
3488
|
`Failed to run "${convertCmd}": ${err instanceof Error ? err.message : String(err)}`
|
|
3065
3489
|
);
|
|
3066
3490
|
}
|
|
3067
|
-
const outPath = (0,
|
|
3068
|
-
await
|
|
3069
|
-
(0,
|
|
3491
|
+
const outPath = (0, import_path2.join)(tempDir, "requirements.pipenv.txt");
|
|
3492
|
+
await import_fs2.default.promises.writeFile(outPath, stdout);
|
|
3493
|
+
(0, import_build_utils2.debug)(`Exported pipfile requirements to ${outPath}`);
|
|
3070
3494
|
return outPath;
|
|
3071
3495
|
}
|
|
3496
|
+
async function mirrorSitePackagesIntoVendor({
|
|
3497
|
+
venvPath,
|
|
3498
|
+
vendorDirName
|
|
3499
|
+
}) {
|
|
3500
|
+
const vendorFiles = {};
|
|
3501
|
+
try {
|
|
3502
|
+
const sitePackageDirs = await getVenvSitePackagesDirs(venvPath);
|
|
3503
|
+
for (const dir of sitePackageDirs) {
|
|
3504
|
+
if (!import_fs2.default.existsSync(dir))
|
|
3505
|
+
continue;
|
|
3506
|
+
const dirFiles = await (0, import_build_utils2.glob)("**", dir);
|
|
3507
|
+
for (const relativePath of Object.keys(dirFiles)) {
|
|
3508
|
+
if (relativePath.endsWith(".pyc") || relativePath.includes("__pycache__")) {
|
|
3509
|
+
continue;
|
|
3510
|
+
}
|
|
3511
|
+
const srcFsPath = (0, import_path2.join)(dir, relativePath);
|
|
3512
|
+
const bundlePath = (0, import_path2.join)(vendorDirName, relativePath).replace(
|
|
3513
|
+
/\\/g,
|
|
3514
|
+
"/"
|
|
3515
|
+
);
|
|
3516
|
+
vendorFiles[bundlePath] = new import_build_utils2.FileFsRef({ fsPath: srcFsPath });
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
} catch (err) {
|
|
3520
|
+
console.log("Failed to collect site-packages from virtual environment");
|
|
3521
|
+
throw err;
|
|
3522
|
+
}
|
|
3523
|
+
return vendorFiles;
|
|
3524
|
+
}
|
|
3072
3525
|
|
|
3073
3526
|
// src/index.ts
|
|
3074
|
-
var
|
|
3527
|
+
var import_build_utils8 = require("@vercel/build-utils");
|
|
3075
3528
|
|
|
3076
3529
|
// src/version.ts
|
|
3077
|
-
var
|
|
3530
|
+
var import_build_utils3 = require("@vercel/build-utils");
|
|
3078
3531
|
var import_which2 = __toESM(require_lib());
|
|
3079
3532
|
var allOptions = [
|
|
3080
3533
|
{
|
|
@@ -3125,7 +3578,7 @@ function getLatestPythonVersion({
|
|
|
3125
3578
|
}
|
|
3126
3579
|
const selection = allOptions.find(isInstalled2);
|
|
3127
3580
|
if (!selection) {
|
|
3128
|
-
throw new
|
|
3581
|
+
throw new import_build_utils3.NowBuildError({
|
|
3129
3582
|
code: "PYTHON_NOT_FOUND",
|
|
3130
3583
|
link: "http://vercel.link/python-version",
|
|
3131
3584
|
message: `Unable to find any supported Python versions.`
|
|
@@ -3226,7 +3679,7 @@ function getSupportedPythonVersion({
|
|
|
3226
3679
|
}
|
|
3227
3680
|
if (requested) {
|
|
3228
3681
|
if (isDiscontinued(requested)) {
|
|
3229
|
-
throw new
|
|
3682
|
+
throw new import_build_utils3.NowBuildError({
|
|
3230
3683
|
code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
|
|
3231
3684
|
link: "http://vercel.link/python-version",
|
|
3232
3685
|
message: `Python version "${requested.version}" detected in ${source} is discontinued and must be upgraded.`
|
|
@@ -3257,7 +3710,7 @@ function getSupportedPythonVersion({
|
|
|
3257
3710
|
);
|
|
3258
3711
|
}
|
|
3259
3712
|
if (isDiscontinued(selection)) {
|
|
3260
|
-
throw new
|
|
3713
|
+
throw new import_build_utils3.NowBuildError({
|
|
3261
3714
|
code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
|
|
3262
3715
|
link: "http://vercel.link/python-version",
|
|
3263
3716
|
message: `Python version "${selection.version}" declared in project configuration is discontinued and must be upgraded.`
|
|
@@ -3287,16 +3740,16 @@ var import_path4 = require("path");
|
|
|
3287
3740
|
var import_build_utils6 = require("@vercel/build-utils");
|
|
3288
3741
|
|
|
3289
3742
|
// src/entrypoint.ts
|
|
3290
|
-
var
|
|
3291
|
-
var
|
|
3292
|
-
var import_build_utils3 = require("@vercel/build-utils");
|
|
3743
|
+
var import_fs3 = __toESM(require("fs"));
|
|
3744
|
+
var import_path3 = require("path");
|
|
3293
3745
|
var import_build_utils4 = require("@vercel/build-utils");
|
|
3746
|
+
var import_build_utils5 = require("@vercel/build-utils");
|
|
3294
3747
|
var FASTAPI_ENTRYPOINT_FILENAMES = ["app", "index", "server", "main"];
|
|
3295
3748
|
var FASTAPI_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
|
|
3296
3749
|
var FASTAPI_CONTENT_REGEX = /(from\s+fastapi\s+import\s+FastAPI|import\s+fastapi|FastAPI\s*\()/;
|
|
3297
3750
|
var FASTAPI_CANDIDATE_ENTRYPOINTS = FASTAPI_ENTRYPOINT_FILENAMES.flatMap(
|
|
3298
3751
|
(filename) => FASTAPI_ENTRYPOINT_DIRS.map(
|
|
3299
|
-
(dir) =>
|
|
3752
|
+
(dir) => import_path3.posix.join(dir, `${filename}.py`)
|
|
3300
3753
|
)
|
|
3301
3754
|
);
|
|
3302
3755
|
function isFastapiEntrypoint(file) {
|
|
@@ -3304,7 +3757,7 @@ function isFastapiEntrypoint(file) {
|
|
|
3304
3757
|
const fsPath = file.fsPath;
|
|
3305
3758
|
if (!fsPath)
|
|
3306
3759
|
return false;
|
|
3307
|
-
const contents =
|
|
3760
|
+
const contents = import_fs3.default.readFileSync(fsPath, "utf8");
|
|
3308
3761
|
return FASTAPI_CONTENT_REGEX.test(contents);
|
|
3309
3762
|
} catch {
|
|
3310
3763
|
return false;
|
|
@@ -3315,7 +3768,7 @@ var FLASK_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
|
|
|
3315
3768
|
var FLASK_CONTENT_REGEX = /(from\s+flask\s+import\s+Flask|import\s+flask|Flask\s*\()/;
|
|
3316
3769
|
var FLASK_CANDIDATE_ENTRYPOINTS = FLASK_ENTRYPOINT_FILENAMES.flatMap(
|
|
3317
3770
|
(filename) => FLASK_ENTRYPOINT_DIRS.map(
|
|
3318
|
-
(dir) =>
|
|
3771
|
+
(dir) => import_path3.posix.join(dir, `${filename}.py`)
|
|
3319
3772
|
)
|
|
3320
3773
|
);
|
|
3321
3774
|
function isFlaskEntrypoint(file) {
|
|
@@ -3323,7 +3776,7 @@ function isFlaskEntrypoint(file) {
|
|
|
3323
3776
|
const fsPath = file.fsPath;
|
|
3324
3777
|
if (!fsPath)
|
|
3325
3778
|
return false;
|
|
3326
|
-
const contents =
|
|
3779
|
+
const contents = import_fs3.default.readFileSync(fsPath, "utf8");
|
|
3327
3780
|
return FLASK_CONTENT_REGEX.test(contents);
|
|
3328
3781
|
} catch {
|
|
3329
3782
|
return false;
|
|
@@ -3332,7 +3785,7 @@ function isFlaskEntrypoint(file) {
|
|
|
3332
3785
|
async function detectFlaskEntrypoint(workPath, configuredEntrypoint) {
|
|
3333
3786
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
3334
3787
|
try {
|
|
3335
|
-
const fsFiles = await (0,
|
|
3788
|
+
const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
|
|
3336
3789
|
if (fsFiles[entry])
|
|
3337
3790
|
return entry;
|
|
3338
3791
|
const candidates = FLASK_CANDIDATE_ENTRYPOINTS.filter(
|
|
@@ -3342,19 +3795,19 @@ async function detectFlaskEntrypoint(workPath, configuredEntrypoint) {
|
|
|
3342
3795
|
const flaskEntrypoint = candidates.find(
|
|
3343
3796
|
(c) => isFlaskEntrypoint(fsFiles[c])
|
|
3344
3797
|
) || candidates[0];
|
|
3345
|
-
(0,
|
|
3798
|
+
(0, import_build_utils4.debug)(`Detected Flask entrypoint: ${flaskEntrypoint}`);
|
|
3346
3799
|
return flaskEntrypoint;
|
|
3347
3800
|
}
|
|
3348
3801
|
return null;
|
|
3349
3802
|
} catch {
|
|
3350
|
-
(0,
|
|
3803
|
+
(0, import_build_utils4.debug)("Failed to discover entrypoint for Flask");
|
|
3351
3804
|
return null;
|
|
3352
3805
|
}
|
|
3353
3806
|
}
|
|
3354
3807
|
async function detectFastapiEntrypoint(workPath, configuredEntrypoint) {
|
|
3355
3808
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
3356
3809
|
try {
|
|
3357
|
-
const fsFiles = await (0,
|
|
3810
|
+
const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
|
|
3358
3811
|
if (fsFiles[entry])
|
|
3359
3812
|
return entry;
|
|
3360
3813
|
const candidates = FASTAPI_CANDIDATE_ENTRYPOINTS.filter(
|
|
@@ -3364,17 +3817,17 @@ async function detectFastapiEntrypoint(workPath, configuredEntrypoint) {
|
|
|
3364
3817
|
const fastapiEntrypoint = candidates.find(
|
|
3365
3818
|
(c) => isFastapiEntrypoint(fsFiles[c])
|
|
3366
3819
|
) || candidates[0];
|
|
3367
|
-
(0,
|
|
3820
|
+
(0, import_build_utils4.debug)(`Detected FastAPI entrypoint: ${fastapiEntrypoint}`);
|
|
3368
3821
|
return fastapiEntrypoint;
|
|
3369
3822
|
}
|
|
3370
3823
|
return null;
|
|
3371
3824
|
} catch {
|
|
3372
|
-
(0,
|
|
3825
|
+
(0, import_build_utils4.debug)("Failed to discover entrypoint for FastAPI");
|
|
3373
3826
|
return null;
|
|
3374
3827
|
}
|
|
3375
3828
|
}
|
|
3376
3829
|
async function getPyprojectEntrypoint(workPath) {
|
|
3377
|
-
const pyprojectData = await (0,
|
|
3830
|
+
const pyprojectData = await (0, import_build_utils5.readConfigFile)((0, import_path3.join)(workPath, "pyproject.toml"));
|
|
3378
3831
|
if (!pyprojectData)
|
|
3379
3832
|
return null;
|
|
3380
3833
|
const scripts = pyprojectData.project?.scripts;
|
|
@@ -3387,7 +3840,7 @@ async function getPyprojectEntrypoint(workPath) {
|
|
|
3387
3840
|
const modulePath = match[1];
|
|
3388
3841
|
const relPath = modulePath.replace(/\./g, "/");
|
|
3389
3842
|
try {
|
|
3390
|
-
const fsFiles = await (0,
|
|
3843
|
+
const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
|
|
3391
3844
|
const candidates = [`${relPath}.py`, `${relPath}/__init__.py`];
|
|
3392
3845
|
for (const candidate of candidates) {
|
|
3393
3846
|
if (fsFiles[candidate])
|
|
@@ -3395,7 +3848,7 @@ async function getPyprojectEntrypoint(workPath) {
|
|
|
3395
3848
|
}
|
|
3396
3849
|
return null;
|
|
3397
3850
|
} catch {
|
|
3398
|
-
(0,
|
|
3851
|
+
(0, import_build_utils4.debug)("Failed to discover Python entrypoint from pyproject.toml");
|
|
3399
3852
|
return null;
|
|
3400
3853
|
}
|
|
3401
3854
|
}
|
|
@@ -3411,61 +3864,6 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint)
|
|
|
3411
3864
|
return await getPyprojectEntrypoint(workPath);
|
|
3412
3865
|
}
|
|
3413
3866
|
|
|
3414
|
-
// src/utils.ts
|
|
3415
|
-
var import_fs3 = __toESM(require("fs"));
|
|
3416
|
-
var import_path3 = require("path");
|
|
3417
|
-
var import_build_utils5 = require("@vercel/build-utils");
|
|
3418
|
-
var isInVirtualEnv = () => {
|
|
3419
|
-
return process.env.VIRTUAL_ENV;
|
|
3420
|
-
};
|
|
3421
|
-
function useVirtualEnv(workPath, env, systemPython) {
|
|
3422
|
-
const venvDirs = [".venv", "venv"];
|
|
3423
|
-
let pythonCmd = systemPython;
|
|
3424
|
-
for (const venv of venvDirs) {
|
|
3425
|
-
const venvRoot = (0, import_path3.join)(workPath, venv);
|
|
3426
|
-
const binDir = process.platform === "win32" ? (0, import_path3.join)(venvRoot, "Scripts") : (0, import_path3.join)(venvRoot, "bin");
|
|
3427
|
-
const candidates = process.platform === "win32" ? [(0, import_path3.join)(binDir, "python.exe"), (0, import_path3.join)(binDir, "python")] : [(0, import_path3.join)(binDir, "python3"), (0, import_path3.join)(binDir, "python")];
|
|
3428
|
-
const found = candidates.find((p) => import_fs3.default.existsSync(p));
|
|
3429
|
-
if (found) {
|
|
3430
|
-
pythonCmd = found;
|
|
3431
|
-
env.VIRTUAL_ENV = venvRoot;
|
|
3432
|
-
env.PATH = `${binDir}${import_path3.delimiter}${env.PATH || ""}`;
|
|
3433
|
-
return { pythonCmd, venvRoot };
|
|
3434
|
-
}
|
|
3435
|
-
}
|
|
3436
|
-
return { pythonCmd };
|
|
3437
|
-
}
|
|
3438
|
-
async function runPyprojectScript(workPath, scriptNames, env) {
|
|
3439
|
-
const pyprojectPath = (0, import_path3.join)(workPath, "pyproject.toml");
|
|
3440
|
-
if (!import_fs3.default.existsSync(pyprojectPath))
|
|
3441
|
-
return false;
|
|
3442
|
-
let pyproject = null;
|
|
3443
|
-
try {
|
|
3444
|
-
pyproject = await (0, import_build_utils5.readConfigFile)(pyprojectPath);
|
|
3445
|
-
} catch {
|
|
3446
|
-
console.error("Failed to parse pyproject.toml");
|
|
3447
|
-
return false;
|
|
3448
|
-
}
|
|
3449
|
-
const scripts = pyproject?.tool?.vercel?.scripts || {};
|
|
3450
|
-
const candidates = typeof scriptNames === "string" ? [scriptNames] : Array.from(scriptNames);
|
|
3451
|
-
const scriptToRun = candidates.find((name) => Boolean(scripts[name]));
|
|
3452
|
-
if (!scriptToRun)
|
|
3453
|
-
return false;
|
|
3454
|
-
const systemPython = process.platform === "win32" ? "python" : "python3";
|
|
3455
|
-
const finalEnv = { ...process.env, ...env };
|
|
3456
|
-
useVirtualEnv(workPath, finalEnv, systemPython);
|
|
3457
|
-
const scriptCommand = scripts[scriptToRun];
|
|
3458
|
-
if (typeof scriptCommand === "string" && scriptCommand.trim()) {
|
|
3459
|
-
console.log(`Executing: ${scriptCommand}`);
|
|
3460
|
-
await (0, import_build_utils5.execCommand)(scriptCommand, {
|
|
3461
|
-
cwd: workPath,
|
|
3462
|
-
env: finalEnv
|
|
3463
|
-
});
|
|
3464
|
-
return true;
|
|
3465
|
-
}
|
|
3466
|
-
return false;
|
|
3467
|
-
}
|
|
3468
|
-
|
|
3469
3867
|
// src/start-dev-server.ts
|
|
3470
3868
|
function silenceNodeWarnings() {
|
|
3471
3869
|
const original = process.emitWarning.bind(
|
|
@@ -3835,159 +4233,37 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3835
4233
|
}
|
|
3836
4234
|
};
|
|
3837
4235
|
|
|
3838
|
-
// src/uv-workspace.ts
|
|
3839
|
-
var import_fs5 = __toESM(require("fs"));
|
|
3840
|
-
var import_os2 = __toESM(require("os"));
|
|
3841
|
-
var import_path5 = require("path");
|
|
3842
|
-
var import_build_utils7 = require("@vercel/build-utils");
|
|
3843
|
-
function getDependencyName(spec) {
|
|
3844
|
-
const match = spec.match(/^[A-Za-z0-9_.-]+/);
|
|
3845
|
-
return match ? match[0] : null;
|
|
3846
|
-
}
|
|
3847
|
-
async function installUvWorkspaceDependencies({
|
|
3848
|
-
repoRootPath,
|
|
3849
|
-
pyprojectDir,
|
|
3850
|
-
pythonPath,
|
|
3851
|
-
pipPath,
|
|
3852
|
-
uvPath,
|
|
3853
|
-
workPath,
|
|
3854
|
-
vendorBaseDir,
|
|
3855
|
-
meta
|
|
3856
|
-
}) {
|
|
3857
|
-
if (!repoRootPath || !pyprojectDir) {
|
|
3858
|
-
return;
|
|
3859
|
-
}
|
|
3860
|
-
let rootPyproject = null;
|
|
3861
|
-
try {
|
|
3862
|
-
rootPyproject = await (0, import_build_utils7.readConfigFile)(
|
|
3863
|
-
(0, import_path5.join)(repoRootPath, "pyproject.toml")
|
|
3864
|
-
);
|
|
3865
|
-
} catch (err) {
|
|
3866
|
-
(0, import_build_utils7.debug)("Failed to parse workspace root pyproject.toml", err);
|
|
3867
|
-
}
|
|
3868
|
-
const uvTool = rootPyproject?.tool?.uv;
|
|
3869
|
-
const workspaceCfg = uvTool?.workspace;
|
|
3870
|
-
const sourcesCfg = uvTool?.sources;
|
|
3871
|
-
if (!workspaceCfg || !sourcesCfg) {
|
|
3872
|
-
return;
|
|
3873
|
-
}
|
|
3874
|
-
const workspaceSourceNames = new Set(
|
|
3875
|
-
Object.entries(sourcesCfg).filter(([, src]) => src && src.workspace).map(([name]) => name)
|
|
3876
|
-
);
|
|
3877
|
-
if (!workspaceSourceNames.size) {
|
|
3878
|
-
return;
|
|
3879
|
-
}
|
|
3880
|
-
let appPyproject = null;
|
|
3881
|
-
try {
|
|
3882
|
-
appPyproject = await (0, import_build_utils7.readConfigFile)(
|
|
3883
|
-
(0, import_path5.join)(pyprojectDir, "pyproject.toml")
|
|
3884
|
-
);
|
|
3885
|
-
} catch (err) {
|
|
3886
|
-
(0, import_build_utils7.debug)("Failed to parse app pyproject.toml for workspace deps", err);
|
|
3887
|
-
}
|
|
3888
|
-
const appDeps = appPyproject?.project?.dependencies ?? [];
|
|
3889
|
-
const workspaceDepsForApp = /* @__PURE__ */ new Set();
|
|
3890
|
-
for (const spec of appDeps) {
|
|
3891
|
-
const name = getDependencyName(spec);
|
|
3892
|
-
if (name && workspaceSourceNames.has(name)) {
|
|
3893
|
-
workspaceDepsForApp.add(name);
|
|
3894
|
-
}
|
|
3895
|
-
}
|
|
3896
|
-
if (!workspaceDepsForApp.size) {
|
|
3897
|
-
return;
|
|
3898
|
-
}
|
|
3899
|
-
const members = workspaceCfg.members ?? [];
|
|
3900
|
-
const nameToDir = /* @__PURE__ */ new Map();
|
|
3901
|
-
for (const member of members) {
|
|
3902
|
-
const memberDir = (0, import_path5.join)(repoRootPath, member);
|
|
3903
|
-
let memberPyproject = null;
|
|
3904
|
-
try {
|
|
3905
|
-
memberPyproject = await (0, import_build_utils7.readConfigFile)(
|
|
3906
|
-
(0, import_path5.join)(memberDir, "pyproject.toml")
|
|
3907
|
-
);
|
|
3908
|
-
} catch (err) {
|
|
3909
|
-
(0, import_build_utils7.debug)("Failed to parse workspace member pyproject.toml", err);
|
|
3910
|
-
continue;
|
|
3911
|
-
}
|
|
3912
|
-
const projectName = memberPyproject?.project?.name;
|
|
3913
|
-
if (projectName) {
|
|
3914
|
-
nameToDir.set(projectName, memberDir);
|
|
3915
|
-
}
|
|
3916
|
-
}
|
|
3917
|
-
const requirementLines = [];
|
|
3918
|
-
for (const name of workspaceDepsForApp) {
|
|
3919
|
-
const dir = nameToDir.get(name);
|
|
3920
|
-
if (!dir) {
|
|
3921
|
-
(0, import_build_utils7.debug)(
|
|
3922
|
-
`uv workspace dependency "${name}" declared but corresponding member directory not found`
|
|
3923
|
-
);
|
|
3924
|
-
continue;
|
|
3925
|
-
}
|
|
3926
|
-
requirementLines.push(dir);
|
|
3927
|
-
}
|
|
3928
|
-
if (!requirementLines.length) {
|
|
3929
|
-
return;
|
|
3930
|
-
}
|
|
3931
|
-
const tmpDir = await import_fs5.default.promises.mkdtemp(
|
|
3932
|
-
(0, import_path5.join)(import_os2.default.tmpdir(), "vercel-uv-workspace-")
|
|
3933
|
-
);
|
|
3934
|
-
const reqPath = (0, import_path5.join)(tmpDir, "requirements.workspace.txt");
|
|
3935
|
-
await import_fs5.default.promises.writeFile(reqPath, requirementLines.join("\n"));
|
|
3936
|
-
await installRequirementsFile({
|
|
3937
|
-
pythonPath,
|
|
3938
|
-
pipPath,
|
|
3939
|
-
uvPath,
|
|
3940
|
-
filePath: reqPath,
|
|
3941
|
-
workPath,
|
|
3942
|
-
targetDir: vendorBaseDir,
|
|
3943
|
-
meta
|
|
3944
|
-
});
|
|
3945
|
-
}
|
|
3946
|
-
|
|
3947
4236
|
// src/index.ts
|
|
3948
|
-
var readFile = (0, import_util.promisify)(
|
|
3949
|
-
var writeFile = (0, import_util.promisify)(
|
|
4237
|
+
var readFile = (0, import_util.promisify)(import_fs5.default.readFile);
|
|
4238
|
+
var writeFile = (0, import_util.promisify)(import_fs5.default.writeFile);
|
|
3950
4239
|
var version = 3;
|
|
3951
|
-
function findDir({
|
|
3952
|
-
file,
|
|
3953
|
-
entryDirectory,
|
|
3954
|
-
workPath,
|
|
3955
|
-
fsFiles
|
|
3956
|
-
}) {
|
|
3957
|
-
if (fsFiles[(0, import_path6.join)(entryDirectory, file)]) {
|
|
3958
|
-
return (0, import_path6.join)(workPath, entryDirectory);
|
|
3959
|
-
}
|
|
3960
|
-
if (fsFiles[file]) {
|
|
3961
|
-
return workPath;
|
|
3962
|
-
}
|
|
3963
|
-
return null;
|
|
3964
|
-
}
|
|
3965
4240
|
async function downloadFilesInWorkPath({
|
|
3966
4241
|
entrypoint,
|
|
3967
4242
|
workPath,
|
|
3968
4243
|
files,
|
|
3969
4244
|
meta = {}
|
|
3970
4245
|
}) {
|
|
3971
|
-
(0,
|
|
3972
|
-
let downloadedFiles = await (0,
|
|
4246
|
+
(0, import_build_utils7.debug)("Downloading user files...");
|
|
4247
|
+
let downloadedFiles = await (0, import_build_utils7.download)(files, workPath, meta);
|
|
3973
4248
|
if (meta.isDev) {
|
|
3974
|
-
const { devCacheDir = (0,
|
|
3975
|
-
const destCache = (0,
|
|
3976
|
-
await (0,
|
|
3977
|
-
downloadedFiles = await (0,
|
|
4249
|
+
const { devCacheDir = (0, import_path5.join)(workPath, ".now", "cache") } = meta;
|
|
4250
|
+
const destCache = (0, import_path5.join)(devCacheDir, (0, import_path5.basename)(entrypoint, ".py"));
|
|
4251
|
+
await (0, import_build_utils7.download)(downloadedFiles, destCache);
|
|
4252
|
+
downloadedFiles = await (0, import_build_utils7.glob)("**", destCache);
|
|
3978
4253
|
workPath = destCache;
|
|
3979
4254
|
}
|
|
3980
4255
|
return workPath;
|
|
3981
4256
|
}
|
|
3982
4257
|
var build = async ({
|
|
3983
4258
|
workPath,
|
|
3984
|
-
repoRootPath,
|
|
3985
4259
|
files: originalFiles,
|
|
3986
4260
|
entrypoint,
|
|
3987
4261
|
meta = {},
|
|
3988
4262
|
config
|
|
3989
4263
|
}) => {
|
|
3990
4264
|
const framework = config?.framework;
|
|
4265
|
+
let spawnEnv;
|
|
4266
|
+
let projectInstallCommand;
|
|
3991
4267
|
workPath = await downloadFilesInWorkPath({
|
|
3992
4268
|
workPath,
|
|
3993
4269
|
files: originalFiles,
|
|
@@ -3996,7 +4272,7 @@ var build = async ({
|
|
|
3996
4272
|
});
|
|
3997
4273
|
try {
|
|
3998
4274
|
if (meta.isDev) {
|
|
3999
|
-
const setupCfg = (0,
|
|
4275
|
+
const setupCfg = (0, import_path5.join)(workPath, "setup.cfg");
|
|
4000
4276
|
await writeFile(setupCfg, "[install]\nprefix=\n");
|
|
4001
4277
|
}
|
|
4002
4278
|
} catch (err) {
|
|
@@ -4009,8 +4285,8 @@ var build = async ({
|
|
|
4009
4285
|
lockfileVersion,
|
|
4010
4286
|
packageJsonPackageManager,
|
|
4011
4287
|
turboSupportsCorepackHome
|
|
4012
|
-
} = await (0,
|
|
4013
|
-
|
|
4288
|
+
} = await (0, import_build_utils7.scanParentDirs)(workPath, true);
|
|
4289
|
+
spawnEnv = (0, import_build_utils7.getEnvForPackageManager)({
|
|
4014
4290
|
cliType,
|
|
4015
4291
|
lockfileVersion,
|
|
4016
4292
|
packageJsonPackageManager,
|
|
@@ -4020,12 +4296,9 @@ var build = async ({
|
|
|
4020
4296
|
});
|
|
4021
4297
|
const installCommand = config?.projectSettings?.installCommand;
|
|
4022
4298
|
if (typeof installCommand === "string") {
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
env: spawnEnv,
|
|
4027
|
-
cwd: workPath
|
|
4028
|
-
});
|
|
4299
|
+
const trimmed = installCommand.trim();
|
|
4300
|
+
if (trimmed) {
|
|
4301
|
+
projectInstallCommand = trimmed;
|
|
4029
4302
|
} else {
|
|
4030
4303
|
console.log('Skipping "install" command...');
|
|
4031
4304
|
}
|
|
@@ -4034,7 +4307,7 @@ var build = async ({
|
|
|
4034
4307
|
config?.buildCommand;
|
|
4035
4308
|
if (projectBuildCommand) {
|
|
4036
4309
|
console.log(`Running "${projectBuildCommand}"`);
|
|
4037
|
-
await (0,
|
|
4310
|
+
await (0, import_build_utils7.execCommand)(projectBuildCommand, {
|
|
4038
4311
|
env: spawnEnv,
|
|
4039
4312
|
cwd: workPath
|
|
4040
4313
|
});
|
|
@@ -4046,7 +4319,7 @@ var build = async ({
|
|
|
4046
4319
|
);
|
|
4047
4320
|
}
|
|
4048
4321
|
}
|
|
4049
|
-
let fsFiles = await (0,
|
|
4322
|
+
let fsFiles = await (0, import_build_utils7.glob)("**", workPath);
|
|
4050
4323
|
if ((framework === "fastapi" || framework === "flask") && (!fsFiles[entrypoint] || !entrypoint.endsWith(".py"))) {
|
|
4051
4324
|
const detected = await detectPythonEntrypoint(
|
|
4052
4325
|
config.framework,
|
|
@@ -4054,13 +4327,13 @@ var build = async ({
|
|
|
4054
4327
|
entrypoint
|
|
4055
4328
|
);
|
|
4056
4329
|
if (detected) {
|
|
4057
|
-
(0,
|
|
4330
|
+
(0, import_build_utils7.debug)(
|
|
4058
4331
|
`Resolved Python entrypoint to "${detected}" (configured "${entrypoint}" not found).`
|
|
4059
4332
|
);
|
|
4060
4333
|
entrypoint = detected;
|
|
4061
4334
|
} else {
|
|
4062
4335
|
const searchedList = framework === "fastapi" ? FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ") : FLASK_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
4063
|
-
throw new
|
|
4336
|
+
throw new import_build_utils7.NowBuildError({
|
|
4064
4337
|
code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
|
|
4065
4338
|
message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
|
|
4066
4339
|
link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
|
|
@@ -4068,46 +4341,42 @@ var build = async ({
|
|
|
4068
4341
|
});
|
|
4069
4342
|
}
|
|
4070
4343
|
}
|
|
4071
|
-
const entryDirectory = (0,
|
|
4072
|
-
const
|
|
4073
|
-
|
|
4074
|
-
const uvLockDir = findDir({
|
|
4075
|
-
file: "uv.lock",
|
|
4344
|
+
const entryDirectory = (0, import_path5.dirname)(entrypoint);
|
|
4345
|
+
const pyprojectDir = findDir({
|
|
4346
|
+
file: "pyproject.toml",
|
|
4076
4347
|
entryDirectory,
|
|
4077
4348
|
workPath,
|
|
4078
4349
|
fsFiles
|
|
4079
4350
|
});
|
|
4080
|
-
const
|
|
4081
|
-
file: "
|
|
4351
|
+
const pipfileLockDir = findDir({
|
|
4352
|
+
file: "Pipfile.lock",
|
|
4082
4353
|
entryDirectory,
|
|
4083
4354
|
workPath,
|
|
4084
4355
|
fsFiles
|
|
4085
4356
|
});
|
|
4086
|
-
const pipfileLockDir = fsFiles[(0, import_path6.join)(entryDirectory, "Pipfile.lock")] ? (0, import_path6.join)(workPath, entryDirectory) : fsFiles["Pipfile.lock"] ? workPath : null;
|
|
4087
|
-
const pipfileDir = fsFiles[(0, import_path6.join)(entryDirectory, "Pipfile")] ? (0, import_path6.join)(workPath, entryDirectory) : fsFiles["Pipfile"] ? workPath : null;
|
|
4088
4357
|
let declaredPythonVersion;
|
|
4089
4358
|
if (pyprojectDir) {
|
|
4090
4359
|
let requiresPython;
|
|
4091
4360
|
try {
|
|
4092
|
-
const pyproject = await (0,
|
|
4361
|
+
const pyproject = await (0, import_build_utils8.readConfigFile)((0, import_path5.join)(pyprojectDir, "pyproject.toml"));
|
|
4093
4362
|
requiresPython = pyproject?.project?.["requires-python"];
|
|
4094
4363
|
} catch (err) {
|
|
4095
|
-
(0,
|
|
4364
|
+
(0, import_build_utils7.debug)("Failed to parse pyproject.toml", err);
|
|
4096
4365
|
}
|
|
4097
4366
|
if (typeof requiresPython === "string" && requiresPython.trim()) {
|
|
4098
4367
|
declaredPythonVersion = {
|
|
4099
4368
|
version: requiresPython.trim(),
|
|
4100
4369
|
source: "pyproject.toml"
|
|
4101
4370
|
};
|
|
4102
|
-
(0,
|
|
4371
|
+
(0, import_build_utils7.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
|
|
4103
4372
|
}
|
|
4104
4373
|
} else if (pipfileLockDir) {
|
|
4105
4374
|
let lock = {};
|
|
4106
4375
|
try {
|
|
4107
|
-
const json = await readFile((0,
|
|
4376
|
+
const json = await readFile((0, import_path5.join)(pipfileLockDir, "Pipfile.lock"), "utf8");
|
|
4108
4377
|
lock = JSON.parse(json);
|
|
4109
4378
|
} catch (err) {
|
|
4110
|
-
throw new
|
|
4379
|
+
throw new import_build_utils7.NowBuildError({
|
|
4111
4380
|
code: "INVALID_PIPFILE_LOCK",
|
|
4112
4381
|
message: "Unable to parse Pipfile.lock"
|
|
4113
4382
|
});
|
|
@@ -4115,191 +4384,68 @@ var build = async ({
|
|
|
4115
4384
|
const pyFromLock = lock?._meta?.requires?.python_version;
|
|
4116
4385
|
if (pyFromLock) {
|
|
4117
4386
|
declaredPythonVersion = { version: pyFromLock, source: "Pipfile.lock" };
|
|
4118
|
-
(0,
|
|
4387
|
+
(0, import_build_utils7.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
|
|
4119
4388
|
}
|
|
4120
4389
|
}
|
|
4121
4390
|
const pythonVersion = getSupportedPythonVersion({
|
|
4122
4391
|
isDev: meta.isDev,
|
|
4123
4392
|
declaredPythonVersion
|
|
4124
4393
|
});
|
|
4125
|
-
fsFiles = await (0,
|
|
4126
|
-
const
|
|
4127
|
-
|
|
4128
|
-
workPath,
|
|
4129
|
-
".vercel",
|
|
4130
|
-
"python",
|
|
4131
|
-
`py${pythonVersion.version}`,
|
|
4132
|
-
entryDirectory
|
|
4133
|
-
);
|
|
4134
|
-
try {
|
|
4135
|
-
await import_fs6.default.promises.mkdir(vendorBaseDir, { recursive: true });
|
|
4136
|
-
} catch (err) {
|
|
4137
|
-
console.log("Failed to create vendor cache directory");
|
|
4138
|
-
throw err;
|
|
4139
|
-
}
|
|
4140
|
-
let installationSource;
|
|
4141
|
-
if (uvLockDir && pyprojectDir) {
|
|
4142
|
-
installationSource = "uv.lock";
|
|
4143
|
-
} else if (pyprojectDir) {
|
|
4144
|
-
installationSource = "pyproject.toml";
|
|
4145
|
-
} else if (pipfileLockDir) {
|
|
4146
|
-
installationSource = "Pipfile.lock";
|
|
4147
|
-
} else if (pipfileDir) {
|
|
4148
|
-
installationSource = "Pipfile";
|
|
4149
|
-
} else if (fsFiles[requirementsTxt] || fsFiles["requirements.txt"]) {
|
|
4150
|
-
installationSource = "requirements.txt";
|
|
4151
|
-
}
|
|
4152
|
-
if (installationSource) {
|
|
4153
|
-
console.log(
|
|
4154
|
-
`Installing required dependencies from ${installationSource}...`
|
|
4155
|
-
);
|
|
4156
|
-
} else {
|
|
4157
|
-
console.log("Installing required dependencies...");
|
|
4158
|
-
}
|
|
4159
|
-
let uvPath = null;
|
|
4160
|
-
try {
|
|
4161
|
-
uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
|
|
4162
|
-
console.log(`Using uv at "${uvPath}"`);
|
|
4163
|
-
} catch (err) {
|
|
4164
|
-
if (uvLockDir || pyprojectDir && !hasReqLocal && !hasReqGlobal) {
|
|
4165
|
-
console.log("Failed to install uv");
|
|
4166
|
-
throw new Error(
|
|
4167
|
-
`uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
|
|
4168
|
-
);
|
|
4169
|
-
}
|
|
4170
|
-
(0, import_build_utils8.debug)("Failed to install uv", err);
|
|
4171
|
-
}
|
|
4172
|
-
await installRequirement({
|
|
4394
|
+
fsFiles = await (0, import_build_utils7.glob)("**", workPath);
|
|
4395
|
+
const venvPath = (0, import_path5.join)(workPath, ".vercel", "python", ".venv");
|
|
4396
|
+
await ensureVenv({
|
|
4173
4397
|
pythonPath: pythonVersion.pythonPath,
|
|
4174
|
-
|
|
4175
|
-
uvPath,
|
|
4176
|
-
dependency: "werkzeug",
|
|
4177
|
-
version: "1.0.1",
|
|
4178
|
-
workPath,
|
|
4179
|
-
targetDir: vendorBaseDir,
|
|
4180
|
-
meta
|
|
4398
|
+
venvPath
|
|
4181
4399
|
});
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4400
|
+
const hasCustomInstallCommand = (framework === "fastapi" || framework === "flask") && !!projectInstallCommand;
|
|
4401
|
+
if (hasCustomInstallCommand) {
|
|
4402
|
+
const baseEnv = spawnEnv || process.env;
|
|
4403
|
+
const pythonEnv = createVenvEnv(venvPath, baseEnv);
|
|
4404
|
+
pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
|
|
4405
|
+
const installCommand = projectInstallCommand;
|
|
4406
|
+
console.log(`Running "install" command: \`${installCommand}\`...`);
|
|
4407
|
+
await (0, import_build_utils7.execCommand)(installCommand, {
|
|
4408
|
+
env: pythonEnv,
|
|
4409
|
+
cwd: workPath
|
|
4192
4410
|
});
|
|
4193
|
-
}
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
pythonPath: pythonVersion.pythonPath,
|
|
4203
|
-
pipPath: pythonVersion.pipPath,
|
|
4204
|
-
uvPath,
|
|
4205
|
-
filePath: exportedReq,
|
|
4206
|
-
workPath,
|
|
4207
|
-
targetDir: vendorBaseDir,
|
|
4208
|
-
meta
|
|
4209
|
-
});
|
|
4210
|
-
installedFromProjectFiles = true;
|
|
4211
|
-
} else {
|
|
4212
|
-
(0, import_build_utils8.debug)('Skipping uv export because "pyproject.toml" was not found');
|
|
4213
|
-
}
|
|
4214
|
-
} else if (pyprojectDir) {
|
|
4215
|
-
(0, import_build_utils8.debug)('Found "pyproject.toml"');
|
|
4216
|
-
if (hasReqLocal || hasReqGlobal) {
|
|
4217
|
-
console.log(
|
|
4218
|
-
"Detected both pyproject.toml and requirements.txt but no lockfile; using pyproject.toml"
|
|
4411
|
+
} else {
|
|
4412
|
+
let uvPath;
|
|
4413
|
+
try {
|
|
4414
|
+
uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
|
|
4415
|
+
console.log(`Using uv at "${uvPath}"`);
|
|
4416
|
+
} catch (err) {
|
|
4417
|
+
console.log("Failed to install or locate uv");
|
|
4418
|
+
throw new Error(
|
|
4419
|
+
`uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
|
|
4219
4420
|
);
|
|
4220
4421
|
}
|
|
4221
|
-
const
|
|
4222
|
-
|
|
4223
|
-
});
|
|
4224
|
-
await installRequirementsFile({
|
|
4225
|
-
pythonPath: pythonVersion.pythonPath,
|
|
4226
|
-
pipPath: pythonVersion.pipPath,
|
|
4227
|
-
uvPath,
|
|
4228
|
-
filePath: exportedReq,
|
|
4229
|
-
workPath,
|
|
4230
|
-
targetDir: vendorBaseDir,
|
|
4231
|
-
meta
|
|
4232
|
-
});
|
|
4233
|
-
installedFromProjectFiles = true;
|
|
4234
|
-
} else if (pipfileLockDir || pipfileDir) {
|
|
4235
|
-
(0, import_build_utils8.debug)(`Found ${pipfileLockDir ? '"Pipfile.lock"' : '"Pipfile"'}`);
|
|
4236
|
-
if (hasReqLocal || hasReqGlobal) {
|
|
4237
|
-
(0, import_build_utils8.debug)('Skipping Pipfile export because "requirements.txt" exists');
|
|
4238
|
-
} else {
|
|
4239
|
-
const exportedReq = await exportRequirementsFromPipfile({
|
|
4240
|
-
pythonPath: pythonVersion.pythonPath,
|
|
4241
|
-
pipPath: pythonVersion.pipPath,
|
|
4242
|
-
uvPath,
|
|
4243
|
-
projectDir: pipfileLockDir || pipfileDir,
|
|
4244
|
-
meta
|
|
4245
|
-
});
|
|
4246
|
-
await installRequirementsFile({
|
|
4247
|
-
pythonPath: pythonVersion.pythonPath,
|
|
4248
|
-
pipPath: pythonVersion.pipPath,
|
|
4249
|
-
uvPath,
|
|
4250
|
-
filePath: exportedReq,
|
|
4251
|
-
workPath,
|
|
4252
|
-
targetDir: vendorBaseDir,
|
|
4253
|
-
meta
|
|
4254
|
-
});
|
|
4255
|
-
installedFromProjectFiles = true;
|
|
4256
|
-
}
|
|
4257
|
-
}
|
|
4258
|
-
if (!installedFromProjectFiles && fsFiles[requirementsTxt]) {
|
|
4259
|
-
(0, import_build_utils8.debug)('Found local "requirements.txt"');
|
|
4260
|
-
const requirementsTxtPath = fsFiles[requirementsTxt].fsPath;
|
|
4261
|
-
await installRequirementsFile({
|
|
4262
|
-
pythonPath: pythonVersion.pythonPath,
|
|
4263
|
-
pipPath: pythonVersion.pipPath,
|
|
4264
|
-
uvPath,
|
|
4265
|
-
filePath: requirementsTxtPath,
|
|
4422
|
+
const runtimeDependencies = framework === "flask" ? ["werkzeug>=1.0.1"] : ["werkzeug>=1.0.1", "uvicorn>=0.24"];
|
|
4423
|
+
const { projectDir } = await ensureUvProject({
|
|
4266
4424
|
workPath,
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
});
|
|
4270
|
-
} else if (!installedFromProjectFiles && fsFiles["requirements.txt"]) {
|
|
4271
|
-
(0, import_build_utils8.debug)('Found global "requirements.txt"');
|
|
4272
|
-
const requirementsTxtPath = fsFiles["requirements.txt"].fsPath;
|
|
4273
|
-
await installRequirementsFile({
|
|
4425
|
+
entryDirectory,
|
|
4426
|
+
fsFiles,
|
|
4274
4427
|
pythonPath: pythonVersion.pythonPath,
|
|
4275
4428
|
pipPath: pythonVersion.pipPath,
|
|
4276
4429
|
uvPath,
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
meta
|
|
4430
|
+
venvPath,
|
|
4431
|
+
meta,
|
|
4432
|
+
runtimeDependencies
|
|
4281
4433
|
});
|
|
4282
|
-
|
|
4283
|
-
if (pyprojectDir && repoRootPath) {
|
|
4284
|
-
await installUvWorkspaceDependencies({
|
|
4285
|
-
repoRootPath,
|
|
4286
|
-
pyprojectDir,
|
|
4287
|
-
pythonPath: pythonVersion.pythonPath,
|
|
4288
|
-
pipPath: pythonVersion.pipPath,
|
|
4434
|
+
await runUvSync({
|
|
4289
4435
|
uvPath,
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4436
|
+
venvPath,
|
|
4437
|
+
projectDir,
|
|
4438
|
+
locked: true
|
|
4293
4439
|
});
|
|
4294
4440
|
}
|
|
4295
|
-
const originalPyPath = (0,
|
|
4441
|
+
const originalPyPath = (0, import_path5.join)(__dirname, "..", "vc_init.py");
|
|
4296
4442
|
const originalHandlerPyContents = await readFile(originalPyPath, "utf8");
|
|
4297
|
-
(0,
|
|
4443
|
+
(0, import_build_utils7.debug)("Entrypoint is", entrypoint);
|
|
4298
4444
|
const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
|
|
4299
4445
|
const vendorDir = resolveVendorDir();
|
|
4300
4446
|
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
4301
4447
|
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
4302
|
-
(0,
|
|
4448
|
+
(0, import_build_utils7.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
4303
4449
|
const handlerPyContents = originalHandlerPyContents.replace(/__VC_HANDLER_MODULE_NAME/g, moduleName).replace(/__VC_HANDLER_ENTRYPOINT/g, entrypointWithSuffix).replace(/__VC_HANDLER_VENDOR_DIR/g, vendorDir);
|
|
4304
4450
|
const predefinedExcludes = [
|
|
4305
4451
|
".git/**",
|
|
@@ -4325,26 +4471,21 @@ var build = async ({
|
|
|
4325
4471
|
cwd: workPath,
|
|
4326
4472
|
ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
|
|
4327
4473
|
};
|
|
4328
|
-
const files = await (0,
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
}
|
|
4336
|
-
}
|
|
4337
|
-
} catch (err) {
|
|
4338
|
-
console.log("Failed to include cached vendor directory");
|
|
4339
|
-
throw err;
|
|
4474
|
+
const files = await (0, import_build_utils7.glob)("**", globOptions);
|
|
4475
|
+
const vendorFiles = await mirrorSitePackagesIntoVendor({
|
|
4476
|
+
venvPath,
|
|
4477
|
+
vendorDirName: vendorDir
|
|
4478
|
+
});
|
|
4479
|
+
for (const [p, f] of Object.entries(vendorFiles)) {
|
|
4480
|
+
files[p] = f;
|
|
4340
4481
|
}
|
|
4341
4482
|
const handlerPyFilename = "vc__handler__python";
|
|
4342
|
-
files[`${handlerPyFilename}.py`] = new
|
|
4483
|
+
files[`${handlerPyFilename}.py`] = new import_build_utils7.FileBlob({ data: handlerPyContents });
|
|
4343
4484
|
if (config.framework === "fasthtml") {
|
|
4344
4485
|
const { SESSKEY = "" } = process.env;
|
|
4345
|
-
files[".sesskey"] = new
|
|
4486
|
+
files[".sesskey"] = new import_build_utils7.FileBlob({ data: `"${SESSKEY}"` });
|
|
4346
4487
|
}
|
|
4347
|
-
const output = new
|
|
4488
|
+
const output = new import_build_utils7.Lambda({
|
|
4348
4489
|
files,
|
|
4349
4490
|
handler: `${handlerPyFilename}.vc_handler`,
|
|
4350
4491
|
runtime: pythonVersion.runtime,
|
|
@@ -4380,7 +4521,7 @@ var defaultShouldServe = ({
|
|
|
4380
4521
|
if (entrypoint === requestPath && hasProp(files, entrypoint)) {
|
|
4381
4522
|
return true;
|
|
4382
4523
|
}
|
|
4383
|
-
const { dir, name } = (0,
|
|
4524
|
+
const { dir, name } = (0, import_path5.parse)(entrypoint);
|
|
4384
4525
|
if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
|
|
4385
4526
|
return true;
|
|
4386
4527
|
}
|