@vercel/python 14.2.0 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +627 -528
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -7078,6 +7078,7 @@ var UvRunner = class {
|
|
|
7078
7078
|
frozen,
|
|
7079
7079
|
noBuild,
|
|
7080
7080
|
noInstallProject,
|
|
7081
|
+
onlyGroup,
|
|
7081
7082
|
pythonPlatform
|
|
7082
7083
|
} = options;
|
|
7083
7084
|
const args = ["sync", "--active", "--no-dev", "--link-mode", "hardlink"];
|
|
@@ -7092,6 +7093,9 @@ var UvRunner = class {
|
|
|
7092
7093
|
if (noInstallProject) {
|
|
7093
7094
|
args.push("--no-install-project");
|
|
7094
7095
|
}
|
|
7096
|
+
if (onlyGroup) {
|
|
7097
|
+
args.push("--only-group", onlyGroup);
|
|
7098
|
+
}
|
|
7095
7099
|
if (pythonPlatform) {
|
|
7096
7100
|
args.push("--python-platform", pythonPlatform);
|
|
7097
7101
|
}
|
|
@@ -13330,95 +13334,17 @@ async function installInjectedPackage({
|
|
|
13330
13334
|
]
|
|
13331
13335
|
});
|
|
13332
13336
|
}
|
|
13333
|
-
|
|
13337
|
+
async function setupPythonToolchain({
|
|
13338
|
+
builderSpan,
|
|
13334
13339
|
workPath,
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
meta
|
|
13339
|
-
|
|
13340
|
-
span: parentSpan,
|
|
13341
|
-
service,
|
|
13342
|
-
registerPreDeploy
|
|
13343
|
-
}) => {
|
|
13344
|
-
let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
13345
|
-
const isPyprojectEntrypoint = entrypoint !== void 0 && (0, import_path21.basename)(entrypoint) === "pyproject.toml";
|
|
13346
|
-
if (isPyprojectEntrypoint && entrypoint !== "pyproject.toml") {
|
|
13347
|
-
throw new import_build_utils24.NowBuildError({
|
|
13348
|
-
code: "PYTHON_INVALID_PYPROJECT_ENTRYPOINT",
|
|
13349
|
-
message: `A "pyproject.toml" entrypoint must sit at the service root. Set the service "root" to "${(0, import_path21.dirname)(entrypoint)}" and use entrypoint "pyproject.toml".`
|
|
13350
|
-
});
|
|
13351
|
-
}
|
|
13352
|
-
const builderSpan = parentSpan ?? new import_build_utils24.Span({ name: "vc.builder" });
|
|
13353
|
-
const framework = config?.framework;
|
|
13354
|
-
let subscriberDeclarations = [];
|
|
13355
|
-
let subscribers = [];
|
|
13356
|
-
let workflows = [];
|
|
13357
|
-
let legacyWorkersProject = false;
|
|
13358
|
-
let workflowMode = "workers";
|
|
13359
|
-
let spawnEnv;
|
|
13360
|
-
let projectInstallCommand;
|
|
13361
|
-
let hasCustomCommand = false;
|
|
13362
|
-
const target = getTargetPlatform(meta.isDev ?? false);
|
|
13363
|
-
(0, import_build_utils24.debug)(`workPath: ${workPath}`);
|
|
13364
|
-
workPath = await downloadFilesInWorkPath({
|
|
13365
|
-
workPath,
|
|
13366
|
-
files: originalFiles,
|
|
13367
|
-
entrypoint,
|
|
13368
|
-
meta
|
|
13369
|
-
});
|
|
13370
|
-
legacyWorkersProject = await isLegacyWorkersProject(workPath);
|
|
13371
|
-
if (isPyprojectEntrypoint || !service && (0, import_build_utils24.isPythonFramework)(framework)) {
|
|
13372
|
-
subscriberDeclarations = await getPyprojectSubscribers(workPath, {
|
|
13373
|
-
legacySchema: legacyWorkersProject
|
|
13374
|
-
});
|
|
13375
|
-
workflows = await getPyprojectWorkflows(workPath);
|
|
13376
|
-
}
|
|
13377
|
-
try {
|
|
13378
|
-
if (meta.isDev) {
|
|
13379
|
-
const setupCfg = (0, import_path21.join)(workPath, "setup.cfg");
|
|
13380
|
-
await writeFile(setupCfg, "[install]\nprefix=\n");
|
|
13381
|
-
}
|
|
13382
|
-
} catch (err) {
|
|
13383
|
-
console.log('Failed to create "setup.cfg" file');
|
|
13384
|
-
throw err;
|
|
13385
|
-
}
|
|
13386
|
-
let detected;
|
|
13387
|
-
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
13388
|
-
if (isPyprojectEntrypoint) {
|
|
13389
|
-
const declared = await getVercelToolsEntrypoint(workPath, repoRootPath);
|
|
13390
|
-
if (declared) {
|
|
13391
|
-
detected = { entrypoint: declared };
|
|
13392
|
-
} else if (subscriberDeclarations.length === 0 && workflows.length === 0) {
|
|
13393
|
-
throw new import_build_utils24.NowBuildError({
|
|
13394
|
-
code: "PYTHON_PYPROJECT_NOTHING_TO_BUILD",
|
|
13395
|
-
message: 'Entrypoint "pyproject.toml" declares nothing to build. Set "tool.vercel.entrypoint" for a web app and/or declare "[[tool.vercel.subscribers]]" or "[[tool.vercel.workflows]]" entries in pyproject.toml.'
|
|
13396
|
-
});
|
|
13397
|
-
}
|
|
13398
|
-
entrypoint = void 0;
|
|
13399
|
-
} else {
|
|
13400
|
-
detected = await detectPythonEntrypoint(
|
|
13401
|
-
config.framework,
|
|
13402
|
-
workPath,
|
|
13403
|
-
entrypoint ? {
|
|
13404
|
-
filePath: entrypoint,
|
|
13405
|
-
// For schedule-triggered jobs, the WSGI variable is always 'app' (created dynamically).
|
|
13406
|
-
// For other services, handlerFunction is used as the entrypoint variable name.
|
|
13407
|
-
varName: service && (0, import_build_utils24.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
|
|
13408
|
-
} : void 0,
|
|
13409
|
-
service,
|
|
13410
|
-
repoRootPath
|
|
13411
|
-
) ?? void 0;
|
|
13412
|
-
}
|
|
13413
|
-
if (detected?.error && detected?.baseDir === void 0) {
|
|
13414
|
-
throw detected?.error;
|
|
13415
|
-
}
|
|
13416
|
-
const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path21.dirname)(entrypoint) : ".");
|
|
13417
|
-
const entrypointAbsDir = (0, import_path21.join)(workPath, entryDirectory);
|
|
13418
|
-
const rootDir = repoRootPath ?? workPath;
|
|
13340
|
+
entrypointDir,
|
|
13341
|
+
rootDir,
|
|
13342
|
+
venvPath,
|
|
13343
|
+
meta
|
|
13344
|
+
}) {
|
|
13419
13345
|
const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
|
|
13420
13346
|
() => discoverPackage({
|
|
13421
|
-
entrypointDir
|
|
13347
|
+
entrypointDir,
|
|
13422
13348
|
rootDir
|
|
13423
13349
|
})
|
|
13424
13350
|
);
|
|
@@ -13455,7 +13381,6 @@ var build = async ({
|
|
|
13455
13381
|
}
|
|
13456
13382
|
const uvVersion = checkUvBinaryVersion(uv.getPath());
|
|
13457
13383
|
console.log(`Using ${uvVersion}`);
|
|
13458
|
-
const venvPath = service?.name ? (0, import_path21.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path21.join)(workPath, ".vercel", "python", ".venv");
|
|
13459
13384
|
const hasCachedVenv = import_fs20.default.existsSync((0, import_path21.join)(venvPath, "pyvenv.cfg"));
|
|
13460
13385
|
const hasCachedUv = import_fs20.default.existsSync(uvCacheDir);
|
|
13461
13386
|
const restoredCache = hasCachedVenv && hasCachedUv ? "both" : hasCachedVenv ? "venv" : hasCachedUv ? "uv" : "none";
|
|
@@ -13472,377 +13397,67 @@ var build = async ({
|
|
|
13472
13397
|
uvCacheDir
|
|
13473
13398
|
});
|
|
13474
13399
|
});
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
});
|
|
13492
|
-
const installCommand = config?.projectSettings?.installCommand;
|
|
13493
|
-
if (typeof installCommand === "string") {
|
|
13494
|
-
const trimmed = installCommand.trim();
|
|
13495
|
-
if (trimmed) {
|
|
13496
|
-
projectInstallCommand = trimmed;
|
|
13497
|
-
} else {
|
|
13498
|
-
console.log('Skipping "install" command...');
|
|
13499
|
-
}
|
|
13500
|
-
}
|
|
13501
|
-
}
|
|
13502
|
-
const baseEnv = spawnEnv || process.env;
|
|
13503
|
-
const pythonEnv = createVenvEnv(venvPath, baseEnv, uvCacheDir);
|
|
13504
|
-
pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
|
|
13505
|
-
let assumeDepsInstalled = false;
|
|
13506
|
-
let uvLockPath = null;
|
|
13507
|
-
let uvProjectDir = null;
|
|
13508
|
-
let projectName;
|
|
13509
|
-
let usedUvManagedInstall = false;
|
|
13510
|
-
await builderSpan.child(import_build_utils24.BUILDER_INSTALLER_STEP, {
|
|
13511
|
-
installCommand: projectInstallCommand || void 0,
|
|
13512
|
-
runtime: "python",
|
|
13513
|
-
"python.cache.restored": restoredCache
|
|
13514
|
-
}).trace(async () => {
|
|
13515
|
-
if (projectInstallCommand) {
|
|
13516
|
-
await import_fs20.default.promises.rm(venvPath, { recursive: true, force: true });
|
|
13517
|
-
await ensureVenv({
|
|
13518
|
-
pythonVersion,
|
|
13519
|
-
venvPath,
|
|
13520
|
-
uvPath: uv.getPath(),
|
|
13521
|
-
uvCacheDir,
|
|
13522
|
-
quiet: true
|
|
13523
|
-
});
|
|
13524
|
-
console.log(
|
|
13525
|
-
`Running "install" command: \`${projectInstallCommand}\`...`
|
|
13526
|
-
);
|
|
13527
|
-
await (0, import_build_utils24.execCommand)(projectInstallCommand, {
|
|
13528
|
-
env: pythonEnv,
|
|
13529
|
-
cwd: workPath
|
|
13530
|
-
});
|
|
13531
|
-
assumeDepsInstalled = true;
|
|
13532
|
-
hasCustomCommand = true;
|
|
13533
|
-
} else {
|
|
13534
|
-
const hasCustomScript = await runPyprojectScript(
|
|
13535
|
-
workPath,
|
|
13536
|
-
["vercel-install", "now-install", "install"],
|
|
13537
|
-
pythonEnv,
|
|
13538
|
-
/* useUserVirtualEnv */
|
|
13539
|
-
false
|
|
13540
|
-
);
|
|
13541
|
-
if (hasCustomScript) {
|
|
13542
|
-
assumeDepsInstalled = true;
|
|
13543
|
-
hasCustomCommand = true;
|
|
13544
|
-
}
|
|
13545
|
-
}
|
|
13546
|
-
if (!assumeDepsInstalled) {
|
|
13547
|
-
const lockCacheKey = service?.name ? `uv.lock.${service.name}` : "uv.lock";
|
|
13548
|
-
const cachedLockPath = (0, import_path21.join)(uvCacheDir, lockCacheKey);
|
|
13549
|
-
const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
|
|
13550
|
-
workPath,
|
|
13551
|
-
rootDir,
|
|
13552
|
-
venvPath,
|
|
13553
|
-
pythonPackage,
|
|
13554
|
-
pythonVersion: pythonVersionString(pythonVersion),
|
|
13555
|
-
uv,
|
|
13556
|
-
requireBinaryWheels: false,
|
|
13557
|
-
cachedLockPath
|
|
13558
|
-
});
|
|
13559
|
-
uvLockPath = lockPath;
|
|
13560
|
-
uvProjectDir = projectDir;
|
|
13561
|
-
projectName = pythonPackage?.manifest?.data?.project?.name;
|
|
13562
|
-
await uv.sync({
|
|
13563
|
-
venvPath,
|
|
13564
|
-
projectDir,
|
|
13565
|
-
frozen: lockFileProvidedByUser,
|
|
13566
|
-
locked: !lockFileProvidedByUser,
|
|
13567
|
-
pythonPlatform: target.uvPlatform
|
|
13568
|
-
});
|
|
13569
|
-
usedUvManagedInstall = true;
|
|
13570
|
-
if (lockPath && import_fs20.default.existsSync(lockPath)) {
|
|
13571
|
-
await import_fs20.default.promises.mkdir(uvCacheDir, { recursive: true });
|
|
13572
|
-
await import_fs20.default.promises.copyFile(lockPath, cachedLockPath);
|
|
13573
|
-
}
|
|
13574
|
-
}
|
|
13575
|
-
});
|
|
13576
|
-
if ((0, import_build_utils24.isPythonFramework)(framework)) {
|
|
13577
|
-
const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
|
|
13578
|
-
config?.buildCommand;
|
|
13579
|
-
await builderSpan.child(import_build_utils24.BUILDER_COMPILE_STEP, {
|
|
13580
|
-
buildCommand: projectBuildCommand || void 0
|
|
13581
|
-
}).trace(async () => {
|
|
13582
|
-
if (projectBuildCommand) {
|
|
13583
|
-
console.log(`Running "${projectBuildCommand}"`);
|
|
13584
|
-
await (0, import_build_utils24.execCommand)(projectBuildCommand, {
|
|
13585
|
-
env: pythonEnv,
|
|
13586
|
-
cwd: workPath
|
|
13587
|
-
});
|
|
13588
|
-
} else {
|
|
13589
|
-
await runPyprojectScript(
|
|
13590
|
-
workPath,
|
|
13591
|
-
["vercel-build", "now-build", "build"],
|
|
13592
|
-
pythonEnv
|
|
13593
|
-
);
|
|
13594
|
-
}
|
|
13595
|
-
});
|
|
13596
|
-
}
|
|
13597
|
-
const hookResult = await runFrameworkHook(framework, {
|
|
13598
|
-
pythonEnv,
|
|
13400
|
+
return { pythonPackage, pythonVersion, uv, uvCacheDir, restoredCache };
|
|
13401
|
+
}
|
|
13402
|
+
async function runUvManagedInstall({
|
|
13403
|
+
workPath,
|
|
13404
|
+
rootDir,
|
|
13405
|
+
venvPath,
|
|
13406
|
+
pythonPackage,
|
|
13407
|
+
pythonVersion,
|
|
13408
|
+
uv,
|
|
13409
|
+
uvCacheDir,
|
|
13410
|
+
lockCacheKey,
|
|
13411
|
+
pythonPlatform,
|
|
13412
|
+
extraSyncParams
|
|
13413
|
+
}) {
|
|
13414
|
+
const cachedLockPath = (0, import_path21.join)(uvCacheDir, lockCacheKey);
|
|
13415
|
+
const result = await ensureUvProject({
|
|
13599
13416
|
workPath,
|
|
13417
|
+
rootDir,
|
|
13600
13418
|
venvPath,
|
|
13601
|
-
entrypoint,
|
|
13602
|
-
detected,
|
|
13603
|
-
pyprojectData: pythonPackage.manifest?.data
|
|
13604
|
-
});
|
|
13605
|
-
const resolved = isPyprojectEntrypoint ? detected?.entrypoint : hookResult?.entrypoint ?? detected?.entrypoint;
|
|
13606
|
-
if (!resolved && detected?.error) {
|
|
13607
|
-
throw detected?.error;
|
|
13608
|
-
}
|
|
13609
|
-
entrypoint = resolved?.entrypoint;
|
|
13610
|
-
const isWorkersOnly = !entrypoint && isPyprojectEntrypoint && (subscriberDeclarations.length > 0 || workflows.length > 0);
|
|
13611
|
-
if (!entrypoint && !isWorkersOnly) {
|
|
13612
|
-
throw new import_build_utils24.NowBuildError({
|
|
13613
|
-
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
13614
|
-
message: "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
13615
|
-
});
|
|
13616
|
-
}
|
|
13617
|
-
const djangoStatic = hookResult?.djangoStatic ?? null;
|
|
13618
|
-
const fastapiStatic = hookResult?.fastapiStatic ?? null;
|
|
13619
|
-
const importSeeds = hookResult?.importSeeds ?? [];
|
|
13620
|
-
const cdnOutputDir = djangoStatic?.cdnOutputDir ?? fastapiStatic?.cdnOutputDir ?? null;
|
|
13621
|
-
const pipPlatformArgs = target.uvPlatform ? ["--python-platform", target.uvPlatform] : [];
|
|
13622
|
-
await installInjectedPackage({
|
|
13623
|
-
name: "vercel-runtime",
|
|
13624
|
-
requirement: `vercel-runtime==${VERCEL_RUNTIME_VERSION}`,
|
|
13625
|
-
envOverride: baseEnv.VERCEL_RUNTIME_PYTHON,
|
|
13626
|
-
allowLocalSource: true,
|
|
13627
|
-
uv,
|
|
13628
|
-
venvPath,
|
|
13629
|
-
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
13630
|
-
pipPlatformArgs
|
|
13631
|
-
});
|
|
13632
|
-
const queueAdapterBootstrap = await getQueueAdapterBootstrap({
|
|
13633
13419
|
pythonPackage,
|
|
13634
|
-
|
|
13635
|
-
|
|
13636
|
-
|
|
13420
|
+
pythonVersion: pythonVersionString(pythonVersion),
|
|
13421
|
+
uv,
|
|
13422
|
+
requireBinaryWheels: false,
|
|
13423
|
+
cachedLockPath
|
|
13637
13424
|
});
|
|
13638
|
-
const
|
|
13639
|
-
|
|
13640
|
-
await
|
|
13641
|
-
...injectedPackage,
|
|
13642
|
-
uv,
|
|
13425
|
+
const { projectDir, lockPath, lockFileProvidedByUser } = result;
|
|
13426
|
+
if (extraSyncParams !== void 0) {
|
|
13427
|
+
await uv.sync({
|
|
13643
13428
|
venvPath,
|
|
13644
|
-
projectDir
|
|
13645
|
-
|
|
13429
|
+
projectDir,
|
|
13430
|
+
frozen: lockFileProvidedByUser,
|
|
13431
|
+
locked: !lockFileProvidedByUser,
|
|
13432
|
+
pythonPlatform,
|
|
13433
|
+
...extraSyncParams
|
|
13646
13434
|
});
|
|
13647
13435
|
}
|
|
13648
|
-
|
|
13649
|
-
|
|
13650
|
-
|
|
13651
|
-
});
|
|
13652
|
-
if (localSdkSourcePaths.length > 0) {
|
|
13653
|
-
(0, import_build_utils24.debug)(
|
|
13654
|
-
`Installing vercel SDK override from ${baseEnv.VERCEL_SDK_PYTHON}: ` + localSdkSourcePaths.join(", ")
|
|
13655
|
-
);
|
|
13656
|
-
await uv.pip({
|
|
13657
|
-
venvPath,
|
|
13658
|
-
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
13659
|
-
args: [
|
|
13660
|
-
"install",
|
|
13661
|
-
"--link-mode",
|
|
13662
|
-
"copy",
|
|
13663
|
-
// Without --no-sources, uv resolves the checkout's workspace
|
|
13664
|
-
// dependencies as editable .pth installs pointing at the (build
|
|
13665
|
-
// only) checkout mount — invisible to bundling and dangling at
|
|
13666
|
-
// runtime. Explicit paths stay real installs; the remaining
|
|
13667
|
-
// workspace siblings resolve from PyPI.
|
|
13668
|
-
"--no-sources",
|
|
13669
|
-
...pipPlatformArgs,
|
|
13670
|
-
...localSdkSourcePaths
|
|
13671
|
-
]
|
|
13672
|
-
});
|
|
13673
|
-
}
|
|
13674
|
-
if (workflows.length > 0) {
|
|
13675
|
-
workflowMode = await resolveWorkflowServingMode({
|
|
13676
|
-
pythonPackage,
|
|
13677
|
-
uv,
|
|
13678
|
-
venvPath,
|
|
13679
|
-
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
13680
|
-
uvLockPath
|
|
13681
|
-
});
|
|
13682
|
-
if (workflowMode === "workers" && workflows.length > 1) {
|
|
13683
|
-
throw new import_build_utils24.NowBuildError({
|
|
13684
|
-
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
13685
|
-
message: `"tool.vercel.workflows" declares multiple entrypoints, which requires ${QUEUE_WORKFLOW_SDK_REQUIREMENT} with a distinct namespace per Workflows registry; the installed SDK serves every workflow on the shared __wkf_* topic`
|
|
13686
|
-
});
|
|
13687
|
-
}
|
|
13688
|
-
}
|
|
13689
|
-
const shouldInstallVercelWorkers = legacyWorkersProject || workflows.length > 0 && workflowMode === "workers";
|
|
13690
|
-
if (shouldInstallVercelWorkers) {
|
|
13691
|
-
await installInjectedPackage({
|
|
13692
|
-
name: "vercel-workers",
|
|
13693
|
-
requirement: `vercel-workers==${VERCEL_WORKERS_VERSION}`,
|
|
13694
|
-
envOverride: baseEnv.VERCEL_WORKERS_PYTHON,
|
|
13695
|
-
allowLocalSource: true,
|
|
13696
|
-
uv,
|
|
13697
|
-
venvPath,
|
|
13698
|
-
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
13699
|
-
pipPlatformArgs
|
|
13700
|
-
});
|
|
13701
|
-
}
|
|
13702
|
-
const quirksResult = await runQuirks({ venvPath, pythonEnv, workPath });
|
|
13703
|
-
if (quirksResult.buildEnv) {
|
|
13704
|
-
Object.assign(pythonEnv, quirksResult.buildEnv);
|
|
13705
|
-
}
|
|
13706
|
-
const queueIntegrations = queueAdapterBootstrap.integrations;
|
|
13707
|
-
const writeGeneratedQueueHandler = async (outputPath, declaration) => {
|
|
13708
|
-
const generatedPath = getGeneratedQueueHandlerPath(outputPath);
|
|
13709
|
-
await import_fs20.default.promises.mkdir((0, import_path21.dirname)((0, import_path21.join)(workPath, generatedPath)), {
|
|
13710
|
-
recursive: true
|
|
13711
|
-
});
|
|
13712
|
-
await import_fs20.default.promises.writeFile(
|
|
13713
|
-
(0, import_path21.join)(workPath, generatedPath),
|
|
13714
|
-
createQueueHandlerModule(declaration, queueIntegrations)
|
|
13715
|
-
);
|
|
13716
|
-
};
|
|
13717
|
-
if (subscriberDeclarations.length > 0 && !legacyWorkersProject) {
|
|
13718
|
-
subscribers = await resolveQueueSubscribers({
|
|
13719
|
-
declarations: subscriberDeclarations,
|
|
13720
|
-
uv,
|
|
13721
|
-
venvPath,
|
|
13722
|
-
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
13723
|
-
integrations: queueIntegrations
|
|
13724
|
-
});
|
|
13725
|
-
if (workflowMode === "queue") {
|
|
13726
|
-
for (const subscriber of subscribers) {
|
|
13727
|
-
if (!subscriber.topicPatterns) {
|
|
13728
|
-
subscriber.subscriptions = subscriber.subscriptions.filter(
|
|
13729
|
-
(subscription) => !isWorkflowQueueTopic(subscription.topic)
|
|
13730
|
-
);
|
|
13731
|
-
}
|
|
13732
|
-
}
|
|
13733
|
-
}
|
|
13734
|
-
for (const subscriber of subscribers) {
|
|
13735
|
-
await writeGeneratedQueueHandler(
|
|
13736
|
-
getSubscriberOutputPath(subscriber.name),
|
|
13737
|
-
subscriber
|
|
13738
|
-
);
|
|
13739
|
-
}
|
|
13740
|
-
}
|
|
13741
|
-
const workflowQueueSubscriptions = /* @__PURE__ */ new Map();
|
|
13742
|
-
if (workflows.length > 0 && workflowMode === "queue") {
|
|
13743
|
-
const resolved2 = await resolveQueueSubscribers({
|
|
13744
|
-
declarations: workflows.map((workflow) => ({
|
|
13745
|
-
name: workflow.name,
|
|
13746
|
-
entrypoint: workflow.entrypoint,
|
|
13747
|
-
moduleName: workflow.moduleName,
|
|
13748
|
-
variableName: workflow.variableName
|
|
13749
|
-
})),
|
|
13750
|
-
uv,
|
|
13751
|
-
venvPath,
|
|
13752
|
-
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
13753
|
-
kind: "workflow",
|
|
13754
|
-
integrations: queueIntegrations
|
|
13755
|
-
});
|
|
13756
|
-
for (let i = 0; i < resolved2.length; i++) {
|
|
13757
|
-
for (let j = i + 1; j < resolved2.length; j++) {
|
|
13758
|
-
const overlaps = resolved2[i].subscriptions.some(
|
|
13759
|
-
(left) => resolved2[j].subscriptions.some(
|
|
13760
|
-
(right) => queueTopicPatternsOverlap(left.topic, right.topic)
|
|
13761
|
-
)
|
|
13762
|
-
);
|
|
13763
|
-
if (overlaps) {
|
|
13764
|
-
throw new import_build_utils24.NowBuildError({
|
|
13765
|
-
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
13766
|
-
message: `workflow entrypoints "${resolved2[i].moduleName}:${resolved2[i].variableName}" and "${resolved2[j].moduleName}:${resolved2[j].variableName}" subscribe to overlapping queue topics; construct each vercel.workflow.Workflows registry with a distinct namespace`
|
|
13767
|
-
});
|
|
13768
|
-
}
|
|
13769
|
-
}
|
|
13770
|
-
}
|
|
13771
|
-
for (const workflow of resolved2) {
|
|
13772
|
-
workflowQueueSubscriptions.set(workflow.name, workflow.subscriptions);
|
|
13773
|
-
await writeGeneratedQueueHandler(
|
|
13774
|
-
getWorkflowOutputPath(workflow.name),
|
|
13775
|
-
workflow
|
|
13776
|
-
);
|
|
13777
|
-
}
|
|
13778
|
-
}
|
|
13779
|
-
const preDeployCommand = config?.preDeployCommand;
|
|
13780
|
-
if (registerPreDeploy && typeof preDeployCommand === "string") {
|
|
13781
|
-
const capturedEnv = { ...pythonEnv };
|
|
13782
|
-
const capturedCwd = workPath;
|
|
13783
|
-
registerPreDeploy(async () => {
|
|
13784
|
-
await builderSpan.child(import_build_utils24.BUILDER_PRE_DEPLOY_STEP, {
|
|
13785
|
-
preDeployCommand
|
|
13786
|
-
}).trace(async () => {
|
|
13787
|
-
console.log(`Running pre-deploy command: \`${preDeployCommand}\``);
|
|
13788
|
-
await (0, import_build_utils24.execCommand)(preDeployCommand, {
|
|
13789
|
-
env: capturedEnv,
|
|
13790
|
-
cwd: capturedCwd
|
|
13791
|
-
});
|
|
13792
|
-
});
|
|
13793
|
-
});
|
|
13436
|
+
if (lockPath && import_fs20.default.existsSync(lockPath)) {
|
|
13437
|
+
await import_fs20.default.promises.mkdir(uvCacheDir, { recursive: true });
|
|
13438
|
+
await import_fs20.default.promises.copyFile(lockPath, cachedLockPath);
|
|
13794
13439
|
}
|
|
13440
|
+
return result;
|
|
13441
|
+
}
|
|
13442
|
+
async function packFunctionBundle({
|
|
13443
|
+
builderSpan,
|
|
13444
|
+
workPath,
|
|
13445
|
+
uvLockPath,
|
|
13446
|
+
uvProjectDir,
|
|
13447
|
+
projectName,
|
|
13448
|
+
pythonVersion,
|
|
13449
|
+
hasCustomCommand,
|
|
13450
|
+
alwaysBundlePackages,
|
|
13451
|
+
initialFiles,
|
|
13452
|
+
additionalExcludes,
|
|
13453
|
+
compileAllEnabled,
|
|
13454
|
+
compileEnv,
|
|
13455
|
+
venvPath,
|
|
13456
|
+
entrypoint,
|
|
13457
|
+
importClosureContext,
|
|
13458
|
+
largeFunctionLabel
|
|
13459
|
+
}) {
|
|
13795
13460
|
const vendorDir = resolveVendorDir();
|
|
13796
|
-
let crons;
|
|
13797
|
-
let runtimeTrampoline;
|
|
13798
|
-
if (entrypoint) {
|
|
13799
|
-
(0, import_build_utils24.debug)("Entrypoint is", entrypoint);
|
|
13800
|
-
const moduleName = entrypointToModule(entrypoint);
|
|
13801
|
-
if (handlerFunction) {
|
|
13802
|
-
const entrypointPath = (0, import_path21.join)(workPath, entrypoint);
|
|
13803
|
-
const source = await import_fs20.default.promises.readFile(entrypointPath, "utf-8");
|
|
13804
|
-
const found = await (0, import_python_analysis12.containsTopLevelCallable)(source, handlerFunction);
|
|
13805
|
-
if (!found) {
|
|
13806
|
-
throw new import_build_utils24.NowBuildError({
|
|
13807
|
-
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
13808
|
-
message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
|
|
13809
|
-
});
|
|
13810
|
-
}
|
|
13811
|
-
}
|
|
13812
|
-
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
13813
|
-
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
13814
|
-
(0, import_build_utils24.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
13815
|
-
crons = await getServiceCrons({
|
|
13816
|
-
service,
|
|
13817
|
-
entrypoint,
|
|
13818
|
-
rawEntrypoint,
|
|
13819
|
-
handlerFunction,
|
|
13820
|
-
pythonBin: getVenvPythonBin(venvPath),
|
|
13821
|
-
env: pythonEnv,
|
|
13822
|
-
workPath
|
|
13823
|
-
});
|
|
13824
|
-
const extraTrampolineEnv = [];
|
|
13825
|
-
if (crons?.length) {
|
|
13826
|
-
const json = JSON.stringify(buildCronRouteTable(crons));
|
|
13827
|
-
(0, import_assert.default)(!json.includes("\\"), `backslash in cron route table: ${json}`);
|
|
13828
|
-
extraTrampolineEnv.push(`"__VC_CRON_ROUTES": '${json}'`);
|
|
13829
|
-
}
|
|
13830
|
-
const variableName = resolved?.variableName ?? "";
|
|
13831
|
-
runtimeTrampoline = createRuntimeTrampoline({
|
|
13832
|
-
moduleName,
|
|
13833
|
-
entrypoint: entrypointWithSuffix,
|
|
13834
|
-
vendorDir,
|
|
13835
|
-
variableName,
|
|
13836
|
-
extraEnv: extraTrampolineEnv
|
|
13837
|
-
});
|
|
13838
|
-
}
|
|
13839
|
-
const compileAllEnabled = shouldCompileAll({
|
|
13840
|
-
isDev: meta.isDev,
|
|
13841
|
-
hasCustomCommand,
|
|
13842
|
-
// A pre-deploy command can rewrite source after the build, which would make
|
|
13843
|
-
// unchecked-hash precompiled bytecode stale; skip precompilation to avoid serving it.
|
|
13844
|
-
hasPreDeployCommand: typeof preDeployCommand === "string"
|
|
13845
|
-
});
|
|
13846
13461
|
const predefinedExcludes = [
|
|
13847
13462
|
".git/**",
|
|
13848
13463
|
".gitignore",
|
|
@@ -13861,71 +13476,13 @@ var build = async ({
|
|
|
13861
13476
|
"**/yarn.lock",
|
|
13862
13477
|
"**/package-lock.json"
|
|
13863
13478
|
];
|
|
13864
|
-
const
|
|
13865
|
-
lambdaEnv.PYTHONPATH = vendorDir;
|
|
13866
|
-
lambdaEnv.PYTHONDONTWRITEBYTECODE = "1";
|
|
13867
|
-
Object.assign(lambdaEnv, quirksResult.env);
|
|
13868
|
-
if (shouldInstallVercelWorkers) {
|
|
13869
|
-
lambdaEnv.VERCEL_HAS_WORKER_SERVICES = "1";
|
|
13870
|
-
}
|
|
13871
|
-
if (queueIntegrations.length > 0) {
|
|
13872
|
-
lambdaEnv.VERCEL_QUEUE_INTEGRATIONS = queueIntegrations.map(
|
|
13873
|
-
({ module: module2, installer, servingActivator }) => `${module2}:${installer}` + (servingActivator ? `:${servingActivator}` : "")
|
|
13874
|
-
).join(",");
|
|
13875
|
-
}
|
|
13876
|
-
const apschedulerSubscribers = apschedulerSubscriberIdentities(subscribers);
|
|
13877
|
-
if (apschedulerSubscribers.length > 0) {
|
|
13878
|
-
lambdaEnv.VERCEL_APSCHEDULER_SUBSCRIBERS = JSON.stringify(
|
|
13879
|
-
apschedulerSubscribers
|
|
13880
|
-
);
|
|
13881
|
-
const previewConfig = await getApschedulerPreviewConfig(workPath);
|
|
13882
|
-
if (previewConfig) {
|
|
13883
|
-
lambdaEnv.VERCEL_APSCHEDULER_PREVIEW_IDLE_TIMEOUT_SECONDS = String(
|
|
13884
|
-
previewConfig.idleTimeoutSeconds
|
|
13885
|
-
);
|
|
13886
|
-
}
|
|
13887
|
-
}
|
|
13888
|
-
const functionConfig = getMatchingFunction(
|
|
13889
|
-
config,
|
|
13890
|
-
entrypoint
|
|
13891
|
-
)?.functionConfig;
|
|
13892
|
-
const includeFilesPatterns = [
|
|
13893
|
-
...normalizeGlobs(config?.includeFiles),
|
|
13894
|
-
...normalizeGlobs(functionConfig?.includeFiles)
|
|
13895
|
-
];
|
|
13896
|
-
const excludeFilesPatterns = [
|
|
13897
|
-
...normalizeGlobs(config?.excludeFiles),
|
|
13898
|
-
...normalizeGlobs(functionConfig?.excludeFiles)
|
|
13899
|
-
];
|
|
13900
|
-
const cdnBundle = getFastAPICdnBundle(
|
|
13901
|
-
fastapiStatic?.collectedMounts ?? [],
|
|
13902
|
-
workPath,
|
|
13903
|
-
pythonPackage.manifest?.data?.tool?.vercel?.fastapi
|
|
13904
|
-
);
|
|
13905
|
-
const globOptions = {
|
|
13479
|
+
const files = await (0, import_build_utils24.glob)("**", {
|
|
13906
13480
|
cwd: workPath,
|
|
13907
|
-
ignore: [
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
...cdnBundle.excludePatterns
|
|
13911
|
-
]
|
|
13912
|
-
};
|
|
13913
|
-
const files = await (0, import_build_utils24.glob)("**", globOptions);
|
|
13914
|
-
for (const pattern of includeFilesPatterns) {
|
|
13915
|
-
Object.assign(files, await (0, import_build_utils24.glob)(pattern, workPath));
|
|
13916
|
-
}
|
|
13917
|
-
Object.assign(files, cdnBundle.directoryStubs);
|
|
13481
|
+
ignore: [...predefinedExcludes, ...additionalExcludes ?? []]
|
|
13482
|
+
});
|
|
13483
|
+
Object.assign(files, initialFiles);
|
|
13918
13484
|
const appPythonSourceFiles = Object.keys(files).filter((file) => file.endsWith(".py")).map((file) => (0, import_path21.join)(workPath, file)).sort();
|
|
13919
|
-
|
|
13920
|
-
files[djangoStatic.manifestRelPath] = new import_build_utils24.FileFsRef({
|
|
13921
|
-
fsPath: (0, import_path21.join)(workPath, djangoStatic.manifestRelPath)
|
|
13922
|
-
});
|
|
13923
|
-
}
|
|
13924
|
-
const handlerPyFilename = "vc__handler__python";
|
|
13925
|
-
if (config.framework === "fasthtml") {
|
|
13926
|
-
const { SESSKEY = "" } = process.env;
|
|
13927
|
-
files[".sesskey"] = new import_build_utils24.FileBlob({ data: `"${SESSKEY}"` });
|
|
13928
|
-
}
|
|
13485
|
+
let pycachePrefix;
|
|
13929
13486
|
await builderSpan.child("vc.builder.python.bundle").trace(async (bundleSpan) => {
|
|
13930
13487
|
const installedDistributions = await InstalledPythonDistributions.load({
|
|
13931
13488
|
venvPath,
|
|
@@ -13941,10 +13498,7 @@ var build = async ({
|
|
|
13941
13498
|
projectName,
|
|
13942
13499
|
pythonVersion,
|
|
13943
13500
|
hasCustomCommand,
|
|
13944
|
-
alwaysBundlePackages
|
|
13945
|
-
...quirksResult.alwaysBundlePackages ?? [],
|
|
13946
|
-
...shouldInstallVercelWorkers ? ["vercel-workers", "vercel_workers"] : []
|
|
13947
|
-
]
|
|
13501
|
+
alwaysBundlePackages
|
|
13948
13502
|
});
|
|
13949
13503
|
const depAnalysis = await depExternalizer.analyze(files, {
|
|
13950
13504
|
onSized: ({ totalSizeBytes, runtimeInstallEnabled }) => {
|
|
@@ -13958,11 +13512,11 @@ var build = async ({
|
|
|
13958
13512
|
});
|
|
13959
13513
|
const compileAllOptions = compileAllEnabled ? {
|
|
13960
13514
|
pythonBin: getVenvPythonBin(venvPath),
|
|
13961
|
-
env:
|
|
13515
|
+
env: compileEnv
|
|
13962
13516
|
} : null;
|
|
13963
13517
|
const compileSources = async ({
|
|
13964
13518
|
includePackages,
|
|
13965
|
-
pycachePrefix
|
|
13519
|
+
pycachePrefix: pycachePrefixArg
|
|
13966
13520
|
}) => {
|
|
13967
13521
|
if (!compileAllOptions)
|
|
13968
13522
|
return void 0;
|
|
@@ -13973,7 +13527,7 @@ var build = async ({
|
|
|
13973
13527
|
const result = await runCompileAll({
|
|
13974
13528
|
...compileAllOptions,
|
|
13975
13529
|
sourceFiles: [...appPythonSourceFiles, ...vendorSourceFiles],
|
|
13976
|
-
pycachePrefix
|
|
13530
|
+
pycachePrefix: pycachePrefixArg
|
|
13977
13531
|
});
|
|
13978
13532
|
timings = result.timings;
|
|
13979
13533
|
compileSpan.setAttributes({
|
|
@@ -13998,13 +13552,8 @@ var build = async ({
|
|
|
13998
13552
|
getImportClosureOptions({
|
|
13999
13553
|
workPath,
|
|
14000
13554
|
entrypoint,
|
|
14001
|
-
|
|
14002
|
-
|
|
14003
|
-
subscriberDeclarations,
|
|
14004
|
-
subscribers,
|
|
14005
|
-
workflows,
|
|
14006
|
-
workflowMode,
|
|
14007
|
-
sitePackageDirs
|
|
13555
|
+
sitePackageDirs,
|
|
13556
|
+
...importClosureContext
|
|
14008
13557
|
})
|
|
14009
13558
|
),
|
|
14010
13559
|
IMPORT_CLOSURE_TIMEOUT_MS,
|
|
@@ -14158,7 +13707,7 @@ var build = async ({
|
|
|
14158
13707
|
timings
|
|
14159
13708
|
});
|
|
14160
13709
|
if (bytesAdded > 0) {
|
|
14161
|
-
|
|
13710
|
+
pycachePrefix = RUNTIME_PYCACHE_PREFIX;
|
|
14162
13711
|
}
|
|
14163
13712
|
} catch (err) {
|
|
14164
13713
|
console.log(
|
|
@@ -14168,7 +13717,7 @@ var build = async ({
|
|
|
14168
13717
|
}
|
|
14169
13718
|
};
|
|
14170
13719
|
const announceLargeFunction = () => console.log(
|
|
14171
|
-
`Function "${
|
|
13720
|
+
`Function "${largeFunctionLabel}" exceeds the standard size limit; enabling large functions (beta).`
|
|
14172
13721
|
);
|
|
14173
13722
|
let packingMode;
|
|
14174
13723
|
let runtimeToolingBytes = 0;
|
|
@@ -14235,6 +13784,556 @@ var build = async ({
|
|
|
14235
13784
|
"python.bundle.packingMode": packingMode
|
|
14236
13785
|
});
|
|
14237
13786
|
});
|
|
13787
|
+
return { pycachePrefix, vendorDir, files };
|
|
13788
|
+
}
|
|
13789
|
+
var build = async ({
|
|
13790
|
+
workPath,
|
|
13791
|
+
repoRootPath,
|
|
13792
|
+
files: originalFiles,
|
|
13793
|
+
entrypoint: rawEntrypoint,
|
|
13794
|
+
meta = {},
|
|
13795
|
+
config,
|
|
13796
|
+
span: parentSpan,
|
|
13797
|
+
service,
|
|
13798
|
+
registerPreDeploy
|
|
13799
|
+
}) => {
|
|
13800
|
+
if (config?.middleware === true) {
|
|
13801
|
+
throw new import_build_utils24.NowBuildError({
|
|
13802
|
+
code: "PYTHON_PROXY_NOT_IMPLEMENTED",
|
|
13803
|
+
message: "Python proxy middleware is not yet supported."
|
|
13804
|
+
});
|
|
13805
|
+
}
|
|
13806
|
+
let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
13807
|
+
const builderSpan = parentSpan ?? new import_build_utils24.Span({ name: "vc.builder" });
|
|
13808
|
+
const isPyprojectEntrypoint = entrypoint !== void 0 && (0, import_path21.basename)(entrypoint) === "pyproject.toml";
|
|
13809
|
+
if (isPyprojectEntrypoint && entrypoint !== "pyproject.toml") {
|
|
13810
|
+
throw new import_build_utils24.NowBuildError({
|
|
13811
|
+
code: "PYTHON_INVALID_PYPROJECT_ENTRYPOINT",
|
|
13812
|
+
message: `A "pyproject.toml" entrypoint must sit at the service root. Set the service "root" to "${(0, import_path21.dirname)(entrypoint)}" and use entrypoint "pyproject.toml".`
|
|
13813
|
+
});
|
|
13814
|
+
}
|
|
13815
|
+
const framework = config?.framework;
|
|
13816
|
+
let subscriberDeclarations = [];
|
|
13817
|
+
let subscribers = [];
|
|
13818
|
+
let workflows = [];
|
|
13819
|
+
let legacyWorkersProject = false;
|
|
13820
|
+
let workflowMode = "workers";
|
|
13821
|
+
let spawnEnv;
|
|
13822
|
+
let projectInstallCommand;
|
|
13823
|
+
let hasCustomCommand = false;
|
|
13824
|
+
const target = getTargetPlatform(meta.isDev ?? false);
|
|
13825
|
+
(0, import_build_utils24.debug)(`workPath: ${workPath}`);
|
|
13826
|
+
workPath = await downloadFilesInWorkPath({
|
|
13827
|
+
workPath,
|
|
13828
|
+
files: originalFiles,
|
|
13829
|
+
entrypoint,
|
|
13830
|
+
meta
|
|
13831
|
+
});
|
|
13832
|
+
legacyWorkersProject = await isLegacyWorkersProject(workPath);
|
|
13833
|
+
if (isPyprojectEntrypoint || !service && (0, import_build_utils24.isPythonFramework)(framework)) {
|
|
13834
|
+
subscriberDeclarations = await getPyprojectSubscribers(workPath, {
|
|
13835
|
+
legacySchema: legacyWorkersProject
|
|
13836
|
+
});
|
|
13837
|
+
workflows = await getPyprojectWorkflows(workPath);
|
|
13838
|
+
}
|
|
13839
|
+
try {
|
|
13840
|
+
if (meta.isDev) {
|
|
13841
|
+
const setupCfg = (0, import_path21.join)(workPath, "setup.cfg");
|
|
13842
|
+
await writeFile(setupCfg, "[install]\nprefix=\n");
|
|
13843
|
+
}
|
|
13844
|
+
} catch (err) {
|
|
13845
|
+
console.log('Failed to create "setup.cfg" file');
|
|
13846
|
+
throw err;
|
|
13847
|
+
}
|
|
13848
|
+
let detected;
|
|
13849
|
+
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
13850
|
+
if (isPyprojectEntrypoint) {
|
|
13851
|
+
const declared = await getVercelToolsEntrypoint(workPath, repoRootPath);
|
|
13852
|
+
if (declared) {
|
|
13853
|
+
detected = { entrypoint: declared };
|
|
13854
|
+
} else if (subscriberDeclarations.length === 0 && workflows.length === 0) {
|
|
13855
|
+
throw new import_build_utils24.NowBuildError({
|
|
13856
|
+
code: "PYTHON_PYPROJECT_NOTHING_TO_BUILD",
|
|
13857
|
+
message: 'Entrypoint "pyproject.toml" declares nothing to build. Set "tool.vercel.entrypoint" for a web app and/or declare "[[tool.vercel.subscribers]]" or "[[tool.vercel.workflows]]" entries in pyproject.toml.'
|
|
13858
|
+
});
|
|
13859
|
+
}
|
|
13860
|
+
entrypoint = void 0;
|
|
13861
|
+
} else {
|
|
13862
|
+
detected = await detectPythonEntrypoint(
|
|
13863
|
+
config.framework,
|
|
13864
|
+
workPath,
|
|
13865
|
+
entrypoint ? {
|
|
13866
|
+
filePath: entrypoint,
|
|
13867
|
+
// For schedule-triggered jobs, the WSGI variable is always 'app' (created dynamically).
|
|
13868
|
+
// For other services, handlerFunction is used as the entrypoint variable name.
|
|
13869
|
+
varName: service && (0, import_build_utils24.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
|
|
13870
|
+
} : void 0,
|
|
13871
|
+
service,
|
|
13872
|
+
repoRootPath
|
|
13873
|
+
) ?? void 0;
|
|
13874
|
+
}
|
|
13875
|
+
if (detected?.error && detected?.baseDir === void 0) {
|
|
13876
|
+
throw detected?.error;
|
|
13877
|
+
}
|
|
13878
|
+
const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path21.dirname)(entrypoint) : ".");
|
|
13879
|
+
const entrypointAbsDir = (0, import_path21.join)(workPath, entryDirectory);
|
|
13880
|
+
const rootDir = repoRootPath ?? workPath;
|
|
13881
|
+
const venvPath = service?.name ? (0, import_path21.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path21.join)(workPath, ".vercel", "python", ".venv");
|
|
13882
|
+
const { pythonPackage, pythonVersion, uv, uvCacheDir, restoredCache } = await setupPythonToolchain({
|
|
13883
|
+
builderSpan,
|
|
13884
|
+
workPath,
|
|
13885
|
+
entrypointDir: entrypointAbsDir,
|
|
13886
|
+
rootDir,
|
|
13887
|
+
venvPath,
|
|
13888
|
+
meta
|
|
13889
|
+
});
|
|
13890
|
+
if ((0, import_build_utils24.isPythonFramework)(framework)) {
|
|
13891
|
+
const {
|
|
13892
|
+
cliType,
|
|
13893
|
+
lockfileVersion,
|
|
13894
|
+
packageJsonPackageManager,
|
|
13895
|
+
packageJsonDevEngines,
|
|
13896
|
+
turboSupportsCorepackHome
|
|
13897
|
+
} = await (0, import_build_utils24.scanParentDirs)(workPath, true);
|
|
13898
|
+
spawnEnv = (0, import_build_utils24.getEnvForPackageManager)({
|
|
13899
|
+
cliType,
|
|
13900
|
+
lockfileVersion,
|
|
13901
|
+
packageJsonPackageManager,
|
|
13902
|
+
packageJsonDevEngines,
|
|
13903
|
+
env: process.env,
|
|
13904
|
+
turboSupportsCorepackHome,
|
|
13905
|
+
projectCreatedAt: config?.projectSettings?.createdAt
|
|
13906
|
+
});
|
|
13907
|
+
const installCommand = config?.projectSettings?.installCommand;
|
|
13908
|
+
if (typeof installCommand === "string") {
|
|
13909
|
+
const trimmed = installCommand.trim();
|
|
13910
|
+
if (trimmed) {
|
|
13911
|
+
projectInstallCommand = trimmed;
|
|
13912
|
+
} else {
|
|
13913
|
+
console.log('Skipping "install" command...');
|
|
13914
|
+
}
|
|
13915
|
+
}
|
|
13916
|
+
}
|
|
13917
|
+
const baseEnv = spawnEnv || process.env;
|
|
13918
|
+
const pythonEnv = createVenvEnv(venvPath, baseEnv, uvCacheDir);
|
|
13919
|
+
pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
|
|
13920
|
+
let assumeDepsInstalled = false;
|
|
13921
|
+
let uvLockPath = null;
|
|
13922
|
+
let uvProjectDir = null;
|
|
13923
|
+
let projectName;
|
|
13924
|
+
let usedUvManagedInstall = false;
|
|
13925
|
+
await builderSpan.child(import_build_utils24.BUILDER_INSTALLER_STEP, {
|
|
13926
|
+
installCommand: projectInstallCommand || void 0,
|
|
13927
|
+
runtime: "python",
|
|
13928
|
+
"python.cache.restored": restoredCache
|
|
13929
|
+
}).trace(async () => {
|
|
13930
|
+
if (projectInstallCommand) {
|
|
13931
|
+
await import_fs20.default.promises.rm(venvPath, { recursive: true, force: true });
|
|
13932
|
+
await ensureVenv({
|
|
13933
|
+
pythonVersion,
|
|
13934
|
+
venvPath,
|
|
13935
|
+
uvPath: uv.getPath(),
|
|
13936
|
+
uvCacheDir,
|
|
13937
|
+
quiet: true
|
|
13938
|
+
});
|
|
13939
|
+
console.log(
|
|
13940
|
+
`Running "install" command: \`${projectInstallCommand}\`...`
|
|
13941
|
+
);
|
|
13942
|
+
await (0, import_build_utils24.execCommand)(projectInstallCommand, {
|
|
13943
|
+
env: pythonEnv,
|
|
13944
|
+
cwd: workPath
|
|
13945
|
+
});
|
|
13946
|
+
assumeDepsInstalled = true;
|
|
13947
|
+
hasCustomCommand = true;
|
|
13948
|
+
} else {
|
|
13949
|
+
const hasCustomScript = await runPyprojectScript(
|
|
13950
|
+
workPath,
|
|
13951
|
+
["vercel-install", "now-install", "install"],
|
|
13952
|
+
pythonEnv,
|
|
13953
|
+
/* useUserVirtualEnv */
|
|
13954
|
+
false
|
|
13955
|
+
);
|
|
13956
|
+
if (hasCustomScript) {
|
|
13957
|
+
assumeDepsInstalled = true;
|
|
13958
|
+
hasCustomCommand = true;
|
|
13959
|
+
}
|
|
13960
|
+
}
|
|
13961
|
+
if (!assumeDepsInstalled) {
|
|
13962
|
+
const { projectDir, lockPath } = await runUvManagedInstall({
|
|
13963
|
+
workPath,
|
|
13964
|
+
rootDir,
|
|
13965
|
+
venvPath,
|
|
13966
|
+
pythonPackage,
|
|
13967
|
+
pythonVersion,
|
|
13968
|
+
uv,
|
|
13969
|
+
uvCacheDir,
|
|
13970
|
+
lockCacheKey: service?.name ? `uv.lock.${service.name}` : "uv.lock",
|
|
13971
|
+
pythonPlatform: target.uvPlatform,
|
|
13972
|
+
extraSyncParams: {}
|
|
13973
|
+
});
|
|
13974
|
+
uvLockPath = lockPath;
|
|
13975
|
+
uvProjectDir = projectDir;
|
|
13976
|
+
projectName = pythonPackage?.manifest?.data?.project?.name;
|
|
13977
|
+
usedUvManagedInstall = true;
|
|
13978
|
+
}
|
|
13979
|
+
});
|
|
13980
|
+
if ((0, import_build_utils24.isPythonFramework)(framework)) {
|
|
13981
|
+
const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
|
|
13982
|
+
config?.buildCommand;
|
|
13983
|
+
await builderSpan.child(import_build_utils24.BUILDER_COMPILE_STEP, {
|
|
13984
|
+
buildCommand: projectBuildCommand || void 0
|
|
13985
|
+
}).trace(async () => {
|
|
13986
|
+
if (projectBuildCommand) {
|
|
13987
|
+
console.log(`Running "${projectBuildCommand}"`);
|
|
13988
|
+
await (0, import_build_utils24.execCommand)(projectBuildCommand, {
|
|
13989
|
+
env: pythonEnv,
|
|
13990
|
+
cwd: workPath
|
|
13991
|
+
});
|
|
13992
|
+
} else {
|
|
13993
|
+
await runPyprojectScript(
|
|
13994
|
+
workPath,
|
|
13995
|
+
["vercel-build", "now-build", "build"],
|
|
13996
|
+
pythonEnv
|
|
13997
|
+
);
|
|
13998
|
+
}
|
|
13999
|
+
});
|
|
14000
|
+
}
|
|
14001
|
+
const hookResult = await runFrameworkHook(framework, {
|
|
14002
|
+
pythonEnv,
|
|
14003
|
+
workPath,
|
|
14004
|
+
venvPath,
|
|
14005
|
+
entrypoint,
|
|
14006
|
+
detected,
|
|
14007
|
+
pyprojectData: pythonPackage.manifest?.data
|
|
14008
|
+
});
|
|
14009
|
+
const resolved = isPyprojectEntrypoint ? detected?.entrypoint : hookResult?.entrypoint ?? detected?.entrypoint;
|
|
14010
|
+
if (!resolved && detected?.error) {
|
|
14011
|
+
throw detected?.error;
|
|
14012
|
+
}
|
|
14013
|
+
entrypoint = resolved?.entrypoint;
|
|
14014
|
+
const isWorkersOnly = !entrypoint && isPyprojectEntrypoint && (subscriberDeclarations.length > 0 || workflows.length > 0);
|
|
14015
|
+
if (!entrypoint && !isWorkersOnly) {
|
|
14016
|
+
throw new import_build_utils24.NowBuildError({
|
|
14017
|
+
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
14018
|
+
message: "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
14019
|
+
});
|
|
14020
|
+
}
|
|
14021
|
+
const djangoStatic = hookResult?.djangoStatic ?? null;
|
|
14022
|
+
const fastapiStatic = hookResult?.fastapiStatic ?? null;
|
|
14023
|
+
const importSeeds = hookResult?.importSeeds ?? [];
|
|
14024
|
+
const cdnOutputDir = djangoStatic?.cdnOutputDir ?? fastapiStatic?.cdnOutputDir ?? null;
|
|
14025
|
+
const pipPlatformArgs = target.uvPlatform ? ["--python-platform", target.uvPlatform] : [];
|
|
14026
|
+
await installInjectedPackage({
|
|
14027
|
+
name: "vercel-runtime",
|
|
14028
|
+
requirement: `vercel-runtime==${VERCEL_RUNTIME_VERSION}`,
|
|
14029
|
+
envOverride: baseEnv.VERCEL_RUNTIME_PYTHON,
|
|
14030
|
+
allowLocalSource: true,
|
|
14031
|
+
uv,
|
|
14032
|
+
venvPath,
|
|
14033
|
+
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
14034
|
+
pipPlatformArgs
|
|
14035
|
+
});
|
|
14036
|
+
const queueAdapterBootstrap = await getQueueAdapterBootstrap({
|
|
14037
|
+
pythonPackage,
|
|
14038
|
+
env: baseEnv,
|
|
14039
|
+
legacyWorkersProject,
|
|
14040
|
+
hasDeclaredSubscribers: await hasPyprojectSubscribers(workPath)
|
|
14041
|
+
});
|
|
14042
|
+
const queueAdapterInjectedPackages = usedUvManagedInstall ? queueAdapterBootstrap.injectedPackages : [];
|
|
14043
|
+
for (const injectedPackage of queueAdapterInjectedPackages) {
|
|
14044
|
+
await installInjectedPackage({
|
|
14045
|
+
...injectedPackage,
|
|
14046
|
+
uv,
|
|
14047
|
+
venvPath,
|
|
14048
|
+
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
14049
|
+
pipPlatformArgs
|
|
14050
|
+
});
|
|
14051
|
+
}
|
|
14052
|
+
const localSdkSourcePaths = await getLocalSdkSourcePaths({
|
|
14053
|
+
pythonPackage,
|
|
14054
|
+
env: baseEnv
|
|
14055
|
+
});
|
|
14056
|
+
if (localSdkSourcePaths.length > 0) {
|
|
14057
|
+
(0, import_build_utils24.debug)(
|
|
14058
|
+
`Installing vercel SDK override from ${baseEnv.VERCEL_SDK_PYTHON}: ` + localSdkSourcePaths.join(", ")
|
|
14059
|
+
);
|
|
14060
|
+
await uv.pip({
|
|
14061
|
+
venvPath,
|
|
14062
|
+
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
14063
|
+
args: [
|
|
14064
|
+
"install",
|
|
14065
|
+
"--link-mode",
|
|
14066
|
+
"copy",
|
|
14067
|
+
// Without --no-sources, uv resolves the checkout's workspace
|
|
14068
|
+
// dependencies as editable .pth installs pointing at the (build
|
|
14069
|
+
// only) checkout mount — invisible to bundling and dangling at
|
|
14070
|
+
// runtime. Explicit paths stay real installs; the remaining
|
|
14071
|
+
// workspace siblings resolve from PyPI.
|
|
14072
|
+
"--no-sources",
|
|
14073
|
+
...pipPlatformArgs,
|
|
14074
|
+
...localSdkSourcePaths
|
|
14075
|
+
]
|
|
14076
|
+
});
|
|
14077
|
+
}
|
|
14078
|
+
if (workflows.length > 0) {
|
|
14079
|
+
workflowMode = await resolveWorkflowServingMode({
|
|
14080
|
+
pythonPackage,
|
|
14081
|
+
uv,
|
|
14082
|
+
venvPath,
|
|
14083
|
+
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
14084
|
+
uvLockPath
|
|
14085
|
+
});
|
|
14086
|
+
if (workflowMode === "workers" && workflows.length > 1) {
|
|
14087
|
+
throw new import_build_utils24.NowBuildError({
|
|
14088
|
+
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
14089
|
+
message: `"tool.vercel.workflows" declares multiple entrypoints, which requires ${QUEUE_WORKFLOW_SDK_REQUIREMENT} with a distinct namespace per Workflows registry; the installed SDK serves every workflow on the shared __wkf_* topic`
|
|
14090
|
+
});
|
|
14091
|
+
}
|
|
14092
|
+
}
|
|
14093
|
+
const shouldInstallVercelWorkers = legacyWorkersProject || workflows.length > 0 && workflowMode === "workers";
|
|
14094
|
+
if (shouldInstallVercelWorkers) {
|
|
14095
|
+
await installInjectedPackage({
|
|
14096
|
+
name: "vercel-workers",
|
|
14097
|
+
requirement: `vercel-workers==${VERCEL_WORKERS_VERSION}`,
|
|
14098
|
+
envOverride: baseEnv.VERCEL_WORKERS_PYTHON,
|
|
14099
|
+
allowLocalSource: true,
|
|
14100
|
+
uv,
|
|
14101
|
+
venvPath,
|
|
14102
|
+
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
14103
|
+
pipPlatformArgs
|
|
14104
|
+
});
|
|
14105
|
+
}
|
|
14106
|
+
const quirksResult = await runQuirks({ venvPath, pythonEnv, workPath });
|
|
14107
|
+
if (quirksResult.buildEnv) {
|
|
14108
|
+
Object.assign(pythonEnv, quirksResult.buildEnv);
|
|
14109
|
+
}
|
|
14110
|
+
const queueIntegrations = queueAdapterBootstrap.integrations;
|
|
14111
|
+
const writeGeneratedQueueHandler = async (outputPath, declaration) => {
|
|
14112
|
+
const generatedPath = getGeneratedQueueHandlerPath(outputPath);
|
|
14113
|
+
await import_fs20.default.promises.mkdir((0, import_path21.dirname)((0, import_path21.join)(workPath, generatedPath)), {
|
|
14114
|
+
recursive: true
|
|
14115
|
+
});
|
|
14116
|
+
await import_fs20.default.promises.writeFile(
|
|
14117
|
+
(0, import_path21.join)(workPath, generatedPath),
|
|
14118
|
+
createQueueHandlerModule(declaration, queueIntegrations)
|
|
14119
|
+
);
|
|
14120
|
+
};
|
|
14121
|
+
if (subscriberDeclarations.length > 0 && !legacyWorkersProject) {
|
|
14122
|
+
subscribers = await resolveQueueSubscribers({
|
|
14123
|
+
declarations: subscriberDeclarations,
|
|
14124
|
+
uv,
|
|
14125
|
+
venvPath,
|
|
14126
|
+
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
14127
|
+
integrations: queueIntegrations
|
|
14128
|
+
});
|
|
14129
|
+
if (workflowMode === "queue") {
|
|
14130
|
+
for (const subscriber of subscribers) {
|
|
14131
|
+
if (!subscriber.topicPatterns) {
|
|
14132
|
+
subscriber.subscriptions = subscriber.subscriptions.filter(
|
|
14133
|
+
(subscription) => !isWorkflowQueueTopic(subscription.topic)
|
|
14134
|
+
);
|
|
14135
|
+
}
|
|
14136
|
+
}
|
|
14137
|
+
}
|
|
14138
|
+
for (const subscriber of subscribers) {
|
|
14139
|
+
await writeGeneratedQueueHandler(
|
|
14140
|
+
getSubscriberOutputPath(subscriber.name),
|
|
14141
|
+
subscriber
|
|
14142
|
+
);
|
|
14143
|
+
}
|
|
14144
|
+
}
|
|
14145
|
+
const workflowQueueSubscriptions = /* @__PURE__ */ new Map();
|
|
14146
|
+
if (workflows.length > 0 && workflowMode === "queue") {
|
|
14147
|
+
const resolved2 = await resolveQueueSubscribers({
|
|
14148
|
+
declarations: workflows.map((workflow) => ({
|
|
14149
|
+
name: workflow.name,
|
|
14150
|
+
entrypoint: workflow.entrypoint,
|
|
14151
|
+
moduleName: workflow.moduleName,
|
|
14152
|
+
variableName: workflow.variableName
|
|
14153
|
+
})),
|
|
14154
|
+
uv,
|
|
14155
|
+
venvPath,
|
|
14156
|
+
projectDir: (0, import_path21.join)(workPath, entryDirectory),
|
|
14157
|
+
kind: "workflow",
|
|
14158
|
+
integrations: queueIntegrations
|
|
14159
|
+
});
|
|
14160
|
+
for (let i = 0; i < resolved2.length; i++) {
|
|
14161
|
+
for (let j = i + 1; j < resolved2.length; j++) {
|
|
14162
|
+
const overlaps = resolved2[i].subscriptions.some(
|
|
14163
|
+
(left) => resolved2[j].subscriptions.some(
|
|
14164
|
+
(right) => queueTopicPatternsOverlap(left.topic, right.topic)
|
|
14165
|
+
)
|
|
14166
|
+
);
|
|
14167
|
+
if (overlaps) {
|
|
14168
|
+
throw new import_build_utils24.NowBuildError({
|
|
14169
|
+
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
14170
|
+
message: `workflow entrypoints "${resolved2[i].moduleName}:${resolved2[i].variableName}" and "${resolved2[j].moduleName}:${resolved2[j].variableName}" subscribe to overlapping queue topics; construct each vercel.workflow.Workflows registry with a distinct namespace`
|
|
14171
|
+
});
|
|
14172
|
+
}
|
|
14173
|
+
}
|
|
14174
|
+
}
|
|
14175
|
+
for (const workflow of resolved2) {
|
|
14176
|
+
workflowQueueSubscriptions.set(workflow.name, workflow.subscriptions);
|
|
14177
|
+
await writeGeneratedQueueHandler(
|
|
14178
|
+
getWorkflowOutputPath(workflow.name),
|
|
14179
|
+
workflow
|
|
14180
|
+
);
|
|
14181
|
+
}
|
|
14182
|
+
}
|
|
14183
|
+
const preDeployCommand = config?.preDeployCommand;
|
|
14184
|
+
if (registerPreDeploy && typeof preDeployCommand === "string") {
|
|
14185
|
+
const capturedEnv = { ...pythonEnv };
|
|
14186
|
+
const capturedCwd = workPath;
|
|
14187
|
+
registerPreDeploy(async () => {
|
|
14188
|
+
await builderSpan.child(import_build_utils24.BUILDER_PRE_DEPLOY_STEP, {
|
|
14189
|
+
preDeployCommand
|
|
14190
|
+
}).trace(async () => {
|
|
14191
|
+
console.log(`Running pre-deploy command: \`${preDeployCommand}\``);
|
|
14192
|
+
await (0, import_build_utils24.execCommand)(preDeployCommand, {
|
|
14193
|
+
env: capturedEnv,
|
|
14194
|
+
cwd: capturedCwd
|
|
14195
|
+
});
|
|
14196
|
+
});
|
|
14197
|
+
});
|
|
14198
|
+
}
|
|
14199
|
+
const vendorDir = resolveVendorDir();
|
|
14200
|
+
let crons;
|
|
14201
|
+
let runtimeTrampoline;
|
|
14202
|
+
if (entrypoint) {
|
|
14203
|
+
(0, import_build_utils24.debug)("Entrypoint is", entrypoint);
|
|
14204
|
+
const moduleName = entrypointToModule(entrypoint);
|
|
14205
|
+
if (handlerFunction) {
|
|
14206
|
+
const entrypointPath = (0, import_path21.join)(workPath, entrypoint);
|
|
14207
|
+
const source = await import_fs20.default.promises.readFile(entrypointPath, "utf-8");
|
|
14208
|
+
const found = await (0, import_python_analysis12.containsTopLevelCallable)(source, handlerFunction);
|
|
14209
|
+
if (!found) {
|
|
14210
|
+
throw new import_build_utils24.NowBuildError({
|
|
14211
|
+
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
14212
|
+
message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
|
|
14213
|
+
});
|
|
14214
|
+
}
|
|
14215
|
+
}
|
|
14216
|
+
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
14217
|
+
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
14218
|
+
(0, import_build_utils24.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
14219
|
+
crons = await getServiceCrons({
|
|
14220
|
+
service,
|
|
14221
|
+
entrypoint,
|
|
14222
|
+
rawEntrypoint,
|
|
14223
|
+
handlerFunction,
|
|
14224
|
+
pythonBin: getVenvPythonBin(venvPath),
|
|
14225
|
+
env: pythonEnv,
|
|
14226
|
+
workPath
|
|
14227
|
+
});
|
|
14228
|
+
const extraTrampolineEnv = [];
|
|
14229
|
+
if (crons?.length) {
|
|
14230
|
+
const json = JSON.stringify(buildCronRouteTable(crons));
|
|
14231
|
+
(0, import_assert.default)(!json.includes("\\"), `backslash in cron route table: ${json}`);
|
|
14232
|
+
extraTrampolineEnv.push(`"__VC_CRON_ROUTES": '${json}'`);
|
|
14233
|
+
}
|
|
14234
|
+
const variableName = resolved?.variableName ?? "";
|
|
14235
|
+
runtimeTrampoline = createRuntimeTrampoline({
|
|
14236
|
+
moduleName,
|
|
14237
|
+
entrypoint: entrypointWithSuffix,
|
|
14238
|
+
vendorDir,
|
|
14239
|
+
variableName,
|
|
14240
|
+
extraEnv: extraTrampolineEnv
|
|
14241
|
+
});
|
|
14242
|
+
}
|
|
14243
|
+
const compileAllEnabled = shouldCompileAll({
|
|
14244
|
+
isDev: meta.isDev,
|
|
14245
|
+
hasCustomCommand,
|
|
14246
|
+
// A pre-deploy command can rewrite source after the build, which would make
|
|
14247
|
+
// unchecked-hash precompiled bytecode stale; skip precompilation to avoid serving it.
|
|
14248
|
+
hasPreDeployCommand: typeof preDeployCommand === "string"
|
|
14249
|
+
});
|
|
14250
|
+
const lambdaEnv = {};
|
|
14251
|
+
lambdaEnv.PYTHONPATH = vendorDir;
|
|
14252
|
+
lambdaEnv.PYTHONDONTWRITEBYTECODE = "1";
|
|
14253
|
+
Object.assign(lambdaEnv, quirksResult.env);
|
|
14254
|
+
if (shouldInstallVercelWorkers) {
|
|
14255
|
+
lambdaEnv.VERCEL_HAS_WORKER_SERVICES = "1";
|
|
14256
|
+
}
|
|
14257
|
+
if (queueIntegrations.length > 0) {
|
|
14258
|
+
lambdaEnv.VERCEL_QUEUE_INTEGRATIONS = queueIntegrations.map(
|
|
14259
|
+
({ module: module2, installer, servingActivator }) => `${module2}:${installer}` + (servingActivator ? `:${servingActivator}` : "")
|
|
14260
|
+
).join(",");
|
|
14261
|
+
}
|
|
14262
|
+
const apschedulerSubscribers = apschedulerSubscriberIdentities(subscribers);
|
|
14263
|
+
if (apschedulerSubscribers.length > 0) {
|
|
14264
|
+
lambdaEnv.VERCEL_APSCHEDULER_SUBSCRIBERS = JSON.stringify(
|
|
14265
|
+
apschedulerSubscribers
|
|
14266
|
+
);
|
|
14267
|
+
const previewConfig = await getApschedulerPreviewConfig(workPath);
|
|
14268
|
+
if (previewConfig) {
|
|
14269
|
+
lambdaEnv.VERCEL_APSCHEDULER_PREVIEW_IDLE_TIMEOUT_SECONDS = String(
|
|
14270
|
+
previewConfig.idleTimeoutSeconds
|
|
14271
|
+
);
|
|
14272
|
+
}
|
|
14273
|
+
}
|
|
14274
|
+
const functionConfig = getMatchingFunction(
|
|
14275
|
+
config,
|
|
14276
|
+
entrypoint
|
|
14277
|
+
)?.functionConfig;
|
|
14278
|
+
const includeFilesPatterns = [
|
|
14279
|
+
...normalizeGlobs(config?.includeFiles),
|
|
14280
|
+
...normalizeGlobs(functionConfig?.includeFiles)
|
|
14281
|
+
];
|
|
14282
|
+
const excludeFilesPatterns = [
|
|
14283
|
+
...normalizeGlobs(config?.excludeFiles),
|
|
14284
|
+
...normalizeGlobs(functionConfig?.excludeFiles)
|
|
14285
|
+
];
|
|
14286
|
+
const cdnBundle = getFastAPICdnBundle(
|
|
14287
|
+
fastapiStatic?.collectedMounts ?? [],
|
|
14288
|
+
workPath,
|
|
14289
|
+
pythonPackage.manifest?.data?.tool?.vercel?.fastapi
|
|
14290
|
+
);
|
|
14291
|
+
const initialFiles = {};
|
|
14292
|
+
for (const pattern of includeFilesPatterns) {
|
|
14293
|
+
Object.assign(initialFiles, await (0, import_build_utils24.glob)(pattern, workPath));
|
|
14294
|
+
}
|
|
14295
|
+
Object.assign(initialFiles, cdnBundle.directoryStubs);
|
|
14296
|
+
if (djangoStatic?.manifestRelPath) {
|
|
14297
|
+
initialFiles[djangoStatic.manifestRelPath] = new import_build_utils24.FileFsRef({
|
|
14298
|
+
fsPath: (0, import_path21.join)(workPath, djangoStatic.manifestRelPath)
|
|
14299
|
+
});
|
|
14300
|
+
}
|
|
14301
|
+
const handlerPyFilename = "vc__handler__python";
|
|
14302
|
+
if (config.framework === "fasthtml") {
|
|
14303
|
+
const { SESSKEY = "" } = process.env;
|
|
14304
|
+
initialFiles[".sesskey"] = new import_build_utils24.FileBlob({ data: `"${SESSKEY}"` });
|
|
14305
|
+
}
|
|
14306
|
+
const { pycachePrefix, files } = await packFunctionBundle({
|
|
14307
|
+
builderSpan,
|
|
14308
|
+
workPath,
|
|
14309
|
+
uvLockPath,
|
|
14310
|
+
uvProjectDir,
|
|
14311
|
+
projectName,
|
|
14312
|
+
pythonVersion,
|
|
14313
|
+
hasCustomCommand,
|
|
14314
|
+
alwaysBundlePackages: [
|
|
14315
|
+
...quirksResult.alwaysBundlePackages ?? [],
|
|
14316
|
+
...shouldInstallVercelWorkers ? ["vercel-workers", "vercel_workers"] : []
|
|
14317
|
+
],
|
|
14318
|
+
initialFiles,
|
|
14319
|
+
additionalExcludes: [...excludeFilesPatterns, ...cdnBundle.excludePatterns],
|
|
14320
|
+
compileAllEnabled,
|
|
14321
|
+
compileEnv: pythonEnv,
|
|
14322
|
+
venvPath,
|
|
14323
|
+
entrypoint,
|
|
14324
|
+
importClosureContext: {
|
|
14325
|
+
frameworkSeeds: importSeeds,
|
|
14326
|
+
extraPythonPath: hookResult?.extraPythonPath,
|
|
14327
|
+
subscriberDeclarations,
|
|
14328
|
+
subscribers,
|
|
14329
|
+
workflows,
|
|
14330
|
+
workflowMode
|
|
14331
|
+
},
|
|
14332
|
+
largeFunctionLabel: entrypoint ?? rawEntrypoint
|
|
14333
|
+
});
|
|
14334
|
+
if (pycachePrefix) {
|
|
14335
|
+
lambdaEnv.PYTHONPYCACHEPREFIX = pycachePrefix;
|
|
14336
|
+
}
|
|
14238
14337
|
let output;
|
|
14239
14338
|
if (entrypoint && runtimeTrampoline) {
|
|
14240
14339
|
const webFiles = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@vercel/python-analysis": "0.14.0"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@vercel/build-utils": "14.
|
|
20
|
+
"@vercel/build-utils": "14.11.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@renovatebot/pep440": "4.2.1",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"smol-toml": "1.5.2",
|
|
39
39
|
"vitest": "4.1.10",
|
|
40
40
|
"which": "3.0.0",
|
|
41
|
+
"@vercel/build-utils": "14.11.0",
|
|
41
42
|
"@vercel/error-utils": "2.2.1",
|
|
42
|
-
"@vercel/build-utils": "14.10.1",
|
|
43
43
|
"@vercel/python-runtime": "0.23.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|