vercel-cli 48.6.6__py3-none-any.whl → 50.4.6__py3-none-any.whl
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.
- vercel_cli/vendor/dist/index.js +70005 -64961
- vercel_cli/vendor/dist/vc.js +4 -3
- vercel_cli/vendor/node_modules/.package-lock.json +6 -6
- vercel_cli/vendor/node_modules/@vercel/build-utils/CHANGELOG.md +132 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/framework-helpers.d.ts +5 -4
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/framework-helpers.js +28 -2
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/fs/node-version.js +8 -3
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/fs/read-config-file.d.ts +6 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/fs/read-config-file.js +11 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/fs/run-user-scripts.d.ts +25 -6
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/fs/run-user-scripts.js +53 -11
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/generate-node-builder-functions.d.ts +8 -2
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/generate-node-builder-functions.js +4 -2
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/index.d.ts +5 -4
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/index.js +2545 -502
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/lambda.d.ts +17 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/lambda.js +11 -1
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/python.d.ts +22 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/python.js +85 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/dist/types.d.ts +9 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/lib/python/ast_parser.py +72 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/lib/python/tests/test_ast_parser.py +72 -0
- vercel_cli/vendor/node_modules/@vercel/build-utils/package.json +4 -4
- vercel_cli/vendor/node_modules/@vercel/python/dist/index.js +910 -421
- vercel_cli/vendor/node_modules/@vercel/python/package.json +3 -3
- vercel_cli/vendor/node_modules/@vercel/python/vc_init.py +371 -161
- vercel_cli/vendor/node_modules/@vercel/python/vc_init_dev_asgi.py +3 -2
- vercel_cli/vendor/package.json +5 -4
- {vercel_cli-48.6.6.dist-info → vercel_cli-50.4.6.dist-info}/METADATA +1 -1
- {vercel_cli-48.6.6.dist-info → vercel_cli-50.4.6.dist-info}/RECORD +34 -30
- {vercel_cli-48.6.6.dist-info → vercel_cli-50.4.6.dist-info}/WHEEL +1 -1
- /vercel_cli/vendor/dist/{builder-worker.js → builder-worker.cjs} +0 -0
- /vercel_cli/vendor/dist/{get-latest-worker.js → get-latest-worker.cjs} +0 -0
- {vercel_cli-48.6.6.dist-info → vercel_cli-50.4.6.dist-info}/entry_points.txt +0 -0
|
@@ -137,12 +137,12 @@ var require_isexe = __commonJS({
|
|
|
137
137
|
if (typeof Promise !== "function") {
|
|
138
138
|
throw new TypeError("callback not provided");
|
|
139
139
|
}
|
|
140
|
-
return new Promise(function(
|
|
140
|
+
return new Promise(function(resolve2, reject) {
|
|
141
141
|
isexe(path, options || {}, function(er, is) {
|
|
142
142
|
if (er) {
|
|
143
143
|
reject(er);
|
|
144
144
|
} else {
|
|
145
|
-
|
|
145
|
+
resolve2(is);
|
|
146
146
|
}
|
|
147
147
|
});
|
|
148
148
|
});
|
|
@@ -423,15 +423,15 @@ var require_readShebang = __commonJS({
|
|
|
423
423
|
var require_semver = __commonJS({
|
|
424
424
|
"../../node_modules/.pnpm/semver@5.7.2/node_modules/semver/semver.js"(exports, module2) {
|
|
425
425
|
exports = module2.exports = SemVer;
|
|
426
|
-
var
|
|
426
|
+
var debug6;
|
|
427
427
|
if (typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG)) {
|
|
428
|
-
|
|
428
|
+
debug6 = function() {
|
|
429
429
|
var args = Array.prototype.slice.call(arguments, 0);
|
|
430
430
|
args.unshift("SEMVER");
|
|
431
431
|
console.log.apply(console, args);
|
|
432
432
|
};
|
|
433
433
|
} else {
|
|
434
|
-
|
|
434
|
+
debug6 = function() {
|
|
435
435
|
};
|
|
436
436
|
}
|
|
437
437
|
exports.SEMVER_SPEC_VERSION = "2.0.0";
|
|
@@ -540,7 +540,7 @@ var require_semver = __commonJS({
|
|
|
540
540
|
var STAR = R++;
|
|
541
541
|
src[STAR] = "(<|>)?=?\\s*\\*";
|
|
542
542
|
for (i = 0; i < R; i++) {
|
|
543
|
-
|
|
543
|
+
debug6(i, src[i]);
|
|
544
544
|
if (!re[i]) {
|
|
545
545
|
re[i] = new RegExp(src[i]);
|
|
546
546
|
safeRe[i] = new RegExp(makeSafeRe(src[i]));
|
|
@@ -607,7 +607,7 @@ var require_semver = __commonJS({
|
|
|
607
607
|
if (!(this instanceof SemVer)) {
|
|
608
608
|
return new SemVer(version2, options);
|
|
609
609
|
}
|
|
610
|
-
|
|
610
|
+
debug6("SemVer", version2, options);
|
|
611
611
|
this.options = options;
|
|
612
612
|
this.loose = !!options.loose;
|
|
613
613
|
var m = version2.trim().match(options.loose ? safeRe[LOOSE] : safeRe[FULL]);
|
|
@@ -654,7 +654,7 @@ var require_semver = __commonJS({
|
|
|
654
654
|
return this.version;
|
|
655
655
|
};
|
|
656
656
|
SemVer.prototype.compare = function(other) {
|
|
657
|
-
|
|
657
|
+
debug6("SemVer.compare", this.version, this.options, other);
|
|
658
658
|
if (!(other instanceof SemVer)) {
|
|
659
659
|
other = new SemVer(other, this.options);
|
|
660
660
|
}
|
|
@@ -681,7 +681,7 @@ var require_semver = __commonJS({
|
|
|
681
681
|
do {
|
|
682
682
|
var a = this.prerelease[i2];
|
|
683
683
|
var b = other.prerelease[i2];
|
|
684
|
-
|
|
684
|
+
debug6("prerelease compare", i2, a, b);
|
|
685
685
|
if (a === void 0 && b === void 0) {
|
|
686
686
|
return 0;
|
|
687
687
|
} else if (b === void 0) {
|
|
@@ -935,7 +935,7 @@ var require_semver = __commonJS({
|
|
|
935
935
|
return new Comparator(comp, options);
|
|
936
936
|
}
|
|
937
937
|
comp = comp.trim().split(/\s+/).join(" ");
|
|
938
|
-
|
|
938
|
+
debug6("comparator", comp, options);
|
|
939
939
|
this.options = options;
|
|
940
940
|
this.loose = !!options.loose;
|
|
941
941
|
this.parse(comp);
|
|
@@ -944,7 +944,7 @@ var require_semver = __commonJS({
|
|
|
944
944
|
} else {
|
|
945
945
|
this.value = this.operator + this.semver.version;
|
|
946
946
|
}
|
|
947
|
-
|
|
947
|
+
debug6("comp", this);
|
|
948
948
|
}
|
|
949
949
|
var ANY = {};
|
|
950
950
|
Comparator.prototype.parse = function(comp) {
|
|
@@ -967,7 +967,7 @@ var require_semver = __commonJS({
|
|
|
967
967
|
return this.value;
|
|
968
968
|
};
|
|
969
969
|
Comparator.prototype.test = function(version2) {
|
|
970
|
-
|
|
970
|
+
debug6("Comparator.test", version2, this.options.loose);
|
|
971
971
|
if (this.semver === ANY) {
|
|
972
972
|
return true;
|
|
973
973
|
}
|
|
@@ -989,10 +989,10 @@ var require_semver = __commonJS({
|
|
|
989
989
|
var rangeTmp;
|
|
990
990
|
if (this.operator === "") {
|
|
991
991
|
rangeTmp = new Range(comp.value, options);
|
|
992
|
-
return
|
|
992
|
+
return satisfies2(this.value, rangeTmp, options);
|
|
993
993
|
} else if (comp.operator === "") {
|
|
994
994
|
rangeTmp = new Range(this.value, options);
|
|
995
|
-
return
|
|
995
|
+
return satisfies2(comp.semver, rangeTmp, options);
|
|
996
996
|
}
|
|
997
997
|
var sameDirectionIncreasing = (this.operator === ">=" || this.operator === ">") && (comp.operator === ">=" || comp.operator === ">");
|
|
998
998
|
var sameDirectionDecreasing = (this.operator === "<=" || this.operator === "<") && (comp.operator === "<=" || comp.operator === "<");
|
|
@@ -1050,9 +1050,9 @@ var require_semver = __commonJS({
|
|
|
1050
1050
|
var loose = this.options.loose;
|
|
1051
1051
|
var hr = loose ? safeRe[HYPHENRANGELOOSE] : safeRe[HYPHENRANGE];
|
|
1052
1052
|
range = range.replace(hr, hyphenReplace);
|
|
1053
|
-
|
|
1053
|
+
debug6("hyphen replace", range);
|
|
1054
1054
|
range = range.replace(safeRe[COMPARATORTRIM], comparatorTrimReplace);
|
|
1055
|
-
|
|
1055
|
+
debug6("comparator trim", range, safeRe[COMPARATORTRIM]);
|
|
1056
1056
|
range = range.replace(safeRe[TILDETRIM], tildeTrimReplace);
|
|
1057
1057
|
range = range.replace(safeRe[CARETTRIM], caretTrimReplace);
|
|
1058
1058
|
var compRe = loose ? safeRe[COMPARATORLOOSE] : safeRe[COMPARATOR];
|
|
@@ -1092,15 +1092,15 @@ var require_semver = __commonJS({
|
|
|
1092
1092
|
});
|
|
1093
1093
|
}
|
|
1094
1094
|
function parseComparator(comp, options) {
|
|
1095
|
-
|
|
1095
|
+
debug6("comp", comp, options);
|
|
1096
1096
|
comp = replaceCarets(comp, options);
|
|
1097
|
-
|
|
1097
|
+
debug6("caret", comp);
|
|
1098
1098
|
comp = replaceTildes(comp, options);
|
|
1099
|
-
|
|
1099
|
+
debug6("tildes", comp);
|
|
1100
1100
|
comp = replaceXRanges(comp, options);
|
|
1101
|
-
|
|
1101
|
+
debug6("xrange", comp);
|
|
1102
1102
|
comp = replaceStars(comp, options);
|
|
1103
|
-
|
|
1103
|
+
debug6("stars", comp);
|
|
1104
1104
|
return comp;
|
|
1105
1105
|
}
|
|
1106
1106
|
function isX(id) {
|
|
@@ -1114,7 +1114,7 @@ var require_semver = __commonJS({
|
|
|
1114
1114
|
function replaceTilde(comp, options) {
|
|
1115
1115
|
var r = options.loose ? safeRe[TILDELOOSE] : safeRe[TILDE];
|
|
1116
1116
|
return comp.replace(r, function(_, M, m, p, pr) {
|
|
1117
|
-
|
|
1117
|
+
debug6("tilde", comp, _, M, m, p, pr);
|
|
1118
1118
|
var ret;
|
|
1119
1119
|
if (isX(M)) {
|
|
1120
1120
|
ret = "";
|
|
@@ -1123,12 +1123,12 @@ var require_semver = __commonJS({
|
|
|
1123
1123
|
} else if (isX(p)) {
|
|
1124
1124
|
ret = ">=" + M + "." + m + ".0 <" + M + "." + (+m + 1) + ".0";
|
|
1125
1125
|
} else if (pr) {
|
|
1126
|
-
|
|
1126
|
+
debug6("replaceTilde pr", pr);
|
|
1127
1127
|
ret = ">=" + M + "." + m + "." + p + "-" + pr + " <" + M + "." + (+m + 1) + ".0";
|
|
1128
1128
|
} else {
|
|
1129
1129
|
ret = ">=" + M + "." + m + "." + p + " <" + M + "." + (+m + 1) + ".0";
|
|
1130
1130
|
}
|
|
1131
|
-
|
|
1131
|
+
debug6("tilde return", ret);
|
|
1132
1132
|
return ret;
|
|
1133
1133
|
});
|
|
1134
1134
|
}
|
|
@@ -1138,10 +1138,10 @@ var require_semver = __commonJS({
|
|
|
1138
1138
|
}).join(" ");
|
|
1139
1139
|
}
|
|
1140
1140
|
function replaceCaret(comp, options) {
|
|
1141
|
-
|
|
1141
|
+
debug6("caret", comp, options);
|
|
1142
1142
|
var r = options.loose ? safeRe[CARETLOOSE] : safeRe[CARET];
|
|
1143
1143
|
return comp.replace(r, function(_, M, m, p, pr) {
|
|
1144
|
-
|
|
1144
|
+
debug6("caret", comp, _, M, m, p, pr);
|
|
1145
1145
|
var ret;
|
|
1146
1146
|
if (isX(M)) {
|
|
1147
1147
|
ret = "";
|
|
@@ -1154,7 +1154,7 @@ var require_semver = __commonJS({
|
|
|
1154
1154
|
ret = ">=" + M + "." + m + ".0 <" + (+M + 1) + ".0.0";
|
|
1155
1155
|
}
|
|
1156
1156
|
} else if (pr) {
|
|
1157
|
-
|
|
1157
|
+
debug6("replaceCaret pr", pr);
|
|
1158
1158
|
if (M === "0") {
|
|
1159
1159
|
if (m === "0") {
|
|
1160
1160
|
ret = ">=" + M + "." + m + "." + p + "-" + pr + " <" + M + "." + m + "." + (+p + 1);
|
|
@@ -1165,7 +1165,7 @@ var require_semver = __commonJS({
|
|
|
1165
1165
|
ret = ">=" + M + "." + m + "." + p + "-" + pr + " <" + (+M + 1) + ".0.0";
|
|
1166
1166
|
}
|
|
1167
1167
|
} else {
|
|
1168
|
-
|
|
1168
|
+
debug6("no pr");
|
|
1169
1169
|
if (M === "0") {
|
|
1170
1170
|
if (m === "0") {
|
|
1171
1171
|
ret = ">=" + M + "." + m + "." + p + " <" + M + "." + m + "." + (+p + 1);
|
|
@@ -1176,12 +1176,12 @@ var require_semver = __commonJS({
|
|
|
1176
1176
|
ret = ">=" + M + "." + m + "." + p + " <" + (+M + 1) + ".0.0";
|
|
1177
1177
|
}
|
|
1178
1178
|
}
|
|
1179
|
-
|
|
1179
|
+
debug6("caret return", ret);
|
|
1180
1180
|
return ret;
|
|
1181
1181
|
});
|
|
1182
1182
|
}
|
|
1183
1183
|
function replaceXRanges(comp, options) {
|
|
1184
|
-
|
|
1184
|
+
debug6("replaceXRanges", comp, options);
|
|
1185
1185
|
return comp.split(/\s+/).map(function(comp2) {
|
|
1186
1186
|
return replaceXRange(comp2, options);
|
|
1187
1187
|
}).join(" ");
|
|
@@ -1190,7 +1190,7 @@ var require_semver = __commonJS({
|
|
|
1190
1190
|
comp = comp.trim();
|
|
1191
1191
|
var r = options.loose ? safeRe[XRANGELOOSE] : safeRe[XRANGE];
|
|
1192
1192
|
return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
|
|
1193
|
-
|
|
1193
|
+
debug6("xRange", comp, ret, gtlt, M, m, p, pr);
|
|
1194
1194
|
var xM = isX(M);
|
|
1195
1195
|
var xm = xM || isX(m);
|
|
1196
1196
|
var xp = xm || isX(p);
|
|
@@ -1233,12 +1233,12 @@ var require_semver = __commonJS({
|
|
|
1233
1233
|
} else if (xp) {
|
|
1234
1234
|
ret = ">=" + M + "." + m + ".0 <" + M + "." + (+m + 1) + ".0";
|
|
1235
1235
|
}
|
|
1236
|
-
|
|
1236
|
+
debug6("xRange return", ret);
|
|
1237
1237
|
return ret;
|
|
1238
1238
|
});
|
|
1239
1239
|
}
|
|
1240
1240
|
function replaceStars(comp, options) {
|
|
1241
|
-
|
|
1241
|
+
debug6("replaceStars", comp, options);
|
|
1242
1242
|
return comp.trim().replace(safeRe[STAR], "");
|
|
1243
1243
|
}
|
|
1244
1244
|
function hyphenReplace($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr, tb) {
|
|
@@ -1286,7 +1286,7 @@ var require_semver = __commonJS({
|
|
|
1286
1286
|
}
|
|
1287
1287
|
if (version2.prerelease.length && !options.includePrerelease) {
|
|
1288
1288
|
for (i2 = 0; i2 < set.length; i2++) {
|
|
1289
|
-
|
|
1289
|
+
debug6(set[i2].semver);
|
|
1290
1290
|
if (set[i2].semver === ANY) {
|
|
1291
1291
|
continue;
|
|
1292
1292
|
}
|
|
@@ -1301,8 +1301,8 @@ var require_semver = __commonJS({
|
|
|
1301
1301
|
}
|
|
1302
1302
|
return true;
|
|
1303
1303
|
}
|
|
1304
|
-
exports.satisfies =
|
|
1305
|
-
function
|
|
1304
|
+
exports.satisfies = satisfies2;
|
|
1305
|
+
function satisfies2(version2, range, options) {
|
|
1306
1306
|
try {
|
|
1307
1307
|
range = new Range(range, options);
|
|
1308
1308
|
} catch (er) {
|
|
@@ -1430,7 +1430,7 @@ var require_semver = __commonJS({
|
|
|
1430
1430
|
default:
|
|
1431
1431
|
throw new TypeError('Must provide a hilo val of "<" or ">"');
|
|
1432
1432
|
}
|
|
1433
|
-
if (
|
|
1433
|
+
if (satisfies2(version2, range, options)) {
|
|
1434
1434
|
return false;
|
|
1435
1435
|
}
|
|
1436
1436
|
for (var i2 = 0; i2 < range.set.length; ++i2) {
|
|
@@ -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;
|
|
@@ -2042,7 +2042,7 @@ var require_get_stream = __commonJS({
|
|
|
2042
2042
|
options = Object.assign({ maxBuffer: Infinity }, options);
|
|
2043
2043
|
const { maxBuffer } = options;
|
|
2044
2044
|
let stream;
|
|
2045
|
-
return new Promise((
|
|
2045
|
+
return new Promise((resolve2, reject) => {
|
|
2046
2046
|
const rejectPromise = (error) => {
|
|
2047
2047
|
if (error) {
|
|
2048
2048
|
error.bufferedData = stream.getBufferedValue();
|
|
@@ -2054,7 +2054,7 @@ var require_get_stream = __commonJS({
|
|
|
2054
2054
|
rejectPromise(error);
|
|
2055
2055
|
return;
|
|
2056
2056
|
}
|
|
2057
|
-
|
|
2057
|
+
resolve2();
|
|
2058
2058
|
});
|
|
2059
2059
|
stream.on("data", () => {
|
|
2060
2060
|
if (stream.getBufferedLength() > maxBuffer) {
|
|
@@ -2078,11 +2078,11 @@ var require_p_finally = __commonJS({
|
|
|
2078
2078
|
onFinally = onFinally || (() => {
|
|
2079
2079
|
});
|
|
2080
2080
|
return promise.then(
|
|
2081
|
-
(val) => new Promise((
|
|
2082
|
-
|
|
2081
|
+
(val) => new Promise((resolve2) => {
|
|
2082
|
+
resolve2(onFinally());
|
|
2083
2083
|
}).then(() => val),
|
|
2084
|
-
(err) => new Promise((
|
|
2085
|
-
|
|
2084
|
+
(err) => new Promise((resolve2) => {
|
|
2085
|
+
resolve2(onFinally());
|
|
2086
2086
|
}).then(() => {
|
|
2087
2087
|
throw err;
|
|
2088
2088
|
})
|
|
@@ -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;
|
|
@@ -2461,8 +2461,8 @@ var require_execa = __commonJS({
|
|
|
2461
2461
|
}
|
|
2462
2462
|
let ret;
|
|
2463
2463
|
if (!buffer) {
|
|
2464
|
-
ret = new Promise((
|
|
2465
|
-
process2[stream].once("end",
|
|
2464
|
+
ret = new Promise((resolve2, reject) => {
|
|
2465
|
+
process2[stream].once("end", resolve2).once("error", reject);
|
|
2466
2466
|
});
|
|
2467
2467
|
} else if (encoding) {
|
|
2468
2468
|
ret = _getStream(process2[stream], {
|
|
@@ -2551,19 +2551,19 @@ ${stderr}${stdout}`;
|
|
|
2551
2551
|
spawned.kill(parsed.opts.killSignal);
|
|
2552
2552
|
}, parsed.opts.timeout);
|
|
2553
2553
|
}
|
|
2554
|
-
const processDone = new Promise((
|
|
2554
|
+
const processDone = new Promise((resolve2) => {
|
|
2555
2555
|
spawned.on("exit", (code, signal) => {
|
|
2556
2556
|
cleanup();
|
|
2557
|
-
|
|
2557
|
+
resolve2({ code, signal });
|
|
2558
2558
|
});
|
|
2559
2559
|
spawned.on("error", (err) => {
|
|
2560
2560
|
cleanup();
|
|
2561
|
-
|
|
2561
|
+
resolve2({ error: err });
|
|
2562
2562
|
});
|
|
2563
2563
|
if (spawned.stdin) {
|
|
2564
2564
|
spawned.stdin.on("error", (err) => {
|
|
2565
2565
|
cleanup();
|
|
2566
|
-
|
|
2566
|
+
resolve2({ error: err });
|
|
2567
2567
|
});
|
|
2568
2568
|
}
|
|
2569
2569
|
});
|
|
@@ -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);
|
|
@@ -2751,17 +2751,146 @@ module.exports = __toCommonJS(src_exports);
|
|
|
2751
2751
|
var import_fs5 = __toESM(require("fs"));
|
|
2752
2752
|
var import_util = require("util");
|
|
2753
2753
|
var import_path5 = require("path");
|
|
2754
|
-
var
|
|
2754
|
+
var import_build_utils7 = require("@vercel/build-utils");
|
|
2755
2755
|
|
|
2756
2756
|
// src/install.ts
|
|
2757
|
-
var
|
|
2758
|
-
var
|
|
2757
|
+
var import_execa2 = __toESM(require_execa());
|
|
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 import_execa = __toESM(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 (0, import_execa.default)(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, useUserVirtualEnv = true) {
|
|
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
|
+
if (useUserVirtualEnv) {
|
|
2836
|
+
useVirtualEnv(workPath, finalEnv, systemPython);
|
|
2837
|
+
}
|
|
2838
|
+
const scriptCommand = scripts[scriptToRun];
|
|
2839
|
+
if (typeof scriptCommand === "string" && scriptCommand.trim()) {
|
|
2840
|
+
console.log(`Executing: ${scriptCommand}`);
|
|
2841
|
+
await (0, import_build_utils.execCommand)(scriptCommand, {
|
|
2842
|
+
cwd: workPath,
|
|
2843
|
+
env: finalEnv
|
|
2844
|
+
});
|
|
2845
|
+
return true;
|
|
2846
|
+
}
|
|
2847
|
+
return false;
|
|
2848
|
+
}
|
|
2849
|
+
async function runUvCommand(options) {
|
|
2850
|
+
const { uvPath, args, cwd, venvPath } = options;
|
|
2851
|
+
const pretty = `uv ${args.join(" ")}`;
|
|
2852
|
+
(0, import_build_utils.debug)(`Running "${pretty}"...`);
|
|
2853
|
+
if (!uvPath) {
|
|
2854
|
+
throw new Error(`uv is required to run "${pretty}" but is not available`);
|
|
2855
|
+
}
|
|
2856
|
+
try {
|
|
2857
|
+
await (0, import_execa.default)(uvPath, args, {
|
|
2858
|
+
cwd,
|
|
2859
|
+
env: createVenvEnv(venvPath)
|
|
2860
|
+
});
|
|
2861
|
+
return true;
|
|
2862
|
+
} catch (err) {
|
|
2863
|
+
const error = new Error(
|
|
2864
|
+
`Failed to run "${pretty}": ${err instanceof Error ? err.message : String(err)}`
|
|
2865
|
+
);
|
|
2866
|
+
if (err && typeof err === "object") {
|
|
2867
|
+
if ("code" in err) {
|
|
2868
|
+
error.code = err.code;
|
|
2869
|
+
} else if ("signal" in err) {
|
|
2870
|
+
error.code = err.signal;
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
throw error;
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
function findDir({
|
|
2877
|
+
file,
|
|
2878
|
+
entryDirectory,
|
|
2879
|
+
workPath,
|
|
2880
|
+
fsFiles
|
|
2881
|
+
}) {
|
|
2882
|
+
if (fsFiles[(0, import_path.join)(entryDirectory, file)]) {
|
|
2883
|
+
return (0, import_path.join)(workPath, entryDirectory);
|
|
2884
|
+
}
|
|
2885
|
+
if (fsFiles[file]) {
|
|
2886
|
+
return workPath;
|
|
2887
|
+
}
|
|
2888
|
+
return null;
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
// src/install.ts
|
|
2892
|
+
var isWin2 = process.platform === "win32";
|
|
2893
|
+
var uvExec = isWin2 ? "uv.exe" : "uv";
|
|
2765
2894
|
var makeDependencyCheckCode = (dependency) => `
|
|
2766
2895
|
from importlib import util
|
|
2767
2896
|
dep = '${dependency}'.replace('-', '_')
|
|
@@ -2770,13 +2899,13 @@ print(spec.origin)
|
|
|
2770
2899
|
`;
|
|
2771
2900
|
async function isInstalled(pythonPath, dependency, cwd) {
|
|
2772
2901
|
try {
|
|
2773
|
-
const { stdout } = await (0,
|
|
2902
|
+
const { stdout } = await (0, import_execa2.default)(
|
|
2774
2903
|
pythonPath,
|
|
2775
2904
|
["-c", makeDependencyCheckCode(dependency)],
|
|
2776
2905
|
{
|
|
2777
2906
|
stdio: "pipe",
|
|
2778
2907
|
cwd,
|
|
2779
|
-
env: { ...process.env, PYTHONPATH: (0,
|
|
2908
|
+
env: { ...process.env, PYTHONPATH: (0, import_path2.join)(cwd, resolveVendorDir()) }
|
|
2780
2909
|
}
|
|
2781
2910
|
);
|
|
2782
2911
|
return stdout.startsWith(cwd);
|
|
@@ -2793,13 +2922,13 @@ pkg_resources.require(dependencies)
|
|
|
2793
2922
|
`;
|
|
2794
2923
|
async function areRequirementsInstalled(pythonPath, requirementsPath, cwd) {
|
|
2795
2924
|
try {
|
|
2796
|
-
await (0,
|
|
2925
|
+
await (0, import_execa2.default)(
|
|
2797
2926
|
pythonPath,
|
|
2798
2927
|
["-c", makeRequirementsCheckCode(requirementsPath)],
|
|
2799
2928
|
{
|
|
2800
2929
|
stdio: "pipe",
|
|
2801
2930
|
cwd,
|
|
2802
|
-
env: { ...process.env, PYTHONPATH: (0,
|
|
2931
|
+
env: { ...process.env, PYTHONPATH: (0, import_path2.join)(cwd, resolveVendorDir()) }
|
|
2803
2932
|
}
|
|
2804
2933
|
);
|
|
2805
2934
|
return true;
|
|
@@ -2807,18 +2936,354 @@ async function areRequirementsInstalled(pythonPath, requirementsPath, cwd) {
|
|
|
2807
2936
|
return false;
|
|
2808
2937
|
}
|
|
2809
2938
|
}
|
|
2939
|
+
async function runUvSync({
|
|
2940
|
+
uvPath,
|
|
2941
|
+
venvPath,
|
|
2942
|
+
projectDir,
|
|
2943
|
+
locked
|
|
2944
|
+
}) {
|
|
2945
|
+
const args = ["sync", "--active", "--no-dev", "--link-mode", "copy"];
|
|
2946
|
+
if (locked) {
|
|
2947
|
+
args.push("--locked");
|
|
2948
|
+
}
|
|
2949
|
+
args.push("--no-editable");
|
|
2950
|
+
await runUvCommand({
|
|
2951
|
+
uvPath,
|
|
2952
|
+
args,
|
|
2953
|
+
cwd: projectDir,
|
|
2954
|
+
venvPath
|
|
2955
|
+
});
|
|
2956
|
+
}
|
|
2957
|
+
async function getSitePackagesDirs(pythonBin) {
|
|
2958
|
+
const code = `
|
|
2959
|
+
import json
|
|
2960
|
+
import sysconfig
|
|
2961
|
+
paths = []
|
|
2962
|
+
for key in ("purelib", "platlib"):
|
|
2963
|
+
candidate = sysconfig.get_path(key)
|
|
2964
|
+
if candidate and candidate not in paths:
|
|
2965
|
+
paths.append(candidate)
|
|
2966
|
+
print(json.dumps(paths))
|
|
2967
|
+
`.trim();
|
|
2968
|
+
const { stdout } = await (0, import_execa2.default)(pythonBin, ["-c", code]);
|
|
2969
|
+
try {
|
|
2970
|
+
const parsed = JSON.parse(stdout);
|
|
2971
|
+
if (Array.isArray(parsed)) {
|
|
2972
|
+
return parsed.filter((p) => typeof p === "string");
|
|
2973
|
+
}
|
|
2974
|
+
} catch (err) {
|
|
2975
|
+
(0, import_build_utils2.debug)("Failed to parse site-packages output", err);
|
|
2976
|
+
}
|
|
2977
|
+
return [];
|
|
2978
|
+
}
|
|
2979
|
+
async function getVenvSitePackagesDirs(venvPath) {
|
|
2980
|
+
const pythonBin = getVenvPythonBin(venvPath);
|
|
2981
|
+
return getSitePackagesDirs(pythonBin);
|
|
2982
|
+
}
|
|
2810
2983
|
function resolveVendorDir() {
|
|
2811
2984
|
const vendorDir = process.env.VERCEL_PYTHON_VENDOR_DIR || "_vendor";
|
|
2812
2985
|
return vendorDir;
|
|
2813
2986
|
}
|
|
2987
|
+
async function detectInstallSource({
|
|
2988
|
+
workPath,
|
|
2989
|
+
entryDirectory,
|
|
2990
|
+
fsFiles
|
|
2991
|
+
}) {
|
|
2992
|
+
const uvLockDir = findDir({
|
|
2993
|
+
file: "uv.lock",
|
|
2994
|
+
entryDirectory,
|
|
2995
|
+
workPath,
|
|
2996
|
+
fsFiles
|
|
2997
|
+
});
|
|
2998
|
+
const pyprojectDir = findDir({
|
|
2999
|
+
file: "pyproject.toml",
|
|
3000
|
+
entryDirectory,
|
|
3001
|
+
workPath,
|
|
3002
|
+
fsFiles
|
|
3003
|
+
});
|
|
3004
|
+
const pipfileLockDir = findDir({
|
|
3005
|
+
file: "Pipfile.lock",
|
|
3006
|
+
entryDirectory,
|
|
3007
|
+
workPath,
|
|
3008
|
+
fsFiles
|
|
3009
|
+
});
|
|
3010
|
+
const pipfileDir = findDir({
|
|
3011
|
+
file: "Pipfile",
|
|
3012
|
+
entryDirectory,
|
|
3013
|
+
workPath,
|
|
3014
|
+
fsFiles
|
|
3015
|
+
});
|
|
3016
|
+
const requirementsDir = findDir({
|
|
3017
|
+
file: "requirements.txt",
|
|
3018
|
+
entryDirectory,
|
|
3019
|
+
workPath,
|
|
3020
|
+
fsFiles
|
|
3021
|
+
});
|
|
3022
|
+
let manifestPath = null;
|
|
3023
|
+
let manifestType = null;
|
|
3024
|
+
if (uvLockDir && pyprojectDir) {
|
|
3025
|
+
manifestType = "uv.lock";
|
|
3026
|
+
manifestPath = (0, import_path2.join)(uvLockDir, "uv.lock");
|
|
3027
|
+
} else if (pyprojectDir) {
|
|
3028
|
+
manifestType = "pyproject.toml";
|
|
3029
|
+
manifestPath = (0, import_path2.join)(pyprojectDir, "pyproject.toml");
|
|
3030
|
+
} else if (pipfileLockDir) {
|
|
3031
|
+
manifestType = "Pipfile.lock";
|
|
3032
|
+
manifestPath = (0, import_path2.join)(pipfileLockDir, "Pipfile.lock");
|
|
3033
|
+
} else if (pipfileDir) {
|
|
3034
|
+
manifestType = "Pipfile";
|
|
3035
|
+
manifestPath = (0, import_path2.join)(pipfileDir, "Pipfile");
|
|
3036
|
+
} else if (requirementsDir) {
|
|
3037
|
+
manifestType = "requirements.txt";
|
|
3038
|
+
manifestPath = (0, import_path2.join)(requirementsDir, "requirements.txt");
|
|
3039
|
+
}
|
|
3040
|
+
let manifestContent;
|
|
3041
|
+
if (manifestPath) {
|
|
3042
|
+
try {
|
|
3043
|
+
manifestContent = await import_fs2.default.promises.readFile(manifestPath, "utf8");
|
|
3044
|
+
} catch (err) {
|
|
3045
|
+
(0, import_build_utils2.debug)("Failed to read install manifest contents", err);
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
return { manifestPath, manifestType, manifestContent };
|
|
3049
|
+
}
|
|
3050
|
+
async function createPyprojectToml({
|
|
3051
|
+
projectName,
|
|
3052
|
+
pyprojectPath,
|
|
3053
|
+
dependencies
|
|
3054
|
+
}) {
|
|
3055
|
+
const requiresPython = ">=3.12";
|
|
3056
|
+
const depsToml = dependencies.length > 0 ? [
|
|
3057
|
+
"dependencies = [",
|
|
3058
|
+
...dependencies.map((dep) => ` "${dep}",`),
|
|
3059
|
+
"]"
|
|
3060
|
+
].join("\n") : "dependencies = []";
|
|
3061
|
+
const content = [
|
|
3062
|
+
"[project]",
|
|
3063
|
+
`name = "${projectName}"`,
|
|
3064
|
+
'version = "0.1.0"',
|
|
3065
|
+
`requires-python = "${requiresPython}"`,
|
|
3066
|
+
"classifiers = [",
|
|
3067
|
+
' "Private :: Do Not Upload",',
|
|
3068
|
+
"]",
|
|
3069
|
+
depsToml,
|
|
3070
|
+
""
|
|
3071
|
+
].join("\n");
|
|
3072
|
+
await import_fs2.default.promises.writeFile(pyprojectPath, content);
|
|
3073
|
+
}
|
|
3074
|
+
async function uvLock({
|
|
3075
|
+
projectDir,
|
|
3076
|
+
uvPath
|
|
3077
|
+
}) {
|
|
3078
|
+
const args = ["lock"];
|
|
3079
|
+
const pretty = `${uvPath} ${args.join(" ")}`;
|
|
3080
|
+
(0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
|
|
3081
|
+
try {
|
|
3082
|
+
await (0, import_execa2.default)(uvPath, args, { cwd: projectDir });
|
|
3083
|
+
} catch (err) {
|
|
3084
|
+
throw new Error(
|
|
3085
|
+
`Failed to run "${pretty}": ${err instanceof Error ? err.message : String(err)}`
|
|
3086
|
+
);
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
async function uvAddDependencies({
|
|
3090
|
+
projectDir,
|
|
3091
|
+
uvPath,
|
|
3092
|
+
venvPath,
|
|
3093
|
+
dependencies
|
|
3094
|
+
}) {
|
|
3095
|
+
const toAdd = dependencies.filter(Boolean);
|
|
3096
|
+
if (!toAdd.length)
|
|
3097
|
+
return;
|
|
3098
|
+
const args = ["add", "--active", ...toAdd];
|
|
3099
|
+
const pretty = `${uvPath} ${args.join(" ")}`;
|
|
3100
|
+
(0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
|
|
3101
|
+
await runUvCommand({ uvPath, args, cwd: projectDir, venvPath });
|
|
3102
|
+
}
|
|
3103
|
+
async function uvAddFromFile({
|
|
3104
|
+
projectDir,
|
|
3105
|
+
uvPath,
|
|
3106
|
+
venvPath,
|
|
3107
|
+
requirementsPath
|
|
3108
|
+
}) {
|
|
3109
|
+
const args = ["add", "--active", "-r", requirementsPath];
|
|
3110
|
+
const pretty = `${uvPath} ${args.join(" ")}`;
|
|
3111
|
+
(0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
|
|
3112
|
+
await runUvCommand({ uvPath, args, cwd: projectDir, venvPath });
|
|
3113
|
+
}
|
|
3114
|
+
function getDependencyName(spec) {
|
|
3115
|
+
const match = spec.match(/^[A-Za-z0-9_.-]+/);
|
|
3116
|
+
return match ? match[0].toLowerCase() : spec.toLowerCase();
|
|
3117
|
+
}
|
|
3118
|
+
async function filterMissingRuntimeDependencies({
|
|
3119
|
+
pyprojectPath,
|
|
3120
|
+
runtimeDependencies
|
|
3121
|
+
}) {
|
|
3122
|
+
let declared = [];
|
|
3123
|
+
try {
|
|
3124
|
+
const config = await (0, import_build_utils2.readConfigFile)(pyprojectPath);
|
|
3125
|
+
declared = config?.project?.dependencies || [];
|
|
3126
|
+
} catch (err) {
|
|
3127
|
+
(0, import_build_utils2.debug)("Failed to parse pyproject.toml when filtering runtime deps", err);
|
|
3128
|
+
}
|
|
3129
|
+
const declaredNames = new Set(declared.map(getDependencyName));
|
|
3130
|
+
return runtimeDependencies.filter((spec) => {
|
|
3131
|
+
const name = getDependencyName(spec);
|
|
3132
|
+
return !declaredNames.has(name);
|
|
3133
|
+
});
|
|
3134
|
+
}
|
|
3135
|
+
function findUvLockUpwards(startDir, repoRootPath) {
|
|
3136
|
+
const start = (0, import_path2.resolve)(startDir);
|
|
3137
|
+
const base = repoRootPath ? (0, import_path2.resolve)(repoRootPath) : void 0;
|
|
3138
|
+
for (const dir of (0, import_build_utils2.traverseUpDirectories)({ start, base })) {
|
|
3139
|
+
const lockPath = (0, import_path2.join)(dir, "uv.lock");
|
|
3140
|
+
const pyprojectPath = (0, import_path2.join)(dir, "pyproject.toml");
|
|
3141
|
+
if (import_fs2.default.existsSync(lockPath) && import_fs2.default.existsSync(pyprojectPath)) {
|
|
3142
|
+
return lockPath;
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
return null;
|
|
3146
|
+
}
|
|
3147
|
+
async function ensureUvProject({
|
|
3148
|
+
workPath,
|
|
3149
|
+
entryDirectory,
|
|
3150
|
+
fsFiles,
|
|
3151
|
+
repoRootPath,
|
|
3152
|
+
pythonPath,
|
|
3153
|
+
pipPath,
|
|
3154
|
+
uvPath,
|
|
3155
|
+
venvPath,
|
|
3156
|
+
meta,
|
|
3157
|
+
runtimeDependencies
|
|
3158
|
+
}) {
|
|
3159
|
+
const installInfo = await detectInstallSource({
|
|
3160
|
+
workPath,
|
|
3161
|
+
entryDirectory,
|
|
3162
|
+
fsFiles
|
|
3163
|
+
});
|
|
3164
|
+
const { manifestType, manifestPath } = installInfo;
|
|
3165
|
+
let projectDir;
|
|
3166
|
+
let pyprojectPath;
|
|
3167
|
+
let lockPath = null;
|
|
3168
|
+
if (manifestType === "uv.lock") {
|
|
3169
|
+
if (!manifestPath) {
|
|
3170
|
+
throw new Error("Expected uv.lock path to be resolved, but it was null");
|
|
3171
|
+
}
|
|
3172
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3173
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3174
|
+
if (!import_fs2.default.existsSync(pyprojectPath)) {
|
|
3175
|
+
throw new Error(
|
|
3176
|
+
`Expected "pyproject.toml" next to "uv.lock" in "${projectDir}"`
|
|
3177
|
+
);
|
|
3178
|
+
}
|
|
3179
|
+
lockPath = manifestPath;
|
|
3180
|
+
console.log("Installing required dependencies from uv.lock...");
|
|
3181
|
+
} else if (manifestType === "pyproject.toml") {
|
|
3182
|
+
if (!manifestPath) {
|
|
3183
|
+
throw new Error(
|
|
3184
|
+
"Expected pyproject.toml path to be resolved, but it was null"
|
|
3185
|
+
);
|
|
3186
|
+
}
|
|
3187
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3188
|
+
pyprojectPath = manifestPath;
|
|
3189
|
+
console.log("Installing required dependencies from pyproject.toml...");
|
|
3190
|
+
const workspaceLock = findUvLockUpwards(projectDir, repoRootPath);
|
|
3191
|
+
if (workspaceLock) {
|
|
3192
|
+
lockPath = workspaceLock;
|
|
3193
|
+
} else {
|
|
3194
|
+
await uvLock({ projectDir, uvPath });
|
|
3195
|
+
}
|
|
3196
|
+
} else if (manifestType === "Pipfile.lock" || manifestType === "Pipfile") {
|
|
3197
|
+
if (!manifestPath) {
|
|
3198
|
+
throw new Error(
|
|
3199
|
+
"Expected Pipfile/Pipfile.lock path to be resolved, but it was null"
|
|
3200
|
+
);
|
|
3201
|
+
}
|
|
3202
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3203
|
+
console.log(`Installing required dependencies from ${manifestType}...`);
|
|
3204
|
+
const exportedReq = await exportRequirementsFromPipfile({
|
|
3205
|
+
pythonPath,
|
|
3206
|
+
pipPath,
|
|
3207
|
+
uvPath,
|
|
3208
|
+
projectDir,
|
|
3209
|
+
meta
|
|
3210
|
+
});
|
|
3211
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3212
|
+
if (!import_fs2.default.existsSync(pyprojectPath)) {
|
|
3213
|
+
await createPyprojectToml({
|
|
3214
|
+
projectName: "app",
|
|
3215
|
+
pyprojectPath,
|
|
3216
|
+
dependencies: []
|
|
3217
|
+
});
|
|
3218
|
+
}
|
|
3219
|
+
await uvAddFromFile({
|
|
3220
|
+
projectDir,
|
|
3221
|
+
uvPath,
|
|
3222
|
+
venvPath,
|
|
3223
|
+
requirementsPath: exportedReq
|
|
3224
|
+
});
|
|
3225
|
+
} else if (manifestType === "requirements.txt") {
|
|
3226
|
+
if (!manifestPath) {
|
|
3227
|
+
throw new Error(
|
|
3228
|
+
"Expected requirements.txt path to be resolved, but it was null"
|
|
3229
|
+
);
|
|
3230
|
+
}
|
|
3231
|
+
projectDir = (0, import_path2.dirname)(manifestPath);
|
|
3232
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3233
|
+
console.log(
|
|
3234
|
+
"Installing required dependencies from requirements.txt with uv..."
|
|
3235
|
+
);
|
|
3236
|
+
if (!import_fs2.default.existsSync(pyprojectPath)) {
|
|
3237
|
+
await createPyprojectToml({
|
|
3238
|
+
projectName: "app",
|
|
3239
|
+
pyprojectPath,
|
|
3240
|
+
dependencies: []
|
|
3241
|
+
});
|
|
3242
|
+
}
|
|
3243
|
+
await uvAddFromFile({
|
|
3244
|
+
projectDir,
|
|
3245
|
+
uvPath,
|
|
3246
|
+
venvPath,
|
|
3247
|
+
requirementsPath: manifestPath
|
|
3248
|
+
});
|
|
3249
|
+
} else {
|
|
3250
|
+
projectDir = workPath;
|
|
3251
|
+
pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
|
|
3252
|
+
console.log(
|
|
3253
|
+
"No Python manifest found; creating an empty pyproject.toml and uv.lock..."
|
|
3254
|
+
);
|
|
3255
|
+
await createPyprojectToml({
|
|
3256
|
+
projectName: "app",
|
|
3257
|
+
pyprojectPath,
|
|
3258
|
+
dependencies: []
|
|
3259
|
+
});
|
|
3260
|
+
await uvLock({ projectDir, uvPath });
|
|
3261
|
+
}
|
|
3262
|
+
if (runtimeDependencies.length) {
|
|
3263
|
+
const missingRuntimeDeps = await filterMissingRuntimeDependencies({
|
|
3264
|
+
pyprojectPath,
|
|
3265
|
+
runtimeDependencies
|
|
3266
|
+
});
|
|
3267
|
+
if (missingRuntimeDeps.length) {
|
|
3268
|
+
await uvAddDependencies({
|
|
3269
|
+
projectDir,
|
|
3270
|
+
uvPath,
|
|
3271
|
+
venvPath,
|
|
3272
|
+
dependencies: missingRuntimeDeps
|
|
3273
|
+
});
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
const resolvedLockPath = lockPath && import_fs2.default.existsSync(lockPath) ? lockPath : findUvLockUpwards(projectDir, repoRootPath) || (0, import_path2.join)(projectDir, "uv.lock");
|
|
3277
|
+
return { projectDir, pyprojectPath, lockPath: resolvedLockPath };
|
|
3278
|
+
}
|
|
2814
3279
|
async function getGlobalScriptsDir(pythonPath) {
|
|
2815
3280
|
const code = `import sysconfig; print(sysconfig.get_path('scripts'))`;
|
|
2816
3281
|
try {
|
|
2817
|
-
const { stdout } = await (0,
|
|
3282
|
+
const { stdout } = await (0, import_execa2.default)(pythonPath, ["-c", code]);
|
|
2818
3283
|
const out = stdout.trim();
|
|
2819
3284
|
return out || null;
|
|
2820
3285
|
} catch (err) {
|
|
2821
|
-
(0,
|
|
3286
|
+
(0, import_build_utils2.debug)("Failed to resolve Python global scripts directory", err);
|
|
2822
3287
|
return null;
|
|
2823
3288
|
}
|
|
2824
3289
|
}
|
|
@@ -2828,16 +3293,16 @@ async function getUserScriptsDir(pythonPath) {
|
|
|
2828
3293
|
" "
|
|
2829
3294
|
);
|
|
2830
3295
|
try {
|
|
2831
|
-
const { stdout } = await (0,
|
|
3296
|
+
const { stdout } = await (0, import_execa2.default)(pythonPath, ["-c", code]);
|
|
2832
3297
|
const out = stdout.trim();
|
|
2833
3298
|
return out || null;
|
|
2834
3299
|
} catch (err) {
|
|
2835
|
-
(0,
|
|
3300
|
+
(0, import_build_utils2.debug)("Failed to resolve Python user scripts directory", err);
|
|
2836
3301
|
return null;
|
|
2837
3302
|
}
|
|
2838
3303
|
}
|
|
2839
3304
|
async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
|
|
2840
|
-
const target = targetDir ? (0,
|
|
3305
|
+
const target = targetDir ? (0, import_path2.join)(targetDir, resolveVendorDir()) : resolveVendorDir();
|
|
2841
3306
|
process.env.PIP_USER = "0";
|
|
2842
3307
|
if (uvPath) {
|
|
2843
3308
|
const uvArgs = [
|
|
@@ -2847,18 +3312,18 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
|
|
|
2847
3312
|
"--no-cache-dir",
|
|
2848
3313
|
"--target",
|
|
2849
3314
|
target,
|
|
2850
|
-
...args
|
|
3315
|
+
...filterUnsafeUvPipArgs(args)
|
|
2851
3316
|
];
|
|
2852
3317
|
const prettyUv = `${uvPath} ${uvArgs.join(" ")}`;
|
|
2853
|
-
(0,
|
|
3318
|
+
(0, import_build_utils2.debug)(`Running "${prettyUv}"...`);
|
|
2854
3319
|
try {
|
|
2855
|
-
await (0,
|
|
3320
|
+
await (0, import_execa2.default)(uvPath, uvArgs, {
|
|
2856
3321
|
cwd: workPath
|
|
2857
3322
|
});
|
|
2858
3323
|
return;
|
|
2859
3324
|
} catch (err) {
|
|
2860
3325
|
console.log(`Failed to run "${prettyUv}", falling back to pip`);
|
|
2861
|
-
(0,
|
|
3326
|
+
(0, import_build_utils2.debug)(`error: ${err}`);
|
|
2862
3327
|
}
|
|
2863
3328
|
}
|
|
2864
3329
|
const cmdArgs = [
|
|
@@ -2871,14 +3336,14 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
|
|
|
2871
3336
|
...args
|
|
2872
3337
|
];
|
|
2873
3338
|
const pretty = `${pipPath} ${cmdArgs.join(" ")}`;
|
|
2874
|
-
(0,
|
|
3339
|
+
(0, import_build_utils2.debug)(`Running "${pretty}"...`);
|
|
2875
3340
|
try {
|
|
2876
|
-
await (0,
|
|
3341
|
+
await (0, import_execa2.default)(pipPath, cmdArgs, {
|
|
2877
3342
|
cwd: workPath
|
|
2878
3343
|
});
|
|
2879
3344
|
} catch (err) {
|
|
2880
3345
|
console.log(`Failed to run "${pretty}"`);
|
|
2881
|
-
(0,
|
|
3346
|
+
(0, import_build_utils2.debug)(`error: ${err}`);
|
|
2882
3347
|
throw err;
|
|
2883
3348
|
}
|
|
2884
3349
|
}
|
|
@@ -2889,38 +3354,38 @@ async function maybeFindUvBin(pythonPath) {
|
|
|
2889
3354
|
try {
|
|
2890
3355
|
const globalScriptsDir = await getGlobalScriptsDir(pythonPath);
|
|
2891
3356
|
if (globalScriptsDir) {
|
|
2892
|
-
const uvPath = (0,
|
|
2893
|
-
if (
|
|
3357
|
+
const uvPath = (0, import_path2.join)(globalScriptsDir, uvExec);
|
|
3358
|
+
if (import_fs2.default.existsSync(uvPath))
|
|
2894
3359
|
return uvPath;
|
|
2895
3360
|
}
|
|
2896
3361
|
} catch (err) {
|
|
2897
|
-
(0,
|
|
3362
|
+
(0, import_build_utils2.debug)("Failed to resolve Python global scripts directory", err);
|
|
2898
3363
|
}
|
|
2899
3364
|
try {
|
|
2900
3365
|
const userScriptsDir = await getUserScriptsDir(pythonPath);
|
|
2901
3366
|
if (userScriptsDir) {
|
|
2902
|
-
const uvPath = (0,
|
|
2903
|
-
if (
|
|
3367
|
+
const uvPath = (0, import_path2.join)(userScriptsDir, uvExec);
|
|
3368
|
+
if (import_fs2.default.existsSync(uvPath))
|
|
2904
3369
|
return uvPath;
|
|
2905
3370
|
}
|
|
2906
3371
|
} catch (err) {
|
|
2907
|
-
(0,
|
|
3372
|
+
(0, import_build_utils2.debug)("Failed to resolve Python user scripts directory", err);
|
|
2908
3373
|
}
|
|
2909
3374
|
try {
|
|
2910
3375
|
const candidates = [];
|
|
2911
|
-
if (!
|
|
2912
|
-
candidates.push((0,
|
|
3376
|
+
if (!isWin2) {
|
|
3377
|
+
candidates.push((0, import_path2.join)(import_os.default.homedir(), ".local", "bin", "uv"));
|
|
2913
3378
|
candidates.push("/usr/local/bin/uv");
|
|
2914
3379
|
candidates.push("/opt/homebrew/bin/uv");
|
|
2915
3380
|
} else {
|
|
2916
3381
|
candidates.push("C:\\Users\\Public\\uv\\uv.exe");
|
|
2917
3382
|
}
|
|
2918
3383
|
for (const p of candidates) {
|
|
2919
|
-
if (
|
|
3384
|
+
if (import_fs2.default.existsSync(p))
|
|
2920
3385
|
return p;
|
|
2921
3386
|
}
|
|
2922
3387
|
} catch (err) {
|
|
2923
|
-
(0,
|
|
3388
|
+
(0, import_build_utils2.debug)("Failed to resolve uv fallback paths", err);
|
|
2924
3389
|
}
|
|
2925
3390
|
return null;
|
|
2926
3391
|
}
|
|
@@ -2930,7 +3395,7 @@ async function getUvBinaryOrInstall(pythonPath) {
|
|
|
2930
3395
|
return uvBin;
|
|
2931
3396
|
try {
|
|
2932
3397
|
console.log("Installing uv...");
|
|
2933
|
-
await (0,
|
|
3398
|
+
await (0, import_execa2.default)(
|
|
2934
3399
|
pythonPath,
|
|
2935
3400
|
[
|
|
2936
3401
|
"-m",
|
|
@@ -2968,7 +3433,7 @@ async function installRequirement({
|
|
|
2968
3433
|
}) {
|
|
2969
3434
|
const actualTargetDir = targetDir || workPath;
|
|
2970
3435
|
if (meta.isDev && await isInstalled(pythonPath, dependency, actualTargetDir)) {
|
|
2971
|
-
(0,
|
|
3436
|
+
(0, import_build_utils2.debug)(
|
|
2972
3437
|
`Skipping ${dependency} dependency installation, already installed in ${actualTargetDir}`
|
|
2973
3438
|
);
|
|
2974
3439
|
return;
|
|
@@ -2988,7 +3453,7 @@ async function installRequirementsFile({
|
|
|
2988
3453
|
}) {
|
|
2989
3454
|
const actualTargetDir = targetDir || workPath;
|
|
2990
3455
|
if (meta.isDev && await areRequirementsInstalled(pythonPath, filePath, actualTargetDir)) {
|
|
2991
|
-
(0,
|
|
3456
|
+
(0, import_build_utils2.debug)(`Skipping requirements file installation, already installed`);
|
|
2992
3457
|
return;
|
|
2993
3458
|
}
|
|
2994
3459
|
await pipInstall(
|
|
@@ -2999,30 +3464,8 @@ async function installRequirementsFile({
|
|
|
2999
3464
|
targetDir
|
|
3000
3465
|
);
|
|
3001
3466
|
}
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
if (!uvPath) {
|
|
3005
|
-
throw new Error("uv is not available to export requirements");
|
|
3006
|
-
}
|
|
3007
|
-
const args = ["export"];
|
|
3008
|
-
if (locked) {
|
|
3009
|
-
args.push("--frozen");
|
|
3010
|
-
}
|
|
3011
|
-
(0, import_build_utils.debug)(`Running "${uvPath} ${args.join(" ")}" in ${projectDir}...`);
|
|
3012
|
-
let stdout;
|
|
3013
|
-
try {
|
|
3014
|
-
const { stdout: out } = await (0, import_execa.default)(uvPath, args, { cwd: projectDir });
|
|
3015
|
-
stdout = out;
|
|
3016
|
-
} catch (err) {
|
|
3017
|
-
throw new Error(
|
|
3018
|
-
`Failed to run "${uvPath} ${args.join(" ")}": ${err instanceof Error ? err.message : String(err)}`
|
|
3019
|
-
);
|
|
3020
|
-
}
|
|
3021
|
-
const tmpDir = await import_fs.default.promises.mkdtemp((0, import_path.join)(import_os.default.tmpdir(), "vercel-uv-"));
|
|
3022
|
-
const outPath = (0, import_path.join)(tmpDir, "requirements.uv.txt");
|
|
3023
|
-
await import_fs.default.promises.writeFile(outPath, stdout);
|
|
3024
|
-
(0, import_build_utils.debug)(`Exported requirements to ${outPath}`);
|
|
3025
|
-
return outPath;
|
|
3467
|
+
function filterUnsafeUvPipArgs(args) {
|
|
3468
|
+
return args.filter((arg) => arg !== "--no-warn-script-location");
|
|
3026
3469
|
}
|
|
3027
3470
|
async function exportRequirementsFromPipfile({
|
|
3028
3471
|
pythonPath,
|
|
@@ -3031,8 +3474,8 @@ async function exportRequirementsFromPipfile({
|
|
|
3031
3474
|
projectDir,
|
|
3032
3475
|
meta
|
|
3033
3476
|
}) {
|
|
3034
|
-
const tempDir = await
|
|
3035
|
-
(0,
|
|
3477
|
+
const tempDir = await import_fs2.default.promises.mkdtemp(
|
|
3478
|
+
(0, import_path2.join)(import_os.default.tmpdir(), "vercel-pipenv-")
|
|
3036
3479
|
);
|
|
3037
3480
|
await installRequirement({
|
|
3038
3481
|
pythonPath,
|
|
@@ -3044,12 +3487,12 @@ async function exportRequirementsFromPipfile({
|
|
|
3044
3487
|
args: ["--no-warn-script-location"],
|
|
3045
3488
|
uvPath
|
|
3046
3489
|
});
|
|
3047
|
-
const tempVendorDir = (0,
|
|
3048
|
-
const convertCmd =
|
|
3049
|
-
(0,
|
|
3490
|
+
const tempVendorDir = (0, import_path2.join)(tempDir, resolveVendorDir());
|
|
3491
|
+
const convertCmd = isWin2 ? (0, import_path2.join)(tempVendorDir, "Scripts", "pipfile2req.exe") : (0, import_path2.join)(tempVendorDir, "bin", "pipfile2req");
|
|
3492
|
+
(0, import_build_utils2.debug)(`Running "${convertCmd}" in ${projectDir}...`);
|
|
3050
3493
|
let stdout;
|
|
3051
3494
|
try {
|
|
3052
|
-
const { stdout: out } = await (0,
|
|
3495
|
+
const { stdout: out } = await (0, import_execa2.default)(convertCmd, [], {
|
|
3053
3496
|
cwd: projectDir,
|
|
3054
3497
|
env: { ...process.env, PYTHONPATH: tempVendorDir }
|
|
3055
3498
|
});
|
|
@@ -3059,17 +3502,46 @@ async function exportRequirementsFromPipfile({
|
|
|
3059
3502
|
`Failed to run "${convertCmd}": ${err instanceof Error ? err.message : String(err)}`
|
|
3060
3503
|
);
|
|
3061
3504
|
}
|
|
3062
|
-
const outPath = (0,
|
|
3063
|
-
await
|
|
3064
|
-
(0,
|
|
3505
|
+
const outPath = (0, import_path2.join)(tempDir, "requirements.pipenv.txt");
|
|
3506
|
+
await import_fs2.default.promises.writeFile(outPath, stdout);
|
|
3507
|
+
(0, import_build_utils2.debug)(`Exported pipfile requirements to ${outPath}`);
|
|
3065
3508
|
return outPath;
|
|
3066
3509
|
}
|
|
3510
|
+
async function mirrorSitePackagesIntoVendor({
|
|
3511
|
+
venvPath,
|
|
3512
|
+
vendorDirName
|
|
3513
|
+
}) {
|
|
3514
|
+
const vendorFiles = {};
|
|
3515
|
+
try {
|
|
3516
|
+
const sitePackageDirs = await getVenvSitePackagesDirs(venvPath);
|
|
3517
|
+
for (const dir of sitePackageDirs) {
|
|
3518
|
+
if (!import_fs2.default.existsSync(dir))
|
|
3519
|
+
continue;
|
|
3520
|
+
const dirFiles = await (0, import_build_utils2.glob)("**", dir);
|
|
3521
|
+
for (const relativePath of Object.keys(dirFiles)) {
|
|
3522
|
+
if (relativePath.endsWith(".pyc") || relativePath.includes("__pycache__")) {
|
|
3523
|
+
continue;
|
|
3524
|
+
}
|
|
3525
|
+
const srcFsPath = (0, import_path2.join)(dir, relativePath);
|
|
3526
|
+
const bundlePath = (0, import_path2.join)(vendorDirName, relativePath).replace(
|
|
3527
|
+
/\\/g,
|
|
3528
|
+
"/"
|
|
3529
|
+
);
|
|
3530
|
+
vendorFiles[bundlePath] = new import_build_utils2.FileFsRef({ fsPath: srcFsPath });
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
} catch (err) {
|
|
3534
|
+
console.log("Failed to collect site-packages from virtual environment");
|
|
3535
|
+
throw err;
|
|
3536
|
+
}
|
|
3537
|
+
return vendorFiles;
|
|
3538
|
+
}
|
|
3067
3539
|
|
|
3068
3540
|
// src/index.ts
|
|
3069
|
-
var
|
|
3541
|
+
var import_build_utils8 = require("@vercel/build-utils");
|
|
3070
3542
|
|
|
3071
3543
|
// src/version.ts
|
|
3072
|
-
var
|
|
3544
|
+
var import_build_utils3 = require("@vercel/build-utils");
|
|
3073
3545
|
var import_which2 = __toESM(require_lib());
|
|
3074
3546
|
var allOptions = [
|
|
3075
3547
|
{
|
|
@@ -3120,7 +3592,7 @@ function getLatestPythonVersion({
|
|
|
3120
3592
|
}
|
|
3121
3593
|
const selection = allOptions.find(isInstalled2);
|
|
3122
3594
|
if (!selection) {
|
|
3123
|
-
throw new
|
|
3595
|
+
throw new import_build_utils3.NowBuildError({
|
|
3124
3596
|
code: "PYTHON_NOT_FOUND",
|
|
3125
3597
|
link: "http://vercel.link/python-version",
|
|
3126
3598
|
message: `Unable to find any supported Python versions.`
|
|
@@ -3128,6 +3600,81 @@ function getLatestPythonVersion({
|
|
|
3128
3600
|
}
|
|
3129
3601
|
return selection;
|
|
3130
3602
|
}
|
|
3603
|
+
function parseVersionTuple(input) {
|
|
3604
|
+
const cleaned = input.trim().replace(/\s+/g, "");
|
|
3605
|
+
const m = cleaned.match(/^(\d+)(?:\.(\d+))?/);
|
|
3606
|
+
if (!m)
|
|
3607
|
+
return null;
|
|
3608
|
+
const major = Number(m[1]);
|
|
3609
|
+
const minor = m[2] !== void 0 ? Number(m[2]) : 0;
|
|
3610
|
+
if (Number.isNaN(major) || Number.isNaN(minor))
|
|
3611
|
+
return null;
|
|
3612
|
+
return [major, minor];
|
|
3613
|
+
}
|
|
3614
|
+
function compareTuples(a, b) {
|
|
3615
|
+
if (a[0] !== b[0])
|
|
3616
|
+
return a[0] - b[0];
|
|
3617
|
+
return a[1] - b[1];
|
|
3618
|
+
}
|
|
3619
|
+
function parseSpecifier(spec) {
|
|
3620
|
+
const s = spec.trim();
|
|
3621
|
+
const m = s.match(/^(<=|>=|==|!=|~=|<|>)\s*([0-9]+(?:\.[0-9]+)?)(?:\.\*)?$/) || // Bare version like "3.11" -> implied ==
|
|
3622
|
+
s.match(/^()([0-9]+(?:\.[0-9]+)?)(?:\.\*)?$/);
|
|
3623
|
+
if (!m)
|
|
3624
|
+
return null;
|
|
3625
|
+
const op = m[1] || "==";
|
|
3626
|
+
const vt = parseVersionTuple(m[2]);
|
|
3627
|
+
if (!vt)
|
|
3628
|
+
return null;
|
|
3629
|
+
return { op, ver: vt };
|
|
3630
|
+
}
|
|
3631
|
+
function satisfies(candidate, spec) {
|
|
3632
|
+
const cmp = compareTuples(candidate, spec.ver);
|
|
3633
|
+
switch (spec.op) {
|
|
3634
|
+
case "==":
|
|
3635
|
+
return cmp === 0;
|
|
3636
|
+
case "!=":
|
|
3637
|
+
return cmp !== 0;
|
|
3638
|
+
case "<":
|
|
3639
|
+
return cmp < 0;
|
|
3640
|
+
case "<=":
|
|
3641
|
+
return cmp <= 0;
|
|
3642
|
+
case ">":
|
|
3643
|
+
return cmp > 0;
|
|
3644
|
+
case ">=":
|
|
3645
|
+
return cmp >= 0;
|
|
3646
|
+
case "~=": {
|
|
3647
|
+
const lowerOk = cmp >= 0;
|
|
3648
|
+
const upper = [spec.ver[0], spec.ver[1] + 1];
|
|
3649
|
+
return lowerOk && compareTuples(candidate, upper) < 0;
|
|
3650
|
+
}
|
|
3651
|
+
default:
|
|
3652
|
+
return false;
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
function selectFromRequiresPython(expr) {
|
|
3656
|
+
const raw = expr.trim();
|
|
3657
|
+
if (!raw)
|
|
3658
|
+
return void 0;
|
|
3659
|
+
const parts = raw.split(",").map((p) => p.trim()).filter(Boolean);
|
|
3660
|
+
const specifiers = [];
|
|
3661
|
+
for (const p of parts) {
|
|
3662
|
+
const sp = parseSpecifier(p);
|
|
3663
|
+
if (sp)
|
|
3664
|
+
specifiers.push(sp);
|
|
3665
|
+
}
|
|
3666
|
+
if (specifiers.length === 0) {
|
|
3667
|
+
return allOptions.find((o) => o.version === raw);
|
|
3668
|
+
}
|
|
3669
|
+
const matches = allOptions.filter((opt) => {
|
|
3670
|
+
const vt = parseVersionTuple(opt.version);
|
|
3671
|
+
return specifiers.every((sp) => satisfies(vt, sp));
|
|
3672
|
+
});
|
|
3673
|
+
if (matches.length === 0)
|
|
3674
|
+
return void 0;
|
|
3675
|
+
const installedMatch = matches.find(isInstalled2);
|
|
3676
|
+
return installedMatch ?? matches[0];
|
|
3677
|
+
}
|
|
3131
3678
|
function getSupportedPythonVersion({
|
|
3132
3679
|
isDev,
|
|
3133
3680
|
declaredPythonVersion
|
|
@@ -3138,10 +3685,15 @@ function getSupportedPythonVersion({
|
|
|
3138
3685
|
let selection = getLatestPythonVersion({ isDev: false });
|
|
3139
3686
|
if (declaredPythonVersion) {
|
|
3140
3687
|
const { version: version2, source } = declaredPythonVersion;
|
|
3141
|
-
|
|
3688
|
+
let requested;
|
|
3689
|
+
if (source === "pyproject.toml") {
|
|
3690
|
+
requested = selectFromRequiresPython(version2);
|
|
3691
|
+
} else {
|
|
3692
|
+
requested = allOptions.find((o) => o.version === version2);
|
|
3693
|
+
}
|
|
3142
3694
|
if (requested) {
|
|
3143
3695
|
if (isDiscontinued(requested)) {
|
|
3144
|
-
throw new
|
|
3696
|
+
throw new import_build_utils3.NowBuildError({
|
|
3145
3697
|
code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
|
|
3146
3698
|
link: "http://vercel.link/python-version",
|
|
3147
3699
|
message: `Python version "${requested.version}" detected in ${source} is discontinued and must be upgraded.`
|
|
@@ -3172,7 +3724,7 @@ function getSupportedPythonVersion({
|
|
|
3172
3724
|
);
|
|
3173
3725
|
}
|
|
3174
3726
|
if (isDiscontinued(selection)) {
|
|
3175
|
-
throw new
|
|
3727
|
+
throw new import_build_utils3.NowBuildError({
|
|
3176
3728
|
code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
|
|
3177
3729
|
link: "http://vercel.link/python-version",
|
|
3178
3730
|
message: `Python version "${selection.version}" declared in project configuration is discontinued and must be upgraded.`
|
|
@@ -3199,18 +3751,19 @@ function isInstalled2({ pipPath, pythonPath }) {
|
|
|
3199
3751
|
var import_child_process = require("child_process");
|
|
3200
3752
|
var import_fs4 = require("fs");
|
|
3201
3753
|
var import_path4 = require("path");
|
|
3202
|
-
var
|
|
3754
|
+
var import_build_utils6 = require("@vercel/build-utils");
|
|
3203
3755
|
|
|
3204
3756
|
// src/entrypoint.ts
|
|
3205
|
-
var
|
|
3206
|
-
var
|
|
3207
|
-
var
|
|
3757
|
+
var import_fs3 = __toESM(require("fs"));
|
|
3758
|
+
var import_path3 = require("path");
|
|
3759
|
+
var import_build_utils4 = require("@vercel/build-utils");
|
|
3760
|
+
var import_build_utils5 = require("@vercel/build-utils");
|
|
3208
3761
|
var FASTAPI_ENTRYPOINT_FILENAMES = ["app", "index", "server", "main"];
|
|
3209
|
-
var FASTAPI_ENTRYPOINT_DIRS = ["", "src", "app"];
|
|
3762
|
+
var FASTAPI_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
|
|
3210
3763
|
var FASTAPI_CONTENT_REGEX = /(from\s+fastapi\s+import\s+FastAPI|import\s+fastapi|FastAPI\s*\()/;
|
|
3211
3764
|
var FASTAPI_CANDIDATE_ENTRYPOINTS = FASTAPI_ENTRYPOINT_FILENAMES.flatMap(
|
|
3212
3765
|
(filename) => FASTAPI_ENTRYPOINT_DIRS.map(
|
|
3213
|
-
(dir) =>
|
|
3766
|
+
(dir) => import_path3.posix.join(dir, `${filename}.py`)
|
|
3214
3767
|
)
|
|
3215
3768
|
);
|
|
3216
3769
|
function isFastapiEntrypoint(file) {
|
|
@@ -3218,18 +3771,18 @@ function isFastapiEntrypoint(file) {
|
|
|
3218
3771
|
const fsPath = file.fsPath;
|
|
3219
3772
|
if (!fsPath)
|
|
3220
3773
|
return false;
|
|
3221
|
-
const contents =
|
|
3774
|
+
const contents = import_fs3.default.readFileSync(fsPath, "utf8");
|
|
3222
3775
|
return FASTAPI_CONTENT_REGEX.test(contents);
|
|
3223
3776
|
} catch {
|
|
3224
3777
|
return false;
|
|
3225
3778
|
}
|
|
3226
3779
|
}
|
|
3227
3780
|
var FLASK_ENTRYPOINT_FILENAMES = ["app", "index", "server", "main"];
|
|
3228
|
-
var FLASK_ENTRYPOINT_DIRS = ["", "src", "app"];
|
|
3781
|
+
var FLASK_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
|
|
3229
3782
|
var FLASK_CONTENT_REGEX = /(from\s+flask\s+import\s+Flask|import\s+flask|Flask\s*\()/;
|
|
3230
3783
|
var FLASK_CANDIDATE_ENTRYPOINTS = FLASK_ENTRYPOINT_FILENAMES.flatMap(
|
|
3231
3784
|
(filename) => FLASK_ENTRYPOINT_DIRS.map(
|
|
3232
|
-
(dir) =>
|
|
3785
|
+
(dir) => import_path3.posix.join(dir, `${filename}.py`)
|
|
3233
3786
|
)
|
|
3234
3787
|
);
|
|
3235
3788
|
function isFlaskEntrypoint(file) {
|
|
@@ -3237,7 +3790,7 @@ function isFlaskEntrypoint(file) {
|
|
|
3237
3790
|
const fsPath = file.fsPath;
|
|
3238
3791
|
if (!fsPath)
|
|
3239
3792
|
return false;
|
|
3240
|
-
const contents =
|
|
3793
|
+
const contents = import_fs3.default.readFileSync(fsPath, "utf8");
|
|
3241
3794
|
return FLASK_CONTENT_REGEX.test(contents);
|
|
3242
3795
|
} catch {
|
|
3243
3796
|
return false;
|
|
@@ -3246,7 +3799,7 @@ function isFlaskEntrypoint(file) {
|
|
|
3246
3799
|
async function detectFlaskEntrypoint(workPath, configuredEntrypoint) {
|
|
3247
3800
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
3248
3801
|
try {
|
|
3249
|
-
const fsFiles = await (0,
|
|
3802
|
+
const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
|
|
3250
3803
|
if (fsFiles[entry])
|
|
3251
3804
|
return entry;
|
|
3252
3805
|
const candidates = FLASK_CANDIDATE_ENTRYPOINTS.filter(
|
|
@@ -3256,19 +3809,19 @@ async function detectFlaskEntrypoint(workPath, configuredEntrypoint) {
|
|
|
3256
3809
|
const flaskEntrypoint = candidates.find(
|
|
3257
3810
|
(c) => isFlaskEntrypoint(fsFiles[c])
|
|
3258
3811
|
) || candidates[0];
|
|
3259
|
-
(0,
|
|
3812
|
+
(0, import_build_utils4.debug)(`Detected Flask entrypoint: ${flaskEntrypoint}`);
|
|
3260
3813
|
return flaskEntrypoint;
|
|
3261
3814
|
}
|
|
3262
3815
|
return null;
|
|
3263
3816
|
} catch {
|
|
3264
|
-
(0,
|
|
3817
|
+
(0, import_build_utils4.debug)("Failed to discover entrypoint for Flask");
|
|
3265
3818
|
return null;
|
|
3266
3819
|
}
|
|
3267
3820
|
}
|
|
3268
3821
|
async function detectFastapiEntrypoint(workPath, configuredEntrypoint) {
|
|
3269
3822
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
3270
3823
|
try {
|
|
3271
|
-
const fsFiles = await (0,
|
|
3824
|
+
const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
|
|
3272
3825
|
if (fsFiles[entry])
|
|
3273
3826
|
return entry;
|
|
3274
3827
|
const candidates = FASTAPI_CANDIDATE_ENTRYPOINTS.filter(
|
|
@@ -3278,38 +3831,51 @@ async function detectFastapiEntrypoint(workPath, configuredEntrypoint) {
|
|
|
3278
3831
|
const fastapiEntrypoint = candidates.find(
|
|
3279
3832
|
(c) => isFastapiEntrypoint(fsFiles[c])
|
|
3280
3833
|
) || candidates[0];
|
|
3281
|
-
(0,
|
|
3834
|
+
(0, import_build_utils4.debug)(`Detected FastAPI entrypoint: ${fastapiEntrypoint}`);
|
|
3282
3835
|
return fastapiEntrypoint;
|
|
3283
3836
|
}
|
|
3284
3837
|
return null;
|
|
3285
3838
|
} catch {
|
|
3286
|
-
(0,
|
|
3839
|
+
(0, import_build_utils4.debug)("Failed to discover entrypoint for FastAPI");
|
|
3287
3840
|
return null;
|
|
3288
3841
|
}
|
|
3289
3842
|
}
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
const
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
const
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
return { pythonCmd, venvRoot };
|
|
3843
|
+
async function getPyprojectEntrypoint(workPath) {
|
|
3844
|
+
const pyprojectData = await (0, import_build_utils5.readConfigFile)((0, import_path3.join)(workPath, "pyproject.toml"));
|
|
3845
|
+
if (!pyprojectData)
|
|
3846
|
+
return null;
|
|
3847
|
+
const scripts = pyprojectData.project?.scripts;
|
|
3848
|
+
const appScript = scripts?.app;
|
|
3849
|
+
if (typeof appScript !== "string")
|
|
3850
|
+
return null;
|
|
3851
|
+
const match = appScript.match(/([A-Za-z_][\w.]*)\s*:\s*([A-Za-z_][\w]*)/);
|
|
3852
|
+
if (!match)
|
|
3853
|
+
return null;
|
|
3854
|
+
const modulePath = match[1];
|
|
3855
|
+
const relPath = modulePath.replace(/\./g, "/");
|
|
3856
|
+
try {
|
|
3857
|
+
const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
|
|
3858
|
+
const candidates = [`${relPath}.py`, `${relPath}/__init__.py`];
|
|
3859
|
+
for (const candidate of candidates) {
|
|
3860
|
+
if (fsFiles[candidate])
|
|
3861
|
+
return candidate;
|
|
3310
3862
|
}
|
|
3863
|
+
return null;
|
|
3864
|
+
} catch {
|
|
3865
|
+
(0, import_build_utils4.debug)("Failed to discover Python entrypoint from pyproject.toml");
|
|
3866
|
+
return null;
|
|
3311
3867
|
}
|
|
3312
|
-
|
|
3868
|
+
}
|
|
3869
|
+
async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint) {
|
|
3870
|
+
let entrypoint = null;
|
|
3871
|
+
if (framework === "fastapi") {
|
|
3872
|
+
entrypoint = await detectFastapiEntrypoint(workPath, configuredEntrypoint);
|
|
3873
|
+
} else if (framework === "flask") {
|
|
3874
|
+
entrypoint = await detectFlaskEntrypoint(workPath, configuredEntrypoint);
|
|
3875
|
+
}
|
|
3876
|
+
if (entrypoint)
|
|
3877
|
+
return entrypoint;
|
|
3878
|
+
return await getPyprojectEntrypoint(workPath);
|
|
3313
3879
|
}
|
|
3314
3880
|
|
|
3315
3881
|
// src/start-dev-server.ts
|
|
@@ -3355,12 +3921,12 @@ function installGlobalCleanupHandlers() {
|
|
|
3355
3921
|
try {
|
|
3356
3922
|
process.kill(info.pid, "SIGTERM");
|
|
3357
3923
|
} catch (err) {
|
|
3358
|
-
(0,
|
|
3924
|
+
(0, import_build_utils6.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
|
|
3359
3925
|
}
|
|
3360
3926
|
try {
|
|
3361
3927
|
process.kill(info.pid, "SIGKILL");
|
|
3362
3928
|
} catch (err) {
|
|
3363
|
-
(0,
|
|
3929
|
+
(0, import_build_utils6.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
|
|
3364
3930
|
}
|
|
3365
3931
|
PERSISTENT_SERVERS.delete(key);
|
|
3366
3932
|
}
|
|
@@ -3368,7 +3934,7 @@ function installGlobalCleanupHandlers() {
|
|
|
3368
3934
|
try {
|
|
3369
3935
|
restoreWarnings();
|
|
3370
3936
|
} catch (err) {
|
|
3371
|
-
(0,
|
|
3937
|
+
(0, import_build_utils6.debug)(`Error restoring warnings: ${err}`);
|
|
3372
3938
|
}
|
|
3373
3939
|
restoreWarnings = null;
|
|
3374
3940
|
}
|
|
@@ -3394,10 +3960,10 @@ function createDevAsgiShim(workPath, modulePath) {
|
|
|
3394
3960
|
const template = (0, import_fs4.readFileSync)(templatePath, "utf8");
|
|
3395
3961
|
const shimSource = template.replace(/__VC_DEV_MODULE_PATH__/g, modulePath);
|
|
3396
3962
|
(0, import_fs4.writeFileSync)(shimPath, shimSource, "utf8");
|
|
3397
|
-
(0,
|
|
3963
|
+
(0, import_build_utils6.debug)(`Prepared Python dev static shim at ${shimPath}`);
|
|
3398
3964
|
return ASGI_SHIM_MODULE;
|
|
3399
3965
|
} catch (err) {
|
|
3400
|
-
(0,
|
|
3966
|
+
(0, import_build_utils6.debug)(`Failed to prepare dev static shim: ${err?.message || err}`);
|
|
3401
3967
|
return null;
|
|
3402
3968
|
}
|
|
3403
3969
|
}
|
|
@@ -3410,10 +3976,10 @@ function createDevWsgiShim(workPath, modulePath) {
|
|
|
3410
3976
|
const template = (0, import_fs4.readFileSync)(templatePath, "utf8");
|
|
3411
3977
|
const shimSource = template.replace(/__VC_DEV_MODULE_PATH__/g, modulePath);
|
|
3412
3978
|
(0, import_fs4.writeFileSync)(shimPath, shimSource, "utf8");
|
|
3413
|
-
(0,
|
|
3979
|
+
(0, import_build_utils6.debug)(`Prepared Python dev WSGI shim at ${shimPath}`);
|
|
3414
3980
|
return WSGI_SHIM_MODULE;
|
|
3415
3981
|
} catch (err) {
|
|
3416
|
-
(0,
|
|
3982
|
+
(0, import_build_utils6.debug)(`Failed to prepare dev WSGI shim: ${err?.message || err}`);
|
|
3417
3983
|
return null;
|
|
3418
3984
|
}
|
|
3419
3985
|
}
|
|
@@ -3426,26 +3992,19 @@ var startDevServer = async (opts) => {
|
|
|
3426
3992
|
if (!restoreWarnings)
|
|
3427
3993
|
restoreWarnings = silenceNodeWarnings();
|
|
3428
3994
|
installGlobalCleanupHandlers();
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
const detectedFlask = await detectFlaskEntrypoint(workPath, rawEntrypoint);
|
|
3443
|
-
if (!detectedFlask) {
|
|
3444
|
-
throw new Error(
|
|
3445
|
-
`No Flask entrypoint found. Searched for: ${FLASK_CANDIDATE_ENTRYPOINTS.join(", ")}`
|
|
3446
|
-
);
|
|
3447
|
-
}
|
|
3448
|
-
entry = detectedFlask;
|
|
3995
|
+
const entry = await detectPythonEntrypoint(
|
|
3996
|
+
framework,
|
|
3997
|
+
workPath,
|
|
3998
|
+
rawEntrypoint
|
|
3999
|
+
);
|
|
4000
|
+
if (!entry) {
|
|
4001
|
+
const searched = framework === "fastapi" ? FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ") : FLASK_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
4002
|
+
throw new import_build_utils6.NowBuildError({
|
|
4003
|
+
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
4004
|
+
message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searched}.`,
|
|
4005
|
+
link: `https://vercel.com/docs/frameworks/backend/${framework?.toLowerCase()}#exporting-the-${framework?.toLowerCase()}-application`,
|
|
4006
|
+
action: "Learn More"
|
|
4007
|
+
});
|
|
3449
4008
|
}
|
|
3450
4009
|
const modulePath = entry.replace(/\.py$/i, "").replace(/[\\/]/g, ".");
|
|
3451
4010
|
const env = { ...process.env, ...meta.env || {} };
|
|
@@ -3477,20 +4036,20 @@ var startDevServer = async (opts) => {
|
|
|
3477
4036
|
let resolveChildReady;
|
|
3478
4037
|
let rejectChildReady;
|
|
3479
4038
|
const childReady = new Promise(
|
|
3480
|
-
(
|
|
3481
|
-
resolveChildReady =
|
|
4039
|
+
(resolve2, reject) => {
|
|
4040
|
+
resolveChildReady = resolve2;
|
|
3482
4041
|
rejectChildReady = reject;
|
|
3483
4042
|
}
|
|
3484
4043
|
);
|
|
3485
4044
|
PENDING_STARTS.set(serverKey, childReady);
|
|
3486
4045
|
try {
|
|
3487
|
-
await new Promise((
|
|
4046
|
+
await new Promise((resolve2, reject) => {
|
|
3488
4047
|
let resolved = false;
|
|
3489
4048
|
const { pythonPath: systemPython } = getLatestPythonVersion(meta);
|
|
3490
4049
|
let pythonCmd = systemPython;
|
|
3491
4050
|
const venv = isInVirtualEnv();
|
|
3492
4051
|
if (venv) {
|
|
3493
|
-
(0,
|
|
4052
|
+
(0, import_build_utils6.debug)(`Running in virtualenv at ${venv}`);
|
|
3494
4053
|
} else {
|
|
3495
4054
|
const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
|
|
3496
4055
|
workPath,
|
|
@@ -3499,9 +4058,9 @@ var startDevServer = async (opts) => {
|
|
|
3499
4058
|
);
|
|
3500
4059
|
pythonCmd = venvPythonCmd;
|
|
3501
4060
|
if (venvRoot) {
|
|
3502
|
-
(0,
|
|
4061
|
+
(0, import_build_utils6.debug)(`Using virtualenv at ${venvRoot}`);
|
|
3503
4062
|
} else {
|
|
3504
|
-
(0,
|
|
4063
|
+
(0, import_build_utils6.debug)("No virtualenv found");
|
|
3505
4064
|
try {
|
|
3506
4065
|
const yellow = "\x1B[33m";
|
|
3507
4066
|
const reset = "\x1B[0m";
|
|
@@ -3524,7 +4083,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3524
4083
|
}
|
|
3525
4084
|
const moduleToRun = devShimModule || modulePath;
|
|
3526
4085
|
const argv = ["-u", "-m", moduleToRun];
|
|
3527
|
-
(0,
|
|
4086
|
+
(0, import_build_utils6.debug)(`Starting ASGI dev server: ${pythonCmd} ${argv.join(" ")}`);
|
|
3528
4087
|
const child = (0, import_child_process.spawn)(pythonCmd, argv, {
|
|
3529
4088
|
cwd: workPath,
|
|
3530
4089
|
env,
|
|
@@ -3572,7 +4131,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3572
4131
|
child.stderr?.removeListener("data", onDetect);
|
|
3573
4132
|
const port2 = Number(portMatch[1]);
|
|
3574
4133
|
resolveChildReady({ port: port2, pid: child.pid });
|
|
3575
|
-
|
|
4134
|
+
resolve2();
|
|
3576
4135
|
}
|
|
3577
4136
|
}
|
|
3578
4137
|
};
|
|
@@ -3602,7 +4161,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3602
4161
|
}
|
|
3603
4162
|
const moduleToRun = devShimModule || modulePath;
|
|
3604
4163
|
const argv = ["-u", "-m", moduleToRun];
|
|
3605
|
-
(0,
|
|
4164
|
+
(0, import_build_utils6.debug)(`Starting Flask dev server: ${pythonCmd} ${argv.join(" ")}`);
|
|
3606
4165
|
const child = (0, import_child_process.spawn)(pythonCmd, argv, {
|
|
3607
4166
|
cwd: workPath,
|
|
3608
4167
|
env,
|
|
@@ -3649,7 +4208,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3649
4208
|
child.stderr?.removeListener("data", onDetect);
|
|
3650
4209
|
const port2 = Number(portMatch[1]);
|
|
3651
4210
|
resolveChildReady({ port: port2, pid: child.pid });
|
|
3652
|
-
|
|
4211
|
+
resolve2();
|
|
3653
4212
|
}
|
|
3654
4213
|
}
|
|
3655
4214
|
};
|
|
@@ -3692,44 +4251,34 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3692
4251
|
var readFile = (0, import_util.promisify)(import_fs5.default.readFile);
|
|
3693
4252
|
var writeFile = (0, import_util.promisify)(import_fs5.default.writeFile);
|
|
3694
4253
|
var version = 3;
|
|
3695
|
-
function findDir({
|
|
3696
|
-
file,
|
|
3697
|
-
entryDirectory,
|
|
3698
|
-
workPath,
|
|
3699
|
-
fsFiles
|
|
3700
|
-
}) {
|
|
3701
|
-
if (fsFiles[(0, import_path5.join)(entryDirectory, file)]) {
|
|
3702
|
-
return (0, import_path5.join)(workPath, entryDirectory);
|
|
3703
|
-
}
|
|
3704
|
-
if (fsFiles[file]) {
|
|
3705
|
-
return workPath;
|
|
3706
|
-
}
|
|
3707
|
-
return null;
|
|
3708
|
-
}
|
|
3709
4254
|
async function downloadFilesInWorkPath({
|
|
3710
4255
|
entrypoint,
|
|
3711
4256
|
workPath,
|
|
3712
4257
|
files,
|
|
3713
4258
|
meta = {}
|
|
3714
4259
|
}) {
|
|
3715
|
-
(0,
|
|
3716
|
-
let downloadedFiles = await (0,
|
|
4260
|
+
(0, import_build_utils7.debug)("Downloading user files...");
|
|
4261
|
+
let downloadedFiles = await (0, import_build_utils7.download)(files, workPath, meta);
|
|
3717
4262
|
if (meta.isDev) {
|
|
3718
4263
|
const { devCacheDir = (0, import_path5.join)(workPath, ".now", "cache") } = meta;
|
|
3719
4264
|
const destCache = (0, import_path5.join)(devCacheDir, (0, import_path5.basename)(entrypoint, ".py"));
|
|
3720
|
-
await (0,
|
|
3721
|
-
downloadedFiles = await (0,
|
|
4265
|
+
await (0, import_build_utils7.download)(downloadedFiles, destCache);
|
|
4266
|
+
downloadedFiles = await (0, import_build_utils7.glob)("**", destCache);
|
|
3722
4267
|
workPath = destCache;
|
|
3723
4268
|
}
|
|
3724
4269
|
return workPath;
|
|
3725
4270
|
}
|
|
3726
4271
|
var build = async ({
|
|
3727
4272
|
workPath,
|
|
4273
|
+
repoRootPath,
|
|
3728
4274
|
files: originalFiles,
|
|
3729
4275
|
entrypoint,
|
|
3730
4276
|
meta = {},
|
|
3731
4277
|
config
|
|
3732
4278
|
}) => {
|
|
4279
|
+
const framework = config?.framework;
|
|
4280
|
+
let spawnEnv;
|
|
4281
|
+
let projectInstallCommand;
|
|
3733
4282
|
workPath = await downloadFilesInWorkPath({
|
|
3734
4283
|
workPath,
|
|
3735
4284
|
files: originalFiles,
|
|
@@ -3745,73 +4294,96 @@ var build = async ({
|
|
|
3745
4294
|
console.log('Failed to create "setup.cfg" file');
|
|
3746
4295
|
throw err;
|
|
3747
4296
|
}
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
4297
|
+
if (framework === "fastapi" || framework === "flask") {
|
|
4298
|
+
const {
|
|
4299
|
+
cliType,
|
|
4300
|
+
lockfileVersion,
|
|
4301
|
+
packageJsonPackageManager,
|
|
4302
|
+
turboSupportsCorepackHome
|
|
4303
|
+
} = await (0, import_build_utils7.scanParentDirs)(workPath, true);
|
|
4304
|
+
spawnEnv = (0, import_build_utils7.getEnvForPackageManager)({
|
|
4305
|
+
cliType,
|
|
4306
|
+
lockfileVersion,
|
|
4307
|
+
packageJsonPackageManager,
|
|
4308
|
+
env: process.env,
|
|
4309
|
+
turboSupportsCorepackHome,
|
|
4310
|
+
projectCreatedAt: config?.projectSettings?.createdAt
|
|
4311
|
+
});
|
|
4312
|
+
const installCommand = config?.projectSettings?.installCommand;
|
|
4313
|
+
if (typeof installCommand === "string") {
|
|
4314
|
+
const trimmed = installCommand.trim();
|
|
4315
|
+
if (trimmed) {
|
|
4316
|
+
projectInstallCommand = trimmed;
|
|
4317
|
+
} else {
|
|
4318
|
+
console.log('Skipping "install" command...');
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
|
|
4322
|
+
config?.buildCommand;
|
|
4323
|
+
if (projectBuildCommand) {
|
|
4324
|
+
console.log(`Running "${projectBuildCommand}"`);
|
|
4325
|
+
await (0, import_build_utils7.execCommand)(projectBuildCommand, {
|
|
4326
|
+
env: spawnEnv,
|
|
4327
|
+
cwd: workPath
|
|
3761
4328
|
});
|
|
4329
|
+
} else {
|
|
4330
|
+
await runPyprojectScript(
|
|
4331
|
+
workPath,
|
|
4332
|
+
["vercel-build", "now-build", "build"],
|
|
4333
|
+
spawnEnv
|
|
4334
|
+
);
|
|
3762
4335
|
}
|
|
3763
|
-
}
|
|
3764
|
-
|
|
4336
|
+
}
|
|
4337
|
+
let fsFiles = await (0, import_build_utils7.glob)("**", workPath);
|
|
4338
|
+
if ((framework === "fastapi" || framework === "flask") && (!fsFiles[entrypoint] || !entrypoint.endsWith(".py"))) {
|
|
4339
|
+
const detected = await detectPythonEntrypoint(
|
|
4340
|
+
config.framework,
|
|
4341
|
+
workPath,
|
|
4342
|
+
entrypoint
|
|
4343
|
+
);
|
|
3765
4344
|
if (detected) {
|
|
3766
|
-
(0,
|
|
4345
|
+
(0, import_build_utils7.debug)(
|
|
3767
4346
|
`Resolved Python entrypoint to "${detected}" (configured "${entrypoint}" not found).`
|
|
3768
4347
|
);
|
|
3769
4348
|
entrypoint = detected;
|
|
3770
4349
|
} else {
|
|
3771
|
-
const searchedList = FLASK_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
3772
|
-
throw new
|
|
3773
|
-
code:
|
|
3774
|
-
message: `No
|
|
4350
|
+
const searchedList = framework === "fastapi" ? FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ") : FLASK_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
4351
|
+
throw new import_build_utils7.NowBuildError({
|
|
4352
|
+
code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
|
|
4353
|
+
message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
|
|
4354
|
+
link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
|
|
4355
|
+
action: "Learn More"
|
|
3775
4356
|
});
|
|
3776
4357
|
}
|
|
3777
4358
|
}
|
|
3778
4359
|
const entryDirectory = (0, import_path5.dirname)(entrypoint);
|
|
3779
|
-
const
|
|
3780
|
-
|
|
3781
|
-
const uvLockDir = findDir({
|
|
3782
|
-
file: "uv.lock",
|
|
4360
|
+
const pyprojectDir = findDir({
|
|
4361
|
+
file: "pyproject.toml",
|
|
3783
4362
|
entryDirectory,
|
|
3784
4363
|
workPath,
|
|
3785
4364
|
fsFiles
|
|
3786
4365
|
});
|
|
3787
|
-
const
|
|
3788
|
-
file: "
|
|
4366
|
+
const pipfileLockDir = findDir({
|
|
4367
|
+
file: "Pipfile.lock",
|
|
3789
4368
|
entryDirectory,
|
|
3790
4369
|
workPath,
|
|
3791
4370
|
fsFiles
|
|
3792
4371
|
});
|
|
3793
|
-
const pipfileLockDir = fsFiles[(0, import_path5.join)(entryDirectory, "Pipfile.lock")] ? (0, import_path5.join)(workPath, entryDirectory) : fsFiles["Pipfile.lock"] ? workPath : null;
|
|
3794
|
-
const pipfileDir = fsFiles[(0, import_path5.join)(entryDirectory, "Pipfile")] ? (0, import_path5.join)(workPath, entryDirectory) : fsFiles["Pipfile"] ? workPath : null;
|
|
3795
4372
|
let declaredPythonVersion;
|
|
3796
4373
|
if (pyprojectDir) {
|
|
3797
4374
|
let requiresPython;
|
|
3798
4375
|
try {
|
|
3799
|
-
const pyproject = await (0,
|
|
4376
|
+
const pyproject = await (0, import_build_utils8.readConfigFile)((0, import_path5.join)(pyprojectDir, "pyproject.toml"));
|
|
3800
4377
|
requiresPython = pyproject?.project?.["requires-python"];
|
|
3801
4378
|
} catch (err) {
|
|
3802
|
-
(0,
|
|
3803
|
-
}
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
);
|
|
3811
|
-
} else if (requiresPython) {
|
|
3812
|
-
(0, import_build_utils5.debug)(
|
|
3813
|
-
`Could not parse Python version from pyproject.toml requires-python: "${requiresPython}"`
|
|
3814
|
-
);
|
|
4379
|
+
(0, import_build_utils7.debug)("Failed to parse pyproject.toml", err);
|
|
4380
|
+
}
|
|
4381
|
+
if (typeof requiresPython === "string" && requiresPython.trim()) {
|
|
4382
|
+
declaredPythonVersion = {
|
|
4383
|
+
version: requiresPython.trim(),
|
|
4384
|
+
source: "pyproject.toml"
|
|
4385
|
+
};
|
|
4386
|
+
(0, import_build_utils7.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
|
|
3815
4387
|
}
|
|
3816
4388
|
} else if (pipfileLockDir) {
|
|
3817
4389
|
let lock = {};
|
|
@@ -3819,7 +4391,7 @@ var build = async ({
|
|
|
3819
4391
|
const json = await readFile((0, import_path5.join)(pipfileLockDir, "Pipfile.lock"), "utf8");
|
|
3820
4392
|
lock = JSON.parse(json);
|
|
3821
4393
|
} catch (err) {
|
|
3822
|
-
throw new
|
|
4394
|
+
throw new import_build_utils7.NowBuildError({
|
|
3823
4395
|
code: "INVALID_PIPFILE_LOCK",
|
|
3824
4396
|
message: "Unable to parse Pipfile.lock"
|
|
3825
4397
|
});
|
|
@@ -3827,167 +4399,84 @@ var build = async ({
|
|
|
3827
4399
|
const pyFromLock = lock?._meta?.requires?.python_version;
|
|
3828
4400
|
if (pyFromLock) {
|
|
3829
4401
|
declaredPythonVersion = { version: pyFromLock, source: "Pipfile.lock" };
|
|
3830
|
-
(0,
|
|
4402
|
+
(0, import_build_utils7.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
|
|
3831
4403
|
}
|
|
3832
4404
|
}
|
|
3833
4405
|
const pythonVersion = getSupportedPythonVersion({
|
|
3834
4406
|
isDev: meta.isDev,
|
|
3835
4407
|
declaredPythonVersion
|
|
3836
4408
|
});
|
|
3837
|
-
fsFiles = await (0,
|
|
3838
|
-
const
|
|
3839
|
-
|
|
3840
|
-
workPath,
|
|
3841
|
-
".vercel",
|
|
3842
|
-
"python",
|
|
3843
|
-
`py${pythonVersion.version}`,
|
|
3844
|
-
entryDirectory
|
|
3845
|
-
);
|
|
3846
|
-
try {
|
|
3847
|
-
await import_fs5.default.promises.mkdir(vendorBaseDir, { recursive: true });
|
|
3848
|
-
} catch (err) {
|
|
3849
|
-
console.log("Failed to create vendor cache directory");
|
|
3850
|
-
throw err;
|
|
3851
|
-
}
|
|
3852
|
-
let installationSource;
|
|
3853
|
-
if (uvLockDir && pyprojectDir) {
|
|
3854
|
-
installationSource = "uv.lock";
|
|
3855
|
-
} else if (pyprojectDir) {
|
|
3856
|
-
installationSource = "pyproject.toml";
|
|
3857
|
-
} else if (pipfileLockDir) {
|
|
3858
|
-
installationSource = "Pipfile.lock";
|
|
3859
|
-
} else if (pipfileDir) {
|
|
3860
|
-
installationSource = "Pipfile";
|
|
3861
|
-
} else if (fsFiles[requirementsTxt] || fsFiles["requirements.txt"]) {
|
|
3862
|
-
installationSource = "requirements.txt";
|
|
3863
|
-
}
|
|
3864
|
-
if (installationSource) {
|
|
3865
|
-
console.log(
|
|
3866
|
-
`Installing required dependencies from ${installationSource}...`
|
|
3867
|
-
);
|
|
3868
|
-
} else {
|
|
3869
|
-
console.log("Installing required dependencies...");
|
|
3870
|
-
}
|
|
3871
|
-
let uvPath = null;
|
|
3872
|
-
try {
|
|
3873
|
-
uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
|
|
3874
|
-
console.log(`Using uv at "${uvPath}"`);
|
|
3875
|
-
} catch (err) {
|
|
3876
|
-
if (uvLockDir || pyprojectDir && !hasReqLocal && !hasReqGlobal) {
|
|
3877
|
-
console.log("Failed to install uv");
|
|
3878
|
-
throw new Error(
|
|
3879
|
-
`uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
|
|
3880
|
-
);
|
|
3881
|
-
}
|
|
3882
|
-
(0, import_build_utils5.debug)("Failed to install uv", err);
|
|
3883
|
-
}
|
|
3884
|
-
await installRequirement({
|
|
4409
|
+
fsFiles = await (0, import_build_utils7.glob)("**", workPath);
|
|
4410
|
+
const venvPath = (0, import_path5.join)(workPath, ".vercel", "python", ".venv");
|
|
4411
|
+
await ensureVenv({
|
|
3885
4412
|
pythonPath: pythonVersion.pythonPath,
|
|
3886
|
-
|
|
3887
|
-
uvPath,
|
|
3888
|
-
dependency: "werkzeug",
|
|
3889
|
-
version: "1.0.1",
|
|
3890
|
-
workPath,
|
|
3891
|
-
targetDir: vendorBaseDir,
|
|
3892
|
-
meta
|
|
4413
|
+
venvPath
|
|
3893
4414
|
});
|
|
3894
|
-
|
|
3895
|
-
if (
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
4415
|
+
const hasCustomInstallCommand = (framework === "fastapi" || framework === "flask") && !!projectInstallCommand;
|
|
4416
|
+
if (hasCustomInstallCommand) {
|
|
4417
|
+
const baseEnv = spawnEnv || process.env;
|
|
4418
|
+
const pythonEnv = createVenvEnv(venvPath, baseEnv);
|
|
4419
|
+
pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
|
|
4420
|
+
const installCommand = projectInstallCommand;
|
|
4421
|
+
console.log(`Running "install" command: \`${installCommand}\`...`);
|
|
4422
|
+
await (0, import_build_utils7.execCommand)(installCommand, {
|
|
4423
|
+
env: pythonEnv,
|
|
4424
|
+
cwd: workPath
|
|
4425
|
+
});
|
|
4426
|
+
} else {
|
|
4427
|
+
let ranPyprojectInstall = false;
|
|
4428
|
+
if (framework === "fastapi" || framework === "flask") {
|
|
4429
|
+
const baseEnv = spawnEnv || process.env;
|
|
4430
|
+
const pythonEnv = createVenvEnv(venvPath, baseEnv);
|
|
4431
|
+
pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
|
|
4432
|
+
ranPyprojectInstall = await runPyprojectScript(
|
|
3906
4433
|
workPath,
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
} else {
|
|
3912
|
-
(0, import_build_utils5.debug)('Skipping uv export because "pyproject.toml" was not found');
|
|
3913
|
-
}
|
|
3914
|
-
} else if (pyprojectDir) {
|
|
3915
|
-
(0, import_build_utils5.debug)('Found "pyproject.toml"');
|
|
3916
|
-
if (hasReqLocal || hasReqGlobal) {
|
|
3917
|
-
console.log(
|
|
3918
|
-
"Detected both pyproject.toml and requirements.txt but no lockfile; using pyproject.toml"
|
|
4434
|
+
["vercel-install", "now-install", "install"],
|
|
4435
|
+
pythonEnv,
|
|
4436
|
+
/* useUserVirtualEnv */
|
|
4437
|
+
false
|
|
3919
4438
|
);
|
|
3920
4439
|
}
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
} else {
|
|
3939
|
-
const exportedReq = await exportRequirementsFromPipfile({
|
|
4440
|
+
if (!ranPyprojectInstall) {
|
|
4441
|
+
let uvPath;
|
|
4442
|
+
try {
|
|
4443
|
+
uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
|
|
4444
|
+
console.log(`Using uv at "${uvPath}"`);
|
|
4445
|
+
} catch (err) {
|
|
4446
|
+
console.log("Failed to install or locate uv");
|
|
4447
|
+
throw new Error(
|
|
4448
|
+
`uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
|
|
4449
|
+
);
|
|
4450
|
+
}
|
|
4451
|
+
const runtimeDependencies = framework === "flask" ? ["werkzeug>=1.0.1"] : ["werkzeug>=1.0.1", "uvicorn>=0.24"];
|
|
4452
|
+
const { projectDir } = await ensureUvProject({
|
|
4453
|
+
workPath,
|
|
4454
|
+
entryDirectory,
|
|
4455
|
+
fsFiles,
|
|
4456
|
+
repoRootPath,
|
|
3940
4457
|
pythonPath: pythonVersion.pythonPath,
|
|
3941
4458
|
pipPath: pythonVersion.pipPath,
|
|
3942
4459
|
uvPath,
|
|
3943
|
-
|
|
3944
|
-
meta
|
|
4460
|
+
venvPath,
|
|
4461
|
+
meta,
|
|
4462
|
+
runtimeDependencies
|
|
3945
4463
|
});
|
|
3946
|
-
await
|
|
3947
|
-
pythonPath: pythonVersion.pythonPath,
|
|
3948
|
-
pipPath: pythonVersion.pipPath,
|
|
4464
|
+
await runUvSync({
|
|
3949
4465
|
uvPath,
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
meta
|
|
4466
|
+
venvPath,
|
|
4467
|
+
projectDir,
|
|
4468
|
+
locked: true
|
|
3954
4469
|
});
|
|
3955
|
-
installedFromProjectFiles = true;
|
|
3956
4470
|
}
|
|
3957
4471
|
}
|
|
3958
|
-
if (!installedFromProjectFiles && fsFiles[requirementsTxt]) {
|
|
3959
|
-
(0, import_build_utils5.debug)('Found local "requirements.txt"');
|
|
3960
|
-
const requirementsTxtPath = fsFiles[requirementsTxt].fsPath;
|
|
3961
|
-
await installRequirementsFile({
|
|
3962
|
-
pythonPath: pythonVersion.pythonPath,
|
|
3963
|
-
pipPath: pythonVersion.pipPath,
|
|
3964
|
-
uvPath,
|
|
3965
|
-
filePath: requirementsTxtPath,
|
|
3966
|
-
workPath,
|
|
3967
|
-
targetDir: vendorBaseDir,
|
|
3968
|
-
meta
|
|
3969
|
-
});
|
|
3970
|
-
} else if (!installedFromProjectFiles && fsFiles["requirements.txt"]) {
|
|
3971
|
-
(0, import_build_utils5.debug)('Found global "requirements.txt"');
|
|
3972
|
-
const requirementsTxtPath = fsFiles["requirements.txt"].fsPath;
|
|
3973
|
-
await installRequirementsFile({
|
|
3974
|
-
pythonPath: pythonVersion.pythonPath,
|
|
3975
|
-
pipPath: pythonVersion.pipPath,
|
|
3976
|
-
uvPath,
|
|
3977
|
-
filePath: requirementsTxtPath,
|
|
3978
|
-
workPath,
|
|
3979
|
-
targetDir: vendorBaseDir,
|
|
3980
|
-
meta
|
|
3981
|
-
});
|
|
3982
|
-
}
|
|
3983
4472
|
const originalPyPath = (0, import_path5.join)(__dirname, "..", "vc_init.py");
|
|
3984
4473
|
const originalHandlerPyContents = await readFile(originalPyPath, "utf8");
|
|
3985
|
-
(0,
|
|
4474
|
+
(0, import_build_utils7.debug)("Entrypoint is", entrypoint);
|
|
3986
4475
|
const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
|
|
3987
4476
|
const vendorDir = resolveVendorDir();
|
|
3988
4477
|
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
3989
4478
|
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
3990
|
-
(0,
|
|
4479
|
+
(0, import_build_utils7.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
3991
4480
|
const handlerPyContents = originalHandlerPyContents.replace(/__VC_HANDLER_MODULE_NAME/g, moduleName).replace(/__VC_HANDLER_ENTRYPOINT/g, entrypointWithSuffix).replace(/__VC_HANDLER_VENDOR_DIR/g, vendorDir);
|
|
3992
4481
|
const predefinedExcludes = [
|
|
3993
4482
|
".git/**",
|
|
@@ -4000,7 +4489,12 @@ var build = async ({
|
|
|
4000
4489
|
"**/.venv/**",
|
|
4001
4490
|
"**/venv/**",
|
|
4002
4491
|
"**/__pycache__/**",
|
|
4003
|
-
"
|
|
4492
|
+
"**/.mypy_cache/**",
|
|
4493
|
+
"**/.ruff_cache/**",
|
|
4494
|
+
"**/public/**",
|
|
4495
|
+
"**/pnpm-lock.yaml",
|
|
4496
|
+
"**/yarn.lock",
|
|
4497
|
+
"**/package-lock.json"
|
|
4004
4498
|
];
|
|
4005
4499
|
const lambdaEnv = {};
|
|
4006
4500
|
lambdaEnv.PYTHONPATH = vendorDir;
|
|
@@ -4008,26 +4502,21 @@ var build = async ({
|
|
|
4008
4502
|
cwd: workPath,
|
|
4009
4503
|
ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
|
|
4010
4504
|
};
|
|
4011
|
-
const files = await (0,
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
}
|
|
4019
|
-
}
|
|
4020
|
-
} catch (err) {
|
|
4021
|
-
console.log("Failed to include cached vendor directory");
|
|
4022
|
-
throw err;
|
|
4505
|
+
const files = await (0, import_build_utils7.glob)("**", globOptions);
|
|
4506
|
+
const vendorFiles = await mirrorSitePackagesIntoVendor({
|
|
4507
|
+
venvPath,
|
|
4508
|
+
vendorDirName: vendorDir
|
|
4509
|
+
});
|
|
4510
|
+
for (const [p, f] of Object.entries(vendorFiles)) {
|
|
4511
|
+
files[p] = f;
|
|
4023
4512
|
}
|
|
4024
4513
|
const handlerPyFilename = "vc__handler__python";
|
|
4025
|
-
files[`${handlerPyFilename}.py`] = new
|
|
4514
|
+
files[`${handlerPyFilename}.py`] = new import_build_utils7.FileBlob({ data: handlerPyContents });
|
|
4026
4515
|
if (config.framework === "fasthtml") {
|
|
4027
4516
|
const { SESSKEY = "" } = process.env;
|
|
4028
|
-
files[".sesskey"] = new
|
|
4517
|
+
files[".sesskey"] = new import_build_utils7.FileBlob({ data: `"${SESSKEY}"` });
|
|
4029
4518
|
}
|
|
4030
|
-
const output = new
|
|
4519
|
+
const output = new import_build_utils7.Lambda({
|
|
4031
4520
|
files,
|
|
4032
4521
|
handler: `${handlerPyFilename}.vc_handler`,
|
|
4033
4522
|
runtime: pythonVersion.runtime,
|