@vercel/python 6.0.3 → 6.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +226 -61
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -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 === "<");
|
|
@@ -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) {
|
|
@@ -2751,7 +2751,7 @@ 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
2757
|
var import_execa = __toESM(require_execa());
|
|
@@ -3071,7 +3071,7 @@ async function exportRequirementsFromPipfile({
|
|
|
3071
3071
|
}
|
|
3072
3072
|
|
|
3073
3073
|
// src/index.ts
|
|
3074
|
-
var
|
|
3074
|
+
var import_build_utils8 = require("@vercel/build-utils");
|
|
3075
3075
|
|
|
3076
3076
|
// src/version.ts
|
|
3077
3077
|
var import_build_utils2 = require("@vercel/build-utils");
|
|
@@ -3133,6 +3133,81 @@ function getLatestPythonVersion({
|
|
|
3133
3133
|
}
|
|
3134
3134
|
return selection;
|
|
3135
3135
|
}
|
|
3136
|
+
function parseVersionTuple(input) {
|
|
3137
|
+
const cleaned = input.trim().replace(/\s+/g, "");
|
|
3138
|
+
const m = cleaned.match(/^(\d+)(?:\.(\d+))?/);
|
|
3139
|
+
if (!m)
|
|
3140
|
+
return null;
|
|
3141
|
+
const major = Number(m[1]);
|
|
3142
|
+
const minor = m[2] !== void 0 ? Number(m[2]) : 0;
|
|
3143
|
+
if (Number.isNaN(major) || Number.isNaN(minor))
|
|
3144
|
+
return null;
|
|
3145
|
+
return [major, minor];
|
|
3146
|
+
}
|
|
3147
|
+
function compareTuples(a, b) {
|
|
3148
|
+
if (a[0] !== b[0])
|
|
3149
|
+
return a[0] - b[0];
|
|
3150
|
+
return a[1] - b[1];
|
|
3151
|
+
}
|
|
3152
|
+
function parseSpecifier(spec) {
|
|
3153
|
+
const s = spec.trim();
|
|
3154
|
+
const m = s.match(/^(<=|>=|==|!=|~=|<|>)\s*([0-9]+(?:\.[0-9]+)?)(?:\.\*)?$/) || // Bare version like "3.11" -> implied ==
|
|
3155
|
+
s.match(/^()([0-9]+(?:\.[0-9]+)?)(?:\.\*)?$/);
|
|
3156
|
+
if (!m)
|
|
3157
|
+
return null;
|
|
3158
|
+
const op = m[1] || "==";
|
|
3159
|
+
const vt = parseVersionTuple(m[2]);
|
|
3160
|
+
if (!vt)
|
|
3161
|
+
return null;
|
|
3162
|
+
return { op, ver: vt };
|
|
3163
|
+
}
|
|
3164
|
+
function satisfies(candidate, spec) {
|
|
3165
|
+
const cmp = compareTuples(candidate, spec.ver);
|
|
3166
|
+
switch (spec.op) {
|
|
3167
|
+
case "==":
|
|
3168
|
+
return cmp === 0;
|
|
3169
|
+
case "!=":
|
|
3170
|
+
return cmp !== 0;
|
|
3171
|
+
case "<":
|
|
3172
|
+
return cmp < 0;
|
|
3173
|
+
case "<=":
|
|
3174
|
+
return cmp <= 0;
|
|
3175
|
+
case ">":
|
|
3176
|
+
return cmp > 0;
|
|
3177
|
+
case ">=":
|
|
3178
|
+
return cmp >= 0;
|
|
3179
|
+
case "~=": {
|
|
3180
|
+
const lowerOk = cmp >= 0;
|
|
3181
|
+
const upper = [spec.ver[0], spec.ver[1] + 1];
|
|
3182
|
+
return lowerOk && compareTuples(candidate, upper) < 0;
|
|
3183
|
+
}
|
|
3184
|
+
default:
|
|
3185
|
+
return false;
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
function selectFromRequiresPython(expr) {
|
|
3189
|
+
const raw = expr.trim();
|
|
3190
|
+
if (!raw)
|
|
3191
|
+
return void 0;
|
|
3192
|
+
const parts = raw.split(",").map((p) => p.trim()).filter(Boolean);
|
|
3193
|
+
const specifiers = [];
|
|
3194
|
+
for (const p of parts) {
|
|
3195
|
+
const sp = parseSpecifier(p);
|
|
3196
|
+
if (sp)
|
|
3197
|
+
specifiers.push(sp);
|
|
3198
|
+
}
|
|
3199
|
+
if (specifiers.length === 0) {
|
|
3200
|
+
return allOptions.find((o) => o.version === raw);
|
|
3201
|
+
}
|
|
3202
|
+
const matches = allOptions.filter((opt) => {
|
|
3203
|
+
const vt = parseVersionTuple(opt.version);
|
|
3204
|
+
return specifiers.every((sp) => satisfies(vt, sp));
|
|
3205
|
+
});
|
|
3206
|
+
if (matches.length === 0)
|
|
3207
|
+
return void 0;
|
|
3208
|
+
const installedMatch = matches.find(isInstalled2);
|
|
3209
|
+
return installedMatch ?? matches[0];
|
|
3210
|
+
}
|
|
3136
3211
|
function getSupportedPythonVersion({
|
|
3137
3212
|
isDev,
|
|
3138
3213
|
declaredPythonVersion
|
|
@@ -3143,7 +3218,12 @@ function getSupportedPythonVersion({
|
|
|
3143
3218
|
let selection = getLatestPythonVersion({ isDev: false });
|
|
3144
3219
|
if (declaredPythonVersion) {
|
|
3145
3220
|
const { version: version2, source } = declaredPythonVersion;
|
|
3146
|
-
|
|
3221
|
+
let requested;
|
|
3222
|
+
if (source === "pyproject.toml") {
|
|
3223
|
+
requested = selectFromRequiresPython(version2);
|
|
3224
|
+
} else {
|
|
3225
|
+
requested = allOptions.find((o) => o.version === version2);
|
|
3226
|
+
}
|
|
3147
3227
|
if (requested) {
|
|
3148
3228
|
if (isDiscontinued(requested)) {
|
|
3149
3229
|
throw new import_build_utils2.NowBuildError({
|
|
@@ -3204,7 +3284,7 @@ function isInstalled2({ pipPath, pythonPath }) {
|
|
|
3204
3284
|
var import_child_process = require("child_process");
|
|
3205
3285
|
var import_fs4 = require("fs");
|
|
3206
3286
|
var import_path4 = require("path");
|
|
3207
|
-
var
|
|
3287
|
+
var import_build_utils6 = require("@vercel/build-utils");
|
|
3208
3288
|
|
|
3209
3289
|
// src/entrypoint.ts
|
|
3210
3290
|
var import_fs2 = __toESM(require("fs"));
|
|
@@ -3334,6 +3414,8 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint)
|
|
|
3334
3414
|
// src/utils.ts
|
|
3335
3415
|
var import_fs3 = __toESM(require("fs"));
|
|
3336
3416
|
var import_path3 = require("path");
|
|
3417
|
+
var import_execa2 = __toESM(require_execa());
|
|
3418
|
+
var import_build_utils5 = require("@vercel/build-utils");
|
|
3337
3419
|
var isInVirtualEnv = () => {
|
|
3338
3420
|
return process.env.VIRTUAL_ENV;
|
|
3339
3421
|
};
|
|
@@ -3354,6 +3436,51 @@ function useVirtualEnv(workPath, env, systemPython) {
|
|
|
3354
3436
|
}
|
|
3355
3437
|
return { pythonCmd };
|
|
3356
3438
|
}
|
|
3439
|
+
async function runPyprojectScript(workPath, scriptNames, env) {
|
|
3440
|
+
const pyprojectPath = (0, import_path3.join)(workPath, "pyproject.toml");
|
|
3441
|
+
if (!import_fs3.default.existsSync(pyprojectPath))
|
|
3442
|
+
return false;
|
|
3443
|
+
let pyproject = null;
|
|
3444
|
+
try {
|
|
3445
|
+
pyproject = await (0, import_build_utils5.readConfigFile)(pyprojectPath);
|
|
3446
|
+
} catch {
|
|
3447
|
+
console.error("Failed to parse pyproject.toml");
|
|
3448
|
+
return false;
|
|
3449
|
+
}
|
|
3450
|
+
const scripts = pyproject?.tool?.vercel?.scripts || {};
|
|
3451
|
+
const candidates = typeof scriptNames === "string" ? [scriptNames] : Array.from(scriptNames);
|
|
3452
|
+
const scriptToRun = candidates.find((name) => Boolean(scripts[name]));
|
|
3453
|
+
if (!scriptToRun)
|
|
3454
|
+
return false;
|
|
3455
|
+
const systemPython = process.platform === "win32" ? "python" : "python3";
|
|
3456
|
+
const finalEnv = { ...process.env, ...env };
|
|
3457
|
+
const { pythonCmd } = useVirtualEnv(workPath, finalEnv, systemPython);
|
|
3458
|
+
const uvPath = await getUvBinaryOrInstall(pythonCmd);
|
|
3459
|
+
const scriptCommand = scripts[scriptToRun];
|
|
3460
|
+
if (typeof scriptCommand === "string" && scriptCommand.trim()) {
|
|
3461
|
+
const uvDir = (0, import_path3.dirname)(uvPath);
|
|
3462
|
+
finalEnv.PATH = `${uvDir}${import_path3.delimiter}${finalEnv.PATH || ""}`;
|
|
3463
|
+
if (/^\s*uv(\s|$)/i.test(scriptCommand)) {
|
|
3464
|
+
console.log(`Executing: ${scriptCommand}`);
|
|
3465
|
+
await (0, import_build_utils5.execCommand)(scriptCommand, {
|
|
3466
|
+
cwd: workPath,
|
|
3467
|
+
env: finalEnv
|
|
3468
|
+
});
|
|
3469
|
+
return true;
|
|
3470
|
+
}
|
|
3471
|
+
const args = process.platform === "win32" ? ["run", "cmd", "/d", "/s", "/c", scriptCommand] : ["run", "sh", "-lc", scriptCommand];
|
|
3472
|
+
console.log(
|
|
3473
|
+
`Executing: ${uvPath} ${args.map((a) => /\s/.test(a) ? `"${a.replace(/"/g, '\\"')}"` : a).join(" ")}`
|
|
3474
|
+
);
|
|
3475
|
+
await (0, import_execa2.default)(uvPath, args, {
|
|
3476
|
+
cwd: workPath,
|
|
3477
|
+
stdio: "inherit",
|
|
3478
|
+
env: finalEnv
|
|
3479
|
+
});
|
|
3480
|
+
return true;
|
|
3481
|
+
}
|
|
3482
|
+
return false;
|
|
3483
|
+
}
|
|
3357
3484
|
|
|
3358
3485
|
// src/start-dev-server.ts
|
|
3359
3486
|
function silenceNodeWarnings() {
|
|
@@ -3398,12 +3525,12 @@ function installGlobalCleanupHandlers() {
|
|
|
3398
3525
|
try {
|
|
3399
3526
|
process.kill(info.pid, "SIGTERM");
|
|
3400
3527
|
} catch (err) {
|
|
3401
|
-
(0,
|
|
3528
|
+
(0, import_build_utils6.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
|
|
3402
3529
|
}
|
|
3403
3530
|
try {
|
|
3404
3531
|
process.kill(info.pid, "SIGKILL");
|
|
3405
3532
|
} catch (err) {
|
|
3406
|
-
(0,
|
|
3533
|
+
(0, import_build_utils6.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
|
|
3407
3534
|
}
|
|
3408
3535
|
PERSISTENT_SERVERS.delete(key);
|
|
3409
3536
|
}
|
|
@@ -3411,7 +3538,7 @@ function installGlobalCleanupHandlers() {
|
|
|
3411
3538
|
try {
|
|
3412
3539
|
restoreWarnings();
|
|
3413
3540
|
} catch (err) {
|
|
3414
|
-
(0,
|
|
3541
|
+
(0, import_build_utils6.debug)(`Error restoring warnings: ${err}`);
|
|
3415
3542
|
}
|
|
3416
3543
|
restoreWarnings = null;
|
|
3417
3544
|
}
|
|
@@ -3437,10 +3564,10 @@ function createDevAsgiShim(workPath, modulePath) {
|
|
|
3437
3564
|
const template = (0, import_fs4.readFileSync)(templatePath, "utf8");
|
|
3438
3565
|
const shimSource = template.replace(/__VC_DEV_MODULE_PATH__/g, modulePath);
|
|
3439
3566
|
(0, import_fs4.writeFileSync)(shimPath, shimSource, "utf8");
|
|
3440
|
-
(0,
|
|
3567
|
+
(0, import_build_utils6.debug)(`Prepared Python dev static shim at ${shimPath}`);
|
|
3441
3568
|
return ASGI_SHIM_MODULE;
|
|
3442
3569
|
} catch (err) {
|
|
3443
|
-
(0,
|
|
3570
|
+
(0, import_build_utils6.debug)(`Failed to prepare dev static shim: ${err?.message || err}`);
|
|
3444
3571
|
return null;
|
|
3445
3572
|
}
|
|
3446
3573
|
}
|
|
@@ -3453,10 +3580,10 @@ function createDevWsgiShim(workPath, modulePath) {
|
|
|
3453
3580
|
const template = (0, import_fs4.readFileSync)(templatePath, "utf8");
|
|
3454
3581
|
const shimSource = template.replace(/__VC_DEV_MODULE_PATH__/g, modulePath);
|
|
3455
3582
|
(0, import_fs4.writeFileSync)(shimPath, shimSource, "utf8");
|
|
3456
|
-
(0,
|
|
3583
|
+
(0, import_build_utils6.debug)(`Prepared Python dev WSGI shim at ${shimPath}`);
|
|
3457
3584
|
return WSGI_SHIM_MODULE;
|
|
3458
3585
|
} catch (err) {
|
|
3459
|
-
(0,
|
|
3586
|
+
(0, import_build_utils6.debug)(`Failed to prepare dev WSGI shim: ${err?.message || err}`);
|
|
3460
3587
|
return null;
|
|
3461
3588
|
}
|
|
3462
3589
|
}
|
|
@@ -3476,7 +3603,7 @@ var startDevServer = async (opts) => {
|
|
|
3476
3603
|
);
|
|
3477
3604
|
if (!entry) {
|
|
3478
3605
|
const searched = framework === "fastapi" ? FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ") : FLASK_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
3479
|
-
throw new
|
|
3606
|
+
throw new import_build_utils6.NowBuildError({
|
|
3480
3607
|
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
3481
3608
|
message: `No ${framework} entrypoint found. Define a valid application entrypoint in one of the following locations: ${searched} or add an 'app' script in pyproject.toml.`,
|
|
3482
3609
|
link: `https://vercel.com/docs/frameworks/backend/${framework?.toLowerCase()}#exporting-the-${framework?.toLowerCase()}-application`,
|
|
@@ -3526,7 +3653,7 @@ var startDevServer = async (opts) => {
|
|
|
3526
3653
|
let pythonCmd = systemPython;
|
|
3527
3654
|
const venv = isInVirtualEnv();
|
|
3528
3655
|
if (venv) {
|
|
3529
|
-
(0,
|
|
3656
|
+
(0, import_build_utils6.debug)(`Running in virtualenv at ${venv}`);
|
|
3530
3657
|
} else {
|
|
3531
3658
|
const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
|
|
3532
3659
|
workPath,
|
|
@@ -3535,9 +3662,9 @@ var startDevServer = async (opts) => {
|
|
|
3535
3662
|
);
|
|
3536
3663
|
pythonCmd = venvPythonCmd;
|
|
3537
3664
|
if (venvRoot) {
|
|
3538
|
-
(0,
|
|
3665
|
+
(0, import_build_utils6.debug)(`Using virtualenv at ${venvRoot}`);
|
|
3539
3666
|
} else {
|
|
3540
|
-
(0,
|
|
3667
|
+
(0, import_build_utils6.debug)("No virtualenv found");
|
|
3541
3668
|
try {
|
|
3542
3669
|
const yellow = "\x1B[33m";
|
|
3543
3670
|
const reset = "\x1B[0m";
|
|
@@ -3560,7 +3687,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3560
3687
|
}
|
|
3561
3688
|
const moduleToRun = devShimModule || modulePath;
|
|
3562
3689
|
const argv = ["-u", "-m", moduleToRun];
|
|
3563
|
-
(0,
|
|
3690
|
+
(0, import_build_utils6.debug)(`Starting ASGI dev server: ${pythonCmd} ${argv.join(" ")}`);
|
|
3564
3691
|
const child = (0, import_child_process.spawn)(pythonCmd, argv, {
|
|
3565
3692
|
cwd: workPath,
|
|
3566
3693
|
env,
|
|
@@ -3638,7 +3765,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
3638
3765
|
}
|
|
3639
3766
|
const moduleToRun = devShimModule || modulePath;
|
|
3640
3767
|
const argv = ["-u", "-m", moduleToRun];
|
|
3641
|
-
(0,
|
|
3768
|
+
(0, import_build_utils6.debug)(`Starting Flask dev server: ${pythonCmd} ${argv.join(" ")}`);
|
|
3642
3769
|
const child = (0, import_child_process.spawn)(pythonCmd, argv, {
|
|
3643
3770
|
cwd: workPath,
|
|
3644
3771
|
env,
|
|
@@ -3748,13 +3875,13 @@ async function downloadFilesInWorkPath({
|
|
|
3748
3875
|
files,
|
|
3749
3876
|
meta = {}
|
|
3750
3877
|
}) {
|
|
3751
|
-
(0,
|
|
3752
|
-
let downloadedFiles = await (0,
|
|
3878
|
+
(0, import_build_utils7.debug)("Downloading user files...");
|
|
3879
|
+
let downloadedFiles = await (0, import_build_utils7.download)(files, workPath, meta);
|
|
3753
3880
|
if (meta.isDev) {
|
|
3754
3881
|
const { devCacheDir = (0, import_path5.join)(workPath, ".now", "cache") } = meta;
|
|
3755
3882
|
const destCache = (0, import_path5.join)(devCacheDir, (0, import_path5.basename)(entrypoint, ".py"));
|
|
3756
|
-
await (0,
|
|
3757
|
-
downloadedFiles = await (0,
|
|
3883
|
+
await (0, import_build_utils7.download)(downloadedFiles, destCache);
|
|
3884
|
+
downloadedFiles = await (0, import_build_utils7.glob)("**", destCache);
|
|
3758
3885
|
workPath = destCache;
|
|
3759
3886
|
}
|
|
3760
3887
|
return workPath;
|
|
@@ -3782,7 +3909,50 @@ var build = async ({
|
|
|
3782
3909
|
console.log('Failed to create "setup.cfg" file');
|
|
3783
3910
|
throw err;
|
|
3784
3911
|
}
|
|
3785
|
-
|
|
3912
|
+
if (framework === "fastapi" || framework === "flask") {
|
|
3913
|
+
const {
|
|
3914
|
+
cliType,
|
|
3915
|
+
lockfileVersion,
|
|
3916
|
+
packageJsonPackageManager,
|
|
3917
|
+
turboSupportsCorepackHome
|
|
3918
|
+
} = await (0, import_build_utils7.scanParentDirs)(workPath, true);
|
|
3919
|
+
const spawnEnv = (0, import_build_utils7.getEnvForPackageManager)({
|
|
3920
|
+
cliType,
|
|
3921
|
+
lockfileVersion,
|
|
3922
|
+
packageJsonPackageManager,
|
|
3923
|
+
env: process.env,
|
|
3924
|
+
turboSupportsCorepackHome,
|
|
3925
|
+
projectCreatedAt: config?.projectSettings?.createdAt
|
|
3926
|
+
});
|
|
3927
|
+
const installCommand = config?.projectSettings?.installCommand;
|
|
3928
|
+
if (typeof installCommand === "string") {
|
|
3929
|
+
if (installCommand.trim()) {
|
|
3930
|
+
console.log(`Running "install" command: \`${installCommand}\`...`);
|
|
3931
|
+
await (0, import_build_utils7.execCommand)(installCommand, {
|
|
3932
|
+
env: spawnEnv,
|
|
3933
|
+
cwd: workPath
|
|
3934
|
+
});
|
|
3935
|
+
} else {
|
|
3936
|
+
console.log('Skipping "install" command...');
|
|
3937
|
+
}
|
|
3938
|
+
}
|
|
3939
|
+
const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
|
|
3940
|
+
config?.buildCommand;
|
|
3941
|
+
if (projectBuildCommand) {
|
|
3942
|
+
console.log(`Running "${projectBuildCommand}"`);
|
|
3943
|
+
await (0, import_build_utils7.execCommand)(projectBuildCommand, {
|
|
3944
|
+
env: spawnEnv,
|
|
3945
|
+
cwd: workPath
|
|
3946
|
+
});
|
|
3947
|
+
} else {
|
|
3948
|
+
await runPyprojectScript(
|
|
3949
|
+
workPath,
|
|
3950
|
+
["vercel-build", "now-build", "build"],
|
|
3951
|
+
spawnEnv
|
|
3952
|
+
);
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
let fsFiles = await (0, import_build_utils7.glob)("**", workPath);
|
|
3786
3956
|
if ((framework === "fastapi" || framework === "flask") && (!fsFiles[entrypoint] || !entrypoint.endsWith(".py"))) {
|
|
3787
3957
|
const detected = await detectPythonEntrypoint(
|
|
3788
3958
|
config.framework,
|
|
@@ -3790,13 +3960,13 @@ var build = async ({
|
|
|
3790
3960
|
entrypoint
|
|
3791
3961
|
);
|
|
3792
3962
|
if (detected) {
|
|
3793
|
-
(0,
|
|
3963
|
+
(0, import_build_utils7.debug)(
|
|
3794
3964
|
`Resolved Python entrypoint to "${detected}" (configured "${entrypoint}" not found).`
|
|
3795
3965
|
);
|
|
3796
3966
|
entrypoint = detected;
|
|
3797
3967
|
} else {
|
|
3798
3968
|
const searchedList = framework === "fastapi" ? FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ") : FLASK_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
3799
|
-
throw new
|
|
3969
|
+
throw new import_build_utils7.NowBuildError({
|
|
3800
3970
|
code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
|
|
3801
3971
|
message: `No ${framework} entrypoint found. Define a valid application entrypoint in one of the following locations: ${searchedList} or add an 'app' script in pyproject.toml.`,
|
|
3802
3972
|
link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
|
|
@@ -3825,22 +3995,17 @@ var build = async ({
|
|
|
3825
3995
|
if (pyprojectDir) {
|
|
3826
3996
|
let requiresPython;
|
|
3827
3997
|
try {
|
|
3828
|
-
const pyproject = await (0,
|
|
3998
|
+
const pyproject = await (0, import_build_utils8.readConfigFile)((0, import_path5.join)(pyprojectDir, "pyproject.toml"));
|
|
3829
3999
|
requiresPython = pyproject?.project?.["requires-python"];
|
|
3830
4000
|
} catch (err) {
|
|
3831
|
-
(0,
|
|
3832
|
-
}
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
);
|
|
3840
|
-
} else if (requiresPython) {
|
|
3841
|
-
(0, import_build_utils6.debug)(
|
|
3842
|
-
`Could not parse Python version from pyproject.toml requires-python: "${requiresPython}"`
|
|
3843
|
-
);
|
|
4001
|
+
(0, import_build_utils7.debug)("Failed to parse pyproject.toml", err);
|
|
4002
|
+
}
|
|
4003
|
+
if (typeof requiresPython === "string" && requiresPython.trim()) {
|
|
4004
|
+
declaredPythonVersion = {
|
|
4005
|
+
version: requiresPython.trim(),
|
|
4006
|
+
source: "pyproject.toml"
|
|
4007
|
+
};
|
|
4008
|
+
(0, import_build_utils7.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
|
|
3844
4009
|
}
|
|
3845
4010
|
} else if (pipfileLockDir) {
|
|
3846
4011
|
let lock = {};
|
|
@@ -3848,7 +4013,7 @@ var build = async ({
|
|
|
3848
4013
|
const json = await readFile((0, import_path5.join)(pipfileLockDir, "Pipfile.lock"), "utf8");
|
|
3849
4014
|
lock = JSON.parse(json);
|
|
3850
4015
|
} catch (err) {
|
|
3851
|
-
throw new
|
|
4016
|
+
throw new import_build_utils7.NowBuildError({
|
|
3852
4017
|
code: "INVALID_PIPFILE_LOCK",
|
|
3853
4018
|
message: "Unable to parse Pipfile.lock"
|
|
3854
4019
|
});
|
|
@@ -3856,14 +4021,14 @@ var build = async ({
|
|
|
3856
4021
|
const pyFromLock = lock?._meta?.requires?.python_version;
|
|
3857
4022
|
if (pyFromLock) {
|
|
3858
4023
|
declaredPythonVersion = { version: pyFromLock, source: "Pipfile.lock" };
|
|
3859
|
-
(0,
|
|
4024
|
+
(0, import_build_utils7.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
|
|
3860
4025
|
}
|
|
3861
4026
|
}
|
|
3862
4027
|
const pythonVersion = getSupportedPythonVersion({
|
|
3863
4028
|
isDev: meta.isDev,
|
|
3864
4029
|
declaredPythonVersion
|
|
3865
4030
|
});
|
|
3866
|
-
fsFiles = await (0,
|
|
4031
|
+
fsFiles = await (0, import_build_utils7.glob)("**", workPath);
|
|
3867
4032
|
const requirementsTxt = (0, import_path5.join)(entryDirectory, "requirements.txt");
|
|
3868
4033
|
const vendorBaseDir = (0, import_path5.join)(
|
|
3869
4034
|
workPath,
|
|
@@ -3908,7 +4073,7 @@ var build = async ({
|
|
|
3908
4073
|
`uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
|
|
3909
4074
|
);
|
|
3910
4075
|
}
|
|
3911
|
-
(0,
|
|
4076
|
+
(0, import_build_utils7.debug)("Failed to install uv", err);
|
|
3912
4077
|
}
|
|
3913
4078
|
await installRequirement({
|
|
3914
4079
|
pythonPath: pythonVersion.pythonPath,
|
|
@@ -3934,7 +4099,7 @@ var build = async ({
|
|
|
3934
4099
|
}
|
|
3935
4100
|
let installedFromProjectFiles = false;
|
|
3936
4101
|
if (uvLockDir) {
|
|
3937
|
-
(0,
|
|
4102
|
+
(0, import_build_utils7.debug)('Found "uv.lock"');
|
|
3938
4103
|
if (pyprojectDir) {
|
|
3939
4104
|
const exportedReq = await exportRequirementsFromUv(pyprojectDir, uvPath, {
|
|
3940
4105
|
locked: true
|
|
@@ -3950,10 +4115,10 @@ var build = async ({
|
|
|
3950
4115
|
});
|
|
3951
4116
|
installedFromProjectFiles = true;
|
|
3952
4117
|
} else {
|
|
3953
|
-
(0,
|
|
4118
|
+
(0, import_build_utils7.debug)('Skipping uv export because "pyproject.toml" was not found');
|
|
3954
4119
|
}
|
|
3955
4120
|
} else if (pyprojectDir) {
|
|
3956
|
-
(0,
|
|
4121
|
+
(0, import_build_utils7.debug)('Found "pyproject.toml"');
|
|
3957
4122
|
if (hasReqLocal || hasReqGlobal) {
|
|
3958
4123
|
console.log(
|
|
3959
4124
|
"Detected both pyproject.toml and requirements.txt but no lockfile; using pyproject.toml"
|
|
@@ -3973,9 +4138,9 @@ var build = async ({
|
|
|
3973
4138
|
});
|
|
3974
4139
|
installedFromProjectFiles = true;
|
|
3975
4140
|
} else if (pipfileLockDir || pipfileDir) {
|
|
3976
|
-
(0,
|
|
4141
|
+
(0, import_build_utils7.debug)(`Found ${pipfileLockDir ? '"Pipfile.lock"' : '"Pipfile"'}`);
|
|
3977
4142
|
if (hasReqLocal || hasReqGlobal) {
|
|
3978
|
-
(0,
|
|
4143
|
+
(0, import_build_utils7.debug)('Skipping Pipfile export because "requirements.txt" exists');
|
|
3979
4144
|
} else {
|
|
3980
4145
|
const exportedReq = await exportRequirementsFromPipfile({
|
|
3981
4146
|
pythonPath: pythonVersion.pythonPath,
|
|
@@ -3997,7 +4162,7 @@ var build = async ({
|
|
|
3997
4162
|
}
|
|
3998
4163
|
}
|
|
3999
4164
|
if (!installedFromProjectFiles && fsFiles[requirementsTxt]) {
|
|
4000
|
-
(0,
|
|
4165
|
+
(0, import_build_utils7.debug)('Found local "requirements.txt"');
|
|
4001
4166
|
const requirementsTxtPath = fsFiles[requirementsTxt].fsPath;
|
|
4002
4167
|
await installRequirementsFile({
|
|
4003
4168
|
pythonPath: pythonVersion.pythonPath,
|
|
@@ -4009,7 +4174,7 @@ var build = async ({
|
|
|
4009
4174
|
meta
|
|
4010
4175
|
});
|
|
4011
4176
|
} else if (!installedFromProjectFiles && fsFiles["requirements.txt"]) {
|
|
4012
|
-
(0,
|
|
4177
|
+
(0, import_build_utils7.debug)('Found global "requirements.txt"');
|
|
4013
4178
|
const requirementsTxtPath = fsFiles["requirements.txt"].fsPath;
|
|
4014
4179
|
await installRequirementsFile({
|
|
4015
4180
|
pythonPath: pythonVersion.pythonPath,
|
|
@@ -4023,12 +4188,12 @@ var build = async ({
|
|
|
4023
4188
|
}
|
|
4024
4189
|
const originalPyPath = (0, import_path5.join)(__dirname, "..", "vc_init.py");
|
|
4025
4190
|
const originalHandlerPyContents = await readFile(originalPyPath, "utf8");
|
|
4026
|
-
(0,
|
|
4191
|
+
(0, import_build_utils7.debug)("Entrypoint is", entrypoint);
|
|
4027
4192
|
const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
|
|
4028
4193
|
const vendorDir = resolveVendorDir();
|
|
4029
4194
|
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
4030
4195
|
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
4031
|
-
(0,
|
|
4196
|
+
(0, import_build_utils7.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
4032
4197
|
const handlerPyContents = originalHandlerPyContents.replace(/__VC_HANDLER_MODULE_NAME/g, moduleName).replace(/__VC_HANDLER_ENTRYPOINT/g, entrypointWithSuffix).replace(/__VC_HANDLER_VENDOR_DIR/g, vendorDir);
|
|
4033
4198
|
const predefinedExcludes = [
|
|
4034
4199
|
".git/**",
|
|
@@ -4054,11 +4219,11 @@ var build = async ({
|
|
|
4054
4219
|
cwd: workPath,
|
|
4055
4220
|
ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
|
|
4056
4221
|
};
|
|
4057
|
-
const files = await (0,
|
|
4222
|
+
const files = await (0, import_build_utils7.glob)("**", globOptions);
|
|
4058
4223
|
try {
|
|
4059
4224
|
const cachedVendorAbs = (0, import_path5.join)(vendorBaseDir, resolveVendorDir());
|
|
4060
4225
|
if (import_fs5.default.existsSync(cachedVendorAbs)) {
|
|
4061
|
-
const vendorFiles = await (0,
|
|
4226
|
+
const vendorFiles = await (0, import_build_utils7.glob)("**", cachedVendorAbs, resolveVendorDir());
|
|
4062
4227
|
for (const [p, f] of Object.entries(vendorFiles)) {
|
|
4063
4228
|
files[p] = f;
|
|
4064
4229
|
}
|
|
@@ -4068,12 +4233,12 @@ var build = async ({
|
|
|
4068
4233
|
throw err;
|
|
4069
4234
|
}
|
|
4070
4235
|
const handlerPyFilename = "vc__handler__python";
|
|
4071
|
-
files[`${handlerPyFilename}.py`] = new
|
|
4236
|
+
files[`${handlerPyFilename}.py`] = new import_build_utils7.FileBlob({ data: handlerPyContents });
|
|
4072
4237
|
if (config.framework === "fasthtml") {
|
|
4073
4238
|
const { SESSKEY = "" } = process.env;
|
|
4074
|
-
files[".sesskey"] = new
|
|
4239
|
+
files[".sesskey"] = new import_build_utils7.FileBlob({ data: `"${SESSKEY}"` });
|
|
4075
4240
|
}
|
|
4076
|
-
const output = new
|
|
4241
|
+
const output = new import_build_utils7.Lambda({
|
|
4077
4242
|
files,
|
|
4078
4243
|
handler: `${handlerPyFilename}.vc_handler`,
|
|
4079
4244
|
runtime: pythonVersion.runtime,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.5",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@types/jest": "27.4.1",
|
|
22
22
|
"@types/node": "14.18.33",
|
|
23
23
|
"@types/which": "3.0.0",
|
|
24
|
-
"@vercel/build-utils": "13.0.
|
|
24
|
+
"@vercel/build-utils": "13.0.1",
|
|
25
25
|
"cross-env": "7.0.3",
|
|
26
26
|
"execa": "^1.0.0",
|
|
27
27
|
"fs-extra": "11.1.1",
|